Skip to content

Commit f7fd046

Browse files
Fix fixed-length string attribute reading and writing
1 parent 8517b19 commit f7fd046

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

Source/Datatype.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public class Datatype : Object, Equatable {
3535
guard id >= 0 else {
3636
fatalError("Failed to create Datatype")
3737
}
38+
if dataClass == .string {
39+
H5Tset_cset(id, H5T_CSET_UTF8)
40+
}
3841
self.init(id: id)
3942
}
4043

Source/StringAttribute.swift

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ open class StringAttribute: Attribute {
6868
let string = String(utf8String: pointer.baseAddress! + index)!
6969
strings.append(string)
7070
index += string.lengthOfBytes(using: .utf8)
71-
while index <= size && pointer[index] == 0 {
71+
while index < size && pointer[index] == 0 {
7272
index += 1
7373
}
7474
}
@@ -77,6 +77,14 @@ open class StringAttribute: Attribute {
7777
}
7878

7979
public func write(_ data: String) throws {
80+
if type.isVariableLengthString {
81+
try writeVariable(data)
82+
} else {
83+
try writeFixed(data)
84+
}
85+
}
86+
87+
public func writeVariable(_ data: String) throws {
8088
let size = self.space.size
8189
precondition(1 == size, "Data size doesn't match Dataspace dimensions")
8290

@@ -94,12 +102,30 @@ open class StringAttribute: Attribute {
94102
}
95103
}
96104

105+
public func writeFixed(_ data: String) throws {
106+
let size = self.space.size
107+
precondition(1 == size, "Data size doesn't match Dataspace dimensions")
108+
109+
let stringSize = self.type.size
110+
var data = data
111+
if stringSize != -1 && data.utf8.count < stringSize {
112+
data.append(contentsOf: String(repeating: "\0", count: stringSize - data.utf8.count))
113+
}
114+
115+
try data.utf8CString.withUnsafeBufferPointer { pointer in
116+
let type = Datatype.createString(size: stringSize)
117+
guard H5Awrite(id, type.id, pointer.baseAddress) >= 0 else {
118+
throw Error.ioError
119+
}
120+
}
121+
}
122+
97123
}
98124

99125

100126
public extension GroupType {
101127
/// Creates a `String` attribute.
102-
public func createStringAttribute(_ name: String) -> StringAttribute? {
128+
func createStringAttribute(_ name: String) -> StringAttribute? {
103129
guard let datatype = Datatype(type: String.self) else {
104130
return nil
105131
}
@@ -110,8 +136,18 @@ public extension GroupType {
110136
return StringAttribute(id: attributeID)
111137
}
112138

139+
/// Creates a fixed-length `String` attribute.
140+
func createFixedStringAttribute(_ name: String, size: Int) -> StringAttribute? {
141+
let datatype = Datatype(dataClass: .string, size: size)
142+
let dataspace = Dataspace(dims: [1])
143+
let attributeID = name.withCString { name in
144+
return H5Acreate2(id, name, datatype.id, dataspace.id, 0, 0)
145+
}
146+
return StringAttribute(id: attributeID)
147+
}
148+
113149
/// Opens a `String` attribute.
114-
public func openStringAttribute(_ name: String) -> StringAttribute? {
150+
func openStringAttribute(_ name: String) -> StringAttribute? {
115151
let attributeID = name.withCString{ name in
116152
return H5Aopen(id, name, 0)
117153
}

Tests/HDF5KitTests/AttributeTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,19 @@ class AttributeTests: XCTestCase {
5858

5959
let writeData = "ABCD😀"
6060
try attribute.write(writeData)
61+
XCTAssertEqual(try attribute.read(), [writeData])
62+
}
63+
64+
func testWriteReadFixedString() throws {
65+
let filePath = tempFilePath()
66+
guard let file = File.create(filePath, mode: .truncate) else {
67+
fatalError("Failed to create file")
68+
}
69+
let group = file.createGroup("group")
70+
let attribute = try XCTUnwrap(group.createFixedStringAttribute("attribute", size: 50))
6171

72+
let writeData = "ABCD😀"
73+
try attribute.write(writeData)
6274
XCTAssertEqual(try attribute.read(), [writeData])
6375
}
6476
}

0 commit comments

Comments
 (0)