libpath-ruby 0.2.1 → 0.2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +33 -0
  3. data/README.md +25 -8
  4. data/examples/path_from_arg0.md +43 -43
  5. data/examples/path_from_arg0.rb +25 -23
  6. data/lib/libpath/constants/unix.rb +71 -71
  7. data/lib/libpath/constants/windows.rb +72 -72
  8. data/lib/libpath/constants.rb +18 -19
  9. data/lib/libpath/diagnostics/parameter_checking.rb +25 -25
  10. data/lib/libpath/diagnostics.rb +1 -1
  11. data/lib/libpath/exceptions/libpath_base_exception.rb +13 -13
  12. data/lib/libpath/exceptions/malformed_name_exception.rb +23 -22
  13. data/lib/libpath/exceptions.rb +3 -3
  14. data/lib/libpath/form/unix.rb +104 -103
  15. data/lib/libpath/form/windows.rb +200 -199
  16. data/lib/libpath/form.rb +18 -18
  17. data/lib/libpath/internal_/array.rb +53 -53
  18. data/lib/libpath/internal_/platform.rb +24 -24
  19. data/lib/libpath/internal_/string.rb +20 -17
  20. data/lib/libpath/internal_/unix/form.rb +117 -112
  21. data/lib/libpath/internal_/windows/drive.rb +62 -59
  22. data/lib/libpath/internal_/windows/form.rb +193 -188
  23. data/lib/libpath/libpath.rb +3 -0
  24. data/lib/libpath/path/unix.rb +114 -112
  25. data/lib/libpath/path/windows.rb +120 -118
  26. data/lib/libpath/path.rb +18 -20
  27. data/lib/libpath/util/unix.rb +258 -258
  28. data/lib/libpath/util/windows.rb +400 -400
  29. data/lib/libpath/util.rb +18 -19
  30. data/lib/libpath/version.rb +23 -23
  31. data/lib/libpath.rb +1 -1
  32. data/test/performance/benchmark_drive_letter.rb +50 -10
  33. data/test/performance/benchmark_gsub_string_or_regex.rb +27 -23
  34. data/test/performance/benchmark_rindex2.rb +56 -48
  35. data/test/performance/benchmark_split.rb +16 -10
  36. data/test/unit/compare/ts_all.rb +4 -4
  37. data/test/unit/equate/ts_all.rb +4 -4
  38. data/test/unit/equate/unix/ts_all.rb +4 -4
  39. data/test/unit/equate/windows/ts_all.rb +4 -4
  40. data/test/unit/exceptions/tc_libpath_base_exception.rb +10 -8
  41. data/test/unit/exceptions/tc_malformed_name_exception.rb +14 -12
  42. data/test/unit/exceptions/ts_all.rb +4 -4
  43. data/test/unit/form/tc_absolute_functions.rb +242 -240
  44. data/test/unit/form/ts_all.rb +4 -4
  45. data/test/unit/form/unix/tc_absolute_functions.rb +158 -155
  46. data/test/unit/form/unix/ts_all.rb +4 -4
  47. data/test/unit/form/windows/tc_absolute_functions.rb +628 -625
  48. data/test/unit/form/windows/ts_all.rb +4 -4
  49. data/test/unit/internal_/tc_array.rb +36 -32
  50. data/test/unit/internal_/ts_all.rb +4 -4
  51. data/test/unit/internal_/unix/form/tc_slash_functions.rb +38 -35
  52. data/test/unit/internal_/unix/form/ts_all.rb +4 -4
  53. data/test/unit/internal_/unix/tc_split_path.rb +387 -384
  54. data/test/unit/internal_/unix/ts_all.rb +4 -4
  55. data/test/unit/internal_/windows/form/tc_get_windows_volume.rb +157 -153
  56. data/test/unit/internal_/windows/form/tc_slash_functions.rb +39 -35
  57. data/test/unit/internal_/windows/form/ts_all.rb +4 -4
  58. data/test/unit/internal_/windows/tc_split_path.rb +874 -869
  59. data/test/unit/internal_/windows/ts_all.rb +4 -4
  60. data/test/unit/parse/ts_all.rb +4 -4
  61. data/test/unit/path/tc_path.rb +732 -732
  62. data/test/unit/path/ts_all.rb +4 -4
  63. data/test/unit/path/unix/tc_path.rb +544 -540
  64. data/test/unit/path/unix/ts_all.rb +4 -4
  65. data/test/unit/path/windows/tc_path.rb +608 -603
  66. data/test/unit/path/windows/ts_all.rb +4 -4
  67. data/test/unit/tc_version.rb +25 -22
  68. data/test/unit/ts_all.rb +4 -4
  69. data/test/unit/util/tc_combine_paths.rb +110 -105
  70. data/test/unit/util/tc_derive_relative_path.rb +8 -3
  71. data/test/unit/util/tc_make_path_canonical.rb +142 -138
  72. data/test/unit/util/ts_all.rb +4 -4
  73. data/test/unit/util/unix/tc_combine_paths.rb +38 -34
  74. data/test/unit/util/unix/tc_derive_relative_path.rb +80 -75
  75. data/test/unit/util/unix/tc_make_path_absolute.rb +74 -70
  76. data/test/unit/util/unix/tc_make_path_canonical.rb +95 -90
  77. data/test/unit/util/unix/ts_all.rb +4 -4
  78. data/test/unit/util/windows/tc_combine_paths.rb +82 -77
  79. data/test/unit/util/windows/tc_derive_relative_path.rb +98 -93
  80. data/test/unit/util/windows/tc_make_path_absolute.rb +105 -101
  81. data/test/unit/util/windows/tc_make_path_canonical.rb +158 -153
  82. data/test/unit/util/windows/ts_all.rb +4 -4
  83. metadata +9 -8
