|
@@ -36,17 +36,31 @@ static inline const char* find_next_slash(const char* path) {
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Finds previous '/' in `path` (starting from `size` - 1) and returns offset to it.
|
|
|
+ * Finds previous '/' in `path` (starting from `offset` - 1).
|
|
|
* If the last character is '/', then it is skipped (as a token can end with '/').
|
|
|
+ *
|
|
|
+ * Returns whether '/' was found.
|
|
|
+ * Updates `*offset` to the index of the found '/' (or 0 if none was found).
|
|
|
*/
|
|
|
-static inline size_t find_prev_slash_offset(const char* path, size_t size) {
|
|
|
- if (size && path[size - 1] == '/') {
|
|
|
- size--;
|
|
|
+static inline bool find_prev_slash_offset(const char* path, size_t* offset) {
|
|
|
+ size_t off = *offset;
|
|
|
+
|
|
|
+ if (!off) {
|
|
|
+ return false;
|
|
|
}
|
|
|
- while (size && path[size - 1] != '/') {
|
|
|
- size--;
|
|
|
+
|
|
|
+ off--; // get offset to last character
|
|
|
+
|
|
|
+ /* Skip trailing '/' if there is one */
|
|
|
+ if (off && path[off] == '/') {
|
|
|
+ off--;
|
|
|
}
|
|
|
- return size;
|
|
|
+ while (off && path[off] != '/') {
|
|
|
+ off--;
|
|
|
+ }
|
|
|
+
|
|
|
+ *offset = off;
|
|
|
+ return path[off] == '/';
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -67,8 +81,8 @@ int get_norm_path(const char* path, char* buf, size_t* size_ptr) {
|
|
|
|
|
|
size_t offset = 0, ret_size = 0; /* accounts for undiscardable bytes written to `buf`
|
|
|
* i.e. `buf - ret_size` points to original `buf` */
|
|
|
- unsigned char need_slash = 0; // is '/' needed before next token
|
|
|
- bool is_absolute_path = *path == '/';
|
|
|
+ bool need_slash = false; // is '/' needed before next token
|
|
|
+ bool is_absolute_path = *path == '/';
|
|
|
|
|
|
/* handle an absolute path */
|
|
|
if (is_absolute_path) {
|
|
@@ -88,8 +102,7 @@ int get_norm_path(const char* path, char* buf, size_t* size_ptr) {
|
|
|
/* ".." */
|
|
|
if (offset) {
|
|
|
/* eat up previously written token */
|
|
|
- offset = find_prev_slash_offset(buf, offset);
|
|
|
- need_slash = 0;
|
|
|
+ need_slash = find_prev_slash_offset(buf, &offset);
|
|
|
} else if (!is_absolute_path) {
|
|
|
/* append undiscardable ".." since there is no previous token
|
|
|
* but only if the path is not absolute */
|
|
@@ -103,7 +116,7 @@ int get_norm_path(const char* path, char* buf, size_t* size_ptr) {
|
|
|
*buf++ = '.';
|
|
|
size -= need_slash + 2u;
|
|
|
ret_size += need_slash + 2u;
|
|
|
- need_slash = 1;
|
|
|
+ need_slash = true;
|
|
|
} else {
|
|
|
/* remaining case: offset == 0, path is absolute and ".." was just seen,
|
|
|
* i.e. "/..", which is collapsed to "/", hence nothing needs to be done
|
|
@@ -121,7 +134,7 @@ int get_norm_path(const char* path, char* buf, size_t* size_ptr) {
|
|
|
}
|
|
|
memcpy(buf + offset, path, len);
|
|
|
offset += len;
|
|
|
- need_slash = 1;
|
|
|
+ need_slash = true;
|
|
|
}
|
|
|
if (!*end) {
|
|
|
break;
|