Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zstring.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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_int_leu(*op, max_int);
39
0
    size = (uint)op->value.intval;
40
0
    sbody = ialloc_bytes(size, ".bytestring");
41
0
    if (sbody == 0)
42
0
        return_error(gs_error_VMerror);
43
0
    make_astruct(op, a_all | icurrent_space, sbody);
44
0
    memset(sbody, 0, size);
45
0
    return 0;
46
0
}
47
48
/* <int> string <string> */
49
int
50
zstring(i_ctx_t *i_ctx_p)
51
136M
{
52
136M
    os_ptr op = osp;
53
136M
    byte *sbody;
54
136M
    uint size;
55
56
136M
    check_type(*op, t_integer);
57
136M
    if (op->value.intval < 0 )
58
7
        return_error(gs_error_rangecheck);
59
136M
    if (op->value.intval > max_string_size )
60
8
        return_error(gs_error_limitcheck); /* to match Distiller */
61
136M
    size = op->value.intval;
62
136M
    sbody = ialloc_string(size, "string");
63
136M
    if (sbody == 0)
64
0
        return_error(gs_error_VMerror);
65
136M
    make_string(op, a_all | icurrent_space, size, sbody);
66
136M
    memset(sbody, 0, size);
67
136M
    return 0;
68
136M
}
69
70
/* <name> .namestring <string> */
71
static int
72
znamestring(i_ctx_t *i_ctx_p)
73
100M
{
74
100M
    os_ptr op = osp;
75
76
100M
    check_type(*op, t_name);
77
100M
    name_string_ref(imemory, op, op);
78
100M
    return 0;
79
100M
}
80
81
/* <string> <pattern> anchorsearch <post> <match> -true- */
82
/* <string> <pattern> anchorsearch <string> -false- */
83
static int
84
zanchorsearch(i_ctx_t *i_ctx_p)
85
2.56M
{
86
2.56M
    os_ptr op = osp;
87
2.56M
    os_ptr op1 = op - 1;
88
2.56M
    uint size = r_size(op);
89
90
2.56M
    check_read_type(*op, t_string);
91
2.56M
    check_read_type(*op1, t_string);
92
2.56M
    if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) {
93
1.26M
        os_ptr op0 = op;
94
95
1.26M
        push(1);
96
1.26M
        *op0 = *op1;
97
1.26M
        r_set_size(op0, size);
98
1.26M
        op1->value.bytes += size;
99
1.26M
        r_dec_size(op1, size);
100
1.26M
        make_true(op);
101
1.26M
    } else
102
2.56M
        make_false(op);
103
2.56M
    return 0;
104
2.56M
}
105
106
/* <string> <pattern> (r)search <post> <match> <pre> -true- */
107
/* <string> <pattern> (r)search <string> -false- */
108
static int
109
search_impl(i_ctx_t *i_ctx_p, bool forward)
110
20.4M
{
111
20.4M
    os_ptr op = osp;
112
20.4M
    os_ptr op1 = op - 1;
113
20.4M
    uint size = r_size(op);
114
20.4M
    uint count;
115
20.4M
    byte *pat;
116
20.4M
    byte *ptr;
117
20.4M
    byte ch;
118
20.4M
    int incr = forward ? 1 : -1;
119
120
20.4M
    check_read_type(*op1, t_string);
121
20.4M
    check_read_type(*op, t_string);
122
20.4M
    if (size > r_size(op1)) { /* can't match */
123
1.84M
        make_false(op);
124
1.84M
        return 0;
125
1.84M
    }
126
18.5M
    count = r_size(op1) - size;
127
18.5M
    ptr = op1->value.bytes;
128
18.5M
    if (size == 0)
129
1
        goto found;
130
18.5M
    if (!forward)
131
17.8M
        ptr += count;
132
18.5M
    pat = op->value.bytes;
133
18.5M
    ch = pat[0];
134
216M
    do {
135
216M
        if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size)))
136
667k
            goto found;
137
215M
        ptr += incr;
138
215M
    }
139
215M
    while (count--);
140
    /* No match */
141
17.9M
    make_false(op);
142
17.9M
    return 0;
143
667k
found:
144
667k
    op->tas.type_attrs = op1->tas.type_attrs;
145
667k
    op->value.bytes = ptr;        /* match */
146
667k
    op->tas.rsize = size;       /* match */
147
667k
    push(2);
148
667k
    op[-1] = *op1;          /* pre */
149
667k
    op[-3].value.bytes = ptr + size;      /* post */
150
667k
    if (forward) {
151
399k
        op[-1].tas.rsize = ptr - op[-1].value.bytes;  /* pre */
152
399k
        op[-3].tas.rsize = count;     /* post */
153
399k
    } else {
154
267k
        op[-1].tas.rsize = count;     /* pre */
155
267k
        op[-3].tas.rsize -= count + size;   /* post */
156
267k
    }
157
667k
    make_true(op);
158
667k
    return 0;
159
667k
}
160
161
/* Search from the start of the string */
162
static int
163
zsearch(i_ctx_t *i_ctx_p)
164
2.57M
{
165
2.57M
    return search_impl(i_ctx_p, true);
166
2.57M
}
167
168
/* Search from the end of the string */
169
static int
170
zrsearch(i_ctx_t *i_ctx_p)
171
17.8M
{
172
17.8M
    return search_impl(i_ctx_p, false);
173
17.8M
}
174
175
/* <string> <charstring> .stringbreak <int|null> */
176
static int
177
zstringbreak(i_ctx_t *i_ctx_p)
178
0
{
179
0
    os_ptr op = osp;
180
0
    uint i, j;
181
182
0
    check_read_type(op[-1], t_string);
183
0
    check_read_type(*op, t_string);
184
    /* We can't use strpbrk here, because C doesn't allow nulls in strings. */
185
0
    for (i = 0; i < r_size(op - 1); ++i)
186
0
        for (j = 0; j < r_size(op); ++j)
187
0
            if (op[-1].value.const_bytes[i] == op->value.const_bytes[j]) {
188
0
                make_int(op - 1, i);
189
0
                goto done;
190
0
            }
191
0
    make_null(op - 1);
192
0
 done:
193
0
    pop(1);
194
0
    return 0;
195
0
}
196
197
/* <obj> <pattern> .stringmatch <bool> */
198
static int
199
zstringmatch(i_ctx_t *i_ctx_p)
200
0
{
201
0
    os_ptr op = osp;
202
0
    os_ptr op1 = op - 1;
203
0
    bool result;
204
205
0
    check_read_type(*op, t_string);
206
0
    switch (r_type(op1)) {
207
0
        case t_string:
208
0
            check_read(*op1);
209
0
            goto cmp;
210
0
        case t_name:
211
0
            name_string_ref(imemory, op1, op1);  /* can't fail */
212
0
cmp:
213
0
            result = string_match(op1->value.const_bytes, r_size(op1),
214
0
                                  op->value.const_bytes, r_size(op),
215
0
                                  NULL);
216
0
            break;
217
0
        default:
218
0
            result = (r_size(op) == 1 && *op->value.bytes == '*');
219
0
    }
220
0
    make_bool(op1, result);
221
0
    pop(1);
222
0
    return 0;
223
0
}
224
225
/* ------ Initialization procedure ------ */
226
227
const op_def zstring_op_defs[] =
228
{
229
    {"1.bytestring", zbytestring},
230
    {"2anchorsearch", zanchorsearch},
231
    {"1.namestring", znamestring},
232
    {"2search", zsearch},
233
    {"2rsearch", zrsearch},
234
    {"1string", zstring},
235
    {"2.stringbreak", zstringbreak},
236
    {"2.stringmatch", zstringmatch},
237
    op_def_end(0)
238
};