1//========================================================================
2//
3// FlateEncoder.cc
4//
5// Copyright (C) 2016, William Bader <williambader@hotmail.com>
6// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
7// Copyright (C) 2021 Even Rouault <even.rouault@spatialys.com>
8// Copyright (C) 2022 Albert Astals Cid <aacid@kde.org>
9//
10// This file is under the GPLv2 or later license
11//
12//========================================================================
13
14#include <config.h>
15
16#include "FlateEncoder.h"
17
18//------------------------------------------------------------------------
19// FlateEncoder
20//------------------------------------------------------------------------
21
22FlateEncoder::FlateEncoder(Stream *strA) : FilterStream(strA)
23{
24 int zlib_status;
25
26 outBufPtr = outBufEnd = outBuf;
27 inBufEof = outBufEof = false;
28
29 // We used to assign Z_NULL to the 3 following members of zlib_stream,
30 // but as Z_NULL is a #define to 0, using it triggers the
31 // -Wzero-as-null-pointer-constant warning.
32 // For safety, check that the Z_NULL definition is equivalent to
33 // 0 / null pointer.
34 static_assert(static_cast<int>(Z_NULL) == 0);
35 zlib_stream.zalloc = nullptr;
36 zlib_stream.zfree = nullptr;
37 zlib_stream.opaque = nullptr;
38
39 zlib_status = deflateInit(&zlib_stream, Z_DEFAULT_COMPRESSION);
40
41 if (zlib_status != Z_OK) {
42 inBufEof = outBufEof = true;
43 error(category: errInternal, pos: -1, msg: "Internal: deflateInit() failed in FlateEncoder::FlateEncoder()");
44 }
45
46 zlib_stream.next_out = outBufEnd;
47 zlib_stream.avail_out = 1; /* anything but 0 to trigger a read */
48}
49
50FlateEncoder::~FlateEncoder()
51{
52 deflateEnd(strm: &zlib_stream);
53 if (str->isEncoder()) {
54 delete str;
55 }
56}
57
58void FlateEncoder::reset()
59{
60 int zlib_status;
61
62 str->reset();
63
64 outBufPtr = outBufEnd = outBuf;
65 inBufEof = outBufEof = false;
66
67 deflateEnd(strm: &zlib_stream);
68
69 zlib_status = deflateInit(&zlib_stream, Z_DEFAULT_COMPRESSION);
70
71 if (zlib_status != Z_OK) {
72 inBufEof = outBufEof = true;
73 error(category: errInternal, pos: -1, msg: "Internal: deflateInit() failed in FlateEncoder::reset()");
74 }
75
76 zlib_stream.next_out = outBufEnd;
77 zlib_stream.avail_out = 1; /* anything but 0 to trigger a read */
78}
79
80bool FlateEncoder::fillBuf()
81{
82 unsigned int starting_avail_out;
83 int zlib_status;
84
85 /* If the output is done, don't try to read more. */
86
87 if (outBufEof) {
88 return false;
89 }
90
91 /* The output buffer should be empty. */
92 /* If it is not empty, push any processed data to the start. */
93
94 if (outBufPtr > outBuf && outBufPtr < outBufEnd) {
95 const ptrdiff_t n = outBufEnd - outBufPtr;
96 memmove(dest: outBuf, src: outBufPtr, n: n);
97 outBufEnd = &outBuf[n];
98 } else {
99 outBufEnd = outBuf;
100 }
101 outBufPtr = outBuf;
102
103 /* Keep feeding zlib until we get output. */
104 /* zlib might consume a few input buffers */
105 /* before it starts producing output. */
106
107 do {
108
109 /* avail_out > 0 means that zlib has depleted its input */
110 /* and needs a new chunk of input in order to generate */
111 /* more output. */
112
113 if (zlib_stream.avail_out != 0) {
114
115 /* Fill the input buffer */
116
117 const int n = (inBufEof ? 0 : str->doGetChars(nChars: inBufSize, buffer: inBuf));
118
119 if (n == 0) {
120 inBufEof = true;
121 }
122
123 zlib_stream.next_in = inBuf;
124 zlib_stream.avail_in = n;
125 }
126
127 /* Ask zlib for output. */
128
129 zlib_stream.next_out = outBufEnd;
130 starting_avail_out = static_cast<unsigned int>(&outBuf[outBufSize] - outBufEnd);
131 zlib_stream.avail_out = starting_avail_out;
132
133 zlib_status = deflate(strm: &zlib_stream, flush: (inBufEof ? Z_FINISH : Z_NO_FLUSH));
134
135 if (zlib_status == Z_STREAM_ERROR || zlib_stream.avail_out > starting_avail_out) {
136 /* Unrecoverable error */
137 inBufEof = outBufEof = true;
138 error(category: errInternal, pos: -1, msg: "Internal: deflate() failed in FlateEncoder::fillBuf()");
139 return false;
140 }
141
142 } while (zlib_stream.avail_out == outBufSize && !inBufEof);
143
144 outBufEnd = &outBuf[outBufSize] - zlib_stream.avail_out;
145
146 if (inBufEof && zlib_stream.avail_out != 0) {
147 outBufEof = true;
148 }
149
150 return outBufPtr < outBufEnd;
151}
152

source code of poppler/poppler/FlateEncoder.cc