Module: HDF5::StringCodec
- Defined in:
- lib/hdf5/string_codec.rb
Constant Summary collapse
- UTF8 =
1- VARIABLE_SIZE =
(1 << (::FFI.type_size(:size_t) * 8)) - 1
Class Method Summary collapse
- .array_shape(value) ⇒ Object
- .buffer_for(value) ⇒ Object
- .buffer_for_values(values) ⇒ Object
- .check(status, operation) ⇒ Object
- .datatype_id ⇒ Object
- .normalize(value) ⇒ Object
- .normalize_data(value) ⇒ Object
- .read(buffer) ⇒ Object
- .read_values(buffer, count, shape) ⇒ Object
- .string_data?(value) ⇒ Boolean
- .variable?(type_id) ⇒ Boolean
Class Method Details
.array_shape(value) ⇒ Object
66 67 68 69 70 71 72 73 74 |
# File 'lib/hdf5/string_codec.rb', line 66 def array_shape(value) return [] unless value.is_a?(Array) raise HDF5::Error, 'String data must not be empty' if value.empty? child_shapes = value.map { |item| array_shape(item) } raise HDF5::ShapeError, 'String data must be rectangular' unless child_shapes.uniq.length == 1 [value.length, *child_shapes.first] end |
.buffer_for(value) ⇒ Object
20 21 22 |
# File 'lib/hdf5/string_codec.rb', line 20 def buffer_for(value) buffer_for_values([normalize(value)]) end |
.buffer_for_values(values) ⇒ Object
24 25 26 27 28 29 |
# File 'lib/hdf5/string_codec.rb', line 24 def buffer_for_values(values) pointers = values.map { |value| ::FFI::MemoryPointer.from_string(normalize(value)) } buffer = ::FFI::MemoryPointer.new(:pointer, pointers.length) buffer.write_array_of_pointer(pointers) [buffer, pointers] end |
.check(status, operation) ⇒ Object
89 90 91 |
# File 'lib/hdf5/string_codec.rb', line 89 def check(status, operation) raise HDF5::Error, "Failed to #{operation}" if status < 0 end |
.datatype_id ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/hdf5/string_codec.rb', line 8 def datatype_id type_id = HDF5::FFI.H5Tcopy(HDF5::FFI.H5T_C_S1) raise HDF5::Error, 'Failed to create string datatype' if type_id < 0 check(HDF5::FFI.H5Tset_size(type_id, VARIABLE_SIZE), 'set variable string size') check(HDF5::FFI.H5Tset_cset(type_id, UTF8), 'set UTF-8 string encoding') type_id rescue StandardError HDF5::FFI.H5Tclose(type_id) if type_id && type_id >= 0 raise end |
.normalize(value) ⇒ Object
80 81 82 83 84 85 86 87 |
# File 'lib/hdf5/string_codec.rb', line 80 def normalize(value) raise HDF5::Error, 'String dataset data must be a String' unless value.is_a?(String) raise HDF5::Error, 'Variable-length strings cannot contain NUL bytes' if value.include?("\0") value.encode(Encoding::UTF_8) rescue EncodingError raise HDF5::Error, 'String dataset data must be valid UTF-8' end |
.normalize_data(value) ⇒ Object
58 59 60 61 62 63 64 |
# File 'lib/hdf5/string_codec.rb', line 58 def normalize_data(value) return [[normalize(value)], []] if value.is_a?(String) return [value.to_a.flatten.map { |item| normalize(item) }, value.shape] if value.is_a?(Numo::RObject) shape = array_shape(value) [value.flatten.map { |item| normalize(item) }, shape] end |
.read(buffer) ⇒ Object
31 32 33 34 |
# File 'lib/hdf5/string_codec.rb', line 31 def read(buffer) pointer = buffer.read_pointer pointer.null? ? nil : pointer.read_string.force_encoding(Encoding::UTF_8) end |
.read_values(buffer, count, shape) ⇒ Object
36 37 38 39 40 41 42 43 |
# File 'lib/hdf5/string_codec.rb', line 36 def read_values(buffer, count, shape) values = buffer.read_array_of_pointer(count).map do |pointer| pointer.null? ? nil : pointer.read_string.force_encoding(Encoding::UTF_8) end return values.first if shape.empty? Numo::RObject.cast(values).reshape(*shape) end |
.string_data?(value) ⇒ Boolean
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/hdf5/string_codec.rb', line 45 def string_data?(value) return true if value.is_a?(String) values = if value.is_a?(Numo::RObject) value.to_a.flatten elsif value.is_a?(Array) value.flatten else [] end !values.empty? && values.all? { |item| item.is_a?(String) } end |