@@ -8,89 +8,89 @@ module Internal_ # :nodoc: all
8
8
  # @!visibility private
9
9
  module Array # :nodoc:
10
10
 
11
- # @!visibility private
12
- def self.index(ar, v, after = nil) # :nodoc:
11
+ # @!visibility private
12
+ def self.index(ar, v, after = nil) # :nodoc:
13
13
 
14
- if after
14
+ if after
15
15
 
16
- if after < 0
16
+ if after < 0
17
17
 
18
- after = ar.size + after
18
+ after = ar.size + after
19
19
 
20
- return nil if after < 0
21
- else
20
+ return nil if after < 0
21
+ else
22
22
 
23
- return nil unless after < ar.size
24
- end
23
+ return nil unless after < ar.size
24
+ end
25
25
 
26
- ar.each_with_index do |el, ix|
26
+ ar.each_with_index do |el, ix|
27
27
 
28
- if ix >= after
28
+ if ix >= after
29
29
 
30
- if v == el
30
+ if v == el
31
31
 
32
- return ix
33
- end
34
- end
35
- end
32
+ return ix
33
+ end
34
+ end
35
+ end
36
36
 
37
- nil
38
- else
37
+ nil
38
+ else
39
39
 
40
- ar.index(v)
41
- end
42
- end
40
+ ar.index(v)
41
+ end
42
+ end
43
43
 
44
- # @!visibility private
45
- def self.index2(ar, v1, v2, after = nil) # :nodoc:
44
+ # @!visibility private
45
+ def self.index2(ar, v1, v2, after = nil) # :nodoc:
46
46
 
47
- i_1 = self.index(ar, v1, after)
48
- i_2 = self.index(ar, v2, after)
47
+ i_1 = self.index(ar, v1, after)
48
+ i_2 = self.index(ar, v2, after)
49
49
 
50
- if i_1
50
+ if i_1
51
51
 
52
- if i_2
52
+ if i_2
53
53
 
54
- i_1 < i_2 ? i_1 : i_2
55
- else
54
+ i_1 < i_2 ? i_1 : i_2
55
+ else
56
56
 
57
- i_1
58
- end
59
- else
57
+ i_1
58
+ end
59
+ else
60
60
 
61
- i_2
62
- end
63
- end
61
+ i_2
62
+ end
63
+ end
64
64
 
65
65
 
66
- # @!visibility private
67
- def self.rindex2(ar, v1, v2) # :nodoc:
66
+ # @!visibility private
67
+ def self.rindex2(ar, v1, v2) # :nodoc:
68
68
 
69
- i_1 = ar.rindex(v1)
70
- i_2 = ar.rindex(v2)
69
+ i_1 = ar.rindex(v1)
70
+ i_2 = ar.rindex(v2)
71
71
 
72
- if i_1
72
+ if i_1
73
73
 
74
- if i_2
74
+ if i_2
75
75
 
76
- i_1 < i_2 ? i_2 : i_1
77
- else
76
+ i_1 < i_2 ? i_2 : i_1
77
+ else
78
78
 
79
- i_1
80
- end
81
- else
79
+ i_1
80
+ end
81
+ else
82
82
 
83
- i_2
84
- end
85
- end
83
+ i_2
84
+ end
85
+ end
86
86
 
87
- end
87
+ end # module Array
88
88
 
89
- end
90
- end
89
+ end # module Internal_
90
+ end # module LibPath
91
91
 
92
92
  # :startdoc:
93
93
 
94
- # ############################## end of file ############################# #
95
94
 
95
+ # ############################## end of file ############################# #
96
96
 
@@ -8,38 +8,38 @@ module Internal_ # :nodoc: all
8
8
  # @!visibility private
9
9
  module Platform # :nodoc: all
10
10
 
11
- # @!visibility private
12
- module OS_Internal_ # :nodoc: all
11
+ # @!visibility private
12
+ module OS_Internal_ # :nodoc: all
13
13
 
14
- # @!visibility private
15
- def self.win_platform_? # :nodoc:
14
+ # @!visibility private
15
+ def self.win_platform_? # :nodoc:
16
16
 
17
- return true if 'Windows_NT' == ENV['OS']
17
+ return true if 'Windows_NT' == ENV['OS']
18
18
 
19
- [
20
- 'bccwin',
21
- 'cygwin',
22
- 'djgpp',
23
- 'mingw',
24
- 'mswin',
25
- 'wince',
26
- ].each do |os_name|
19
+ [
20
+ 'bccwin',
21
+ 'cygwin',
22
+ 'djgpp',
23
+ 'mingw',
24
+ 'mswin',
25
+ 'wince',
26
+ ].each do |os_name|
27
27
 
28
- return true if /#{os_name}/i =~ RUBY_PLATFORM
29
- end
28
+ return true if /#{os_name}/i =~ RUBY_PLATFORM
29
+ end
30
30
 
31
- false
32
- end
31
+ false
32
+ end
33
33
 
34
- end # module OS_Internal_
34
+ end # module OS_Internal_
35
35
 
36
- # @!visibility private
37
- module Constants # :nodoc: all
36
+ # @!visibility private
37
+ module Constants # :nodoc: all
38
38
 
39
- # @!visibility private
40
- PLATFORM_IS_WINDOWS = OS_Internal_.win_platform_? # :nodoc:
39
+ # @!visibility private
40
+ PLATFORM_IS_WINDOWS = OS_Internal_.win_platform_? # :nodoc:
41
41
 
42
- end # module Constants
42
+ end # module Constants
43
43
 
44
44
  end # module Platform
45
45
 
@@ -48,6 +48,6 @@ end # module LibPath
48
48
 
49
49
  # :startdoc:
50
50
 
51
- # ############################## end of file ############################# #
52
51
 
52
+ # ############################## end of file ############################# #
53
53
 
@@ -5,29 +5,32 @@ module Internal_ # :nodoc: all
5
5
 
6
6
  module String # :nodoc:
7
7
 
8
- # @!visibility private
9
- def self.rindex2(s, c1, c2) # :nodoc:
8
+ # @!visibility private
9
+ def self.rindex2(s, c1, c2) # :nodoc:
10
10
 
11
- ri_1 = s.rindex(c1)
12
- ri_2 = s.rindex(c2)
11
+ ri_1 = s.rindex(c1)
12
+ ri_2 = s.rindex(c2)
13
13
 
14
- if ri_1
14
+ if ri_1
15
15
 
16
- if ri_2
16
+ if ri_2
17
17
 
18
- ri_1 < ri_2 ? ri_2 : ri_1
19
- else
18
+ ri_1 < ri_2 ? ri_2 : ri_1
19
+ else
20
20
 
21
- ri_1
22
- end
23
- else
21
+ ri_1
22
+ end
23
+ else
24
24
 
25
- ri_2
26
- end
27
- end
25
+ ri_2
26
+ end
27
+ end
28
28
 
29
- end
29
+ end # module String
30
30
 
