Читаем Фундаментальные алгоритмы и структуры данных в Delphi полностью

FRecordLen4 := FRecordLen + sizeof(longint);

GetMem(FRecord, FRecordLen4);

end;

Обратите внимание, что конструктор считывает текущее положение потока и записывает его в FZeroPosition. Текущее положение, которое, как правило, равно нулю, будет использовать для указания положения служебного заголовка для постоянного массива. Это означает, что перед вызовом конструктора Create программист может записать в поток свой служебный заголовок, и методы класса не будут его изменять. Тем не менее, класс предполагает, что оставшаяся часть потока, начиная с положения FZeroPosition, принадлежит классу и в нее допускается вносить изменения.

Конструктор вызывает либо метод rsCreateHeaderRec, который создает новый служебный заголовок для пустого потока (т.е. при необходимости создания нового массива), либо метод rsReadHeaderRec, который считывает текущий служебный заголовок (и, кроме того, проверяет его корректность).

И, наконец, конструктор Create выделяет из кучи память для записи (память выделяется с учетом размера флага удаления). Деструктор Destroy освобождает память, выделенную под запись.

Листинг 2.20. Деструктор класса TtdRecordStream

destructor TtdRecordStream.Destroy;

begin

if (FHeaderRec <> nil) then

FreeMem(FHeaderRec, FheaderRec^.hrHeaderLen);

if (FRecord <> nil) then

FreeMem(FRecord, FRecordLen4);

inherited Destroy;

end;

А теперь давайте рассмотрим два вспомогательных метода, которые соответственно создают новый или считывают существующий служебный заголовок.

Листинг 2.21. Создание и считывание служебного заголовка

procedure TtdRecordStream.rsCreateHeaderRec(aRecordLen : integer);

begin

{выделить память под служебный заголовок}

if ((aRecordLen + sizeof(longint)) < sizeof(TtdRSHeaderRec)) then begin

FHeaderRec := AllocMem(sizeof(TtdRSHeaderRec));

FHeaderRec^.hrHeaderLen := sizeof(TtdRSHeaderRec);

end

else begin

FHeaderRec := AllocMem( aRecordLen + sizeof(longint));

FHeaderRec^.hrHeaderLen := aRecordLen + sizeof(longint);

end;

{задать значения остальных стандартных полей}

with FHeaderRec^ do

begin

hrSignature := cRSSignature;

hrVersion := $00010000; {Major=1; Minor=0}

hrRecordLen := aRecordLen;

hrCapacity := 0;

hrCount := 0;

hr1stDelRec := cEndOfDeletedChain;

end;

{обновить служебный заголовок}

rsSeekStream(FZeroPosition);

rsWriteStream(FHeaderRec^, FHeaderRec^.hrHeaderLen);

{задать значение поля длины записи}

FRecordLen := aRecordLen;

end;

procedure TtdRecordStream.rsReadHeaderRec;

var

StreamSize : longint;

TempHeaderRec : TtdRSHeaderRec;

begin

{если размер потока меньше размера служебного заголовка, это неверный поток}

StreamSize := FStream.Size - FZeroPosition;

if (StreamSize < sizeof(TtdRSHeaderRec)) then

rsError(tdeRSNoHeaderRec, 'rsReadHeaderRec', 0);

{считать служебный заголовок}

rsSeekStream(FZeroPosition);

rsReadStream(TempHeaderRec, sizeof(TtdRSHeaderRec));

{первая санитарная проверка: сигнатура и счетчик/емкость}

with TempHeaderRec do

begin

if (hrSignatureocRSSignature) or (hrCount > hrCapacity) then

rsError(tdeRSBadHeaderRec, 'rsReadHeaderRec', 0);

end;

{выделить память под реальный служебный заголовок, скопировать уже считанные данные}

FHeaderRec := AllocMem(TempHeaderRec.hrHeaderLen);

Move(TempHeaderRec, FHeaderRec^, TempHeaderRec.hrHeaderLen);

{вторая санитарная проверка: проверка данных записи}

with FHeaderRec^ do

begin

FRecordLen4 := hrRecordLen + 4;

{for rsCalcRecordOffset}

if (StreamSize <> rsCalcRecordOffset(hrCapacity)) then

rsError(tdeRSBadHeaderRec, 'rsReadHeaderRec', 0);

{установить значения полей класса}

FCount :=hrCount;

FCapacity := hrCapacity;

FRecordLen := hrRecordLen;

end;

end;

function TtdRecordStream.rsCalcRecordOffset(aIndex : longint): longint;

begin

Result := FZeroPosition + FHeaderRec^.hrHeaderLen + (aIndex * FRecordLen4);

end;

Приведенный метод создания служебного заголовка вызывается только в случае, когда поток пуст. Принцип его работы очень прост. Сначала служебный заголовок создается в памяти, а затем записывается в поток. Если длина записи больше, чем нормальный размер служебного заголовка, его размер увеличивает до размера записи. В служебном заголовке содержится семь полей: поле сигнатуры, которое может использоваться для контроля при считывании записи;

номер версии служебного заголовка (это позволит в будущем добавлять в заголовок новые поля и сохранять совместимость версий);

длина служебного заголовка;

длина записи;

емкость потока (т.е. количество записей как активных, так и удаленных, которые в данный момент находятся в потоке);

количество активных записей;

и, наконец, порядковый номер первой удаленной записи (здесь значение этого поля устанавливается равным cEndOfDetectedChain или -2).

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных