A different approach. Convert native string array to string buffer of user-defined encoding.
Code: Select all
CompilerIf #PB_Compiler_Unicode = 0
MessageRequester("try-uni-Array-utf8-mem", "Requires #PB_Compiler_Unicode." + #CRLF$ +
"PB v5.4+ is dropping Ascii compiler switch." + #CRLF$, #MB_ICONWARNING)
End
CompilerEndIf
EnableExplicit
Procedure.i JoinToMem(*nBytes.Integer, Array A$(1), Delm$=#Empty$, iStart.i=0, iStop.i=-1, Enc.i=#PB_Ascii)
; REV: 151207, skywalk
; Spinoff of Join() which returns a concatenated native PB string(Unicode only).
; RETURN:
; *s = String buffer concatenated from A$() in user-defined encoding(Enc).
; nBytes = num bytes within string buffer. *s contains Chr(0)'s so cannot use Len(PeekS(*s,-1,Enc))
; NOTES:
; Delm$ Action
; #Empty$ OK to write Chr(0) after each element.
; #Null$ Set #PB_String_NoZero and add nothing between elements.
; > 0 Set #PB_String_NoZero and only add Delm$ between elements.
Protected.i i, k, npb, nBytes, lenbEOS, *p, *s
Protected.i PokeNoZero = #PB_String_NoZero
Protected.s r$
If iStart < 0
iStart = 0
EndIf
If iStop < 0
k = ArraySize(A$())
iStop = k
Else
If iStart >= iStop
iStop = iStart
k = iStop - iStart
Else
k = iStop - iStart + 1
EndIf
EndIf
; Determine nBytes required to hold string array contents
For i = iStart To iStop
nBytes + StringByteLength(A$(i), Enc)
Next i
If Delm$
nBytes + k * StringByteLength(Delm$, Enc) ; Add room for delimiters
EndIf
If @Delm$ And Len(Delm$) < 1 ; Delm$ has an address so allow PokeZero
PokeNoZero = 0
If Enc <> #PB_Unicode ; Set Size(bytes) of trailing nullchar in user defined encoding.
lenbEOS = 1
Else
lenbEOS = 2
EndIf
nBytes + k * lenbEOS ; Account for nullchar delimiters + 1 trailer.
EndIf
*s = AllocateMemory(nBytes+lenbEOS)
If *s
If nBytes <= MemorySize(*s) ; Verify enough memory created
*p = *s ; Create tracking pointer for concatenating memory
If Delm$
npb = PokeS(*p, A$(iStart), -1, Enc | PokeNoZero)
*p + npb + lenbEOS
If k > 0
npb = PokeS(*p, Delm$, -1, Enc | PokeNoZero)
*p + npb + lenbEOS
k = iStop - 1 ; Avoid recalculating k-1 in For-Next loop
For i = iStart + 1 To k
npb = PokeS(*p, A$(i), -1, Enc | PokeNoZero)
*p + npb + lenbEOS
npb = PokeS(*p, Delm$, -1, Enc | PokeNoZero)
*p + npb + lenbEOS
Next i
npb = PokeS(*p, A$(i), -1, Enc | PokeNoZero)
EndIf
Else
npb = PokeS(*p, A$(iStart), -1, Enc | PokeNoZero)
*p + npb + lenbEOS
If k > 0
For i = iStart + 1 To iStop
npb = PokeS(*p, A$(i), -1, Enc | PokeNoZero)
*p + npb + lenbEOS
Next i
EndIf
EndIf
;FreeMemory(*s) ; Not now, but remember to free memory when done.
EndIf
EndIf
If *nBytes ; Avoid null pointer.
*nBytes\i = nBytes ; Buffer contains 0's so <> Len(PeekS(*s,-1,Enc))
EndIf
ProcedureReturn *s
EndProcedure
;-{ TEST
#NUL$ = #Empty$
#SP$ = " "
#CMA$ = ","
Define.i i, *s, nBytes, Enc, nPts = 5
Define.s s$
Dim a$(nPts-1)
a$(0) = "000011112222333344445555666677778888"
a$(1) = "Huber"
a$(2) = "Völler"
a$(3) = "Müller"
a$(4) = "Šimûnek"
Enc = #PB_UTF8
;Enc = #PB_Ascii
;Enc = #PB_Unicode
*s = JoinToMem(@nBytes, a$(), #CMA$, 0, -1, Enc)
ShowMemoryViewer(*s, nBytes)
Debug PeekS(*s+nBytes-2, 1, Enc)
FreeMemory(*s)
*s = JoinToMem(@nBytes, a$(), #Null$, 0, -1, Enc)
ShowMemoryViewer(*s, nBytes)
Debug PeekS(*s+nBytes-2, 1, Enc)
FreeMemory(*s)
*s = JoinToMem(@nBytes, a$(), #NUL$, 0, -1, Enc)
ShowMemoryViewer(*s, nBytes)
Debug PeekS(*s+nBytes-2, 1, Enc)
FreeMemory(*s)
;-} TEST