-- Autogenerated with DRAKON Editor 1.33
local table = table
local string = string
local pairs = pairs
local ipairs = ipairs
local type = type

local tostring = tostring
local tonumber = tonumber
local error = error
local print = print

-- configuration
local global_cfg = global_cfg
local price_cfg = price_cfg



local math = require("math")
local clock = require("clock")
local log = require("log")

local digest = require("digest")
local fiber = require("fiber")
local io = require("io")
local os = require("os")
local utf8 = require("lua-utf8")
local json=require('json')
local msgpack = require("msgpack")
local pickle = require("pickle")
local fun = require('fun')
local socket = require("socket")



local a_code = string.byte("a")
local z_code = string.byte("z")
local d0 = string.byte("0")
local d9 = string.byte("9")
local under = string.byte("_")
local at = string.byte("@")
local dot = string.byte(".")
local dash = string.byte("-")


setfenv(1, {}) 

local content_types = {}
local g_separators = {}

local gspace = {}
local g_chars = {}

gspace[10] = true
gspace[13] = true
gspace[32] = true
gspace[9] = true

gspace[string.byte("{")] = true
gspace[string.byte("}")] = true
gspace[string.byte("-")] = true
gspace[string.byte("_")] = true
gspace[string.byte("/")] = true
gspace[string.byte("+")] = true
gspace[string.byte("*")] = true
gspace[string.byte("\\")] = true
gspace[string.byte("%")] = true
gspace[string.byte("&")] = true
gspace[string.byte("^")] = true
gspace[string.byte("=")] = true
gspace[string.byte("?")] = true
gspace[string.byte("!")] = true
gspace[string.byte("\"")] = true
gspace[string.byte("\'")] = true
gspace[string.byte(".")] = true
gspace[string.byte(",")] = true
gspace[string.byte(";")] = true
gspace[string.byte(":")] = true
gspace[string.byte("(")] = true
gspace[string.byte(")")] = true
gspace[string.byte("[")] = true
gspace[string.byte("]")] = true
gspace[string.byte("<")] = true
gspace[string.byte(">")] = true
gspace[string.byte("|")] = true

local g_days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 

function add_char_range(first, last, result)
    local i
    local f = string.byte(first, 1)
    local l = string.byte(last, 1)
    i = f
    while true do
        if i <= l then
            
        else
            break
        end
        table.insert(result, i)
        i = i + 1
    end
end

function add_list_to_set(set, list)
    if list then
        for _, value in ipairs(list) do
            set[value] = true
        end
    end
end

function add_months(now, months)
    local datetime = os.date("*t", now)
    local add_months = months % 12
    local next_month = datetime.month + add_months
    local year2 = datetime.year + math.floor(months / 12)
    if next_month > 12 then
        year2 = year2 + 1
        next_month = next_month - 12
    end
    local days_next_month = get_days_in_month(
    	year2,
    	next_month
    )
    local day2 = math.min(
    	datetime.day,
    	days_next_month
    )
    datetime.day = day2
    datetime.month = next_month
    datetime.year = year2
    return os.time(datetime)
end

function add_range(dst, src)
    local count = #src
    local insert = table.insert
    i = 1
    while true do
        if i <= count then
            
        else
            break
        end
        insert(
        	dst,
        	src[i]
        )
        i = i + 1
    end
end

function add_separator(text)
    g_separators[utf8.byte(text)] = true
end

function add_set(src, dst)
    if src then
        for key, value in pairs(src) do
            dst[key] = value
        end
    end
end

function append_char(text, code)
    return utf8.insert(
    	text,
    	utf8.char(code)
    )
end

function bash_escape(text)
    local quote = utf8.codepoint("'")
    local result = ""
    for i, code in utf8.next, text do
        if code == quote then
            result = utf8.insert(
            	result,
            	"'\\''"
            )
        else
            result = utf8.insert(
            	result,
            	utf8.char(code)
            )
        end
    end
    return result
