duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 7eb73f66648ba5261cbd809c131b47b332298cb4
parent d30142337aa8b5cd6a63ae45a41375d3f8f27a72
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed, 25 Jan 2023 21:20:15 -0500

lib/str: add "[str]?", remove unused "scontains", add docs

Diffstat:
Afs/doc/lib/str.txt | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfs/lib/str.fs | 38++++++--------------------------------
Mfs/tests/lib/str.fs | 6++----
3 files changed, 75 insertions(+), 36 deletions(-)

diff --git a/fs/doc/lib/str.txt b/fs/doc/lib/str.txt @@ -0,0 +1,67 @@ +# String utilities + +This unit lives at /lib/str.fs and provides a few string-related words. + +Most strings in Dusk are regular strings as doc/usage describes. However, we +sometimes have to deal with null-terminated strings and this unit also has words +to deal with them. We refer to null-terminated strings as "zstr" (z for zero). + +This unit also defines the concept of "string lists". Those are simply strings +following each other in memory, ending with a null string. To iterate a string +list, all we need to do is "skip" the string using its size byte. + +## API + +Constants: + +STR_MAXSZ Maximum size of strings, including size byte +NULLSTR An empty string + +Words: + +ws? ( c -- f ) + Returns whether character "c" is a whitespace. + +s) ( str -- a ) + Skip "str", that is, return the address following its last char. + +s, ( str -- ) + Write "str" to here. + +s[]= ( str a u -- f ) + Compares a string to a range. + +zstrlen ( ztr -- len ) + Returns the length of "zstr". + +sfind ( str list -- idx ) + Find "str" in "list" and return its index, -1 if not found. + +slistiter ( idx list -- str ) + Given a string list "list", iterate to its "idx" element and return the str. + +rmatch ( c range -- f ) + Given a list of character ranges, which is given in the form of a string of + character pairs, return whether the specified character is in one of the + ranges. + +0-9? ( c -- f ) + Returns whether "c" is a digit. + +A-Za-z? ( c -- f ) + Returns whether "c" is an ASCII letter. + +alnum? ( c -- f ) + Returns whether "c" is a letter or digit. + +toword ( -- c ) + Read stdin until next non WS and yield it. + +expectchar ( c -- ) + Read stdin, discarding whitespaces and expect the next char to be "c" + +stringlist ( n "name" "..." -- ) + Create a list of strings (same format as sfind above) with the specified + number of elements. Each element must be "quoted" with no space (unless you + want them in the string) in the quotes. +\ Example: 3 stringlist mylist "foo" "bar" "hello world!" diff --git a/fs/lib/str.fs b/fs/lib/str.fs @@ -1,51 +1,31 @@ \ String/range utilities -\\ maximum size of strings (including size byte) $100 value STR_MAXSZ create NULLSTR 0 c, -\ is c a whitespace? : ws? ( c -- f ) SPC <= ; -\ "skip" str, that is, return the address following its last char : s) ( str -- a ) c@+ + ; -\ write "str" to here : s, ( str -- ) dup c@ 1+ move, ; -\ compare a string to a range -: s[]= ( str a len -- f ) +: s[]= ( str a u -- f ) rot dup c@ rot = if ( a str ) c@+ []= else 2drop 0 then ; -\ null-terminated strings (zstr) routines : zstrlen ( zstr -- len ) 0 swap $100 [c]? ( idx ) dup 0< if abort" string too long" then ; -\\ append character to end of string -: sappend ( c str -- ) tuck s) c! dup c@ 1+ swap c! ; +: [str]? ( str a u -- idx ) rot> >r >r ( u ) \ V1=aref V2=str + V2 c@ - dup 0>= if 1+ >r V1 begin ( a ) + dup V2 c@+ []= if ( a ) rdrop rdrop r> - exit then 1+ next ( a ) + else drop then ( a ) + drop rdrop rdrop -1 ; -\\ checks if str1 contains all of str2 (is str2 a substring?) -: scontains ( str1 str2 -- f ) - >r c@+ begin - dup r@ c@ >= while - over r@ c@+ []= if - r> drop 2drop 1 exit - then - 1- swap 1+ swap - repeat r> drop 2drop 0 ; - -\ find active string in "list" and return its index, -1 if not found. -\ A list is a simple sequence of strings (length byte, then contents, then -\ another one...) ended by a 0 length : sfind ( str list -- idx ) -1 rot> begin ( idx s a ) rot 1+ rot> ( idx s a ) 2dup s= if ( found ) 2drop exit then s) dup c@ not until ( idx s a ) 2drop drop -1 ; -\ Given a string list "list", iterate to its "idx" element and return the str. : slistiter ( idx list -- str ) swap dup if >r begin s) next else drop then ; -\ Given a list of character ranges, which is given in the form of a string of -\ character pairs, return whether the specified character is in one of the -\ ranges. : rmatch ( c range -- f ) >r 8b to@+ V1 >> ( len/2 ) >r begin ( c ) dup 8b to@+ V1 8b to@+ V1 ( c c lo hi ) =><= if @@ -59,15 +39,9 @@ create _ 4 c, ," AZaz" create _ 6 c, ," AZaz09" : alnum? ( c -- f ) _ rmatch ; -\\ Read stdin until next non WS and yield it : toword ( -- c ) begin stdin dup ws? while drop repeat ( c ) ; -\\ Read stdin, discarding whitespaces and expect the next char to be "c" : expectchar ( c -- ) toword over = not if emit abort" expected" else drop then ; -\ Create a list of strings (same format as sfind above) with the specified -\ number of elements. Each element must be "quoted" with no space (unless you -\ want them in the string) in the quotes. -\ Example: 3 stringlist mylist "foo" "bar" "hello world!" : stringlist create >r begin '"' expectchar [compile] S" drop next 0 c, ; diff --git a/fs/tests/lib/str.fs b/fs/tests/lib/str.fs @@ -16,8 +16,6 @@ S" baz" list sfind -1 #eq 'z' alnum? # '0' alnum? # -S" foobar" S" foo" scontains # -S" foobar" S" bar" scontains # -S" foobar" S" oba" scontains # -S" foobar" S" baz" scontains not # +S" bar" S" foobar" c@+ [str]? 3 #eq +S" baz" S" foobar" c@+ [str]? -1 #eq testend