Upgrade to 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-io / mrblib / file.rb
1 class File < IO
2   attr_accessor :path
3
4   def initialize(fd_or_path, mode = "r", perm = 0666)
5     if fd_or_path.kind_of? Fixnum
6       super(fd_or_path, mode)
7     else
8       @path = fd_or_path
9       fd = IO.sysopen(@path, mode, perm)
10       super(fd, mode)
11     end
12   end
13
14   def self.join(*names)
15     return "" if names.empty?
16
17     names.map! do |name|
18       case name
19       when String
20         name
21       when Array
22         if names == name
23           raise ArgumentError, "recursive array"
24         end
25         join(*name)
26       else
27         raise TypeError, "no implicit conversion of #{name.class} into String"
28       end
29     end
30
31     return names[0] if names.size == 1
32
33     if names[0][-1] == File::SEPARATOR
34       s = names[0][0..-2]
35     else
36       s = names[0].dup
37     end
38
39     (1..names.size-2).each { |i|
40       t = names[i]
41       if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR
42         t = t[1..-2]
43       elsif t[0] == File::SEPARATOR
44         t = t[1..-1]
45       elsif t[-1] == File::SEPARATOR
46         t = t[0..-2]
47       end
48       s += File::SEPARATOR + t if t != ""
49     }
50     if names[-1][0] == File::SEPARATOR
51       s += File::SEPARATOR + names[-1][1..-1]
52     else
53       s += File::SEPARATOR + names[-1]
54     end
55     s
56   end
57
58   def self._concat_path(path, base_path)
59     if path[0] == "/" || path[1] == ':' # Windows root!
60       expanded_path = path
61     elsif path[0] == "~"
62       if (path[1] == "/" || path[1] == nil)
63         dir = path[1, path.size]
64         home_dir = _gethome
65
66         unless home_dir
67           raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
68         end
69
70         expanded_path = home_dir
71         expanded_path += dir if dir
72         expanded_path += "/"
73       else
74         splitted_path = path.split("/")
75         user = splitted_path[0][1, splitted_path[0].size]
76         dir = "/" + splitted_path[1, splitted_path.size].join("/")
77
78         home_dir = _gethome(user)
79
80         unless home_dir
81           raise ArgumentError, "user #{user} doesn't exist"
82         end
83
84         expanded_path = home_dir
85         expanded_path += dir if dir
86         expanded_path += "/"
87       end
88     else
89       expanded_path = _concat_path(base_path, _getwd)
90       expanded_path += "/" + path
91     end
92
93     expanded_path
94   end
95
96   def self.expand_path(path, default_dir = '.')
97     expanded_path = _concat_path(path, default_dir)
98     drive_prefix = ""
99     if File::ALT_SEPARATOR && expanded_path.size > 2 &&
100         ("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
101       drive_prefix = expanded_path[0, 2]
102       expanded_path = expanded_path[2, expanded_path.size]
103     end
104     expand_path_array = []
105     if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR)
106       expanded_path.gsub!(File::ALT_SEPARATOR, '/')
107     end
108     while expanded_path.include?('//')
109       expanded_path = expanded_path.gsub('//', '/')
110     end
111
112     if expanded_path != "/"
113       expanded_path.split('/').each do |path_token|
114         if path_token == '..'
115           if expand_path_array.size > 1
116             expand_path_array.pop
117           end
118         elsif path_token == '.'
119           # nothing to do.
120         else
121           expand_path_array << path_token
122         end
123       end
124
125       expanded_path = expand_path_array.join("/")
126       if expanded_path.empty?
127         expanded_path = '/'
128       end
129     end
130     if drive_prefix.empty?
131       expanded_path
132     else
133       drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR)
134     end
135   end
136
137   def self.foreach(file)
138     if block_given?
139       self.open(file) do |f|
140         f.each {|l| yield l}
141       end
142     else
143       return self.new(file)
144     end
145   end
146
147   def self.directory?(file)
148     FileTest.directory?(file)
149   end
150
151   def self.exist?(file)
152     FileTest.exist?(file)
153   end
154
155   def self.exists?(file)
156     FileTest.exists?(file)
157   end
158
159   def self.file?(file)
160     FileTest.file?(file)
161   end
162
163   def self.pipe?(file)
164     FileTest.pipe?(file)
165   end
166
167   def self.size(file)
168     FileTest.size(file)
169   end
170
171   def self.size?(file)
172     FileTest.size?(file)
173   end
174
175   def self.socket?(file)
176     FileTest.socket?(file)
177   end
178
179   def self.symlink?(file)
180     FileTest.symlink?(file)
181   end
182
183   def self.zero?(file)
184     FileTest.zero?(file)
185   end
186
187   def self.extname(filename)
188     fname = self.basename(filename)
189     return '' if fname[0] == '.' || fname.index('.').nil?
190     ext = fname.split('.').last
191     ext.empty? ? '' : ".#{ext}"
192   end
193
194   def self.path(filename)
195     if filename.kind_of?(String)
196       filename
197     elsif filename.respond_to?(:to_path)
198       filename.to_path
199     else
200       raise TypeError, "no implicit conversion of #{filename.class} into String"
201     end
202   end
203 end