Class: JSON5::Input
- Inherits:
-
Object
- Object
- JSON5::Input
- Defined in:
- lib/json5/input.rb
Defined Under Namespace
Classes: Position
Instance Attribute Summary collapse
-
#column ⇒ Object
readonly
Returns the value of attribute column.
-
#index ⇒ Object
readonly
Returns the value of attribute index.
-
#line ⇒ Object
readonly
Returns the value of attribute line.
-
#line_start_byte ⇒ Object
readonly
Returns the value of attribute line_start_byte.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
Class Method Summary collapse
Instance Method Summary collapse
- #byteslice(start_byte, end_byte = index) ⇒ Object
- #consume_ascii(expected = nil) ⇒ Object
- #consume_ascii_bytes(count) ⇒ Object
- #consume_byte ⇒ Object
- #consume_bytes(count) ⇒ Object
- #consume_codepoint ⇒ Object
- #eof? ⇒ Boolean
- #excerpt_at(byte_offset, radius: 40) ⇒ Object
-
#initialize(source, limits: Limits.default, filename: nil) ⇒ Input
constructor
A new instance of Input.
- #line_terminator?(codepoint) ⇒ Boolean
- #mark ⇒ Object
- #peek_byte(offset = 0) ⇒ Object
- #peek_codepoint ⇒ Object
- #position ⇒ Object
- #remaining ⇒ Object
Constructor Details
#initialize(source, limits: Limits.default, filename: nil) ⇒ Input
Returns a new instance of Input.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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 |
# File 'lib/json5/input.rb', line 9 def initialize(source, limits: Limits.default, filename: nil) unless source.is_a?(String) raise TypeError, "source must be a String" end unless limits.is_a?(Limits) raise ArgumentError, "limits must be a JSON5::Limits" end @filename = filename unless [Encoding::UTF_8, Encoding::US_ASCII].include?(source.encoding) raise EncodingError.new( "source must be UTF-8 or US-ASCII", code: "invalid_encoding", filename: filename, byte_offset: 0, end_byte_offset: [source.bytesize, 1].min, line: 1, column: 1, excerpt: excerpt_for(source, 0) ) end if limits.max_input_bytes && source.bytesize > limits.max_input_bytes line, column = position_for_limit(source, limits.max_input_bytes) raise LimitError.new( "input exceeds max_input_bytes", code: "maximum_input_size_exceeded", filename: filename, byte_offset: limits.max_input_bytes, end_byte_offset: limits.max_input_bytes + 1, line: line, column: column, excerpt: limit_excerpt_for(source, limits.max_input_bytes) ) end unless source.valid_encoding? offset = first_invalid_utf8_offset(source) line, column = position_at(source, offset) raise EncodingError.new( "source is not valid UTF-8", code: "invalid_encoding", filename: filename, byte_offset: offset, end_byte_offset: [offset + 1, source.bytesize].min, line: line, column: column, excerpt: excerpt_for(source, offset) ) end @source = source @limits = limits @index = 0 @line = 1 @column = 1 @line_start_byte = 0 end |
Instance Attribute Details
#column ⇒ Object (readonly)
Returns the value of attribute column.
7 8 9 |
# File 'lib/json5/input.rb', line 7 def column @column end |
#index ⇒ Object (readonly)
Returns the value of attribute index.
7 8 9 |
# File 'lib/json5/input.rb', line 7 def index @index end |
#line ⇒ Object (readonly)
Returns the value of attribute line.
7 8 9 |
# File 'lib/json5/input.rb', line 7 def line @line end |
#line_start_byte ⇒ Object (readonly)
Returns the value of attribute line_start_byte.
7 8 9 |
# File 'lib/json5/input.rb', line 7 def line_start_byte @line_start_byte end |
#source ⇒ Object (readonly)
Returns the value of attribute source.
7 8 9 |
# File 'lib/json5/input.rb', line 7 def source @source end |
Class Method Details
.position_for(source, byte_offset) ⇒ Object
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/json5/input.rb', line 81 def self.position_for(source, byte_offset) return [nil, nil] unless source.is_a?(String) normalized = source.dup normalized.force_encoding(Encoding::UTF_8) unless normalized.encoding == Encoding::UTF_8 input = allocate input.send(:position_at, normalized, [[byte_offset, 0].max, normalized.bytesize].min) rescue ArgumentError, TypeError [nil, nil] end |
Instance Method Details
#byteslice(start_byte, end_byte = index) ⇒ Object
92 93 94 |
# File 'lib/json5/input.rb', line 92 def byteslice(start_byte, end_byte = index) source.byteslice(start_byte...end_byte) end |
#consume_ascii(expected = nil) ⇒ Object
108 109 110 111 112 113 114 |
# File 'lib/json5/input.rb', line 108 def consume_ascii(expected = nil) byte = peek_byte if expected && byte != expected raise ArgumentError, "expected byte #{expected}, got #{byte.inspect}" end consume_byte end |
#consume_ascii_bytes(count) ⇒ Object
120 121 122 123 |
# File 'lib/json5/input.rb', line 120 def consume_ascii_bytes(count) @index += count @column += count end |
#consume_byte ⇒ Object
100 101 102 103 104 105 106 |
# File 'lib/json5/input.rb', line 100 def consume_byte byte = peek_byte return nil unless byte @index += 1 @column += 1 byte end |
#consume_bytes(count) ⇒ Object
116 117 118 |
# File 'lib/json5/input.rb', line 116 def consume_bytes(count) count.times { consume_byte } end |
#consume_codepoint ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/json5/input.rb', line 132 def consume_codepoint codepoint, width = peek_codepoint return [nil, 0] unless codepoint if codepoint == 0x0d width += 1 if peek_byte(width) == 0x0a @index += width advance_line elsif line_terminator?(codepoint) @index += width advance_line else @index += width @column += 1 end [codepoint, width] end |
#eof? ⇒ Boolean
65 66 67 |
# File 'lib/json5/input.rb', line 65 def eof? index >= source.bytesize end |
#excerpt_at(byte_offset, radius: 40) ⇒ Object
153 154 155 156 157 |
# File 'lib/json5/input.rb', line 153 def excerpt_at(byte_offset, radius: 40) start_byte = [byte_offset - radius, 0].max finish_byte = [byte_offset + radius, source.bytesize].min source.byteslice(start_byte...finish_byte)&.scrub end |
#line_terminator?(codepoint) ⇒ Boolean
149 150 151 |
# File 'lib/json5/input.rb', line 149 def line_terminator?(codepoint) codepoint == 0x0a || codepoint == 0x0d || codepoint == 0x2028 || codepoint == 0x2029 end |
#mark ⇒ Object
73 74 75 |
# File 'lib/json5/input.rb', line 73 def mark Position.new(index, line, column) end |
#peek_byte(offset = 0) ⇒ Object
69 70 71 |
# File 'lib/json5/input.rb', line 69 def peek_byte(offset = 0) source.getbyte(index + offset) end |
#peek_codepoint ⇒ Object
125 126 127 128 129 130 |
# File 'lib/json5/input.rb', line 125 def peek_codepoint return [nil, 0] if eof? byte = peek_byte return [byte, 1] if byte < 0x80 decode_utf8(index) end |
#position ⇒ Object
77 78 79 |
# File 'lib/json5/input.rb', line 77 def position mark end |
#remaining ⇒ Object
96 97 98 |
# File 'lib/json5/input.rb', line 96 def remaining source.bytesize - index end |