/src/ghostpdl/base/gsutil.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 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 | | /* Utilities for Ghostscript library */ |
18 | | |
19 | | #include "string_.h" |
20 | | #include "memory_.h" |
21 | | #include "gstypes.h" |
22 | | #include "gserrors.h" |
23 | | #include "gsmemory.h" /* for init procedure */ |
24 | | #include "gsrect.h" /* for prototypes */ |
25 | | #include "gsuid.h" |
26 | | #include "gsutil.h" /* for prototypes */ |
27 | | #include "gxsync.h" /* for gx_monitor_t */ |
28 | | |
29 | | /* ------ Unique IDs ------ */ |
30 | | |
31 | | /* This is used by multiple threads, so lock around updates */ |
32 | | ulong |
33 | | gs_next_ids(const gs_memory_t *mem, uint count) |
34 | 335M | { |
35 | 335M | gs_lib_ctx_core_t *core = mem->gs_lib_ctx->core; |
36 | 335M | ulong id; |
37 | | |
38 | 335M | gx_monitor_enter((gx_monitor_t *)(core->monitor)); |
39 | 335M | id = core->gs_next_id; |
40 | 335M | core->gs_next_id += count; |
41 | 335M | gx_monitor_leave((gx_monitor_t *)(core->monitor)); |
42 | | |
43 | 335M | return id; |
44 | 335M | } |
45 | | |
46 | | /* ------ Memory utilities ------ */ |
47 | | |
48 | | /* Transpose an 8 x 8 block of bits. line_size is the raster of */ |
49 | | /* the input data. dist is the distance between output bytes. */ |
50 | | |
51 | | void |
52 | | memflip8x8(const byte * inp, int line_size, byte * outp, int dist) |
53 | 7.56M | { |
54 | 7.56M | uint aceg, bdfh; |
55 | | |
56 | 7.56M | { |
57 | 7.56M | const byte *ptr4 = inp + (line_size << 2); |
58 | 7.56M | const int ls2 = line_size << 1; |
59 | | |
60 | 7.56M | aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) | |
61 | 7.56M | ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24); |
62 | 7.56M | inp += line_size, ptr4 += line_size; |
63 | 7.56M | bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) | |
64 | 7.56M | ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24); |
65 | 7.56M | } |
66 | | |
67 | | /* Check for all 8 bytes being the same. */ |
68 | | /* This is especially worth doing for the case where all are zero. */ |
69 | 7.56M | if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) { |
70 | 7.26M | if (aceg == 0 || aceg == 0xffffffff) |
71 | 7.25M | goto store; |
72 | 7.98k | *outp = (byte)-(int)((aceg >> 7) & 1); |
73 | 7.98k | outp[dist] = (byte)-(int)((aceg >> 6) & 1); |
74 | 7.98k | outp += dist << 1; |
75 | 7.98k | *outp = (byte)-(int)((aceg >> 5) & 1); |
76 | 7.98k | outp[dist] = (byte)-(int)((aceg >> 4) & 1); |
77 | 7.98k | outp += dist << 1; |
78 | 7.98k | *outp = (byte)-(int)((aceg >> 3) & 1); |
79 | 7.98k | outp[dist] = (byte)-(int)((aceg >> 2) & 1); |
80 | 7.98k | outp += dist << 1; |
81 | 7.98k | *outp = (byte)-(int)((aceg >> 1) & 1); |
82 | 7.98k | outp[dist] = (byte)-(int)(aceg & 1); |
83 | 7.98k | return; |
84 | 7.26M | } { |
85 | 308k | register uint temp; |
86 | | |
87 | | /* Transpose a block of bits between registers. */ |
88 | 308k | #define TRANSPOSE(r,s,mask,shift)\ |
89 | 1.54M | (r ^= (temp = ((s >> shift) ^ r) & mask),\ |
90 | 1.54M | s ^= temp << shift) |
91 | | |
92 | | /* Transpose blocks of 4 x 4 */ |
93 | 308k | TRANSPOSE(aceg, aceg, 0x00000f0f, 20); |
94 | 308k | TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20); |
95 | | |
96 | | /* Transpose blocks of 2 x 2 */ |
97 | 308k | TRANSPOSE(aceg, aceg, 0x00330033, 10); |
98 | 308k | TRANSPOSE(bdfh, bdfh, 0x00330033, 10); |
99 | | |
100 | | /* Transpose blocks of 1 x 1 */ |
101 | 308k | TRANSPOSE(aceg, bdfh, 0x55555555, 1); |
102 | | |
103 | 308k | #undef TRANSPOSE |
104 | 308k | } |
105 | | |
106 | 7.56M | store: |
107 | 7.56M | *outp = (byte)aceg; |
108 | 7.56M | outp[dist] = (byte)bdfh; |
109 | 7.56M | outp += dist << 1; |
110 | 7.56M | *outp = (byte)(aceg >>= 8); |
111 | 7.56M | outp[dist] = (byte)(bdfh >>= 8); |
112 | 7.56M | outp += dist << 1; |
113 | 7.56M | *outp = (byte)(aceg >>= 8); |
114 | 7.56M | outp[dist] = (byte)(bdfh >>= 8); |
115 | 7.56M | outp += dist << 1; |
116 | 7.56M | *outp = (byte)(aceg >> 8); |
117 | 7.56M | outp[dist] = (byte)(bdfh >> 8); |
118 | 7.56M | } |
119 | | |
120 | | #ifdef PACIFY_VALGRIND |
121 | | void |
122 | | memflip8x8_eol(const byte * inp, int line_size, byte * outp, int dist, int bits) |
123 | 6.26M | { |
124 | 6.26M | uint aceg, bdfh; |
125 | 6.26M | uint mask; |
126 | | |
127 | 6.26M | { |
128 | 6.26M | const byte *ptr4 = inp + (line_size << 2); |
129 | 6.26M | const int ls2 = line_size << 1; |
130 | | |
131 | 6.26M | aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) | |
132 | 6.26M | ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24); |
133 | 6.26M | inp += line_size, ptr4 += line_size; |
134 | 6.26M | bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) | |
135 | 6.26M | ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24); |
136 | 6.26M | } |
137 | | |
138 | | /* Keep just the defined bits */ |
139 | 6.26M | mask = (0xff00>>(bits&7)) & 0xff; |
140 | 6.26M | mask |= mask<<8; |
141 | 6.26M | mask |= mask<<16; |
142 | 6.26M | aceg &= mask; |
143 | 6.26M | bdfh &= mask; |
144 | | |
145 | | /* Check for all 8 bytes being the same. */ |
146 | | /* This is especially worth doing for the case where all are zero. */ |
147 | 6.26M | if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) { |
148 | 6.07M | if (aceg == 0 || aceg == 0xffffffff) |
149 | 6.05M | goto store; |
150 | 16.1k | *outp = (byte)-(int)((aceg >> 7) & 1); |
151 | 16.1k | outp[dist] = (byte)-(int)((aceg >> 6) & 1); |
152 | 16.1k | outp += dist << 1; |
153 | 16.1k | *outp = (byte)-(int)((aceg >> 5) & 1); |
154 | 16.1k | outp[dist] = (byte)-(int)((aceg >> 4) & 1); |
155 | 16.1k | outp += dist << 1; |
156 | 16.1k | *outp = (byte)-(int)((aceg >> 3) & 1); |
157 | 16.1k | outp[dist] = (byte)-(int)((aceg >> 2) & 1); |
158 | 16.1k | outp += dist << 1; |
159 | 16.1k | *outp = (byte)-(int)((aceg >> 1) & 1); |
160 | 16.1k | outp[dist] = (byte)-(int)(aceg & 1); |
161 | 16.1k | return; |
162 | 6.07M | } { |
163 | 195k | register uint temp; |
164 | | |
165 | | /* Transpose a block of bits between registers. */ |
166 | 195k | #define TRANSPOSE(r,s,mask,shift)\ |
167 | 979k | (r ^= (temp = ((s >> shift) ^ r) & mask),\ |
168 | 979k | s ^= temp << shift) |
169 | | |
170 | | /* Transpose blocks of 4 x 4 */ |
171 | 195k | TRANSPOSE(aceg, aceg, 0x00000f0f, 20); |
172 | 195k | TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20); |
173 | | |
174 | | /* Transpose blocks of 2 x 2 */ |
175 | 195k | TRANSPOSE(aceg, aceg, 0x00330033, 10); |
176 | 195k | TRANSPOSE(bdfh, bdfh, 0x00330033, 10); |
177 | | |
178 | | /* Transpose blocks of 1 x 1 */ |
179 | 195k | TRANSPOSE(aceg, bdfh, 0x55555555, 1); |
180 | | |
181 | 195k | #undef TRANSPOSE |
182 | 195k | } |
183 | | |
184 | 6.25M | store: |
185 | 6.25M | *outp = (byte)aceg; |
186 | 6.25M | outp[dist] = (byte)bdfh; |
187 | 6.25M | outp += dist << 1; |
188 | 6.25M | *outp = (byte)(aceg >>= 8); |
189 | 6.25M | outp[dist] = (byte)(bdfh >>= 8); |
190 | 6.25M | outp += dist << 1; |
191 | 6.25M | *outp = (byte)(aceg >>= 8); |
192 | 6.25M | outp[dist] = (byte)(bdfh >>= 8); |
193 | 6.25M | outp += dist << 1; |
194 | 6.25M | *outp = (byte)(aceg >> 8); |
195 | 6.25M | outp[dist] = (byte)(bdfh >> 8); |
196 | 6.25M | } |
197 | | #endif |
198 | | |
199 | | /* Get an unsigned, big-endian 32-bit value. */ |
200 | | ulong |
201 | | get_u32_msb(const byte *p) |
202 | 445M | { |
203 | 445M | return ((uint)p[0] << 24) + ((uint)p[1] << 16) + ((uint)p[2] << 8) + p[3]; |
204 | 445M | } |
205 | | |
206 | | /* Put an unsigned, big-endian 32-bit value. */ |
207 | | void |
208 | | put_u32_msb(byte *p, const ulong n, const int offs) |
209 | 0 | { |
210 | 0 | (p + offs)[0] = n >> 24 & 255; |
211 | 0 | (p + offs)[1] = n >> 16 & 255; |
212 | 0 | (p + offs)[2] = n >> 8 & 255; |
213 | 0 | (p + offs)[3] = n & 255; |
214 | 0 | } |
215 | | |
216 | | /* ------ String utilities ------ */ |
217 | | |
218 | | /* Compare two strings, returning -1 if the first is less, */ |
219 | | /* 0 if they are equal, and 1 if first is greater. */ |
220 | | /* We can't use memcmp, because we always use unsigned characters. */ |
221 | | int |
222 | | bytes_compare(const byte * s1, uint len1, const byte * s2, uint len2) |
223 | 303M | { |
224 | 303M | register uint len = len1; |
225 | | |
226 | 303M | if (len2 < len) |
227 | 81.6M | len = len2; |
228 | 303M | { |
229 | 303M | register const byte *p1 = s1; |
230 | 303M | register const byte *p2 = s2; |
231 | | |
232 | 1.41G | while (len--) |
233 | 1.31G | if (*p1++ != *p2++) |
234 | 199M | return (p1[-1] < p2[-1] ? -1 : 1); |
235 | 303M | } |
236 | | /* Now check for differing lengths */ |
237 | 104M | return (len1 == len2 ? 0 : len1 < len2 ? -1 : 1); |
238 | 303M | } |
239 | | |
240 | | /* Test whether a string matches a pattern with wildcards. */ |
241 | | /* '*' = any substring, '?' = any character, '\' quotes next character. */ |
242 | | const string_match_params string_match_params_default = { |
243 | | '*', '?', '\\', false, false |
244 | | }; |
245 | | |
246 | | bool |
247 | | string_match(const byte * str, uint len, const byte * pstr, uint plen, |
248 | | register const string_match_params * psmp) |
249 | 131M | { |
250 | 131M | const byte *pback = 0; |
251 | 131M | const byte *spback = 0; /* initialized only to pacify gcc */ |
252 | 131M | const byte *p = pstr, *pend = pstr + plen; |
253 | 131M | const byte *sp = str, *spend = str + len; |
254 | | |
255 | 131M | if (psmp == 0) |
256 | 131M | psmp = &string_match_params_default; |
257 | 893M | again:while (p < pend) { |
258 | 892M | register byte ch = *p; |
259 | | |
260 | 892M | if (ch == psmp->any_substring) { |
261 | 324k | pback = ++p, spback = sp; |
262 | 324k | continue; |
263 | 892M | } else if (ch == psmp->any_char) { |
264 | 0 | if (sp == spend) |
265 | 0 | return false; /* str too short */ |
266 | 0 | p++, sp++; |
267 | 0 | continue; |
268 | 892M | } else if (ch == psmp->quote_next) { |
269 | 0 | if (++p == pend) |
270 | 0 | return true; /* bad pattern */ |
271 | 0 | ch = *p; |
272 | 0 | } |
273 | 892M | if (sp == spend) |
274 | 0 | return false; /* str too short */ |
275 | 892M | if (*sp == ch || |
276 | 892M | (psmp->ignore_case && (*sp ^ ch) == 0x20 && |
277 | 130M | (ch &= ~0x20) >= 0x41 && ch <= 0x5a) || |
278 | 892M | (psmp->slash_equiv && ((ch == '\\' && *sp == '/') || |
279 | 0 | (ch == '/' && *sp == '\\'))) |
280 | 892M | ) |
281 | 761M | p++, sp++; |
282 | 130M | else if (pback == 0) |
283 | 130M | return false; /* no * to back up to */ |
284 | 0 | else { |
285 | 0 | sp = ++spback; |
286 | 0 | p = pback; |
287 | 0 | } |
288 | 892M | } |
289 | 649k | if (sp < spend) { /* We got a match, but there are chars left over. */ |
290 | | /* If we can back up, back up to the only place that */ |
291 | | /* could produce a complete match, otherwise fail. */ |
292 | 324k | if (pback == 0) |
293 | 0 | return false; |
294 | 324k | p = pback; |
295 | 324k | pback = 0; |
296 | 324k | sp = spend - (pend - p); |
297 | 324k | goto again; |
298 | 324k | } |
299 | 324k | return true; |
300 | 649k | } |
301 | | |
302 | | /* ------ UID utilities ------ */ |
303 | | |
304 | | /* Compare two UIDs for equality. */ |
305 | | /* We know that at least one of them is valid. */ |
306 | | bool |
307 | | uid_equal(register const gs_uid * puid1, register const gs_uid * puid2) |
308 | 12.2M | { |
309 | 12.2M | if (puid1->id != puid2->id) |
310 | 718k | return false; |
311 | 11.5M | if (puid1->id >= 0) |
312 | 2.44k | return true; /* UniqueID */ |
313 | 11.5M | return |
314 | 11.5M | !memcmp((const char *)puid1->xvalues, |
315 | 11.5M | (const char *)puid2->xvalues, |
316 | 11.5M | (uint) - (puid1->id) * sizeof(long)); |
317 | 11.5M | } |
318 | | |
319 | | /* Copy the XUID data for a uid, if needed, updating the uid in place. */ |
320 | | int |
321 | | uid_copy(gs_uid *puid, gs_memory_t *mem, client_name_t cname) |
322 | 2.74M | { |
323 | 2.74M | if (uid_is_XUID(puid)) { |
324 | 141k | uint xsize = uid_XUID_size(puid); |
325 | 141k | long *xvalues = (long *) |
326 | 141k | gs_alloc_byte_array(mem, xsize, sizeof(long), cname); |
327 | | |
328 | 141k | if (xvalues == 0) |
329 | 0 | return_error(gs_error_VMerror); |
330 | 141k | memcpy(xvalues, uid_XUID_values(puid), xsize * sizeof(long)); |
331 | 141k | puid->xvalues = xvalues; |
332 | 141k | } |
333 | 2.74M | return 0; |
334 | 2.74M | } |
335 | | |
336 | | /* ------ Rectangle utilities ------ */ |
337 | | |
338 | | /* |
339 | | * Calculate the difference of two rectangles, a list of up to 4 rectangles. |
340 | | * Return the number of rectangles in the list, and set the first rectangle |
341 | | * to the intersection. |
342 | | */ |
343 | | int |
344 | | int_rect_difference(gs_int_rect * outer, const gs_int_rect * inner, |
345 | | gs_int_rect * diffs /*[4] */ ) |
346 | 0 | { |
347 | 0 | int x0 = outer->p.x, y0 = outer->p.y; |
348 | 0 | int x1 = outer->q.x, y1 = outer->q.y; |
349 | 0 | int count = 0; |
350 | |
|
351 | 0 | if (y0 < inner->p.y) { |
352 | 0 | diffs[0].p.x = x0, diffs[0].p.y = y0; |
353 | 0 | diffs[0].q.x = x1, diffs[0].q.y = min(y1, inner->p.y); |
354 | 0 | outer->p.y = y0 = diffs[0].q.y; |
355 | 0 | ++count; |
356 | 0 | } |
357 | 0 | if (y1 > inner->q.y) { |
358 | 0 | diffs[count].p.x = x0, diffs[count].p.y = max(y0, inner->q.y); |
359 | 0 | diffs[count].q.x = x1, diffs[count].q.y = y1; |
360 | 0 | outer->q.y = y1 = diffs[count].p.y; |
361 | 0 | ++count; |
362 | 0 | } |
363 | 0 | if (x0 < inner->p.x) { |
364 | 0 | diffs[0].p.x = x0, diffs[0].p.y = y0; |
365 | 0 | diffs[0].q.x = min(x1, inner->p.x), diffs[0].q.y = y1; |
366 | 0 | outer->p.x = x0 = diffs[count].q.x; |
367 | 0 | ++count; |
368 | 0 | } |
369 | 0 | if (x1 > inner->q.x) { |
370 | 0 | diffs[count].p.x = max(x0, inner->q.x), diffs[count].p.y = y0; |
371 | 0 | diffs[count].q.x = x1, diffs[count].q.y = y1; |
372 | 0 | outer->q.x = x1 = diffs[count].p.x; |
373 | 0 | ++count; |
374 | 0 | } |
375 | 0 | return count; |
376 | 0 | } |