@@ -310,53 +310,68 @@ public struct OmFileWriterArrayFinalised {
310310/// Specialized string array writer
311311public final class OmFileWriterStringArray < FileHandle: OmFileWriterBackend > {
312312 private var lookUpTable : [ UInt64 ]
313- private var currentPosition : UInt64
313+ private var currentIndex : Int
314314 private let buffer : OmBufferedWriter < FileHandle >
315315 private let dimensions : [ UInt64 ]
316+ private let totalNumberOfStrings : Int
316317
317318 public init ( dimensions: [ UInt64 ] , buffer: OmBufferedWriter < FileHandle > ) {
318319 self . dimensions = dimensions
319- let numberOfStrings = dimensions. reduce ( 1 , * )
320+ self . totalNumberOfStrings = Int ( dimensions. reduce ( 1 , * ) )
320321 // Allocate space for a lookup table.
321- // Needs to be numberOfStrings +1 to store start of first string
322+ // Needs to be totalNumberOfStrings +1 to store start of first string
322323 // as first element and for each string then the end address
323- self . lookUpTable = . init( repeating: 0 , count: Int ( numberOfStrings + 1 ) )
324- self . currentPosition = 0
324+ self . lookUpTable = . init( repeating: 0 , count: self . totalNumberOfStrings + 1 )
325+ self . currentIndex = 0
325326 self . buffer = buffer
326327 }
327328
328- /// Write all strings at once. The array must match the dimensions
329- public func writeData( array: [ String ] ) throws {
330- // Verify array size matches dimensions
331- let expectedSize = dimensions. reduce ( 1 , * )
332- guard array. count == expectedSize && self . currentPosition == 0 else {
333- throw OmFileFormatSwiftError . omEncoder ( error: " String arrays need to be encoded all at once and must match the dimensions " )
334- }
329+ /// Write strings to file. Can be all, a single or multiple strings.
330+ /// - Parameters:
331+ /// - array: Array of strings to write
332+ /// - arrayDimensions: The dimensions of the input array
333+ /// - arrayOffset: Starting position in the target array
334+ /// - arrayCount: Number of elements to write in each dimension
335+ public func writeData( array: [ String ] , arrayDimensions: [ UInt64 ] ? = nil , arrayOffset: [ UInt64 ] ? = nil , arrayCount: [ UInt64 ] ? = nil ) throws {
336+ let arrayDimensions = arrayDimensions ?? self . dimensions
337+ let arrayCount = arrayCount ?? arrayDimensions
338+ let arrayOffset = arrayOffset ?? [ UInt64] ( repeating: 0 , count: arrayDimensions. count)
339+
340+ // Verify parameters
341+ assert ( array. count == arrayCount. reduce ( 1 , * ) )
342+ assert ( arrayDimensions. allSatisfy ( { $0 >= 0 } ) )
343+ assert ( arrayOffset. allSatisfy ( { $0 >= 0 } ) )
344+ assert ( zip ( arrayDimensions, zip ( arrayOffset, arrayCount) ) . allSatisfy { $1. 0 + $1. 1 <= $0 } )
335345
336346 // Store data start address if this is the first time this read is called
337- let lutOffset = UInt64 ( buffer. totalBytesWritten)
338- if self . currentPosition == 0 {
339- lookUpTable [ 0 ] = lutOffset
347+ if self . currentIndex == 0 {
348+ lookUpTable [ self . currentIndex] = UInt64 ( buffer. totalBytesWritten)
340349 }
341350
342351 // Pre-calculate total required capacity
343352 let totalCapacity = array. reduce ( 0 ) { $0 + $1. utf8. count }
344353 try buffer. reallocate ( minimumCapacity: totalCapacity)
345354
346355 // Write all strings consecutively
347- for (i , string) in array. enumerated ( ) {
356+ for string in array {
348357 string. utf8. withContiguousStorageIfAvailable { utf8 in
349- buffer. bufferAtWritePosition. advanced ( by: Int ( self . currentPosition) )
350- . copyMemory ( from: utf8. baseAddress!, byteCount: utf8. count)
351- self . currentPosition += UInt64 ( utf8. count)
352- lookUpTable [ i+ 1 ] = lutOffset + self . currentPosition
358+ let writeByteCount = utf8. count
359+
360+ buffer. bufferAtWritePosition
361+ . copyMemory ( from: utf8. baseAddress!, byteCount: writeByteCount)
362+ buffer. incrementWritePosition ( by: writeByteCount)
363+
364+ lookUpTable [ self . currentIndex+ 1 ] = UInt64 ( buffer. totalBytesWritten)
365+ self . currentIndex += 1
353366 }
354367 }
355-
356- buffer. incrementWritePosition ( by: Int ( self . currentPosition) )
357368 }
358369
359370 public func finalise( ) throws -> OmFileWriterArrayFinalised {
371+ guard self . currentIndex == self . totalNumberOfStrings else {
372+ throw OmFileFormatSwiftError . omEncoder ( error: " Not all strings have been written " )
373+ }
374+
360375 try buffer. alignTo8Bytes ( )
361376 let lutOffset = buffer. totalBytesWritten
362377
0 commit comments