OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 17 Июль, 2018 14:31

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 14 ] 
Автор Сообщение
 Заголовок сообщения: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 03:16 

Зарегистрирован: Суббота, 02 Август, 2008 23:01
Сообщения: 43
Скажите, никто, случаем, не писал процедуру, через которую разом можно было бы перенести из файла в запись кусок объёмом SIZE(запись). И возможно ли вообще поместить скопом байты в запись без явной инициализации её полей?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 12:14 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2930
Откуда: г. Ярославль
Много ли полей в записи?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 12:53 

Зарегистрирован: Суббота, 02 Август, 2008 23:01
Сообщения: 43
Например, такая запись:
Код:
TgaHeader = RECORD;
   idLength: BYTE;
   colorMapType: BYTE;
   imageTypeCode: BYTE;
   colorMapSpec: ARRAY 5 OF BYTE;
   xOrigin: SHORTINT;
   yOrigin: SHORTINT;
   width: SHORTINT;
   height: SHORTINT;
   bpp: BYTE;
   imageDesc: BYTE
END;


Занести байты в поля с помощью rd.ReadByte и rd.ReadSInt не такая уж и проблема, но всё равно трудоёмко. Наверняка ведь можно сделать обобщённый вариант для всех записей. Или нет?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 12:54 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8958
Откуда: Россия, Орёл
Прошу:

Код:
MODULE назовите-как-хотите;
   IMPORT S := SYSTEM, Kernel, Files;

   TYPE
      Bytes = ARRAY [untagged] 1000000000 OF BYTE;

   PROCEDURE SizeOf* (IN rec: ANYREC): INTEGER;
      VAR type: Kernel.Type;
   BEGIN
      type := S.VAL(Kernel.Type, S.TYP(rec));
      RETURN type.size
   END SizeOf;

   PROCEDURE RecWithoutPtrFields* (IN rec: ANYREC): BOOLEAN;
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      RETURN t.ptroffs[0] < 0
   END RecWithoutPtrFields;

   PROCEDURE RecToBytes* (IN rec: ANYREC; VAR bytes: ARRAY OF BYTE; VAR pos: INTEGER);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      ASSERT(pos + t.size <= LEN(bytes), 21);
      IF Kernel.littleEndian THEN
         S.MOVE(S.ADR(rec), S.ADR(bytes) + pos, t.size);
         INC(pos, t.size)
      ELSE
         HALT(126)
      END
   END RecToBytes;

   PROCEDURE RecFromBytes* (VAR rec: ANYREC; IN bytes: ARRAY OF BYTE; VAR pos: INTEGER);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      ASSERT(pos + t.size <= LEN(bytes), 21);
      IF Kernel.littleEndian THEN
         S.MOVE(S.ADR(bytes) + pos, S.ADR(rec), t.size);
         INC(pos, t.size)
      ELSE
         HALT(126)
      END
   END RecFromBytes;

   PROCEDURE RecToFile* (IN rec: ANYREC; wr: Files.Writer);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      IF Kernel.littleEndian THEN
         wr.WriteBytes(S.VAL(Bytes, rec), 0, t.size)
      ELSE
         HALT(126)
      END
   END RecToFile;

   PROCEDURE RecFromFile* (VAR rec: ANYREC; rd: Files.Reader);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      IF Kernel.littleEndian THEN
         rd.ReadBytes(S.VAL(Bytes, rec), 0, t.size)
      ELSE
         HALT(126)
      END
   END RecFromFile;

   PROCEDURE New* (IN sameType: ANYREC): ANYPTR;
   BEGIN
      RETURN S.VAL(ANYPTR, Kernel.NewRec(S.TYP(sameType)))
   END New;

   PROCEDURE CopyBase* (IN src: ANYREC; VAR dest: ANYREC);
(* Берёт "общий знаменатель" двух записей и копирует из src в dest *)
      VAR ts, td: Kernel.Type;
            i: INTEGER;
   BEGIN
      ASSERT(S.ADR(src) # S.ADR(dest), 20);
      ts := S.VAL(Kernel.Type, S.TYP(src));
      td := S.VAL(Kernel.Type, S.TYP(dest));
      i := 0;
      WHILE (ts.base[i] # NIL) & (ts.base[i] = td.base[i]) DO
         INC(i)
      END;
      IF i > 0 THEN
         S.MOVE(S.ADR(src), S.ADR(dest), ts.base[i-1].size) 
      END
   END CopyBase;



Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 12:57 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8958
Откуда: Россия, Орёл
Получаем аналог паскалёвого file of record, но принципиально более мощный за счёт того, что это динамика, а не статика.

Рискну утверждать, от своего опыта, что Files.File и пара процедур RecToFile и RecFromFile способна закрыть целый пучок задач с хранением данных - хоть на диске, хоть в памяти (можно - и даже нужно :) - ведь и с оперативной памятью работать через соотв. реализацию File).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 13:13 

Зарегистрирован: Суббота, 02 Август, 2008 23:01
Сообщения: 43
Илья, большое спасибо!)
Я тогда уж в целях избегания изобретения велосипедов, спрошу: не писал ли кто-нибудь процедурку загрузки tga?)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 13:16 

