4cade/src/parse.common.a
2020-03-24 16:30:14 -04:00

138 lines
4.2 KiB
Plaintext

;license:MIT
;(c) 2018-9 by 4am
;
; generic key/value text parser
;
; Public functions:
; - ParseKeyValueList
; - IncAndGetChar
;
;------------------------------------------------------------------------------
; ParseKeyValueList
; parse buffer with KEY=VALUE lines of a text file into an okvs
; keys and values limited to 127 characters, which should be enough for anyone
; if '=' is missing, key is kept and value is a 0-length string
; blank lines are ignored
; '#' character at beginning of line is a comment, entire line is ignored
; '[' character at beginning of line exits the parser
;
; in: stack contains 5 bytes of parameters:
; +1 [word] handle to storage space for okvs
; +3 [word] handle to buffer containing contents of text file
; +5 [byte] max length for okvs records (or 0)
; out: all registers and flags clobbered
; $1F00..$1FFF clobbered
; $00/$01 clobbered
; $02/$03 clobbered
; $04/$05 has the address of the next available byte after the okvs
; $FE/$FF clobbered
;------------------------------------------------------------------------------
ParseKeyValueList
+PARAMS_ON_STACK 5
+LDPARAM 1
+ST16 @store2
jsr SetKeyPtr
ldy #5
lda (PARAM),y
sta @maxLength
ldy #$00 ; index into ($FE) pointing to current character
@newkey ldx #$00 ; X = index into current key
stx gValLen ; initialize value length (in case this line has no value)
beq @emptyline ; always branches
@skipLine ; skip to CR
jsr IncAndGetChar
cmp #$0A ; CR
bne @skipLine
@emptyline
jsr IncAndGetChar
cmp #$0A ; CR in first position (blank line) -> no key
beq @emptyline
cmp #$23 ; '#' starts a comment -> no key, skip to CR
beq @skipLine
cmp #$5B ; '[' ends the parsing
beq .parseKeyValueDone
bne @appendToKey
@gatherKey
jsr IncAndGetChar
cmp #$0A ; CR -> finalize key, no value
beq @finalizeKey
cmp #$3D ; '=' -> finalize key, start gathering value
beq @finalizeKey
@appendToKey
sta gKey,x
inx
bpl @gatherKey
@finalizeKey
stx gKeyLen
cmp #$0A
beq @storeInOKVS
ldx #$00 ; now X = index into the current value
@gatherValue
jsr IncAndGetChar
cmp #$0A ; CR -> finalize value
beq @finalizeValue
sta gVal,x
inx
bpl @gatherValue
@finalizeValue
stx gValLen
@storeInOKVS
tya
pha ; okvs functions clobber everything but we need Y
jsr okvs_append
@store2 !word $FDFD ; SMC
!word gKeyLen
!word gValLen
@maxLength
!byte $FD ; SMC
pla
tay
clc
bcc @newkey ; always branches
;------------------------------------------------------------------------------
; SetKeyPtr
;
; in: PARAM set
; out: okvs initialised
; ($FE) -> buffer
;------------------------------------------------------------------------------
SetKeyPtr
jsr okvs_init ; reset key/value store
+LDPARAMPTR 3, $FE
ldy #0
lda ($FE),y
tax
bne +
iny
lda ($FE),y
sta $FF
dec $FF
+ dex
stx $FE
rts
;------------------------------------------------------------------------------
; IncAndGetChar
;
; in: Y = index into ($FE)
; ($FE) -> buffer
; out: A contains next byte from buffer
; Y incremented
; $FF possibly incremented
;------------------------------------------------------------------------------
IncAndGetChar
iny
bne +
inc $FF
+ lda ($FE),y
cmp #$0D ; CR - hide it
beq IncAndGetChar
.parseKeyValueDone
rts