Class: VirtFS::IOBuffer

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

Overview

I/O Buffer utility class, provides a fixed length byte buffer for I/O operations

Constant Summary collapse

MAX_CHAR_LEN =
8

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io_obj, min_buf_sz) ⇒ IOBuffer

Returns a new instance of IOBuffer.



10
11
12
13
14
15
16
17
18
# File 'lib/virtfs/io_buffer.rb', line 10

def initialize(io_obj, min_buf_sz)
  @io_obj            = io_obj
  @min_buf_sz        = min_buf_sz
  @binary_encoding   = Encoding.find("ASCII-8BIT")
  @buffer            = ""
  @range             = ByteRange.new
  @write_range       = ByteRange.new
  @sync              = false
end

Instance Attribute Details

#bufferObject (readonly)

Returns the value of attribute buffer.



6
7
8
# File 'lib/virtfs/io_buffer.rb', line 6

def buffer
  @buffer
end

#external_encodingObject

Returns the value of attribute external_encoding.



5
6
7
# File 'lib/virtfs/io_buffer.rb', line 5

def external_encoding
  @external_encoding
end

#min_buf_szObject

Returns the value of attribute min_buf_sz.



5
6
7
# File 'lib/virtfs/io_buffer.rb', line 5

def min_buf_sz
  @min_buf_sz
end

#rangeObject (readonly)

Returns the value of attribute range.



6
7
8
# File 'lib/virtfs/io_buffer.rb', line 6

def range
  @range
end

#syncObject

Returns the value of attribute sync.



5
6
7
# File 'lib/virtfs/io_buffer.rb', line 5

def sync
  @sync
end

Instance Method Details

#adjust_len_to_eof(len, pos) ⇒ Object



84
85
86
87
# File 'lib/virtfs/io_buffer.rb', line 84

def adjust_len_to_eof(len, pos)
  return @io_obj.end_byte_addr - pos + 1 if (pos + len - 1) > @io_obj.end_byte_addr
  len
end

#at_eof?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/virtfs/io_buffer.rb', line 125

def at_eof?
  @range.last >= @io_obj.end_byte_addr
end

#available_bytes(pos) ⇒ Object



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

def available_bytes(pos)
  @range.last - pos + 1
end

#buf_offset(pos) ⇒ Object



129
130
131
# File 'lib/virtfs/io_buffer.rb', line 129

def buf_offset(pos)
  pos - @range.first
end

#cover_range(pos, len) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/virtfs/io_buffer.rb', line 20

def cover_range(pos, len)
  len = adjust_len_to_eof(len, pos)
  end_pos = pos + len - 1

  return if @range.include?(pos) && @range.include?(end_pos)

  if @range.include?(pos)
    truncate_left(pos)
    extend_right(len)
    return
  end

  flush # If write data, flush.
  raw_read_len = adjust_len_to_eof([@min_buf_sz, len].max, pos)
  @buffer = @io_obj.fs_io_obj.raw_read(pos, raw_read_len)
  @range.set(pos, pos + raw_read_len - 1)
end

#extend_right(len) ⇒ Object



38
39
40
41
42
43
# File 'lib/virtfs/io_buffer.rb', line 38

def extend_right(len)
  raw_read_len = adjust_len_to_eof([@min_buf_sz, len].max, @range.last)
  rv = @io_obj.fs_io_obj.raw_read(@range.last + 1, raw_read_len)
  @buffer << rv
  @range.last += raw_read_len
end

#flushObject



112
113
114
115
116
117
118
119
# File 'lib/virtfs/io_buffer.rb', line 112

def flush
  return if @write_range.empty?
  offset = buf_offset(@write_range.first)
  length = @write_range.length
  rv = @io_obj.fs_io_obj.raw_write(@write_range.first, @buffer[offset, length])
  @write_range.clear
  rv
end

#get_byte(pos) ⇒ Object



89
90
91
92
# File 'lib/virtfs/io_buffer.rb', line 89

def get_byte(pos)
  cover_range(pos, 1)
  @buffer.getbyte(buf_offset(pos))
end

#get_char(pos) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/virtfs/io_buffer.rb', line 94

def get_char(pos)
  max_char_len = adjust_len_to_eof(MAX_CHAR_LEN, pos)
  cover_range(pos, max_char_len)
  offset = buf_offset(pos)
  (1..max_char_len).each do |len|
    char = @buffer[offset, len]
    char.force_encoding(@io_obj.external_encoding)
    return char if char.valid_encoding?
  end
  raise "Invalid byte sequence"
end

#get_str(pos, len) ⇒ Object



106
107
108
109
110
# File 'lib/virtfs/io_buffer.rb', line 106

def get_str(pos, len)
  len = adjust_len_to_eof(len, pos)
  cover_range(pos, len)
  @buffer[buf_offset(pos), len]
end

#prepend(str) ⇒ Object

for unget, data does not get written - never in write_range.



67
68
69
70
71
# File 'lib/virtfs/io_buffer.rb', line 67

def prepend(str)
  @buffer.insert(0, str)
  @range.first -= str.bytesize
  str.bytesize
end

#prepend_bytes(str) ⇒ Object



53
54
55
56
57
# File 'lib/virtfs/io_buffer.rb', line 53

def prepend_bytes(str)
  str = str.dup
  str.force_encoding(@binary_encoding)
  prepend(str)
end

#prepend_str(str) ⇒ Object



59
60
61
62
63
64
# File 'lib/virtfs/io_buffer.rb', line 59

def prepend_str(str)
  str = str.dup
  str.encode!(@io_obj.external_encoding) if @io_obj.external_encoding
  str.force_encoding(@binary_encoding)
  prepend(str)
end

#truncate_left(pos) ⇒ Object



45
46
47
48
49
50
51
# File 'lib/virtfs/io_buffer.rb', line 45

def truncate_left(pos)
  flush if @write_range.include?(pos) # If pos is within write_range, flush.
  offset = buf_offset(pos)
  return if offset == 0
  @buffer = @buffer[offset..-1]
  @range.first += offset
end

#write_to_buffer(pos, str) ⇒ Object



73
74
75
76
77
78
79
80
81
82
# File 'lib/virtfs/io_buffer.rb', line 73

def write_to_buffer(pos, str)
  len = str.bytesize
  end_pos = pos + len - 1
  flush unless @write_range.contiguous?(pos, end_pos)
  @write_range.expand(pos, end_pos)
  @range.expand(@write_range)
  @buffer[buf_offset(pos), len] = str
  flush if @sync
  len
end