The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

12.4 Загрузка объектов — retrieve()

12.4 Загрузка объектов — retrieve()

Предыдущая  Содержание  Следующая V*D*V

Кто читает имя класса, выделяет память объекту и вызывает geto(), чтобы заполнить его? Возможно странно, что это выполняется функцией retrieve(), которая декларируется в файле описания класса Object.d, но которая не является методом:

 

void * retrieve (FILE * fp); // object from file

 

retrieve() читает имя класса из потока как строку; каким-нибудь образом находит подходящий указатель описания класса; использует allocate(), чтобы выделить место для объекта; и просит geto() заполнить его. Поскольку заключительный указатель описания класса вставляет allocate(), geto() может в самом деле быть применён к выделенной области памяти:

 

struct classList { const char * name; const void * class; };

 

void * retrieve (FILE * fp) {

    char buf [BUFSIZ];

    static struct classList * cL;              // локальная копия

    static int cD = -1;                        // количество классов

 

    if (cD < 0)

        ... build classList in cL[0..cD-1] ...

    if (! cD)

        fputs("no classes known\n", stderr);

 

    else if (fp && ! feof(fp) && fscanf(fp, "%s", buf) == 1) {

        struct classList key, * p;

 

        key.name = buf;

        if (p = bsearch(& key, cL, cD, sizeof key,

                (int (*) (const void *, const void *)) cmp))

            return geto(allocate(p -> class), fp);

        fprintf(stderr, "%s: cannot retrieve\n", buf);

    }

    return 0;

}

 

retrieve() требуется список имён классов и указателей описаний классов. Описания классов указывают на методы и селекторы, то есть этот список действительно гарантирует, что retrieve() использует код классов, связанный с использованием программы. Если данные для объекта считаны, методы для объекта доступны в программе — geto() только один из них.

Откуда берётся список классов? Можно было бы создать его вручную, но в главе 9 мы видели munch, простую программу awk для извлечения имён классов из списка объектных модулей, создаваемого nm. Поскольку nm может быть применена к библиотеке объектных модулей, можно даже извлечь список классов, поддерживаемый всей библиотекой. Результатом является массив classes[] со списком указателей на функции инициализации класса, отсортированный по именам классов в алфавитном порядке.

retrieve() могла бы искать в этом списке, вызывая каждую функцию, чтобы получить инициализированное описание класса и применяя nameOf() к результату для получения строкового представления имени класса. Это не очень эффективно, если надо получить много объектов. Поэтому retrieve() создаёт собственный список следующим образом:

 

extern const void * (* classes[]) (void);   // munch

 

if (cD < 0) {

    for (cD = 0; classes[cD]; ++ cD)

        ;                                   // подсчёт классов

    if (cD > 0) {                           // собираем имена/описания

        cL = malloc(cD * sizeof(struct classList));

        assert(cL);

        for (cD = 0; classes[cD]; ++ cD)

            cL[cD].class = classes[cD](),

            cL[cD].name = nameOf(cL[cD].class);

    }

}

 

У собственного списка классов есть дополнительное преимущество, он позволяет избежать дальнейших вызовов функций инициализаций классов.

 

Предыдущая  Содержание  Следующая