OberonCore https://forum.oberoncore.ru/ |
|
Аналог fread https://forum.oberoncore.ru/viewtopic.php?f=2&t=2006 |
Страница 1 из 1 |
Автор: | Rafi [ Среда, 04 Ноябрь, 2009 03:16 ] |
Заголовок сообщения: | Аналог fread |
Скажите, никто, случаем, не писал процедуру, через которую разом можно было бы перенести из файла в запись кусок объёмом SIZE(запись). И возможно ли вообще поместить скопом байты в запись без явной инициализации её полей? |
Автор: | Иван Кузьмицкий [ Среда, 04 Ноябрь, 2009 12:14 ] |
Заголовок сообщения: | Re: Аналог fread |
Много ли полей в записи? |
Автор: | Rafi [ Среда, 04 Ноябрь, 2009 12:53 ] |
Заголовок сообщения: | Re: Аналог fread |
Например, такая запись: Код: 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 не такая уж и проблема, но всё равно трудоёмко. Наверняка ведь можно сделать обобщённый вариант для всех записей. Или нет? |
Автор: | Илья Ермаков [ Среда, 04 Ноябрь, 2009 12:54 ] |
Заголовок сообщения: | Re: Аналог fread |
Прошу: Код: 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; |
Автор: | Илья Ермаков [ Среда, 04 Ноябрь, 2009 12:57 ] |
Заголовок сообщения: | Re: Аналог fread |
Получаем аналог паскалёвого file of record, но принципиально более мощный за счёт того, что это динамика, а не статика. Рискну утверждать, от своего опыта, что Files.File и пара процедур RecToFile и RecFromFile способна закрыть целый пучок задач с хранением данных - хоть на диске, хоть в памяти (можно - и даже нужно - ведь и с оперативной памятью работать через соотв. реализацию File). |
Автор: | Rafi [ Среда, 04 Ноябрь, 2009 13:13 ] |
Заголовок сообщения: | Re: Аналог fread |
Илья, большое спасибо!) Я тогда уж в целях избегания изобретения велосипедов, спрошу: не писал ли кто-нибудь процедурку загрузки tga?) |
Автор: | Валерий Лаптев [ Среда, 04 Ноябрь, 2009 13:16 ] |
Заголовок сообщения: | Re: Аналог fread |
Илья Ермаков писал(а): Получаем аналог паскалёвого file of record, но принципиально более мощный за счёт того, что это динамика, а не статика. Рискну утверждать, от своего опыта, что Files.File и пара процедур RecToFile и RecFromFile способна закрыть целый пучок задач с хранением данных - хоть на диске, хоть в памяти (можно - и даже нужно - ведь и с оперативной памятью работать через соотв. реализацию File). Ага!!!! Это как раз то, что я хочу в обучающем языке. Одна структура данных - контейнер. А внешний он или внутренний, нумерованный или нет - это его атрибуты... |
Автор: | Александр Ильин [ Среда, 04 Ноябрь, 2009 14:55 ] |
Заголовок сообщения: | Re: Аналог fread |
Rafi писал(а): Я тогда уж в целях избегания изобретения велосипедов, спрошу: не писал ли кто-нибудь процедурку загрузки tga?) Если речь идёт о графическом формате, то см. FreeImage.dll.
|
Автор: | Rafi [ Среда, 04 Ноябрь, 2009 21:29 ] |
Заголовок сообщения: | Re: Аналог fread |
Илья, а что это за 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; |
Автор: | Илья Ермаков [ Четверг, 05 Ноябрь, 2009 00:02 ] |
Заголовок сообщения: | Re: Аналог fread |
Пардон. Добавил. См. выше. |
Автор: | Роман М. [ Понедельник, 16 Ноябрь, 2009 23:42 ] |
Заголовок сообщения: | Re: Аналог fread |
Маленький пример использования кто-нибудь может написать? На примере записи, состоящей из двух INTEGER. А то сложно как-то. Меня смущает тот факт, что в BP7 всё на порядок проще. Или я не с той стороны смотрю. |
Автор: | Евгений Темиргалеев [ Понедельник, 16 Ноябрь, 2009 23:58 ] |
Заголовок сообщения: | Re: Аналог fread |
Вовсе не сложно. Код: 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); |
Автор: | Comdiv [ Воскресенье, 17 Июнь, 2018 23:32 ] |
Заголовок сообщения: | Re: Аналог fread |
Илья Ермаков писал(а): Код: 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 раз, но лучше не трогать. |
Автор: | Илья Ермаков [ Понедельник, 18 Июнь, 2018 14:42 ] |
Заголовок сообщения: | Re: Аналог fread |
Код уже кочевал в другие либы сто раз, надо проверить! Спасибо за указание! |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |