Class: LibBin::Structure Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/libbin/data_types.rb,
lib/libbin.rb,
ext/libbin/libbin_c.c

Overview

This class is abstract.

This class is used to describe a binary data structure

composed of different fields.

Defined Under Namespace

Classes: Bitfield, Double, Double_BE, Double_LE, Enum, Field, Flt, Flt_BE, Flt_LE, Half, Half_BE, Half_LE, Int16, Int16_BE, Int16_LE, Int32, Int32_BE, Int32_LE, Int64, Int64_BE, Int64_LE, Int8, PGHalf, PGHalf_BE, PGHalf_LE, Scalar, Str, UInt16, UInt16_BE, UInt16_LE, UInt32, UInt32_BE, UInt32_LE, UInt64, UInt64_BE, UInt64_LE, UInt8

Class Attribute Summary collapse

Instance Attribute Summary collapse

Scalars collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeStructure

Create new Structure object.



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'ext/libbin/libbin_c.c', line 177

static VALUE cStructure_initialize(VALUE self) {
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__input = Qnil;
  data->__output = Qnil;
  data->__input_big = Qnil;
  data->__output_big = Qnil;
  data->__parent = Qnil;
  data->__index = Qnil;
  data->__position = Qnil;
  data->__cur_position = Qnil;
  data->__offset = Qnil;
  data->__condition = Qnil;
  data->__type = Qnil;
  data->__length = Qnil;
  data->__count = Qnil;
  data->__iterator = Qnil;
  return self;
}

Class Attribute Details

.always_alignObject

Returns the value of attribute always_align.



89
90
91
# File 'lib/libbin.rb', line 89

def always_align
  @always_align
end

.fieldsObject (readonly)

Returns the value of attribute fields.



90
91
92
# File 'lib/libbin.rb', line 90

def fields
  @fields
end

Instance Attribute Details

#__conditionObject

Returns the value of attribute __condition.



11
12
13
# File 'lib/libbin.rb', line 11

def __condition
  @__condition
end

#__countObject

Returns the value of attribute __count.



14
15
16
# File 'lib/libbin.rb', line 14

def __count
  @__count
end

#__cur_positionObject

Returns the value of attribute __cur_position.



4
5
6
# File 'lib/libbin.rb', line 4

def __cur_position
  @__cur_position
end

#__indexObject

Returns the value of attribute __index.



2
3
4
# File 'lib/libbin.rb', line 2

def __index
  @__index
end

#__inputObject

Returns the value of attribute __input.



5
6
7
# File 'lib/libbin.rb', line 5

def __input
  @__input
end

#__input_bigObject

Returns the value of attribute __input_big.



7
8
9
# File 'lib/libbin.rb', line 7

def __input_big
  @__input_big
end

#__iteratorObject

Returns the value of attribute __iterator.



15
16
17
# File 'lib/libbin.rb', line 15

def __iterator
  @__iterator
end

#__lengthObject

Returns the value of attribute __length.



13
14
15
# File 'lib/libbin.rb', line 13

def __length
  @__length
end

#__offsetObject

Returns the value of attribute __offset.



10
11
12
# File 'lib/libbin.rb', line 10

def __offset
  @__offset
end

#__outputObject

Returns the value of attribute __output.



6
7
8
# File 'lib/libbin.rb', line 6

def __output
  @__output
end

#__output_bigObject

Returns the value of attribute __output_big.



8
9
10
# File 'lib/libbin.rb', line 8

def __output_big
  @__output_big
end

#__parentObject

Returns the value of attribute __parent.



1
2
3
# File 'lib/libbin.rb', line 1

def __parent
  @__parent
end

#__positionObject

Returns the value of attribute __position.



3
4
5
# File 'lib/libbin.rb', line 3

def __position
  @__position
end

#__typeObject

Returns the value of attribute __type.



12
13
14
# File 'lib/libbin.rb', line 12

def __type
  @__type
end

#__valueObject

Returns the value of attribute __value.



16
17
18
# File 'lib/libbin.rb', line 16

def __value
  @__value
end

Class Method Details

.alignInteger

Returns the alignement of the structure

Returns:

  • (Integer)

    alignment of the structure



66
67
68
69
70
71
# File 'lib/libbin.rb', line 66

def self.align
  return @always_align if @always_align
  align = @fields.collect(&:align).select { |v| v }.max
  align = 0 unless align
  align
end

.bitfield(name, map, size: 32, signed: false, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil) ⇒ Object

Create a new field of a type inheriting from Bitfield and name name. See field for more options

Parameters:

  • name (Symbol, String)

    name of the field.

  • map (Hash{Symbol => Integer})

    bitfield field names and number of bits.

  • size (Integer) (defaults to: 32)

    size in bits of the underlying integer

  • signed (Boolean) (defaults to: false)

    signedness of the underlying type

Returns:

  • self



697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
# File 'lib/libbin/data_types.rb', line 697

def self.bitfield(name, map, size: 32, signed: false, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil)
  klass = Class.new(Bitfield) do |c|
    c.set_type_size(size, signed)
    c.set_map(map)
  end
  if klass.always_align
    al = klass.align
    if align.kind_of?(Integer)
      align = align >= al ? align : al
    else
      align = al
    end
  end
  if align == true
    align = klass.align
  else
    raise "alignement must be a power of 2" if align && (align - 1) & align != 0
  end
  @fields.push(Field::new(name, klass, length, count, offset, sequence, condition, relative_offset, align, expect))
  attr_accessor name
  self
end

.convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil) ⇒ Structure+

Convert a structure by loading it from input and dumping it to output. Returns the loaded structure.

Examples:

# Original Ruby implementation
def self.convert(input, output, input_big = LibBin::default_big?, output_big = !input_big, parent = nil, index = nil, length = nil)
  if length
    length.times.collect {
      self.new.__convert(input, output, input_big, output_big, parent, index)
    }
  else
    self.new.__convert(input, output, input_big, output_big, parent, index)
  end
end

Parameters:

  • input (IO)

    the stream to load the structure from

  • output (IO)

    the stream to dump the structure to

  • input_big (Boolean) (defaults to: LibBin::default_big?)

    the endianness of input

  • output_big (Boolean) (defaults to: !input_big)

    the endianness of output

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

  • length (Integer) (defaults to: nil)

    if given, the length of the vector of structure

Returns:

  • (Structure, Array<Structure>)

    a new strcuture, or an array of structures if length was specified



961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
# File 'ext/libbin/libbin_c.c', line 961

static VALUE cStructure_singl_convert(int argc, VALUE *argv, VALUE self) {
  VALUE input;
  VALUE output;
  VALUE input_big;
  VALUE output_big;
  VALUE parent;
  VALUE index;
  VALUE length;
  rb_scan_args(argc, argv, "25", &input, &output, &input_big, &output_big, &parent, &index, &length);
  if (NIL_P(input_big))
    input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0);
  if (NIL_P(output_big))
    output_big = RTEST(input_big) ? Qfalse : Qtrue;
  VALUE res;
  if (!NIL_P(length)) {
    long l = NUM2LONG(length);
    res = rb_ary_new_capa(l);
    for (long i = 0; i < l; i++) {
      VALUE obj = rb_class_new_instance(0, NULL, self);
      rb_funcall(obj, id___convert, 6, input, output, input_big, output_big, parent, index);
      rb_ary_store(res, i, obj);
    }
  } else {
    res = rb_class_new_instance(0, NULL, self);
    rb_funcall(res, id___convert, 6, input, output, input_big, output_big, parent, index);
  }
  return res;
}

.double(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Double and name name. See field for options.

Returns:

  • self



306
# File 'lib/libbin/data_types.rb', line 306

define_scalar_constructor "Double", :double, :double, "A double precision floating point scalar"

.double_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Double_BE and name name. See field for options.

Returns:

  • self



308
# File 'lib/libbin/data_types.rb', line 308

define_scalar_constructor "Double_BE", :double_be, :double, "A double precision big endian floating point scalar"

.double_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Double_LE and name name. See field for options.

Returns:

  • self



307
# File 'lib/libbin/data_types.rb', line 307

define_scalar_constructor "Double_LE", :double_le, :double, "A double precision little endian floating point scalar"

.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil) ⇒ Structure+

Dump a structure to output.

Examples:

# Original Ruby implementation
def self.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
  if length
    length.times.each { |i|
      value[i].__dump(output, output_big, parent, index)
    }
    value
  else
    value.__dump(output, output_big, parent, index)
  end
end

Parameters:

  • value (Structure, Array<Structure>)

    the value of structure to dump

  • output (IO)

    the stream to dump the structure to

  • output_big (Boolean) (defaults to: LibBin::default_big?)

    the endianness of output

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

  • length (Integer) (defaults to: nil)

    if given, the length of the vector of structure

Returns:



942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
# File 'ext/libbin/libbin_c.c', line 942

static VALUE cStructure_singl_dump(int argc, VALUE *argv, VALUE self) {
  VALUE value;
  VALUE output;
  VALUE output_big;
  VALUE parent;
  VALUE index;
  VALUE length;
  rb_scan_args(argc, argv, "24", &value, &output, &output_big, &parent, &index, &length);
  if (NIL_P(output_big))
    output_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0);
  if (!NIL_P(length)) {
    long l = NUM2LONG(length);
    for (long i = 0; i < l; i++)
      rb_funcall(rb_ary_entry(value, i), id___dump, 4, output, output_big, parent, index);
  } else
    rb_funcall(value, id___dump, 4, output, output_big, parent, index);
  return value;
}

.enum(name, map, size: 32, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil) ⇒ Object

Create a new field of a type inheriting from Enum and name name. See field for more options

Parameters:

  • name (Symbol, String)

    name of the field.

  • map (Hash{Symbol => Integer})

    enum values.

  • size (Integer) (defaults to: 32)

    size in bits of the underlying integer

Returns:

  • self



476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/libbin/data_types.rb', line 476

def self.enum(name, map, size: 32, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil)
  klass = Class.new(Enum) do |c|
    c.type_size = size
    c.map = map
  end
  if klass.always_align
    al = klass.align
    if align.kind_of?(Integer)
      align = align >= al ? align : al
    else
      align = al
    end
  end
  if align == true
    align = klass.align
  else
    raise "alignement must be a power of 2" if align && (align - 1) & align != 0
  end
  @fields.push(Field::new(name, klass, length, count, offset, sequence, condition, relative_offset, align, expect))
  attr_accessor name
  self
end

.field(name, type, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil) ⇒ Object Also known as: register_field

Define a new field in the structure

Parameters:

  • name (Symbol, String)

    the name of the field.

  • type (Class, String, Proc)

    the type of the field, as a Class, or as a String or Proc that will be evaluated in the context of the LibBin::Structure instance.

  • length (Integer, String, Proc) (defaults to: nil)

    if given, consider the field a vector of the type. The length is either a constant Integer of a String or Proc that will be evaluated in the context of the LibBin::Structure instance.

  • count (Integer, String, Proc) (defaults to: nil)

    if given, consider the field is repeated count times. The count is either a constant Integer of a String or Proc that will be evaluated in the context of the LibBin::Structure instance.

  • offset (integer, String, Proc) (defaults to: nil)

    if given, the absolute offset in the file, or the offset from the parent position, where the field can be found. See relative offset. The offset is either a constant Integer of a String or Proc that will be evaluated in the context of the LibBin::Structure instance.

  • sequence (Boolean) (defaults to: false)

    if true, type, length, offset, and condition are evaluated for each repetition.

  • condition (String, Proc) (defaults to: nil)

    if given, the field, or repetition of the field can be conditionally present. The condition will be evaluated in the context of the LibBin::Structure instance.

  • relative_offset (Boolean) (defaults to: false)

    consider the offset relative to the field parent.

  • align (Boolean, Integer) (defaults to: false)

    if given, align the field. If given as an Integer it must be a power of 2. Else the field is aligned to the field’s type preferred alignment.

  • expect (Proc, Object) (defaults to: nil)

    if given, the field value must validate or an eexception is raised. If a proc the proc resulted must be truthy. If not, the object will be tested for equality.

