aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/lib/io/path.cc
diff options
context:
space:
mode:
authorGravatar Rohan Jain <rohanj@google.com>2016-09-14 09:07:53 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2016-09-14 10:22:05 -0700
commit857fc259445fbff9a23ba1723d7f617ff40fbf05 (patch)
tree91fd4ac2e3cf08c172abc2e298a9aedf95dcf615 /tensorflow/core/lib/io/path.cc
parent7794f94cbe28db421a27afac95bfc780fd10be4d (diff)
Adding io::CleanPath in path.h to clean up paths. Also made TranslateName call CleanPath so that all paths are clean before doing file system ops.
Change: 133140241
Diffstat (limited to 'tensorflow/core/lib/io/path.cc')
-rw-r--r--tensorflow/core/lib/io/path.cc81
1 files changed, 81 insertions, 0 deletions
diff --git a/tensorflow/core/lib/io/path.cc b/tensorflow/core/lib/io/path.cc
index 107bd5e56a..c59d6d1893 100644
--- a/tensorflow/core/lib/io/path.cc
+++ b/tensorflow/core/lib/io/path.cc
@@ -101,5 +101,86 @@ StringPiece Extension(StringPiece path) {
return internal::SplitBasename(path).second;
}
+string CleanPath(StringPiece unclean_path) {
+ string path = unclean_path.ToString();
+ const char *src = path.c_str();
+ string::iterator dst = path.begin();
+
+ // Check for absolute path and determine initial backtrack limit.
+ const bool is_absolute_path = *src == '/';
+ if (is_absolute_path) {
+ *dst++ = *src++;
+ while (*src == '/') ++src;
+ }
+ string::const_iterator backtrack_limit = dst;
+
+ // Process all parts
+ while (*src) {
+ bool parsed = false;
+
+ if (src[0] == '.') {
+ // 1dot ".<whateverisnext>", check for END or SEP.
+ if (src[1] == '/' || !src[1]) {
+ if (*++src) {
+ ++src;
+ }
+ parsed = true;
+ } else if (src[1] == '.' && (src[2] == '/' || !src[2])) {
+ // 2dot END or SEP (".." | "../<whateverisnext>").
+ src += 2;
+ if (dst != backtrack_limit) {
+ // We can backtrack the previous part
+ for (--dst; dst != backtrack_limit && dst[-1] != '/'; --dst) {
+ // Empty.
+ }
+ } else if (!is_absolute_path) {
+ // Failed to backtrack and we can't skip it either. Rewind and copy.
+ src -= 2;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ if (*src) {
+ *dst++ = *src;
+ }
+ // We can never backtrack over a copied "../" part so set new limit.
+ backtrack_limit = dst;
+ }
+ if (*src) {
+ ++src;
+ }
+ parsed = true;
+ }
+ }
+
+ // If not parsed, copy entire part until the next SEP or EOS.
+ if (!parsed) {
+ while (*src && *src != '/') {
+ *dst++ = *src++;
+ }
+ if (*src) {
+ *dst++ = *src++;
+ }
+ }
+
+ // Skip consecutive SEP occurrences
+ while (*src == '/') {
+ ++src;
+ }
+ }
+
+ // Calculate and check the length of the cleaned path.
+ int path_length = dst - path.begin();
+ if (path_length != 0) {
+ // Remove trailing '/' except if it is root path ("/" ==> path_length := 1)
+ if (path_length > 1 && path[path_length - 1] == '/') {
+ --path_length;
+ }
+ path.resize(path_length);
+ } else {
+ // The cleaned path is empty; assign "." as per the spec.
+ path.assign(1, '.');
+ }
+ return path;
+}
+
} // namespace io
} // namespace tensorflow