summaryrefslogtreecommitdiff
path: root/xps/xpsmem.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2007-01-22 18:41:23 +0000
committerTor Andersson <tor.andersson@artifex.com>2007-01-22 18:41:23 +0000
commit6d249aafcbfd612398274300cccda4f1028ac63b (patch)
tree24f4fb31038a2c05c86cf43261627a2c324d2477 /xps/xpsmem.c
parent6aac431a30e05933071eaff2692962a3b26a8145 (diff)
downloadghostpdl-6d249aafcbfd612398274300cccda4f1028ac63b.tar.gz
Add a function to normalize a path name in-place by stripping out extra slashes and resolving dotdots.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@2740 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'xps/xpsmem.c')
-rw-r--r--xps/xpsmem.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/xps/xpsmem.c b/xps/xpsmem.c
index fb7a299e3..a7435fb07 100644
--- a/xps/xpsmem.c
+++ b/xps/xpsmem.c
@@ -1,6 +1,5 @@
#include "ghostxps.h"
-
char *
xps_strdup_imp(xps_context_t *ctx, const char *str, const char *cname)
{
@@ -12,3 +11,60 @@ xps_strdup_imp(xps_context_t *ctx, const char *str, const char *cname)
return cpy;
}
+#define SEP(x) ((x)=='/' || (x) == 0)
+
+char *
+xps_clean_path(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;
+}
+