Работа выполняется в GNAT -gnat95.
За основу программного интерфейса берётся Vector из библиотеки контейнеров. В GNAT явно указано, что то, что выше private, имеет происхождение из ISO стандарта Ada, и общедоступен. У нас будет солянка. Производный от общедоступного продукт можно лицензировать под Апаче. Расписывать, какой метод повторяет то, что есть в стандарте, а какой — нет, можно заскучать. Я предлагаю ограничиться пометкой, как в GNAT, что нечто, но не всё, имеет происхождение из ISO стандарта Ada, но в отличие от GNAT, не расписывать.
Реализовать нужно как минимум добавление и определение количества элементов.
Также нужно реализовать по аналогии с Fast_Strings быстрый доступ к элементам.
При разработке необходимо учесть «любовь» транслятора к избыточному копированию. Учёт этого обстоятельства заключается в том, что реализуется копирование при записи. Вектор по своей природе содержит ссылки, это нормально, но, как правило, структура, на которую сделана ссылка, уникальна. Придётся уникальностью пожертвовать.
В отличие от TList<>, IList<> и TArray<> в Delphi, и аналогично Ada 2005+ контейнерам, значения типа Vector считаются независимыми после копирования. Так что для чтения можно разделять структуры данных, но и только. Перед любыми изменяющими операциями выполняется публично доступная процедура Unique, приводящая вектор к состоянию уникальности содержимого, если счётчик ссылок не 1.
Структура в динамической памяти не должна быть tagged. Массив, из которого структура состоит, должен быть из Storage_Element, но с выравниванием, как у Element. Впоследствии, при выделении элементов используется специальный выделитель памяти, который при выделении возвращает заранее известный адрес, а при освобождении — ничего не делает. С его помощью инициализируются и финализируются элементы в векторе.
Под быстрым доступом имеется в виду возможность закрепить на стеке структуру Vector_View, посредством которой можно обозревать содержимое на чтение. Для этого используется дискриминант неограниченного указателя на массив элементов. И тогда это закрепление добавляет ссылку на время своего существования. В Fixed_Strings это достигалось копированием Unbounded_String внутрь себя. В данном проекте Vector предполагает наличие внутри себя замков на запись, и тогда класть копию Vector внутри себя не очень хорошо. Придётся сделать ещё раз Initialize/Finalize для подсчёта ссылок.
Для доступа на запись структура Vector_Edit. Аналогично String_Edit, забирает на время своего существования содержимое исходного вектора, ведь редактировать можно только уникальное содержимое. А если не забирать, уникальным оно не будет. В Finalize гипотетически может обнаружиться, что в том векторе, откуда забирали содержимое, снова что-то есть. Значит, уничтожить и заменить своим.
В Fast_Strings String_View — это функция, возвращающая Ada 2012 ссылку, а String_Edit — структура, производящая манипуляции над собой и целью в Initialize и Finalize. В Ada 95 нельзя из функции вернуть limited. Позволить этим структурам быть копируемыми тоже нельзя. Поэтому и View, и Edit будут устроены как Edit.
Такой вектор должен будет стать фундаментом для аналога Unbounded_Wide_Wide_String.
Куда складывать, напишу позже.