add strings.ncopy and nappend (length limited)

This commit is contained in:
Irmen de Jong
2025-10-31 21:22:15 +01:00
parent b02a8ed954
commit 0cd8c4f87e
8 changed files with 123 additions and 26 deletions

View File

@@ -266,6 +266,25 @@ strcpy .proc
rts
.pend
strncpy .proc
; copy a string (must be 0-terminated) from A/Y to (P8ZP_SCRATCH_W1)
; with maximum length to copy in X.
; returns the length of the string that was copied in Y.
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
ldy #$ff
- iny
lda (P8ZP_SCRATCH_W2),y
sta (P8ZP_SCRATCH_W1),y
beq +
dex
bne -
iny
lda #0
sta (P8ZP_SCRATCH_W1),y
+ rts
.pend
strcmp_expression .proc
; -- compare strings, result in A
lda _arg_s2

View File

@@ -222,6 +222,18 @@ _found tya
}}
}
asmsub ncopy(str source @R0, str target @AY, ubyte maxlength @X) clobbers(A, X) -> ubyte @Y {
; Copy a string to another, overwriting that one.
; Returns the length of the string that was copied.
%asm {{
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda cx16.r0
ldy cx16.r0+1
jmp prog8_lib.strncpy
}}
}
asmsub append(str target @R0, str suffix @R1) clobbers(Y) -> ubyte @A {
; Append the suffix string to the target. (make sure the buffer is large enough!)
; Returns the length of the resulting string.
@@ -247,6 +259,41 @@ _found tya
}}
}
asmsub nappend(str target @R0, str suffix @R1, ubyte maxlength @X) clobbers(Y) -> ubyte @A {
; Append the suffix string to the target. (make sure the buffer is large enough!)
; Returns the length of the resulting string.
%asm {{
lda cx16.r0
ldy cx16.r0+1
jsr length
sty P8ZP_SCRATCH_B1
cpx P8ZP_SCRATCH_B1
beq _max_too_small
bmi _max_too_small
txa
sec
sbc P8ZP_SCRATCH_B1
sta P8ZP_SCRATCH_B1
tya
clc
adc cx16.r0
sta P8ZP_SCRATCH_W1
lda cx16.r0+1
adc #0
sta P8ZP_SCRATCH_W1+1
lda cx16.r1
ldy cx16.r1+1
ldx P8ZP_SCRATCH_B1
jsr prog8_lib.strncpy
tya
clc
adc P8ZP_SCRATCH_B1
rts
_max_too_small
rts
}}
}
asmsub compare(str string1 @R0, str string2 @AY) clobbers(Y) -> byte @A {
; Compares two strings for sorting.
; Returns -1 (255), 0 or 1, meaning: string1 sorts before, equal or after string2.

View File

@@ -109,7 +109,20 @@ strings {
%ir {{
loadm.w r99000,strings.copy.source
loadm.w r99001,strings.copy.target
syscall 39 (r99000.w, r99001.w): r99100.b
load.b r99100,255
syscall 39 (r99000.w, r99001.w, r99100.b): r99100.b
returnr.b r99100
}}
}
sub ncopy(str source, str target, ubyte maxlength) -> ubyte {
; Copy a string to another, overwriting that one, but limited to the given length.
; Returns the length of the string that was copied.
%ir {{
loadm.w r99000,strings.ncopy.source
loadm.w r99001,strings.ncopy.target
loadm.b r99100,strings.ncopy.maxlength
syscall 39 (r99000.w, r99001.w, r99100.b): r99100.b
returnr.b r99100
}}
}
@@ -121,6 +134,16 @@ strings {
return copy(suffix, target+cx16.r0L) + cx16.r0L
}
sub nappend(str target, str suffix, ubyte maxlength) -> ubyte {
; Append the suffix string to the target, up to the given maximum length of the combined string.
; Returns the length of the resulting string.
cx16.r0L = length(target)
if maxlength<cx16.r0L
return cx16.r0L
maxlength -= cx16.r0L
return ncopy(suffix, target+cx16.r0L, maxlength) + cx16.r0L
}
sub compare(str st1, str st2) -> byte {
; Compares two strings for sorting.
; Returns -1 (255), 0 or 1, meaning: string1 sorts before, equal or after string2.

View File

@@ -53,7 +53,8 @@ sys {
%ir {{
loadm.w r99000,sys.internal_stringcopy.source
loadm.w r99001,sys.internal_stringcopy.tgt
syscall 39 (r99000.w, r99001.w): r99100.b
load.b r99100,255
syscall 39 (r99000.w, r99001.w, r99100.b): r99100.b
}}
}

View File

@@ -996,10 +996,19 @@ Provides string manipulation routines.
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.
Copy a string to another, overwriting that one. Make sure it was large enough to contain the new string.
Returns the length of the string that was copied.
``ncopy (from, to, maxlength) -> ubyte length``
Copy a string to another, overwriting that one, but limited to the given length.
Returns the length of the string that was copied.
``append (string, suffix) -> ubyte length``
Appends the suffix string to the other string (make sure the memory buffer is large enough!)
Appends the suffix string to the other string. Make sure the memory buffer is large enough to contain the combined strings.
Returns the length of the combined string.
``nappend (string, suffix, maxlength) -> ubyte length``
Appends the suffix string to the other string, up to the given maximum length of the combined string.
Returns the length of the combined string.
``lower (string)``

View File

@@ -1,7 +1,6 @@
TODO
====
- add strings.ncopy and nappend (length limited)
- fix/check github issues.
- docs: sort the routines in the library chapter alphabetically
- redo the benchmark-c tests with final 12.0 release version.

View File

@@ -1,26 +1,25 @@
%import textio
%import strings
%zeropage basicsafe
main {
struct Node1 {
ubyte type
word ww
}
struct Node2 {
ubyte type
^^ubyte text
}
sub start() {
^^Node1 @shared next
^^Node2 @shared this
^^ubyte ubptr
str n1 = "irmen"
str n2 = "de jong 12345678"
ubptr = next as ^^ubyte
ubptr = 12345
ubptr = cx16.r0
ubptr = next as uword ; TODO fix type error; the cast should succeed
;;strings.copy(n2,n1)
strings.ncopy(n2,n1,len(n1))
txt.print(n1)
txt.nl()
this.text = next as ^^ubyte
this.text = 12345
this.text = cx16.r0
this.text = next as uword ; TODO fix type error; the cast should succeed
n2[9]=0
txt.print(n2)
txt.nl()
strings.nappend(n2, "the quick brown fox jumps over", 16)
txt.print(n2)
txt.nl()
txt.print("12345678901234567890\n")
}
}

View File

@@ -510,10 +510,10 @@ object SysCalls {
}
}
Syscall.STRINGCOPY -> {
val (sourceA, targetA) = getArgValues(callspec.arguments, vm)
val (sourceA, targetA, maxlength) = getArgValues(callspec.arguments, vm)
val source = (sourceA as UShort).toInt()
val target = (targetA as UShort).toInt()
val string = vm.memory.getString(source)
val string = vm.memory.getString(source).take((maxlength as UByte).toInt())
vm.memory.setString(target, string, true)
returnValue(callspec.returns.single(), string.length, vm)
}