GNAT -gnat95
Выбранная тактика поддержки Юникода такова, что с системными файловыми API мы не морочимся, а вот с содержимым заморочиться можно и нужно. Уж байтики прочитанные-то понять надо суметь.
Требуется реализовать пассивный интерфейс конвертации туда и обратно по типу iconv. iconv принимает на вход буфер, на выход буфер, и сообщает позицию, где остановились чтение и запись. Также возвращается причина остановки. Реальный сишный iconv, если смотреть его API, ещё принимает размеры входного и выходного буфера, в нашем случае нужно полагаться на возможности языка Ада передавать длины массива и, если, допустим, из буфера нужно читать не сначала или в буфер писать не с начала, нарезать нужный кусочек массива синтаксисом Массив (Индекс .. Индекс).
ВАЖНО: всевозможные функции, возвращающие массивы, как правило, делают их с начальным индексом 1, но полагаться на это запрещено. Начинать перебирать любой массив нужно с 'First, причём, с правильного 'First, соответствующего массиву, а то я как раз в библиотеке GNAT где-то напоролся в конвертации UTF, что там 'First не от того массива берётся.
Под пассивностью подразумевается, что функция конвертации не выделяет память, а только пишет, куда ей дали.
У конвертации есть некоторое состояние. Я думаю, будет достаточно объявить type Conversion_UTF_32_To_UTF_8 is private; и type Conversion_UTF_8_To_UTF_32 is private;
Внутри состояние конечного автомата и недособранный 32битный символ, предпочтительно, Interfaces.Unsigned_32.
От реализации я бы очень хотел реализации разгона, когда оба буфера позволяют. В общем случае работа функции конвертации может происходить так:
Если только UTF-8 <--> UTF-32, то посмотрите внимательно реализацию пакета Unbouded_Array. Может быть всё что нужно там уже есть. Все определения символов и строк специфицированы в файлах Ada_Magic_Forward.ads, Ada_Magic_Forward.Character_32s.ads и Ada_Magic_Forward.Strings.ads неким универсальным способом. Тип Character_32 я с самого начала определил как беззнаковый (мне для преобразования нужны были bitwize-операции). Все операции преобразования реализованы в пакете Unbounded_array. При преобразованиях определены способы реагирования на BOM. Если в UTF-8 строке недостаёт символов, генерируется исключения. Может просто дополнить пакет Unbouded_Array процедурами работы с бинарными потоками ЮНИКОДА? В проверку валидности включить проверку на присутствие символа в исключаемом диапазоне ЮНИКОДА?
При конвертации строк холостой проход у меня делается всегда, чтобы определить можно ли использовать существующий буфер или разместить новый. При конвертации потоков можно бы было использовать циклический буфер, но это бы нарушило понятие стандартного потока. Может быть расширить понятие бинарного потока для циклических буферов? Алгоритмы циклических буферов широко используются в системном программировании и в цифровых фильтрах. Собственно преобразование потоков по сути и есть классический цифровой фильтр.
Требуемый програмный интерфейс достаточно универсален, чтоб можно было закодировать поверх него и циклический буфер тоже. Если последний раз остановились где-то посередине, передаём срез в конце массива в конвертор. Потом передаём срез в начале массива в конвертор.
А не подскажете, есть ли сейчас в стандартной библиотеке АДы конвейеры FIFO?
Очередь и куча там есть, но это для многопоточных программ.
http://www.ada-auth.org/standards/12rat/html/Rat12-8-6.html
Я так понимаю, Ada.Containers.Bounded_Synchronized_Queues будет именно циклической.