Фундаментальные алгоритмы и структуры данных в 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));
{обновить значение поля первой удаленной записи служебного заголовка, чтобы оно указывало на удаляемую запись}