tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

destination_manager.cc (5436B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include <string.h>
      7 
      8 #include "lib/jpegli/encode.h"
      9 #include "lib/jpegli/error.h"
     10 #include "lib/jpegli/memory_manager.h"
     11 
     12 namespace jpegli {
     13 
     14 constexpr size_t kDestBufferSize = 64 << 10;
     15 
     16 struct StdioDestinationManager {
     17  jpeg_destination_mgr pub;
     18  FILE* f;
     19  uint8_t* buffer;
     20 
     21  static void init_destination(j_compress_ptr cinfo) {
     22    auto* dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
     23    dest->pub.next_output_byte = dest->buffer;
     24    dest->pub.free_in_buffer = kDestBufferSize;
     25  }
     26 
     27  static boolean empty_output_buffer(j_compress_ptr cinfo) {
     28    auto* dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
     29    if (fwrite(dest->buffer, 1, kDestBufferSize, dest->f) != kDestBufferSize) {
     30      JPEGLI_ERROR("Failed to write to output stream.");
     31    }
     32    dest->pub.next_output_byte = dest->buffer;
     33    dest->pub.free_in_buffer = kDestBufferSize;
     34    return TRUE;
     35  }
     36 
     37  static void term_destination(j_compress_ptr cinfo) {
     38    auto* dest = reinterpret_cast<StdioDestinationManager*>(cinfo->dest);
     39    size_t bytes_left = kDestBufferSize - dest->pub.free_in_buffer;
     40    if (bytes_left &&
     41        fwrite(dest->buffer, 1, bytes_left, dest->f) != bytes_left) {
     42      JPEGLI_ERROR("Failed to write to output stream.");
     43    }
     44    fflush(dest->f);
     45    if (ferror(dest->f)) {
     46      JPEGLI_ERROR("Failed to write to output stream.");
     47    }
     48  }
     49 };
     50 
     51 struct MemoryDestinationManager {
     52  jpeg_destination_mgr pub;
     53  // Output buffer supplied by the application
     54  uint8_t** output;
     55  unsigned long* output_size;  // NOLINT
     56  // Output buffer allocated by us.
     57  uint8_t* temp_buffer;
     58  // Current output buffer (either application supplied or allocated by us).
     59  uint8_t* current_buffer;
     60  size_t buffer_size;
     61 
     62  static void init_destination(j_compress_ptr cinfo) {}
     63 
     64  static boolean empty_output_buffer(j_compress_ptr cinfo) {
     65    auto* dest = reinterpret_cast<MemoryDestinationManager*>(cinfo->dest);
     66    uint8_t* next_buffer =
     67        reinterpret_cast<uint8_t*>(malloc(dest->buffer_size * 2));
     68    memcpy(next_buffer, dest->current_buffer, dest->buffer_size);
     69    if (dest->temp_buffer != nullptr) {
     70      free(dest->temp_buffer);
     71    }
     72    dest->temp_buffer = next_buffer;
     73    dest->current_buffer = next_buffer;
     74    *dest->output = next_buffer;
     75    *dest->output_size = dest->buffer_size;
     76    dest->pub.next_output_byte = next_buffer + dest->buffer_size;
     77    dest->pub.free_in_buffer = dest->buffer_size;
     78    dest->buffer_size *= 2;
     79    return TRUE;
     80  }
     81 
     82  static void term_destination(j_compress_ptr cinfo) {
     83    auto* dest = reinterpret_cast<MemoryDestinationManager*>(cinfo->dest);
     84    *dest->output_size = dest->buffer_size - dest->pub.free_in_buffer;
     85  }
     86 };
     87 
     88 }  // namespace jpegli
     89 
     90 void jpegli_stdio_dest(j_compress_ptr cinfo, FILE* outfile) {
     91  if (outfile == nullptr) {
     92    JPEGLI_ERROR("jpegli_stdio_dest: Invalid destination.");
     93  }
     94  if (cinfo->dest && cinfo->dest->init_destination !=
     95                         jpegli::StdioDestinationManager::init_destination) {
     96    JPEGLI_ERROR("jpegli_stdio_dest: a different dest manager was already set");
     97  }
     98  if (!cinfo->dest) {
     99    cinfo->dest = reinterpret_cast<jpeg_destination_mgr*>(
    100        jpegli::Allocate<jpegli::StdioDestinationManager>(cinfo, 1));
    101  }
    102  auto* dest = reinterpret_cast<jpegli::StdioDestinationManager*>(cinfo->dest);
    103  dest->f = outfile;
    104  dest->buffer = jpegli::Allocate<uint8_t>(cinfo, jpegli::kDestBufferSize);
    105  dest->pub.next_output_byte = dest->buffer;
    106  dest->pub.free_in_buffer = jpegli::kDestBufferSize;
    107  dest->pub.init_destination =
    108      jpegli::StdioDestinationManager::init_destination;
    109  dest->pub.empty_output_buffer =
    110      jpegli::StdioDestinationManager::empty_output_buffer;
    111  dest->pub.term_destination =
    112      jpegli::StdioDestinationManager::term_destination;
    113 }
    114 
    115 void jpegli_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer,
    116                     unsigned long* outsize /* NOLINT */) {
    117  if (outbuffer == nullptr || outsize == nullptr) {
    118    JPEGLI_ERROR("jpegli_mem_dest: Invalid destination.");
    119  }
    120  if (cinfo->dest && cinfo->dest->init_destination !=
    121                         jpegli::MemoryDestinationManager::init_destination) {
    122    JPEGLI_ERROR("jpegli_mem_dest: a different dest manager was already set");
    123  }
    124  if (!cinfo->dest) {
    125    auto* dest = jpegli::Allocate<jpegli::MemoryDestinationManager>(cinfo, 1);
    126    dest->temp_buffer = nullptr;
    127    cinfo->dest = reinterpret_cast<jpeg_destination_mgr*>(dest);
    128  }
    129  auto* dest = reinterpret_cast<jpegli::MemoryDestinationManager*>(cinfo->dest);
    130  dest->pub.init_destination =
    131      jpegli::MemoryDestinationManager::init_destination;
    132  dest->pub.empty_output_buffer =
    133      jpegli::MemoryDestinationManager::empty_output_buffer;
    134  dest->pub.term_destination =
    135      jpegli::MemoryDestinationManager::term_destination;
    136  dest->output = outbuffer;
    137  dest->output_size = outsize;
    138  if (*outbuffer == nullptr || *outsize == 0) {
    139    dest->temp_buffer =
    140        reinterpret_cast<uint8_t*>(malloc(jpegli::kDestBufferSize));
    141    *outbuffer = dest->temp_buffer;
    142    *outsize = jpegli::kDestBufferSize;
    143  }
    144  dest->current_buffer = *outbuffer;
    145  dest->buffer_size = *outsize;
    146  dest->pub.next_output_byte = dest->current_buffer;
    147  dest->pub.free_in_buffer = dest->buffer_size;
    148 }