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).

Метод считывания служебного заголовка должен содержать определенную проверку, которая будет гарантировать, что данный заголовок является действительным. Для этого сначала выполняется проверка сигнатуры, затем проверка того, что количество активных записей меньше или равно емкости потока и имеет ли поток достаточный объем для объявленной емкости. Если все проверки проходят успешно, считается, что служебный блок содержит корректные данные, и поля класса обновляются значениями, считанными из потока.

Метод rsCalcRecordOffset просто вычисляет смещение записи, порядковый номер которой передан ему во входном параметре. При этом учитывается начальное положение потока и размер служебного заголовка.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату