/src/ghostpdl/xps/xpsmem.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2025 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* XPS interpreter - string manipulation functions */ |
18 | | |
19 | | #include "ghostxps.h" |
20 | | |
21 | | void * |
22 | | xps_realloc_imp(xps_context_t *ctx, void *ptr, size_t size, const char *func) |
23 | 0 | { |
24 | 0 | if (!ptr) |
25 | 0 | return gs_alloc_bytes(ctx->memory, size, func); |
26 | 0 | return gs_resize_object(ctx->memory, ptr, size, func); |
27 | 0 | } |
28 | | |
29 | | static inline int |
30 | | xps_tolower(int c) |
31 | 19.3k | { |
32 | 19.3k | if (c >= 'A' && c <= 'Z') |
33 | 4.52k | return c + 32; |
34 | 14.8k | return c; |
35 | 19.3k | } |
36 | | |
37 | | int |
38 | | xps_strcasecmp(const char *a, const char *b) |
39 | 1.10k | { |
40 | 8.68k | while (xps_tolower(*a) == xps_tolower(*b)) |
41 | 7.68k | { |
42 | 7.68k | if (*a++ == 0) |
43 | 108 | return 0; |
44 | 7.58k | b++; |
45 | 7.58k | } |
46 | 1.00k | return xps_tolower(*a) - xps_tolower(*b); |
47 | 1.10k | } |
48 | | |
49 | | char * |
50 | | xps_strdup_imp(xps_context_t *ctx, const char *str, const char *cname) |
51 | 165 | { |
52 | 165 | char *cpy = NULL; |
53 | 165 | if (str) |
54 | 165 | cpy = (char*) gs_alloc_bytes(ctx->memory, (size_t)strlen(str) + 1, cname); |
55 | 165 | if (cpy) |
56 | 165 | strcpy(cpy, str); |
57 | 165 | return cpy; |
58 | 165 | } |
59 | | |
60 | 0 | #define SEP(x) ((x)=='/' || (x) == 0) |
61 | | |
62 | | static char * |
63 | | xps_clean_path(char *name) |
64 | 107 | { |
65 | 107 | char *p, *q, *dotdot; |
66 | 107 | int rooted; |
67 | | |
68 | 107 | rooted = name[0] == '/'; |
69 | | |
70 | | /* |
71 | | * invariants: |
72 | | * p points at beginning of path element we're considering. |
73 | | * q points just past the last path element we wrote (no slash). |
74 | | * dotdot points just past the point where .. cannot backtrack |
75 | | * any further (no slash). |
76 | | */ |
77 | 107 | p = q = dotdot = name + rooted; |
78 | 694 | while (*p) |
79 | 587 | { |
80 | 587 | if(p[0] == '/') /* null element */ |
81 | 240 | p++; |
82 | 347 | else if (p[0] == '.' && SEP(p[1])) |
83 | 0 | p += 1; /* don't count the separator in case it is nul */ |
84 | 347 | else if (p[0] == '.' && p[1] == '.' && SEP(p[2])) |
85 | 0 | { |
86 | 0 | p += 2; |
87 | 0 | if (q > dotdot) /* can backtrack */ |
88 | 0 | { |
89 | 0 | while(--q > dotdot && *q != '/') |
90 | 0 | ; |
91 | 0 | } |
92 | 0 | else if (!rooted) /* /.. is / but ./../ is .. */ |
93 | 0 | { |
94 | 0 | if (q != name) |
95 | 0 | *q++ = '/'; |
96 | 0 | *q++ = '.'; |
97 | 0 | *q++ = '.'; |
98 | 0 | dotdot = q; |
99 | 0 | } |
100 | 0 | } |
101 | 347 | else /* real path element */ |
102 | 347 | { |
103 | 347 | if (q != name+rooted) |
104 | 240 | *q++ = '/'; |
105 | 3.93k | while ((*q = *p) != '/' && *q != 0) |
106 | 3.58k | p++, q++; |
107 | 347 | } |
108 | 587 | } |
109 | | |
110 | | /* Guard against the 'blah:' case, where name == terminator. */ |
111 | 107 | if (q == name && *q != 0) /* empty string is really "." */ |
112 | 0 | *q++ = '.'; |
113 | 107 | *q = '\0'; |
114 | | |
115 | 107 | return name; |
116 | 107 | } |
117 | | |
118 | | void |
119 | | xps_absolute_path(char *output, char *base_uri, char *path, int output_size) |
120 | 107 | { |
121 | 107 | if (path[0] == '/') |
122 | 107 | { |
123 | 107 | gs_strlcpy(output, path, output_size); |
124 | 107 | } |
125 | 0 | else |
126 | 0 | { |
127 | 0 | gs_strlcpy(output, base_uri, output_size); |
128 | 0 | gs_strlcat(output, "/", output_size); |
129 | 0 | gs_strlcat(output, path, output_size); |
130 | 0 | } |
131 | 107 | xps_clean_path(output); |
132 | 107 | } |