Фундаментальные алгоритмы и структуры данных в Delphi | страница 58



Листинг 2.23. Чтение и обновление записи в постоянном массиве


procedure TtdRecordStream.Read(aIndex : longint; var aRecord; var alsDeleted : boolean);

begin

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

if (aIndex < 0) or (aIndex >= Capacity) then

rsError(tdeRSOutOfBounds, 'Read', aIndex);

{определить смещение записи и считать ее}

rsSeekStream(rsCalcRecordOffset(aIndex));

rsReadStream(FRecord^, FRecordLen4);

if (PLongint(FRecord)^ = cActiveRecord) then begin

alsDeleted := falser-Move (FRecord^[sizeof(longint)], aRecord, FRecordLen);

end

else begin

alsDeleted := true;

FillChar(aRecord, FRecordLen, 0);

end;

end;


procedure TtdRecordStream.Write(aIndex : longint; var aRecord);

var

DeletedFlag : longint;

begin

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

if (aIndex < 0) or (aIndex >= Capacity) then

rsError(tdeIndexOutOfBounds, 'Write', aIndex);

{проверить, что запись не была удалена}

rsSeekStream(rsCalcRecordOffset(aIndex));

rsReadStream(DeletedFlag, sizeof(longint));

if (DeletedFlag <> cActiveRecord) then

rsError(tdeRSRecIsDeleted, 'Write', aIndex);

{сохранить запись}

rsWriteStream(aRecord, FRecordLen);

end;


Метод Read возвращает флаг, который показывает, была ли удалена запись. Если запись не удалена, буфер записи, переданный во входном параметре, заполняется записью, считанной из потока. Код просто в один прием считывает всю запись и ее флаг удаления и действует в соответствии со значением флага.

Метод Write, прежде всего, проверяет, была ли удалена требуемая запись. Если запись удалена, она недоступна для изменения, вследствие чего возникает исключение. В противном случае в поток помещается новое значение записи.

И последний метод, связанный с обработкой записей, - это метод Delete.

Листинг 2.24. Чтение и обновление записи в постоянном массиве


procedure TtdRecordStream.Delete(aIndex : longint);

var

DeletedFlag : longint;

begin

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

if (aIndex < 0) or (aIndex >= Capacity) then

rsError(tdeRSOutOfBounds, 'Delete', aIndex);

{проверить, что запись не была удалена}

rsSeekStream(rsCalcRecordOffset(aIndex));

rsReadStream(DeletedFlag, sizeof(longint));

if (DeletedFlag <> cActiveRecord) then

rsError(tdeRSAlreadyDeleted, 'Delete', aIndex);

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

rsSeekStream(rsCalcRecordOffset(aIndex));

rsWriteStream(FHeaderRec^.hr1stDelRec, sizeof(longint));

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