end

function build_random_chars()
    local result = {}
    add_char_range("a", "z", result)
    add_char_range("A", "Z", result)
    add_char_range("0", "9", result)
    return result
end

function bulk_action(table, field_index, action)
    local counter = 0
    if table then
        for it, row in table:pairs() do
            local old_value = row[field_index]
            local new_value = action(old_value)
            if new_value then
                local row2 = row:update(
                	{{"=", field_index, new_value}}
                )
                table:replace(row2)
                counter = counter + 1
            end
        end
        return counter
    else
        error("table not found: " .. table_name)
    end
end

function contains(list, element)
    if list then
        for _, item in ipairs(list) do
            if item == element then
                return true
            end
        end
        return false
    else
        return false
    end
end

function copy(obj)
    local result = {}
    add_set(obj, result)
    return result
end

function date(yyyy, mm, dd)
    local tt = {
    	year = yyyy,
    	month = mm,
    	day = dd
    }
    return os.time(tt)
end

function date8_to_expiry(date8)
    local time = parse_date8(date8)
    if time then
        local minute = 60
        return time - minute
    else
        return nil
    end
end

function days_to_secs(days)
    return days * 24 * 3600
end

function ends_with(what, with)
    local walen = utf8.len(what)
    local wilen = utf8.len(with)
    local start = walen - wilen + 1
    if start > 0 then
        local sub = utf8.sub(what, start, walen)
        return sub == with
    else
        return false
    end
end

function filter(list, criterion)
    local result = {}
    if list then
        for _, item in ipairs(list) do
            if criterion(item) then
                table.insert(
                	result,
                	item
                )
            end
        end
    end
    return result
end

function find(list, item)
    if list then
        for i, v in ipairs(list) do
            if v == item then
                return i
            end
        end
        return -1
    else
        return -1
    end
end

function find_many_in_line(line_no, line, needle, result, original)
    local first, last
    local current = line
    local start = 0
    while true do
        first, last = utf8.find(
        	current,
        	needle
        )
        if first then
            
        else
            break
        end
        local item = {
        	line = original,
        	first = first + start,
        	last = last + start,
        	line_no = line_no
        }
        table.insert(result, item)
        current = utf8.sub(
        	current, 
        	last + 1
        )
        start = start + last
    end
end

function find_many_substrings(haystack, needle, ignore_case)
    local original
    local result = {}
    if (is_empty(haystack)) or (is_empty(needle)) then
        
    else
        local lines = split(haystack, "\n")
        for i, line in ipairs(lines) do
            original = line
            if ignore_case then
                line = utf8.lower(line)
            end
            find_many_in_line(
            	i,
            	line,
            	needle,
            	result,
            	original
            )
        end
    end
    return result
end

function get_days_in_month(year, month)
    local days = g_days_in_month[month]
    if (month == 2) and (is_leap_year(year)) then
        return 29
    else
        return days
    end
end

function get_extension(filename)
    local dotstr = "."
    local dot = dotstr:byte(1)
    local i = #filename
    while true do
        if i > 0 then
            
        else
            return ""
        end
        if filename:byte(i) == dot then
            return string.sub(filename, i + 1)
        end
        i = i - 1
    end
end

