-------- Пересылаемое сообщение -------- От кого: Nikita Tatunov Кому: Vladislav Shpilevoy Копия: tarantool-patches@freelists.org, Alexander Turenko Дата: Четверг, 9 августа 2018, 13:08 +03:00 Тема: Re[3]: [PATCH] lua: add string.fromhex method Diff: diff --git a/src/lua/string.lua b/src/lua/string.lua index 5ff64c9f6..f6accb42c 100644 --- a/src/lua/string.lua +++ b/src/lua/string.lua @@ -292,6 +292,54 @@ local function string_hex(inp) return ffi.string(res, len) end +local hexadecimal_chars = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', + 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f'} + +local hexadecimal_values = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15} + +local hexadecimals_mapping = {} + +local function chars_to_hex(chars, values, mapping) + for i, char in ipairs(chars) do + mapping[string.byte(char)] = values[i] + end +end + +chars_to_hex(hexadecimal_chars, hexadecimal_values, hexadecimals_mapping) + +--- Match a hexadecimal representation of a string to its +-- string representation. +-- @function fromhex +-- @string inp the string of hexadecimals +-- @returns formatted string +local function string_fromhex(inp) + if type(inp) ~= 'string' then + error(err_string_arg:format(1, 'string.fromhex', 'string', + type(inp)), 2) + end + if inp:len() % 2 ~= 0 then + error(err_string_arg:format(1, 'string.fromhex', + 'even amount of chars', + 'odd amount'), 2) + end + local len = inp:len() / 2 + local casted_inp = ffi.cast('const char *', inp) + local res = ffi.new('char[?]', len) + for i = 0, len - 1 do + local first = hexadecimals_mapping[casted_inp[i * 2]] + local second = hexadecimals_mapping[casted_inp[i * 2 + 1]] + if first == nil or second == nil then + error(err_string_arg:format(1, 'string.fromhex', 'hex string', + 'non hex chars'), 2) + end + res[i] = first * 16 + second + end + return ffi.string(res, len) +end + local function string_strip(inp) if type(inp) ~= 'string' then error(err_string_arg:format(1, "string.strip", 'string', type(inp)), 2) @@ -323,6 +371,7 @@ string.center = string_center string.startswith = string_startswith string.endswith = string_endswith string.hex = string_hex +string.fromhex = string_fromhex string.strip = string_strip string.lstrip = string_lstrip string.rstrip = string_rstrip diff --git a/test/app-tap/string.test.lua b/test/app-tap/string.test.lua index 1d10dcfc9..32333bff1 100755 --- a/test/app-tap/string.test.lua +++ b/test/app-tap/string.test.lua @@ -3,7 +3,7 @@ local tap = require('tap') local test = tap.test("string extensions") -test:plan(6) +test:plan(7) test:test("split", function(test) test:plan(10) @@ -114,6 +114,25 @@ test:test("hex", function(test) test:is(string.hex(""), "", "hex empty string") end) +test:test("fromhex", function(test) + test:plan(11) + test:is(string.fromhex("48656c6c6f"), "Hello", "from hex to bin") + test:is(string.fromhex("4c696e7578"), "Linux", "from hex to bin") + test:is(string.fromhex("6C6F72656D"), "lorem", "from hex to bin") + test:is(string.fromhex("697073756D"), "ipsum", "from hex to bin") + test:is(string.fromhex("6c6f72656d"), "lorem", "from hex to bin") + test:is(string.fromhex("697073756d"), "ipsum", "from hex to bin") + test:is(string.fromhex("6A6B6C6D6E6F"), "jklmno", "from hex to bin") + test:is(string.fromhex("6a6b6c6d6e6f"), "jklmno", "from hex to bin") + local _, err = pcall(string.fromhex, "aaa") + test:ok(err and err:match("(even amount of chars expected," .. + " got odd amount)")) + local _, err = pcall(string.fromhex, "qq") + test:ok(err and err:match("(hex string expected, got non hex chars)")) + local _, err = pcall(string.fromhex, 795) + test:ok(err and err:match("(string expected, got number)")) +end) + test:test("strip", function(test) test:plan(6) local str = " hello hello " ---------------------------------------------------------------------- -- WBR, Nikita Tatunov.