Class: Flexr::Runtime::Buffer
- Inherits:
-
Object
- Object
- Flexr::Runtime::Buffer
- Defined in:
- lib/flexr/runtime/buffer.rb
Constant Summary collapse
- DEFAULT_CHUNK_SIZE =
64 * 1024
Instance Attribute Summary collapse
-
#base_offset ⇒ Object
readonly
Returns the value of attribute base_offset.
-
#max_buffer_size ⇒ Object
readonly
Returns the value of attribute max_buffer_size.
Instance Method Summary collapse
- #bytesize ⇒ Object
- #byteslice(range, length = nil) ⇒ Object
- #discard_before(position) ⇒ Object
- #ensure_available?(end_position) ⇒ Boolean
- #eof?(position) ⇒ Boolean
- #eof_loaded? ⇒ Boolean
- #getbyte(position) ⇒ Object
-
#initialize(input, chunk_size: DEFAULT_CHUNK_SIZE, max_buffer_size: 64 * 1024 * 1024, retain_input: true, filename: nil) ⇒ Buffer
constructor
A new instance of Buffer.
- #read_to_end ⇒ Object
- #retained_bytesize ⇒ Object
- #source ⇒ Object
- #stable_source ⇒ Object
- #utf8_boundary?(position) ⇒ Boolean
- #utf8_character_length(position) ⇒ Object
- #valid_utf8_at?(position) ⇒ Boolean
Constructor Details
#initialize(input, chunk_size: DEFAULT_CHUNK_SIZE, max_buffer_size: 64 * 1024 * 1024, retain_input: true, filename: nil) ⇒ Buffer
Returns a new instance of Buffer.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/flexr/runtime/buffer.rb', line 10 def initialize(input, chunk_size: DEFAULT_CHUNK_SIZE, max_buffer_size: 64 * 1024 * 1024, retain_input: true, filename: nil) raise ArgumentError, "chunk_size must be positive" unless chunk_size.to_i.positive? raise ArgumentError, "max_buffer_size must be non-negative" if max_buffer_size.to_i.negative? @chunk_size = chunk_size.to_i @max_buffer_size = max_buffer_size.to_i @retain_input = retain_input @filename = filename @base_offset = 0 @window_start = 0 @io = input.is_a?(String) ? nil : input raise ArgumentError, "input must be a String or IO" if @io && !@io.respond_to?(:read) @source = input.is_a?(String) ? input : String.new(encoding: Encoding::BINARY) @eof = @io.nil? ensure_buffer_size!(@source.bytesize) end |
Instance Attribute Details
#base_offset ⇒ Object (readonly)
Returns the value of attribute base_offset.
8 9 10 |
# File 'lib/flexr/runtime/buffer.rb', line 8 def base_offset @base_offset end |
#max_buffer_size ⇒ Object (readonly)
Returns the value of attribute max_buffer_size.
8 9 10 |
# File 'lib/flexr/runtime/buffer.rb', line 8 def max_buffer_size @max_buffer_size end |
Instance Method Details
#bytesize ⇒ Object
29 30 31 32 33 |
# File 'lib/flexr/runtime/buffer.rb', line 29 def bytesize return @source.bytesize if @window_start.zero? && base_offset.zero? base_offset + retained_bytesize end |
#byteslice(range, length = nil) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/flexr/runtime/buffer.rb', line 56 def byteslice(range, length = nil) ensure_range(range, length) if @window_start.zero? && base_offset.zero? return length ? @source.byteslice(range, length) : @source.byteslice(range) end if length @source.byteslice(storage_position(range), length) else @source.byteslice(storage_range(range)) end end |
#discard_before(position) ⇒ Object
141 142 143 144 145 146 147 148 149 |
# File 'lib/flexr/runtime/buffer.rb', line 141 def discard_before(position) return if @retain_input || position <= base_offset ending = [position, bytesize].min removed = ending - base_offset @window_start += removed @base_offset = ending compact_storage! end |
#ensure_available?(end_position) ⇒ Boolean
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/flexr/runtime/buffer.rb', line 69 def ensure_available?(end_position) return true if end_position <= bytesize return false if @eof while bytesize < end_position && !@eof chunk = read_chunk if chunk.nil? || chunk.empty? @eof = true break end @source.force_encoding(chunk.encoding) if @source.empty? @source << chunk end bytesize >= end_position end |
#eof?(position) ⇒ Boolean
95 96 97 |
# File 'lib/flexr/runtime/buffer.rb', line 95 def eof?(position) !ensure_available?(position + 1) end |
#eof_loaded? ⇒ Boolean
91 92 93 |
# File 'lib/flexr/runtime/buffer.rb', line 91 def eof_loaded? @eof end |
#getbyte(position) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/flexr/runtime/buffer.rb', line 49 def getbyte(position) return @source.getbyte(position) if @window_start.zero? && base_offset.zero? && position < @source.bytesize ensure_available?(position + 1) @source.getbyte(storage_position(position)) end |
#read_to_end ⇒ Object
86 87 88 89 |
# File 'lib/flexr/runtime/buffer.rb', line 86 def read_to_end ensure_available?(Float::INFINITY) source end |
#retained_bytesize ⇒ Object
35 36 37 |
# File 'lib/flexr/runtime/buffer.rb', line 35 def retained_bytesize @source.bytesize - @window_start end |
#source ⇒ Object
39 40 41 42 43 |
# File 'lib/flexr/runtime/buffer.rb', line 39 def source return @source if @window_start.zero? @source.byteslice(@window_start..).to_s end |
#stable_source ⇒ Object
45 46 47 |
# File 'lib/flexr/runtime/buffer.rb', line 45 def stable_source @source if @retain_input && @window_start.zero? && base_offset.zero? end |
#utf8_boundary?(position) ⇒ Boolean
99 100 101 102 103 104 105 106 |
# File 'lib/flexr/runtime/buffer.rb', line 99 def utf8_boundary?(position) return false if position < base_offset return true if position == base_offset return true unless ensure_available?(position) following = getbyte(position) following.nil? || (following & 0xc0) != 0x80 end |
#utf8_character_length(position) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/flexr/runtime/buffer.rb', line 126 def utf8_character_length(position) first = getbyte(position) return 0 unless first return 1 if first <= 0x7f length = if first <= 0xdf 2 elsif first <= 0xef 3 else 4 end valid_utf8_at?(position) ? length : 1 end |
#valid_utf8_at?(position) ⇒ Boolean
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/flexr/runtime/buffer.rb', line 108 def valid_utf8_at?(position) first = getbyte(position) return false unless first return true if first <= 0x7f length = if first.between?(0xc2, 0xdf) 2 elsif first.between?(0xe0, 0xef) 3 elsif first.between?(0xf0, 0xf4) 4 end return false unless length return false unless ensure_available?(position + length) byteslice(position, length).dup.force_encoding(Encoding::UTF_8).valid_encoding? end |