Archive: String arrays, sort of


String arrays, sort of
Several times, I've wanted to do the same body of script code, just changing one string. Without some sort of string array, I've just made the body a function and called it several times.

It finally occurred to me, looking at StrStr, that if I just had a special delimiter character, I could get the same effect by separating the string elements with that delimiter. So here's an implementation using "$\n" as the delimiter. I hope someone finds it useful:

-------- PerLine.nsh


!include LogicLib.nsh

;;;;;;;
;
; global vars for loop
;
var /global PerLineArray
var /global PerLineCount
var /global PerLineChars

!macro _PerLine lineArray loopVar
StrCpy $PerLineArray ${lineArray}
StrLen $PerLineChars $PerLineArray
StrCpy $PerLineCount 1
${DoWhile} $PerLineChars > 1
Push $PerLineArray
Call leadingLine
Pop ${loopVar}
Push $r0
StrLen $r0 ${loopVar}
IntOp $r0 $r0 + 1
StrCpy $PerLineArray $PerLineArray "" $r0
Pop $r0
StrLen $PerLineChars $PerLineArray
!macroend
!define PerLine `!insertmacro _PerLine`

;;;;;;;;;;
;
; usage, for example:
;
; StrCpy $1 1 ; line number
; StrCpy $2 "" ; accumulating message
; ${PerLine} "line1$\nline2$\n$line3" $line
; ; body does something with $line 3 times
; StrCpy $2 "$2$\n$1 - $line"
; IntOp $1 $1 + 1
; ${Loop}
; MessageBox MB_OK $2
;

;;;;;;;;;;
;
; helper function to strip off leading line
;
Function LeadingLine
; input - top of stack contains string, possibly containing "$\n"
; output - top of stack contains string up to 1st "$\n"
; r0 - working copy of input & result
; r1 - char index
; r2 - length of input
; r3 - nth char of input
Exch $r0
Push $r1
Push $r2
Push $r3
StrCpy $r1 0
StrLen $r2 $r0
_leadLoop:
IntCmp $r1 $r2 _leadDone
StrCpy $r3 $r0 1 $r1
StrCmp $r3 "$\n" _leadDone
IntOp $r1 $r1 + 1
Goto _leadLoop

_leadDone:
StrCpy $r0 $r0 $r1
Pop $r3
Pop $r2
Pop $r1
Exch $r0

FunctionEnd

This is one way but it is much easier (and cleaner) to use a plug-in (such as NSISArray) or use INI files/registry to store multiple values (i.e. by index or value name). You do not need to worry about the delimiter being in your array elements then.

Stu