0,0 → 1,94 |
#include "fitz.h" |
#include "muxps.h" |
|
static inline int xps_tolower(int c) |
{ |
if (c >= 'A' && c <= 'Z') |
return c + 32; |
return c; |
} |
|
int |
xps_strcasecmp(char *a, char *b) |
{ |
while (xps_tolower(*a) == xps_tolower(*b)) |
{ |
if (*a++ == 0) |
return 0; |
b++; |
} |
return xps_tolower(*a) - xps_tolower(*b); |
} |
|
#define SEP(x) ((x)=='/' || (x) == 0) |
|
static 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; |
} |
|
void |
xps_absolute_path(char *output, char *base_uri, char *path, int output_size) |
{ |
if (path[0] == '/') |
{ |
fz_strlcpy(output, path, output_size); |
} |
else |
{ |
fz_strlcpy(output, base_uri, output_size); |
fz_strlcat(output, "/", output_size); |
fz_strlcat(output, path, output_size); |
} |
xps_clean_path(output); |
} |