Returns:

  • self



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/libbin/data_types.rb', line 154

def self.field(name, type, length: nil, count: nil, offset: nil,
               sequence: false, condition: nil, relative_offset: false,
               align: false, expect: nil)
  if type.respond_to?(:always_align) && type.always_align
    al = type.align
    if align.kind_of?(Integer)
      align = align >= al ? align : al
    else
      align = al
    end
  end
  if align == true
    # Automatic alignment not supported for dynamic types
    if type.respond_to?(:align)
      align = type.align
    else
      raise "alignment is unsupported for dynamic types"
    end
  else
    raise "alignement must be a power of 2" if align && (align - 1) & align != 0
  end
  @fields.push(Field::new(name, type, length, count, offset, sequence,
                          condition, relative_offset, align, expect))
  attr_accessor name
  self
end

.float(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Flt and name name. See field for options.

Returns:

  • self



303
# File 'lib/libbin/data_types.rb', line 303

define_scalar_constructor "Flt", :float, :float, "A single precision floating point scalar"

.float_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Flt_BE and name name. See field for options.

Returns:

  • self



305
# File 'lib/libbin/data_types.rb', line 305

define_scalar_constructor "Flt_BE", :float_be, :float, "A single precision big endian floating point scalar"

.float_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Flt_LE and name name. See field for options.

Returns:

  • self



304
# File 'lib/libbin/data_types.rb', line 304

define_scalar_constructor "Flt_LE", :float_le, :float, "A single precision little endian floating point scalar"

.half(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Half and name name. See field for options.

Returns:

  • self



309
# File 'lib/libbin/data_types.rb', line 309

define_scalar_constructor "Half", :half, :half, "A half precision floating point scalar"

.half_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Half_BE and name name. See field for options.

Returns:

  • self



311
# File 'lib/libbin/data_types.rb', line 311

define_scalar_constructor "Half_BE", :half_be, :half, "A half precision big endian floating point scalar"

.half_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Half_LE and name name. See field for options.

Returns:

  • self



310
# File 'lib/libbin/data_types.rb', line 310

define_scalar_constructor "Half_LE", :half_le, :half, "A half precision little endian floating point scalar"

.int16(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int16 and name name. See field for options.

Returns:

  • self



285
# File 'lib/libbin/data_types.rb', line 285

define_scalar_constructor "Int16", :int16, :int16_t, "A signed 16 bit integer"

.int16_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int16_BE and name name. See field for options.

Returns:

  • self



287
# File 'lib/libbin/data_types.rb', line 287

define_scalar_constructor "Int16_BE", :int16_be, :int16_t, "A signed big endian 16 bit integer"

.int16_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int16_LE and name name. See field for options.

Returns:

  • self



286
# File 'lib/libbin/data_types.rb', line 286

define_scalar_constructor "Int16_LE", :int16_le, :int16_t, "A signed little endian 16 bit integer"

.int32(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int32 and name name. See field for options.

Returns:

  • self



291
# File 'lib/libbin/data_types.rb', line 291

define_scalar_constructor "Int32", :int32, :int32_t, "A signed little endian 32 bit integer"

.int32_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int32_BE and name name. See field for options.

Returns:

  • self



293
# File 'lib/libbin/data_types.rb', line 293

define_scalar_constructor "Int32_BE", :int32_be, :int32_t, "A signed big endian 32 bit integer"

.int32_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int32_LE and name name. See field for options.

Returns:

  • self



292
# File 'lib/libbin/data_types.rb', line 292

define_scalar_constructor "Int32_LE", :int32_le, :int32_t, "A signed little endian 32 bit integer"

.int64(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int64 and name name. See field for options.

Returns:

  • self



297
# File 'lib/libbin/data_types.rb', line 297

define_scalar_constructor "Int64", :int64, :int64_t, "A signed little endian 64 bit integer"

.int64_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int64_BE and name name. See field for options.

Returns:

  • self



299
# File 'lib/libbin/data_types.rb', line 299

define_scalar_constructor "Int64_BE", :int64_be, :int64_t, "A signed big endian 64 bit integer"

.int64_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int64_LE and name name. See field for options.

Returns:

  • self



298
# File 'lib/libbin/data_types.rb', line 298

define_scalar_constructor "Int64_LE", :int64_le, :int64_t, "A signed little endian 64 bit integer"

.int8(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type Int8 and name name. See field for options.

Returns:

  • self



283
# File 'lib/libbin/data_types.rb', line 283

define_scalar_constructor "Int8", :int8, :int8_t, "A signed 8 bit integer"

.load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil) ⇒ Structure+

Load a structure from input.

Examples:

# Original Ruby implementation
def self.load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
  if length
    length.times.collect {
      self.new.__load(input, input_big, parent, index)
    }
  else
    self.new.__load(input, input_big, parent, index)
  end
end

Parameters:

  • input (IO)

    the stream to load the structure from

  • input_big (Boolean) (defaults to: LibBin::default_big?)

    the endianness of input

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

  • length (Integer) (defaults to: nil)

    if given, the length of the vector of structure

Returns:

  • (Structure, Array<Structure>)

    a new strcuture, or an array of structures if length was specified



916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
# File 'ext/libbin/libbin_c.c', line 916

static VALUE cStructure_singl_load(int argc, VALUE *argv, VALUE self) {
  VALUE input;
  VALUE input_big;
  VALUE parent;
  VALUE index;
  VALUE length;
  rb_scan_args(argc, argv, "14", &input, &input_big, &parent, &index, &length);
  if (NIL_P(input_big))
    input_big = rb_funcall(mLibBin, rb_intern("default_big?"), 0);
  VALUE res;
  if (!NIL_P(length)) {
    long l = NUM2LONG(length);
    res = rb_ary_new_capa(l);
    for (long i = 0; i < l; i++) {
      VALUE obj = rb_class_new_instance(0, NULL, self);
      rb_funcall(obj, id___load, 4, input, input_big, parent, index);
      rb_ary_store(res, i, obj);
    }
    return res;
  } else {
    res = rb_class_new_instance(0, NULL, self);
    rb_funcall(res, id___load, 4, input, input_big, parent, index);
  }
  return res;
}

.pghalf(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type PGHalf and name name. See field for options.

Returns:

  • self



312
# File 'lib/libbin/data_types.rb', line 312

define_scalar_constructor "PGHalf", :pghalf, :pghalf, "A half precision floating point scalar as used by PlatinumGames in certain formats"

.pghalf_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type PGHalf_BE and name name. See field for options.

Returns:

  • self



314
# File 'lib/libbin/data_types.rb', line 314

define_scalar_constructor "PGHalf_BE", :pghalf_be, :pghalf, "A half precision big endian floating point scalar as used by PlatinumGames in certain formats"

.pghalf_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type PGHalf_LE and name name. See field for options.

Returns:

  • self



313
# File 'lib/libbin/data_types.rb', line 313

define_scalar_constructor "PGHalf_LE", :pghalf_le, :pghalf, "A half precision little endian floating point scalar as used by PlatinumGames in certain formats"

.set_always_align(align) ⇒ Object Also known as: always_align=

Set the structure as needing to always be aligned

Parameters:

  • align (true, Integer)

    if true use the fields’ maximum alignment

Returns:

  • align



76
77
78
79
80
81
82
83
84
85
# File 'lib/libbin.rb', line 76

def self.set_always_align(align)
  if align == true
    @always_align = @fields.collect(&:align).select { |v| v }.max
    @always_align = 0 unless align
  else
    raise "alignement must be a power of 2" if align && (align - 1) & align != 0
    @always_align = align
  end
  align
end

.shape(value, offset = 0, parent = nil, index = nil, kind = DataShape, length = nil) ⇒ kind

Return the shape of the value.

Examples:

# Original Ruby implementation
def self.shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil)
  if length
    kind.new(length.times.collect { |i|
      value[i].__shape(previous_offset, parent, index, kind)
    })
  else
    value.__shape(previous_offset, parent, index, kind)
  end
end

Parameters:

  • value (Structure, Array<Structure>)

    the value of structure to get the shape of

  • offset (Integer) (defaults to: 0)

    the base position of the field

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

  • kind (Class) (defaults to: DataShape)

    the kind of structure to create

  • length (Integer) (defaults to: nil)

    if given, the length of the vector of structure

Returns:

  • (kind)

    the the shape of the structure



990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
# File 'ext/libbin/libbin_c.c', line 990

static VALUE cStructure_singl_shape(int argc, VALUE *argv, VALUE self) {
  VALUE value;
  VALUE previous_offset;
  VALUE parent;
  VALUE index;
  VALUE kind;
  VALUE length;
  rb_scan_args(argc, argv, "15", &value, &previous_offset, &parent, &index, &kind, &length);
  if (NIL_P(previous_offset))
    previous_offset = INT2FIX(0);
  if (NIL_P(kind))
    kind = cDataShape;
  VALUE res;
  if (!NIL_P(length)) {
    long l = NUM2LONG(length);
    res = rb_ary_new_capa(l);
    for (long i = 0; i < l; i++)
      rb_ary_store(res, i, rb_funcall(rb_ary_entry(value, i), id___shape, 4, previous_offset, parent, index, kind));
    res = rb_class_new_instance(1, &res, kind);
  } else
    res = rb_funcall(value, id___shape, 4, previous_offset, parent, index, kind);
  return res;
}

.size(value, offset = 0, parent = nil, index = nil, length = nil) ⇒ Object

Returns the size of a structure

Parameters:

  • value (Structure, Array<Structure>)

    field or array of field to get the size of

  • offset (Integer) (defaults to: 0)

    position in the stream

  • parent (Structure) (defaults to: nil)

    if given, parent structure

  • index (Integer) (defaults to: nil)

    index if part of a repeated field inside parent

  • length (Integer) (defaults to: nil)

    if given, the length of the vector



99
100
101
102
103
104
105
# File 'lib/libbin.rb', line 99

def self.size(value, offset = 0, parent = nil, index = nil, length = nil)
  if length
    shape(value, offset, parent, index, length).size
  else
    value.__shape(offset, parent, index).size
  end
end

.string(field, length = nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil) ⇒ Object

Create a new field of type Str and name name. See field for options.

Returns:

  • self



323
324
325
326
327
328
329
330
331
332
# File 'lib/libbin/data_types.rb', line 323

def self.string(field, length = nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false, expect: nil)
  if align == true
    align = Str.align
  else
    raise "alignement must be a power of 2" if align && (align - 1) & align != 0
  end
  @fields.push(Field::new(field, Str, length, count, offset, sequence, condition, relative_offset, align, expect))
  attr_accessor field
  self
end

.uint16(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt16 and name name. See field for options.

Returns:

  • self



288
# File 'lib/libbin/data_types.rb', line 288

define_scalar_constructor "UInt16", :uint16, :uint16_t, "An unsigned 16 bit integer"

.uint16_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt16_BE and name name. See field for options.

Returns:

  • self



290
# File 'lib/libbin/data_types.rb', line 290

define_scalar_constructor "UInt16_BE", :uint16_be, :uint16_t, "An unsigned big endian 16 bit integer"

.uint16_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt16_LE and name name. See field for options.

Returns:

  • self



289
# File 'lib/libbin/data_types.rb', line 289

define_scalar_constructor "UInt16_LE", :uint16_le, :uint16_t, "An unsigned little endian 16 bit integer"

.uint32(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt32 and name name. See field for options.

Returns:

  • self



294
# File 'lib/libbin/data_types.rb', line 294

define_scalar_constructor "UInt32", :uint32, :uint32_t, "An unsigned 32 bit integer"

.uint32_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt32_BE and name name. See field for options.

Returns:

  • self



296
# File 'lib/libbin/data_types.rb', line 296

define_scalar_constructor "UInt32_BE", :uint32_be, :uint32_t, "An unsigned big endian 32 bit integer"

.uint32_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt32_LE and name name. See field for options.

Returns:

  • self



295
# File 'lib/libbin/data_types.rb', line 295

define_scalar_constructor "UInt32_LE", :uint32_le, :uint32_t, "An unsigned little endian 32 bit integer"

.uint64(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt64 and name name. See field for options.

Returns:

  • self



300
# File 'lib/libbin/data_types.rb', line 300

define_scalar_constructor "UInt64", :uint64, :uint64_t, "An unsigned 64 bit integer"

.uint64_be(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt64_BE and name name. See field for options.

Returns:

  • self



302
# File 'lib/libbin/data_types.rb', line 302

define_scalar_constructor "UInt64_BE", :uint64_be, :uint64_t, "An unsigned big endian 64 bit integer"

.uint64_le(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt64_LE and name name. See field for options.

Returns:

  • self



301
# File 'lib/libbin/data_types.rb', line 301

define_scalar_constructor "UInt64_LE", :uint64_le, :uint64_t, "An unsigned little endian 64 bit integer"

.uint8(method_signature(name, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false, align: false)) ⇒ Object

Create a new field of type UInt8 and name name. See field for options.

Returns:

  • self



284
# File 'lib/libbin/data_types.rb', line 284

define_scalar_constructor "UInt8", :uint8, :uint8_t, "An unsigned 8 bit integer"

Instance Method Details

#__convert(input, output, input_big, output_big, parent = nil, index = nil) ⇒ Structure

Fill in the structure by loading it from input and dumping it to output.

Examples:

# Original Ruby implementation
def __convert(input, output, input_big, output_big, parent = nil, index = nil)
  __set_convert_state(input, output, input_big, output_big, parent, index)
  __convert_fields
  __unset_convert_state
  self
end

Parameters:

  • input (IO)

    the stream to load the structure from

  • output (IO)

    the stream to dump the structure to

  • input_big (Boolean)

    the endianness of input

  • output_big (Boolean)

    the endianness of output

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

Returns:



882
883
884
885
886
887
888
889
890
891
892
893
894
# File 'ext/libbin/libbin_c.c', line 882

static VALUE cStructure_convert(int argc, VALUE *argv, VALUE self) {
  VALUE input;
  VALUE output;
  VALUE input_big;
  VALUE output_big;
  VALUE parent;
  VALUE index;
  rb_scan_args(argc, argv, "42", &input, &output, &input_big, &output_big, &parent, &index);
  rb_funcall(self, id___set_convert_state, 6, input, output, input_big, output_big, parent, index);
  rb_funcall(self, id___convert_fields, 0);
  rb_funcall(self, id___unset_convert_state, 0);
  return self;
}

#__convert_field(field) ⇒ Object

Load and dump the value of a structure field.

Examples:

# Original Ruby implementation
def __convert_field(field)
  return nil if __decode_static_conditions(field).nil?
  vs = __count.times.collect do |it|
    __iterator = it
    if __decode_dynamic_conditions(field)
      __value = __type::convert(__input, __output, __input_big, __output_big, self, it, __length)
      __decode_expect(field.expect, __value)
    else
      nil
    end
  end
  __restore_context
  vs = vs.first unless field.count
  vs
end

Parameters:

  • field (Field)

    the field descriptor

Returns:

  • the field value or nil if the field was inactive

#__convert_fieldsStructure

Convert the fields of the structure. The conversion state must have been set beforehand.

Examples:

# Original Ruby implementation
def __convert_fields
  field = nil
  begin
    __fields.each { |field|
      send("#{field.name}=", __convert_field(field))
    }
  rescue
    STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
    raise
  end
  self
end

Returns:



816
817
818
819
820
821
# File 'ext/libbin/libbin_c.c', line 816

static VALUE cStructure_convert_fields(VALUE self) {
  struct fields_state state = {self, Qnil, Qnil};
  rb_rescue(&cStructure_convert_fields_wrapper, (VALUE)&state,
            &cStructure_fields_rescue, (VALUE)&state);
  return self;
}

#__decode_condition(condition) ⇒ Boolean

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Decode the condition expression

Examples:

# Original Ruby implementation
def __decode_condition(condition)
  return true unless condition
  __decode_expression(condition)
end

Parameters:

  • condition (Proc, Boolean, nil)

    the expression to decode

Returns:

  • (Boolean)

    the field is active

#__decode_count(count) ⇒ Integer

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Decode the count expression.

Examples:

# Original Ruby implementation
def __decode_count(count)
  return 1 unless count
  __decode_expression(count)
end

Parameters:

  • count (Proc, Integer, nil)

    the expression to decode

Returns:

  • (Integer)

    1 if count is nil, the decoded count otherwise

#__decode_dynamic_conditions(field) ⇒ Boolean

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons.

Sets field repetition specific context. Namely __offset, __condition, __type, and __length should be set if the field repetition is active.

Examples:

# Original Ruby implementation
def __decode_dynamic_conditions(field)
  return true unless field.sequence?
  __offset = nil
  __condition = nil
  __type = nil
  __length = nil
  __offset = __decode_seek_offset(field.offset, field.relative_offset?, field.align)
  return false if __offset == false
  __condition = __decode_condition(field.condition)
  return false unless __condition
  __type = __decode_type(field.type)
  __length = __decode_length(field.length)
  return true
end

Parameters:

  • field (Field)

    the field descriptor

Returns:

  • (Boolean)

    field repetition is active

#__decode_expect(expect, value) ⇒ Object

Decode the given expect expression, given the field value.

Examples:

# Original Ruby implementation
def __decode_expect(expect, value)
  return value if expect.nil?
  if expect.is_a?(Proc)
    raise "could not validate field value: #{value}" unless instance_exec(value, &expect)
  else
    raise "could not validate field value: #{value} expected: #{expect}" unless expect == value
  end
  return value
end

Parameters:

  • expect (Proc, Object, nil)

    the expression to decode

  • value (Object)

    the field value to validate

Returns:

  • (Object)

    returns value if validated. If expect is a Proc, the proc will be passed value as an argument and be evaluated. If expect is a scalar, expect and value will be tested for equality. If the result of the evaluation or the test is truthy, value is validate. Else an exception is raised.

#__decode_expression(expression) ⇒ Object

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Decode the given expression in the context of the receiver.

Examples:

# Original Ruby implementation
def __decode_expression(expression)
  if expression.is_a?(Proc)
    instance_exec &expression
  else
    expression
  end
end

Parameters:

  • expression (Proc, Object)

    the expression to decode

Returns:

  • (Object)

    the decoded value

#__decode_length(length) ⇒ Integer?

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Decode the length expression.

Examples:

# Original Ruby implementation
def __decode_length(length)
  __decode_expression(length)
end

Parameters:

  • length (Proc, Integer, nil)

    the expression to decode

Returns:

  • (Integer, nil)

    nil if the field is not a vector, or the length of the vector

#__decode_seek_offset(offset, relative_offset, align) ⇒ nil, ...

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Decode the offset and seek to this position in the active streams.

Examples:

# Original Ruby implementation
def __decode_seek_offset(offset, relative_offset, align)
  cur_pos = nil
  if !offset
    return nil unless align
    cur_pos =
      if __input
        __input.tell
      elsif __output
        __output.tell
      else
        __cur_position
      end
    pad = cur_pos % align
    return nil if pad == 0
    cur_pos += align - pad
  else
    cur_pos = __decode_expression(offset)
    return false if cur_pos == 0x0
    cur_pos += __position if relative_offset
    cur_pos +=  align - (cur_pos % align) if align && cur_pos % align > 0
  end
  __cur_position = cur_pos
  __input.seek(cur_pos) if __input
  __output.seek(cur_pos) if __output
  cur_pos
end

Parameters:

  • offset (Proc, Integer, nil)

    the expression to decode

  • relative_offset (Boolean)

    the offset should be relative to the structure base (__position)

  • align (false, Integer)

    the required alignement of the field

Returns:

  • (nil, false, Integer)

    return nil if no offset was specified, an Integer if the active streams had to seek, or false if a zero offset was computed.

#__decode_static_conditions(field) ⇒ Integer?

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Sets field specific context. Return nil if the field is inactive. If the field is a sequence, only __count is set, if not, __offset, __condition, __type, and __count are also set.

Examples:

# Original Ruby implementation
def __decode_static_conditions(field)
  __offset = nil
  __condition = nil
  __type = nil
  __length = nil
  __count = nil
  unless field.sequence?
    __offset = __decode_seek_offset(field.offset, field.relative_offset?, field.align)
    return nil if __offset == false
    __condition = __decode_condition(field.condition)
    return nil unless __condition
    __type = __decode_type(field.type)
    __length = __decode_length(field.length)
  end
  __count = __decode_count(field.count)
end

Parameters:

  • field (Field)

    the field descriptor

Returns:

  • (Integer, nil)

    nil if the field is inactive, the repetition count otherwise

#__decode_type(type) ⇒ Class

Note:

Do not overload, this is not called through the usual ruby dispatch for performance reasons

Decode the type expression.

Examples:

# Original Ruby implementation
def __decode_type(type)
  __decode_expression(type)
end

Parameters:

  • type (Proc, Class)

    the expression to decode

Returns:

  • (Class)

    the decoded type

#__dump(output, output_big, parent = nil, index = nil) ⇒ Structure

Dump the structure to output.

Examples:

# Original Ruby implementation
def __dump(output, output_big, parent = nil, index = nil)
  __set_dump_state(output, output_big, parent, index)
  __dump_fields
  __unset_dump_state
  self
end

Parameters:

  • output (IO)

    the stream to dump the structure to

  • output_big (Boolean)

    the endianness of output

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

Returns:

#__dump_field(value, field) ⇒ Object

Dump the value of a structure field.

Examples:

# Original Ruby implementation
def __dump_field(vs, field)
  return nil if __decode_static_conditions(field).nil?
  vs = [vs] unless field.count
  __count.times do |it|
    __iterator = it
    if __decode_dynamic_conditions(field)
      __value = vs[it]
      __decode_expect(field.expect, __value)
      __type::dump(__value, __output, __output_big, self, it, __length)
    end
  end
  __restore_context
end

Parameters:

  • value

    the field value

  • field (Field)

    the field descriptor

Returns:

  • nil

#__dump_fieldsStructure

Dump the fields of the structure. The dump state must have been set beforehand.

Examples:

# Original Ruby implementation
def __dump_fields
  field = nil
  begin
    __fields.each { |field|
      __dump_field(send(field.name), field)
    }
  rescue
    STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
    raise
  end
  self
end

Returns:



# File 'lib/libbin.rb', line 18

#__fieldsArray<Field>

Return the structure class fields

Returns:



109
110
111
# File 'lib/libbin.rb', line 109

def __fields
  return self.class.fields
end

#__load(input, input_big, parent = nil, index = nil) ⇒ Structure

Fill in the structure by loading it from input.

Examples:

# Original Ruby implementation
def __load(input, input_big, parent = nil, index = nil)
  __set_load_state(input, input_big, parent, index)
  __load_fields
  __unset_load_state
  self
end

Parameters:

  • input (IO)

    the stream to load the structure from

  • input_big (Boolean)

    the endianness of input

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

Returns:

#__load_field(field) ⇒ Object

Load the value of a structure field.

Examples:

# Original Ruby implementation
def __load_field(field)
  return nil if __decode_static_conditions(field).nil?
  vs = __count.times.collect do |it|
    __iterator = it
    if __decode_dynamic_conditions(field)
      __value = __type::load(__input, __input_big, self, it, __length)
      __decode_expect(field.expect, __value)
    else
      nil
    end
  end
  __restore_context
  vs = vs.first unless field.count
  vs
end

Parameters:

  • field (Field)

    the field descriptor

Returns:

  • the field value or nil if the field was inactive

#__load_fieldsStructure

Load the fields of the structure. The load state must have been set beforehand.

Examples:

# Original Ruby implementation
def __load_fields
  field = nil
  begin
    __fields.each { |field|
      send("#{field.name}=", __load_field(field))
    }
  rescue
    STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
    raise
  end
  self
end

Returns:



774
775
776
777
778
779
# File 'ext/libbin/libbin_c.c', line 774

static VALUE cStructure_load_fields(VALUE self) {
  struct fields_state state = {self, Qnil, Qnil};
  rb_rescue(&cStructure_load_fields_wrapper, (VALUE)&state,
            &cStructure_fields_rescue, (VALUE)&state);
  return self;
}

#__restore_contextObject

Restore the field specific context.

Examples:

# Original Ruby implementation
def __restore_context
  __iterator = nil
  __type = nil
  __length = nil
  __count = nil
  __offset = nil
  __condition = nil
  __value = nil
end

Returns:

  • nil

#__set_convert_state(input, output, input_big, output_big, parent, index) ⇒ nil

Set attributes for conversion

Examples:

# Orignal Ruby implementation
def __set_convert_state(input, output, input_big, output_big, parent, index)
  __input_big = input_big
  __output_big = output_big
  __input = input
  __output = output
  __parent = parent
  __index = index
  __position = input.tell
  __cur_position = __position
end

Parameters:

  • input (IO)

    the stream to read data from

  • output (IO)

    the stream to write data to

  • input_big (Boolean)

    str endianness of input

  • output_big (Boolean)

    str endianness of output

  • parent (nil, Structure)

    the parent if it exists, nil otherwise

  • index (nil, Integer)

    the index if the structure is repeated, nil otherwise

Returns:

  • (nil)


239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'ext/libbin/libbin_c.c', line 239

static VALUE cStructure_set_convert_state(
    VALUE self,
    VALUE input,
    VALUE output,
    VALUE input_big,
    VALUE output_big,
    VALUE parent,
    VALUE index)
{
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__input = input;
  data->__output = output;
  data->__input_big = input_big;
  data->__output_big = output_big;
  data->__parent = parent;
  data->__index = index;
  data->__position = rb_funcall(input, id_tell, 0);
  data->__cur_position = data->__position;
  return Qnil;
}

#__set_dump_state(output, output_big, parent, index) ⇒ nil

Set attributes for dumping

Examples:

# Orignal Ruby implementation
def __set_dump_state(output, output_big, parent, index)
  __output_big = output_big
  __output = output
  __parent = parent
  __index = index
  __position = output.tell
  __cur_position = __position
end

Parameters:

  • output (IO)

    the stream to write data to

  • output_big (Boolean)

    str endianness of output

  • parent (nil, Structure)

    the parent if it exists, nil otherwise

  • index (nil, Integer)

    the index if the structure is repeated, nil otherwise

Returns:

  • (nil)


342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'ext/libbin/libbin_c.c', line 342

static VALUE cStructure_set_dump_state(
    VALUE self,
    VALUE output,
    VALUE output_big,
    VALUE parent,
    VALUE index)
{
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__output = output;
  data->__output_big = output_big;
  data->__parent = parent;
  data->__index = index;
  data->__position = rb_funcall(output, id_tell, 0);
  data->__cur_position = data->__position;
  return Qnil;
}

#__set_load_state(input, input_big, parent, index) ⇒ nil

Set attributes for loading

Examples:

# Orignal Ruby implementation
def __set_load_state(input, input_big, parent, index)
  __input_big = input_big
  __input = input
  __parent = parent
  __index = index
  __position = input.tell
  __cur_position = __position
end

Parameters:

  • input (IO)

    the stream to read data from

  • input_big (Boolean)

    str endianness of input

  • parent (nil, Structure)

    the parent if it exists, nil otherwise

  • index (nil, Integer)

    the index if the structure is repeated, nil otherwise

Returns:

  • (nil)


308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'ext/libbin/libbin_c.c', line 308

static VALUE cStructure_set_load_state(
    VALUE self,
    VALUE input,
    VALUE input_big,
    VALUE parent,
    VALUE index)
{
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__input = input;
  data->__input_big = input_big;
  data->__parent = parent;
  data->__index = index;
  data->__position = rb_funcall(input, id_tell, 0);
  data->__cur_position = data->__position;
  return Qnil;
}

#__set_size_state(position, parent, index) ⇒ nil

Set attributes for computing size or shape

Examples:

# Orignal Ruby implementation
def __set_size_state(position, parent, index)
  __parent = parent
  __index = index
  __position = position
  __cur_position = __position
end

Parameters:

  • position (Integer)

    The position of the field

  • parent (nil, Structure)

    the parent if it exists, nil otherwise

  • index (nil, Integer)

    the index if the structure is repeated, nil otherwise

Returns:

  • (nil)


279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'ext/libbin/libbin_c.c', line 279

static VALUE cStructure_set_size_state(
    VALUE self,
    VALUE position,
    VALUE parent,
    VALUE index)
{
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__parent = parent;
  data->__index = index;
  data->__position = position;
  data->__cur_position = data->__position;
  return Qnil;
}

#__shape(offset = 0, parent = nil, index = nil, kind = DataShape) ⇒ kind

Return the shape of the structure.

Examples:

# Original Ruby implementation
def __shape(previous_offset = 0, parent = nil, index = nil, kind = DataShape)
  __set_size_state(previous_offset, parent, index)
  members = __shape_fields(kind)
  __unset_size_state
  return nil if members.values.compact.size <= 0
  kind::new(members)
end

Parameters:

  • offset (Integer) (defaults to: 0)

    the base position of the field

  • parent (Structure) (defaults to: nil)

    if given, the parent of the structure

  • index (Integer) (defaults to: nil)

    if given, the structure is repeated and index is the rank this structure

  • kind (Class) (defaults to: DataShape)

    the kind of structure to create

Returns:

  • (kind)

    the the shape of the structure



898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
# File 'ext/libbin/libbin_c.c', line 898

static VALUE cStructure_shape(int argc, VALUE *argv, VALUE self) {
  VALUE previous_offset;
  VALUE parent;
  VALUE index;
  VALUE kind;
  rb_scan_args(argc, argv, "04", &previous_offset, &parent, &index, &kind);
  if (NIL_P(previous_offset))
    previous_offset = INT2FIX(0);
  if (NIL_P(kind))
    kind = cDataShape;
  rb_funcall(self, id___set_size_state, 3, previous_offset, parent, index);
  VALUE members = rb_funcall(self, id___shape_fields, 1, kind);
  rb_funcall(self, id___unset_size_state, 0);
  if (RARRAY_LEN(rb_funcall(rb_funcall(members, rb_intern("values"), 0), rb_intern("compact"), 0)) <= 0)
    return Qnil;
  return rb_class_new_instance(1, &members, kind);
}

#__shape_field(value, kind, field) ⇒ nil, ...

Return the shape of the structure field.

Examples:

# Original Ruby implementation
def __shape_field(vs, kind, field)
  return nil if __decode_static_conditions(field).nil?
  vs = [vs] unless field.count
  vs = vs.each_with_index.collect do |v, it|
    __iterator = it
    if __decode_dynamic_conditions(field)
      sh = __type::shape(v, __cur_position, self, it, kind, __length)
      __cur_position = sh.last + 1 if sh.last && sh.last >= 0
      sh
    end
  end
  __restore_context
  vs = field.count ? kind.new(vs) : vs.first
  vs
end

Parameters:

  • value

    the field value

  • kind (Class)

    the class of the shape required

  • field (Field)

    the field descriptor

Returns:

  • (nil, kind, Array<kind>)

    the field shape, or nil if the field was inactive

#__shape_fields(kind) ⇒ Hash{Symbol=>kind}

Return the shape of the structure fields in a Hash, indexed by the fields’ names. The size state must have been set beforehand.

Examples:

# Original Ruby implementation
def __shape_fields(kind)
  members = {}
  field = nil
  begin
    __fields.each { |field|
      members[field.name] = __shape_field(send(field.name), kind, field)
    }
  rescue
    LibBin.output.puts "#{self.class}: #{field.name}(#{field.type})" if LibBin.output
    raise
  end
  return members
end

Parameters:

  • kind (Class)

    the kind of structure to create

Returns:

  • (Hash{Symbol=>kind})

    the fields shape



846
847
848
849
850
# File 'ext/libbin/libbin_c.c', line 846

static VALUE cStructure_shape_fields(VALUE self, VALUE kind) {
  struct shape_fields_state state = {self, Qnil, Qnil, kind};
  return rb_rescue(&cStructure_shape_fields_wrapper, (VALUE)&state,
                   &cStructure_fields_rescue, (VALUE)&state);
}

#__size(offset = 0, parent = nil, index = nil) ⇒ Integer

Returns the size of the structure

Parameters:

  • offset (Integer) (defaults to: 0)

    position in the stream

  • parent (Structure) (defaults to: nil)

    if given, parent structure

  • index (Integer) (defaults to: nil)

    index if part of a repeated field inside parent

Returns:

  • (Integer)

    size of the structure



60
61
62
# File 'lib/libbin.rb', line 60

def __size(offset = 0, parent = nil, index = nil)
  __shape(offset, parent, index, DataRange).size
end

#__unset_convert_statenil

Unset attributes after conversion.

Examples:

# Orignal Ruby implementation
def __unset_convert_state
  __input_big = nil
  __output_big = nil
  __input = nil
  __output = nil
  __parent = nil
  __index = nil
  __position = nil
  __cur_position = nil
end

Returns:

  • (nil)


263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'ext/libbin/libbin_c.c', line 263

static VALUE cStructure_unset_convert_state(VALUE self) {
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__input = Qnil;
  data->__output = Qnil;
  data->__input_big = Qnil;
  data->__output_big = Qnil;
  data->__parent = Qnil;
  data->__index = Qnil;
  data->__position = Qnil;
  data->__cur_position = Qnil;
  return Qnil;
}

#__unset_dump_statenil

Unset attributes after dumping

Examples:

# Orignal Ruby implementation
def __unset_dump_state
  __output_big = nil
  __output = nil
  __parent = nil
  __index = nil
  __position = nil
  __cur_position = nil
end

Returns:

  • (nil)


362
363
364
365
366
367
368
369
370
371
372
# File 'ext/libbin/libbin_c.c', line 362

static VALUE cStructure_unset_dump_state(VALUE self) {
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__output = Qnil;
  data->__output_big = Qnil;
  data->__parent = Qnil;
  data->__index = Qnil;
  data->__position = Qnil;
  data->__cur_position = Qnil;
  return Qnil;
}

#__unset_load_statenil

Unset attributes after loading

Examples:

# Orignal Ruby implementation
def __unset_load_state
  __input_big = nil
  __input = nil
  __parent = nil
  __index = nil
  __position = nil
  __cur_position = nil
end

Returns:

  • (nil)


328
329
330
331
332
333
334
335
336
337
338
# File 'ext/libbin/libbin_c.c', line 328

static VALUE cStructure_unset_load_state(VALUE self) {
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__input = Qnil;
  data->__input_big = Qnil;
  data->__parent = Qnil;
  data->__index = Qnil;
  data->__position = Qnil;
  data->__cur_position = Qnil;
  return Qnil;
}

#__unset_size_statenil

Unset attributes after size or shape computation

Examples:

# Orignal Ruby implementation
def __unset_size_state
  __parent = nil
  __index = nil
  __position = nil
  __cur_position = nil
end

Returns:

  • (nil)


296
297
298
299
300
301
302
303
304
# File 'ext/libbin/libbin_c.c', line 296

static VALUE cStructure_unset_size_state(VALUE self) {
  struct cStructure_data *data;
  TypedData_Get_Struct(self, struct cStructure_data, &cStructure_type, data);
  data->__parent = Qnil;
  data->__index = Qnil;
  data->__position = Qnil;
  data->__cur_position = Qnil;
  return Qnil;
}