[PATCH] osmo-gsm-tester[master]: ms: Add lua script support utilities

2018-02-26 Thread Holger Freyther
Hello Pau Espin Pedrol, Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/6915

to look at the new patch set (#4).

ms: Add lua script support utilities

Add a JSON encoder and a small module to sent registration and
other events per unix datagram socket.

json.lua fetched using:
$ wget -O src/osmo_ms_driver/lua/json.lua \
https://raw.githubusercontent.com/rxi/json.lua/master/json.lua

Change-Id: I43ae84a944c7f33e41d5de0880d4aaab3378809b
---
A src/osmo_ms_driver/lua/json.lua
A src/osmo_ms_driver/lua/ms_support.lua
2 files changed, 411 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/15/6915/4

diff --git a/src/osmo_ms_driver/lua/json.lua b/src/osmo_ms_driver/lua/json.lua
new file mode 100644
index 000..dda6193
--- /dev/null
+++ b/src/osmo_ms_driver/lua/json.lua
@@ -0,0 +1,380 @@
+--
+-- json.lua
+--
+-- Copyright (c) 2015 rxi
+--
+-- This library is free software; you can redistribute it and/or modify it
+-- under the terms of the MIT license. See LICENSE for details.
+--
+
+local json = { _version = "0.1.0" }
+
+---
+-- Encode
+---
+
+local encode
+
+local escape_char_map = {
+  [ "\\" ] = "",
+  [ "\"" ] = "\\\"",
+  [ "\b" ] = "\\b",
+  [ "\f" ] = "\\f",
+  [ "\n" ] = "\\n",
+  [ "\r" ] = "\\r",
+  [ "\t" ] = "\\t",
+}
+
+local escape_char_map_inv = { [ "\\/" ] = "/" }
+for k, v in pairs(escape_char_map) do
+  escape_char_map_inv[v] = k
+end
+
+
+local function escape_char(c)
+  return escape_char_map[c] or string.format("\\u%04x", c:byte())
+end
+
+
+local function encode_nil(val)
+  return "null"
+end 
+
+
+local function encode_table(val, stack)
+  local res = {}
+  stack = stack or {}
+
+  -- Circular reference?
+  if stack[val] then error("circular reference") end
+
+  stack[val] = true
+
+  if val[1] ~= nil or next(val) == nil then
+-- Treat as array -- check keys are valid and it is not sparse
+local n = 0
+for k in pairs(val) do
+  if type(k) ~= "number" then
+error("invalid table: mixed or invalid key types")
+  end
+  n = n + 1
+end
+if n ~= #val then
+  error("invalid table: sparse array")
+end
+-- Encode
+for i, v in ipairs(val) do
+  table.insert(res, encode(v, stack))
+end
+stack[val] = nil
+return "[" .. table.concat(res, ",") .. "]"
+
+  else
+-- Treat as an object
+for k, v in pairs(val) do
+  if type(k) ~= "string" then
+error("invalid table: mixed or invalid key types")
+  end
+  table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
+end
+stack[val] = nil
+return "{" .. table.concat(res, ",") .. "}"
+  end
+end
+
+
+local function encode_string(val)
+  return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
+end
+
+
+local function encode_number(val)
+  -- Check for NaN, -inf and inf
+  if val ~= val or val <= -math.huge or val >= math.huge then
+error("unexpected number value '" .. tostring(val) .. "'")
+  end
+  return string.format("%.14g", val)
+end
+
+
+local type_func_map = {
+  [ "nil" ] = encode_nil,
+  [ "table"   ] = encode_table,
+  [ "string"  ] = encode_string,
+  [ "number"  ] = encode_number,
+  [ "boolean" ] = tostring,
+}
+
+
+encode = function(val, stack)
+  local t = type(val)
+  local f = type_func_map[t]
+  if f then
+return f(val, stack)
+  end
+  error("unexpected type '" .. t .. "'")
+end
+
+
+function json.encode(val)
+  return ( encode(val) )
+end
+
+
+---
+-- Decode
+---
+
+local parse
+
+local function create_set(...) 
+  local res = {}
+  for i = 1, select("#", ...) do
+res[ select(i, ...) ] = true
+  end
+  return res
+end
+
+local space_chars   = create_set(" ", "\t", "\r", "\n")
+local delim_chars   = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
+local escape_chars  = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
+local literals  = create_set("true", "false", "null")
+
+local literal_map = {
+  [ "true"  ] = true,
+  [ "false" ] = false,
+  [ "null"  ] = nil,
+}
+
+
+local function next_char(str, idx, set, negate)
+  for i = idx, #str do
+if set[str:sub(i, i)] ~= negate then
+  return i
+end
+  end
+  return #str + 1
+end
+
+
+local function decode_error(str, idx, msg)
+  local line_count = 1
+  local col_count = 1
+  for i = 1, idx - 1 do
+col_count = col_count + 1
+if str:sub(i, i) == "\n" then
+  line_count = line_count + 1
+  col_count = 1
+end
+  end
+  error( string.format("%s at line %d col %d", msg, line_count, col_count) )
+end
+
+
+local function codepoint_to_utf8(n)
+  -- 

[PATCH] osmo-gsm-tester[master]: ms: Add lua script support utilities

2018-02-25 Thread Holger Freyther

ms: Add lua script support utilities

Add a JSON encoder and a small module to sent registration and
other events per unix datagram socket.

Change-Id: I43ae84a944c7f33e41d5de0880d4aaab3378809b
---
A src/osmo_ms_driver/lua/json.lua
A src/osmo_ms_driver/lua/ms_support.lua
2 files changed, 411 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/15/6915/3

diff --git a/src/osmo_ms_driver/lua/json.lua b/src/osmo_ms_driver/lua/json.lua
new file mode 100644
index 000..dda6193
--- /dev/null
+++ b/src/osmo_ms_driver/lua/json.lua
@@ -0,0 +1,380 @@
+--
+-- json.lua
+--
+-- Copyright (c) 2015 rxi
+--
+-- This library is free software; you can redistribute it and/or modify it
+-- under the terms of the MIT license. See LICENSE for details.
+--
+
+local json = { _version = "0.1.0" }
+
+---
+-- Encode
+---
+
+local encode
+
+local escape_char_map = {
+  [ "\\" ] = "",
+  [ "\"" ] = "\\\"",
+  [ "\b" ] = "\\b",
+  [ "\f" ] = "\\f",
+  [ "\n" ] = "\\n",
+  [ "\r" ] = "\\r",
+  [ "\t" ] = "\\t",
+}
+
+local escape_char_map_inv = { [ "\\/" ] = "/" }
+for k, v in pairs(escape_char_map) do
+  escape_char_map_inv[v] = k
+end
+
+
+local function escape_char(c)
+  return escape_char_map[c] or string.format("\\u%04x", c:byte())
+end
+
+
+local function encode_nil(val)
+  return "null"
+end 
+
+
+local function encode_table(val, stack)
+  local res = {}
+  stack = stack or {}
+
+  -- Circular reference?
+  if stack[val] then error("circular reference") end
+
+  stack[val] = true
+
+  if val[1] ~= nil or next(val) == nil then
+-- Treat as array -- check keys are valid and it is not sparse
+local n = 0
+for k in pairs(val) do
+  if type(k) ~= "number" then
+error("invalid table: mixed or invalid key types")
+  end
+  n = n + 1
+end
+if n ~= #val then
+  error("invalid table: sparse array")
+end
+-- Encode
+for i, v in ipairs(val) do
+  table.insert(res, encode(v, stack))
+end
+stack[val] = nil
+return "[" .. table.concat(res, ",") .. "]"
+
+  else
+-- Treat as an object
+for k, v in pairs(val) do
+  if type(k) ~= "string" then
+error("invalid table: mixed or invalid key types")
+  end
+  table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
+end
+stack[val] = nil
+return "{" .. table.concat(res, ",") .. "}"
+  end
+end
+
+
+local function encode_string(val)
+  return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
+end
+
+
+local function encode_number(val)
+  -- Check for NaN, -inf and inf
+  if val ~= val or val <= -math.huge or val >= math.huge then
+error("unexpected number value '" .. tostring(val) .. "'")
+  end
+  return string.format("%.14g", val)
+end
+
+
+local type_func_map = {
+  [ "nil" ] = encode_nil,
+  [ "table"   ] = encode_table,
+  [ "string"  ] = encode_string,
+  [ "number"  ] = encode_number,
+  [ "boolean" ] = tostring,
+}
+
+
+encode = function(val, stack)
+  local t = type(val)
+  local f = type_func_map[t]
+  if f then
+return f(val, stack)
+  end
+  error("unexpected type '" .. t .. "'")
+end
+
+
+function json.encode(val)
+  return ( encode(val) )
+end
+
+
+---
+-- Decode
+---
+
+local parse
+
+local function create_set(...) 
+  local res = {}
+  for i = 1, select("#", ...) do
+res[ select(i, ...) ] = true
+  end
+  return res
+end
+
+local space_chars   = create_set(" ", "\t", "\r", "\n")
+local delim_chars   = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
+local escape_chars  = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
+local literals  = create_set("true", "false", "null")
+
+local literal_map = {
+  [ "true"  ] = true,
+  [ "false" ] = false,
+  [ "null"  ] = nil,
+}
+
+
+local function next_char(str, idx, set, negate)
+  for i = idx, #str do
+if set[str:sub(i, i)] ~= negate then
+  return i
+end
+  end
+  return #str + 1
+end
+
+
+local function decode_error(str, idx, msg)
+  local line_count = 1
+  local col_count = 1
+  for i = 1, idx - 1 do
+col_count = col_count + 1
+if str:sub(i, i) == "\n" then
+  line_count = line_count + 1
+  col_count = 1
+end
+  end
+  error( string.format("%s at line %d col %d", msg, line_count, col_count) )
+end
+
+
+local function codepoint_to_utf8(n)
+  -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi=iws-appendixa
+  local f = math.floor
+  if n <= 0x7f then
+return string.char(n)
+  elseif n <= 0x7ff then
+return string.char(f(n / 64) + 192, n % 64 + 128)
+  elseif n <= 0x then
+return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
+  elseif n <= 0x10 then
+

[PATCH] osmo-gsm-tester[master]: ms: Add lua script support utilities

2018-02-25 Thread Holger Freyther

Review at  https://gerrit.osmocom.org/6915

ms: Add lua script support utilities

Add a JSON encoder and a small module to sent registration and
other events per unix datagram socket.

Change-Id: I43ae84a944c7f33e41d5de0880d4aaab3378809b
---
A src/osmo_ms_driver/lua/json.lua
A src/osmo_ms_driver/lua/ms_support.lua
2 files changed, 411 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/15/6915/1

diff --git a/src/osmo_ms_driver/lua/json.lua b/src/osmo_ms_driver/lua/json.lua
new file mode 100644
index 000..dda6193
--- /dev/null
+++ b/src/osmo_ms_driver/lua/json.lua
@@ -0,0 +1,380 @@
+--
+-- json.lua
+--
+-- Copyright (c) 2015 rxi
+--
+-- This library is free software; you can redistribute it and/or modify it
+-- under the terms of the MIT license. See LICENSE for details.
+--
+
+local json = { _version = "0.1.0" }
+
+---
+-- Encode
+---
+
+local encode
+
+local escape_char_map = {
+  [ "\\" ] = "",
+  [ "\"" ] = "\\\"",
+  [ "\b" ] = "\\b",
+  [ "\f" ] = "\\f",
+  [ "\n" ] = "\\n",
+  [ "\r" ] = "\\r",
+  [ "\t" ] = "\\t",
+}
+
+local escape_char_map_inv = { [ "\\/" ] = "/" }
+for k, v in pairs(escape_char_map) do
+  escape_char_map_inv[v] = k
+end
+
+
+local function escape_char(c)
+  return escape_char_map[c] or string.format("\\u%04x", c:byte())
+end
+
+
+local function encode_nil(val)
+  return "null"
+end 
+
+
+local function encode_table(val, stack)
+  local res = {}
+  stack = stack or {}
+
+  -- Circular reference?
+  if stack[val] then error("circular reference") end
+
+  stack[val] = true
+
+  if val[1] ~= nil or next(val) == nil then
+-- Treat as array -- check keys are valid and it is not sparse
+local n = 0
+for k in pairs(val) do
+  if type(k) ~= "number" then
+error("invalid table: mixed or invalid key types")
+  end
+  n = n + 1
+end
+if n ~= #val then
+  error("invalid table: sparse array")
+end
+-- Encode
+for i, v in ipairs(val) do
+  table.insert(res, encode(v, stack))
+end
+stack[val] = nil
+return "[" .. table.concat(res, ",") .. "]"
+
+  else
+-- Treat as an object
+for k, v in pairs(val) do
+  if type(k) ~= "string" then
+error("invalid table: mixed or invalid key types")
+  end
+  table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
+end
+stack[val] = nil
+return "{" .. table.concat(res, ",") .. "}"
+  end
+end
+
+
+local function encode_string(val)
+  return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
+end
+
+
+local function encode_number(val)
+  -- Check for NaN, -inf and inf
+  if val ~= val or val <= -math.huge or val >= math.huge then
+error("unexpected number value '" .. tostring(val) .. "'")
+  end
+  return string.format("%.14g", val)
+end
+
+
+local type_func_map = {
+  [ "nil" ] = encode_nil,
+  [ "table"   ] = encode_table,
+  [ "string"  ] = encode_string,
+  [ "number"  ] = encode_number,
+  [ "boolean" ] = tostring,
+}
+
+
+encode = function(val, stack)
+  local t = type(val)
+  local f = type_func_map[t]
+  if f then
+return f(val, stack)
+  end
+  error("unexpected type '" .. t .. "'")
+end
+
+
+function json.encode(val)
+  return ( encode(val) )
+end
+
+
+---
+-- Decode
+---
+
+local parse
+
+local function create_set(...) 
+  local res = {}
+  for i = 1, select("#", ...) do
+res[ select(i, ...) ] = true
+  end
+  return res
+end
+
+local space_chars   = create_set(" ", "\t", "\r", "\n")
+local delim_chars   = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
+local escape_chars  = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
+local literals  = create_set("true", "false", "null")
+
+local literal_map = {
+  [ "true"  ] = true,
+  [ "false" ] = false,
+  [ "null"  ] = nil,
+}
+
+
+local function next_char(str, idx, set, negate)
+  for i = idx, #str do
+if set[str:sub(i, i)] ~= negate then
+  return i
+end
+  end
+  return #str + 1
+end
+
+
+local function decode_error(str, idx, msg)
+  local line_count = 1
+  local col_count = 1
+  for i = 1, idx - 1 do
+col_count = col_count + 1
+if str:sub(i, i) == "\n" then
+  line_count = line_count + 1
+  col_count = 1
+end
+  end
+  error( string.format("%s at line %d col %d", msg, line_count, col_count) )
+end
+
+
+local function codepoint_to_utf8(n)
+  -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi=iws-appendixa
+  local f = math.floor
+  if n <= 0x7f then
+return string.char(n)
+  elseif n <= 0x7ff then
+return string.char(f(n / 64) + 192, n % 64 + 128)
+  elseif n <= 0x then
+return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 +