/src/ghostpdl/psi/zstring.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 | | /* String operators */ |
18 | | #include "memory_.h" |
19 | | #include "ghost.h" |
20 | | #include "gsutil.h" |
21 | | #include "ialloc.h" |
22 | | #include "iname.h" |
23 | | #include "ivmspace.h" |
24 | | #include "oper.h" |
25 | | #include "store.h" |
26 | | |
27 | | /* The generic operators (copy, get, put, getinterval, putinterval, */ |
28 | | /* length, and forall) are implemented in zgeneric.c. */ |
29 | | |
30 | | /* <int> .bytestring <bytestring> */ |
31 | | static int |
32 | | zbytestring(i_ctx_t *i_ctx_p) |
33 | 0 | { |
34 | 0 | os_ptr op = osp; |
35 | 0 | byte *sbody; |
36 | 0 | uint size; |
37 | |
|
38 | 0 | check_op(1); |
39 | 0 | check_int_leu(*op, max_int); |
40 | 0 | size = (uint)op->value.intval; |
41 | 0 | sbody = ialloc_bytes(size, ".bytestring"); |
42 | 0 | if (sbody == 0) |
43 | 0 | return_error(gs_error_VMerror); |
44 | 0 | make_astruct(op, a_all | icurrent_space, sbody); |
45 | 0 | memset(sbody, 0, size); |
46 | 0 | return 0; |
47 | 0 | } |
48 | | |
49 | | /* <int> string <string> */ |
50 | | int |
51 | | zstring(i_ctx_t *i_ctx_p) |
52 | 247M | { |
53 | 247M | os_ptr op = osp; |
54 | 247M | byte *sbody; |
55 | 247M | uint size; |
56 | | |
57 | 247M | check_op(1); |
58 | 247M | check_type(*op, t_integer); |
59 | 247M | if (op->value.intval < 0 ) |
60 | 9 | return_error(gs_error_rangecheck); |
61 | 247M | if (op->value.intval > max_string_size ) |
62 | 10 | return_error(gs_error_limitcheck); /* to match Distiller */ |
63 | 247M | size = op->value.intval; |
64 | 247M | sbody = ialloc_string(size, "string"); |
65 | 247M | if (sbody == 0) |
66 | 0 | return_error(gs_error_VMerror); |
67 | 247M | make_string(op, a_all | icurrent_space, size, sbody); |
68 | 247M | memset(sbody, 0, size); |
69 | 247M | return 0; |
70 | 247M | } |
71 | | |
72 | | /* <name> .namestring <string> */ |
73 | | static int |
74 | | znamestring(i_ctx_t *i_ctx_p) |
75 | 227M | { |
76 | 227M | os_ptr op = osp; |
77 | | |
78 | 227M | check_op(1); |
79 | 227M | check_type(*op, t_name); |
80 | 227M | name_string_ref(imemory, op, op); |
81 | 227M | return 0; |
82 | 227M | } |
83 | | |
84 | | /* <string> <pattern> anchorsearch <post> <match> -true- */ |
85 | | /* <string> <pattern> anchorsearch <string> -false- */ |
86 | | static int |
87 | | zanchorsearch(i_ctx_t *i_ctx_p) |
88 | 3.86M | { |
89 | 3.86M | os_ptr op = osp; |
90 | 3.86M | os_ptr op1 = op - 1; |
91 | 3.86M | uint size = r_size(op); |
92 | | |
93 | 3.86M | check_op(2); |
94 | 3.86M | check_read_type(*op, t_string); |
95 | 3.86M | check_read_type(*op1, t_string); |
96 | 3.86M | if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) { |
97 | 2.17M | os_ptr op0 = op; |
98 | | |
99 | 2.17M | push(1); |
100 | 2.17M | *op0 = *op1; |
101 | 2.17M | r_set_size(op0, size); |
102 | 2.17M | op1->value.bytes += size; |
103 | 2.17M | r_dec_size(op1, size); |
104 | 2.17M | make_true(op); |
105 | 2.17M | } else |
106 | 3.86M | make_false(op); |
107 | 3.86M | return 0; |
108 | 3.86M | } |
109 | | |
110 | | /* <string> <pattern> (r)search <post> <match> <pre> -true- */ |
111 | | /* <string> <pattern> (r)search <string> -false- */ |
112 | | static int |
113 | | search_impl(i_ctx_t *i_ctx_p, bool forward) |
114 | 40.1M | { |
115 | 40.1M | os_ptr op = osp; |
116 | 40.1M | os_ptr op1 = op - 1; |
117 | 40.1M | uint size = r_size(op); |
118 | 40.1M | uint count; |
119 | 40.1M | byte *pat; |
120 | 40.1M | byte *ptr; |
121 | 40.1M | byte ch; |
122 | 40.1M | int incr = forward ? 1 : -1; |
123 | | |
124 | 40.1M | check_op(2); |
125 | 40.1M | check_read_type(*op1, t_string); |
126 | 40.1M | check_read_type(*op, t_string); |
127 | 40.1M | if (size > r_size(op1)) { /* can't match */ |
128 | 6.19M | make_false(op); |
129 | 6.19M | return 0; |
130 | 6.19M | } |
131 | 33.9M | count = r_size(op1) - size; |
132 | 33.9M | ptr = op1->value.bytes; |
133 | 33.9M | if (size == 0) |
134 | 2 | goto found; |
135 | 33.9M | if (!forward) |
136 | 32.3M | ptr += count; |
137 | 33.9M | pat = op->value.bytes; |
138 | 33.9M | ch = pat[0]; |
139 | 388M | do { |
140 | 388M | if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size))) |
141 | 1.07M | goto found; |
142 | 387M | ptr += incr; |
143 | 387M | } |
144 | 387M | while (count--); |
145 | | /* No match */ |
146 | 32.8M | make_false(op); |
147 | 32.8M | return 0; |
148 | 1.07M | found: |
149 | 1.07M | op->tas.type_attrs = op1->tas.type_attrs; |
150 | 1.07M | op->value.bytes = ptr; /* match */ |
151 | 1.07M | op->tas.rsize = size; /* match */ |
152 | 1.07M | push(2); |
153 | 1.07M | op[-1] = *op1; /* pre */ |
154 | 1.07M | op[-3].value.bytes = ptr + size; /* post */ |
155 | 1.07M | if (forward) { |
156 | 750k | op[-1].tas.rsize = ptr - op[-1].value.bytes; /* pre */ |
157 | 750k | op[-3].tas.rsize = count; /* post */ |
158 | 750k | } else { |
159 | 324k | op[-1].tas.rsize = count; /* pre */ |
160 | 324k | op[-3].tas.rsize -= count + size; /* post */ |
161 | 324k | } |
162 | 1.07M | make_true(op); |
163 | 1.07M | return 0; |
164 | 1.07M | } |
165 | | |
166 | | /* Search from the start of the string */ |
167 | | static int |
168 | | zsearch(i_ctx_t *i_ctx_p) |
169 | 7.78M | { |
170 | 7.78M | return search_impl(i_ctx_p, true); |
171 | 7.78M | } |
172 | | |
173 | | /* Search from the end of the string */ |
174 | | static int |
175 | | zrsearch(i_ctx_t *i_ctx_p) |
176 | 32.3M | { |
177 | 32.3M | return search_impl(i_ctx_p, false); |
178 | 32.3M | } |
179 | | |
180 | | /* <string> <charstring> .stringbreak <int|null> */ |
181 | | static int |
182 | | zstringbreak(i_ctx_t *i_ctx_p) |
183 | 83 | { |
184 | 83 | os_ptr op = osp; |
185 | 83 | uint i, j; |
186 | | |
187 | 83 | check_op(2); |
188 | 83 | check_read_type(op[-1], t_string); |
189 | 83 | check_read_type(*op, t_string); |
190 | | /* We can't use strpbrk here, because C doesn't allow nulls in strings. */ |
191 | 989 | for (i = 0; i < r_size(op - 1); ++i) |
192 | 16.3k | for (j = 0; j < r_size(op); ++j) |
193 | 15.4k | if (op[-1].value.const_bytes[i] == op->value.const_bytes[j]) { |
194 | 0 | make_int(op - 1, i); |
195 | 0 | goto done; |
196 | 0 | } |
197 | 83 | make_null(op - 1); |
198 | 83 | done: |
199 | 83 | pop(1); |
200 | 83 | return 0; |
201 | 83 | } |
202 | | |
203 | | /* <obj> <pattern> .stringmatch <bool> */ |
204 | | static int |
205 | | zstringmatch(i_ctx_t *i_ctx_p) |
206 | 0 | { |
207 | 0 | os_ptr op = osp; |
208 | 0 | os_ptr op1 = op - 1; |
209 | 0 | bool result; |
210 | |
|
211 | 0 | check_op(2); |
212 | 0 | check_read_type(*op, t_string); |
213 | 0 | switch (r_type(op1)) { |
214 | 0 | case t_string: |
215 | 0 | check_read(*op1); |
216 | 0 | goto cmp; |
217 | 0 | case t_name: |
218 | 0 | name_string_ref(imemory, op1, op1); /* can't fail */ |
219 | 0 | cmp: |
220 | 0 | result = string_match(op1->value.const_bytes, r_size(op1), |
221 | 0 | op->value.const_bytes, r_size(op), |
222 | 0 | NULL); |
223 | 0 | break; |
224 | 0 | default: |
225 | 0 | result = (r_size(op) == 1 && *op->value.bytes == '*'); |
226 | 0 | } |
227 | 0 | make_bool(op1, result); |
228 | 0 | pop(1); |
229 | 0 | return 0; |
230 | 0 | } |
231 | | |
232 | | /* ------ Initialization procedure ------ */ |
233 | | |
234 | | const op_def zstring_op_defs[] = |
235 | | { |
236 | | {"1.bytestring", zbytestring}, |
237 | | {"2anchorsearch", zanchorsearch}, |
238 | | {"1.namestring", znamestring}, |
239 | | {"2search", zsearch}, |
240 | | {"2rsearch", zrsearch}, |
241 | | {"1string", zstring}, |
242 | | {"2.stringbreak", zstringbreak}, |
243 | | {"2.stringmatch", zstringmatch}, |
244 | | op_def_end(0) |
245 | | }; |