summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua')
-rw-r--r--Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua393
1 files changed, 238 insertions, 155 deletions
diff --git a/Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua b/Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua
index 415719a2f4d..b43bc511d72 100644
--- a/Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua
+++ b/Master/texmf-dist/scripts/barracuda/lib-barcode/brcd-barcode.lua
@@ -1,6 +1,6 @@
--- Barcode abstract class
--- Copyright (C) 2019 Roberto Giacomelli
+-- Barcode Abstract Class
+-- Copyright (C) 2020 Roberto Giacomelli
-- Please see LICENSE.TXT for any legal information about present software
local Barcode = {
@@ -18,11 +18,15 @@ Barcode._available_enc = {-- keys must be lowercase
i2of5 = "lib-barcode.brcd-i2of5", -- Interleaved 2 of 5
}
Barcode._builder_instances = {} -- encoder builder instances repository
+Barcode._encoder_instances = {} -- encoder instances repository
-- common parameters to all the barcode objects
+Barcode._super_par_order = {
+ "ax",
+ "ay",
+}
Barcode._super_par_def = {}
local pardef = Barcode._super_par_def
-
-- set an Anchor point (ax, ay) relatively to the barcode bounding box
-- without considering any text object
-- ax = 0, ay = 0 is the lower left corner of the symbol
@@ -32,7 +36,6 @@ pardef.ax = {
default = 0.0,
unit = "sp", -- scaled point
isReserved = false,
- order = 1,
fncheck = function (self, ax, _) --> boolean, err
if ax >= 0.0 and ax <= 1.0 then return true, nil end
return false, "[OutOfRange] 'ax' out of [0, 1] interval"
@@ -43,7 +46,6 @@ pardef.ay = {
default = 0.0,
unit = "sp", -- scaled point
isReserved = false,
- order = 2,
fncheck = function (self, ay, _) --> boolean, err
if ay >= 0.0 and ay <= 1.0 then return true, nil end
return false, "[OutOfRange] 'ay' out of [0, 1] interval"
@@ -54,120 +56,203 @@ pardef.ay = {
-- Barcode methods
--- stateless iterator troughtout the ordered parameters collection
-local function p_iter(state, i)
- i = i + 1
- local t = state[i]
- if t then
- return i, t
+-- extract id from an encoder 'tree name'
+local function parse_treename(treename) --> fam, var, name, err
+ if not type(treename) == "string" then
+ return nil, nil, nil, "[ArgErr] 'treename' arg must be a string"
+ end
+ if treename:find(" ") then
+ return nil, nil, nil,
+ "[ArgErr] spaces are not allowed in an encoder identifier"
+ end
+ local fam, var, name
+ -- family name extraction
+ local idash = treename:find("-")
+ local icolon = treename:find(":")
+ if idash then
+ fam = treename:sub(1, idash - 1)
+ else
+ if icolon then
+ fam = treename:sub(1, icolon - 1)
+ else
+ fam = treename
+ end
+ end
+ if fam == "" then
+ return nil, nil, nil, "[ArgErr] empty encoder id"
end
+ if idash then
+ if icolon then
+ var = treename:sub(idash + 1, icolon - 1)
+ else
+ var = treename:sub(idash + 1)
+ end
+ if var == "" then
+ return nil, nil, nil, "[ArgErr] empty 'variant' encoder id"
+ end
+ end
+ if icolon then
+ name = treename:sub(icolon + 1)
+ if name == "" then
+ return nil, nil, nil, "[ArgErr] empty 'name' after colon"
+ end
+ if name:find("-") then
+ return nil, nil, nil, "[ArgErr] the name mustn't contain a dash"
+ end
+ if name:find(":") then
+ return nil, nil, nil, "[ArgErr] the name mustn't contain a colon"
+ end
+ end
+ return fam, var, name, nil
end
-- main iterator on parameter definitions
-function Barcode:param_ord_iter()
+-- optional argument 'filter' eventually excludes some parameters
+-- "*all" -> encoder and Barcode parameters
+-- "*enc" -> only encoder parameters
+-- "*super" -> only Barcode superclass paramenters
+function Barcode:param_ord_iter(filter)
+ local is_iter_enc, is_iter_super = true, true
+ if filter then
+ if type(filter) ~= "string" then
+ error("[param_ord_iter] 'filter' is not a string")
+ elseif filter == "*enc" then
+ is_iter_super = false
+ elseif filter == "*super" then
+ is_iter_enc = false
+ elseif filter ~= "*all" then
+ error("[param_ord_iter] 'filter' enumeration '"..filter.."' not found")
+ end
+ end
local state = {}
- -- append family parameter
- local p2_family = self._par_def -- base family parameters
- local fam_len = 0
- if p2_family then
- for pname, pdef in pairs(p2_family) do
- state[pdef.order] = {
- pname = pname,
- pdef = pdef,
- isSuper = false,
- }
- fam_len = fam_len + 1
+ local ordkey = {}
+ if is_iter_enc then
+ local var = self._variant
+ local p2_family = self._par_def -- base family parameters
+ local p2_family_var
+ if var then
+ local pvar = "_par_def_"..var
+ p2_family_var = self[pvar] -- variant specific family parameters
+ end
+ local p2_idlist = self._par_order
+ if p2_idlist then -- family parameters
+ for i, pid in ipairs(p2_idlist) do
+ if ordkey[pid] then
+ error("[Ops] duplicated entry in parameter ordered list")
+ end
+ ordkey[pid] = true
+ local pdef -- parameter definition
+ if var and p2_family_var then
+ pdef = p2_family_var[pid]
+ end
+ pdef = pdef or p2_family[pid]
+ assert(pdef, "[Ops] parameter definition for option '"..pid.."' not found")
+ state[i] = {
+ pname = pid,
+ pdef = pdef,
+ isSuper = false,
+ }
+ end
+ end
+ -- append variant parameters
+ if var and self._par_def_variant then
+ local p2_variant = self._par_def_variant[var]
+ if p2_variant then
+ local p2_idlist_var = self._par_variant_order[var] -- parameters' list
+ if p2_idlist_var then
+ for _, pid in ipairs(p2_idlist_var) do
+ if ordkey[pid] then
+ error("[Ops] duplicated entry in variant parameter ordered list")
+ end
+ ordkey[pid] = true
+ local pdef = p2_variant[pid] -- parameter definition
+ assert(pdef, "[Ops] parameter definition for option '"..pid.."' not found")
+ state[#state + 1] = {
+ pname = pid,
+ pdef = pdef,
+ isSuper = false,
+ }
+ end
+ end
+ end
end
- assert(fam_len == #state)
- end
- -- append the variant parameters
- local var_len = 0
- local var = self._variant
- if var then -- specific variant parameters
- local p2_variant = assert(self._par_def_variant[var])
- for pname, pdef in pairs(p2_variant) do
- if state[pname] then
- error("[InternalErr] overriding paramenter '"..pname.."'")
+ end
+ if is_iter_super then
+ -- append the super class parameter to the iterator state
+ local p1_idlist_super = self._super_par_order
+ local p1_super = self._super_par_def
+ for _, pid in ipairs(p1_idlist_super) do
+ if ordkey[pid] then
+ error("[Ops] duplicated entry in superclass parameter ordered list")
end
- state[pdef.order + fam_len] = {
- pname = pname,
+ ordkey[pid] = true
+ local pdef = p1_super[pid] -- parameter definition
+ assert(pdef, "[Ops] parameter definition for option '"..pid.."' not found")
+ state[#state + 1] = {
+ pname = pid,
pdef = pdef,
- isSuper = false,
+ isSuper = true,
}
- var_len = var_len + 1
end
- assert(fam_len + var_len == #state)
- end
- -- append the super class parameter to the iterator state
- local p1 = self._super_par_def
- local super_len = 0
- for pname, pdef in pairs(p1) do
- if state[pname] then
- error("[InternalError] overriding paramenter name '"..pname.."'")
+ end
+ -- stateless iterator troughtout the ordered parameters collection
+ local p_iter = function (st, i)
+ i = i + 1
+ local t = st[i]
+ if t then
+ return i, t
end
- state[fam_len + var_len + pdef.order] = {
- pname = pname,
- pdef = pdef,
- isSuper = true,
- }
- super_len = super_len + 1
end
- assert(super_len + fam_len + var_len == #state)
return p_iter, state, 0
end
-- encoder costructor
-- Symbology can be a family with many variants. This is represented by the
--- first argument 'bc_type' formatted as <family>-<variant>.
--- in more details:
--- <family id><dash char><variant id> if there are variants
--- <encoder id> if not
--- i.e. when 'bc_type' is the string "ean-13", "ean" is the barcode family and
+-- first argument 'tree_name' formatted as <family>-<variant>:<id>.
+-- i.e. when 'tree_name' is the string "ean-13", "ean" is the barcode family and
-- "13" is its variant name.
--- For whose barcodes that do not have variants, 'bc_type' is simply the endoder id
--- such as "code128".
--- 'id_enc' is an optional identifier useful to retrive an encoder reference later
--- 'opt' is an optional table with the user-defined parameters setting up encoders
---
-function Barcode:new_encoder(bc_type, id_enc, opt) --> object, err
+-- For whose barcodes that do not have variants, 'treename' is simply the
+-- encoder id such as in the case of "code128".
+-- <id> is an optional identifier useful if there are more than one encoders of
+-- the same type
+-- 'opt' is an optional table with the user-defined parameters setting up
+-- encoders
+function Barcode:new_encoder(treename, opt) --> object, err
-- argument checking
- if type(bc_type) ~= "string" then
- return nil, "[ArgErr] 'bc_type' is not a string"
- end
- local pdash = string.find(bc_type, "-")
- local family, variant
- if pdash then
- family = string.sub(bc_type, 1, pdash - 1)
- variant = string.sub(bc_type, pdash + 1)
- else
- family = bc_type
+ local family, variant, enc_name, err = parse_treename(treename)
+ if err then
+ return err
end
local av_enc = self._available_enc
- if not av_enc[family] then -- is the barcode type a real module?
- return nil, "[Err] barcode type '"..family.."' not found"
- end
- if id_enc == nil then
- id_enc = (variant or "") .. "_noname"
- elseif type(id_enc) ~= "string" then
- return nil, "[ArgErr] provided 'id_enc' is not a string"
- end
- if type(opt) == "table" or opt == nil then
- opt = opt or {}
- else
- return nil, "[ArgErr] provided 'opt' is wrong"
+ local mod_path = av_enc[family]
+ -- check family identifier
+ if not mod_path then
+ return nil, "[ArgErr] barcode family '"..family.."' not found"
end
+ -- retrive/load the builder
+ local builder
local tenc = self._builder_instances
- local builder;
if tenc[family] then -- is the encoder builder already loaded?
builder = tenc[family]
- else -- loading the encoder builder
- local mod_path = av_enc[family]
+ else -- load the encoder builder
builder = require(mod_path)
- tenc[family] = assert(builder, "[InternalErr] module not found!")
- builder._enc_instances = {}
+ tenc[family] = builder
end
- if builder._enc_instances[id_enc] then
- return nil, "[Err] 'id_enc' already present"
+ -- check the variant identifier
+ local av_var = builder._id_variant
+ if av_var and variant and (not av_var[variant]) then
+ local fmt = "[ArgErr] family '%s' does not have '%s' variant"
+ return nil, string.format(fmt, family, variant)
+ end
+ -- check unique encoder identifier
+ local enc_archive = self._encoder_instances
+ if enc_archive[treename] then
+ return nil, "[Err] encoder name '"..treename.."' already exists"
+ end
+ if type(opt) == "table" or opt == nil then
+ opt = opt or {}
+ else
+ return nil, "[ArgErr] provided 'opt' is not a table"
end
local enc = {} -- the new encoder
enc.__index = enc
@@ -180,19 +265,19 @@ function Barcode:new_encoder(bc_type, id_enc, opt) --> object, err
return self[k]
end
})
- builder._enc_instances[id_enc] = enc
- -- param defition
+ enc_archive[treename] = enc
+ -- parameters definition
for _, tpar in enc:param_ord_iter() do
local pname = tpar.pname
local pdef = tpar.pdef
local isSuper = tpar.isSuper
local val = opt[pname] -- param = val
if val ~= nil then
- local ok, err = pdef:fncheck(val, enc)
+ local ok, perr = pdef:fncheck(val, enc)
if ok then
enc[pname] = val
- else -- error!
- return nil, err
+ else -- parameter error!
+ return nil, perr
end
else
-- load the default value of <pname>
@@ -206,49 +291,30 @@ function Barcode:new_encoder(bc_type, id_enc, opt) --> object, err
end
end
end
- if enc.config then -- this must be called after the parameter definition
- enc:config(variant)
+ if enc._config then -- this must be called after the parameter definition
+ enc:_config()
end
return enc, nil
end
--- retrive encoder object already created
--- 'name' is optional in case you didn't assign one to the encoder
-function Barcode:enc_by_name(bc_type, name) --> <encoder object>, <err>
- if type(bc_type) ~= "string" then
- return nil, "[ArgErr] 'bc_type' must be a string"
- end
- local pdash = string.find(bc_type, "-")
- local family, variant
- if pdash then
- family = string.sub(bc_type, 1, pdash - 1)
- variant = string.sub(bc_type, pdash + 1)
- else
- family = bc_type
+-- retrive an encoder object already created
+-- 'trename' is the special identifier of the encoder
+function Barcode:enc_by_name(treename) --> <encoder object>, <err>
+ -- argument checking
+ local _family, _variant, _enc_name, err = parse_treename(treename)
+ if err then
+ return nil, err
end
- local av_enc = self._available_enc
- if not av_enc[family] then -- is the barcode type a real module?
- return nil, "[Err] barcode type '"..family.."' not found"
- end
- local builder = self._builder_instances[family]
- if builder == nil then
- return nil, "[Err] enc builder '"..family.."' not loaded, use 'new_encoder()' method"
- end
- if name == nil then
- name = (variant or "") .. "_noname"
- elseif type(name) ~= "string" then
- return nil, "[ArgErr] 'name' must be a string"
- end
- local repo = builder._enc_instances
- local enc = repo[name]
- if enc == nil then
- return nil, "[Err] encoder '"..name.."' not found"
- else
+ local enc = self._encoder_instances[treename]
+ if enc then
return enc, nil
+ else
+ return nil, "[Err] encoder '"..treename.."' not found"
end
end
--- base constructors common to all the encoders
+-- base methods common to all the encoders
+
-- for numeric only simbology
function Barcode:_check_char(c) --> elem, err
if type(c) ~= "string" or #c ~= 1 then
@@ -260,19 +326,19 @@ function Barcode:_check_char(c) --> elem, err
end
return n, nil
end
+--
function Barcode:_check_digit(n) --> elem, err
if type(n) ~= "number" then
- return nil, "[InternalErr] not a number"
+ return nil, "[ArgErr] not a number"
end
if n < 0 or n > 9 then
- return nil, "[InternalErr] not a digit"
+ return nil, "[ArgErr] not a digit"
end
return n, nil
end
-- not empty string --> Barcode object
function Barcode:from_string(symb, opt) --> object, err
- assert(self._check_char, "[InternalErr] undefined _check_char() method")
if type(symb) ~= "string" then
return nil, "[ArgErr] 'symb' is not a string"
end
@@ -281,11 +347,12 @@ function Barcode:from_string(symb, opt) --> object, err
end
local chars = {}
local len = 0
+ local parse_state = {}
for c in string.gmatch(symb, ".") do
- local elem, err = self:_check_char(c)
+ local elem, err = self:_check_char(c, parse_state)
if err then
return nil, err
- else
+ elseif elem then
chars[#chars+1] = elem
len = len + 1
end
@@ -307,7 +374,7 @@ function Barcode:from_string(symb, opt) --> object, err
end
end
if o._finalize then
- local ok, e = o:_finalize()
+ local ok, e = o:_finalize(parse_state)
if not ok then return nil, e end
end
return o, nil
@@ -315,9 +382,12 @@ end
-- positive integer --> Barcode object
function Barcode:from_uint(n, opt) --> object, err
- assert(self._check_digit, "[InternalErr] undefined _check_digit() method")
- if type(n) ~= "number" then return nil, "[ArgErr] 'n' is not a number" end
- if n < 0 then return nil, "[ArgErr] 'n' must be a positive integer" end
+ if type(n) ~= "number" then
+ return nil, "[ArgErr] 'n' is not a number"
+ end
+ if n < 0 then
+ return nil, "[ArgErr] 'n' must be a positive integer"
+ end
if n - math.floor(n) ~= 0 then
return nil, "[ArgErr] 'n' is not an integer"
end
@@ -325,23 +395,28 @@ function Barcode:from_uint(n, opt) --> object, err
return nil, "[ArgErr] 'opt' is not a table"
end
local digits = {}
+ local parse_state = {}
local i = 0
if n == 0 then
- local elem, err = self:_check_digit(0)
+ local elem, err = self:_check_digit(0, parse_state)
if err then
return nil, err
end
- digits[1] = elem
- i = 1
+ if elem then
+ digits[1] = elem
+ i = 1
+ end
else
while n > 0 do
local d = n % 10
- i = i + 1
- local elem, err = self:_check_digit(d)
+ local elem, err = self:_check_digit(d, parse_state)
if err then
return nil, err
end
- digits[i] = elem
+ if elem then
+ i = i + 1
+ digits[i] = elem
+ end
n = (n - d) / 10
end
for k = 1, i/2 do -- reverse the array
@@ -368,7 +443,7 @@ function Barcode:from_uint(n, opt) --> object, err
end
end
if o._finalize then
- local ok, e = o:_finalize()
+ local ok, e = o:_finalize(parse_state)
if not ok then return nil, e end
end
return o, nil
@@ -458,20 +533,29 @@ function Barcode:info() --> table
param = {},
}
local tpar = info.param
- for _, pardef in self:param_ord_iter() do
- local id = pardef.pname
- local pdef = pardef.pdef
+ for _, pdef in self:param_ord_iter() do
+ local id = pdef.pname
+ local def = pdef.pdef
tpar[#tpar + 1] = {
name = id,
descr = nil, -- TODO:
value = self[id],
- isReserved = pdef.isReserved,
- unit = pdef.unit,
+ isReserved = def.isReserved,
+ unit = def.unit,
}
end
return info
end
+-- return the code being represented as a string
+-- or nil if the method is called from Barcode abstract class
+function Barcode:get_code() --> string|nil
+ local code = self._code_data
+ if code then
+ return table.concat(code)
+ end
+end
+
-- make accessible by name parameter values
-- id: parameter identifier
function Barcode:get_param(id) --> value, err
@@ -509,11 +593,10 @@ function Barcode:set_param(arg1, arg2) --> boolean, err
else
return false, "[ArgErr] param name must be a string"
end
- -- preparing to the checking process
+ -- preparing the check process
local cktab = {}
local ckparam = {}
- -- checking process
- for _, tpar in self:param_ord_iter() do
+ for _, tpar in self:param_ord_iter() do -- checking process
local pname = tpar.pname
local pdef = tpar.pdef
local val = targ[pname] -- par = val