Coverage Report

Created: 2025-06-10 06:58

/src/ghostpdl/base/gxbcache.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
/* Bitmap cache implementation */
18
#include "memory_.h"
19
#include "stdint_.h"
20
#include "gx.h"
21
#include "gxobj.h"
22
#include "gsmdebug.h"
23
#include "gxbcache.h"
24
25
/* ------ Entire cache ------ */
26
27
/* Initialize a cache.  The caller must allocate and initialize */
28
/* the first chunk. */
29
void
30
gx_bits_cache_init(gx_bits_cache * bc, gx_bits_cache_chunk * bck)
31
28.8k
{
32
28.8k
    bck->next = bck;
33
28.8k
    bc->chunks = bck;
34
28.8k
    bc->cnext = 0;
35
28.8k
    bc->bsize = 0;
36
28.8k
    bc->csize = 0;
37
28.8k
}
38
39
/* ------ Chunks ------ */
40
41
/* Initialize a chunk.  The caller must allocate it and its data. */
42
void
43
gx_bits_cache_chunk_init(gx_bits_cache_chunk * bck, byte * data, uint size)
44
28.9k
{
45
28.9k
    bck->next = 0;
46
28.9k
    bck->data = data;
47
28.9k
    bck->size = size;
48
28.9k
    bck->allocated = 0;
49
28.9k
    if (data != 0) {
50
2.22k
        gx_cached_bits_head *cbh = (gx_cached_bits_head *) data;
51
52
2.22k
        cbh->size = size;
53
2.22k
        cb_head_set_free(cbh);
54
2.22k
    }
55
28.9k
}
56
57
/* ------ Individual entries ------ */
58
59
/* Attempt to allocate an entry.  If successful, set *pcbh and return 0. */
60
/* If there isn't enough room, set *pcbh to an entry requiring freeing, */
61
/* or to 0 if we are at the end of the chunk, and return -1. */
62
int
63
gx_bits_cache_alloc(gx_bits_cache * bc, ulong lsize0, gx_cached_bits_head ** pcbh)
64
3.12k
{
65
3.12k
    ulong lsize = ROUND_UP(lsize0, obj_align_mod);
66
67
27.1k
#define ssize ((uint)lsize)
68
3.12k
    ulong lsize1 = lsize + sizeof(gx_cached_bits_head);
69
70
17.9k
#define ssize1 ((uint)lsize1)
71
3.12k
    uint cnext = bc->cnext;
72
3.12k
    gx_bits_cache_chunk *bck = bc->chunks;
73
3.12k
    uint left = bck->size - cnext;
74
3.12k
    gx_cached_bits_head *cbh;
75
3.12k
    gx_cached_bits_head *cbh_next;
76
3.12k
    uint fsize = 0;
77
78
3.12k
    if (lsize1 > bck->size - cnext && lsize != left) { /* Not enough room to allocate in this chunk. */
79
92
        *pcbh = 0;
80
92
        return -1;
81
92
    }
82
    /* Look for and/or free enough space. */
83
3.02k
    cbh = cbh_next = (gx_cached_bits_head *) (bck->data + cnext);
84
8.98k
    while (fsize < ssize1 && fsize != ssize) {
85
5.95k
        if (!cb_head_is_free(cbh_next)) { /* Ask the caller to free the entry. */
86
0
            if (fsize)
87
0
                cbh->size = fsize;
88
0
            *pcbh = cbh_next;
89
0
            return -1;
90
0
        }
91
5.95k
        fsize += cbh_next->size;
92
5.95k
        if_debug2('K', "[K]merging free bits "PRI_INTPTR"(%u)\n",
93
5.95k
                  (intptr_t)cbh_next, cbh_next->size);
94
5.95k
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + fsize);
95
5.95k
    }
96
3.02k
    if (fsize > ssize) { /* fsize >= ssize1 */
97
3.02k
        cbh_next = (gx_cached_bits_head *) ((byte *) cbh + ssize);
98
3.02k
        cbh_next->size = fsize - ssize;
99
3.02k
        cb_head_set_free(cbh_next);
100
3.02k
        if_debug2('K', "[K]shortening bits "PRI_INTPTR" by %u (initial)\n",
101
3.02k
                  (intptr_t)cbh, fsize - ssize);
102
3.02k
    }
103
3.02k
    gs_alloc_fill(cbh, gs_alloc_fill_block, ssize);
104
3.02k
    cbh->size = ssize;
105
3.02k
    bc->bsize += ssize;
106
3.02k
    bc->csize++;
107
3.02k
    bc->cnext += ssize;
108
3.02k
    bck->allocated += ssize;
109
3.02k
    *pcbh = cbh;
110
3.02k
    return 0;
111
3.02k
#undef ssize
112
3.02k
#undef ssize1
113
3.02k
}
114
115
/* Shorten an entry by a given amount. */
116
void
117
gx_bits_cache_shorten(gx_bits_cache * bc, gx_cached_bits_head * cbh,
118
                      uint diff, gx_bits_cache_chunk * bck)
119
3.02k
{
120
3.02k
    gx_cached_bits_head *next;
121
122
3.02k
    if ((byte *) cbh + cbh->size == bck->data + bc->cnext &&
123
3.02k
        bck == bc->chunks
124
3.02k
        )
125
3.02k
        bc->cnext -= diff;
126
3.02k
    bc->bsize -= diff;
127
3.02k
    bck->allocated -= diff;
128
3.02k
    cbh->size -= diff;
129
3.02k
    next = (gx_cached_bits_head *) ((byte *) cbh + cbh->size);
130
3.02k
    cb_head_set_free(next);
131
3.02k
    next->size = diff;
132
3.02k
}
133
134
/* Free an entry.  The caller is responsible for removing the entry */
135
/* from any other structures (like a hash table). */
136
void
137
gx_bits_cache_free(gx_bits_cache * bc, gx_cached_bits_head * cbh,
138
                   gx_bits_cache_chunk * bck)
139
3.02k
{
140
3.02k
    uint size = cbh->size;
141
142
3.02k
    bc->csize--;
143
3.02k
    bc->bsize -= size;
144
3.02k
    bck->allocated -= size;
145
3.02k
    gs_alloc_fill(cbh, gs_alloc_fill_deleted, size);
146
3.02k
    cbh->size = size;   /* gs_alloc_fill may have overwritten */
147
3.02k
    cb_head_set_free(cbh);
148
3.02k
}
149
150
#ifdef DEBUG
151
/* A useful bit of code to dump the contents of the bitmap cache. Not
152
 * currently called. Current position is indicated with a '>'. */
153
void
154
gx_bits_cache_dump(gx_bits_cache * bc)
155
{
156
    gx_bits_cache_chunk *bck = bc->chunks;
157
    gx_bits_cache_chunk *first = bck;
158
159
    dlprintf2("%d entries making %d bytes\n", bc->csize, bc->bsize);
160
161
    do {
162
        gx_cached_bits_head *cbh;
163
        uint pos = 0;
164
165
        dlprintf2(" chunk of %d bytes (%d allocated)\n", bck->size, bck->allocated);
166
167
        cbh = (gx_cached_bits_head *)bck->data;
168
        while (pos != bck->size) {
169
            dlprintf3(" %csize=%d depth=%d\n",
170
                      pos == bc->cnext && bck == bc->chunks ? '>' : ' ',
171
                      cbh->size, cbh->depth);
172
            pos += cbh->size;
173
            cbh = (gx_cached_bits_head *)(((byte *)cbh) + cbh->size);
174
        }
175
        bck = bck->next;
176
    } while (bck != first);
177
178
    bck=bck;
179
}
180
#endif