Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/sbrotlie.c
Line
Count
Source (jump to first uncovered line)
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
#include "brotli/encode.h"
23
24
/* Set defaults for stream parameters. */
25
void
26
s_brotliE_set_defaults(stream_state * st)
27
0
{
28
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
29
30
0
    ss->mode = BROTLI_MODE_GENERIC;
31
0
    ss->windowBits = BROTLI_MAX_WINDOW_BITS;
32
0
    ss->level = 5; /* BROTLI_MAX_QUALITY is 11. 9 is 'better than zlib' */
33
0
}
34
35
/* Initialize the filter. */
36
static int
37
s_brotliE_init(stream_state * st)
38
0
{
39
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
40
41
0
    ss->enc_state = BrotliEncoderCreateInstance(s_brotli_alloc,
42
0
            s_brotli_free,
43
0
            st->memory->non_gc_memory);
44
0
    if (ss->enc_state == NULL)
45
0
        return ERRC; /****** WRONG ******/
46
47
0
    if (BrotliEncoderSetParameter((BrotliEncoderState *)ss->enc_state,
48
0
          BROTLI_PARAM_MODE,
49
0
          ss->mode) == BROTLI_FALSE)
50
0
        goto bad;
51
0
    if (BrotliEncoderSetParameter((BrotliEncoderState *)ss->enc_state,
52
0
          BROTLI_PARAM_QUALITY,
53
0
          ss->level) == BROTLI_FALSE)
54
0
        goto bad;
55
0
    if (BrotliEncoderSetParameter((BrotliEncoderState *)ss->enc_state,
56
0
          BROTLI_PARAM_LGWIN,
57
0
          ss->windowBits) == BROTLI_FALSE)
58
0
        goto bad;
59
60
0
    return 0;
61
62
0
bad:
63
0
    BrotliEncoderDestroyInstance((BrotliEncoderState *)ss->enc_state);
64
0
    ss->enc_state = NULL;
65
0
    return ERRC;
66
0
}
67
68
/* Process a buffer */
69
static int
70
s_brotliE_process(stream_state * st, stream_cursor_read * pr,
71
                  stream_cursor_write * pw, bool last)
72
0
{
73
0
    stream_brotlie_state *const ss = (stream_brotlie_state *)st;
74
0
    const byte *p      = pr->ptr;
75
0
    const byte *inBuf  = p + 1;
76
0
    size_t      inLen  = pr->limit - p;
77
0
    byte       *outBuf = pw->ptr + 1;
78
0
    size_t      outLen = pw->limit - pw->ptr;
79
0
    BROTLI_BOOL status;
80
81
0
    status = BrotliEncoderCompressStream(
82
0
                     (BrotliEncoderState *)ss->enc_state,
83
0
                     last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
84
0
                     &inLen,
85
0
                     &inBuf,
86
0
                     &outLen,
87
0
                     &outBuf,
88
0
                     NULL);
89
90
0
    pr->ptr = inBuf - 1;
91
0
    pw->ptr = outBuf - 1;
92
0
    switch (status) {
93
0
        case BROTLI_TRUE:
94
0
            if (last)
95
0
            {
96
0
                if (BrotliEncoderIsFinished((BrotliEncoderState *)ss->enc_state))
97
0
                    return 0;
98
0
               return 1;
99
0
            }
100
0
            else if (pw->ptr == pw->limit)
101
0
                return 1; /* No output space left */
102
0
            else
103
0
                return 0; /* Anything else interpreted as "Need more input" */
104
0
        default:
105
0
            return ERRC;
106
0
    }
107
0
}
108
109
/* Release the stream */
110
static void
111
s_brotliE_release(stream_state * st)
112
0
{
113
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
114
115
0
    if (ss->enc_state != NULL)
116
0
    {
117
0
        BrotliEncoderDestroyInstance((BrotliEncoderState *)ss->enc_state);
118
0
        ss->enc_state = NULL;
119
0
    }
120
0
}
121
122
static void
123
brotliE_final(const gs_memory_t *mem, void *st)
124
0
{
125
0
    stream_brotlie_state *ss = (stream_brotlie_state *)st;
126
127
0
    if (ss->enc_state != NULL)
128
0
    {
129
0
        BrotliEncoderDestroyInstance((BrotliEncoderState *)ss->enc_state);
130
0
        ss->enc_state = NULL;
131
0
    }
132
0
}
133
134
gs_public_st_simple_final(st_brotlie_state, stream_brotlie_state,
135
  "brotli encode state", brotliE_final);
136
137
/* Stream template */
138
const stream_template s_brotliE_template = {
139
    &st_brotlie_state, s_brotliE_init, s_brotliE_process, 1, 1, s_brotliE_release,
140
    s_brotliE_set_defaults
141
};