31
- end
32
- end
31
+ end # module Internal_
32
+ end # module LibPath
33
+
34
+
35
+ # ############################## end of file ############################# #
33
36
 
@@ -2,159 +2,164 @@
2
2
  module LibPath # :nodoc:
3
3
  # @!visibility private
4
4
  module Internal_ # :nodoc: all
5
+ # @!visibility private
5
6
  module Unix # :nodoc:
6
7
 
8
+ # @!visibility private
7
9
  module Form # :nodoc:
8
10
 
9
- # [INTERNAL] This function is undocumented, and subject to change at any
10
- # time
11
- #
12
- # @!visibility private
13
- def self.char_is_path_name_separator? c # :nodoc:
14
-
15
- '/' == c
16
- end
17
-
18
- # [INTERNAL] This function is undocumented, and subject to change at any
19
- # time
20
- #
21
- # @!visibility private
22
- def self.append_trailing_slash s # :nodoc:
23
-
24
- return s if '/' == s[-1]
11
+ # [INTERNAL] This function is undocumented, and subject to change at any
12
+ # time
13
+ #
14
+ # @!visibility private
15
+ def self.char_is_path_name_separator? c # :nodoc:
16
+
17
+ '/' == c
18
+ end
19
+
20
+ # [INTERNAL] This function is undocumented, and subject to change at any
21
+ # time
22
+ #
23
+ # @!visibility private
24
+ def self.append_trailing_slash s # :nodoc:
25
+
26
+ return s if '/' == s[-1]
25
27
 
26
- s + '/'
27
- end
28
+ s + '/'
29
+ end
28
30
 
29
- # [INTERNAL] This function is undocumented, and subject to change at any
30
- # time
31
- #
32
- # @!visibility private
33
- def self.get_trailing_slash s # :nodoc:
31
+ # [INTERNAL] This function is undocumented, and subject to change at any
32
+ # time
33
+ #
34
+ # @!visibility private
35
+ def self.get_trailing_slash s # :nodoc:
34
36
 
35
- '/' == s[-1] ? '/' : nil
36
- end
37
+ '/' == s[-1] ? '/' : nil
38
+ end
37
39
 
38
- # [INTERNAL] This function is undocumented, and subject to change at any
39
- # time
40
- #
41
- # @!visibility private
42
- def self.has_trailing_slash? s # :nodoc:
40
+ # [INTERNAL] This function is undocumented, and subject to change at any
41
+ # time
42
+ #
43
+ # @!visibility private
44
+ def self.has_trailing_slash? s # :nodoc:
43
45
 
44
- '/' == s[-1]
45
- end
46
+ '/' == s[-1]
47
+ end
46
48
 
47
- # [INTERNAL] This function is undocumented, and subject to change at any
48
- # time
49
- #
50
- # @!visibility private
51
- def self.trim_trailing_slash s # :nodoc:
49
+ # [INTERNAL] This function is undocumented, and subject to change at any
50
+ # time
51
+ #
52
+ # @!visibility private
53
+ def self.trim_trailing_slash s # :nodoc:
52
54
 
53
- return s unless '/' == s[-1]
55
+ return s unless '/' == s[-1]
54
56
 
55
- s.chop
56
- end
57
+ s.chop
58
+ end
57
59
 
58
- # [INTERNAL] This function is undocumented, and subject to change at any
59
- # time
60
- #
61
- # @!visibility private
62
- def self.elide_redundant_path_name_separators s # :nodoc:
60
+ # [INTERNAL] This function is undocumented, and subject to change at any
61
+ # time
62
+ #
63
+ # @!visibility private
64
+ def self.elide_redundant_path_name_separators s # :nodoc:
63
65
 
64
- s.gsub(/\/\/+/, '/')
65
- end
66
+ s.gsub(/\/\/+/, '/')
67
+ end
66
68
 
67
- # [INTERNAL] This function is undocumented, and subject to change at any
68
- # time
69
- #
70
- # @!visibility private
71
- def self.elide_redundant_path_name_separators! s # :nodoc:
69
+ # [INTERNAL] This function is undocumented, and subject to change at any
70
+ # time
71
+ #
72
+ # @!visibility private
73
+ def self.elide_redundant_path_name_separators! s # :nodoc:
72
74
 
