summaryrefslogtreecommitdiff
path: root/source/fitz/string.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2014-11-24 14:59:29 +0100
committerTor Andersson <tor@ccxvii.net>2014-12-03 01:33:00 +0100
commit83b0d9af9e4f4e4bc296894982250a01ad7b6de9 (patch)
treefd1f5046b4adf24c5da23d11540ed0b1d88289e0 /source/fitz/string.c
parent178f953c048ae5119070419d5d353114bf7e29b1 (diff)
downloadmupdf-83b0d9af9e4f4e4bc296894982250a01ad7b6de9.tar.xz
Add dirname and cleanname path manipulation functions.
Diffstat (limited to 'source/fitz/string.c')
-rw-r--r--source/fitz/string.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/source/fitz/string.c b/source/fitz/string.c
index cab8387e..224eeff7 100644
--- a/source/fitz/string.c
+++ b/source/fitz/string.c
@@ -64,6 +64,81 @@ fz_strlcat(char *dst, const char *src, int siz)
return dlen + (s - src); /* count does not include NUL */
}
+void
+fz_dirname(char *dir, const char *path, int n)
+{
+ int i;
+
+ if (!path || !path[0])
+ {
+ fz_strlcpy(dir, ".", n);
+ return;
+ }
+
+ fz_strlcpy(dir, path, n);
+
+ i = strlen(dir);
+ for(; dir[i] == '/'; --i) if (!i) { fz_strlcpy(dir, "/", n); return; }
+ for(; dir[i] != '/'; --i) if (!i) { fz_strlcpy(dir, ".", n); return; }
+ for(; dir[i] == '/'; --i) if (!i) { fz_strlcpy(dir, "/", n); return; }
+ dir[i+1] = 0;
+}
+
+#define SEP(x) ((x)=='/' || (x) == 0)
+
+char *
+fz_cleanname(char *name)
+{
+ char *p, *q, *dotdot;
+ int rooted;
+
+ rooted = name[0] == '/';
+
+ /*
+ * invariants:
+ * p points at beginning of path element we're considering.
+ * q points just past the last path element we wrote (no slash).
+ * dotdot points just past the point where .. cannot backtrack
+ * any further (no slash).
+ */
+ p = q = dotdot = name + rooted;
+ while (*p)
+ {
+ if(p[0] == '/') /* null element */
+ p++;
+ else if (p[0] == '.' && SEP(p[1]))
+ p += 1; /* don't count the separator in case it is nul */
+ else if (p[0] == '.' && p[1] == '.' && SEP(p[2]))
+ {
+ p += 2;
+ if (q > dotdot) /* can backtrack */
+ {
+ while(--q > dotdot && *q != '/')
+ ;
+ }
+ else if (!rooted) /* /.. is / but ./../ is .. */
+ {
+ if (q != name)
+ *q++ = '/';
+ *q++ = '.';
+ *q++ = '.';
+ dotdot = q;
+ }
+ }
+ else /* real path element */
+ {
+ if (q != name+rooted)
+ *q++ = '/';
+ while ((*q = *p) != '/' && *q != 0)
+ p++, q++;
+ }
+ }
+
+ if (q == name) /* empty string is really "." */
+ *q++ = '.';
+ *q = '\0';
+ return name;
+}
enum
{
UTFmax = 4, /* maximum bytes per rune */