Commit 661db7435145279ae81c87c837c4de263991ab8f
Committed by
GitHub
Merge pull request #1481 from m-holger/pl_dct
Refactor `Pl_DCT` buffer management to use `std::string` and simplify…
Showing
2 changed files
with
20 additions
and
28 deletions
include/qpdf/Pl_DCT.hh
| @@ -22,7 +22,6 @@ | @@ -22,7 +22,6 @@ | ||
| 22 | 22 | ||
| 23 | #include <qpdf/Pipeline.hh> | 23 | #include <qpdf/Pipeline.hh> |
| 24 | 24 | ||
| 25 | -#include <qpdf/Pl_Buffer.hh> | ||
| 26 | #include <cstddef> | 25 | #include <cstddef> |
| 27 | #include <functional> | 26 | #include <functional> |
| 28 | 27 | ||
| @@ -88,9 +87,9 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline | @@ -88,9 +87,9 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline | ||
| 88 | 87 | ||
| 89 | private: | 88 | private: |
| 90 | QPDF_DLL_PRIVATE | 89 | QPDF_DLL_PRIVATE |
| 91 | - void compress(void* cinfo, Buffer*); | 90 | + void compress(void* cinfo); |
| 92 | QPDF_DLL_PRIVATE | 91 | QPDF_DLL_PRIVATE |
| 93 | - void decompress(void* cinfo, Buffer*); | 92 | + void decompress(void* cinfo); |
| 94 | 93 | ||
| 95 | enum action_e { a_compress, a_decompress }; | 94 | enum action_e { a_compress, a_decompress }; |
| 96 | 95 |
libqpdf/Pl_DCT.cc
| @@ -84,7 +84,6 @@ class Pl_DCT::Members | @@ -84,7 +84,6 @@ class Pl_DCT::Members | ||
| 84 | J_COLOR_SPACE color_space, | 84 | J_COLOR_SPACE color_space, |
| 85 | CompressConfig* config_callback) : | 85 | CompressConfig* config_callback) : |
| 86 | action(a_compress), | 86 | action(a_compress), |
| 87 | - buf("DCT uncompressed image"), | ||
| 88 | image_width(image_width), | 87 | image_width(image_width), |
| 89 | image_height(image_height), | 88 | image_height(image_height), |
| 90 | components(components), | 89 | components(components), |
| @@ -95,8 +94,7 @@ class Pl_DCT::Members | @@ -95,8 +94,7 @@ class Pl_DCT::Members | ||
| 95 | 94 | ||
| 96 | // For decompression | 95 | // For decompression |
| 97 | Members() : | 96 | Members() : |
| 98 | - action(a_decompress), | ||
| 99 | - buf("DCT compressed image") | 97 | + action(a_decompress) |
| 100 | { | 98 | { |
| 101 | } | 99 | } |
| 102 | 100 | ||
| @@ -105,7 +103,7 @@ class Pl_DCT::Members | @@ -105,7 +103,7 @@ class Pl_DCT::Members | ||
| 105 | ~Members() = default; | 103 | ~Members() = default; |
| 106 | 104 | ||
| 107 | action_e action; | 105 | action_e action; |
| 108 | - Pl_Buffer buf; | 106 | + std::string buf; |
| 109 | 107 | ||
| 110 | // Used for compression | 108 | // Used for compression |
| 111 | JDIMENSION image_width{0}; | 109 | JDIMENSION image_width{0}; |
| @@ -163,21 +161,17 @@ Pl_DCT::~Pl_DCT() = default; | @@ -163,21 +161,17 @@ Pl_DCT::~Pl_DCT() = default; | ||
| 163 | void | 161 | void |
| 164 | Pl_DCT::write(unsigned char const* data, size_t len) | 162 | Pl_DCT::write(unsigned char const* data, size_t len) |
| 165 | { | 163 | { |
| 166 | - m->buf.write(data, len); | 164 | + if (len > 0) { |
| 165 | + m->buf.append(reinterpret_cast<char const*>(data), len); | ||
| 166 | + } | ||
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | void | 169 | void |
| 170 | Pl_DCT::finish() | 170 | Pl_DCT::finish() |
| 171 | { | 171 | { |
| 172 | - m->buf.finish(); | ||
| 173 | - | ||
| 174 | - // Using a std::shared_ptr<Buffer> here and passing it into compress and decompress causes a | ||
| 175 | - // memory leak with setjmp/longjmp. Just use a pointer and delete it. | ||
| 176 | - Buffer* b = m->buf.getBuffer(); | ||
| 177 | - if (b->getSize() == 0) { | 172 | + if (m->buf.empty()) { |
| 178 | // Special case: empty data will never succeed and probably means we're calling finish a | 173 | // Special case: empty data will never succeed and probably means we're calling finish a |
| 179 | // second time from an exception handler. | 174 | // second time from an exception handler. |
| 180 | - delete b; | ||
| 181 | next()->finish(); | 175 | next()->finish(); |
| 182 | return; | 176 | return; |
| 183 | } | 177 | } |
| @@ -198,9 +192,9 @@ Pl_DCT::finish() | @@ -198,9 +192,9 @@ Pl_DCT::finish() | ||
| 198 | if (setjmp(jerr.jmpbuf) == 0) { | 192 | if (setjmp(jerr.jmpbuf) == 0) { |
| 199 | try { | 193 | try { |
| 200 | if (m->action == a_compress) { | 194 | if (m->action == a_compress) { |
| 201 | - compress(reinterpret_cast<void*>(&cinfo_compress), b); | 195 | + compress(reinterpret_cast<void*>(&cinfo_compress)); |
| 202 | } else { | 196 | } else { |
| 203 | - decompress(reinterpret_cast<void*>(&cinfo_decompress), b); | 197 | + decompress(reinterpret_cast<void*>(&cinfo_decompress)); |
| 204 | } | 198 | } |
| 205 | } catch (std::exception& e) { | 199 | } catch (std::exception& e) { |
| 206 | // Convert an exception back to a longjmp so we can ensure that the right cleanup | 200 | // Convert an exception back to a longjmp so we can ensure that the right cleanup |
| @@ -211,7 +205,6 @@ Pl_DCT::finish() | @@ -211,7 +205,6 @@ Pl_DCT::finish() | ||
| 211 | } else { | 205 | } else { |
| 212 | error = true; | 206 | error = true; |
| 213 | } | 207 | } |
| 214 | - delete b; | ||
| 215 | 208 | ||
| 216 | if (m->action == a_compress) { | 209 | if (m->action == a_compress) { |
| 217 | jpeg_destroy_compress(&cinfo_compress); | 210 | jpeg_destroy_compress(&cinfo_compress); |
| @@ -312,7 +305,7 @@ term_buffer_source(j_decompress_ptr) | @@ -312,7 +305,7 @@ term_buffer_source(j_decompress_ptr) | ||
| 312 | } | 305 | } |
| 313 | 306 | ||
| 314 | static void | 307 | static void |
| 315 | -jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer) | 308 | +jpeg_buffer_src(j_decompress_ptr cinfo, std::string& buffer) |
| 316 | { | 309 | { |
| 317 | cinfo->src = reinterpret_cast<jpeg_source_mgr*>( | 310 | cinfo->src = reinterpret_cast<jpeg_source_mgr*>( |
| 318 | // line-break | 311 | // line-break |
| @@ -325,12 +318,12 @@ jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer) | @@ -325,12 +318,12 @@ jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer) | ||
| 325 | src->skip_input_data = skip_buffer_input_data; | 318 | src->skip_input_data = skip_buffer_input_data; |
| 326 | src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ | 319 | src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ |
| 327 | src->term_source = term_buffer_source; | 320 | src->term_source = term_buffer_source; |
| 328 | - src->bytes_in_buffer = buffer->getSize(); | ||
| 329 | - src->next_input_byte = buffer->getBuffer(); | 321 | + src->bytes_in_buffer = buffer.size(); |
| 322 | + src->next_input_byte = reinterpret_cast<unsigned char*>(buffer.data()); | ||
| 330 | } | 323 | } |
| 331 | 324 | ||
| 332 | void | 325 | void |
| 333 | -Pl_DCT::compress(void* cinfo_p, Buffer* b) | 326 | +Pl_DCT::compress(void* cinfo_p) |
| 334 | { | 327 | { |
| 335 | auto* cinfo = reinterpret_cast<jpeg_compress_struct*>(cinfo_p); | 328 | auto* cinfo = reinterpret_cast<jpeg_compress_struct*>(cinfo_p); |
| 336 | 329 | ||
| @@ -361,13 +354,13 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) | @@ -361,13 +354,13 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) | ||
| 361 | unsigned int width = cinfo->image_width * QIntC::to_uint(cinfo->input_components); | 354 | unsigned int width = cinfo->image_width * QIntC::to_uint(cinfo->input_components); |
| 362 | size_t expected_size = QIntC::to_size(cinfo->image_height) * | 355 | size_t expected_size = QIntC::to_size(cinfo->image_height) * |
| 363 | QIntC::to_size(cinfo->image_width) * QIntC::to_size(cinfo->input_components); | 356 | QIntC::to_size(cinfo->image_width) * QIntC::to_size(cinfo->input_components); |
| 364 | - if (b->getSize() != expected_size) { | 357 | + if (m->buf.size() != expected_size) { |
| 365 | throw std::runtime_error( | 358 | throw std::runtime_error( |
| 366 | - "Pl_DCT: image buffer size = " + std::to_string(b->getSize()) + | 359 | + "Pl_DCT: image buffer size = " + std::to_string(m->buf.size()) + |
| 367 | "; expected size = " + std::to_string(expected_size)); | 360 | "; expected size = " + std::to_string(expected_size)); |
| 368 | } | 361 | } |
| 369 | JSAMPROW row_pointer[1]; | 362 | JSAMPROW row_pointer[1]; |
| 370 | - unsigned char* buffer = b->getBuffer(); | 363 | + auto buffer = reinterpret_cast<unsigned char*>(m->buf.data()); |
| 371 | while (cinfo->next_scanline < cinfo->image_height) { | 364 | while (cinfo->next_scanline < cinfo->image_height) { |
| 372 | // We already verified that the buffer is big enough. | 365 | // We already verified that the buffer is big enough. |
| 373 | row_pointer[0] = &buffer[cinfo->next_scanline * width]; | 366 | row_pointer[0] = &buffer[cinfo->next_scanline * width]; |
| @@ -378,7 +371,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) | @@ -378,7 +371,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) | ||
| 378 | } | 371 | } |
| 379 | 372 | ||
| 380 | void | 373 | void |
| 381 | -Pl_DCT::decompress(void* cinfo_p, Buffer* b) | 374 | +Pl_DCT::decompress(void* cinfo_p) |
| 382 | { | 375 | { |
| 383 | auto* cinfo = reinterpret_cast<jpeg_decompress_struct*>(cinfo_p); | 376 | auto* cinfo = reinterpret_cast<jpeg_decompress_struct*>(cinfo_p); |
| 384 | 377 | ||
| @@ -395,10 +388,10 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b) | @@ -395,10 +388,10 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b) | ||
| 395 | cinfo->mem->max_memory_to_use = memory_limit; | 388 | cinfo->mem->max_memory_to_use = memory_limit; |
| 396 | } | 389 | } |
| 397 | 390 | ||
| 398 | - jpeg_buffer_src(cinfo, b); | 391 | + jpeg_buffer_src(cinfo, m->buf); |
| 399 | 392 | ||
| 400 | (void)jpeg_read_header(cinfo, TRUE); | 393 | (void)jpeg_read_header(cinfo, TRUE); |
| 401 | - (void)jpeg_calc_output_dimensions(cinfo); | 394 | + jpeg_calc_output_dimensions(cinfo); |
| 402 | unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components); | 395 | unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components); |
| 403 | if (memory_limit > 0 && | 396 | if (memory_limit > 0 && |
| 404 | width > (static_cast<unsigned long>(memory_limit) / (20U * cinfo->output_height))) { | 397 | width > (static_cast<unsigned long>(memory_limit) / (20U * cinfo->output_height))) { |