summaryrefslogtreecommitdiffstats
path: root/debian/vendor-h2o/deps/mruby-io/mrblib/io.rb
blob: c838b96e5ae8cc7155dad7347ed99424e821a201 (plain)
1
2
3
4
5
6
7
8
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
##
# IO

class IOError < StandardError; end
class EOFError < IOError; end

class IO
  SEEK_SET = 0
  SEEK_CUR = 1
  SEEK_END = 2

  BUF_SIZE = 4096

  def self.open(*args, &block)
    io = self.new(*args)

    return io unless block

    begin
      yield io
    ensure
      begin
        io.close unless io.closed?
      rescue StandardError
      end
    end
  end

  def self.popen(command, mode = 'r', &block)
    io = self._popen(command, mode)
    return io unless block

    begin
      yield io
    ensure
      begin
        io.close unless io.closed?
      rescue IOError
        # nothing
      end
    end
  end


  def self.read(path, length=nil, offset=nil, opt=nil)
    if not opt.nil?        # 4 arguments
      offset ||= 0
    elsif not offset.nil?  # 3 arguments
      if offset.is_a? Hash
        opt = offset
        offset = 0
      else
        opt = {}
      end
    elsif not length.nil?  # 2 arguments
      if length.is_a? Hash
        opt = length
        offset = 0
        length = nil
      else
        offset = 0
        opt = {}
      end
    else                   # only 1 argument
      opt = {}
      offset = 0
      length = nil
    end

    str = ""
    fd = -1
    io = nil
    begin
      if path[0] == "|"
        io = IO.popen(path[1..-1], (opt[:mode] || "r"))
      else
        fd = IO.sysopen(path)
        io = IO.open(fd, opt[:mode] || "r")
      end
      io.seek(offset) if offset > 0
      str = io.read(length)
    ensure
      if io
        io.close
      elsif fd != -1
        IO._sysclose(fd)
      end
    end
    str
  end

  def flush
    # mruby-io always writes immediately (no output buffer).
    raise IOError, "closed stream" if self.closed?
    self
  end

  def write(string)
    str = string.is_a?(String) ? string : string.to_s
    return str.size unless str.size > 0

    len = syswrite(str)
    if len != -1
      @pos += len
      return len
    end

    raise IOError
  end

  def eof?
    return true if @buf && @buf.size > 0

    ret = false
    char = ''

    begin
      char = sysread(1)
    rescue EOFError => e
      ret = true
    ensure
      _ungets(char)
    end

    ret
  end
  alias_method :eof, :eof?

  def pos
    raise IOError if closed?
    @pos
  end
  alias_method :tell, :pos

  def pos=(i)
    seek(i, SEEK_SET)
  end

  def seek(i, whence = SEEK_SET)
    raise IOError if closed?
    @pos = sysseek(i, whence)
    @buf = ''
    0
  end

  def _read_buf
    return @buf if @buf && @buf.size > 0
    @buf = sysread(BUF_SIZE)
  end

  def _ungets(substr)
    raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
    raise IOError if @pos == 0 || @pos.nil?
    @pos -= substr.size
    if @buf.empty?
      @buf = substr
    else
      @buf = substr + @buf
    end
    nil
  end

  def ungetc(char)
    raise IOError if @pos == 0 || @pos.nil?
    _ungets(char)
    nil
  end

  def read(length = nil)
    unless length.nil?
      unless length.is_a? Fixnum
        raise TypeError.new "can't convert #{length.class} into Integer"
      end
      if length < 0
        raise ArgumentError.new "negative length: #{length} given"
      end
      if length == 0
        return ""   # easy case
      end
    end

    array = []
    start_pos = @pos
    while 1
      begin
        _read_buf
      rescue EOFError => e
        array = nil if array.empty? and (not length.nil?) and length != 0
        break
      end

      if length && (@pos - start_pos + @buf.size) >= length
        len = length - (@pos - start_pos)
        array.push @buf[0, len]
        @pos += len
        @buf = @buf[len, @buf.size - len]
        break
      else
        array.push @buf
        @pos += @buf.size
        @buf = ''
      end
    end

    array && array.join
  end

  def readline(arg = $/, limit = nil)
    case arg
    when String
      rs = arg
    when Fixnum
      rs = $/
      limit = arg
    else
      raise ArgumentError
    end

    if rs.nil?
      return read
    end

    if rs == ""
      rs = $/ + $/
    end

    array = []
    start_pos = @pos
    while 1
      begin
        _read_buf
      rescue EOFError => e
        array = nil if array.empty?
        break
      end

      if limit && (@pos - start_pos + @buf.size) >= limit
        len = limit - (@pos - start_pos)
        array.push @buf[0, len]
        @pos += len
        @buf = @buf[len, @buf.size - len]
        break
      elsif idx = @buf.index(rs)
        len = idx + rs.size
        array.push @buf[0, len]
        @pos += len
        @buf = @buf[len, @buf.size - len]
        break
      else
        array.push @buf
        @pos += @buf.size
        @buf = ''
      end
    end

    raise EOFError.new "end of file reached" if array.nil?

    array.join
  end

  def gets(*args)
    begin
      readline(*args)
    rescue EOFError => e
      nil
    end
  end

  def readchar
    _read_buf
    c = @buf[0]
    @buf = @buf[1, @buf.size]
    @pos += 1
    c
  end

  def getc
    begin
      readchar
    rescue EOFError => e
      nil
    end
  end

  # 15.2.20.5.3
  def each(&block)
    while line = self.gets
      block.call(line)
    end
    self
  end

  # 15.2.20.5.4
  def each_byte(&block)
    while char = self.getc
      block.call(char)
    end
    self
  end

  # 15.2.20.5.5
  alias each_line each

  alias each_char each_byte

  def readlines
    ary = []
    while (line = gets)
      ary << line
    end
    ary
  end

  def puts(*args)
    i = 0
    len = args.size
    while i < len
      s = args[i].to_s
      write s
      write "\n" if (s[-1] != "\n")
      i += 1
    end
    write "\n" if len == 0
    nil
  end

  def print(*args)
    i = 0
    len = args.size
    while i < len
      write args[i].to_s
      i += 1
    end
  end

  def printf(*args)
    write sprintf(*args)
    nil
  end

  alias_method :to_i, :fileno
end

STDIN  = IO.open(0, "r")
STDOUT = IO.open(1, "w")
STDERR = IO.open(2, "w")

$stdin  = STDIN
$stdout = STDOUT
$stderr = STDERR

module Kernel
  def print(*args)
    STDOUT.print(*args)
  end

  def puts(*args)
    STDOUT.puts(*args)
  end

  def printf(*args)
    STDOUT.printf(*args)
  end

  def gets(*args)
    STDIN.gets(*args)
  end

  def getc(*args)
    STDIN.getc(*args)
  end
end