Зарегистрирован: Суббота, 07 Март, 2009 15:39
Сообщения: 2846
Откуда: Астрахань
Илья Ермаков писал(а):
Получаем аналог паскалёвого file of record, но принципиально более мощный за счёт того, что это динамика, а не статика.

Рискну утверждать, от своего опыта, что Files.File и пара процедур RecToFile и RecFromFile способна закрыть целый пучок задач с хранением данных - хоть на диске, хоть в памяти (можно - и даже нужно :) - ведь и с оперативной памятью работать через соотв. реализацию File).

Ага!!!! Это как раз то, что я хочу в обучающем языке. Одна структура данных - контейнер. А внешний он или внутренний, нумерованный или нет - это его атрибуты... :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 14:55 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2289
Откуда: Россия, Санкт-Петербург
Rafi писал(а):
Я тогда уж в целях избегания изобретения велосипедов, спрошу: не писал ли кто-нибудь процедурку загрузки tga?)
Если речь идёт о графическом формате, то см. FreeImage.dll.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Среда, 04 Ноябрь, 2009 21:29 

Зарегистрирован: Суббота, 02 Август, 2008 23:01
Сообщения: 43
Илья, а что это за Bytes такой?..

Код:
PROCEDURE RecFromFile* (VAR rec: ANYREC; rd: Files.Reader);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      IF Kernel.littleEndian THEN
         rd.ReadBytes(S.VAL(Bytes, rec), 0, t.size)
      ELSE
         HALT(126)
      END
   END RecFromFile;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Четверг, 05 Ноябрь, 2009 00:02 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8958
Откуда: Россия, Орёл
Пардон.
Добавил. См. выше.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Понедельник, 16 Ноябрь, 2009 23:42 
Аватара пользователя

Зарегистрирован: Пятница, 25 Сентябрь, 2009 13:10
Сообщения: 1158
Откуда: Tel-Aviv
Маленький пример использования кто-нибудь может написать? На примере записи, состоящей из двух INTEGER.
А то сложно как-то. Меня смущает тот факт, что в BP7 всё на порядок проще. Или я не с той стороны смотрю. :oops:


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Понедельник, 16 Ноябрь, 2009 23:58 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4485
Откуда: Россия, Орёл
Вовсе не сложно.
Код:
TYPE MyRec = RECORD ... END;

VAR wr: Files.Writer; rd: Files.Reader; f: Files.File; x: MyRec;
f := Files.dir. ... ЧИТАЕМ ДОКУМЕНТАЦИЮ Files
wr := f.NewWriter(NIL); wr.SetPos(0);
назовите-как-хотите.RecToFile(x, wr);
rd := f.NewReader(NIL); rd.SetPos(0);
назовите-как-хотите.RecFromFile(x, rd);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Воскресенье, 17 Июнь, 2018 23:32 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 675
Откуда: Киев
Илья Ермаков писал(а):
Код:
MODULE назовите-как-хотите;
...
   PROCEDURE RecToBytes* (IN rec: ANYREC; VAR bytes: ARRAY OF BYTE; VAR pos: INTEGER);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      ASSERT(pos + t.size <= LEN(bytes), 21);
      IF Kernel.littleEndian THEN
         S.MOVE(S.ADR(rec), S.ADR(bytes) + pos, t.size);
         INC(pos, t.size)
      ELSE
         HALT(126)
      END
   END RecToBytes;

Этот код используется где-то?
Вот эта проверка
Код:
ASSERT(pos + t.size <= LEN(bytes), 21);
Ошибочно пройдёт при отрицательном pos или pos > MAX(INTEGER) - t.size
После того, как в мире Си внезапно обнаружили, что нужно контролировать целостность буфера, для уязвимостей стали использовать ошибки в проверках, зачастую, основанных на неконтролируемом арифметическом переполнении.

Если трогать SYSTEM, то нужно всё проверять по 10 раз, но лучше не трогать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог fread
СообщениеДобавлено: Понедельник, 18 Июнь, 2018 14:42 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 8958
Откуда: Россия, Орёл
Код уже кочевал в другие либы сто раз, надо проверить!

Спасибо за указание!


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 14 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2018, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB