rexml 3.4.0 → 3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/rexml/node.rb CHANGED
@@ -26,7 +26,7 @@ module REXML
26
26
  # REXML::Formatters package for changing the output style.
27
27
  def to_s indent=nil
28
28
  unless indent.nil?
29
- Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated", uplevel: 1)
29
+ Kernel.warn( "#{self.class.name}#to_s(indent) parameter is deprecated", uplevel: 1)
30
30
  f = REXML::Formatters::Pretty.new( indent )
31
31
  f.write( self, rv = "" )
32
32
  else
@@ -68,7 +68,7 @@ module REXML
68
68
  each_recursive {|node|
69
69
  return node if block.call(node)
70
70
  }
71
- return nil
71
+ nil
72
72
  end
73
73
 
74
74
  # Returns the position that +self+ holds in its parent's array, indexed
@@ -144,6 +144,7 @@ module REXML
144
144
  PEREFERENCE_PATTERN = /#{PEREFERENCE}/um
145
145
  TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um
146
146
  CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um
147
+ EQUAL_PATTERN = /\s*=\s*/um
147
148
  ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um
148
149
  NAME_PATTERN = /#{NAME}/um
149
150
  GEDECL_PATTERN = "\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
@@ -168,6 +169,7 @@ module REXML
168
169
  @entity_expansion_limit = Security.entity_expansion_limit
169
170
  @entity_expansion_text_limit = Security.entity_expansion_text_limit
170
171
  @source.ensure_buffer
172
+ @version = nil
171
173
  end
172
174
 
173
175
  def add_listener( listener )
@@ -206,12 +208,12 @@ module REXML
206
208
 
207
209
  # Returns true if there are no more events
208
210
  def empty?
209
- return (@source.empty? and @stack.empty?)
211
+ (@source.empty? and @stack.empty?)
210
212
  end
211
213
 
212
214
  # Returns true if there are more events. Synonymous with !empty?
213
215
  def has_next?
214
- return !(@source.empty? and @stack.empty?)
216
+ !(@source.empty? and @stack.empty?)
215
217
  end
216
218
 
217
219
  # Push an event back on the head of the stream. This method
@@ -277,17 +279,10 @@ module REXML
277
279
  return process_instruction
278
280
  elsif @source.match?("<!", true)
279
281
  if @source.match?("--", true)
280
- md = @source.match(/(.*?)-->/um, true)
281
- if md.nil?
282
- raise REXML::ParseException.new("Unclosed comment", @source)
283
- end
284
- if /--|-\z/.match?(md[1])
285
- raise REXML::ParseException.new("Malformed comment", @source)
286
- end
287
- return [ :comment, md[1] ]
282
+ return [ :comment, process_comment ]
288
283
  elsif @source.match?("DOCTYPE", true)
289
284
  base_error_message = "Malformed DOCTYPE"
290
- unless @source.match?(/\s+/um, true)
285
+ unless @source.skip_spaces
291
286
  if @source.match?(">")
292
287
  message = "#{base_error_message}: name is missing"
293
288
  else
@@ -297,10 +292,11 @@ module REXML
297
292
  raise REXML::ParseException.new(message, @source)
298
293
  end
299
294
  name = parse_name(base_error_message)
300
- if @source.match?(/\s*\[/um, true)
295
+ @source.skip_spaces
296
+ if @source.match?("[", true)
301
297
  id = [nil, nil, nil]
302
298
  @document_status = :in_doctype
303
- elsif @source.match?(/\s*>/um, true)
299
+ elsif @source.match?(">", true)
304
300
  id = [nil, nil, nil]
305
301
  @document_status = :after_doctype
306
302
  @source.ensure_buffer
@@ -312,9 +308,10 @@ module REXML
312
308
  # For backward compatibility
313
309
  id[1], id[2] = id[2], nil
314
310
  end
315
- if @source.match?(/\s*\[/um, true)
311
+ @source.skip_spaces
312
+ if @source.match?("[", true)
316
313
  @document_status = :in_doctype
317
- elsif @source.match?(/\s*>/um, true)
314
+ elsif @source.match?(">", true)
318
315
  @document_status = :after_doctype
319
316
  @source.ensure_buffer
320
317
  else
@@ -324,7 +321,7 @@ module REXML
324
321
  end
325
322
  args = [:start_doctype, name, *id]
326
323
  if @document_status == :after_doctype
327
- @source.match?(/\s*/um, true)
324
+ @source.skip_spaces
328
325
  @stack << [ :end_doctype ]
329
326
  end
330
327
  return args
@@ -335,7 +332,7 @@ module REXML
335
332
  end
336
333
  end
337
334
  if @document_status == :in_doctype
338
- @source.match?(/\s*/um, true) # skip spaces
335
+ @source.skip_spaces
339
336
  start_position = @source.position
340
337
  if @source.match?("<!", true)
341
338
  if @source.match?("ELEMENT", true)
@@ -378,7 +375,7 @@ module REXML
378
375
  md = @source.match(Private::ATTLISTDECL_END, true)
379
376
  raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
380
377
  element = md[1]
381
- contents = md[0]
378
+ contents = "<!ATTLIST" + md[0]
382
379
 
383
380
  pairs = {}
384
381
  values = md[0].strip.scan( ATTDEF_RE )
@@ -396,7 +393,7 @@ module REXML
396
393
  return [ :attlistdecl, element, pairs, contents ]
397
394
  elsif @source.match?("NOTATION", true)
398
395
  base_error_message = "Malformed notation declaration"
399
- unless @source.match?(/\s+/um, true)
396
+ unless @source.skip_spaces
400
397
  if @source.match?(">")
401
398
  message = "#{base_error_message}: name is missing"
402
399
  else
@@ -409,30 +406,28 @@ module REXML
409
406
  id = parse_id(base_error_message,
410
407
  accept_external_id: true,
411
408
  accept_public_id: true)
412
- unless @source.match?(/\s*>/um, true)
409
+ @source.skip_spaces
410
+ unless @source.match?(">", true)
413
411
  message = "#{base_error_message}: garbage before end >"
414
412
  raise REXML::ParseException.new(message, @source)
415
413
  end
416
414
  return [:notationdecl, name, *id]
417
- elsif md = @source.match(/--(.*?)-->/um, true)
418
- case md[1]
419
- when /--/, /-\z/
420
- raise REXML::ParseException.new("Malformed comment", @source)
421
- end
422
- return [ :comment, md[1] ] if md
415
+ elsif @source.match?("--", true)
416
+ return [ :comment, process_comment ]
417
+ else
418
+ raise REXML::ParseException.new("Malformed node: Started with '<!' but not a comment nor ELEMENT,ENTITY,ATTLIST,NOTATION", @source)
423
419
  end
424
420
  elsif match = @source.match(/(%.*?;)\s*/um, true)
425
421
  return [ :externalentity, match[1] ]
426
422
  elsif @source.match?(/\]\s*>/um, true)
427
423
  @document_status = :after_doctype
428
424
  return [ :end_doctype ]
429
- end
430
- if @document_status == :in_doctype
425
+ else
431
426
  raise ParseException.new("Malformed DOCTYPE: invalid declaration", @source)
432
427
  end
433
428
  end
434
429
  if @document_status == :after_doctype
435
- @source.match?(/\s*/um, true)
430
+ @source.skip_spaces
436
431
  end
437
432
  begin
438
433
  start_position = @source.position
@@ -457,23 +452,19 @@ module REXML
457
452
  end
458
453
  return [ :end_element, last_tag ]
459
454
  elsif @source.match?("!", true)
460
- md = @source.match(/([^>]*>)/um)
461
455
  #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
462
- raise REXML::ParseException.new("Malformed node", @source) unless md
463
- if md[0][0] == ?-
464
- md = @source.match(/--(.*?)-->/um, true)
465
-
466
- if md.nil? || /--|-\z/.match?(md[1])
467
- raise REXML::ParseException.new("Malformed comment", @source)
456
+ if @source.match?("--", true)
457
+ return [ :comment, process_comment ]
458
+ elsif @source.match?("[CDATA[", true)
459
+ text = @source.read_until("]]>")
460
+ if text.chomp!("]]>")
461
+ return [ :cdata, text ]
462
+ else
463
+ raise REXML::ParseException.new("Malformed CDATA: Missing end ']]>'", @source)
468
464
  end
469
-
470
- return [ :comment, md[1] ]
471
465
  else
472
- md = @source.match(/\[CDATA\[(.*?)\]\]>/um, true)
473
- return [ :cdata, md[1] ] if md
466
+ raise REXML::ParseException.new("Malformed node: Started with '<!' but not a comment nor CDATA", @source)
474
467
  end
475
- raise REXML::ParseException.new( "Declarations can only occur "+
476
- "in the doctype declaration.", @source)
477
468
  elsif @source.match?("?", true)
478
469
  return process_instruction
479
470
  else
@@ -533,7 +524,8 @@ module REXML
533
524
  raise REXML::ParseException.new( "Exception parsing",
534
525
  @source, self, (error ? error : $!) )
535
526
  end
536
- return [ :dummy ]
527
+ # NOTE: The end of the method never runs, because it is unreachable.
528
+ # All branches of code above have explicit unconditional return or raise statements.
537
529
  end
538
530
  private :pull_event
539
531
 
@@ -652,6 +644,10 @@ module REXML
652
644
  true
653
645
  end
654
646
 
647
+ def normalize_xml_declaration_encoding(xml_declaration_encoding)
648
+ /\AUTF-16(?:BE|LE)\z/i.match?(xml_declaration_encoding) ? "UTF-16" : nil
649
+ end
650
+
655
651
  def parse_name(base_error_message)
656
652
  md = @source.match(Private::NAME_PATTERN, true)
657
653
  unless md
@@ -731,39 +727,137 @@ module REXML
731
727
  end
732
728
  end
733
729
 
730
+ def process_comment
731
+ text = @source.read_until("-->")
732
+ unless text.chomp!("-->")
733
+ raise REXML::ParseException.new("Unclosed comment: Missing end '-->'", @source)
734
+ end
735
+
736
+ if text.include? "--" or text.end_with?("-")
737
+ raise REXML::ParseException.new("Malformed comment", @source)
738
+ end
739
+ text
740
+ end
741
+
734
742
  def process_instruction
735
743
  name = parse_name("Malformed XML: Invalid processing instruction node")
736
- if @source.match?(/\s+/um, true)
737
- match_data = @source.match(/(.*?)\?>/um, true)
738
- unless match_data
739
- raise ParseException.new("Malformed XML: Unclosed processing instruction", @source)
744
+ if name == "xml"
745
+ xml_declaration
746
+ else # PITarget
747
+ if @source.skip_spaces # e.g. <?name content?>
748
+ start_position = @source.position
749
+ content = @source.read_until("?>")
750
+ unless content.chomp!("?>")
751
+ @source.position = start_position
752
+ raise ParseException.new("Malformed XML: Unclosed processing instruction: <#{name}>", @source)
753
+ end
754
+ else # e.g. <?name?>
755
+ content = nil
756
+ unless @source.match?("?>", true)
757
+ raise ParseException.new("Malformed XML: Unclosed processing instruction: <#{name}>", @source)
758
+ end
740
759
  end
741
- content = match_data[1]
742
- else
743
- content = nil
760
+ [:processing_instruction, name, content]
761
+ end
762
+ end
763
+
764
+ def xml_declaration
765
+ unless @version.nil?
766
+ raise ParseException.new("Malformed XML: XML declaration is duplicated", @source)
767
+ end
768
+ if @document_status
769
+ raise ParseException.new("Malformed XML: XML declaration is not at the start", @source)
770
+ end
771
+ unless @source.skip_spaces
772
+ raise ParseException.new("Malformed XML: XML declaration misses spaces before version", @source)
773
+ end
774
+ unless @source.match?("version", true)
775
+ raise ParseException.new("Malformed XML: XML declaration misses version", @source)
776
+ end
777
+ @version = parse_attribute_value_with_equal("xml")
778
+ unless @source.skip_spaces
744
779
  unless @source.match?("?>", true)
745
- raise ParseException.new("Malformed XML: Unclosed processing instruction", @source)
780
+ raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
746
781
  end
782
+ encoding = normalize_xml_declaration_encoding(@source.encoding)
783
+ return [ :xmldecl, @version, encoding, nil ] # e.g. <?xml version="1.0"?>
747
784
  end
748
- if name == "xml"
749
- if @document_status
750
- raise ParseException.new("Malformed XML: XML declaration is not at the start", @source)
785
+
786
+ if @source.match?("encoding", true)
787
+ encoding = parse_attribute_value_with_equal("xml")
788
+ unless @source.skip_spaces
789
+ unless @source.match?("?>", true)
790
+ raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
791
+ end
792
+ if need_source_encoding_update?(encoding)
793
+ @source.encoding = encoding
794
+ end
795
+ encoding ||= normalize_xml_declaration_encoding(@source.encoding)
796
+ return [ :xmldecl, @version, encoding, nil ] # e.g. <?xml version="1.1" encoding="UTF-8"?>
751
797
  end
752
- version = VERSION.match(content)
753
- version = version[1] unless version.nil?
754
- encoding = ENCODING.match(content)
755
- encoding = encoding[1] unless encoding.nil?
756
- if need_source_encoding_update?(encoding)
757
- @source.encoding = encoding
798
+ end
799
+
800
+ if @source.match?("standalone", true)
801
+ standalone = parse_attribute_value_with_equal("xml")
802
+ case standalone
803
+ when "yes", "no"
804
+ else
805
+ raise ParseException.new("Malformed XML: XML declaration standalone is not yes or no : <#{standalone}>", @source)
758
806
  end
759
- if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding
760
- encoding = "UTF-16"
807
+ end
808
+ @source.skip_spaces
809
+ unless @source.match?("?>", true)
810
+ raise ParseException.new("Malformed XML: Unclosed XML declaration", @source)
811
+ end
812
+
813
+ if need_source_encoding_update?(encoding)
814
+ @source.encoding = encoding
815
+ end
816
+ encoding ||= normalize_xml_declaration_encoding(@source.encoding)
817
+
818
+ # e.g. <?xml version="1.0" ?>
819
+ # <?xml version="1.1" encoding="UTF-8" ?>
820
+ # <?xml version="1.1" standalone="yes"?>
821
+ # <?xml version="1.1" encoding="UTF-8" standalone="yes" ?>
822
+ [ :xmldecl, @version, encoding, standalone ]
823
+ end
824
+
825
+ if StringScanner::Version < "3.1.1"
826
+ def scan_quote
827
+ @source.match(/(['"])/, true)&.[](1)
828
+ end
829
+ else
830
+ def scan_quote
831
+ case @source.peek_byte
832
+ when 34 # '"'.ord
833
+ @source.scan_byte
834
+ '"'
835
+ when 39 # "'".ord
836
+ @source.scan_byte
837
+ "'"
838
+ else
839
+ nil
761
840
  end
762
- standalone = STANDALONE.match(content)
763
- standalone = standalone[1] unless standalone.nil?
764
- return [ :xmldecl, version, encoding, standalone ]
765
841
  end
766
- [:processing_instruction, name, content]
842
+ end
843
+
844
+ def parse_attribute_value_with_equal(name)
845
+ unless @source.match?(Private::EQUAL_PATTERN, true)
846
+ message = "Missing attribute equal: <#{name}>"
847
+ raise REXML::ParseException.new(message, @source)
848
+ end
849
+ unless quote = scan_quote
850
+ message = "Missing attribute value start quote: <#{name}>"
851
+ raise REXML::ParseException.new(message, @source)
852
+ end
853
+ start_position = @source.position
854
+ value = @source.read_until(quote)
855
+ unless value.chomp!(quote)
856
+ @source.position = start_position
857
+ message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
858
+ raise REXML::ParseException.new(message, @source)
859
+ end
860
+ value
767
861
  end
768
862
 
769
863
  def parse_attributes(prefixes)
@@ -780,24 +874,8 @@ module REXML
780
874
  name = match[1]
781
875
  prefix = match[2]
782
876
  local_part = match[3]
783
-
784
- unless @source.match?(/\s*=\s*/um, true)
785
- message = "Missing attribute equal: <#{name}>"
786
- raise REXML::ParseException.new(message, @source)
787
- end
788
- unless match = @source.match(/(['"])/, true)
789
- message = "Missing attribute value start quote: <#{name}>"
790
- raise REXML::ParseException.new(message, @source)
791
- end
792
- quote = match[1]
793
- start_position = @source.position
794
- value = @source.read_until(quote)
795
- unless value.chomp!(quote)
796
- @source.position = start_position
797
- message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
798
- raise REXML::ParseException.new(message, @source)
799
- end
800
- @source.match?(/\s*/um, true)
877
+ value = parse_attribute_value_with_equal(name)
878
+ @source.skip_spaces
801
879
  if prefix == "xmlns"
802
880
  if local_part == "xml"
803
881
  if value != Private::XML_PREFIXED_NAMESPACE
@@ -215,7 +215,7 @@ module REXML
215
215
  else
216
216
  path << yield( parsed )
217
217
  end
218
- return path.squeeze(" ")
218
+ path.squeeze(" ")
219
219
  end
220
220
  # For backward compatibility
221
221
  alias_method :preciate_to_string, :predicate_to_path
@@ -252,7 +252,7 @@ module REXML
252
252
  path = path[1..-1]
253
253
  end
254
254
  end
255
- return RelativeLocationPath( path, parsed ) if path.size > 0
255
+ RelativeLocationPath( path, parsed ) if path.size > 0
256
256
  end
257
257
 
258
258
  #RelativeLocationPath
@@ -388,7 +388,7 @@ module REXML
388
388
  else
389
389
  path = original_path
390
390
  end
391
- return path
391
+ path
392
392
  end
393
393
 
394
394
  # Filters the supplied nodeset on the predicate(s)
@@ -600,7 +600,7 @@ module REXML
600
600
  end
601
601
  rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/
602
602
  parsed.concat(n)
603
- return rest
603
+ rest
604
604
  end
605
605
 
606
606
  #| FilterExpr Predicate
@@ -41,7 +41,7 @@ module REXML
41
41
  else
42
42
  results = filter([element], path)
43
43
  end
44
- return results
44
+ results
45
45
  end
46
46
 
47
47
  # Given an array of nodes it filters the array based on the path. The
@@ -51,18 +51,18 @@ module REXML
51
51
  return elements if path.nil? or path == '' or elements.size == 0
52
52
  case path
53
53
  when /^\/\//u # Descendant
54
- return axe( elements, "descendant-or-self", $' )
54
+ axe( elements, "descendant-or-self", $' )
55
55
  when /^\/?\b(\w[-\w]*)\b::/u # Axe
56
- return axe( elements, $1, $' )
56
+ axe( elements, $1, $' )
57
57
  when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
58
58
  rest = $'
59
59
  results = []
60
60
  elements.each do |element|
61
61
  results |= filter( element.to_a, rest )
62
62
  end
63
- return results
63
+ results
64
64
  when /^\/?(\w[-\w]*)\(/u # / Function
65
- return function( elements, $1, $' )
65
+ function( elements, $1, $' )
66
66
  when Namespace::NAMESPLIT # Element name
67
67
  name = $2
68
68
  ns = $1
@@ -73,21 +73,21 @@ module REXML
73
73
  (element.name == name and
74
74
  element.namespace == Functions.namespace_context[ns])))
75
75
  end
76
- return filter( elements, rest )
76
+ filter( elements, rest )
77
77
  when /^\/\[/u
78
78
  matches = []
79
79
  elements.each do |element|
80
80
  matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
81
81
  end
82
- return matches
82
+ matches
83
83
  when /^\[/u # Predicate
84
- return predicate( elements, path )
84
+ predicate( elements, path )
85
85
  when /^\/?\.\.\./u # Ancestor
86
- return axe( elements, "ancestor", $' )
86
+ axe( elements, "ancestor", $' )
87
87
  when /^\/?\.\./u # Parent
88
- return filter( elements.collect{|e|e.parent}, $' )
88
+ filter( elements.collect{|e|e.parent}, $' )
89
89
  when /^\/?\./u # Self
90
- return filter( elements, $' )
90
+ filter( elements, $' )
91
91
  when /^\*/u # Any
92
92
  results = []
93
93
  elements.each do |element|
@@ -98,9 +98,10 @@ module REXML
98
98
  # results |= filter( children, $' )
99
99
  #end
100
100
  end
101
- return results
101
+ results
102
+ else
103
+ []
102
104
  end
103
- return []
104
105
  end
105
106
 
106
107
  def QuickPath::axe( elements, axe_name, rest )
@@ -138,7 +139,7 @@ module REXML
138
139
  matches = filter(elements.collect{|element|
139
140
  element.previous_sibling}.uniq, rest )
140
141
  end
141
- return matches.uniq
142
+ matches.uniq
142
143
  end
143
144
 
144
145
  OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)'
@@ -200,15 +201,15 @@ module REXML
200
201
  results << element
201
202
  end
202
203
  end
203
- return filter( results, rest )
204
+ filter( results, rest )
204
205
  end
205
206
 
206
207
  def QuickPath::attribute( name )
207
- return Functions.node.attributes[name] if Functions.node.kind_of? Element
208
+ Functions.node.attributes[name] if Functions.node.kind_of? Element
208
209
  end
209
210
 
210
211
  def QuickPath::name()
211
- return Functions.node.name if Functions.node.kind_of? Element
212
+ Functions.node.name if Functions.node.kind_of? Element
212
213
  end
213
214
 
214
215
  def QuickPath::method_missing( id, *args )
@@ -234,7 +235,7 @@ module REXML
234
235
  results << element if Functions.pair[0] == res
235
236
  end
236
237
  end
237
- return results
238
+ results
238
239
  end
239
240
 
240
241
  def QuickPath::parse_args( element, string )
data/lib/rexml/rexml.rb CHANGED
@@ -31,7 +31,7 @@
31
31
  module REXML
32
32
  COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser@germane-software.com>"
33
33
  DATE = "2008/019"
34
- VERSION = "3.4.0"
34
+ VERSION = "3.4.2"
35
35
  REVISION = ""
36
36
 
37
37
  Copyright = COPYRIGHT
@@ -10,7 +10,7 @@ module REXML
10
10
 
11
11
  # Get the entity expansion limit. By default the limit is set to 10000.
12
12
  def self.entity_expansion_limit
13
- return @@entity_expansion_limit
13
+ @@entity_expansion_limit
14
14
  end
15
15
 
16
16
  @@entity_expansion_text_limit = 10_240
@@ -22,7 +22,7 @@ module REXML
22
22
 
23
23
  # Get the entity expansion limit. By default the limit is set to 10240.
24
24
  def self.entity_expansion_text_limit
25
- return @@entity_expansion_text_limit
25
+ @@entity_expansion_text_limit
26
26
  end
27
27
  end
28
28
  end
data/lib/rexml/source.rb CHANGED
@@ -65,11 +65,18 @@ module REXML
65
65
  attr_reader :encoding
66
66
 
67
67
  module Private
68
+ SPACES_PATTERN = /\s+/um
68
69
  SCANNER_RESET_SIZE = 100000
69
70
  PRE_DEFINED_TERM_PATTERNS = {}
70
- pre_defined_terms = ["'", '"', "<"]
71
- pre_defined_terms.each do |term|
72
- PRE_DEFINED_TERM_PATTERNS[term] = /#{Regexp.escape(term)}/
71
+ pre_defined_terms = ["'", '"', "<", "]]>", "?>"]
72
+ if StringScanner::Version < "3.1.1"
73
+ pre_defined_terms.each do |term|
74
+ PRE_DEFINED_TERM_PATTERNS[term] = /#{Regexp.escape(term)}/
75
+ end
76
+ else
77
+ pre_defined_terms.each do |term|
78
+ PRE_DEFINED_TERM_PATTERNS[term] = term
79
+ end
73
80
  end
74
81
  end
75
82
  private_constant :Private
@@ -144,6 +151,10 @@ module REXML
144
151
  end
145
152
  end
146
153
 
154
+ def skip_spaces
155
+ @scanner.skip(Private::SPACES_PATTERN) ? true : false
156
+ end
157
+
147
158
  def position
148
159
  @scanner.pos
149
160
  end
@@ -152,6 +163,14 @@ module REXML
152
163
  @scanner.pos = pos
153
164
  end
154
165
 
166
+ def peek_byte
167
+ @scanner.peek_byte
168
+ end
169
+
170
+ def scan_byte
171
+ @scanner.scan_byte
172
+ end
173
+
155
174
  # @return true if the Source is exhausted
156
175
  def empty?
157
176
  @scanner.eos?