IPB
ЛогинПароль:

 
 Ответить  Открыть новую тему 
> Двоичные потоки, На будущее
сообщение
Сообщение #1


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 194
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: bu_gen@octagram.name
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


GNAT -gnat95

Используя механизм сильных ссылок, реализовать потоки



За основу берётся пакет Ada.Streams. Более конкретно, оттуда импортируются типы. И по аналогии с теми методами делаются методы здесь.

Аналогично Sample_Reference, делаются два типа. Один — для наследования, Root_Stream_Referenced. Другой — обёртка Root_Stream для применения в будущих пакетах.

Для интеграции с Адой в одну сторону делается Ada_Stream, обёртка-наследник стандартного Ada.Streams.Root_Stream_Type. Обёртка не реализует по второму разу Root_Stream, а содержит её в публично доступном поле и просто делегирует вызовы методов.

В обратную сторону в общем случае не получится, и делается только один частный случай, File_Stream_Referenced, содержащий Ada.Streams.Stream_IO.File_Type.

Как и всегда при использовании механизма сильных ссылок, делаются попарно два типа, для динамической памяти File_Stream_Referenced и обёртка File_Stream. API изменяется.

    procedure Create (File : in out File_Type;
Mode : in File_Mode := Out_File;
Name : in String := "";
Form : in String := "");


