При имплементации интернет-протоколов часто требуется упаковать значения в
определённом формате. Например, представить число 0x123456
в виде 32-битного
целого числа в формате Big-endian (и получить строку "\0\x12\x34\x56"
).
Для этих целей Lua 5.3 имеет функции string.pack
, string.unpack
и
string.packsize
. Все они требуют строку формата.
Строка формата — это последовательный набор символов, которые определяют, как будут конвертироваться значения.
Опция | Тип аргумента | Описание |
---|---|---|
Конфигурация | ||
< | — | Устанавливает формат little-endian для последующих опций. |
> | — | Устанавливает формат big-endian для последующих опций. |
= | — | Устанавливает формат LE/BE в зависимости от платформы, на которой исполняется код, для последующих опций |
!n | — | Устанавливает выравнивание на i байт. |
Аргументы | ||
b | Целое число | Знаковый числовой тип char (1 байт) |
B | Целое число | Беззнаковый числовой тип char (1 байт) |
h | Целое число | Знаковый числовой тип short |
H | Целое число | Беззнаковый числовой тип short |
l | Целое число | Знаковый числовой тип long |
L | Целое число | Беззнаковый числовой тип long |
j | Целое число | Числовой тип lua_Integer |
J | Целое число | Числовой тип lua_Unsigned |
T | Целое число | Числовой тип size_t |
i | Целое число | Знаковый числовой тип int |
I | Целое число | Беззнаковый числовой тип int |
in | Целое число | Число размером в n байт со знаком |
In | Целое число | Число размером в n байт без знака |
f | Число | Число типа float |
d | Число | Число типа double |
n | Число | Число типа lua_Number |
cn | Строка | Строка размером в n байт |
z | Строка | Строка, заканчивающаяся нулевым байтом \0 |
s | Строка | Строка, перед которой записан её размер числом типа size_t |
sn | Строка | Строка, перед которой записан её размер числом размером в n байт |
Пэддинг | ||
x | — | Один байт пэддинга (нулевой байт) |
Пробелы в строке формата игнорируются.
Скармливать её можно в три функции:
string.pack(formatString: string, args...)
— спакует значения в строку
по формату.string.unpack(formatString: string, args...)
— распакует значения из строки
по формату.string.packsize(formatString: string)
— вернёт размер строки, получаемой из
string.pack
с данной строкой формата. Последняя не должна содержать опции
s
или z
.-- Для удобства определим функцию `hex`.
local function hex(s)
return s:gsub(".", function(c)
return ("%02x "):format(c:byte())
end):sub(1, -2)
end
print(hex(string.pack("> s3 I4 n", "hello", 0x12345678, math.pi)))
--> 00 00 05 68 65 6c 6c 6f 12 34 56 78 40 09 21 fb 54 44 2d 18
--[[\______/ \____________/ \_________/ \_____________________/
длина строка "hello" I4 число 3.1415926535898
\_____________________/ lua_Number
s3
]]
print(string.unpack(
"> s3 I4 n",
"\0\0\5\x68\x65\x6c\x6c\x6f\x12\x34\x56\x78\x40\9\x21\xfb\x54\x44\x2d\x18"
))
--> hello 305419896 3.1415926535898
-- (на разных машинах может отличаться)
print(string.packsize("> I4 n f T"))
--> 24