Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add strings.ncompare (and backing strncmp_mem) to compare up to n characters of a string. #164

Merged
merged 2 commits into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions compiler/res/prog8lib/prog8_lib.asm
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,34 @@ _c1_zero lda (P8ZP_SCRATCH_W2),y
+ rts
.pend

strncmp_mem .proc
; -- compares strings in s1 (AY) and s2 (P8ZP_SCRATCH_W2).
; Compares up to maximum length specified in X.
; Returns -1,0,1 in A, depending on the ordering. Clobbers X & Y.
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
_loop lda (P8ZP_SCRATCH_W1),y
beq _c1_zero
cmp (P8ZP_SCRATCH_W2),y
beq _equal
bmi _less
lda #1
rts
_less lda #-1
rts
_equal dex
bne +
lda #0
rts
+ iny
bne _loop
_c1_zero lda (P8ZP_SCRATCH_W2),y
beq +
lda #-1
+ rts
.pend


strlen .proc
; -- returns the number of bytes in the string in AY, in Y. Clobbers A.
Expand Down
13 changes: 13 additions & 0 deletions compiler/res/prog8lib/strings.p8
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,19 @@ _str .word 0
}}
}

asmsub ncompare(uword string1 @R0, uword string2 @AY, ubyte length @X) clobbers(X, Y) -> byte @A {
; Compares two strings for sorting.
; Returns -1 (255), 0 or 1, meaning: string1 sorts before, equal or after string2.
; Only compares the strings from index 0 up to the length argument.
%asm {{
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
lda cx16.r0
ldy cx16.r0+1
jmp prog8_lib.strncmp_mem
}}
}

asmsub lower(uword st @AY) -> ubyte @Y {
; Lowercases the petscii string in-place. Returns length of the string.
; (for efficiency, non-letter characters > 128 will also not be left intact,
Expand Down
7 changes: 7 additions & 0 deletions compiler/test/comparisons/more_compares.p8
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ main {
txt.print("name2 fail!\n")
}

if (strings.ncompare(name, "aaa", 3)==0) or (strings.compare(name, "johm", 3)==0) or (strings.compare(name, "bbb", 3)==0) {
txt.print("name1 ok\n")
}
if (strings.ncompare(name, "aaa", 2)==0) or (strings.ncompare(name, "zzz", 2)==0) or (strings.ncompare(name, "bbb", 2)==0) {
txt.print("name2 fail!\n")
}

if name=="aaa" or name=="john" or name=="bbb"
txt.print("name1b ok\n")
if name=="aaa" or name=="zzz" or name=="bbb"
Expand Down
6 changes: 6 additions & 0 deletions docs/source/libraries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,12 @@ Provides string manipulation routines.
using ``==``, ``<`` etcetera (it will use strings.compare for you under water automatically).
This even works when dealing with uword (pointer) variables when comparing them to a string type.

``ncompare (string1, string2, length) -> ubyte result``
Compares two strings up to the number of characters in the length parameter.
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
Note that lengths of 0 or 1 evaluate the same. The first character is always compared.
A length larger than either string will function identically to compare.

``copy (from, to) -> ubyte length``
Copy a string to another, overwriting that one. Returns the length of the string that was copied.
Often you don't have to call this explicitly and can just write ``string1 = string2``
Expand Down
2 changes: 1 addition & 1 deletion syntax-files/SublimeText/Prog8.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ contexts:
- match: (\b(const)\b)
scope: storage.modifier.prog8
support:
- match: (\b(abs|atan|ceil|cos|cos8u|cos8|cos16u|cos16|deg|floor|ln|log2|rad|round|sin|sgn|sin8u|sin8|sin16u|sin16|sqrt16|sqrt|tan|any|all|len|max|min|reverse|sum|sort|memcopy|memset|memsetw|leftstr|rightstr|strlen|strcmp|substr|exit|lsb|msb|lsw|msw|mkword|rnd|rndw|rndf|rol|rol2|ror|ror2|rsave|rrestore|read_flags|sizeof|set_carry|clear_carry|set_irqd|clear_irqd|swap)\b)
- match: (\b(abs|atan|ceil|cos|cos8u|cos8|cos16u|cos16|deg|floor|ln|log2|rad|round|sin|sgn|sin8u|sin8|sin16u|sin16|sqrt16|sqrt|tan|any|all|len|max|min|reverse|sum|sort|memcopy|memset|memsetw|leftstr|rightstr|strlen|strcmp|strncmp|substr|exit|lsb|msb|lsw|msw|mkword|rnd|rndw|rndf|rol|rol2|ror|ror2|rsave|rrestore|read_flags|sizeof|set_carry|clear_carry|set_irqd|clear_irqd|swap)\b)
scope: support.function.prog8
variable:
- match: (\b\w+\b)
Expand Down
1 change: 1 addition & 0 deletions syntax-files/Vim/prog8_builtins.vim
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ syn match prog8BuiltInFunc "\<strings\.contains\>"
syn match prog8BuiltInFunc "\<strings\.copy\>"
syn match prog8BuiltInFunc "\<strings\.append\>"
syn match prog8BuiltInFunc "\<strings\.compare\>"
syn match prog8BuiltInFunc "\<strings\.ncompare\>"
syn match prog8BuiltInFunc "\<strings\.lower\>"
syn match prog8BuiltInFunc "\<strings\.lowerchar\>"
syn match prog8BuiltInFunc "\<strings\.upper\>"
Expand Down