Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/sbrotlie.c
Line
Count
Source
1
/* Copyright (C) 2025 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
/* brotli encoding (compression) filter stream */
18
#include "std.h"
19
#include "strimpl.h"
20
#include "sbrotlix.h"
21
22
#if defined(ENABLE_BROTLI) && ENABLE_BROTLI==1
23
#define ENABLE_BROTLI_ENCODE 1
24
#include "brotli/encode.h"
25
#else
26
#define ENABLE_BROTLI_ENCODE 0
27
#endif
28
29
#if ENABLE_BROTLI_ENCODE
30
/* Set defaults for stream parameters. */
31
void
32
s_brotliE_set_defaults(stream_state * st)
33
0
{
34
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
35
36
0
    ss->mode = BROTLI_MODE_GENERIC;
37
0
    ss->windowBits = BROTLI_MAX_WINDOW_BITS;
38
0
    ss->level = 5; /* BROTLI_MAX_QUALITY is 11. 9 is 'better than zlib' */
39
0
}
40
41
/* Initialize the filter. */
42
static int
43
s_brotliE_init(stream_state * st)
44
0
{
45
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
46
47
0
    ss->enc_state = BrotliEncoderCreateInstance(s_brotli_alloc,
48
0
            s_brotli_free,
49
0
            st->memory->non_gc_memory);
50
0
    if (ss->enc_state == NULL)
51
0
        return ERRC; /****** WRONG ******/
52
53
0
    if (BrotliEncoderSetParameter((BrotliEncoderState *)ss->enc_state,
54
0
          BROTLI_PARAM_MODE,
55
0
          ss->mode) == BROTLI_FALSE)
56
0
        goto bad;
57
0
    if (BrotliEncoderSetParameter((BrotliEncoderState *)ss->enc_state,
58
0
          BROTLI_PARAM_QUALITY,
59
0
          ss->level) == BROTLI_FALSE)
60
0
        goto bad;
61
0
    if (BrotliEncoderSetParameter((BrotliEncoderState *)ss->enc_state,
62
0
          BROTLI_PARAM_LGWIN,
63
0
          ss->windowBits) == BROTLI_FALSE)
64
0
        goto bad;
65
66
0
    return 0;
67
68
0
bad:
69
0
    BrotliEncoderDestroyInstance((BrotliEncoderState *)ss->enc_state);
70
0
    ss->enc_state = NULL;
71
0
    return ERRC;
72
0
}
73
74
/* Process a buffer */
75
static int
76
s_brotliE_process(stream_state * st, stream_cursor_read * pr,
77
                  stream_cursor_write * pw, bool last)
78
0
{
79
0
    stream_brotlie_state *const ss = (stream_brotlie_state *)st;
80
0
    const byte *p      = pr->ptr;
81
0
    const byte *inBuf  = p + 1;
82
0
    size_t      inLen  = pr->limit - p;
83
0
    byte       *outBuf = pw->ptr + 1;
84
0
    size_t      outLen = pw->limit - pw->ptr;
85
0
    BROTLI_BOOL status;
86
87
0
    status = BrotliEncoderCompressStream(
88
0
                     (BrotliEncoderState *)ss->enc_state,
89
0
                     last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
90
0
                     &inLen,
91
0
                     &inBuf,
92
0
                     &outLen,
93
0
                     &outBuf,
94
0
                     NULL);
95
96
0
    pr->ptr = inBuf - 1;
97
0
    pw->ptr = outBuf - 1;
98
0
    switch (status) {
99
0
        case BROTLI_TRUE:
100
0
            if (last)
101
0
            {
102
0
                if (BrotliEncoderIsFinished((BrotliEncoderState *)ss->enc_state))
103
0
                    return 0;
104
0
               return 1;
105
0
            }
106
0
            else if (pw->ptr == pw->limit)
107
0
                return 1; /* No output space left */
108
0
            else
109
0
                return 0; /* Anything else interpreted as "Need more input" */
110
0
        default:
111
0
            return ERRC;
112
0
    }
113
0
}
114
115
/* Release the stream */
116
static void
117
s_brotliE_release(stream_state * st)
118
0
{
119
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
120
121
0
    if (ss->enc_state != NULL)
122
0
    {
123
0
        BrotliEncoderDestroyInstance((BrotliEncoderState *)ss->enc_state);
124
0
        ss->enc_state = NULL;
125
0
    }
126
0
}
127
128
static void
129
brotliE_final(const gs_memory_t *mem, void *st)
130
0
{
131
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
132
133
0
    if (ss->enc_state != NULL)
134
0
    {
135
0
        BrotliEncoderDestroyInstance((BrotliEncoderState *)ss->enc_state);
136
        ss->enc_state = NULL;
137
0
    }
138
0
}
139
#else
140
void
141
s_brotliE_set_defaults(stream_state * st)
142
{
143
    (void)st;
144
}
145
static int
146
s_brotliE_init(stream_state * st)
147
{
148
    (void)st;
149
    return ERRC;
150
}
151
static int
152
s_brotliE_process(stream_state * st, stream_cursor_read * pr,
153
                  stream_cursor_write * pw, bool last)
154
{
155
    (void)st;
156
    (void)pr;
157
    (void)pw;
158
    (void)last;
159
    return ERRC;
160
}
161
static void
162
s_brotliE_release(stream_state * st)
163
{
164
    (void)st;
165
}
166
static void
167
brotliE_final(const gs_memory_t *mem, void *st)
168
{
169
    (void)mem;
170
    (void)st;
171
}
172
#endif
173
174
gs_public_st_simple_final(st_brotlie_state, stream_brotlie_state,
175
  "brotli encode state", brotliE_final);
176
177
/* Stream template */
178
const stream_template s_brotliE_template = {
179
    &st_brotlie_state, s_brotliE_init, s_brotliE_process, 1, 1, s_brotliE_release,
180
    s_brotliE_set_defaults
181
};