aboutsummaryrefslogtreecommitdiffstats
path: root/teal-src/util
diff options
context:
space:
mode:
Diffstat (limited to 'teal-src/util')
-rw-r--r--teal-src/util/compat.d.tl4
-rw-r--r--teal-src/util/crand.d.tl6
-rw-r--r--teal-src/util/dataforms.d.tl52
-rw-r--r--teal-src/util/datamapper.tl381
-rw-r--r--teal-src/util/datetime.d.tl11
-rw-r--r--teal-src/util/encodings.d.tl27
-rw-r--r--teal-src/util/error.d.tl78
-rw-r--r--teal-src/util/format.d.tl4
-rw-r--r--teal-src/util/hashes.d.tl23
-rw-r--r--teal-src/util/hex.d.tl6
-rw-r--r--teal-src/util/http.d.tl9
-rw-r--r--teal-src/util/human/units.d.tl5
-rw-r--r--teal-src/util/id.d.tl9
-rw-r--r--teal-src/util/interpolation.d.tl6
-rw-r--r--teal-src/util/jid.d.tl15
-rw-r--r--teal-src/util/json.d.tl18
-rw-r--r--teal-src/util/jsonpointer.tl46
-rw-r--r--teal-src/util/jsonschema.tl374
-rw-r--r--teal-src/util/net.d.tl13
-rw-r--r--teal-src/util/poll.d.tl31
-rw-r--r--teal-src/util/pposix.d.tl108
-rw-r--r--teal-src/util/random.d.tl4
-rw-r--r--teal-src/util/ringbuffer.d.tl20
-rw-r--r--teal-src/util/signal.d.tl41
-rw-r--r--teal-src/util/smqueue.tl99
-rw-r--r--teal-src/util/stanza.d.tl62
-rw-r--r--teal-src/util/strbitop.d.tl6
-rw-r--r--teal-src/util/table.d.tl6
-rw-r--r--teal-src/util/time.d.tl6
-rw-r--r--teal-src/util/uuid.d.tl8
-rw-r--r--teal-src/util/xtemplate.tl101
31 files changed, 0 insertions, 1579 deletions
diff --git a/teal-src/util/compat.d.tl b/teal-src/util/compat.d.tl
deleted file mode 100644
index da9c6083..00000000
--- a/teal-src/util/compat.d.tl
+++ /dev/null
@@ -1,4 +0,0 @@
-local record lib
- xpcall : function (function, function, ...:any):boolean, any
-end
-return lib
diff --git a/teal-src/util/crand.d.tl b/teal-src/util/crand.d.tl
deleted file mode 100644
index b40cb67e..00000000
--- a/teal-src/util/crand.d.tl
+++ /dev/null
@@ -1,6 +0,0 @@
-local record lib
- bytes : function (n : integer) : string
- enum sourceid "OpenSSL" "arc4random()" "Linux" end
- _source : sourceid
-end
-return lib
diff --git a/teal-src/util/dataforms.d.tl b/teal-src/util/dataforms.d.tl
deleted file mode 100644
index 9e4170fa..00000000
--- a/teal-src/util/dataforms.d.tl
+++ /dev/null
@@ -1,52 +0,0 @@
-local stanza_t = require "util.stanza".stanza_t
-
-local enum form_type
- "form"
- "submit"
- "cancel"
- "result"
-end
-
-local enum field_type
- "boolean"
- "fixed"
- "hidden"
- "jid-multi"
- "jid-single"
- "list-multi"
- "list-single"
- "text-multi"
- "text-private"
- "text-single"
-end
-
-local record form_field
-
- type : field_type
- var : string -- protocol name
- name : string -- internal name
-
- label : string
- desc : string
-
- datatype : string
- range_min : number
- range_max : number
-
- value : any -- depends on field_type
- options : table
-end
-
-local record dataform
- title : string
- instructions : string
- { form_field } -- XXX https://github.com/teal-language/tl/pull/415
-
- form : function ( dataform, table, form_type ) : stanza_t
-end
-
-local record lib
- new : function ( dataform ) : dataform
-end
-
-return lib
diff --git a/teal-src/util/datamapper.tl b/teal-src/util/datamapper.tl
deleted file mode 100644
index 73b1dfc0..00000000
--- a/teal-src/util/datamapper.tl
+++ /dev/null
@@ -1,381 +0,0 @@
--- Copyright (C) 2021 Kim Alvefur
---
--- This project is MIT/X11 licensed. Please see the
--- COPYING file in the source package for more information.
---
--- Based on
--- https://json-schema.org/draft/2020-12/json-schema-core.html
--- https://json-schema.org/draft/2020-12/json-schema-validation.html
--- http://spec.openapis.org/oas/v3.0.1#xmlObject
--- https://github.com/OAI/OpenAPI-Specification/issues/630 (text:true)
---
--- XML Object Extensions:
--- text to refer to the text content at the same time as attributes
--- x_name_is_value for enum fields where the <tag-name/> is the value
--- x_single_attribute for <tag attr="this"/>
---
--- TODO pointers
--- TODO cleanup / refactor
--- TODO s/number/integer/ once we have appropriate math.type() compat
---
-
-local st = require "util.stanza";
-local json = require"util.json"
-local pointer = require"util.jsonpointer";
-
-local json_type_name = json.json_type_name;
-local json_schema_object = require "util.jsonschema"
-local type schema_t = boolean | json_schema_object
-
-local function toboolean ( s : string ) : boolean
- if s == "true" or s == "1" then
- return true
- elseif s == "false" or s == "0" then
- return false
- elseif s then
- return true
- end
-end
-
-local function totype(t : json_type_name, s : string) : any
- if not s then return nil end
- if t == "string" then
- return s;
- elseif t == "boolean" then
- return toboolean(s)
- elseif t == "number" or t == "integer" then
- return tonumber(s)
- end
-end
-
-local enum value_goes
- "in_tag_name"
- "in_text"
- "in_text_tag"
- "in_attribute"
- "in_single_attribute"
- "in_children"
- "in_wrapper"
-end
-
-local function resolve_schema(schema : schema_t, root : json_schema_object) : schema_t
- if schema is json_schema_object then
- if schema["$ref"] and schema["$ref"]:sub(1, 1) == "#" then
- return pointer.resolve(root as table, schema["$ref"]:sub(2)) as schema_t;
- end
- end
- return schema;
-end
-
-local function guess_schema_type(schema : json_schema_object) : json_type_name
- local schema_types = schema.type
- if schema_types is json_type_name then
- return schema_types
- elseif schema_types ~= nil then
- error "schema has unsupported 'type' property"
- elseif schema.properties then
- return "object"
- elseif schema.items then
- return "array"
- end
- return "string" -- default assumption
-end
-
-local function unpack_propschema( propschema : schema_t, propname : string, current_ns : string )
- : json_type_name, value_goes, string, string, string, string, { any }
- local proptype : json_type_name = "string"
- local value_where : value_goes = propname and "in_text_tag" or "in_text"
- local name = propname
- local namespace : string
- local prefix : string
- local single_attribute : string
- local enums : { any }
-
- if propschema is json_schema_object then
- proptype = guess_schema_type(propschema);
- elseif propschema is string then -- Teal says this can never be a string, but it could before so best be sure
- error("schema as string is not supported: "..propschema.." {"..current_ns.."}"..propname)
- end
-
- if proptype == "object" or proptype == "array" then
- value_where = "in_children"
- end
-
- if propschema is json_schema_object then
- local xml = propschema.xml
- if xml then
- if xml.name then
- name = xml.name
- end
- if xml.namespace and xml.namespace ~= current_ns then
- namespace = xml.namespace
- end
- if xml.prefix then
- prefix = xml.prefix
- end
- if proptype == "array" and xml.wrapped then
- value_where = "in_wrapper"
- elseif xml.attribute then
- value_where = "in_attribute"
- elseif xml.text then
- value_where = "in_text"
- elseif xml.x_name_is_value then
- value_where = "in_tag_name"
- elseif xml.x_single_attribute then
- single_attribute = xml.x_single_attribute
- value_where = "in_single_attribute"
- end
- end
- if propschema["const"] then
- enums = { propschema["const"] }
- elseif propschema["enum"] then
- enums = propschema["enum"]
- end
- end
-
- if current_ns == "urn:xmpp:reactions:0" and name == "reactions" then
- assert(proptype=="array")
- end
-
- return proptype, value_where, name, namespace, prefix, single_attribute, enums
-end
-
-local parse_object : function (schema : schema_t, s : st.stanza_t, root : json_schema_object) : { string : any }
-local parse_array : function (schema : schema_t, s : st.stanza_t, root : json_schema_object) : { any }
-
-local function extract_value (s : st.stanza_t, value_where : value_goes, proptype : json.json_type_name, name : string, namespace : string, prefix : string, single_attribute : string, enums : { any }) : string
- if value_where == "in_tag_name" then
- local c : st.stanza_t
- if proptype == "boolean" then
- c = s:get_child(name, namespace);
- elseif enums and proptype == "string" then
- -- XXX O(n²) ?
- -- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n)
- -- BUT works first, optimize later
- for i = 1, #enums do
- c = s:get_child(enums[i] as string, namespace);
- if c then break end
- end
- else
- c = s:get_child(nil, namespace);
- end
- if c then
- return c.name;
- end
- elseif value_where == "in_attribute" then
- local attr = name
- if prefix then
- attr = prefix .. ':' .. name
- elseif namespace and namespace ~= s.attr.xmlns then
- attr = namespace .. "\1" .. name
- end
- return s.attr[attr]
-
- elseif value_where == "in_text" then
- return s:get_text()
-
- elseif value_where == "in_single_attribute" then
- local c = s:get_child(name, namespace)
- return c and c.attr[single_attribute]
- elseif value_where == "in_text_tag" then
- return s:get_child_text(name, namespace)
- end
-end
-
-function parse_object (schema : schema_t, s : st.stanza_t, root : json_schema_object) : { string : any }
- local out : { string : any } = {}
- schema = resolve_schema(schema, root)
- if schema is json_schema_object and schema.properties then
- for prop, propschema in pairs(schema.properties) do
- propschema = resolve_schema(propschema, root)
-
- local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns)
-
- if value_where == "in_children" and propschema is json_schema_object then
- if proptype == "object" then
- local c = s:get_child(name, namespace)
- if c then
- out[prop] = parse_object(propschema, c, root);
- end
- elseif proptype == "array" then
- local a = parse_array(propschema, s, root);
- if a and a[1] ~= nil then
- out[prop] = a;
- end
- else
- error "unreachable"
- end
- elseif value_where == "in_wrapper" and propschema is json_schema_object and proptype == "array" then
- local wrapper = s:get_child(name, namespace);
- if wrapper then
- out[prop] = parse_array(propschema, wrapper, root);
- end
- else
- local value : string = extract_value (s, value_where, proptype, name, namespace, prefix, single_attribute, enums)
-
- out[prop] = totype(proptype, value)
- end
- end
- end
-
- return out
-end
-
-function parse_array (schema : json_schema_object, s : st.stanza_t, root : json_schema_object) : { any }
- local itemschema : schema_t = resolve_schema(schema.items, root);
- local proptype, value_where, child_name, namespace, prefix, single_attribute, enums = unpack_propschema(itemschema, nil, s.attr.xmlns)
- local attr_name : string
- if value_where == "in_single_attribute" then -- FIXME this shouldn't be needed
- value_where = "in_attribute";
- attr_name = single_attribute;
- end
- local out : { any } = {}
-
- if proptype == "object" then
- if itemschema is json_schema_object then
- for c in s:childtags(child_name, namespace) do
- table.insert(out, parse_object(itemschema, c, root));
- end
- else
- error "array items must be schema object"
- end
- elseif proptype == "array" then
- if itemschema is json_schema_object then
- for c in s:childtags(child_name, namespace) do
- table.insert(out, parse_array(itemschema, c, root));
- end
- end
- else
- for c in s:childtags(child_name, namespace) do
- local value : string = extract_value (c, value_where, proptype, attr_name or child_name, namespace, prefix, single_attribute, enums)
-
- table.insert(out, totype(proptype, value));
- end
- end
- return out;
-end
-
-local function parse (schema : json_schema_object, s : st.stanza_t) : table
- local s_type = guess_schema_type(schema)
- if s_type == "object" then
- return parse_object(schema, s, schema)
- elseif s_type == "array" then
- return parse_array(schema, s, schema)
- else
- error "top-level scalars unsupported"
- end
-end
-
-local function toxmlstring(proptype : json_type_name, v : any) : string
- if proptype == "string" and v is string then
- return v
- elseif proptype == "number" and v is number then
- return string.format("%g", v)
- elseif proptype == "integer" and v is number then -- TODO is integer
- return string.format("%d", v)
- elseif proptype == "boolean" then
- return v and "1" or "0"
- end
-end
-
-local unparse : function (json_schema_object, table, string, string, st.stanza_t, json_schema_object) : st.stanza_t
-
-local function unparse_property(out : st.stanza_t, v : any, proptype : json_type_name, propschema : schema_t, value_where : value_goes, name : string, namespace : string, current_ns : string, prefix : string, single_attribute : string, root : json_schema_object)
-
- if value_where == "in_attribute" then
- local attr = name
- if prefix then
- attr = prefix .. ':' .. name
- elseif namespace and namespace ~= current_ns then
- attr = namespace .. "\1" .. name
- end
-
- out.attr[attr] = toxmlstring(proptype, v)
- elseif value_where == "in_text" then
- out:text(toxmlstring(proptype, v))
- elseif value_where == "in_single_attribute" then
- assert(single_attribute)
- local propattr : { string : string } = {}
-
- if namespace and namespace ~= current_ns then
- propattr.xmlns = namespace
- end
-
- propattr[single_attribute] = toxmlstring(proptype, v)
- out:tag(name, propattr):up();
-
- else
- local propattr : { string : string }
- if namespace ~= current_ns then
- propattr = { xmlns = namespace }
- end
- if value_where == "in_tag_name" then
- if proptype == "string" and v is string then
- out:tag(v, propattr):up();
- elseif proptype == "boolean" and v == true then
- out:tag(name, propattr):up();
- end
- elseif proptype == "object" and propschema is json_schema_object and v is table then
- local c = unparse(propschema, v, name, namespace, nil, root);
- if c then
- out:add_direct_child(c);
- end
- elseif proptype == "array" and propschema is json_schema_object and v is table then
- if value_where == "in_wrapper" then
- local c = unparse(propschema, v, name, namespace, nil, root);
- if c then
- out:add_direct_child(c);
- end
- else
- unparse(propschema, v, name, namespace, out, root);
- end
- else
- out:text_tag(name, toxmlstring(proptype, v), propattr)
- end
- end
-end
-
-function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string, ctx : st.stanza_t, root : json_schema_object ) : st.stanza_t
-
- if root == nil then root = schema end
-
- if schema.xml then
- if schema.xml.name then
- current_name = schema.xml.name
- end
- if schema.xml.namespace then
- current_ns = schema.xml.namespace
- end
- -- TODO prefix?
- end
-
- local out = ctx or st.stanza(current_name, { xmlns = current_ns })
-
- local s_type = guess_schema_type(schema)
- if s_type == "object" then
-
- for prop, propschema in pairs(schema.properties) do
- propschema = resolve_schema(propschema, root)
- local v = t[prop]
-
- if v ~= nil then
- local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(propschema, prop, current_ns)
- unparse_property(out, v, proptype, propschema, value_where, name, namespace, current_ns, prefix, single_attribute, root)
- end
- end
- return out;
-
- elseif s_type == "array" then
- local itemschema = resolve_schema(schema.items, root)
- local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(itemschema, current_name, current_ns)
- for _, item in ipairs(t as { string }) do
- unparse_property(out, item, proptype, itemschema, value_where, name, namespace, current_ns, prefix, single_attribute, root)
- end
- return out;
- end
-end
-
-return {
- parse = parse,
- unparse = unparse,
-}
diff --git a/teal-src/util/datetime.d.tl b/teal-src/util/datetime.d.tl
deleted file mode 100644
index 971e8f9c..00000000
--- a/teal-src/util/datetime.d.tl
+++ /dev/null
@@ -1,11 +0,0 @@
--- TODO s/number/integer/ once Teal gets support for that
-
-local record lib
- date : function (t : integer) : string
- datetime : function (t : integer) : string
- time : function (t : integer) : string
- legacy : function (t : integer) : string
- parse : function (t : string) : integer
-end
-
-return lib
diff --git a/teal-src/util/encodings.d.tl b/teal-src/util/encodings.d.tl
deleted file mode 100644
index 58aefa5e..00000000
--- a/teal-src/util/encodings.d.tl
+++ /dev/null
@@ -1,27 +0,0 @@
--- TODO many actually return Maybe(String)
-local record lib
- record base64
- encode : function (s : string) : string
- decode : function (s : string) : string
- end
- record stringprep
- nameprep : function (s : string, strict : boolean) : string
- nodeprep : function (s : string, strict : boolean) : string
- resourceprep : function (s : string, strict : boolean) : string
- saslprep : function (s : string, strict : boolean) : string
- end
- record idna
- to_ascii : function (s : string) : string
- to_unicode : function (s : string) : string
- end
- record utf8
- valid : function (s : string) : boolean
- length : function (s : string) : integer
- end
- record confusable
- skeleton : function (s : string) : string
- end
- version : string
-end
-return lib
-
diff --git a/teal-src/util/error.d.tl b/teal-src/util/error.d.tl
deleted file mode 100644
index 05f52405..00000000
--- a/teal-src/util/error.d.tl
+++ /dev/null
@@ -1,78 +0,0 @@
-local enum error_type
- "auth"
- "cancel"
- "continue"
- "modify"
- "wait"
-end
-
-local enum error_condition
- "bad-request"
- "conflict"
- "feature-not-implemented"
- "forbidden"
- "gone"
- "internal-server-error"
- "item-not-found"
- "jid-malformed"
- "not-acceptable"
- "not-allowed"
- "not-authorized"
- "policy-violation"
- "recipient-unavailable"
- "redirect"
- "registration-required"
- "remote-server-not-found"
- "remote-server-timeout"
- "resource-constraint"
- "service-unavailable"
- "subscription-required"
- "undefined-condition"
- "unexpected-request"
-end
-
-local record protoerror
- type : error_type
- condition : error_condition
- text : string
- code : integer
-end
-
-local record error
- type : error_type
- condition : error_condition
- text : string
- code : integer
- context : { any : any }
- source : string
-end
-
-local type compact_registry_item = { string, string, string, string }
-local type compact_registry = { compact_registry_item }
-local type registry = { string : protoerror }
-local type context = { string : any }
-
-local record error_registry_wrapper
- source : string
- registry : registry
- new : function (string, context) : error
- coerce : function (any, string) : any, error
- wrap : function (error) : error
- wrap : function (string, context) : error
- is_error : function (any) : boolean
-end
-
-local record lib
- record configure_opt
- auto_inject_traceback : boolean
- end
- new : function (protoerror, context, { string : protoerror }, string) : error
- init : function (string, string, registry | compact_registry) : error_registry_wrapper
- init : function (string, registry | compact_registry) : error_registry_wrapper
- is_error : function (any) : boolean
- coerce : function (any, string) : any, error
- from_stanza : function (table, context, string) : error
- configure : function
-end
-
-return lib
diff --git a/teal-src/util/format.d.tl b/teal-src/util/format.d.tl
deleted file mode 100644
index 1ff77c97..00000000
--- a/teal-src/util/format.d.tl
+++ /dev/null
@@ -1,4 +0,0 @@
-local record lib
- format : function (string, ... : any) : string
-end
-return lib
diff --git a/teal-src/util/hashes.d.tl b/teal-src/util/hashes.d.tl
deleted file mode 100644
index cbb06f8e..00000000
--- a/teal-src/util/hashes.d.tl
+++ /dev/null
@@ -1,23 +0,0 @@
-local type hash = function (msg : string, hex : boolean) : string
-local type hmac = function (key : string, msg : string, hex : boolean) : string
-local type kdf = function (pass : string, salt : string, i : integer) : string
-
-local record lib
- sha1 : hash
- sha256 : hash
- sha224 : hash
- sha384 : hash
- sha512 : hash
- md5 : hash
- hmac_sha1 : hmac
- hmac_sha256 : hmac
- hmac_sha512 : hmac
- hmac_md5 : hmac
- scram_Hi_sha1 : kdf
- pbkdf2_hmac_sha1 : kdf
- pbkdf2_hmac_sha256 : kdf
- equals : function (string, string) : boolean
- version : string
- _LIBCRYPTO_VERSION : string
-end
-return lib
diff --git a/teal-src/util/hex.d.tl b/teal-src/util/hex.d.tl
deleted file mode 100644
index 3b216a88..00000000
--- a/teal-src/util/hex.d.tl
+++ /dev/null
@@ -1,6 +0,0 @@
-local type s2s = function (s : string) : string
-local record lib
- to : s2s
- from : s2s
-end
-return lib
diff --git a/teal-src/util/http.d.tl b/teal-src/util/http.d.tl
deleted file mode 100644
index ecbe35c3..00000000
--- a/teal-src/util/http.d.tl
+++ /dev/null
@@ -1,9 +0,0 @@
-local record lib
- urlencode : function (s : string) : string
- urldecode : function (s : string) : string
- formencode : function (f : { string : string }) : string
- formdecode : function (s : string) : { string : string }
- contains_token : function (field : string, token : string) : boolean
- normalize_path : function (path : string) : string
-end
-return lib
diff --git a/teal-src/util/human/units.d.tl b/teal-src/util/human/units.d.tl
deleted file mode 100644
index f6568d90..00000000
--- a/teal-src/util/human/units.d.tl
+++ /dev/null
@@ -1,5 +0,0 @@
-local lib = record
- adjust : function (number, string) : number, string
- format : function (number, string, string) : string
-end
-return lib
diff --git a/teal-src/util/id.d.tl b/teal-src/util/id.d.tl
deleted file mode 100644
index 4b6c93b7..00000000
--- a/teal-src/util/id.d.tl
+++ /dev/null
@@ -1,9 +0,0 @@
-local record lib
- short : function () : string
- medium : function () : string
- long : function () : string
- custom : function (integer) : function () : string
-
-end
-return lib
-
diff --git a/teal-src/util/interpolation.d.tl b/teal-src/util/interpolation.d.tl
deleted file mode 100644
index fb653edf..00000000
--- a/teal-src/util/interpolation.d.tl
+++ /dev/null
@@ -1,6 +0,0 @@
-local type renderer = function (string, { string : any }) : string
-local type filter = function (string, any) : string
-local record lib
- new : function (string, string, funcs : { string : filter }) : renderer
-end
-return lib
diff --git a/teal-src/util/jid.d.tl b/teal-src/util/jid.d.tl
deleted file mode 100644
index 897318d9..00000000
--- a/teal-src/util/jid.d.tl
+++ /dev/null
@@ -1,15 +0,0 @@
-local record lib
- split : function (string) : string, string, string
- bare : function (string) : string
- prepped_split : function (string, boolean) : string, string, string
- join : function (string, string, string) : string
- prep : function (string, boolean) : string
- compare : function (string, string) : boolean
- node : function (string) : string
- host : function (string) : string
- resource : function (string) : string
- escape : function (string) : string
- unescape : function (string) : string
-end
-
-return lib
diff --git a/teal-src/util/json.d.tl b/teal-src/util/json.d.tl
deleted file mode 100644
index a1c25004..00000000
--- a/teal-src/util/json.d.tl
+++ /dev/null
@@ -1,18 +0,0 @@
-local record lib
- encode : function (any) : string
- decode : function (string) : any, string
-
- enum json_type_name
- "null"
- "boolean"
- "object"
- "array"
- "number"
- "string"
- "integer"
- end
-
- type null_type = (nil)
- null : null_type
-end
-return lib
diff --git a/teal-src/util/jsonpointer.tl b/teal-src/util/jsonpointer.tl
deleted file mode 100644
index c21e1fbf..00000000
--- a/teal-src/util/jsonpointer.tl
+++ /dev/null
@@ -1,46 +0,0 @@
-
-local enum ptr_error
- "invalid-table"
- "invalid-path"
-end
-
-local function unescape_token(escaped_token : string) : string
- local unescaped = escaped_token:gsub("~1", "/"):gsub("~0", "~")
- return unescaped
-end
-
-local function resolve_json_pointer(ref : table, path : string) : any, ptr_error
- local ptr_len = #path+1
- for part, pos in path:gmatch("/([^/]*)()") do
- local token = unescape_token(part)
- if not ref is table then
- return nil
- end
- local idx = next(ref)
- local new_ref : any
-
- if idx is string then
- new_ref = ref[token]
- elseif idx is integer then
- local i = tonumber(token)
- if token == "-" then i = #ref + 1 end
- new_ref = ref[i+1]
- else
- return nil, "invalid-table"
- end
-
- if pos as integer == ptr_len then
- return new_ref
- elseif new_ref is table then
- ref = new_ref
- elseif not ref is table then
- return nil, "invalid-path"
- end
-
- end
- return ref
-end
-
-return {
- resolve = resolve_json_pointer,
-}
diff --git a/teal-src/util/jsonschema.tl b/teal-src/util/jsonschema.tl
deleted file mode 100644
index 160c164c..00000000
--- a/teal-src/util/jsonschema.tl
+++ /dev/null
@@ -1,374 +0,0 @@
--- Copyright (C) 2021 Kim Alvefur
---
--- This project is MIT/X11 licensed. Please see the
--- COPYING file in the source package for more information.
---
--- Based on
--- https://json-schema.org/draft/2020-12/json-schema-core.html
--- https://json-schema.org/draft/2020-12/json-schema-validation.html
---
-
-local json = require"util.json"
-local null = json.null;
-
-local pointer = require "util.jsonpointer"
-
-local type json_type_name = json.json_type_name
-
--- json_type_name here is non-standard
-local type schema_t = boolean | json_schema_object
-
-local record json_schema_object
- type json_type_name = json.json_type_name
- type schema_object = json_schema_object
-
- type : json_type_name | { json_type_name }
- enum : { any }
- const : any
-
- allOf : { schema_t }
- anyOf : { schema_t }
- oneOf : { schema_t }
-
- ["not"] : schema_t
- ["if"] : schema_t
- ["then"] : schema_t
- ["else"] : schema_t
-
- ["$ref"] : string
-
- -- numbers
- multipleOf : number
- maximum : number
- exclusiveMaximum : number
- minimum : number
- exclusiveMinimum : number
-
- -- strings
- maxLength : integer
- minLength : integer
- pattern : string -- NYI
- format : string
-
- -- arrays
- prefixItems : { schema_t }
- items : schema_t
- contains : schema_t
- maxItems : integer
- minItems : integer
- uniqueItems : boolean
- maxContains : integer -- NYI
- minContains : integer -- NYI
-
- -- objects
- properties : { string : schema_t }
- maxProperties : integer -- NYI
- minProperties : integer -- NYI
- required : { string }
- dependentRequired : { string : { string } }
- additionalProperties: schema_t
- patternProperties: schema_t -- NYI
- propertyNames : schema_t
-
- -- xml
- record xml_t
- name : string
- namespace : string
- prefix : string
- attribute : boolean
- wrapped : boolean
-
- -- nonstantard, maybe in the future
- text : boolean
- x_name_is_value : boolean
- x_single_attribute : string
- end
-
- xml : xml_t
-
- -- descriptive
- title : string
- description : string
- deprecated : boolean
- readOnly : boolean
- writeOnly : boolean
-
- -- methods
- validate : function ( schema_t, any, json_schema_object ) : boolean
-end
-
--- TODO validator function per schema property
-
-local function simple_validate(schema : json_type_name | { json_type_name }, data : any) : boolean
- if schema == nil then
- return true
- elseif schema == "object" and data is table then
- return type(data) == "table" and (next(data)==nil or type((next(data, nil))) == "string")
- elseif schema == "array" and data is table then
- return type(data) == "table" and (next(data)==nil or type((next(data, nil))) == "number")
- elseif schema == "integer" then
- return math.type(data) == schema
- elseif schema == "null" then
- return data == null
- elseif schema is { json_type_name } then
- for _, one in ipairs(schema as { json_type_name }) do
- if simple_validate(one, data) then
- return true
- end
- end
- return false
- else
- return type(data) == schema
- end
-end
-
-local complex_validate : function ( json_schema_object, any, json_schema_object ) : boolean
-
-local function validate (schema : schema_t, data : any, root : json_schema_object) : boolean
- if schema is boolean then
- return schema
- else
- return complex_validate(schema, data, root)
- end
-end
-
-function complex_validate (schema : json_schema_object, data : any, root : json_schema_object) : boolean
-
- if root == nil then
- root = schema
- end
-
- if schema["$ref"] and schema["$ref"]:sub(1,1) == "#" then
- local referenced = pointer.resolve(root as table, schema["$ref"]:sub(2)) as schema_t
- if referenced ~= nil and referenced ~= root and referenced ~= schema then
- if not validate(referenced, data, root) then
- return false;
- end
- end
- end
-
- if not simple_validate(schema.type, data) then
- return false;
- end
-
- if schema.type == "object" then
- if data is table then
- -- just check that there the keys are all strings
- for k in pairs(data) do
- if not k is string then
- return false
- end
- end
- end
- end
-
- if schema.type == "array" then
- if data is table then
- -- just check that there the keys are all numbers
- for i in pairs(data) do
- if not i is integer then
- return false
- end
- end
- end
- end
-
- if schema["enum"] ~= nil then
- local match = false
- for _, v in ipairs(schema["enum"]) do
- if v == data then
- -- FIXME supposed to do deep-compare
- match = true
- break
- end
- end
- if not match then
- return false
- end
- end
-
- -- XXX this is measured in byte, while JSON measures in ... bork
- -- TODO use utf8.len?
- if data is string then
- if schema.maxLength and #data > schema.maxLength then
- return false
- end
- if schema.minLength and #data < schema.minLength then
- return false
- end
- end
-
- if data is number then
- if schema.multipleOf and (data == 0 or data % schema.multipleOf ~= 0) then
- return false
- end
-
- if schema.maximum and not ( data <= schema.maximum ) then
- return false
- end
-
- if schema.exclusiveMaximum and not ( data < schema.exclusiveMaximum ) then
- return false
- end
-
- if schema.minimum and not ( data >= schema.minimum ) then
- return false
- end
-
- if schema.exclusiveMinimum and not ( data > schema.exclusiveMinimum ) then
- return false
- end
- end
-
- if schema.allOf then
- for _, sub in ipairs(schema.allOf) do
- if not validate(sub, data, root) then
- return false
- end
- end
- end
-
- if schema.oneOf then
- local valid = 0
- for _, sub in ipairs(schema.oneOf) do
- if validate(sub, data, root) then
- valid = valid + 1
- end
- end
- if valid ~= 1 then
- return false
- end
- end
-
- if schema.anyOf then
- local match = false
- for _, sub in ipairs(schema.anyOf) do
- if validate(sub, data, root) then
- match = true
- break
- end
- end
- if not match then
- return false
- end
- end
-
- if schema["not"] then
- if validate(schema["not"], data, root) then
- return false
- end
- end
-
- if schema["if"] ~= nil then
- if validate(schema["if"], data, root) then
- if schema["then"] then
- return validate(schema["then"], data, root)
- end
- else
- if schema["else"] then
- return validate(schema["else"], data, root)
- end
- end
- end
-
- if schema.const ~= nil and schema.const ~= data then
- return false
- end
-
- if data is table then
-
- if schema.maxItems and #data > schema.maxItems then
- return false
- end
-
- if schema.minItems and #data < schema.minItems then
- return false
- end
-
- if schema.required then
- for _, k in ipairs(schema.required) do
- if data[k] == nil then
- return false
- end
- end
- end
-
- if schema.propertyNames ~= nil then
- for k in pairs(data) do
- if not validate(schema.propertyNames, k, root) then
- return false
- end
- end
- end
-
- if schema.properties then
- for k, sub in pairs(schema.properties) do
- if data[k] ~= nil and not validate(sub, data[k], root) then
- return false
- end
- end
- end
-
- if schema.additionalProperties ~= nil then
- for k, v in pairs(data) do
- if schema.properties == nil or schema.properties[k as string] == nil then
- if not validate(schema.additionalProperties, v, root) then
- return false
- end
- end
- end
- end
-
- if schema.uniqueItems then
- -- only works for scalars, would need to deep-compare for objects/arrays/tables
- local values : { any : boolean } = {}
- for _, v in pairs(data) do
- if values[v] then
- return false
- end
- values[v] = true
- end
- end
-
- local p = 0
- if schema.prefixItems ~= nil then
- for i, s in ipairs(schema.prefixItems) do
- if data[i] == nil then
- break
- elseif validate(s, data[i], root) then
- p = i
- else
- return false
- end
- end
- end
-
- if schema.items ~= nil then
- for i = p+1, #data do
- if not validate(schema.items, data[i], root) then
- return false
- end
- end
- end
-
- if schema.contains ~= nil then
- local found = false
- for i = 1, #data do
- if validate(schema.contains, data[i], root) then
- found = true
- break
- end
- end
- if not found then
- return false
- end
- end
- end
-
- return true;
-end
-
-
-json_schema_object.validate = validate;
-
-return json_schema_object;
diff --git a/teal-src/util/net.d.tl b/teal-src/util/net.d.tl
deleted file mode 100644
index 1040fcef..00000000
--- a/teal-src/util/net.d.tl
+++ /dev/null
@@ -1,13 +0,0 @@
-
-local enum type_strings
- "both"
- "ipv4"
- "ipv6"
-end
-
-local record lib
- local_addresses : function (type_strings, boolean) : { string }
- pton : function (string):string
- ntop : function (string):string
-end
-return lib
diff --git a/teal-src/util/poll.d.tl b/teal-src/util/poll.d.tl
deleted file mode 100644
index 8df56d57..00000000
--- a/teal-src/util/poll.d.tl
+++ /dev/null
@@ -1,31 +0,0 @@
-local record state
- enum waiterr
- "timeout"
- "signal"
- end
- add : function (state, integer, boolean, boolean) : boolean
- add : function (state, integer, boolean, boolean) : nil, string, integer
- set : function (state, integer, boolean, boolean) : boolean
- set : function (state, integer, boolean, boolean) : nil, string, integer
- del : function (state, integer) : boolean
- del : function (state, integer) : nil, string, integer
- wait : function (state, integer) : integer, boolean, boolean
- wait : function (state, integer) : nil, string, integer
- wait : function (state, integer) : nil, waiterr
- getfd : function (state) : integer
-end
-
-local record lib
- new : function () : state
- EEXIST : integer
- EMFILE : integer
- ENOENT : integer
- enum api_backend
- "epoll"
- "poll"
- "select"
- end
- api : api_backend
-end
-
-return lib
diff --git a/teal-src/util/pposix.d.tl b/teal-src/util/pposix.d.tl
deleted file mode 100644
index 68f49730..00000000
--- a/teal-src/util/pposix.d.tl
+++ /dev/null
@@ -1,108 +0,0 @@
-local record pposix
- enum syslog_facility
- "auth"
- "authpriv"
- "cron"
- "daemon"
- "ftp"
- "kern"
- "local0"
- "local1"
- "local2"
- "local3"
- "local4"
- "local5"
- "local6"
- "local7"
- "lpr"
- "mail"
- "syslog"
- "user"
- "uucp"
- end
-
- enum syslog_level
- "debug"
- "info"
- "notice"
- "warn"
- "error"
- end
-
- enum ulimit_resource
- "CORE"
- "CPU"
- "DATA"
- "FSIZE"
- "NOFILE"
- "STACK"
- "MEMLOCK"
- "NPROC"
- "RSS"
- "NICE"
- end
-
- enum ulimit_unlimited
- "unlimited"
- end
-
- type ulimit_limit = integer | ulimit_unlimited
-
- record utsname
- sysname : string
- nodename : string
- release : string
- version : string
- machine : string
- domainname : string
- end
-
- record memoryinfo
- allocated : integer
- allocated_mmap : integer
- used : integer
- unused : integer
- returnable : integer
- end
-
- abort : function ()
-
- daemonize : function () : boolean, string
-
- syslog_open : function (ident : string, facility : syslog_facility)
- syslog_close : function ()
- syslog_log : function (level : syslog_level, src : string, msg : string)
- syslog_setminlevel : function (level : syslog_level)
-
- getpid : function () : integer
- getuid : function () : integer
- getgid : function () : integer
-
- setuid : function (uid : integer | string) : boolean, string -- string|integer
- setgid : function (uid : integer | string) : boolean, string
- initgroups : function (user : string, gid : integer) : boolean, string
-
- umask : function (umask : string) : string
-
- mkdir : function (dir : string) : boolean, string
-
- setrlimit : function (resource : ulimit_resource, soft : ulimit_limit, hard : ulimit_limit) : boolean, string
- getrlimit : function (resource : ulimit_resource) : boolean, ulimit_limit, ulimit_limit
- getrlimit : function (resource : ulimit_resource) : boolean, string
-
- uname : function () : utsname
-
- setenv : function (key : string, value : string) : boolean
-
- meminfo : function () : memoryinfo
-
- atomic_append : function (f : FILE, s : string) : boolean, string, integer
-
- isatty : function(FILE) : boolean
-
- ENOENT : integer
- _NAME : string
- _VESRION : string
-end
-
-return pposix
diff --git a/teal-src/util/random.d.tl b/teal-src/util/random.d.tl
deleted file mode 100644
index 83ff2fcc..00000000
--- a/teal-src/util/random.d.tl
+++ /dev/null
@@ -1,4 +0,0 @@
-local record lib
- bytes : function (n:integer):string
-end
-return lib
diff --git a/teal-src/util/ringbuffer.d.tl b/teal-src/util/ringbuffer.d.tl
deleted file mode 100644
index e4726d68..00000000
--- a/teal-src/util/ringbuffer.d.tl
+++ /dev/null
@@ -1,20 +0,0 @@
-local record lib
- record ringbuffer
- find : function (ringbuffer, string) : integer
- discard : function (ringbuffer, integer) : boolean
- read : function (ringbuffer, integer, boolean) : string
- readuntil : function (ringbuffer, string) : string
- write : function (ringbuffer, string) : integer
- size : function (ringbuffer) : integer
- length : function (ringbuffer) : integer
- sub : function (ringbuffer, integer, integer) : string
- byte : function (ringbuffer, integer, integer) : integer...
- free : function (ringbuffer) : integer
- end
-
- new : function (integer) : ringbuffer
-end
-
-return lib
-
-
diff --git a/teal-src/util/signal.d.tl b/teal-src/util/signal.d.tl
deleted file mode 100644
index 8610aa7f..00000000
--- a/teal-src/util/signal.d.tl
+++ /dev/null
@@ -1,41 +0,0 @@
-local record lib
- enum signal
- "SIGABRT"
- "SIGALRM"
- "SIGBUS"
- "SIGCHLD"
- "SIGCLD"
- "SIGCONT"
- "SIGFPE"
- "SIGHUP"
- "SIGILL"
- "SIGINT"
- "SIGIO"
- "SIGIOT"
- "SIGKILL"
- "SIGPIPE"
- "SIGPOLL"
- "SIGPROF"
- "SIGQUIT"
- "SIGSEGV"
- "SIGSTKFLT"
- "SIGSTOP"
- "SIGSYS"
- "SIGTERM"
- "SIGTRAP"
- "SIGTTIN"
- "SIGTTOU"
- "SIGURG"
- "SIGUSR1"
- "SIGUSR2"
- "SIGVTALRM"
- "SIGWINCH"
- "SIGXCPU"
- "SIGXFSZ"
- end
- signal : function (integer | signal, function, boolean) : boolean
- raise : function (integer | signal)
- kill : function (integer, integer | signal)
- -- enum : integer
-end
-return lib
diff --git a/teal-src/util/smqueue.tl b/teal-src/util/smqueue.tl
deleted file mode 100644
index e149dde7..00000000
--- a/teal-src/util/smqueue.tl
+++ /dev/null
@@ -1,99 +0,0 @@
-local queue = require "util.queue";
-
-local record lib
- -- T would typically be util.stanza
- record smqueue<T>
- _queue : queue.queue<T>
- _head : integer
- _tail : integer
-
- enum ack_errors
- "tail"
- "head"
- "pop"
- end
- push : function (smqueue, T)
- ack : function (smqueue, integer) : { T }, ack_errors
- resumable : function (smqueue<T>) : boolean
- resume : function (smqueue<T>) : queue.queue.iterator, any, integer
- type consume_iter = function (smqueue<T>) : T
- consume : function (smqueue<T>) : consume_iter
-
- table : function (smqueue<T>) : { T }
- end
- new : function <T>(integer) : smqueue<T>
-end
-
-local type smqueue = lib.smqueue;
-
-function smqueue:push(v)
- self._head = self._head + 1;
- -- Wraps instead of errors
- assert(self._queue:push(v));
-end
-
-function smqueue:ack(h : integer) : { any }, smqueue.ack_errors
- if h < self._tail then
- return nil, "tail";
- elseif h > self._head then
- return nil, "head";
- end
- -- TODO optimize? cache table fields
- local acked = {};
- self._tail = h;
- local expect = self._head - self._tail;
- while expect < self._queue:count() do
- local v = self._queue:pop();
- if not v then return nil, "pop"; end
- table.insert(acked, v);
- end
- return acked;
-end
-
-function smqueue:count_unacked() : integer
- return self._head - self._tail;
-end
-
-function smqueue:count_acked() : integer
- return self._tail;
-end
-
-function smqueue:resumable() : boolean
- return self._queue:count() >= (self._head - self._tail);
-end
-
-function smqueue:resume() : queue.queue.iterator, any, integer
- return self._queue:items();
-end
-
-function smqueue:consume() : queue.queue.consume_iter
- return self._queue:consume()
-end
-
--- Compatibility layer, plain ol' table
-function smqueue:table() : { any }
- local t : { any } = {};
- for i, v in self:resume() do
- t[i] = v;
- end
- return t;
-end
-
-local function freeze(q : smqueue<any>) : { string:integer }
- return { head = q._head, tail = q._tail }
-end
-
-local queue_mt = {
- --
- __name = "smqueue";
- __index = smqueue;
- __len = smqueue.count_unacked;
- __freeze = freeze;
-}
-
-function lib.new<T>(size : integer) : queue.queue<T>
- assert(size>0);
- return setmetatable({ _head = 0; _tail = 0; _queue = queue.new(size, true) }, queue_mt);
-end
-
-return lib;
diff --git a/teal-src/util/stanza.d.tl b/teal-src/util/stanza.d.tl
deleted file mode 100644
index a358248a..00000000
--- a/teal-src/util/stanza.d.tl
+++ /dev/null
@@ -1,62 +0,0 @@
-local record lib
-
- type children_iter = function ( stanza_t ) : stanza_t
- type childtags_iter = function () : stanza_t
- type maptags_cb = function ( stanza_t ) : stanza_t
-
- record stanza_t
- name : string
- attr : { string : string }
- { stanza_t | string }
- tags : { stanza_t }
-
- query : function ( stanza_t, string ) : stanza_t
- body : function ( stanza_t, string, { string : string } ) : stanza_t
- text_tag : function ( stanza_t, string, string, { string : string } ) : stanza_t
- tag : function ( stanza_t, string, { string : string } ) : stanza_t
- text : function ( stanza_t, string ) : stanza_t
- up : function ( stanza_t ) : stanza_t
- reset : function ( stanza_t ) : stanza_t
- add_direct_child : function ( stanza_t, stanza_t )
- add_child : function ( stanza_t, stanza_t )
- remove_children : function ( stanza_t, string, string ) : stanza_t
-
- get_child : function ( stanza_t, string, string ) : stanza_t
- get_text : function ( stanza_t ) : string
- get_child_text : function ( stanza_t, string, string ) : string
- child_with_name : function ( stanza_t, string, string ) : stanza_t
- child_with_ns : function ( stanza_t, string, string ) : stanza_t
- children : function ( stanza_t ) : children_iter, stanza_t, integer
- childtags : function ( stanza_t, string, string ) : childtags_iter
- maptags : function ( stanza_t, maptags_cb ) : stanza_t
- find : function ( stanza_t, string ) : stanza_t | string
-
- top_tag : function ( stanza_t ) : string
- pretty_print : function ( stanza_t ) : string
- pretty_top_tag : function ( stanza_t ) : string
-
- get_error : function ( stanza_t ) : string, string, string, stanza_t
- indent : function ( stanza_t, integer, string ) : stanza_t
- end
-
- record serialized_stanza_t
- name : string
- attr : { string : string }
- { serialized_stanza_t | string }
- end
-
- stanza : function ( string, { string : string } ) : stanza_t
- is_stanza : function ( any ) : boolean
- preserialize : function ( stanza_t ) : serialized_stanza_t
- deserialize : function ( serialized_stanza_t ) : stanza_t
- clone : function ( stanza_t, boolean ) : stanza_t
- message : function ( { string : string }, string ) : stanza_t
- iq : function ( { string : string } ) : stanza_t
- reply : function ( stanza_t ) : stanza_t
- error_reply : function ( stanza_t, string, string, string, string )
- presence : function ( { string : string } ) : stanza_t
- xml_escape : function ( string ) : string
- pretty_print : function ( string ) : string
-end
-
-return lib
diff --git a/teal-src/util/strbitop.d.tl b/teal-src/util/strbitop.d.tl
deleted file mode 100644
index 010efdb8..00000000
--- a/teal-src/util/strbitop.d.tl
+++ /dev/null
@@ -1,6 +0,0 @@
-local record mod
- sand : function (string, string) : string
- sor : function (string, string) : string
- sxor : function (string, string) : string
-end
-return mod
diff --git a/teal-src/util/table.d.tl b/teal-src/util/table.d.tl
deleted file mode 100644
index 0ff5ed95..00000000
--- a/teal-src/util/table.d.tl
+++ /dev/null
@@ -1,6 +0,0 @@
-local record lib
- create : function (narr:integer, nrec:integer):table
- pack : function (...:any):{any}
-end
-return lib
-
diff --git a/teal-src/util/time.d.tl b/teal-src/util/time.d.tl
deleted file mode 100644
index e159706b..00000000
--- a/teal-src/util/time.d.tl
+++ /dev/null
@@ -1,6 +0,0 @@
-
-local record lib
- now : function () : number
- monotonic : function () : number
-end
-return lib
diff --git a/teal-src/util/uuid.d.tl b/teal-src/util/uuid.d.tl
deleted file mode 100644
index 45fd4312..00000000
--- a/teal-src/util/uuid.d.tl
+++ /dev/null
@@ -1,8 +0,0 @@
-local record lib
- get_nibbles : (number) : string
- generate : function () : string
-
- seed : function (string)
-end
-return lib
-
diff --git a/teal-src/util/xtemplate.tl b/teal-src/util/xtemplate.tl
deleted file mode 100644
index b3bdc400..00000000
--- a/teal-src/util/xtemplate.tl
+++ /dev/null
@@ -1,101 +0,0 @@
--- render(template, stanza) --> string
--- {path} --> stanza:find(path)
--- {{ns}name/child|each({ns}name){sub-template}}
-
---[[
-template ::= "{" path ("|" name ("(" args ")")? (template)? )* "}"
-path ::= defined by util.stanza
-name ::= %w+
-args ::= anything with balanced ( ) pairs
-]]
-
-local s_gsub = string.gsub;
-local s_match = string.match;
-local s_sub = string.sub;
-local t_concat = table.concat;
-
-local st = require "util.stanza";
-
-local type escape_t = function (string) : string
-local type filter_t = function (string, string | st.stanza_t, string) : string | st.stanza_t, boolean
-local type filter_coll = { string : filter_t }
-
-local function render(template : string, root : st.stanza_t, escape : escape_t, filters : filter_coll) : string
- escape = escape or st.xml_escape;
-
- return (s_gsub(template, "%b{}", function(block : string) : string
- local inner = s_sub(block, 2, -2);
- local path, pipe, pos = s_match(inner, "^([^|]+)(|?)()");
- if not path is string then return end
- local value : string | st.stanza_t
- if path == "." then
- value = root;
- elseif path == "#" then
- value = root:get_text();
- else
- value = root:find(path);
- end
- local is_escaped = false;
-
- while pipe == "|" do
- local func, args, tmpl, p = s_match(inner, "^(%w+)(%b())(%b{})()", pos as integer);
- if not func then func, args, p = s_match(inner, "^(%w+)(%b())()", pos as integer); end
- if not func then func, tmpl, p = s_match(inner, "^(%w+)(%b{})()", pos as integer); end
- if not func then func, p = s_match(inner, "^(%w+)()", pos as integer); end
- if not func then break end
- if tmpl then tmpl = s_sub(tmpl, 2, -2); end
- if args then args = s_sub(args, 2, -2); end
-
- if func == "each" and tmpl and st.is_stanza(value) then
- if not args then value, args = root, path; end
- local ns, name = s_match(args, "^(%b{})(.*)$");
- if ns then ns = s_sub(ns, 2, -2); else name, ns = args, nil; end
- if ns == "" then ns = nil; end
- if name == "" then name = nil; end
- local out, i = {}, 1;
- for c in (value as st.stanza_t):childtags(name, ns) do
- out[i], i = render(tmpl, c, escape, filters), i + 1;
- end
- value = t_concat(out);
- is_escaped = true;
- elseif func == "and" and tmpl then
- local condition = value;
- if args then condition = root:find(args); end
- if condition then
- value = render(tmpl, root, escape, filters);
- is_escaped = true;
- end
- elseif func == "or" and tmpl then
- local condition = value;
- if args then condition = root:find(args); end
- if not condition then
- value = render(tmpl, root, escape, filters);
- is_escaped = true;
- end
- elseif filters and filters[func] then
- local f = filters[func];
- if args == nil then
- value, is_escaped = f(value, tmpl);
- else
- value, is_escaped = f(args, value, tmpl);
- end
- else
- error("No such filter function: " .. func);
- end
- pipe, pos = s_match(inner, "^(|?)()", p as integer);
- end
-
- if value is string then
- if not is_escaped then value = escape(value); end
- return value;
- elseif st.is_stanza(value) then
- value = value:get_text();
- if value then
- return escape(value);
- end
- end
- return "";
- end));
-end
-
-return { render = render };