73
- s.gsub!(/\/\/+/, '/')
75
+ s.gsub!(/\/\/+/, '/')
74
76
 
75
- s
76
- end
77
+ s
78
+ end
77
79
 
78
80
 
79
- # [INTERNAL] This function is undocumented, and subject to change at any
80
- # time
81
- #
82
- # Returns tuple of:
83
- #
84
- # 0. source path (with redundant path name separators elided)
85
- # 1. Windows volume (which is always nil)
86
- # 2. Directory
87
- # 3. Basename
88
- # 4. Stem
89
- # 5. Extension
90
- # 6. Directory parts
91
- # 7. Directory path parts
92
- #
93
- # @!visibility private
94
- def self.split_path s, **options # :nodoc:
81
+ # [INTERNAL] This function is undocumented, and subject to change at any
82
+ # time
83
+ #
84
+ # Returns tuple of:
85
+ #
86
+ # 0. source path (with redundant path name separators elided)
87
+ # 1. Windows volume (which is always nil)
88
+ # 2. Directory
89
+ # 3. Basename
90
+ # 4. Stem
91
+ # 5. Extension
92
+ # 6. Directory parts
93
+ # 7. Directory path parts
94
+ #
95
+ # @!visibility private
96
+ def self.split_path s, **options # :nodoc:
95
97
 
96
- f2_directory = nil
97
- f3_basename = nil
98
- f4_stem = nil
99
- f5_extension = nil
100
- f6_dir_parts = []
98
+ f2_directory = nil
99
+ f3_basename = nil
100
+ f4_stem = nil
101
+ f5_extension = nil
102
+ f6_dir_parts = []
101
103
 
102
- s = self.elide_redundant_path_name_separators s
104
+ s = self.elide_redundant_path_name_separators s
103
105
 
104
- ri_slash = s.rindex('/')
106
+ ri_slash = s.rindex('/')
105
107
 
106
- if ri_slash
108
+ if ri_slash
107
109
 
108
- f2_directory = s[0..ri_slash]
109
- f3_basename = s[(1 + ri_slash)..-1]
110
- else
110
+ f2_directory = s[0..ri_slash]
111
+ f3_basename = s[(1 + ri_slash)..-1]
112
+ else
111
113
 
112
- f2_directory = nil
113
- f3_basename = s
114
- end
114
+ f2_directory = nil
115
+ f3_basename = s
116
+ end
115
117
 
116
- case f3_basename
117
- when '.', '..'
118
+ case f3_basename
119
+ when '.', '..'
118
120
 
119
- f4_stem = f3_basename
120
- f5_extension = nil
121
- else
121
+ f4_stem = f3_basename
122
+ f5_extension = nil
123
+ else
122
124
 
123
- ri_dot = f3_basename.rindex('.')
125
+ ri_dot = f3_basename.rindex('.')
124
126
 
125
- if ri_dot
127
+ if ri_dot
126
128
 
127
- f4_stem = f3_basename[0...ri_dot]
128
- f5_extension = f3_basename[ri_dot..-1]
129
- else
129
+ f4_stem = f3_basename[0...ri_dot]
130
+ f5_extension = f3_basename[ri_dot..-1]
131
+ else
130
132
 
131
- f4_stem = f3_basename
132
- f5_extension = nil
133
- end
134
- end
133
+ f4_stem = f3_basename
134
+ f5_extension = nil
135
+ end
136
+ end
135
137
 
136
- unless options[:suppress_parts]
138
+ unless options[:suppress_parts]
137
139
 
138
- case f2_directory
139
- when nil
140
+ case f2_directory
141
+ when nil
140
142
 
141
- ;
142
- when '/'
143
+ ;
144
+ when '/'
143
145
 
144
- f6_dir_parts = [ '/' ]
145
- else
146
+ f6_dir_parts = [ '/' ]
147
+ else
146
148
 
147
- f6_dir_parts = f2_directory.split('/').reject { |v| v.empty? }.map { |v| v + '/' }
148
- f6_dir_parts.unshift('/') if '/' == f2_directory[0]
149
- end
150
- end
149
+ f6_dir_parts = f2_directory.split('/').reject { |v| v.empty? }.map { |v| v + '/' }
150
+ f6_dir_parts.unshift('/') if '/' == f2_directory[0]
151
+ end
152
+ end
151
153
 
