Class: Stupidedi::Reader::FileInput

Inherits:
AbstractInput show all
Defined in:
lib/stupidedi/reader/input/file_input.rb

Overview

Note:

This class is not thread-safe. If more than one Thread has access

to the same instance, and they simultaneously call methods on that instance, the methods may produce incorrect results and the object might be left in an inconsistent state.

Querying the Position collapse

Instance Attribute Summary collapse

Querying the Position collapse

Reading the Input collapse

Advancing the Cursor collapse

Testing the Input collapse

Instance Method Summary collapse

Methods inherited from AbstractInput

#==

Methods included from Inspect

#inspect

Constructor Details

#initialize(io, offset = 0, line = 1, column = 1, size = io.stat.size) ⇒ FileInput

Returns a new instance of FileInput.


16
17
18
19
# File 'lib/stupidedi/reader/input/file_input.rb', line 16

def initialize(io, offset = 0, line = 1, column = 1, size = io.stat.size)
  @io, @offset, @line, @column, @size =
    io, offset, line, column, size
end

Instance Attribute Details

#column (readonly)

Returns the value of attribute column


32
33
34
# File 'lib/stupidedi/reader/input/file_input.rb', line 32

def column
  @column
end

#ioIO (readonly)

Returns:

  • (IO)

14
15
16
# File 'lib/stupidedi/reader/input/file_input.rb', line 14

def io
  @io
end

#lineInteger (readonly)

(see AbstractInput#line)

Returns:

  • (Integer)

29
30
31
# File 'lib/stupidedi/reader/input/file_input.rb', line 29

def line
  @line
end

#offset (readonly)

Returns the value of attribute offset


25
26
27
# File 'lib/stupidedi/reader/input/file_input.rb', line 25

def offset
  @offset
end

#path (readonly)

Returns the value of attribute path


35
36
37
# File 'lib/stupidedi/reader/input/file_input.rb', line 35

def path
  @path
end

Instance Method Details

#at(n) ⇒ String

Read a single element at the given index. Result is undefined unless the input contains enough elements, which can be tested with #defined_at?

Parameters:

  • n (Integer)

    the index of the element to read (n >= 0)

Returns:

  • (String)

57
58
59
60
61
62
# File 'lib/stupidedi/reader/input/file_input.rb', line 57

def at(n)
  raise ArgumentError, "n must be positive" unless n >= 0

  @io.seek(@offset + n)
  @io.read(1)
end

#defined_at?(n)

True if the input contains enough elements such that #at(n) is defined

Parameters:

  • n (Integer)

    the index to test (n >= 0)


112
113
114
# File 'lib/stupidedi/reader/input/file_input.rb', line 112

def defined_at?(n)
  n < @size
end

#drop(n) ⇒ AbstractInput

Advance the cursor forward n elements

Parameters:

  • n (Integer)

    the number of elements to advance (n >= 0)

Returns:


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/stupidedi/reader/input/file_input.rb', line 86

def drop(n)
  raise ArgumentError, "n must be positive" unless n >= 0

  @io.seek(@offset)
  prefix = @io.read(n)
  # suffix = @io

  length = prefix.length
  count  = prefix.count("\n")

  column = unless count.zero?
             length - prefix.rindex("\n")
           else
             @column + length
           end

  copy(:offset => @offset + length,
       :line   => @line + count,
       :column => column,
       :size   => @size - length)
end

#empty?

True if no elements remain in the input


117
118
119
# File 'lib/stupidedi/reader/input/file_input.rb', line 117

def empty?
  @io.eof?
end

#index(element) ⇒ Integer

Returns the smallest n, where #at(n) == element

Parameters:

  • element (Object)

    the element to find in the input

Returns:

  • (Integer)
  • nil if element is not present in the input


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/stupidedi/reader/input/file_input.rb', line 65

def index(element)
  @io.seek(@offset)
  length = element.length

  # We need to start with element != buffer, and this is a reasonable guess
  buffer = "\377" * length

  until @io.eof?
    buffer.slice!(0)
    buffer = buffer + @io.read(1)

    if buffer == element
      return @io.tell - @offset - length
    end
  end
end

#positionString

The file name, URI, etc that identifies the input stream

Returns:

  • (String)

38
39
40
# File 'lib/stupidedi/reader/input/file_input.rb', line 38

def position
  Position.new(@offset, @line, @column, @io.path)
end

#pretty_print(q)

This method returns an undefined value.

:nocov:


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/stupidedi/reader/input/file_input.rb', line 126

def pretty_print(q)
  q.text("FileInput")
  q.group(2, "(", ")") do
    preview = take(4)
    preview = if preview.empty?
                "EOF"
              elsif preview.length <= 3
                preview.inspect
              else
                (preview.take(3) + "...").inspect
              end

    q.text preview
    q.text " at line #{@line}, column #{@column}, offset #{@offset}, file #{File.basename(@io.path)}"
  end
end

#take(n) ⇒ String

Read the first n elements

Parameters:

  • n (Integer)

    number of elements to read (n >= 0)

Returns:

  • (String)

47
48
49
50
51
52
53
# File 'lib/stupidedi/reader/input/file_input.rb', line 47

def take(n)
  @io.seek(@offset)

  # Calling @io.read with more than the number of available bytes will
  # return nil, so we have to calculate how many bytes remain
  @io.read((n <= @size) ? n : @size)
end