added string.rfind()

This commit is contained in:
Irmen de Jong 2024-08-22 22:54:38 +02:00
parent 8f6eaeac2c
commit b566ea5c3f
5 changed files with 89 additions and 43 deletions

View File

@ -13,6 +13,7 @@
; NOTE: For sake of speed, NO BOUNDS CHECKING is performed in most routines! ; NOTE: For sake of speed, NO BOUNDS CHECKING is performed in most routines!
; You'll have to make sure yourself that you're not writing outside of bitmap boundaries! ; You'll have to make sure yourself that you're not writing outside of bitmap boundaries!
; ;
; NOTE: the bitmap screen data is positioned in vram at $0:0000
; ;
; SCREEN MODE LIST: ; SCREEN MODE LIST:
; mode 0 = reset back to default text mode ; mode 0 = reset back to default text mode

View File

@ -134,11 +134,11 @@ _startloop dey
; need to copy the the cx16 virtual registers to zeropage to make this run on C64... ; need to copy the the cx16 virtual registers to zeropage to make this run on C64...
sta P8ZP_SCRATCH_W1 sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1 sty P8ZP_SCRATCH_W1+1
stx P8ZP_SCRATCH_B1 stx _comparemod+1
ldy #0 ldy #0
- lda (P8ZP_SCRATCH_W1),y - lda (P8ZP_SCRATCH_W1),y
beq _notfound beq _notfound
cmp P8ZP_SCRATCH_B1 _comparemod cmp #0 ; modified
beq _found beq _found
iny iny
bne - bne -
@ -151,6 +151,37 @@ _found tya
}} }}
} }
asmsub rfind(uword string @AY, ubyte character @X) -> ubyte @A, bool @Pc {
; Locates the first position of the given character in the string, starting from the right.
; returns Carry set if found + index in A, or Carry clear if not found (and A will be 255, an invalid index).
%asm {{
stx _comparemod+1
sta _str
sty _str+1
jsr string.length
dey
lda _str
sta P8ZP_SCRATCH_W1
lda _str+1
sta P8ZP_SCRATCH_W1+1
- lda (P8ZP_SCRATCH_W1),y
_comparemod cmp #0 ; modified
beq _found
dey
cpy #255
bne -
_notfound lda #255
clc
rts
_found tya
sec
rts
_str .word 0
}}
}
asmsub contains(uword string @AY, ubyte character @X) -> bool @Pc { asmsub contains(uword string @AY, ubyte character @X) -> bool @Pc {
; Just return true/false if the character is in the given string or not. ; Just return true/false if the character is in the given string or not.
%asm {{ %asm {{

View File

@ -68,6 +68,21 @@ string {
return 255 return 255
} }
sub rfind(uword stringptr, ubyte character) -> ubyte {
; Locates the first position of the given character in the string, starting from the right.
; returns Carry set if found + index in A, or Carry clear if not found (and A will be 255, an invalid index).
; NOTE: because this isn't an asmsub, there's only a SINGLE return value here. On the c64/cx16 targets etc there are 2 return values.
ubyte ix
for ix in string.length(stringptr)-1 downto 0 {
if stringptr[ix]==character {
sys.set_carry()
return ix
}
}
sys.clear_carry()
return 255
}
sub contains(str st, ubyte character) -> bool { sub contains(str st, ubyte character) -> bool {
void find(st, character) void find(st, character)
if_cs if_cs

View File

@ -483,14 +483,15 @@ Provides string manipulation routines.
Also, you have to make sure yourself that start and length are within bounds of the strings. Also, you have to make sure yourself that start and length are within bounds of the strings.
Modifies in-place, doesn't return a value (so can't be used in an expression). Modifies in-place, doesn't return a value (so can't be used in an expression).
``find (string, char) -> ubyte index + carry bit`` ``find (string, char) -> ubyte index, bool found``
Locates the first position of the given character in the string, returns carry bit set if found Locates the first index of the given character in the string, and a boolean (in Carry flag)
and the index in the string. Or 0+carry bit clear if the character was not found. to say if it was found at all. If the character is not found, index 255 (and false) is returned.
You can consider this a safer way of checking if a character occurs You can consider this a safer way of checking if a character occurs
in a string than using an `in` containment check - because the find routine in a string than using an `in` containment check - because this find routine
properly stops at the first 0-byte string terminator it encounters. properly stops at the first 0-byte string terminator it encounters in case the string was modified.
Simply call this and only act on the carry status with ``if_cc`` for example.
Much like the difference between len(str) and length(str). ``rfind (string, char) -> ubyte index, bool found``
Like ``find``, but now looking from the *right* of the string instead.
``contains (string, char) -> bool`` ``contains (string, char) -> bool``
Just returns true if the character is in the given string, or false if it's not. Just returns true if the character is in the given string, or false if it's not.

View File

@ -1,48 +1,46 @@
%import textio %import textio
%import string
%option no_sysinit %option no_sysinit
%zeropage basicsafe %zeropage basicsafe
main { main {
sub start() { sub start() {
ubyte @shared v1,v2,v3 str name = "zn.iff.jpg"
v1 = %10011001
v2 = %10101010
v3 = %00111100
v1 &= %00011111 ubyte index
v1++ bool found
txt.print_ubbin(v1, true)
txt.nl()
v1 &= ~v2 index, found = string.find(name, '.')
v1++ if found {
txt.print_ubbin(v1, true) txt.print_ub(index)
txt.nl() txt.nl()
} else {
txt.print(". not found\n")
}
v1 |= 100 index, found = string.find(name, '@')
v1++ if found {
txt.print_ubbin(v1, true) txt.print_ub(index)
txt.nl() txt.nl()
} else {
txt.print("@ not found\n")
}
v1 |= v2 index, found = string.rfind(name, '.')
v1++ if found {
txt.print_ubbin(v1, true) txt.print_ub(index)
txt.nl() txt.nl()
} else {
txt.print(". not r found\n")
}
v1 |= v2 & v3 index, found = string.rfind(name, '@')
v1++ if found {
txt.print_ubbin(v1, true) txt.print_ub(index)
txt.nl()
v1 &= v2|v3
v1++
txt.print_ubbin(v1, true)
txt.nl()
v1 &= ~(v2|v3)
v1++
txt.print_ubbin(v1, true)
txt.nl() txt.nl()
} else {
txt.print("@ not r found\n")
}
} }
} }