Files
cc65/libsrc/common/strndup.s
Colin Leroy-Mira 6604c5ce92 Make strndup smaller, safer, faster
First implementation was doing:
- strdup (without checking result!)
- strlen
- terminate
- realloc

New one does:
- malloc to shortest +1
- strncpy
- terminate
2025-07-05 12:11:40 +02:00

54 lines
1.4 KiB
ArmAsm

;
; Colin Leroy-Mira, 03.07.2025
;
; char* __fastcall__ strndup (const char* S, size_t maxlen);
;
.importzp tmp1, tmp2, ptr2
.import _strncpy, _strlen, _malloc
.import pushax, popax, incsp2, incax1, swapstk
.import ___errno
.export _strndup
.include "errno.inc"
.proc _strndup
sta tmp1 ; Remember maxlen
stx tmp1+1
jsr popax ; Get string
jsr pushax ; Keep it in TOS
jsr _strlen ; Get string length,
cpx tmp1+1 ; Compare to max,
bcc alloc
bne :+
cmp tmp1
bcc alloc
: lda tmp1 ; Use maxlen if shorter
ldx tmp1+1
alloc: jsr incax1 ; Add 1 for terminator
jsr _malloc ; Allocate output
cpx #$00 ; Check allocation
beq errmem
jsr swapstk ; Put dest in TOS and get string back
jsr pushax ; Put src in TOS
lda tmp1 ; Get length for strncpy
ldx tmp1+1
jsr _strncpy ; Copy
pha ; Terminate
lda #$00
sta (ptr2),y
pla
rts
errmem: ldy #ENOMEM
sty ___errno
jmp incsp2 ; Pop string and return
.endproc