Python "auxlib"

Admin User, created Apr 16. 2024
         
###
# Modern Albufeira Prolog Interpreter
#
# Warranty & Liability
# To the extent permitted by applicable law and unless explicitly
# otherwise agreed upon, XLOG Technologies AG makes no warranties
# regarding the provided information. XLOG Technologies AG assumes
# no liability that any problems might be solved with the information
# provided by XLOG Technologies AG.
#
# Rights & License
# All industrial property rights regarding the information - copyright
# and patent rights in particular - are the sole property of XLOG
# Technologies AG. If the company was not the originator of some
# excerpts, XLOG Technologies AG has at least obtained the right to
# reproduce, change and translate the information.
#
# Reproduction is restricted to the whole unaltered document. Reproduction
# of the information is only allowed for non-commercial uses. Selling,
# giving away or letting of the execution of the library is prohibited.
# The library can be distributed as part of your applications and libraries
# for execution provided this comment remains unchanged.
#
# Restrictions
# Only to be distributed with programs that add significant and primary
# functionality to the library. Not to be distributed with additional
# software intended to replace any components of the library.
#
# Trademarks
# Jekejeke is a registered trademark of XLOG Technologies AG.
##
from dogelog import (exec_unify, exec_build, deref,
is_variable, unify,
check_atom, check_sink, Source, Sink, add, make_check)
#######################################################################
# open_input_atom_stream/2, open_output_atom_stream/1 and close_output_atom_stream/2 #
#######################################################################
###
# open_input_atom_stream(A, S):
# The built-in succeeds in S with a new input stream for the atom A.
##
def test_open_input_atom_stream(args):
text = deref(exec_build(args[0]))
check_atom(text)
src = Source()
src.buf = text
return exec_unify(args[1], src)
###
# open_output_atom_stream(S):
# The built-in succeeds in S with a new output stream.
##
def test_open_output_atom_stream(args):
dst = Sink()
dst.data = []
dst.send = mem_send
return exec_unify(args[0], dst)
def mem_send(data, buf):
data.append(buf)
###
# close_output_atom_stream(S, A):
# The built-in succeeds in A with the content of the output stream S.
##
def test_close_output_atom_stream(args):
writer = deref(exec_build(args[0]))
check_sink(writer)
writer = "".join(writer.data)
return exec_unify(args[1], writer)
#######################################################################
# XML Escape #
#######################################################################
###
# xml_escape(X, Y):
# The predicate succeeds in Y with the XML escape of X.
##
def test_xml_escape(args):
alpha = deref(exec_build(args[0]))
check_atom(alpha)
alpha = xml_escape(alpha)
return exec_unify(args[1], alpha)
def xml_escape(text):
res = ""
back = 0
i = 0
while i < len(text):
ch = ord(text[i])
if ch == 34: # "
elem = "&quot;"
elif ch == 38: # &
elem = "&amp;"
elif ch == 39: # '
elem = "&apos;"
elif ch == 60: # <
elem = "&lt;"
elif ch == 62: # >
elem = "&gt;"
else:
elem = None
if elem is not None:
res += text[back:i]
res += elem
back = i + 1
i += 1
if back != 0:
res += text[back:]
text = res
return text
#######################################################################
# Percent Encode #
#######################################################################
###
# percent_encode(X, Y):
# The predicate succeeds in Y with the percent encode of X.
##
def test_percent_encode(args):
alpha = deref(exec_build(args[0]))
if is_variable(alpha):
beta = deref(exec_build(args[1]))
beta = percent_decode(beta)
return unify(alpha, beta)
else:
check_atom(alpha)
alpha = percent_encode(alpha)
return exec_unify(args[1], alpha)
def percent_encode(text):
res = ""
back = 0
i = 0
while i < len(text):
ch = ord(text[i])
i += 1
if ch == 32: # space
elem = "+"
elif ch == 35: # #
elem = "%23"
elif ch == 37: # %
elem = "%25"
elif ch == 38: # &
elem = "%26"
elif ch == 43: # +
elem = "%2B"
elif ch == 61: # =
elem = "%3D"
elif ch == 63: # ?
elem = "%3F"
elif ch == 92: # \
elem = "%5C"
else:
elem = None
if elem is not None:
res += text[back:i - 1]
res += elem
back = i
if back != 0:
res += text[back:]
text = res
return text
def percent_decode(text):
res = ""
back = 0
i = 0
while i < len(text):
ch = ord(text[i])
i += 1
if ch == 37:
octet = octet_hex(text, i)
if 0 <= octet < 128:
res += text[back:i - 1]
res += chr(octet)
i += 2
back = i
elif 192 <= octet < 224:
octet2 = percent_hex(text, i + 2)
if 128 <= octet2 < 192:
res += text[back:i - 1]
res += chr((octet - 192) * 64 + (octet2 - 128))
i += 5
back = i
elif 224 <= octet < 240:
octet2 = percent_hex(text, i + 2)
if 128 <= octet2 < 192:
octet = (octet - 224) * 64 + (octet2 - 128)
octet2 = percent_hex(text, i + 5)
if 128 <= octet2 < 192:
res += text[back:i - 1]
res += chr(octet * 64 + (octet2 - 128))
i += 8
back = i
elif 240 <= octet < 248:
octet2 = percent_hex(text, i + 2)
if 128 <= octet2 < 192:
octet = (octet - 240) * 64 + (octet2 - 128)
octet2 = percent_hex(text, i + 5)
if 128 <= octet2 < 192:
octet = octet * 64 + (octet2 - 128)
octet2 = percent_hex(text, i + 8)
if 128 <= octet2 < 192:
res += text[back:i - 1]
res += chr(octet * 64 + (octet2 - 128))
i += 11
back = i
elif ch == 43:
res += text[back:i - 1]
res += chr(32) # space
back = i
if back != 0:
res += text[back:]
text = res
return text
def percent_hex(text, i):
ch = (ord(text[i]) if i < len(text) else -1)
if ch == 37:
i += 1
return octet_hex(text, i)
return -1
def octet_hex(text, i):
val = digit_hex(ord(text[i]) if i < len(text) else -1)
if val != -1:
i += 1
val2 = digit_hex(ord(text[i]) if i < len(text) else -1)
if val2 != -1:
return val * 16 + val2
return -1
def digit_hex(ch):
if 48 <= ch <= 57:
return ch - 48
if 65 <= ch <= 70:
return ch - 65 + 10
if 97 <= ch <= 102:
return ch - 97 + 10
return -1
#######################################################################
# Aux Lib Init #
#######################################################################
def main():
add("open_input_atom_stream", 2, make_check(test_open_input_atom_stream))
add("open_output_atom_stream", 1, make_check(test_open_output_atom_stream))
add("close_output_atom_stream", 2, make_check(test_close_output_atom_stream))
add("xml_escape", 2, make_check(test_xml_escape))
add("percent_encode", 2, make_check(test_percent_encode))