Skip to content

Commit

Permalink
added smart string formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
cnvogelg committed Dec 14, 2024
1 parent 9cd1910 commit 225512e
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
61 changes: 61 additions & 0 deletions amitools/util/strtool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import string

CTRL_CHAR_MAP = {"\t": "\\t", "\r": "\\r", "\n": "\\n"}


def to_text_string(txt, add_size=False):
"""convert a string to text representation but replace non-printable chars"""
# replace non printable chars
result = []
for c in txt:
if c in CTRL_CHAR_MAP:
result.append(CTRL_CHAR_MAP[c])
elif c in string.printable:
# quote
if c == "'":
result.append("\\'")
# regular char
else:
result.append(c)
else:
result.append(f"\\x{ord(c):02x}")
new_txt = "".join(result)
if add_size:
return f"'{new_txt}'({len(txt)})"
else:
return f"'{new_txt}'"


def to_binary_string(txt, crop_after=8):
"""convert a string to binary and crop after a given number"""
result = []
num = 0
ellipsis = False
for c in txt:
if c in string.printable and c not in CTRL_CHAR_MAP:
result.append(f"'{c}'")
else:
result.append(f"{ord(c):02x}")
num += 1
if num >= crop_after:
ellipsis = True
break
new_txt = " ".join(result)
if ellipsis:
new_txt += " ..."
return f"{new_txt} ({len(txt)})"


def to_string(txt, txt_ratio=75, add_size=False):
"""convert a string to a human-readable representation"""
printable = 0
total = len(txt)
for c in txt:
if c in string.printable:
printable += 1
ratio = printable * 100 // total
# if likely a text?
if ratio >= txt_ratio:
return to_text_string(txt, add_size)
else:
return to_binary_string(txt)
5 changes: 3 additions & 2 deletions amitools/vamos/astructs/string.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from amitools.util.strtool import to_string
from .typebase import TypeBase
from .pointer import APTR, BPTR

Expand Down Expand Up @@ -46,7 +47,7 @@ def __eq__(self, other):
def __str__(self):
val = self.get()
if val:
return f"'{val}'({len(val)})"
return to_string(val, add_size=True)
else:
return "NONE"

Expand Down Expand Up @@ -105,7 +106,7 @@ def __eq__(self, other):
def __str__(self):
val = self.get()
if val:
return f"#'{val}'({len(val)})"
return "#" + to_string(val, add_size=True)
else:
return "#NONE"

Expand Down
23 changes: 23 additions & 0 deletions test/unit/util_strtool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from amitools.util.strtool import to_text_string, to_binary_string, to_string


def util_strtool_to_text_test():
assert to_text_string("hello, world!") == "'hello, world!'"
assert to_text_string("hello\nworld!\r") == "'hello\\nworld!\\r'"
assert to_text_string("\xa0") == "'\\xa0'"
assert to_text_string("hello, world!", add_size=True) == "'hello, world!'(13)"


def util_strtool_to_binary_test():
assert to_binary_string("abc") == "'a' 'b' 'c' (3)"
assert to_binary_string("\xa0\xa1\xa2") == "a0 a1 a2 (3)"
# ellipsis
assert (
to_binary_string("hello, world!") == "'h' 'e' 'l' 'l' 'o' ',' ' ' 'w' ... (13)"
)


def util_strtool_to_str_test():
assert to_string("hello, world!") == "'hello, world!'"
assert to_string("\xa0\xa1\xa2") == "a0 a1 a2 (3)"
assert to_string("hello, world!", add_size=True) == "'hello, world!'(13)"

0 comments on commit 225512e

Please sign in to comment.