Apply PIE to nghttpx
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-io / mrblib / io.rb
1 ##
2 # IO
3
4 class IOError < StandardError; end
5 class EOFError < IOError; end
6
7 class IO
8   SEEK_SET = 0
9   SEEK_CUR = 1
10   SEEK_END = 2
11
12   BUF_SIZE = 4096
13
14   def self.open(*args, &block)
15     io = self.new(*args)
16
17     return io unless block
18
19     begin
20       yield io
21     ensure
22       begin
23         io.close unless io.closed?
24       rescue StandardError
25       end
26     end
27   end
28
29   def self.popen(command, mode = 'r', opts={}, &block)
30     if !self.respond_to?(:_popen)
31       raise NotImplementedError, "popen is not supported on this platform"
32     end
33     io = self._popen(command, mode, opts)
34     return io unless block
35
36     begin
37       yield io
38     ensure
39       begin
40         io.close unless io.closed?
41       rescue IOError
42         # nothing
43       end
44     end
45   end
46
47   def self.pipe(&block)
48     if !self.respond_to?(:_pipe)
49       raise NotImplementedError, "pipe is not supported on this platform"
50     end
51     if block
52       begin
53         r, w = IO._pipe
54         yield r, w
55       ensure
56         r.close unless r.closed?
57         w.close unless w.closed?
58       end
59     else
60       IO._pipe
61     end
62   end
63
64   def self.read(path, length=nil, offset=nil, opt=nil)
65     if not opt.nil?        # 4 arguments
66       offset ||= 0
67     elsif not offset.nil?  # 3 arguments
68       if offset.is_a? Hash
69         opt = offset
70         offset = 0
71       else
72         opt = {}
73       end
74     elsif not length.nil?  # 2 arguments
75       if length.is_a? Hash
76         opt = length
77         offset = 0
78         length = nil
79       else
80         offset = 0
81         opt = {}
82       end
83     else                   # only 1 argument
84       opt = {}
85       offset = 0
86       length = nil
87     end
88
89     str = ""
90     fd = -1
91     io = nil
92     begin
93       if path[0] == "|"
94         io = IO.popen(path[1..-1], (opt[:mode] || "r"))
95       else
96         mode = opt[:mode] || "r"
97         fd = IO.sysopen(path, mode)
98         io = IO.open(fd, mode)
99       end
100       io.seek(offset) if offset > 0
101       str = io.read(length)
102     ensure
103       if io
104         io.close
105       elsif fd != -1
106         IO._sysclose(fd)
107       end
108     end
109     str
110   end
111
112   def flush
113     # mruby-io always writes immediately (no output buffer).
114     raise IOError, "closed stream" if self.closed?
115     self
116   end
117
118   def hash
119     # We must define IO#hash here because IO includes Enumerable and
120     # Enumerable#hash will call IO#read...
121     self.__id__
122   end
123
124   def write(string)
125     str = string.is_a?(String) ? string : string.to_s
126     return str.size unless str.size > 0
127     if 0 < @buf.length
128       # reset real pos ignore buf
129       seek(pos, SEEK_SET)
130     end
131     len = syswrite(str)
132     len
133   end
134
135   def <<(str)
136     write(str)
137     self
138   end
139
140   def eof?
141     _check_readable
142     begin
143       buf = _read_buf
144       return buf.size == 0
145     rescue EOFError
146       return true
147     end
148   end
149   alias_method :eof, :eof?
150
151   def pos
152     raise IOError if closed?
153     sysseek(0, SEEK_CUR) - @buf.length
154   end
155   alias_method :tell, :pos
156
157   def pos=(i)
158     seek(i, SEEK_SET)
159   end
160
161   def rewind
162     seek(0, SEEK_SET)
163   end
164
165   def seek(i, whence = SEEK_SET)
166     raise IOError if closed?
167     sysseek(i, whence)
168     @buf = ''
169     0
170   end
171
172   def _read_buf
173     return @buf if @buf && @buf.size > 0
174     @buf = sysread(BUF_SIZE)
175   end
176
177   def ungetc(substr)
178     raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
179     if @buf.empty?
180       @buf = substr.dup
181     else
182       @buf = substr + @buf
183     end
184     nil
185   end
186
187   def read(length = nil, outbuf = "")
188     unless length.nil?
189       unless length.is_a? Fixnum
190         raise TypeError.new "can't convert #{length.class} into Integer"
191       end
192       if length < 0
193         raise ArgumentError.new "negative length: #{length} given"
194       end
195       if length == 0
196         return ""   # easy case
197       end
198     end
199
200     array = []
201     while 1
202       begin
203         _read_buf
204       rescue EOFError
205         array = nil if array.empty? and (not length.nil?) and length != 0
206         break
207       end
208
209       if length
210         consume = (length <= @buf.size) ? length : @buf.size
211         array.push @buf[0, consume]
212         @buf = @buf[consume, @buf.size - consume]
213         length -= consume
214         break if length == 0
215       else
216         array.push @buf
217         @buf = ''
218       end
219     end
220
221     if array.nil?
222       outbuf.replace("")
223       nil
224     else
225       outbuf.replace(array.join)
226     end
227   end
228
229   def readline(arg = $/, limit = nil)
230     case arg
231     when String
232       rs = arg
233     when Fixnum
234       rs = $/
235       limit = arg
236     else
237       raise ArgumentError
238     end
239
240     if rs.nil?
241       return read
242     end
243
244     if rs == ""
245       rs = $/ + $/
246     end
247
248     array = []
249     while 1
250       begin
251         _read_buf
252       rescue EOFError
253         array = nil if array.empty?
254         break
255       end
256
257       if limit && limit <= @buf.size
258         array.push @buf[0, limit]
259         @buf = @buf[limit, @buf.size - limit]
260         break
261       elsif idx = @buf.index(rs)
262         len = idx + rs.size
263         array.push @buf[0, len]
264         @buf = @buf[len, @buf.size - len]
265         break
266       else
267         array.push @buf
268         @buf = ''
269       end
270     end
271
272     raise EOFError.new "end of file reached" if array.nil?
273
274     array.join
275   end
276
277   def gets(*args)
278     begin
279       readline(*args)
280     rescue EOFError
281       nil
282     end
283   end
284
285   def readchar
286     _read_buf
287     c = @buf[0]
288     @buf = @buf[1, @buf.size]
289     c
290   end
291
292   def getc
293     begin
294       readchar
295     rescue EOFError
296       nil
297     end
298   end
299
300   # 15.2.20.5.3
301   def each(&block)
302     while line = self.gets
303       block.call(line)
304     end
305     self
306   end
307
308   # 15.2.20.5.4
309   def each_byte(&block)
310     while char = self.getc
311       block.call(char)
312     end
313     self
314   end
315
316   # 15.2.20.5.5
317   alias each_line each
318
319   alias each_char each_byte
320
321   def readlines
322     ary = []
323     while (line = gets)
324       ary << line
325     end
326     ary
327   end
328
329   def puts(*args)
330     i = 0
331     len = args.size
332     while i < len
333       s = args[i].to_s
334       write s
335       write "\n" if (s[-1] != "\n")
336       i += 1
337     end
338     write "\n" if len == 0
339     nil
340   end
341
342   def print(*args)
343     i = 0
344     len = args.size
345     while i < len
346       write args[i].to_s
347       i += 1
348     end
349   end
350
351   def printf(*args)
352     write sprintf(*args)
353     nil
354   end
355
356   alias_method :to_i, :fileno
357   alias_method :tty?, :isatty
358 end
359
360 STDIN  = IO.open(0, "r")
361 STDOUT = IO.open(1, "w")
362 STDERR = IO.open(2, "w")
363
364 $stdin  = STDIN
365 $stdout = STDOUT
366 $stderr = STDERR
367
368 module Kernel
369   def print(*args)
370     $stdout.print(*args)
371   end
372
373   def puts(*args)
374     $stdout.puts(*args)
375   end
376
377   def printf(*args)
378     $stdout.printf(*args)
379   end
380
381   def gets(*args)
382     $stdin.gets(*args)
383   end
384
385   def getc(*args)
386     $stdin.getc(*args)
387   end
388 end