From 386a391fd95874b6b207c5fa485f8d91c543698b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 7 Feb 2024 23:06:01 +0100 Subject: [PATCH] added string.lstripped() and string.ltrimmed() --- .../res/prog8lib/shared_string_functions.p8 | 79 +++++++++++++++++++ compiler/res/prog8lib/string.p8 | 64 +-------------- compiler/res/prog8lib/virtual/string.p8 | 65 +-------------- compiler/test/TestCallgraph.kt | 8 +- docs/source/libraries.rst | 18 +++-- docs/source/todo.rst | 1 + examples/test.p8 | 44 +++++++---- 7 files changed, 129 insertions(+), 150 deletions(-) create mode 100644 compiler/res/prog8lib/shared_string_functions.p8 diff --git a/compiler/res/prog8lib/shared_string_functions.p8 b/compiler/res/prog8lib/shared_string_functions.p8 new file mode 100644 index 000000000..d6ee81caa --- /dev/null +++ b/compiler/res/prog8lib/shared_string_functions.p8 @@ -0,0 +1,79 @@ +string { + ; the string functions shared across compiler targets + %option merge, no_symbol_prefixing, ignore_unused + + sub strip(str s) { + ; -- gets rid of whitespace and other non-visible characters at the edges of the string + rstrip(s) + lstrip(s) + } + + sub rstrip(str s) { + ; -- gets rid of whitespace and other non-visible characters at the end of the string + if s[0]==0 + return + cx16.r0L = string.length(s) + do { + cx16.r0L-- + cx16.r1L = s[cx16.r0L] + } until cx16.r0L==0 or string.isprint(cx16.r1L) and not string.isspace(cx16.r1L) + s[cx16.r0L+1] = 0 + } + + sub lstrip(str s) { + ; -- gets rid of whitespace and other non-visible characters at the start of the string (destructive) + cx16.r0 = lstripped(s) + if cx16.r0 != s + void string.copy(cx16.r0, s) + } + + sub lstripped(str s) -> str { + ; -- returns pointer to first non-whitespace and non-visible character at the start of the string (non-destructive lstrip) + if s[0]==0 + return s + cx16.r0L = 255 + do { + cx16.r0L++ + cx16.r1L = s[cx16.r0L] + } until cx16.r1L==0 or string.isprint(cx16.r1L) and not string.isspace(cx16.r1L) + return s+cx16.r0L + } + + sub trim(str s) { + ; -- gets rid of whitespace characters at the edges of the string + rtrim(s) + ltrim(s) + } + + sub rtrim(str s) { + ; -- gets rid of whitespace characters at the end of the string + if s[0]==0 + return + cx16.r0L = string.length(s) + do { + cx16.r0L-- + cx16.r1L = s[cx16.r0L] + } until cx16.r0L==0 or not string.isspace(cx16.r1L) + s[cx16.r0L+1] = 0 + } + + sub ltrim(str s) { + ; -- gets rid of whitespace characters at the start of the string (destructive) + cx16.r0 = ltrimmed(s) + if cx16.r0 != s + void string.copy(cx16.r0, s) + } + + sub ltrimmed(str s) -> str { + ; -- return pointer to first non-whitespace character at the start of the string (non-destructive ltrim) + if s[0]==0 + return s + cx16.r0L = 255 + do { + cx16.r0L++ + cx16.r1L = s[cx16.r0L] + } until not string.isspace(cx16.r1L) + return s+cx16.r0L + } + +} diff --git a/compiler/res/prog8lib/string.p8 b/compiler/res/prog8lib/string.p8 index 31d2a9462..e253875d5 100644 --- a/compiler/res/prog8lib/string.p8 +++ b/compiler/res/prog8lib/string.p8 @@ -1,5 +1,7 @@ ; 0-terminated string manipulation routines. +%import shared_string_functions + string { %option no_symbol_prefixing, ignore_unused @@ -386,68 +388,6 @@ fail clc ; yes, no match found, return with c=0 }} } - sub strip(str s) { - ; -- gets rid of whitespace and other non-visible characters at the edges of the string - rstrip(s) - lstrip(s) - } - - sub rstrip(str s) { - ; -- gets rid of whitespace and other non-visible characters at the end of the string - if s[0]==0 - return - cx16.r0L = length(s) - do { - cx16.r0L-- - cx16.r1L = s[cx16.r0L] - } until cx16.r0L==0 or isprint(cx16.r1L) and not isspace(cx16.r1L) - s[cx16.r0L+1] = 0 - } - - sub lstrip(str s) { - ; -- gets rid of whitespace and other non-visible characters at the start of the string - if s[0]==0 - return - cx16.r0L = 255 - do { - cx16.r0L++ - cx16.r1L = s[cx16.r0L] - } until cx16.r1L==0 or isprint(cx16.r1L) and not isspace(cx16.r1L) - if cx16.r0L>0 - copy(s+cx16.r0L, s) - } - - sub trim(str s) { - ; -- gets rid of whitespace characters at the edges of the string - rtrim(s) - ltrim(s) - } - - sub rtrim(str s) { - ; -- gets rid of whitespace characters at the end of the string - if s[0]==0 - return - cx16.r0L = length(s) - do { - cx16.r0L-- - cx16.r1L = s[cx16.r0L] - } until cx16.r0L==0 or not isspace(cx16.r1L) - s[cx16.r0L+1] = 0 - } - - sub ltrim(str s) { - ; -- gets rid of whitespace characters at the start of the string - if s[0]==0 - return - cx16.r0L = 255 - do { - cx16.r0L++ - cx16.r1L = s[cx16.r0L] - } until not isspace(cx16.r1L) - if cx16.r0L>0 - copy(s+cx16.r0L, s) - } - asmsub isdigit(ubyte petsciichar @A) -> bool @Pc { %asm {{ cmp #'0' diff --git a/compiler/res/prog8lib/virtual/string.p8 b/compiler/res/prog8lib/virtual/string.p8 index 5a7a99c52..2be984467 100644 --- a/compiler/res/prog8lib/virtual/string.p8 +++ b/compiler/res/prog8lib/virtual/string.p8 @@ -1,5 +1,7 @@ ; 0-terminated string manipulation routines. For the Virtual Machine target. +%import shared_string_functions + string { %option ignore_unused @@ -184,69 +186,6 @@ string { } } - - sub strip(str s) { - ; -- gets rid of whitespace and other non-visible characters at the edges of the string - rstrip(s) - lstrip(s) - } - - sub rstrip(str s) { - ; -- gets rid of whitespace and other non-visible characters at the end of the string - if s[0]==0 - return - cx16.r0L = length(s) - do { - cx16.r0L-- - cx16.r1L = s[cx16.r0L] - } until cx16.r0L==0 or isprint(cx16.r1L) and not isspace(cx16.r1L) - s[cx16.r0L+1] = 0 - } - - sub lstrip(str s) { - ; -- gets rid of whitespace and other non-visible characters at the start of the string - if s[0]==0 - return - cx16.r0L = 255 - do { - cx16.r0L++ - cx16.r1L = s[cx16.r0L] - } until cx16.r1L==0 or isprint(cx16.r1L) and not isspace(cx16.r1L) - if cx16.r0L>0 - copy(s+cx16.r0L, s) - } - - sub trim(str s) { - ; -- gets rid of whitespace characters at the edges of the string - rtrim(s) - ltrim(s) - } - - sub rtrim(str s) { - ; -- gets rid of whitespace characters at the end of the string - if s[0]==0 - return - cx16.r0L = length(s) - do { - cx16.r0L-- - cx16.r1L = s[cx16.r0L] - } until cx16.r0L==0 or not isspace(cx16.r1L) - s[cx16.r0L+1] = 0 - } - - sub ltrim(str s) { - ; -- gets rid of whitespace characters at the start of the string - if s[0]==0 - return - cx16.r0L = 255 - do { - cx16.r0L++ - cx16.r1L = s[cx16.r0L] - } until not isspace(cx16.r1L) - if cx16.r0L>0 - copy(s+cx16.r0L, s) - } - sub isdigit(ubyte character) -> bool { return character>='0' and character<='9' } diff --git a/compiler/test/TestCallgraph.kt b/compiler/test/TestCallgraph.kt index 85164c87b..b15abff02 100644 --- a/compiler/test/TestCallgraph.kt +++ b/compiler/test/TestCallgraph.kt @@ -22,7 +22,7 @@ import kotlin.io.path.readText class TestCallgraph: FunSpec({ test("testGraphForEmptySubs") { val sourcecode = """ - %import string + %import conv main { sub start() { } @@ -37,7 +37,7 @@ class TestCallgraph: FunSpec({ graph.importedBy.size shouldBe 1 val toplevelModule = result.compilerAst.toplevelModule val importedModule = graph.imports.getValue(toplevelModule).single() - importedModule.name shouldBe "string" + importedModule.name shouldBe "conv" val importedBy = graph.importedBy.getValue(importedModule).single() importedBy.name.startsWith("on_the_fly_test") shouldBe true @@ -61,7 +61,7 @@ class TestCallgraph: FunSpec({ test("reference to empty sub") { val sourcecode = """ - %import string + %import conv main { sub start() { uword xx = &empty @@ -78,7 +78,7 @@ class TestCallgraph: FunSpec({ graph.importedBy.size shouldBe 1 val toplevelModule = result.compilerAst.toplevelModule val importedModule = graph.imports.getValue(toplevelModule).single() - importedModule.name shouldBe "string" + importedModule.name shouldBe "conv" val importedBy = graph.importedBy.getValue(importedModule).single() importedBy.name.startsWith("on_the_fly_test") shouldBe true diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index ef34a386c..13bb4c433 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -292,22 +292,28 @@ Provides string manipulation routines. Returns uppercased PETSCII character. ``strip (string)`` - Gets rid of whitespace and other non-visible characters at the edges of the string. + Gets rid of whitespace and other non-visible characters at the edges of the string. (destructive) ``rstrip (string)`` - Gets rid of whitespace and other non-visible characters at the end of the string. + Gets rid of whitespace and other non-visible characters at the end of the string. (destructive) ``lstrip (string)`` - Gets rid of whitespace and other non-visible characters at the start of the string. + Gets rid of whitespace and other non-visible characters at the start of the string. (destructive) + +``lstripped (string) -> str`` + Returns pointer to first non-whitespace and non-visible character at the start of the string (non-destructive lstrip) ``trim (string)`` - Gets rid of whitespace characters at the edges of the string. + Gets rid of whitespace characters at the edges of the string. (destructive) ``rtrim (string)`` - Gets rid of whitespace characters at the end of the string. + Gets rid of whitespace characters at the end of the string. (destructive) ``ltrim (string)`` - Gets rid of whitespace characters at the start of the string. + Gets rid of whitespace characters at the start of the string. (destructive) + +``ltrimmed (string) -> str`` + Returns pointer to first non-whitespace character at the start of the string (non-destructive ltrim) ``isdigit (char)`` Returns boolean if the character is a numerical digit 0-9 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 5d348898e..c8ac49b89 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -54,6 +54,7 @@ Compiler: Libraries: +- conv: the routines could return the address of conv.string_out, and/or there could be versions that take the address of a different buffer and use it instead. - once kernal rom v47 is released, remove most of the workarounds in cx16 floats.parse_f() . Prototype parse routine in examples/cx16/floatparse.p8 - fix the problems in atari target, and flesh out its libraries. - c128 target: make syslib more complete (missing kernal routines)? diff --git a/examples/test.p8 b/examples/test.p8 index ca4cb5cf1..99fbcd910 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,24 +6,38 @@ main { sub start() { - str namestring = petscii:"The Quick Brown Fox Jumps Over The Lazy Dog\n0123456789!#$%^&*()-=_+[]{};:'<>,./?\n" - str namestring2 = petscii:"The Quick Brown Fox Jumps Over The Lazy Dog\n0123456789!#$%^&*()-=_+[]{};:'<>,./?\n" - txt.petscii2scr_str(namestring2) - for cx16.r0L in 0 to len(namestring) { - txt.print_ubhex(namestring[cx16.r0L], false) - txt.spc() - txt.print_ubhex(namestring2[cx16.r0L], false) - txt.nl() - } - txt.nl() - sys.exit(1) - str name1 = "" - str name2 = "hello \r\n" + str name2 = "hello" str name3 = " \n\rhello" - str name4 = " \n\r\xa0\xa0\xff\xffhello\x02\x02\x02 \n " + str name4 = " \x02\x02\x02\n\r\xa0\xa0\xff\xffhello" - foo(name2) + txt.chrout('[') + txt.print(string.ltrimmed(name1)) + txt.print("]\n") + txt.chrout('[') + txt.print(string.ltrimmed(name2)) + txt.print("]\n") + txt.chrout('[') + txt.print(string.ltrimmed(name3)) + txt.print("]\n") + txt.chrout('[') + txt.print(string.ltrimmed(name4)) + txt.print("]\n\n") + + txt.chrout('[') + txt.print(string.lstripped(name1)) + txt.print("]\n") + txt.chrout('[') + txt.print(string.lstripped(name2)) + txt.print("]\n") + txt.chrout('[') + txt.print(string.lstripped(name3)) + txt.print("]\n") + txt.chrout('[') + txt.print(string.lstripped(name4)) + txt.print("]\n") + + ; foo(name2) } sub foo (str s2) {