libpath-ruby 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +61 -0
  3. data/examples/path_from_arg0.md +99 -0
  4. data/examples/path_from_arg0.rb +55 -0
  5. data/lib/libpath.rb +12 -0
  6. data/lib/libpath/constants.rb +42 -0
  7. data/lib/libpath/constants/unix.rb +146 -0
  8. data/lib/libpath/constants/windows.rb +147 -0
  9. data/lib/libpath/diagnostics.rb +6 -0
  10. data/lib/libpath/diagnostics/parameter_checking.rb +46 -0
  11. data/lib/libpath/exceptions.rb +7 -0
  12. data/lib/libpath/exceptions/libpath_base_exception.rb +77 -0
  13. data/lib/libpath/exceptions/malformed_name_exception.rb +85 -0
  14. data/lib/libpath/form.rb +42 -0
  15. data/lib/libpath/form/unix.rb +215 -0
  16. data/lib/libpath/form/windows.rb +358 -0
  17. data/lib/libpath/internal_/array.rb +96 -0
  18. data/lib/libpath/internal_/platform.rb +53 -0
  19. data/lib/libpath/internal_/string.rb +33 -0
  20. data/lib/libpath/internal_/unix/form.rb +160 -0
  21. data/lib/libpath/internal_/windows/drive.rb +84 -0
  22. data/lib/libpath/internal_/windows/form.rb +281 -0
  23. data/lib/libpath/libpath.rb +6 -0
  24. data/lib/libpath/path.rb +43 -0
  25. data/lib/libpath/path/unix.rb +170 -0
  26. data/lib/libpath/path/windows.rb +176 -0
  27. data/lib/libpath/util.rb +42 -0
  28. data/lib/libpath/util/unix.rb +414 -0
  29. data/lib/libpath/util/windows.rb +636 -0
  30. data/lib/libpath/version.rb +73 -0
  31. data/test/performance/benchmark_drive_letter.rb +31 -0
  32. data/test/performance/benchmark_gsub_string_or_regex.rb +45 -0
  33. data/test/performance/benchmark_rindex2.rb +109 -0
  34. data/test/performance/benchmark_split.rb +32 -0
  35. data/test/unit/compare/ts_all.rb +22 -0
  36. data/test/unit/equate/ts_all.rb +22 -0
  37. data/test/unit/equate/unix/ts_all.rb +22 -0
  38. data/test/unit/equate/windows/ts_all.rb +22 -0
  39. data/test/unit/exceptions/tc_libpath_base_exception.rb +27 -0
  40. data/test/unit/exceptions/tc_malformed_name_exception.rb +31 -0
  41. data/test/unit/exceptions/ts_all.rb +22 -0
  42. data/test/unit/form/tc_absolute_functions.rb +369 -0
  43. data/test/unit/form/ts_all.rb +22 -0
  44. data/test/unit/form/unix/tc_absolute_functions.rb +269 -0
  45. data/test/unit/form/unix/ts_all.rb +22 -0
  46. data/test/unit/form/windows/tc_absolute_functions.rb +854 -0
  47. data/test/unit/form/windows/ts_all.rb +22 -0
  48. data/test/unit/internal_/tc_array.rb +62 -0
  49. data/test/unit/internal_/ts_all.rb +22 -0
  50. data/test/unit/internal_/unix/form/tc_slash_functions.rb +60 -0
  51. data/test/unit/internal_/unix/form/ts_all.rb +22 -0
  52. data/test/unit/internal_/unix/tc_split_path.rb +396 -0
  53. data/test/unit/internal_/unix/ts_all.rb +22 -0
  54. data/test/unit/internal_/windows/form/tc_get_windows_volume.rb +220 -0
  55. data/test/unit/internal_/windows/form/tc_slash_functions.rb +61 -0
  56. data/test/unit/internal_/windows/form/ts_all.rb +22 -0
  57. data/test/unit/internal_/windows/tc_split_path.rb +881 -0
  58. data/test/unit/internal_/windows/ts_all.rb +22 -0
  59. data/test/unit/parse/ts_all.rb +22 -0
  60. data/test/unit/path/tc_path.rb +778 -0
  61. data/test/unit/path/ts_all.rb +22 -0
  62. data/test/unit/path/unix/tc_path.rb +565 -0
  63. data/test/unit/path/unix/ts_all.rb +22 -0
  64. data/test/unit/path/windows/tc_path.rb +630 -0
  65. data/test/unit/path/windows/ts_all.rb +22 -0
  66. data/test/unit/tc_version.rb +47 -0
  67. data/test/unit/ts_all.rb +22 -0
  68. data/test/unit/util/tc_combine_paths.rb +179 -0
  69. data/test/unit/util/tc_derive_relative_path.rb +19 -0
  70. data/test/unit/util/tc_make_path_canonical.rb +228 -0
  71. data/test/unit/util/ts_all.rb +22 -0
  72. data/test/unit/util/unix/tc_combine_paths.rb +65 -0
  73. data/test/unit/util/unix/tc_derive_relative_path.rb +123 -0
  74. data/test/unit/util/unix/tc_make_path_absolute.rb +117 -0
  75. data/test/unit/util/unix/tc_make_path_canonical.rb +139 -0
  76. data/test/unit/util/unix/ts_all.rb +22 -0
  77. data/test/unit/util/windows/tc_combine_paths.rb +131 -0
  78. data/test/unit/util/windows/tc_derive_relative_path.rb +155 -0
  79. data/test/unit/util/windows/tc_make_path_absolute.rb +163 -0
  80. data/test/unit/util/windows/tc_make_path_canonical.rb +220 -0
  81. data/test/unit/util/windows/ts_all.rb +22 -0
  82. metadata +144 -0