function get_filename(path)
    local parts = split(path, "/")
    return parts[#parts]
end

function get_host_name(url)
    if (url) and (not (url == "")) then
        local first, last = url:find("://")
        if last then
            local no_prot = url:sub(last + 1)
            local slash = no_prot:find("/")
            local colon = no_prot:find(":")
            local host_port
            if slash then
                host_port = no_prot:sub(1, slash - 1)
            else
                host_port = no_prot
            end
            if colon then
                return host_port:sub(1, colon - 1)
            else
                return host_port
            end
        else
            return ""
        end
    else
        return ""
    end
end

function get_mime(filename, default)
    local extension = get_extension(filename)
    local type = content_types[extension]
    if type then
        
    else
        type = default
    end
    return type
end

function get_product(product_id)
    local product = price_cfg.products[product_id]
    if product then
        return product
    else
        error("product '"
         .. tostring(product_id)
         .. "' not found")
    end
end

function good_id_symbols(id)
    local chars = string_to_chars(id)
    for _, code in ipairs(chars) do
        if ((((is_alpha(code)) or (is_digit(code))) or (code == under)) or (code == dot)) or (code == dash) then
            
        else
            return false
        end
    end
    return true
end

function group_by(list, property)
    local result = {}
    for _, item in ipairs(list) do
        local key = item[property]
        local group = result[key]
        if group then
            
        else
            group = {}
            result[key] = group
        end
        table.insert(
        	group,
        	item
        )
    end
    return result
end

function http_post(url, data, mime, headers, user)
    local tmp = os.tmpname()
    local tmp0 = os.tmpname()
    local header_str = ""
    local user_str = ""
    if headers then
        for _, header in ipairs(headers) do
            header_str = header_str .. " -H \""
              .. header .. "\""
        end
    end
    if user then
        user_str = "-u '" .. user .. "'"
    end
    log.info(tmp0 .. " > " .. tmp)
    write_all_bytes(tmp0, data)
    local command = string.format(
    	'curl -X POST --data @\'%s\' -H "Content-type: %s" %s %s %s > %s',
    	tmp0,
    	mime,
    	header_str,
    	user_str,
    	url,
    	tmp
    )
    log.info(command)
    os.execute(command)
    local response = read_all_bytes(tmp)
    log.info(tostring(response))
    os.remove(tmp)
    os.remove(tmp0)
    return response
end

function http_post_json(url, obj, headers, user)
    local mime = "application/json; charset=utf-8"
    local data = json.encode(obj)
    local response = http_post(url, data, mime, headers, user)
    if response then
        if response == "" then
            return {}
        else
            local result = json.decode(response)
            return result
        end
    else
        return nil
    end
end

function init()
    content_types["html"] = "text/html; charset=utf-8"
    content_types["htm"] = "text/html; charset=utf-8"
    content_types["css"] = "text/css; charset=utf-8"
    content_types["js"] = "application/javascript; charset=utf-8"
    content_types["png"] = "image/png"
    content_types["jpg"] = "image/jpeg"
    content_types["svg"] = "image/svg+xml"
    content_types["json"] = "application/json; charset=utf-8"
    content_types["txt"] = "text/plain; charset=utf-8"
    content_types["ttf"] = "application/x-font-ttf"
    content_types["eot"] = "application/vnd.ms-fontobject"
    content_types["woff"] = "application/x-font-woff"
    content_types["ico"] = "image/x-icon"
    content_types["pdf"] = "application/pdf"
    init_separators()
    g_chars = build_random_chars()
end

function init_separators()
    add_separator(" ")
    add_separator("\t")
    add_separator("\r")
    add_separator("\n")
    add_separator(".")
    add_separator(",")
    add_separator(":")
    add_separator(";")
    add_separator("-")
    add_separator("=")
    add_separator("\"")
    add_separator("'")
    add_separator("/")
    add_separator("\\")
    add_separator("(")
    add_separator(")")
    add_separator("[")
    add_separator("]")
    add_separator("{")
    add_separator("}")
    add_separator("~")
    add_separator("`")
    add_separator("#")
    add_separator("@")
    add_separator("%")
    add_separator("$")
    add_separator("&")
    add_separator("?")
    add_separator("!")
    add_separator("^")
    add_separator("|")
    add_separator("<")
    add_separator(">")
end

function is_alpha(code)
    if (code >= a_code) and (code <= z_code) then
        return true
    else
        return false
    end
end

function is_digit(code)
    if (code >= d0) and (code <= d9) then
        return true
    else
        return false
    end
end

function is_empty(value)
    if (value) and (not (#value == 0)) then
        return false
    else
        return true
    end
end

function is_leap_year(year)
    if year % 4 == 0 then
        if year % 100 == 0 then
            if year % 400 == 0 then
                return true
            else
                return false
            end
        else
            return true
        end
    else
        return false
    end
end

function is_space(code)
    return not not gspace[code]
end

function join(list, separator)
    local result = ""
    for _, item in ipairs(list) do
        if result == "" then
            result = item
        else
            result = result .. separator .. item
        end
    end
    return result
end

function list_to_set(list)
    local result = {}
    add_list_to_set(result, list)
    return result
end

function load_as_base64(filename)
    local bytes = read_all_bytes(filename)
    if bytes then
        local b64 = digest.base64_encode(bytes)
        return b64
    else
        return nil
    end
end

function make_language_path(language)
    if (language) and (not (language == "")) then
        if language == "en-us" then
            return "en"
        else
            return language
        end
    else
        return "en"
    end
end

function map(list, mapper)
    local result = {}
    if list then
        for _, item in ipairs(list) do
            local copy = mapper(item)
            table.insert(
            	result,
            	copy
            )
        end
    end
    return result
end

function months_to_secs(months)
    local secs_in_month = 3600 * 24 * 365.25 / 12
    return round(months * secs_in_month)
end

function msgpack_call(host, port, request)
    local sock = socket.tcp_connect(host, port)
    if sock then
        local response
        if send_msgpack(sock, request) then
            response = receive_msgpack(sock)
        else
            response = nil
        end
        sock:close()
        return response
    else
        log.error("could not open socket: "
          .. tostring(host) .. ":" .. tostring(port))
        return nil
    end
end

function normalize_string(text)
    local low = utf8.lower(text)
    local machine = string_normalizer()
    machine.result = ""
    for i, code in utf8.next, low do
        if is_space(code) then
            machine:space(code)
        else
            machine:char(code)
        end
    end
    return machine.result
end

function parse_compound_name(text)
    if text then
        local state = "idle"
        local low = utf8.lower(text)
        local result = ""
        local start = true
        for i, code in utf8.next, low do
            local is_separ = g_separators[code]
            if state == "idle" then
                if is_separ then
                    
                else
                    if start then
                        
                    else
                        result = utf8.insert(
                        	result,
                        	" "
                        )
                    end
                    result = utf8.insert(
                    	result,
                    	utf8.char(code)
                    )
                    state = "token"
                end
            else
                if is_separ then
                    state = "idle"
                else
                    start = false
                    result = utf8.insert(
                    	result,
                    	utf8.char(code)
                    )
                end
            end
        end
        return result
    else
        return ""
    end
end

function parse_date8(date8)
    if date8 then
        local text = tostring(date8)
        local ys = text:sub(1, 4)
        local ms = text:sub(5, 6)
        local ds = text:sub(7, 8)
        local year = tonumber(ys)
        local month = tonumber(ms)
        local day = tonumber(ds)
        if ((year) and (month)) and (day) then
            local tt = {
            	year = year,
            	month = month,
            	day = day,
            	hour = 0,
            	min = 0,
            	sec = 0
            }
            return os.time(tt)
        else
            return nil
        end
    else
        return nil
    end
end

function parse_query(text)
    local parts = split(text, "&")
    local result = {}
    for _, part in ipairs(parts) do
        local chunks = split(part, "=")
        if #chunks == 2 then
            local key = chunks[1]
            local value = chunks[2]
            result[key] = value
        end
    end
    return result
end

function parse_xml(names, xml)
    local self = {
    	result = {},
    	names = {}
    }
    for _, name in ipairs(names) do
        local tag = "<" .. name .. ">"
        self.names[tag] = name
    end
    local callbacks = {
    	Default = function(parser, str)
    		simple_xml_default(self, str)
    	end
    }
    local parser = lxp.new(callbacks)
    local ok, msg, line = parser:parse(xml)
    parser:stop()
    if ok then
        return true, self.result
    else
        return false, msg
    end
end

function print_amount(amount)
    return string.format("%.2f", amount)
end

function print_table(obj)
    for i, row in pairs(obj) do
        print(i, row)
    end
end

function random_password(length)
    local result = ""
    local bytes = digest.urandom(length)
    local i = 1
    while true do
        if i <= #bytes then
            
        else
            break
        end
        local code = string.byte(bytes, i)
        local index = (code % #g_chars) + 1
        local char = g_chars[index]
        result = result .. string.char(char)
        i = i + 1
    end
    return result
end

function random_string()
    local result = ""
    local bytes = digest.urandom(40)
    local i = 1
    while true do
        if i <= #bytes then
            
        else
            break
        end
        local code = string.byte(bytes, i)
        result = result .. string.format("%x", code)
        i = i + 1
    end
    return result
end

function read_all_bytes(filename)
    local file, msg = io.open(filename, "rb")
    if file then
        local content = file:read("*all")
        file:close()
        return content
    else
        return nil
    end
end

function read_json(filename)
    local data = read_all_bytes(filename)
    local obj = json.decode(data)
    return obj
end

function receive_length(sock)
    local bytes = sock:read(4)
    if bytes then
        if #bytes == 0 then
            return 0
        else
            local length = pickle.unpack("i", bytes)
            return length
        end
    else
        log.error("error reading length")
        return 0
    end
end

function receive_msgpack(sock)
    local length = receive_length(sock)
    if length then
        local bytes = sock:read(length)
        if length then
            return msgpack.decode(bytes)
        else
            log.error("error reading payload from socket")
            return nil
        end
    else
        return nil
    end
end

function remove(list, item)
    local index = find(list, item)
    if index == -1 then
        
    else
        table.remove(list, index)
    end
end

function repeat_value(what, count)
    qs = {}
    i = 1
    while true do
        if i <= count then
            
        else
            break
        end
        table.insert(qs, what)
        i = i + 1
    end
    return qs
end

function replace(str, from_s, to_s)
    local i
    local c
    local result = ""
    local from = from_s:byte(1)
    local to = to_s:byte(1)
    i = 1
    while true do
        if i <= #str then
            
        else
            break
        end
        c = str:byte(i)
        if c == from then
            result = result .. to_s
        else
            result = result .. string.char(c)
        end
        i = i + 1
    end
    return result
end

function replace_quoted(text, from, to)
    local first, last
    if text then
        local from2 = "'" .. from .. "'"
        first, last = text:find(from2)
        if first == nil then
            local from3 = "\"" .. from .. "\""
            first, last = text:find(from3)
            if first == nil then
                first, last = text:find(from)
                if first == nil then
                    return nil
                else
                    local to2 = "'" .. to .. "'"
                    local result = text:sub(1, first - 1) ..
                    	to2 ..
                    	text:sub(last + 1)
                    return result
                end
            else
                local to2 = "'" .. to .. "'"
                local result = text:sub(1, first - 1) ..
                	to2 ..
                	text:sub(last + 1)
                return result
            end
        else
            local to2 = "'" .. to .. "'"
            local result = text:sub(1, first - 1) ..
            	to2 ..
            	text:sub(last + 1)
            return result
        end
    else
        return nil
    end
end

function replace_quoted_in_object(obj, path, from, to)
    local result = nil
    if obj then
        local current = obj
        local i
        i = 1
        while true do
            if i < #path then
                
            else
                local property = path[#path]
                local value = current[property]
                local value2 = replace_quoted(
                	value,
                	from,
                	to
                )
                if value2 then
                    current[property] = value2
                    result = obj
                end
                break
            end
            local step = path[i]
            current = current[step]
            if current then
                
            else
                break
            end
            i = i + 1
        end
    end
    return result
end

function reverse(list)
    local result = {}
    if list then
        local i = #list
        while true do
            if i > 0 then
                
            else
                break
            end
            local value = list[i]
            table.insert(result, value)
            i = i - 1
        end
    end
    return result
end

function round(num, idp)
    local mult = 10^(idp or 0)
    return math.floor(num * mult + 0.5) / mult
end

function send_length(sock, bytes)
    local length_bytes = pickle.pack("i", #bytes)
    if sock:write(length_bytes) then
        return true
    else
        log.error("could not send length")
        return false
    end
end

function send_msgpack(sock, obj)
    if obj then
        local bytes = msgpack.encode(obj)
        if send_length(sock, bytes) then
            if sock:write(bytes) then
                return true
            else
                log.error("error sending payload")
                return false
            end
        else
            return false
        end
    else
        error("obj is nil")
    end
end

function set_to_list(set)
    local result = {}
    if set then
        for key, value in pairs(set) do
            if value then
                table.insert(
                	result,
                	key
                )
            end
        end
    end
    return result
end

function simple_xml_default(self, text)
    local expected = self.expected
    if expected then
        self.result[expected] = text
        self.expected = nil
    else
        local name = self.names[text]
        if name then
            self.expected = name
        end
    end
end

function split(text, separator)
    local tokens = {}
    local current = ""
    if text then
        local sep_code = utf8.codepoint(separator)
        for i, code in utf8.next, text do
            if sep_code == code then
                if #current == 0 then
                    
                else
                    table.insert(tokens, current)
                    current = ""
                end
            else
                current = utf8.insert(
                	current,
                	utf8.char(code)
                )
            end
        end
        if #current == 0 then
            
        else
            table.insert(tokens, current)
        end
    end
    return tokens
end

function starts_with(what, with)
    local sub = utf8.sub(what, 1, #with)
    return sub == with
end

function string_contains(haystack, needle)
    if is_empty(needle) then
        return false
    else
        local first, last = utf8.find(
        	haystack,
        	needle
        )
        if first then
            return true
        else
            return false
        end
    end
end

function string_contains_words(haystack, needle)
    if (is_empty(needle)) or (is_empty(haystack)) then
        return false
    else
        local first, last = utf8.find(
        	haystack,
        	needle
        )
        if first then
            if first > 1 then
                local before = utf8.sub(
                	haystack,
                	first - 1,
                	first - 1
                )
                if before == " " then
                    if last < utf8.len(haystack) then
                        local after = utf8.sub(
                        	haystack,
                        	last + 1,
                        	last + 1
                        )
                        if after == " " then
                            return true
                        else
                            return false
                        end
                    else
                        return true
                    end
                else
                    return false
                end
            else
                if last < utf8.len(haystack) then
                    local after = utf8.sub(
                    	haystack,
                    	last + 1,
                    	last + 1
                    )
                    if after == " " then
                        return true
                    else
                        return false
                    end
                else
                    return true
                end
            end
        else
            return false
        end
    end
end

function string_normalizer_Normal_char(self, code)
    self.result = append_char(
    	self.result,
    	code
    )
    self.state = "Normal"
end

function string_normalizer_Normal_space(self, code)
    self.state = "Whitespace"
end

function string_normalizer_Start_char(self, code)
    self.result = append_char(
    	self.result,
    	code
    )
    self.state = "Normal"
end

function string_normalizer_Start_space(self, code)
    self.state = "Start"
end

function string_normalizer_Whitespace_char(self, code)
    self.result = append_char(
    	self.result,
    	32
    )
    self.result = append_char(
    	self.result,
    	code
    )
    self.state = "Normal"
end

function string_normalizer_Whitespace_space(self, code)
    self.state = "Whitespace"
end

function string_to_chars(text)
    local result = {}
    local i = 1
    while true do
        if i <= #text then
            
        else
            break
        end
        local code = string.byte(text, i)
        table.insert(result, code)
        i = i + 1
    end
    return result
end

function trim(text)
    return (text:gsub("^%s*(.-)%s*$", "%1"))
end

function update2(space, id, value)
    space:update(id, {{"=", 2, value}})
end

function update3(space, id, id2, value)
    space:update({id, id2}, {{"=", 3, value}})
end

function update4(space, id, id2, id3, value)
    space:update({id, id2, id3}, {{"=", 4, value}})
end

function write2(space, id, value)
    space:upsert({id, value}, {{"=", 2, value}})
end

function write4(space, id, id2, id3, value)
    space:upsert({id, id2, id3, value}, {{"=", 4, value}})
end

function write_all_bytes(filename, data)
    local file, msg = io.open(filename, "w+b")
    if file then
        if data then
            file:write(data)
        end
        file:close()
        return true
    else
        return false
    end
end

function write_json(filename, obj)
    local data = json.encode(obj)
    return write_all_bytes(filename, data)
end


function string_normalizer()
    local obj = {}
    obj.type_name = "string_normalizer"
    obj.state = "Start"
    obj.char = function(self, code)
        local _state_ = self.state
        if _state_ == "Start" then
            return string_normalizer_Start_char(self, code)
        elseif _state_ == "Normal" then
            return string_normalizer_Normal_char(self, code)
        elseif _state_ == "Whitespace" then
            return string_normalizer_Whitespace_char(self, code)
        end
        return nil
    end
    obj.space = function(self, code)
        local _state_ = self.state
        if _state_ == "Start" then
            return string_normalizer_Start_space(self, code)
        elseif _state_ == "Normal" then
            return string_normalizer_Normal_space(self, code)
        elseif _state_ == "Whitespace" then
            return string_normalizer_Whitespace_space(self, code)
        end
        return nil
    end
    return obj
end

init()

return {
	contains = contains,
	reverse = reverse,
	write2 = write2,
	update2 = update2,
	update3 = update3,
	update4 = update4,
	remove = remove,
	write4 = write4,
	read_all_bytes = read_all_bytes,
	write_all_bytes = write_all_bytes,
	split = split,
	list_to_set = list_to_set,
	set_to_list = set_to_list,
	trim = trim,
	good_id_symbols = good_id_symbols,
	random_string = random_string,
	write_json = write_json,
	is_empty = is_empty,
	join = join,
	replace = replace,
	add_range = add_range,
	get_extension = get_extension,
	get_mime = get_mime,
	get_filename = get_filename,
	load_as_base64 = load_as_base64,
	starts_with = starts_with,
	date = date,
	add_list_to_set = add_list_to_set,
	days_to_secs = days_to_secs,
	make_language_path = make_language_path,
	round = round,
	months_to_secs = months_to_secs,
	get_product = get_product,
	copy = copy,
	send_msgpack = send_msgpack,
	receive_msgpack = receive_msgpack,
	http_post = http_post,
	http_post_json = http_post_json,
	msgpack_call = msgpack_call,
	string_to_chars = string_to_chars,
	is_digit = is_digit,
	get_host_name = get_host_name,
	print_amount = print_amount,
	parse_xml = parse_xml,
	parse_query = parse_query,
	parse_compound_name = parse_compound_name,
	parse_date8 = parse_date8,
	date8_to_expiry = date8_to_expiry,
	add_months = add_months,
	get_days_in_month = get_days_in_month,
	is_leap_year = is_leap_year,
	read_json = read_json,
	normalize_string = normalize_string,
	string_contains = string_contains,
	find_many_substrings = find_many_substrings,
	print_table = print_table,
	string_contains_words = string_contains_words,
	random_password = random_password,
	replace_quoted = replace_quoted,
	replace_quoted_in_object = replace_quoted_in_object,
	bulk_action = bulk_action,
	bash_escape = bash_escape,
	ends_with = ends_with,

	map = map,
	group_by = group_by,
	filter = filter,
	repeat_value = repeat_value,
	add_set = add_set
}
