Class: SubObject

Inherits:
Object
  • Object
show all
Defined in:
lib/sub_object.rb,
lib/sub_object/sub_array.rb

Overview

Parent class for SubString and SubObject::SubArray or similar.

Summary

This class SubObject is the parent class for SubString and alike. This class expresses Ruby sub-Object (like Sub-String), which are obtained with the self[i, j] method, but taking up negligible memory space, as its instance internally holds the (likely positional, though arbitrary) information (i, j) only. It provides the basic interface so the instance behaves exactly like the original class (String for SubString, for example) as duck-typing, except destructive modification, which is prohibited.

If the original object is destructively modified in a way it changes its hash value, warning is issued whenever this instance is accessed.

Important note to the developers

To inherit this class, make sure to include the lines equivalent to the following 2 lines, replacing the method name :to_str (which is for SubString class) to suit your child class.

TO_SOURCE_METHOD = :to_str
alias_method TO_SOURCE_METHOD, :to_source

The full reference is found in the top page SubObject and in Github

Author:

  • Masa Sakano (Wise Babel Ltd)

Direct Known Subclasses

SubArray

Defined Under Namespace

Classes: SubArray

Constant Summary collapse

TO_SOURCE_METHOD =

Symbol of the method that projects to (returns) the original-like instance; e.g., :to_str for String. The value should be overwritten in the child class of SubObject.

:itself
DESTRUCTIVE_METHODS =

List of the names (String) of destructive methods (other than those ending with “!”).

%w( []= << clear concat force_encoding insert prepend replace )

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, pos, size, attr: nil) ⇒ SubObject

Returns a new instance of SubObject equivalent to source[ pos, size ]

Parameters:

  • source (String)
  • pos (Integer)
  • size (Integer)


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/sub_object.rb', line 92

def initialize(source, pos, size, attr: nil)
  @source, @pos, @isize = source, pos, size
  @attr = attr

  # Sanity check
  begin
    _ = @source[@pos, @isize]
  rescue NoMethodError
    raise TypeError, ERR_MSGS[:no_method_error]
  rescue ArgumentError
    raise TypeError, ERR_MSGS[:argument_error]
  rescue TypeError
    raise TypeError, ERR_MSGS[:type_error]%[pos.inspect, size.inspect]
  end

  if !source.respond_to? self.class::TO_SOURCE_METHOD
    raise TypeError, "Wrong source class #{source.class.name} for this class #{self.class.name}"
  end

  # Hash value retained to check its potential destructive change
  @hash = @source.hash
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *rest, &block) ⇒ Object

method_missing for any but destructive methods

Returns:

  • (Object)

See Also:



191
192
193
# File 'lib/sub_object.rb', line 191

def method_missing(method_name, *rest, &block)
  destructive_method?(method_name) ? super : to_source.send(method_name, *rest, &block)
end

Instance Attribute Details

#attrObject

Setter/Getter of the attribute. nil in default.



85
86
87
# File 'lib/sub_object.rb', line 85

def attr
  @attr
end

#posObject (readonly)

Starting (character) position



82
83
84
# File 'lib/sub_object.rb', line 82

def pos
  @pos
end

Class Method Details

.verboseObject

Getter of the class instance variable @verbosity



61
62
63
# File 'lib/sub_object.rb', line 61

def self.verbose
  (defined? @verbosity) ? @verbosity : nil
end

.verbose=(obj) ⇒ Object

Setter of the class instance variable @@verbosity



66
67
68
# File 'lib/sub_object.rb', line 66

def self.verbose=(obj)
  @verbosity=obj
end

Instance Method Details

#<=>(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



175
# File 'lib/sub_object.rb', line 175

def <=>(      *rest); to_source.send(__method__, *rest); end

#==(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



165
# File 'lib/sub_object.rb', line 165

def ==(       *rest); to_source.send(__method__, *rest); end

#===(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



167
# File 'lib/sub_object.rb', line 167

def ===(      *rest); to_source.send(__method__, *rest); end

#=~(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



173
# File 'lib/sub_object.rb', line 173

def =~(       *rest); to_source.send(__method__, *rest); end

#inspectString

Returns:

  • (String)


182
183
184
185
# File 'lib/sub_object.rb', line 182

def inspect
  warn_hash
  sprintf('%s[%d,%d]%s', self.class.name.split(/::/)[-1], @pos, @isize, @source[@pos, @isize].inspect)
end

#inspect_before_sub_objectObject



179
# File 'lib/sub_object.rb', line 179

alias_method :inspect_before_sub_object, :inspect

#is_a?(*rest) ⇒ Boolean

Redefining a method in Object to evaluate via #to_source

Returns:

  • (Boolean)


169
# File 'lib/sub_object.rb', line 169

def is_a?(    *rest); to_source.send(__method__, *rest); end

#kind_of?(*rest) ⇒ Boolean

Redefining a method in Object to evaluate via #to_source

Returns:

  • (Boolean)


171
# File 'lib/sub_object.rb', line 171

def kind_of?(*rest); to_source.send(__method__, *rest); end

#pos_sizeAray

Returns:

  • (Aray)


116
117
118
# File 'lib/sub_object.rb', line 116

def pos_size
  [@pos, @isize]
end

#respond_to_missing?(method_name, *rest) ⇒ Boolean

Obligatory redefinition, following redefined #method_missing

Returns:

  • (Boolean)


196
197
198
# File 'lib/sub_object.rb', line 196

def respond_to_missing?(method_name, *rest)
  destructive_method?(method_name) ? super : to_source.send(:respond_to?, method_name, *rest)
end

#sourceObject

Frozen String returned.



126
127
128
129
130
131
# File 'lib/sub_object.rb', line 126

def source
  warn_hash
  src = @source.dup
  src.freeze
  src
end

#subsizeObject

Returns usually the size (Integer).

Returns:

  • usually the size (Integer)



121
122
123
# File 'lib/sub_object.rb', line 121

def subsize
  @isize
end

#to_s(*rest) ⇒ Object

Redefining a method in Object to evaluate via #to_source



177
# File 'lib/sub_object.rb', line 177

def to_s(     *rest); to_source.send(__method__, *rest); end

#to_sourceObject

Returns the original representation of the instance as in the source

Each child class should set the constant TO_SOURCE_METHOD appropriately and should alias this method to the method registered to TO_SOURCE_METHOD . For example, for SubString,

TO_SOURCE_METHOD = :to_str
alias_method TO_SOURCE_METHOD, :to_source

Warning: DO NOT OVERWRITE THIS METHOD.

Returns:

  • (Object)


145
146
147
148
# File 'lib/sub_object.rb', line 145

def to_source
  warn_hash
  @source[@pos, @isize].send(to_source_method)
end