Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
}