module NWN::Gff::Field
A Field
wraps a GFF label->value pair, providing:
-
.field_type
describing the field type (e.g. :int) -
.field_value
holding the value of thisField
and, if loaded by Gff::Reader
or through YAML:
-
.field_label
holding the label -
.parent
holding the struct thisField
is child of.
Note that it is ADVISED to use the provided accessors, since they do some structure-keeping in the background. If you do NOT want it to do that, use hash-notation for access:
field['value'], field['type'], field['str_ref'], field['label']
Constants
- DEFAULT_VALUES
The default values of fields.
Attributes
The parent struct. This is set internally by Gff::Reader
on load.
Public Class Methods
Create a new NWN::Gff::Field
# File lib/nwn/gff/field.rb, line 46 def self.new label, type, value s = {}.extend(self) s['label'], s['type'], s['value'] = label, type.to_sym, value s.extend_meta_classes s.validate s end
Validate if value
is within bounds of type
.
# File lib/nwn/gff/field.rb, line 132 def self.valid_for? value, type case type when :byte, :char value.is_a?(Integer) && value >= 0 && value <= 255 when :short value.is_a?(Integer) && value >= -0x8000 && value <= 0x7fff when :word value.is_a?(Integer) && value >= 0 && value <= 0xffff when :int value.is_a?(Integer) && value >= -0x80000000 && value <= 0x7fffffff when :dword value.is_a?(Integer) && value >= 0 && value <= 0xffffffff when :int64 value.is_a?(Integer) && value >= -0x8000000000000000 && value <= 0x7fffffffffffffff when :dword64 value.is_a?(Integer) && value >= 0 && value <= 0xffffffffffffffff when :float, :double value.is_a?(Float) || value.is_a?(Integer) when :resref if !NWN.setting(:resref32) && value.is_a?(String) && value.size > 16 NWN.log_debug("Warning: :resref too long for NWN1, set env NWN_LIB_RESREF32=1 to turn off warning for NWN2.") NWN.log_debug(" Value found: #{value.inspect}") end if NWN.setting(:resref16) value.is_a?(String) && (0..16).member?(value.size) else value.is_a?(String) && (0..32).member?(value.size) end when :cexostr value.is_a?(String) when :cexolocstr value.is_a?(Hash) && value.keys.reject {|x| x.is_a?(Integer) && x >= 0 }.size == 0 && value.values.reject {|x| x.is_a?(String) }.size == 0 when :struct value.is_a?(Hash) when :list value.is_a?(Array) when :void value.is_a?(String) else false end end
Public Instance Methods
# File lib/nwn/yaml_support.rb, line 45 def encode_with out out.map do |map| map.tag = nil map.style = Psych::Nodes::Mapping::FLOW unless NWN::Gff::Handler::YAML::NonInlineableFields.index(self['type']) map.add('type', self['type'].to_s) map.add('str_ref', self['str_ref']) if has_str_ref? map.add('value', self['value']) end end
This extends this field object and its' value with the appropriate meta classes, depending on field_type.
# File lib/nwn/gff/field.rb, line 102 def extend_meta_classes return if field_type == :struct field_klass_name = field_type.to_s.capitalize field_klass = NWN::Gff.const_defined?(field_klass_name, false) ? NWN::Gff.const_get(field_klass_name, false) : nil field_value_klass = NWN::Gff.const_defined?(field_klass_name + 'Value', false) ? NWN::Gff.const_get(field_klass_name + 'Value', false) : nil self.extend(field_klass) unless field_klass.nil? || self.is_a?(field_klass) field_value.extend(field_value_klass) unless field_value_klass.nil? || field_value.is_a?(field_value_klass) end
# File lib/nwn/gff/field.rb, line 77 def field_label self['label'] end
# File lib/nwn/gff/field.rb, line 82 def field_label= l self['label']= l end
# File lib/nwn/gff/field.rb, line 54 def field_type self['type'] end
# File lib/nwn/gff/field.rb, line 59 def field_type= t self['type'] = t end
# File lib/nwn/gff/field.rb, line 64 def field_value self['value'] end
# File lib/nwn/gff/field.rb, line 69 def field_value= v NWN::Gff::Field.valid_for?(v, field_type) or raise ArgumentError, "Given field_value is not valid for type #{field_type.inspect}." self['value'] = v end
# File lib/nwn/gff/cexolocstr.rb, line 2 def has_str_ref? false end
Returns the path to this field, including all parents structs. For example: UTI/PropertiesList/CostTable
# File lib/nwn/gff/field.rb, line 89 def path raise NWN::Gff::GffError, "field not bound to a parent" unless @parent parent_path = @parent.path if @parent.element && @parent.element.field_type == :list idx = @parent.element.field_value.index(@parent) parent_path + "[#{idx}]/" + field_label else parent_path + "/" + field_label end.gsub(%r{/+}, "/") end
# File lib/nwn/json_support.rb, line 38 def to_json(*a) json_box.to_json(*a) end
Validate if this field value is within the bounds of the set type.
# File lib/nwn/gff/field.rb, line 120 def valid? NWN::Gff::Field.valid_for? self.v, self.t end
Validate this field, and raise an Excpetion if not valid.
# File lib/nwn/gff/field.rb, line 125 def validate valid? or raise NWN::Gff::GffError, "#{self.path rescue $!.to_s + '/' + self.l}: " + "value '#{self.v.inspect}' not valid for type '#{self.t.inspect}'" end
Private Instance Methods
# File lib/nwn/json_support.rb, line 27 def json_box t = Hash[self] t.delete('label') case field_type when :void t['value'] = Base64::strict_encode64(t['value']) end t end