Create превращается в функцию, возвращающую сильную ссылку. Form убирается. Тип Name заменяется на String_32. Можно объявить subtype String_32 is Wide_String, чтоб собиралось. Wide_String приводится к String конструкциями вида Character'Val (Unsigned_8'Mod (Character_32'Pos (Element))). Работать, конечно, с Юникодом оно нормально так не будет, но API правильное.

Аналогично с Open.

Delete не нужен. Close в явном виде не нужен, а неявно он вызывается из Finalize после проверки Is_Open. В Finalize нужно также вызвать родительский Finalize.

Унаследованные Read и Write переопределяются.

Функция Stream выбрасывается. Read и Write реализуются без неё, а если нужен адский поток, то обёртка для этого уже сделана выше.

function Name приводится к String_32 дубовым способом, как и в Create.

function Form выбрасывается.



Задача мне: надо дать заглушки для поддержки Ada 2005+ фич в AdaMagic. Я писал такое, но не под рукой сейчас


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +



Задачу в первом приближении понял. Займусь несколько позже.
Сейчас занимаюсь векторами. К стати, в АДА2012 вектора могут работать с потоками. Реализовать эту функциональность для наших векторов?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +


Раньше мне вроде бы было всё понятно. Сейчас у меня новый уровень понимания -- почти ничего не понятно. Зачем множить ссылки на файл? Лишь для того, чтобы деструктор в конце закрыл файл? Или каждый экземпляр ссылки должен иметь свои собственные атрибуты (типа позиции файла и моды файла)? Тогда нужно ли вводить спин-блокировку на операции, изменяющие эти атрибуты? Как нужно порождать новые экземпляры ссылок, специальной функцией типа "New_Instance" или простым копированием ссылки? Нужно ли вводить процедуру отсоединения ссылки от файла типа "Release_Instance" или "Detach_Instance"? Как реализовывать функциональность пакета, простым вызовом процедур из пакета "Ada.Streams.Stream_IO" или разработать независимую реализацию? И это, думаю, далеко не полный список вопросов.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 194
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: bu_gen@octagram.name
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


Цитата(Sergey Dukov @ 21.10.2019 13:03) *
Раньше мне вроде бы было всё понятно. Сейчас у меня новый уровень понимания -- почти ничего не понятно. Зачем множить ссылки на файл?


Только лишь для того, чтоб перекрытое совместное владение реализовать. Кто в C++ давно, может быть, застал те времена, когда auto_ptr в контейнеры пытались класть, и как оно всё разваливалось. Контейнеры под auto_ptr никто так и не переписал, а зато разделяемые указатели начали применять чаще, чем, казалось бы, можно. Никаких задач сверх этого не возлагается.

И ссылки на файл не множатся. Есть только реализация потомка абстрактного потока, заключающая в себе File_Type. На эту реализацию могут идти потенциально множественные ссылки. Поток при этом один.

Цитата(Sergey Dukov @ 21.10.2019 13:03) *
Лишь для того, чтобы деструктор в конце закрыл файл?


Да, это тоже важная задача.

Цитата(Sergey Dukov @ 21.10.2019 13:03) *
Или каждый экземпляр ссылки должен иметь свои собственные атрибуты (типа позиции файла и моды файла)?


Не требуется ни сейчас, ни потом.

Цитата(Sergey Dukov @ 21.10.2019 13:03) *
Нужно ли вводить процедуру отсоединения ссылки от файла типа "Release_Instance" или "Detach_Instance"?


На текущий момент нет.

Цитата(Sergey Dukov @ 21.10.2019 13:03) *
Как реализовывать функциональность пакета, простым вызовом процедур из пакета "Ada.Streams.Stream_IO" или разработать независимую реализацию? И это, думаю, далеко не полный список вопросов.


Сейчас и, как ожидается, ещё долго, пока не наметится рабочий прототип, это будет вызов стандартной библиотеки. Потом планируется независимая реализация, правильно поддерживающая юникодные имена файлов.


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +



Насколько я понял, задача такова:
Упрятать значение типа "Ada.Streams.Stream_IO.File_Type" в объект некого другого типа, имеющий счётчик инстанций. Новые инстанции открытого объекта получать простой операцией присвоения.
А как назвать новый тип? Может быть "Referenced_File"?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 194
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: bu_gen@octagram.name
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


Цитата(Sergey Dukov @ 25.10.2019 0:57) *

Насколько я понял, задача такова:
Упрятать значение типа "Ada.Streams.Stream_IO.File_Type" в объект некого другого типа, имеющий счётчик инстанций. Новые инстанции открытого объекта получать простой операцией присвоения.
А как назвать новый тип? Может быть "Referenced_File"?


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

Большой объект в памяти File_Stream_Referenced наследуется от абстрактного Root_Stream_Referenced, и автоматически получается limited.

Пользователям по возможности раздаются сильные ссылки File_Stream. У File_Stream_Referenced есть конструирующие методы Create и Open. Ведь функции не могут возвращать limited в Ada 95. Значит, методы. access File_Stream_Referenced у них первым аргументом, как и всегда.

Эти методы заворачиваются в функции, возвращающие сильные ссылки. То есть, на первом плане есть функции Create и Open, возвращающие сильные ссылки на File_Stream. Вот File_Stream-то копируемый.

Должно быть возможно написать

New_Stream : File_Stream := Open (выражение типа Wide_Wide_String, режим файла);


У сильной ссылки File_Stream должен быть метод Upcast, приводящий её к сильной ссылке Root_Stream на абстрактный поток.


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +


Я тут подумал, что на будущее стоит ввести в пакет "Unbounded_Array" процедуры работы с UTF16, чтобы потом реализовать открытие и работу с файловыми потоками через стандартную СИ-шную библиотеку которая поддерживает UTF16.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +


Я проанализировал открытие файла потока в реализациях GNAT и в AdaMagic, и пришёл к выводу что заморачиваться с UTF16 не имеет смысла. Функция _wfopen имеется только в СИ-библиотеке MSVCRT. В GNAT дескриптор потока AFCB имеет поле Encoding, которое описывает кодировку поля имени. По умолчанию это -- UTF-8. Само открытие потока осуществляется функцией fopen (импортируемое имя "__gnat_fopen"), которая третьим параметром имеет значение Encoding. Эта функция анализирует соответствующие условия в целевой ОС и осуществляет перекодировку строки имени файла с помощью функций библиотеки libiconv. Так что в GNAT нет проблем с открытием потока с UNICODE-именем. В стандартной реализации исполняющей библиотеке AdaMagic просто вызывается функция fopen из <stdio.h>, которая обычно не воспринимает UNICODE-имени. Так что AdaMagic нужно переопределить реализацию открытия потока и эта реализация будет зависеть от целевой ОС.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +


Я реализовал задание в пакете "File_Stream_IO". О том, что явный вызов процедуры "Close" не нужен, я помнил, а о процедуре "Delete" забыл. Реализовав эту процедуру, я долго думал как устранить конфликты между инстанциями потока в результате вызова процедуры "Delete". Посмотрел первоначальное задание и просто удалил реализацию этой процедуры. Как это у вас получается -- предусматривать всё на свете?
При реализации процедур с UNICODE-именами я как бы предположил, что стандартный пакет "Ada.Streams.Stream_IO" воспринимает эти имена в кодировке UTF-8. Для GNAT -- это верно, а для других компиляторов может потребоваться отдельная реализация этих процедур.
Жду дальнейших заданий.

Сообщение отредактировано: Sergey Dukov -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 194
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: bu_gen@octagram.name
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


UTF-16 в рантаймах, сейчас мне кажется, не надо

Либо дубовая ASCII поверх стандартного API сейчас. Либо конкретно забуриться в системное API и сделать как следует. Тратить время на промежуточные решения не требуются


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +


Я уже говорил, что с UTF-16 не стоит заморачиваться. Лучше сделать как в GNAT. Там анализируется текущая локаль и делается перекодировка с помощью функций библиотеки LIBICOVN. Кстати, ASCII -- подмножество UTF-8.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Большевик–концептуал
***

Группа: Пользователи
Сообщений: 194
Пол: Мужской
Реальное имя: Иван Левашев
Jabber: bu_gen@octagram.name
Skype: i.levashew
QQ: 3152538431
WeChat
Ада: Сторонник
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик
Turbo Pascal: Установлен

Репутация: -  1  +


В других своих проектах, которые заточены под GNAT, я объявил константу для Form и активно этим пользуюсь, но сейчас не готов делать на это ставку.

Вот, например, gprbuild, помню, перестаёт работать, если где-то в пути есть кириллица. Где-то как UTF-8 всё прочиталось, а где-то забыли, и в другое API всё пошло, где как ANSI интерпретация. Если не размежеваться с однобайтовыми кодировками, этот раздрай так и будет. Уж либо не делать, либо делать как следует.

Сейчас как следует делается наше API, а реализация не делается никак. 32битные символы, которыми задаётся имя файла, нужно через mod 256 приводить к номеру символа Character. Это моё текущее понимание «никак»


--------------------
If you want to get to the top, you have to start at the bottom
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Новичок
*

Группа: Пользователи
Сообщений: 27
Пол: Мужской
Реальное имя: Сергей Дюков
Skype: sergey.dukov54
Ада: Разработчик
Компонентный Паскаль: Сторонник

Репутация: -  0  +


Я подключил API из нашего пакета Unbounded_Array и для ASCII оно так и получится.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 29.03.2024 7:22
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name