Ninja
includes_normalize-win32.cc
Go to the documentation of this file.
1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "includes_normalize.h"
16 
17 #include "string_piece.h"
18 #include "util.h"
19 
20 #include <algorithm>
21 #include <iterator>
22 #include <sstream>
23 
24 #include <windows.h>
25 
26 namespace {
27 
28 /// Return true if paths a and b are on the same Windows drive.
29 bool SameDrive(StringPiece a, StringPiece b) {
30  char a_absolute[_MAX_PATH];
31  char b_absolute[_MAX_PATH];
32  GetFullPathName(a.AsString().c_str(), sizeof(a_absolute), a_absolute, NULL);
33  GetFullPathName(b.AsString().c_str(), sizeof(b_absolute), b_absolute, NULL);
34  char a_drive[_MAX_DIR];
35  char b_drive[_MAX_DIR];
36  _splitpath(a_absolute, a_drive, NULL, NULL, NULL);
37  _splitpath(b_absolute, b_drive, NULL, NULL, NULL);
38  return _stricmp(a_drive, b_drive) == 0;
39 }
40 
41 } // anonymous namespace
42 
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;
49  }
50  return ret;
51 }
52 
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;
60 }
61 
62 string IncludesNormalize::ToLower(const string& s) {
63  string ret;
64  transform(s.begin(), s.end(), back_inserter(ret), ::tolower);
65  return ret;
66 }
67 
69  char result[_MAX_PATH];
70  GetFullPathName(s.AsString().c_str(), sizeof(result), result, NULL);
71  return result;
72 }
73 
74 string IncludesNormalize::Relativize(StringPiece path, const string& start) {
75  vector<string> start_list = Split(AbsPath(start), '\\');
76  vector<string> path_list = Split(AbsPath(path), '\\');
77  int i;
78  for (i = 0; i < static_cast<int>(min(start_list.size(), path_list.size()));
79  ++i) {
80  if (ToLower(start_list[i]) != ToLower(path_list[i]))
81  break;
82  }
83 
84  vector<string> rel_list;
85  for (int j = 0; j < static_cast<int>(start_list.size() - i); ++j)
86  rel_list.push_back("..");
87  for (int j = i; j < static_cast<int>(path_list.size()); ++j)
88  rel_list.push_back(path_list[j]);
89  if (rel_list.size() == 0)
90  return ".";
91  return Join(rel_list, '\\');
92 }
93 
94 string IncludesNormalize::Normalize(const string& input,
95  const char* relative_to) {
96  char copy[_MAX_PATH];
97  size_t len = input.size();
98  strncpy(copy, input.c_str(), input.size() + 1);
99  for (size_t j = 0; j < len; ++j)
100  if (copy[j] == '/')
101  copy[j] = '\\';
102  string err;
103  if (!CanonicalizePath(copy, &len, &err)) {
104  Warning("couldn't canonicalize '%s: %s\n", input.c_str(), err.c_str());
105  }
106  string curdir;
107  if (!relative_to) {
108  curdir = AbsPath(".");
109  relative_to = curdir.c_str();
110  }
111  StringPiece partially_fixed(copy, len);
112  if (!SameDrive(partially_fixed, relative_to))
113  return partially_fixed.AsString();
114  return Relativize(partially_fixed, relative_to);
115 }
static string Relativize(StringPiece path, const string &start)
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:27
static string Join(const vector< string > &list, char sep)
string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
Definition: string_piece.h:45
static vector< string > Split(const string &input, char sep)
bool CanonicalizePath(string *path, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
Definition: util.cc:87
static string Normalize(const string &input, const char *relative_to)
Normalize by fixing slashes style, fixing redundant .
static string AbsPath(StringPiece s)
static string ToLower(const string &s)
void Warning(const char *msg,...)
Log a warning message.
Definition: util.cc:69