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

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

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

Листинг 2.22. Добавление новой записи в постоянный массив

function TtdRecordStream.Add(var aRecord): longint;

begin

{если цепочка удаленных записей пуста, в поток добавляется новая запись}

if (FHeaderRec^.hr1stDelRec = cEndOfDeletedChain) then begin

Result :=FCapacity;

inc(FCapacity);

inc(FHeaderRec^.hrCapacity);

end

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

else begin

Result := FHeaderRec^.hr1stDelRec;

rsSeekStream(rsCalcRecordOffset(FHeaderRec^.hr1stDelRec))/ rsReadStream(FHeaderRec^.hr1stDelRec, sizeof(longint));

end;

{определить смещение записи и сохранить новую запись}

rsSeekStream(rsCalcRecordOffset(Result));

PLongint(FRecord)^ := cActiveRecord;

Move(aRecord, FRecord^[sizeof(longint)], FRecordLen);

rsWritestream(FRecord^, FRecordLen4);

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

inc(FCount);

inc(FHeaderRec^.hrCount);

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

rsSeekStream(FZeroPosition);

rsWriteStream(FHeaderRec^, sizeof(TtdRSHeaderRec));

end;

Если цепочка удаленных записей не пуста, определить первую удаленную запись (именно поверх нее будет сохраняться новая запись). Мы считываем флаг удаления для этой записи и обновляем поле первой удаленной записи служебного заголовка. Затем мы определяем положение начала удаленной записи, устанавливаем значение флага удаления равным cActiveRecord (-1) и сохраняем запись, переданную методу во входном параметре.

При считывании и сохранении записей необходимо учитывать, удалена ли требуемая запись. Записи идентифицируются по их порядковым номерам.

Листинг 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));

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

FHeaderRec^.hr1stDelRec := aIndex;

{количество записей уменьшилось на единицу}

dec(FCount);

dec(FHeaderRec^.hrCount);

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

rsSeekStream(FZeroPosition);

rsWriteStream(FHeaderRec^, sizeof(TtdRSHeaderRec));

end;

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

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

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

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

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

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

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

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

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