15
15
#include " includes_normalize.h"
16
16
17
17
#include " string_piece.h"
18
+ #include " string_piece_util.h"
18
19
#include " util.h"
19
20
20
21
#include < algorithm>
25
26
26
27
namespace {
27
28
28
- // / Return true if paths a and b are on the same Windows drive.
29
+ bool IsPathSeparator (char c) {
30
+ return c == ' /' || c == ' \\ ' ;
31
+ }
32
+
33
+ // Return true if paths a and b are on the same windows drive.
34
+ // Return false if this funcation cannot check
35
+ // whether or not on the same windows drive.
36
+ bool SameDriveFast (StringPiece a, StringPiece b) {
37
+ if (a.size () < 3 || b.size () < 3 ) {
38
+ return false ;
39
+ }
40
+
41
+ if (!isalpha (a[0 ]) || !isalpha (b[0 ])) {
42
+ return false ;
43
+ }
44
+
45
+ if (tolower (a[0 ]) != tolower (b[0 ])) {
46
+ return false ;
47
+ }
48
+
49
+ if (a[1 ] != ' :' || b[1 ] != ' :' ) {
50
+ return false ;
51
+ }
52
+
53
+ if (!IsPathSeparator (a[2 ]) ||
54
+ !IsPathSeparator (b[2 ])) {
55
+ return false ;
56
+ }
57
+
58
+ return true ;
59
+ }
60
+
61
+ // Return true if paths a and b are on the same Windows drive.
29
62
bool SameDrive (StringPiece a, StringPiece b) {
63
+ // Fast check.
64
+ if (SameDriveFast (a, b)) {
65
+ return true ;
66
+ }
67
+
30
68
char a_absolute[_MAX_PATH];
31
69
char b_absolute[_MAX_PATH];
32
70
GetFullPathName (a.AsString ().c_str (), sizeof (a_absolute), a_absolute, NULL );
@@ -38,34 +76,54 @@ bool SameDrive(StringPiece a, StringPiece b) {
38
76
return _stricmp (a_drive, b_drive) == 0 ;
39
77
}
40
78
41
- } // anonymous namespace
79
+ bool IsAbsPath (StringPiece s) {
80
+ if (s.size () < 3 ||
81
+ !isalpha (s[0 ]) ||
82
+ s[1 ] != ' :' ||
83
+ !IsPathSeparator (s[2 ])) {
84
+ return false ;
85
+ }
86
+
87
+ // Check "." or ".." is contained in path.
88
+ for (size_t i = 2 ; i < s.size (); ++i) {
89
+ if (!IsPathSeparator (s[i])) {
90
+ continue ;
91
+ }
42
92
43
- string IncludesNormalize::Join (const vector<string>& list, char sep) {
44
- string ret;
45
- for (size_t i = 0 ; i < list.size (); ++i) {
46
- ret += list[i];
47
- if (i != list.size () - 1 )
48
- ret += sep;
93
+ // Check ".".
94
+ if (i + 1 < s.size () && s[i+1 ] == ' .' &&
95
+ (i + 2 >= s.size () || IsPathSeparator (s[i+2 ]))) {
96
+ return false ;
97
+ }
98
+
99
+ // Check "..".
100
+ if (i + 2 < s.size () && s[i+1 ] == ' .' && s[i+2 ] == ' .' &&
101
+ (i + 3 >= s.size () || IsPathSeparator (s[i+3 ]))) {
102
+ return false ;
103
+ }
49
104
}
50
- return ret;
51
- }
52
105
53
- vector<string> IncludesNormalize::Split (const string& input, char sep) {
54
- vector<string> elems;
55
- stringstream ss (input);
56
- string item;
57
- while (getline (ss, item, sep))
58
- elems.push_back (item);
59
- return elems;
106
+ return true ;
60
107
}
61
108
62
- string IncludesNormalize::ToLower (const string& s) {
63
- string ret;
64
- transform (s.begin (), s.end (), back_inserter (ret), ::tolower);
65
- return ret;
109
+ } // anonymous namespace
110
+
111
+ IncludesNormalize::IncludesNormalize (const string& relative_to) {
112
+ relative_to_ = AbsPath (relative_to);
113
+ splitted_relative_to_ = SplitStringPiece (relative_to_, ' /' );
66
114
}
67
115
68
116
string IncludesNormalize::AbsPath (StringPiece s) {
117
+ if (IsAbsPath (s)) {
118
+ string result = s.AsString ();
119
+ for (size_t i = 0 ; i < result.size (); ++i) {
120
+ if (result[i] == ' \\ ' ) {
121
+ result[i] = ' /' ;
122
+ }
123
+ }
124
+ return result;
125
+ }
126
+
69
127
char result[_MAX_PATH];
70
128
GetFullPathName (s.AsString ().c_str (), sizeof (result), result, NULL );
71
129
for (char * c = result; *c; ++c)
@@ -74,28 +132,30 @@ string IncludesNormalize::AbsPath(StringPiece s) {
74
132
return result;
75
133
}
76
134
77
- string IncludesNormalize::Relativize (StringPiece path, const string& start ) {
78
- vector< string> start_list = Split ( AbsPath (start), ' / ' );
79
- vector<string > path_list = Split ( AbsPath (path) , ' /' );
135
+ string IncludesNormalize::Relativize (StringPiece path, const vector<StringPiece>& start_list ) {
136
+ string abs_path = AbsPath (path );
137
+ vector<StringPiece > path_list = SplitStringPiece (abs_path , ' /' );
80
138
int i;
81
139
for (i = 0 ; i < static_cast <int >(min (start_list.size (), path_list.size ()));
82
140
++i) {
83
- if (ToLower (start_list[i]) != ToLower ( path_list[i]))
141
+ if (! EqualsCaseInsensitiveASCII (start_list[i], path_list[i])) {
84
142
break ;
143
+ }
85
144
}
86
145
87
- vector<string> rel_list;
146
+ vector<StringPiece> rel_list;
147
+ rel_list.reserve (start_list.size () - i + path_list.size () - i);
88
148
for (int j = 0 ; j < static_cast <int >(start_list.size () - i); ++j)
89
149
rel_list.push_back (" .." );
90
150
for (int j = i; j < static_cast <int >(path_list.size ()); ++j)
91
151
rel_list.push_back (path_list[j]);
92
152
if (rel_list.size () == 0 )
93
153
return " ." ;
94
- return Join (rel_list, ' /' );
154
+ return JoinStringPiece (rel_list, ' /' );
95
155
}
96
156
97
- bool IncludesNormalize::Normalize (const string& input, const char * relative_to,
98
- string* result, string* err) {
157
+ bool IncludesNormalize::Normalize (const string& input,
158
+ string* result, string* err) const {
99
159
char copy[_MAX_PATH + 1 ];
100
160
size_t len = input.size ();
101
161
if (len > _MAX_PATH) {
@@ -108,15 +168,10 @@ bool IncludesNormalize::Normalize(const string& input, const char* relative_to,
108
168
return false ;
109
169
StringPiece partially_fixed (copy, len);
110
170
111
- string curdir;
112
- if (!relative_to) {
113
- curdir = AbsPath (" ." );
114
- relative_to = curdir.c_str ();
115
- }
116
- if (!SameDrive (partially_fixed, relative_to)) {
171
+ if (!SameDrive (partially_fixed, relative_to_)) {
117
172
*result = partially_fixed.AsString ();
118
173
return true ;
119
174
}
120
- *result = Relativize (partially_fixed, relative_to );
175
+ *result = Relativize (partially_fixed, splitted_relative_to_ );
121
176
return true ;
122
177
}
0 commit comments