Class: MatchSkeleton

Inherits:
Object
  • Object
show all
Defined in:
lib/match_skeleton.rb

Overview

Class MatchSkeleton

To represent MatchData with much less memory use

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(md, string = nil, pos_begin: nil) ⇒ MatchSkeleton

Returns a new instance of MatchSkeleton.

Parameters:

  • md (MatchData)
  • string (String) (defaults to: nil)

    If not specified, it is taken from the first argument (however, that would spoil the whole point of using this class!)

  • pos_begin: (Integer) (defaults to: nil)

    The position Regexp match has started.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/match_skeleton.rb', line 30

def initialize(md, string=nil, pos_begin: nil)
  size_str = md.string.size
  if string && string.size != size_str
    raise ArgumentError, 'The first parameter is obligatory.'
  end
  @string = (string || md.string)
  @regexp = md.regexp
  @pre_match  = (0...md.pre_match.size) # {Range}
  @post_match = ((size_str-md.post_match.size)...size_str)  # {Range}

  # @offsets is Hash with the keys of both Integer and possibly Symbol
  # if names exist.
  names  = md.names
  ar_off = (0..(md.size-1)).map do |n|
    ar = md.offset(n)
#if names[0]=='foo'
#print "DEBUG: ar=#{ar.inspect}\n"
#printf "DEBUG: n=(%d)range=%s\n", n, (ar.first...ar.last).inspect
#end
    (ar.first...ar.last)
  end
  @offsets = {}
  ar_off.each_with_index do |ev, ei|
    @offsets[ei] = ev
    ej = ei - 1
    @offsets[names[ej]] = ev if (ej >= 0 && names[ej])
#print "DEBUG: names=#{names[ei].inspect}\n"
#p names[ei], ev
#p md.offset(:foo)
  end
#printf "DEBUG: offsets=%s\n", @offsets.inspect if !names.empty?
  

  @pos_begin = pos_begin
end

Instance Attribute Details

#pos_beginObject

The position Regexp match has started. For example, both

/x/.match('0000x', 0)
/x/.match('0000x', 3)

give the same (equal) MatchData. This instance variable #pos_begin holds the position (0 or 3 in the cases above), if set explicitly.



24
25
26
# File 'lib/match_skeleton.rb', line 24

def pos_begin
  @pos_begin
end

#regexpObject (readonly)

The same as MatchData#regexp.



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

def regexp
  @regexp
end

#stringObject (readonly)

The same as MatchData#string but it is identical to the original string. If the original string is modified destructively, this too is modified.



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

def string
  @string
end

Instance Method Details

#==(obj) ⇒ Boolean

Comparable with MatchSkeleton and MatchData

A difference in #pos_begin is not taken into account.

Parameters:

Returns:

  • (Boolean)

See Also:



73
74
75
76
77
# File 'lib/match_skeleton.rb', line 73

def ==(obj)
  (string    == obj.string) &&
  (regexp    == obj.regexp) &&
  (pre_match == obj.pre_match)
end

#[](i, j = nil) ⇒ String, ...

The same as MatchData#[]

Parameters:

  • i (Integer, Range, Symbol, String)
  • j (Integer, NilClass) (defaults to: nil)

Returns:

  • (String, Array, NilClass)

Raises:

  • (IndexError)

    if an invalid argument(s) is given.



85
86
87
88
89
90
91
92
93
# File 'lib/match_skeleton.rb', line 85

def [](i, j=nil)
  if j
    to_a[i, j]
  elsif defined?(i.to_sym)
    values_at(i)[0]
  else
    to_a[i]
  end
end

#begin(n) ⇒ Integer

The same as MatchData#begin

Parameters:

  • n (Integer)

Returns:

  • (Integer)


99
100
101
# File 'lib/match_skeleton.rb', line 99

def begin(n)
  offset(n)[0]
end

#capturesArray

The same as MatchData#captures

Returns:

  • (Array)


106
107
108
# File 'lib/match_skeleton.rb', line 106

def captures
  to_a[1..-1]
end

#end(n) ⇒ Integer

The same as MatchData#end

Parameters:

  • n (Integer)

Returns:

  • (Integer)


114
115
116
# File 'lib/match_skeleton.rb', line 114

def end(n)
  offset(n)[1]
end

#eql?(obj) ⇒ Boolean

The same as #== but stricter comparison.

The comparison between MatchSkeleton and MatchData returns false and that between MatchSkeleton with different #pos_begin or those with strings of different Object-IDs also return false.

Parameters:

  • (Object)

Returns:

  • (Boolean)

See Also:



127
128
129
130
131
132
133
# File 'lib/match_skeleton.rb', line 127

def eql?(obj)
  return false if self != obj
  return false if !defined?(obj.pos_begin)
  return false if (string.object_id != obj.string.object_id)
  return false if pos_begin != obj.pos_begin
  return true
end

#inspectString

Similar to MatchData#inspect

Returns:

  • (String)


138
139
140
141
142
143
144
145
# File 'lib/match_skeleton.rb', line 138

def inspect
  core = ''
  ar = (names.empty? ? captures : names)
  ar.each_with_index do |ev, ei|
    core << sprintf(" %d:%s", ei, ev.inspect)
  end
  sprintf("#<%s %s%s>", self.class.to_s, self[0].inspect, core)
end

#namesArray<String>

The same as MatchData#names and Regexp#names

Returns:

  • (Array<String>)


150
151
152
# File 'lib/match_skeleton.rb', line 150

def names
  regexp.names
end

#offset(n) ⇒ Array<integer>

The same as MatchData#offset

Parameters:

  • n (Integer)

Returns:

  • (Array<integer>)


158
159
160
161
162
163
164
165
# File 'lib/match_skeleton.rb', line 158

def offset(n)
  if defined?(n.to_sym)
    n = n.to_s 
    raise IndexError, sprintf("undefined group name reference: %s", n) if !names.include?(n)
  end
  [@offsets[n].first, 
   @offsets[n].last]
end

#post_matchString

The same as MatchData#post_match

Returns:

  • (String)


177
178
179
# File 'lib/match_skeleton.rb', line 177

def post_match
  @string[@post_match]
end

#pre_matchString

The same as MatchData#pre_match

Returns:

  • (String)


170
171
172
# File 'lib/match_skeleton.rb', line 170

def pre_match
  @string[@pre_match]
end

#sizeInteger Also known as: length

The same as MatchData#size

Returns:

  • (Integer)


184
185
186
# File 'lib/match_skeleton.rb', line 184

def size
  to_a.size
end

#to_aArray

The same as MatchData#to_a

Returns:

  • (Array)


192
193
194
195
196
197
# File 'lib/match_skeleton.rb', line 192

def to_a
#print 'DEBUG: '; p @offsets
  indices = @offsets.keys.sort
  indices.delete_if { |i| !defined?(i.divmod) }
  indices.map { |i| string[@offsets[i]] }
end

#to_sString

The same as MatchData#to_s

Returns:

  • (String)


202
203
204
# File 'lib/match_skeleton.rb', line 202

def to_s
  self[0]
end

#values_at(*rest) ⇒ Array

The same as MatchData#values_at

Parameters:

  • *rest (Integer, Symbol, String)

Returns:

  • (Array)


210
211
212
213
214
215
216
217
# File 'lib/match_skeleton.rb', line 210

def values_at(*rest)
  rest.map do |i|
    key = @offsets[i.to_s]
#    printf "DEBUG(%s): offsets=%s string=%s i=%s key=%s r=%s\n", __method__, @offsets.inspect,string.inspect,i.inspect,key.inspect,(string[key].inspect rescue 'nil') if !names.empty?
    raise IndexError, sprintf("undefined group name reference: %s", i) if !key
    string[key]
  end
end