Skip to content

Commit cce50f7

Browse files
committed
improve writer
1 parent d6dc540 commit cce50f7

1 file changed

Lines changed: 37 additions & 22 deletions

File tree

Swift/OmFileFormat/OmFileWriter.swift

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -310,53 +310,68 @@ public struct OmFileWriterArrayFinalised {
310310
/// Specialized string array writer
311311
public 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

Comments
 (0)