libpath-ruby 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+