@@ -0,0 +1,358 @@
1
+
2
+ # ######################################################################## #
3
+ # File: libpath/form/windows.rb
4
+ #
5
+ # Purpose: LibPath::Form::Windows module
6
+ #
7
+ # Created: 8th January 2019
8
+ # Updated: 16th April 2019
9
+ #
10
+ # Home: http://github.com/synesissoftware/libpath.Ruby
11
+ #
12
+ # Author: Matthew Wilson
13
+ #
14
+ # Copyright (c) 2019, Matthew Wilson and Synesis Software
15
+ # All rights reserved.
16
+ #
17
+ # Redistribution and use in source and binary forms, with or without
18
+ # modification, are permitted provided that the following conditions are
19
+ # met:
20
+ #
21
+ # * Redistributions of source code must retain the above copyright
22
+ # notice, this list of conditions and the following disclaimer.
23
+ #
24
+ # * Redistributions in binary form must reproduce the above copyright
25
+ # notice, this list of conditions and the following disclaimer in the
26
+ # documentation and/or other materials provided with the distribution.
27
+ #
28
+ # * Neither the names of the copyright holder nor the names of its
29
+ # contributors may be used to endorse or promote products derived from
30
+ # this software without specific prior written permission.
31
+ #
32
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
33
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
34
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
36
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+ #
44
+ # ######################################################################## #
45
+
46
+
47
+
48
+ =begin
49
+ =end
50
+
51
+ require 'libpath/constants/windows'
52
+ require 'libpath/diagnostics'
53
+ require 'libpath/internal_/windows/drive'
54
+ require 'libpath/internal_/windows/form'
55
+
56
+ module LibPath # :nodoc:
57
+ module Form # :nodoc:
58
+ module Windows # :nodoc:
59
+
60
+ # Module defining instance functions that will be included and extended into
61
+ # any class or module including/extending module LibPath::Form::Windows
62
+ module LibPath_Form_Windows_Methods
63
+
64
+ # Classifies a path
65
+ #
66
+ # === Return
67
+ #
68
+ # One of +:absolute+, +:drived+, +:homed+, +:relative+, +:rooted+, for
69
+ # any paths that match precisely those classifications, or +nil+ if the
70
+ # path is empty
71
+ def classify_path path
72
+
73
+ Diagnostics.check_string_parameter(path, "path") if $DEBUG
74
+
75
+ return nil if path.nil? || path.empty?
76
+
77
+ return :homed if path_is_homed? path
78
+
79
+ vol, rem, _ = Internal_::Windows::Form.get_windows_volume(path)
80
+
81
+ rooted = Internal_::Windows::Form.char_is_path_name_separator? rem[0]
82
+
83
+ if rooted
84
+
85
+ if vol
86
+
87
+ return :absolute
88
+ else
89
+
90
+ return :rooted
91
+ end
92
+ else
93
+
94
+ if vol
95
+
96
+ return :drived
97
+ else
98
+
99
+ return :relative
100
+ end
101
+ end
102
+
103
+ end
104
+
105
+ # Evaluates whether the given name is malformed, according to the given
106
+ # options.
107
+ #
108
+ # If no options are specified, the only invalid character(s) are: +'\0'+
109
+ #
110
+ # === Signature
111
+ #
112
+ # * *Options:*
113
+ # - +:reject_path_name_separators+:: (boolean) Reject the path
114
+ # separator character(s): +'\\'+ and +'/'+
115
+ # - +:reject_path_separators+:: (boolean) Reject the path separator
116
+ # character(s): +';'+
117
+ # - +:reject_shell_characters+:: (boolean) Reject the shell
118
+ # character(s): +'*'+, +'?'+, +'|'+
119
+ def name_is_malformed? name, **options
120
+
121
+ _Constants = ::LibPath::Constants::Windows
122
+
123
+ if name
124
+
125
+ if options[:reject_shell_characters]
126
+
127
+ return true if name =~ _Constants::InvalidCharacters::Shell::RE
128
+ end
129
+
130
+ if options[:reject_path_separators]
131
+
132
+ return true if name =~ _Constants::InvalidCharacters::PathSeparators::RE
133
+ end
134
+
135
+ if options[:reject_path_name_separators]
136
+
137
+ return true if name =~ _Constants::InvalidCharacters::PathNameSeparators::RE
138
+ end
139
+
140
+ return true if name =~ _Constants::InvalidCharacters::Innate::RE
141
+
142
+ if '\\' == name[0] && '\\' == name[1]
143
+
144
+ return true if name !~ /^\\\\[^\\]+\\[^\\]+/
145
+ end
146
+
147
+ false
148
+ else
149
+
150
+ true
151
+ end
152
+ end
153
+
154
+ # Evaluates whether the given path is absolute, which means it is either
155
+ # rooted (begins with '/') or is homed (is '~' or begins with '~/')
156
+ #
157
+ # === Signature
158
+ #
159
+ # * *Parameters:*
160
+ # - +path+:: (String) The path to be evaluated. May not be +nil+
161
+ def path_is_absolute? path
162
+
163
+ Diagnostics.check_string_parameter(path, "path") if $DEBUG
164
+
165
+ return true if path_is_homed? path
166
+
167
+ vol, rem, _ = Internal_::Windows::Form.get_windows_volume(path)
168
+
169
+ return false unless vol
170
+ return false unless rem
171
+
172
+ Internal_::Windows::Form.char_is_path_name_separator? rem[0]
173
+ end
174
+
175
+ # Evaluates whether the given path is "letter drived", which means that
176
+ # it contains a drive specification. Given the two letter sequence 'X:'
177
+ # representing any ASCII letter (a-zA-Z) and a colon, this function
178
+ # recognises six sequences: +'X:'+, +'X:\'+, +'X:/'+, +'\\?\X:'+,
179
+ # +'\\?\X:\'+, +'\\?\X:/'+
180
+ #
181
+ # === Return
182
+ # - +nil+:: if it is not "drived";
183
+ # - 2:: it begins with the form +'X:'+
184
+ # - 3:: it begins with the form +'X:\'+ or +'X:/'+
185
+ # - 6:: it begins with the form +'\\?\X:'+
186
+ # - 7:: it begins with the form +'\\?\X:\'+ or +'\\?\X:/'+
187
+ def path_is_letter_drived? path
188
+
189
+ Diagnostics.check_string_parameter(path, "path") if $DEBUG
190
+
191
+ if path.size >= 2
192
+
193
+ base_index = 0
194
+
195
+ if '\\' == path[0]
196
+
197
+ if '\\' == path[1]
198
+
199
+ if '?' == path[2]
200
+
201
+ if '\\' == path[3]
202
+
203
+ base_index = 4
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ if ':' == path[base_index + 1]
210
+
211
+ if Internal_::Windows::Drive.character_is_drive_letter? path[base_index + 0]
212
+
213
+ if Internal_::Windows::Form.char_is_path_name_separator? path[base_index + 2]
214
+
215
+ return 4 == base_index ? 7 : 3
216
+ else
217
+
218
+ return 4 == base_index ? 6 : 2
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ nil
225
+ end
226
+
227
+ # Evaluates whether the given path is homed, which means it is '~' or
228
+ # begins with '~/' or '~\'
229
+ #
230
+ # === Signature
231
+ #
232
+ # * *Parameters:*
233
+ # - +path+:: (String) The path to be evaluated. May not be +nil+
234
+ def path_is_homed? path
235
+
236
+ Diagnostics.check_string_parameter(path, "path") if $DEBUG
237
+
238
+ return false unless '~' == path[0]
239
+
240
+ if path.size > 1
241
+
242
+ return Internal_::Windows::Form.char_is_path_name_separator? path[1]
243
+ end
244
+
245
+ true
246
+ end
247
+
248
+ # Evalutes whether the given path is rooted, which means it begins with
249
+ # '/'
250
+ #
251
+ # === Signature
252
+ #
253
+ # * *Parameters:*
254
+ # - +path+:: (String) The path to be evaluated. May not be +nil+
255
+ def path_is_rooted? path
256
+
257
+ Diagnostics.check_string_parameter(path, "path") if $DEBUG
258
+
259
+ case path[0]
260
+ when '/'
261
+
262
+ true
263
+ when '\\'
264
+
265
+ case path[1]
266
+ when '\\'
267
+
268
+ vol, rem, _ = Internal_::Windows::Form.get_windows_volume(path)
269
+
270
+ return false unless vol
271
+
272
+ if rem && Internal_::Windows::Form.char_is_path_name_separator?(rem[0])
273
+
274
+ true
275
+ else
276
+
277
+ false
278
+ end
279
+ else
280
+
281
+ true
282
+ end
283
+ else
284
+
285
+ if path.size > 2
286
+
287
+ if ':' == path[1]
288
+
289
+ if Internal_::Windows::Drive.character_is_drive_letter? path[0]
290
+
291
+ return Internal_::Windows::Form.char_is_path_name_separator? path[2]
292
+ end
293
+ end
294
+ end
295
+
296
+ false
297
+ end
298
+ end
299
+
300
+ # Evalutes whether the given path is UNC
301
+ #
302
+ # === Signature
303
+ #
304
+ # * *Parameters:*
305
+ # - +path+:: (String) The path to be evaluated. May not be +nil+
306
+ def path_is_UNC? path
307
+
308
+ Diagnostics.check_string_parameter(path, "path") if $DEBUG
309
+
310
+ return false unless '\\' == path[0]
311
+ return false unless '\\' == path[1]
312
+
313
+ _, _, frm = Internal_::Windows::Form.get_windows_volume(path)
314
+
315
+ case frm
316
+ when :form_2, :form_3, :form_4, :form_5, :form_6
317
+
318
+ true
319
+ else
320
+
321
+ false
322
+ end
323
+ end
324
+
325
+ end # module LibPath_Form_Windows_Methods
326
+
327
+ # @!visibility private
328
+ def self.extended receiver # :nodoc:
329
+
330
+ receiver.class_eval do
331
+
332
+ extend LibPath_Form_Windows_Methods
333
+ end
334
+
335
+ $stderr.puts "#{receiver} extended by #{LibPath_Form_Windows_Methods}" if $DEBUG
336
+ end
337
+
338
+ # @!visibility private
339
+ def self.included receiver # :nodoc:
340
+
341
+ receiver.class_eval do
342
+
343
+ include LibPath_Form_Windows_Methods
344
+ end
345
+
346
+ $stderr.puts "#{receiver} included #{LibPath_Form_Windows_Methods}" if $DEBUG
347
+ end
348
+
349
+ extend LibPath_Form_Windows_Methods
350
+ include LibPath_Form_Windows_Methods
351
+
352
+ end # module Windows
353
+ end # module Form
354
+ end # module LibPath
355
+
356
+ # ############################## end of file ############################# #
357
+
358
+
@@ -0,0 +1,96 @@
1
+
2
+ # :stopdoc:
3
+
4
+ module LibPath # :nodoc:
5
+ # @!visibility private
6
+ module Internal_ # :nodoc: all
7
+
8
+ # @!visibility private
9
+ module Array # :nodoc:
10
+
11
+ # @!visibility private
12
+ def self.index(ar, v, after = nil) # :nodoc:
13
+
14
+ if after
15
+
16
+ if after < 0
17
+
18
+ after = ar.size + after
19
+
20
+ return nil if after < 0
21
+ else
22
+
23
+ return nil unless after < ar.size
24
+ end
25
+
26
+ ar.each_with_index do |el, ix|
27
+
28
+ if ix >= after
29
+
30
+ if v == el
31
+
32
+ return ix
33
+ end
34
+ end
35
+ end
36
+
37
+ nil
38
+ else
39
+
40
+ ar.index(v)
41
+ end
42
+ end
43
+
44
+ # @!visibility private
45
+ def self.index2(ar, v1, v2, after = nil) # :nodoc:
46
+
47
+ i_1 = self.index(ar, v1, after)
48
+ i_2 = self.index(ar, v2, after)
49
+
50
+ if i_1
51
+
52
+ if i_2
53
+
54
+ i_1 < i_2 ? i_1 : i_2
55
+ else
56
+
57
+ i_1
58
+ end
59
+ else
60
+
61
+ i_2
62
+ end
63
+ end
64
+
65
+
66
+ # @!visibility private
67
+ def self.rindex2(ar, v1, v2) # :nodoc:
68
+
69
+ i_1 = ar.rindex(v1)
70
+ i_2 = ar.rindex(v2)
71
+
72
+ if i_1
73
+
74
+ if i_2
75
+
76
+ i_1 < i_2 ? i_2 : i_1
77
+ else
78
+
79
+ i_1
80
+ end
81
+ else
82
+
83
+ i_2
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+ end
91
+
92
+ # :startdoc:
93
+
94
+ # ############################## end of file ############################# #
95
+
96
+