Google OR-Tools: ortools/base/path.cc Source File

1

2

3

4

5

6

7

8

9

10

11

12

13

15

16#include <cstring>

17#include <string>

18

19#include "absl/strings/str_cat.h"

20

21namespace file {

22

23

24

25std::string JoinPath(absl::string_view path1, absl::string_view path2) {

26 if (path1.empty()) return std::string(path2);

27 if (path2.empty()) return std::string(path1);

28 if (path1.back() == '/') {

29 if (path2.front() == '/')

30 return absl::StrCat(path1, absl::ClippedSubstr(path2, 1));

31 } else {

32 if (path2.front() != '/') return absl::StrCat(path1, "/", path2);

33 }

34 return absl::StrCat(path1, path2);

35}

36

38

39

40

42 std::initializer_list<absl::string_view> paths) {

43 std::string result;

44

45 if (paths.size() != 0) {

46

47

48 size_t total_size = paths.size() - 1;

49 for (const absl::string_view path : paths) total_size += path.size();

50 result.resize(total_size);

51

52 auto begin = result.begin();

53 auto out = begin;

54 bool trailing_slash = false;

55 for (absl::string_view path : paths) {

56 if (path.empty()) continue;

57 if (path.front() == '/') {

58 if (honor_abs) {

59 out = begin;

60 } else if (trailing_slash) {

61 path.remove_prefix(1);

62 }

63 } else {

64 if (!trailing_slash && out != begin) *out++ = '/';

65 }

66 const size_t this_size = path.size();

67 memcpy(&*out, path.data(), this_size);

68 out += this_size;

69 trailing_slash = out[-1] == '/';

70 }

71 result.erase(out - begin);

72 }

73 return result;

74}

75

76

77

78

79std::pair<absl::string_view, absl::string_view> SplitBasename(

80 absl::string_view path) {

82

83 size_t pos = path.find_last_of('.');

84 if (pos == absl::string_view::npos)

85 return std::make_pair(path, absl::ClippedSubstr(path, path.size(), 0));

86 return std::make_pair(path.substr(0, pos),

87 absl::ClippedSubstr(path, pos + 1));

88}

89

90}

91

93 return !path.empty() && path[0] == '/';

94}

95

96std::string AddSlash(absl::string_view path) {

97 size_t length = path.size();

98 if (length && path[length - 1] != '/') {

99 return absl::StrCat(path, "/");

100 } else {

101 return std::string(path);

102 }

103}

104

105absl::string_view Dirname(absl::string_view path) {

107}

108

109absl::string_view Basename(absl::string_view path) {

111}

112

113std::pair<absl::string_view, absl::string_view> SplitPath(

114 absl::string_view path) {

115 size_t pos = path.find_last_of('/');

116

117

118 if (pos == absl::string_view::npos)

119 return std::make_pair(path.substr(0, 0), path);

120

121

122 if (pos == 0)

123 return std::make_pair(path.substr(0, 1), absl::ClippedSubstr(path, 1));

124

125 return std::make_pair(path.substr(0, pos),

126 absl::ClippedSubstr(path, pos + 1));

127}

128

129absl::string_view Stem(absl::string_view path) {

131}

132

133absl::string_view Extension(absl::string_view path) {

135}

136

137std::string CleanPath(const absl::string_view unclean_path) {

138 std::string path = std::string(unclean_path);

139 const char* src = path.c_str();

140 std::string::iterator dst = path.begin();

141

142

143 const bool is_absolute_path = *src == '/';

144 if (is_absolute_path) {

145 *dst++ = *src++;

146 while (*src == '/') ++src;

147 }

148 std::string::const_iterator backtrack_limit = dst;

149

150

151 while (*src) {

152 bool parsed = false;

153

154 if (src[0] == '.') {

155

156 if (src[1] == '/' || !src[1]) {

157 if (*++src) {

158 ++src;

159 }

160 parsed = true;

161 } else if (src[1] == '.' && (src[2] == '/' || !src[2])) {

162

163 src += 2;

164 if (dst != backtrack_limit) {

165

166 for (--dst; dst != backtrack_limit && dst[-1] != '/'; --dst) {

167

168 }

169 } else if (!is_absolute_path) {

170

171 src -= 2;

172 *dst++ = *src++;

173 *dst++ = *src++;

174 if (*src) {

175 *dst++ = *src;

176 }

177

178 backtrack_limit = dst;

179 }

180 if (*src) {

181 ++src;

182 }

183 parsed = true;

184 }

185 }

186

187

188 if (!parsed) {

189 while (*src && *src != '/') {

190 *dst++ = *src++;

191 }

192 if (*src) {

193 *dst++ = *src++;

194 }

195 }

196

197

198 while (*src == '/') {

199 ++src;

200 }

201 }

202

203

204 int path_length = dst - path.begin();

205 if (path_length != 0) {

206

207 if (path_length > 1 && path[path_length - 1] == '/') {

208 --path_length;

209 }

210 path.resize(path_length);

211 } else {

212

213 path.assign(1, '.');

214 }

215 return path;

216}

217

219 std::string ret;

220 ret.reserve(path.size());

221 bool prev_was_slash = false;

222 for (char c : path) {

223 if (c == '/') {

224 if (prev_was_slash) {

225 continue;

226 }

227 prev_was_slash = true;

228 } else {

229 prev_was_slash = false;

230 }

231 ret.push_back(c);

232 }

233 return ret;

234}

235

236}

std::pair< absl::string_view, absl::string_view > SplitBasename(absl::string_view path)

Definition path.cc:79

std::string JoinPathImpl(bool honor_abs, std::initializer_list< absl::string_view > paths)

Definition path.cc:41

std::string AddSlash(absl::string_view path)

Definition path.cc:96

absl::string_view Extension(absl::string_view path)

Definition path.cc:133

std::string CleanPath(const absl::string_view unclean_path)

Definition path.cc:137

std::pair< absl::string_view, absl::string_view > SplitPath(absl::string_view path)

Definition path.cc:113

bool IsAbsolutePath(absl::string_view path)

Definition path.cc:92

absl::string_view Stem(absl::string_view path)

Definition path.cc:129

absl::string_view Basename(absl::string_view path)

Definition path.cc:109

absl::string_view Dirname(absl::string_view path)

Definition path.cc:105

std::string CollapseSlashes(absl::string_view path)

Definition path.cc:218