152
154
 
153
- [ s, nil, f2_directory, f3_basename, f4_stem, f5_extension, f6_dir_parts, f6_dir_parts ].map { |v| ::String === v && v.empty? ? nil : v }
154
- end
155
+ [ s, nil, f2_directory, f3_basename, f4_stem, f5_extension, f6_dir_parts, f6_dir_parts ].map { |v| ::String === v && v.empty? ? nil : v }
156
+ end
155
157
  end # module Form
156
158
 
157
159
  end # module Unix
158
160
  end # module Internal_
159
161
  end # module LibPath
160
162
 
163
+
164
+ # ############################## end of file ############################# #
165
+
@@ -2,83 +2,86 @@
2
2
  module LibPath # :nodoc:
3
3
  # @!visibility private
4
4
  module Internal_ # :nodoc: all
5
+ # @!visibility private
5
6
  module Windows # :nodoc:
7
+ # @!visibility private
6
8
  module Drive # :nodoc:
7
9
 
10
+ # @!visibility private
8
11
  module Constants # :nodoc:
9
12
 
10
- DRIVE_LETTERS = [
13
+ DRIVE_LETTERS = [
11
14
 
12
- 'C',
13
- 'D',
14
- 'E',
15
- 'F',
16
- 'G',
17
- 'H',
18
- 'I',
19
- 'J',
20
- 'K',
21
- 'L',
22
- 'M',
23
- 'N',
24
- 'P',
25
- 'Q',
26
- 'R',
27
- 'S',
28
- 'T',
29
- 'U',
30
- 'V',
31
- 'W',
32
- 'I',
33
- 'X',
34
- 'Y',
35
- 'Z',
15
+ 'C',
16
+ 'D',
17
+ 'E',
18
+ 'F',
19
+ 'G',
20
+ 'H',
21
+ 'I',
22
+ 'J',
23
+ 'K',
24
+ 'L',
25
+ 'M',
26
+ 'N',
27
+ 'P',
28
+ 'Q',
29
+ 'R',
30
+ 'S',
31
+ 'T',
32
+ 'U',
33
+ 'V',
34
+ 'W',
35
+ 'I',
36
+ 'X',
37
+ 'Y',
38
+ 'Z',
36
39
 
37
- 'c',
38
- 'd',
39
- 'e',
40
- 'f',
41
- 'g',
42
- 'h',
43
- 'i',
44
- 'j',
45
- 'k',
46
- 'l',
47
- 'm',
48
- 'n',
49
- 'p',
50
- 'q',
51
- 'r',
52
- 's',
53
- 't',
54
- 'u',
55
- 'v',
56
- 'w',
57
- 'i',
58
- 'x',
59
- 'y',
60
- 'z',
40
+ 'c',
41
+ 'd',
42
+ 'e',
43
+ 'f',
44
+ 'g',
45
+ 'h',
46
+ 'i',
47
+ 'j',
48
+ 'k',
49
+ 'l',
50
+ 'm',
51
+ 'n',
52
+ 'p',
53
+ 'q',
54
+ 'r',
55
+ 's',
56
+ 't',
57
+ 'u',
58
+ 'v',
59
+ 'w',
60
+ 'i',
61
+ 'x',
62
+ 'y',
63
+ 'z',
61
64
 
62
- 'A',
63
- 'B',
65
+ 'A',
66
+ 'B',
64
67
 
65
- 'a',
66
- 'b',
68
+ 'a',
69
+ 'b',
67
70
 
68
- ]
71
+ ]
69
72
  end # module Constants
70
73
 
71
- # @!visibility private
72
- def self.character_is_drive_letter? ch # :nodoc:
74
+ # @!visibility private
75
+ def self.character_is_drive_letter? ch # :nodoc:
73
76
 
74
- ::LibPath::Internal_::Windows::Drive::Constants::DRIVE_LETTERS.include? ch
75
- end
77
+ ::LibPath::Internal_::Windows::Drive::Constants::DRIVE_LETTERS.include? ch
78
+ end
76
79
 
77
80
  end # module Drive
78
81
  end # module Windows
79
82
  end # module Internal_
80
83
  end # module LibPath
81
84
 
82
- # ############################## end of file ############################# #
83
85
 
86
+ # ############################## end of file ############################# #
84
87