вот такая либа надумалась:
<pre>
util/ fld.fts
branch/ handlers.fts
VOCABULARY Arrays
ALSO Arrays DEFINITIONS
0 struct array \ описатель массива
byte[] off_type \ тип массива
cell[] off_size \ размер массива в байтах
addr[] off_body \ смещение в начало массива
zero[] off_init \ флаг инициализации (только для HARRAY)
/struct
\ проверка на выход за диапазон массива
\ предполагается, что в массиве значения байтовой длины
\ ради повышения скорости можно убрать, но тогда не будет контроля границ
: within-limits ( i array --> i array )
DDUP off_size @ 0 SWAP WITHIN IF EXIT THEN
ERROR" запрашиваемый элемент за пределами массива!" ;
\ проверить, проинициализирован ли массив,
\ если нет, выделить память из хипа потока, связать ее с именем
: ?ArrayInit ( array --> array )
>L TlsIndex@ L@ off_init @ + @ IF L> EXIT THEN
L@ off_size @ ALLOCATE THROW L@ off_body A!
TlsIndex@ L@ off_init @ + ON
L> ;
RECENT ALSO Arrays
\ создать именованый массив размером в # байт с именем name
\ в статической области памяти
: ARRAY ( # / name --> )
CREATE HERE OVER /array + ALLOT
1 OVER off_type B!
off_size !
DOES> within-limits
+ off_body ;
\ создать именованый массив размером в # байт с именем name
\ в USER области (поэтому для каждого процесса будет уникален)
: UARRAY ( # / name --> )
CREATE HERE >L /array ALLOT
USER-HERE L@ off_body !
2 L@ off_type B!
DUP USER-ALLOT L> off_size !
DOES> within-limits
off_body @ TlsIndex@ + + ;
\ создать именованый массив размером в # байт с именем name
\ в динамической области памяти (массив с автоинициализацией!)
: HARRAY ( # / name --> )
CREATE HERE >L /array CELL + ALLOT
USER-HERE L@ off_init ! CELL USER-ALLOT \ флаг инициализации
3 L@ off_type B!
L> off_size !
DOES> ?ArrayInit \ отсюда адрес всегда действителен !
within-limits
off_body A@ + ;
\ получить базовый адрес и длину массива с именем name
: ARRAY> ( / name --> addr # )
' CFL + DUP [COMPILE] LITERAL
<: off_type B@
1 OVER = IF DROP <: DUP off_body SWAP off_size @ ;> EXIT THEN
2 OVER = IF DROP <: DUP off_body @ TlsIndex@ + SWAP off_size @ ;> EXIT THEN
3 OVER = IF DROP <: ?ArrayInit DUP off_body A@ SWAP off_size @ ;> EXIT THEN
;> EXECUTE \ --> addr xt
STATE @ IF COMPILE, ELSE EXECUTE THEN ; IMMEDIATE
PREVIOUS
\EOF пример использования:
10 ARRAY test[]
3 0 test[] B!
5 1 test[] B!
8 2 test[] B!
ARRAY> test[] DUMP
ARRAY> test[] ERASE
ARRAY> test[] DUMP
</pre>
изменять размер массива нельзя! Да и смысл это имеет только для массивов,
располагаемых в хипе, да и там лучше RESIZE не делать никогда.
во время обращения к элементам массивов производится проверка выхода за границы массива,
понятно, что это накладные расходы, и если очень хочется быстрее и не важно, будет ли
контроль, то можно удалить ссылки на within-limits в коде ARRAY UARRAY HARRAY
_________________ Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur
|