I have some string vector data that is read from an external file at compile time. I have found the need to move the data at run time to another array in RAM. I know I can get the address of the first item in the array, but I am unsure at to how I can assign the data to a RAM array.
Along the same line of thought, what marks the beginning or end of an array item for string vector data? I am assuming that each indices can be a different length, and if so, is there a specific character that denotes the beginning of a new index?
-Don
Initializing an array with vector data
Re: Initializing an array with vector data
For a single-dimension array (other than string types), you can just copy the data from ProgramMemory to RAM using GetProgMem. For multi-dimension arrays and string types, you'll have to copy the data element-by-element. The reason that multi-dimension arrays are an issue is that the row/column order is different between RAM-based and Program Memory-based arrays. For string type arrays, you can economize on RAM use by using the ProgMem string type along with the string's address in Program Memory. An example program for doing this appears below.Don_Kirby wrote:I know I can get the address of the first item in the array, but I am unsure at to how I can assign the data to a RAM array.
Because the strings can be of different lengths, a StringVectorData item is compiled to an index table followed by the individual strings as illustrated below.Don_Kirby wrote:what marks the beginning or end of an array item for string vector data?
ZBasic Code:
Code: Select all
Dim strData as StringVectorData ({ "able", "baker", "charlie" })
Code: Select all
Dim strData as StringVectorData ({ "able", "baker", "charlie" })
0029 41 prg:strData (28 bytes, 3 entries)
0029 2f 00 35 00 3c 00 04 00 61 62 6c 65 05 00 62 61
0039 6b 65 72 07 00 63 68 61 72 6c 69 65
This example code populates a RAM-based string array with data from a ProgMem-based string array. See Section 3.26.2 of the ZBasic Reference Manual for details on string implementation.
Code: Select all
Dim strData as StringVectorData ({ "able", "baker", "charlie" })
Dim strArray(1 to UBound(strData)) as String
Sub Main()
Call copyStrings(strArray, UBound(strArray), strData.DataAddress)
Dim i as Integer
For i = 1 to UBound(strArray)
Debug.Print strArray(i)
Next i
Debug.Print "Done"
End Sub
Sub copyStrings(ByRef sa() as String, ByVal cnt as Integer, ByVal progMemAddr as Long)
Const ProgMemStrType as Byte = &He2
Structure zxString
Dim strLen as Byte
Dim strType as Byte
Dim strAddr as UnsignedInteger
End Structure
Dim i as Integer
Dim strAddr as UnsignedInteger
strAddr = sa.DataAddress
For i = 1 to cnt
Dim addr as UnsignedInteger
Dim zxStr as zxString Based strAddr
Dim strLen as Byte
' get the address of the string element, read the string length
Call GetProgMem(progMemAddr, addr, 2)
Call GetProgMem(CLng(addr), strLen, 1)
' copy the string data to the RAM-based array
zxStr.strLen = strLen
zxStr.strType = ProgMemStrType
zxStr.strAddr = addr + 2
' advance the addresses for the next pass
strAddr = strAddr + CUint(SizeOf(zxStr))
progMemAddr = progMemAddr + 2
Next i
End Sub
- Don Kinzer
We discovered that there is a code generation error for the program above when compiling for native mode. The issue is that strData.DataAddress produces the address for the string data of the first element instead of the address of the index table. We haven't yet found a clean workaround but the one below corrects the address by subtracting the size of the index table. Again, this is only for native mode.Don_Kirby wrote:that's exactly what I was looking for.
Code: Select all
Call copyStrings(strArray, UBound(strArray), strData.DataAddress - CLng(UBound(strArray) * 2))
Code: Select all
Dim pmAddr as Long
pmAddr = strData.DataAddress
#if (Version.Value < &H020609) And (Option.TargetCode = "Native")
' this corrects a native mode code generation error prior to v2.6.9
pmAddr = pmAddr - CLng(UBound(strArray) * 2)
#endif
Call copyStrings(strArray, UBound(strArray), pmAddr)
Code: Select all
' assign a zero-length string to avoid a memory leak
sa(i) = ""
' copy the string data to the RAM-based array
zxStr.strLen = strLen
- Don Kinzer