1 /* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gsutil.c,v 1.11 2005/09/14 07:13:51 ray Exp $ */
18 /* Utilities for Ghostscript library */
19 #include "string_.h"
20 #include "memory_.h"
21 #include "gstypes.h"
22 #include "gconfigv.h" /* for USE_ASM */
23 #include "gserror.h"
24 #include "gserrors.h"
25 #include "gsmemory.h" /* for init procedure */
26 #include "gsrect.h" /* for prototypes */
27 #include "gsuid.h"
28 #include "gsutil.h" /* for prototypes */
29
30 /* ------ Unique IDs ------ */
31
32 ulong
gs_next_ids(const gs_memory_t * mem,uint count)33 gs_next_ids(const gs_memory_t *mem, uint count)
34 {
35 ulong id = mem->gs_lib_ctx->gs_next_id;
36
37 mem->gs_lib_ctx->gs_next_id += count;
38 return id;
39 }
40
41 /* ------ Memory utilities ------ */
42
43 /* Transpose an 8 x 8 block of bits. line_size is the raster of */
44 /* the input data. dist is the distance between output bytes. */
45 /* This routine may be supplanted by assembly code. */
46 #if !USE_ASM
47
48 void
memflip8x8(const byte * inp,int line_size,byte * outp,int dist)49 memflip8x8(const byte * inp, int line_size, byte * outp, int dist)
50 {
51 uint aceg, bdfh;
52
53 {
54 const byte *ptr4 = inp + (line_size << 2);
55 const int ls2 = line_size << 1;
56
57 aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) |
58 ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
59 inp += line_size, ptr4 += line_size;
60 bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) |
61 ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
62 }
63
64 /* Check for all 8 bytes being the same. */
65 /* This is especially worth doing for the case where all are zero. */
66 if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) {
67 if (aceg == 0 || aceg == 0xffffffff)
68 goto store;
69 *outp = (byte)-(int)((aceg >> 7) & 1);
70 outp[dist] = (byte)-(int)((aceg >> 6) & 1);
71 outp += dist << 1;
72 *outp = (byte)-(int)((aceg >> 5) & 1);
73 outp[dist] = (byte)-(int)((aceg >> 4) & 1);
74 outp += dist << 1;
75 *outp = (byte)-(int)((aceg >> 3) & 1);
76 outp[dist] = (byte)-(int)((aceg >> 2) & 1);
77 outp += dist << 1;
78 *outp = (byte)-(int)((aceg >> 1) & 1);
79 outp[dist] = (byte)-(int)(aceg & 1);
80 return;
81 } {
82 register uint temp;
83
84 /* Transpose a block of bits between registers. */
85 #define TRANSPOSE(r,s,mask,shift)\
86 (r ^= (temp = ((s >> shift) ^ r) & mask),\
87 s ^= temp << shift)
88
89 /* Transpose blocks of 4 x 4 */
90 TRANSPOSE(aceg, aceg, 0x00000f0f, 20);
91 TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20);
92
93 /* Transpose blocks of 2 x 2 */
94 TRANSPOSE(aceg, aceg, 0x00330033, 10);
95 TRANSPOSE(bdfh, bdfh, 0x00330033, 10);
96
97 /* Transpose blocks of 1 x 1 */
98 TRANSPOSE(aceg, bdfh, 0x55555555, 1);
99
100 #undef TRANSPOSE
101 }
102
103 store:
104 *outp = (byte)aceg;
105 outp[dist] = (byte)bdfh;
106 outp += dist << 1;
107 *outp = (byte)(aceg >>= 8);
108 outp[dist] = (byte)(bdfh >>= 8);
109 outp += dist << 1;
110 *outp = (byte)(aceg >>= 8);
111 outp[dist] = (byte)(bdfh >>= 8);
112 outp += dist << 1;
113 *outp = (byte)(aceg >> 8);
114 outp[dist] = (byte)(bdfh >> 8);
115 }
116
117 #endif /* !USE_ASM */
118
119 /* Get an unsigned, big-endian 32-bit value. */
120 ulong
get_u32_msb(const byte * p)121 get_u32_msb(const byte *p)
122 {
123 return ((uint)p[0] << 24) + ((uint)p[1] << 16) + ((uint)p[2] << 8) + p[3];
124 }
125
126 /* ------ String utilities ------ */
127
128 /* Compare two strings, returning -1 if the first is less, */
129 /* 0 if they are equal, and 1 if first is greater. */
130 /* We can't use memcmp, because we always use unsigned characters. */
131 int
bytes_compare(const byte * s1,uint len1,const byte * s2,uint len2)132 bytes_compare(const byte * s1, uint len1, const byte * s2, uint len2)
133 {
134 register uint len = len1;
135
136 if (len2 < len)
137 len = len2;
138 {
139 register const byte *p1 = s1;
140 register const byte *p2 = s2;
141
142 while (len--)
143 if (*p1++ != *p2++)
144 return (p1[-1] < p2[-1] ? -1 : 1);
145 }
146 /* Now check for differing lengths */
147 return (len1 == len2 ? 0 : len1 < len2 ? -1 : 1);
148 }
149
150 /* Test whether a string matches a pattern with wildcards. */
151 /* '*' = any substring, '?' = any character, '\' quotes next character. */
152 const string_match_params string_match_params_default = {
153 '*', '?', '\\', false, false
154 };
155
156 bool
string_match(const byte * str,uint len,const byte * pstr,uint plen,register const string_match_params * psmp)157 string_match(const byte * str, uint len, const byte * pstr, uint plen,
158 register const string_match_params * psmp)
159 {
160 const byte *pback = 0;
161 const byte *spback = 0; /* initialized only to pacify gcc */
162 const byte *p = pstr, *pend = pstr + plen;
163 const byte *sp = str, *spend = str + len;
164
165 if (psmp == 0)
166 psmp = &string_match_params_default;
167 again:while (p < pend) {
168 register byte ch = *p;
169
170 if (ch == psmp->any_substring) {
171 pback = ++p, spback = sp;
172 continue;
173 } else if (ch == psmp->any_char) {
174 if (sp == spend)
175 return false; /* str too short */
176 p++, sp++;
177 continue;
178 } else if (ch == psmp->quote_next) {
179 if (++p == pend)
180 return true; /* bad pattern */
181 ch = *p;
182 }
183 if (sp == spend)
184 return false; /* str too short */
185 if (*sp == ch ||
186 (psmp->ignore_case && (*sp ^ ch) == 0x20 &&
187 (ch &= ~0x20) >= 0x41 && ch <= 0x5a) ||
188 (psmp->slash_equiv && ((ch == '\\' && *sp == '/') ||
189 (ch == '/' && *sp == '\\')))
190 )
191 p++, sp++;
192 else if (pback == 0)
193 return false; /* no * to back up to */
194 else {
195 sp = ++spback;
196 p = pback;
197 }
198 }
199 if (sp < spend) { /* We got a match, but there are chars left over. */
200 /* If we can back up, back up to the only place that */
201 /* could produce a complete match, otherwise fail. */
202 if (pback == 0)
203 return false;
204 p = pback;
205 pback = 0;
206 sp = spend - (pend - p);
207 goto again;
208 }
209 return true;
210 }
211
212 /* ------ UID utilities ------ */
213
214 /* Compare two UIDs for equality. */
215 /* We know that at least one of them is valid. */
216 bool
uid_equal(register const gs_uid * puid1,register const gs_uid * puid2)217 uid_equal(register const gs_uid * puid1, register const gs_uid * puid2)
218 {
219 if (puid1->id != puid2->id)
220 return false;
221 if (puid1->id >= 0)
222 return true; /* UniqueID */
223 return
224 !memcmp((const char *)puid1->xvalues,
225 (const char *)puid2->xvalues,
226 (uint) - (puid1->id) * sizeof(long));
227 }
228
229 /* Copy the XUID data for a uid, if needed, updating the uid in place. */
230 int
uid_copy(gs_uid * puid,gs_memory_t * mem,client_name_t cname)231 uid_copy(gs_uid *puid, gs_memory_t *mem, client_name_t cname)
232 {
233 if (uid_is_XUID(puid)) {
234 uint xsize = uid_XUID_size(puid);
235 long *xvalues = (long *)
236 gs_alloc_byte_array(mem, xsize, sizeof(long), cname);
237
238 if (xvalues == 0)
239 return_error(gs_error_VMerror);
240 memcpy(xvalues, uid_XUID_values(puid), xsize * sizeof(long));
241 puid->xvalues = xvalues;
242 }
243 return 0;
244 }
245
246 /* ------ Rectangle utilities ------ */
247
248 /*
249 * Calculate the difference of two rectangles, a list of up to 4 rectangles.
250 * Return the number of rectangles in the list, and set the first rectangle
251 * to the intersection.
252 */
253 int
int_rect_difference(gs_int_rect * outer,const gs_int_rect * inner,gs_int_rect * diffs)254 int_rect_difference(gs_int_rect * outer, const gs_int_rect * inner,
255 gs_int_rect * diffs /*[4] */ )
256 {
257 int x0 = outer->p.x, y0 = outer->p.y;
258 int x1 = outer->q.x, y1 = outer->q.y;
259 int count = 0;
260
261 if (y0 < inner->p.y) {
262 diffs[0].p.x = x0, diffs[0].p.y = y0;
263 diffs[0].q.x = x1, diffs[0].q.y = min(y1, inner->p.y);
264 outer->p.y = y0 = diffs[0].q.y;
265 ++count;
266 }
267 if (y1 > inner->q.y) {
268 diffs[count].p.x = x0, diffs[count].p.y = max(y0, inner->q.y);
269 diffs[count].q.x = x1, diffs[count].q.y = y1;
270 outer->q.y = y1 = diffs[count].p.y;
271 ++count;
272 }
273 if (x0 < inner->p.x) {
274 diffs[0].p.x = x0, diffs[0].p.y = y0;
275 diffs[0].q.x = min(x1, inner->p.x), diffs[0].q.y = y1;
276 outer->p.x = x0 = diffs[count].q.x;
277 ++count;
278 }
279 if (x1 > inner->q.x) {
280 diffs[count].p.x = max(x0, inner->q.x), diffs[count].p.y = y0;
281 diffs[count].q.x = x1, diffs[count].q.y = y1;
282 outer->q.x = x1 = diffs[count].p.x;
283 ++count;
284 }
285 return count;
286 }
287