MemoryRecord.Create

From SunFlurry wiki
Revision as of 08:50, 24 October 2020 by Admin (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
  Create (Создание записи)
Объект:Запись
Статус разработки: Реализована
Тип:Функция
Обращение к БД:Нет
Исключения:Невозможно превратить в число, строку, не буфер, синтаксическая ошибка.
Визуальность:Нет

Функция создает новый объект записи по указанным правилам, привязывая его к существующему буферу, если это необходимо.

Синтаксис

MemoryRecord.Create(<Описание структуры записи (STRING)>,<Привязать созданную запись к буферу (BUFFER)>,<Индекс в буфере (INT)>):<Новый объект записи (MEMORYRECORD)>

Аргументы

  • <Описание структуры записи (STRING)> - Задает описание структуры записи в виде строки. Строка имеет следующий формат: <Группа полей или поле 1>,<Группа полей или поле 2>,.... Где Группа полей или поле имеет может быть задана в виде <Поле> или [<Поле 1>,<Поле 2>,...]. Группы полей задают поля, смещение которых начинается с одного и того же адреса памяти. Вся группа занимает такое место в памяти, как и максимальное поле этой группы. Группы полей иногда используются в вызовах системы для уменьшения размера передаваемых записей, путем совмещения полей, задающихся по условию. Каждое из полей имеет следующий формат: <Наименование поля>:<Тип данных поля>. Наименование поля не должно содержать знаков ,, [, ], :, наименования используются без учета регистра. Тип данных представляет собой строку, состоящую из некоторого числа префиксов, наименования типа данных и, если требуется, его размера. Далее даются все возможные префиксы и наименования типов данных:
    • ^ (префикс) -- определяет то, что запись будет содержать ссылку (указатель, pointer) на данные, а не сами данные. При наличии префикса массива A, данный префикс можно употреблять как до префикса массива (указывает на то, что запись хранит ссылку на массив), так и после префикса массива (указывает на то, что массив хранит ссылки на значения); кроме того, для массивов разрешается смешанное использование с префиксом ^^ (к примеру, до префикса массива используется префикс ^, а после ^^).
    • ^^ (префикс) -- определяет то, что запись будет содержать ссылку (указатель, pointer) на ссылку на данные, а не сами данные. При наличии префикса массива A, данный префикс можно употреблять как до префикса массива (указывает на то, что запись хранит ссылку на ссылку на массив), так и после префикса массива (указывает на то, что массив хранит ссылки на ссылки на значения); кроме того, для массивов разрешается смешанное использование с префиксом ^ (к примеру, до префикса массива используется префикс ^, а после ^^).
    • U (префикс) -- используется для типов I или N, указывает на то, что данные представляют собой беззнаковое число (по умолчанию число со знаком)
    • A<Размер массива>: (префикс) -- используется для указания на массив. Размер массива может быть нулевым, если он заранее не известен, однако, это допускается только для ссылок на массив, так как иначе система не сможет определить размер записи. Префикс массива можно смешивать с префиксами ^ и ^^, причем данные префиксы могут следовать как до префикса массива, так и после. Система не позволяет использовать несколько префиксов массивов одновременно (планируется к реализации), вместо этого необходимо использовать ссылку на другую запись.
    • I<Размер в битах> или Int<Размер в битах> (наименование типа данных) -- задает целый тип поля. Размер может принимать следующие значения: 8, 16, 32, 64.
    • N или Native (наименование типа данных) -- задает целый тип поля с размером текущей архитектура исполнения. Для x86 длина поля будет поставлять 32 бита, для x64 -- 64 бита.
    • R<Размер в битах> или Real<Размер в битах> (наименование типа данных) -- задает вещественный тип поля. Размер может принимать следующие значения: 32 (одинарная точность), 64 (двойная точность), 80 (расширенная точность).
    • B<Размер в битах> или Bool<Размер в битах> (наименование типа данных) -- задает булевый тип поля. Размер может принимать следующие значения: 8, 16, 32, 64.
    • P или Pointer (наименование типа данных) -- задает тип данных указателя на адрес памяти. Для x86 длина поля будет поставлять 32 бита, для x64 -- 64 бита.
    • @<Переменная с записью> (наименование типа данных) -- задает ссылку на другую запись данных, заданную наименованием переменной, в которой она хранится. Вложение записей можно производить неограниченное количество раз.
    • SZ<Размер в байтах> или SZW<Размер в словах> (наименование типа данных) -- задает поле с типом строка, заканчивающаяся нулевым символом. Строка может иметь формат ANSI (SZ) или UTF-16 (SZW). Обычно задается ссылка на строку (используется ^ префикс), но задание строки внутри записи также разрешено. При использовании ссылки на строку, размер может принимать нулевое значение.
    • S<Размер в байтах> или SW<Размер в словах> (наименование типа данных) -- задает поле с типом строка фиксированной длины. Строка может иметь формат ANSI (S) или UTF-16 (SW).
  • <Привязать созданную запись к буферу (BUFFER)> - (необязательный аргумент) Привязывает новую запись к существующему буферу, если данный аргумент опущен, запись будет создана без привязки (после создания можно выделить новый буфер с помощью функции Allocate или привязать к буферу или системной памяти с помощью функций Assign, AssignToSystemMemory).
  • <Индекс в буфере (INT)> - (необязательный аргумент) Задает индекс в буфере, к которому будет осуществлена привязка созданной записи. Если второй параметр опущен, данный не имеет значения. По умолчанию привязка создается к началу буфера. Адресация буфера начинается с нуля.

Возвращаемое значение

Возвращается новый объект записи

Примеры

Пример создания простых записей

//Системные записи, связанные с разрешениями
SE_PRIVILEGE_ENABLED:=2;
rLUID_AND_ATTRIBUTES:=MemoryRecord.Create("Luid:I64,Attributes:UI32");
rTOKEN_PRIVILEGES1:=MemoryRecord.Create("PrivilegeCount:UI32,Privileges:A1:@rLUID_AND_ATTRIBUTES");
rTOKEN_PRIVILEGES1.Allocate();
rTOKEN_PRIVILEGES1.PrivilegeCount:=1;
rTOKEN_PRIVILEGES1.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
rTOKEN_PRIVILEGES1.Privileges[0].Luid:=Luid;

//Запись элемента BMP-32 файла
rRGBQUAD:=MemoryRecord.Create("rgbBlue:UI8,rgbGreen:UI8,rgbRed:UI8,rgbReserved:UI8");

//Запись заголовка BMP файла
rBITMAPINFOHEADER:=MemoryRecord.Create("biSize:UI32,biWidth:I32,biHeight:I32,biPlanes:UI16,biBitCount:UI16,biCompression:UI32,biSizeImage:UI32,"+
  "biXPelsPerMeter:I32,biYPelsPerMeter:I32,biClrUsed:UI32,biClrImportant:UI32");

//Системная запись SID_IDENTIFIER_AUTHORITY
rSID_IDENTIFIER_AUTHORITY:=MemoryRecord.Create("Value:A6:UI8");
rSID_IDENTIFIER_AUTHORITY.Allocate();
rSID_IDENTIFIER_AUTHORITY.Value[0]:=1;

Пример создания записи со ссылкой на структуру другой записи (^@)

//Заполнение буфера
aBuf:=Buffer.Create(4096);
aBuf.Fill(0,4096,0);
//Байт с позицией 3 равен 132.
aBuf[3]:=132;
//Адрес буфера в системной памяти
aMem:=aBuf.SystemAddress();

//Создание записи
rRec:=MemoryRecord.Create("Value:A6:UI8");
//Создание второй записи с ссылкой на первую
rRec2:=MemoryRecord.Create("Value:^@rRec");
//Выделение памяти под запись
bBuf:=rRec2.Allocate();
//Запись адреса памяти в начало записи (работает как для x86, так и для x64)
If PointerSize()=4 Then
  bBuf.SetDWord(0,aMem);
Else
  bBuf.SetQWord(0,aMem);
EndIf;

//Будет выведено число 132
Message(rRec2.Value.Value[3]);

Пример создания записи со строкой фиксированной длины

rRec:=MemoryRecord.Create("Value:SW20");
//Выделение памяти
rRec.Allocate();
//Заполним запись строкой с 21 символом
rRec.Value:="123456789012345678901";
//Будет выведено "12345678901234567890"
Message(rRec.Value);

Пример создания записи со ссылкой на массив ссылок на байты данных (^A^)

//Заполнение буфера
aBuf:=Buffer.Create(4096);
aBuf.Fill(0,4096,132);
//Байт с позицией 3 равен 133, а не 132, как остальные байты буфера
aBuf[3]:=133;

//Создаем и заполняем массив ссылок на байты первого буфера
bBuf:=Buffer.Create(1000);//требуется всего 800 или 400 байт
iPos:=0;
For i:=1 to 100 Do
  //Адрес байта
  aMem:=aBuf.SystemAddress(i-1);
  //Сохранение адреса во втором буфере
  If PointerSize()=4 Then
    bBuf.SetDWord(iPos,aMem);
    iPos:=iPos+4;
  Else
    bBuf.SetQWord(iPos,aMem);
    iPos:=iPos+8;
  EndIf;
EndDo;

//Адрес начала второго буфера в системной памяти
aMem:=bBuf.SystemAddress();

//Создание записи
rRec:=MemoryRecord.Create("Value:^A100:^UI8");
//Выделение памяти на запись
cBuf:=rRec.Allocate();
//Запись адреса памяти в начало записи
If PointerSize()=4 Then
  cBuf.SetDWord(0,aMem);
Else
  cBuf.SetQWord(0,aMem);
EndIf;

//Будет выведено число 133
Message(rRec.Value[3]);

Пример создания записи с массивом, состоящим из других записей (A@)

//Заполнение буфера
aBuf:=Buffer.Create(4096);
aBuf.Fill(0,4096,0);

//Создаем запись, которая будет содержать в массиве, поля V3 и V4 объединены в группу
rRec2:=MemoryRecord.Create("V1:UI8,V2:UI8,[V3:UI8,V4:UI32]");
//Создаем запись с массивом записей
rRec:=MemoryRecord.Create("Data:A100:@rRec2");
//Выделяем память
aBuf:=rRec.Allocate();
//Записывает в буфер без использования записи (поле V4 элемента массива 2)
aBuf.SetDWord(2+rRec2.Size()*2,132132);
//Будет выведено 132132
Message(rRec.Data[2].V4);
//Будет выведено 36 (младший байт числа 132132)
Message(rRec.Data[2].V3);
//Будет выведено 6 (V1 (1 байт) + V2 (1 байт) + [V3:UI8,V4:UI32] (4 байта))
Message(rRec2.Size());
//Будет выведено 600 (rRec2.Size()*100)
Message(rRec.Size());