Skip to content

Commit d72146a

Browse files
authored
perf: avoid generating utf8_len_func at runtime (#36)
1 parent 3a7b241 commit d72146a

File tree

1 file changed

+17
-20
lines changed

1 file changed

+17
-20
lines changed

lib/jsonschema.lua

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ local DEBUG = os and os.getenv and os.getenv('DEBUG') == '1'
1010
local tab_concat = table.concat
1111
local tab_insert = table.insert
1212
local string = string
13+
local str_byte = string.byte
1314

1415
-- default null token
1516
local default_null = nil
@@ -316,6 +317,20 @@ function validatorlib.tablekind(t)
316317
return 0 -- mixed array/object
317318
end
318319

320+
function validatorlib.utf8_len(s)
321+
local c, j=0, 1
322+
while j <= #s do
323+
local cb = str_byte(s, j)
324+
if cb >= 0 and cb <= 127 then j = j + 1
325+
elseif cb >= 192 and cb <= 223 then j = j + 2
326+
elseif cb >= 224 and cb <= 239 then j = j + 3
327+
elseif cb >= 240 and cb <= 247 then j = j + 4
328+
end
329+
c = c + 1
330+
end
331+
return c
332+
end
333+
319334
-- used for unique items in arrays (not fast at all)
320335
-- from: http://stackoverflow.com/questions/25922437
321336
-- If we consider only the JSON case, this function could be simplified:
@@ -464,22 +479,6 @@ local function to_lua_code(var)
464479
return code .. "}"
465480
end
466481

467-
local function utf8_len_func(ctx)
468-
return sformat([[function(s)
469-
local c, j=0, 1
470-
while j <= #s do
471-
local cb = %s(s, j)
472-
if cb >= 0 and cb <= 127 then j = j + 1
473-
elseif cb >= 192 and cb <= 223 then j = j + 2
474-
elseif cb >= 224 and cb <= 239 then j = j + 3
475-
elseif cb >= 240 and cb <= 247 then j = j + 4
476-
end
477-
c = c + 1
478-
end
479-
return c
480-
end]], ctx:libfunc("string.byte"))
481-
end
482-
483482
generate_validator = function(ctx, schema)
484483
-- get type informations as they will be necessary anyway
485484
local datatype = ctx:localvar(sformat('%s(%s)',
@@ -827,16 +826,14 @@ generate_validator = function(ctx, schema)
827826
if schema.minLength or schema.maxLength or schema.pattern then
828827
ctx:stmt(sformat('if %s == "string" then', datatype))
829828
if schema.minLength then
830-
ctx:stmt(sformat(' local utf8_len_func = %s', utf8_len_func(ctx)))
831-
ctx:stmt(sformat(' local c = utf8_len_func(%s)',ctx:param(1)))
829+
ctx:stmt(sformat(' local c = %s(%s)', ctx:libfunc('lib.utf8_len'), ctx:param(1)))
832830
ctx:stmt(sformat(' if c < %d then', schema.minLength))
833831
ctx:stmt(sformat(' return false, %s("string too short, expected at least %d, got ") ..c',
834832
ctx:libfunc('string.format'), schema.minLength))
835833
ctx:stmt( ' end')
836834
end
837835
if schema.maxLength then
838-
ctx:stmt(sformat(' local utf8_len_func = %s', utf8_len_func(ctx)))
839-
ctx:stmt(sformat(' local c = utf8_len_func(%s)',ctx:param(1)))
836+
ctx:stmt(sformat(' local c = %s(%s)', ctx:libfunc('lib.utf8_len'), ctx:param(1)))
840837
ctx:stmt(sformat(' if c > %d then', schema.maxLength))
841838
ctx:stmt(sformat(' return false, %s("string too long, expected at most %d, got ") .. c',
842839
ctx:libfunc('string.format'), schema.maxLength))

0 commit comments

Comments
 (0)