Beispiel #1
0
static SquashStatus
squash_zling_splice (SquashCodec* codec,
                     SquashOptions* options,
                     SquashStreamType stream_type,
                     SquashReadFunc read_cb,
                     SquashWriteFunc write_cb,
                     void* user_data) {
  try {
    SquashZlingIO stream(user_data, read_cb, write_cb);
    int zres = 0;

    if (stream_type == SQUASH_STREAM_COMPRESS) {
      zres = baidu::zling::Encode(&stream, &stream, NULL, squash_options_get_int_at (options, codec, SQUASH_ZLING_OPT_LEVEL));
    } else {
      zres = baidu::zling::Decode(&stream, &stream, NULL);
    }

    if (zres == 0)
      return SQUASH_OK;
    else if (HEDLEY_LIKELY(stream.last_res < 0))
      return stream.last_res;
    else
      return squash_error (SQUASH_FAILED);
  } catch (const std::bad_alloc& e) {
    return squash_error (SQUASH_MEMORY);
  } catch (const SquashStatus e) {
    return e;
  } catch (...) {
    return squash_error (SQUASH_FAILED);
  }

  HEDLEY_UNREACHABLE ();
}
Beispiel #2
0
static SquashStatus
squash_libdeflate_decompress_buffer (SquashCodec* codec,
                                size_t* decompressed_size,
                                uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)],
                                size_t compressed_size,
                                const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)],
                                SquashOptions* options) {
  struct deflate_decompressor *decompressor = deflate_alloc_decompressor();
  size_t actual_out_nbytes;
  enum decompress_result ret = deflate_decompress(decompressor, compressed, compressed_size,
                                             decompressed, *decompressed_size, &actual_out_nbytes);
  deflate_free_decompressor(decompressor);
  *decompressed_size = actual_out_nbytes;
  switch (ret) {
    case DECOMPRESS_SUCCESS:
      return SQUASH_OK;
    case DECOMPRESS_BAD_DATA:
      return squash_error (SQUASH_FAILED);
    case DECOMPRESS_SHORT_OUTPUT:
      return squash_error (SQUASH_BUFFER_FULL);
    case DECOMPRESS_INSUFFICIENT_SPACE:
      return squash_error (SQUASH_BUFFER_FULL);
  }

  HEDLEY_UNREACHABLE ();
}
Beispiel #3
0
static SquashStatus
squash_lz4f_process_stream (SquashStream* stream, SquashOperation operation) {
  switch (stream->stream_type) {
    case SQUASH_STREAM_COMPRESS:
      return squash_lz4f_compress_stream (stream, operation);
    case SQUASH_STREAM_DECOMPRESS:
      return squash_lz4f_decompress_stream (stream, operation);
    default:
      HEDLEY_UNREACHABLE();
  }
}
Beispiel #4
0
static int test_unreachable(enum Foo code) {
  switch (code) {
  case FOO_BAR:
  case FOO_BAZ:
  case FOO_QUX:
    return 0;
  case FOO_QUUX:
  default:
    HEDLEY_UNREACHABLE();
  }

  HEDLEY_UNREACHABLE_RETURN(0);
}
Beispiel #5
0
static size_t
squash_lz4f_block_size_id_to_size (LZ4F_blockSizeID_t blkid) {
  switch (blkid) {
    case LZ4F_max64KB:
      return  64 * 1024;
    case LZ4F_max256KB:
      return 256 * 1024;
    case LZ4F_max1MB:
      return   1 * 1024 * 1024;
    case LZ4F_max4MB:
      return   4 * 1024 * 1024;
    case LZ4F_default:
    default:
      HEDLEY_UNREACHABLE();
      break;
  }
}
Beispiel #6
0
static SquashStatus
squash_lz4f_get_status (size_t res) {
  if (!LZ4F_isError (res))
    return SQUASH_OK;

  switch ((LZ4F_errorCodes) (-(int)(res))) {
    case LZ4F_OK_NoError:
      return SQUASH_OK;
    case LZ4F_ERROR_GENERIC:
      return squash_error (SQUASH_FAILED);
    case LZ4F_ERROR_maxBlockSize_invalid:
    case LZ4F_ERROR_blockMode_invalid:
    case LZ4F_ERROR_contentChecksumFlag_invalid:
    case LZ4F_ERROR_headerVersion_wrong:
    case LZ4F_ERROR_blockChecksum_unsupported:
    case LZ4F_ERROR_reservedFlag_set:
    case LZ4F_ERROR_frameHeader_incomplete:
    case LZ4F_ERROR_frameType_unknown:
    case LZ4F_ERROR_frameSize_wrong:
    case LZ4F_ERROR_headerChecksum_invalid:
    case LZ4F_ERROR_contentChecksum_invalid:
      return squash_error (SQUASH_INVALID_BUFFER);
    case LZ4F_ERROR_compressionLevel_invalid:
      return squash_error (SQUASH_BAD_VALUE);
    case LZ4F_ERROR_allocation_failed:
      return squash_error (SQUASH_MEMORY);
    case LZ4F_ERROR_srcSize_tooLarge:
    case LZ4F_ERROR_dstMaxSize_tooSmall:
      return squash_error (SQUASH_BUFFER_FULL);
    case LZ4F_ERROR_decompressionFailed:
    case LZ4F_ERROR_srcPtr_wrong:
    case LZ4F_ERROR_maxCode:
      return squash_error (SQUASH_FAILED);
    default:
      HEDLEY_UNREACHABLE ();
  }
}
Beispiel #7
0
static SquashStatus
squash_lz4f_compress_stream (SquashStream* stream, SquashOperation operation) {
  SquashLZ4FStream* s = (SquashLZ4FStream*) stream;
  bool progress = false;

  if (s->data.comp.output_buffer_size != 0) {
    const size_t buffer_remaining = s->data.comp.output_buffer_size - s->data.comp.output_buffer_pos;
    const size_t cp_size = (buffer_remaining < stream->avail_out) ? buffer_remaining : stream->avail_out;

    memcpy (stream->next_out, s->data.comp.output_buffer + s->data.comp.output_buffer_pos, cp_size);
    stream->next_out += cp_size;
    stream->avail_out -= cp_size;
    s->data.comp.output_buffer_pos += cp_size;

    if (cp_size == buffer_remaining) {
      s->data.comp.output_buffer_size = 0;
      s->data.comp.output_buffer_pos = 0;

      progress = true;
    } else {
      return SQUASH_PROCESSING;
    }
  }

  while ((stream->avail_in != 0 || operation != SQUASH_OPERATION_PROCESS) && stream->avail_out != 0) {
    if (s->data.comp.state == SQUASH_LZ4F_STATE_INIT) {
      s->data.comp.state = SQUASH_LZ4F_STATE_ACTIVE;
      if (stream->avail_out < 19) {
        s->data.comp.output_buffer_size =
          LZ4F_compressBegin (s->data.comp.ctx,
                              squash_lz4f_stream_get_output_buffer (stream),
                              squash_lz4f_stream_get_output_buffer_size (stream),
                              &(s->data.comp.prefs));
        break;
      } else {
        size_t written = LZ4F_compressBegin (s->data.comp.ctx, stream->next_out, stream->avail_out, &(s->data.comp.prefs));
        stream->next_out += written;
        stream->avail_out -= written;
        progress = true;
      }
    } else {
      const size_t input_buffer_size = squash_lz4f_get_input_buffer_size (stream);
      const size_t total_input = stream->avail_in + s->data.comp.input_buffer_size;
      const size_t output_buffer_max_size = squash_lz4f_stream_get_output_buffer_size (stream);

      if (progress && (total_input < input_buffer_size || stream->avail_out < output_buffer_max_size))
        break;

      uint8_t* obuf;
      size_t olen;

      const size_t input_size = (total_input > input_buffer_size) ? (input_buffer_size - s->data.comp.input_buffer_size) : stream->avail_in;
      if (input_size > 0) {
        obuf = (output_buffer_max_size > stream->avail_out) ? squash_lz4f_stream_get_output_buffer (stream) : stream->next_out;
        olen = LZ4F_compressUpdate (s->data.comp.ctx, obuf, output_buffer_max_size, stream->next_in, input_size, NULL);

        if (!LZ4F_isError (olen)) {
          if (input_size + s->data.comp.input_buffer_size == input_buffer_size) {
            s->data.comp.input_buffer_size = 0;
          } else {
            s->data.comp.input_buffer_size += input_size;
            assert (olen == 0);
          }

          stream->next_in += input_size;
          stream->avail_in -= input_size;
        } else {
          HEDLEY_UNREACHABLE();
        }
      } else if (operation == SQUASH_OPERATION_FLUSH) {
        assert (stream->avail_in == 0);
        olen = squash_lz4f_stream_get_output_buffer_size (stream);
        obuf = (olen > stream->avail_out) ? squash_lz4f_stream_get_output_buffer (stream) : stream->next_out;
        olen = LZ4F_flush (s->data.comp.ctx, obuf, olen, NULL);

        s->data.comp.input_buffer_size = 0;
      } else if (operation == SQUASH_OPERATION_FINISH) {
        assert (stream->avail_in == 0);
        olen = squash_lz4f_stream_get_output_buffer_size (stream);
        obuf = (olen > stream->avail_out) ? squash_lz4f_stream_get_output_buffer (stream) : stream->next_out;
        olen = LZ4F_compressEnd (s->data.comp.ctx, obuf, olen, NULL);

        s->data.comp.input_buffer_size = 0;
      } else if (progress) {
        break;
      } else {
        HEDLEY_UNREACHABLE();
      }

      if (HEDLEY_UNLIKELY(LZ4F_isError (olen))) {
        HEDLEY_UNREACHABLE();
        return squash_error (SQUASH_FAILED);
      } else {
        if (olen != 0) {
          if (obuf == s->data.comp.output_buffer) {
            s->data.comp.output_buffer_size = olen;
            break;
          } else {
            stream->next_out += olen;
            stream->avail_out -= olen;
          }
        }
      }

      if (operation != SQUASH_OPERATION_PROCESS)
        break;
    }
  }

  if (s->data.comp.output_buffer_size != 0) {
    const size_t buffer_remaining = s->data.comp.output_buffer_size - s->data.comp.output_buffer_pos;
    const size_t cp_size = (buffer_remaining < stream->avail_out) ? buffer_remaining : stream->avail_out;

    memcpy (stream->next_out, s->data.comp.output_buffer + s->data.comp.output_buffer_pos, cp_size);
    stream->next_out += cp_size;
    stream->avail_out -= cp_size;
    s->data.comp.output_buffer_pos += cp_size;

    if (cp_size == buffer_remaining) {
      s->data.comp.output_buffer_size = 0;
      s->data.comp.output_buffer_pos = 0;

      progress = true;
    } else {
      return SQUASH_PROCESSING;
    }
  }

  return (stream->avail_in == 0 && s->data.comp.output_buffer_size == 0) ? SQUASH_OK : SQUASH_PROCESSING;
}
Beispiel #8
0
static SquashStatus
squash_file_write_internal (SquashFile* file,
                            size_t uncompressed_size,
                            const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)],
                            SquashOperation operation) {
  SquashStatus res;

  assert (file != NULL);

  if (HEDLEY_UNLIKELY(file->last_status < 0))
    return file->last_status;

  if (file->stream == NULL) {
    file->stream = squash_codec_create_stream_with_options (file->codec, SQUASH_STREAM_COMPRESS, file->options);
    if (HEDLEY_UNLIKELY(file->stream == NULL)) {
      res = squash_error (SQUASH_FAILED);
      goto cleanup;
    }
  }

  assert (file->stream->next_in == NULL);
  assert (file->stream->avail_in == 0);
  assert (file->stream->next_out == NULL);
  assert (file->stream->avail_out == 0);

  file->stream->next_in = uncompressed;
  file->stream->avail_in = uncompressed_size;

  do {
    file->stream->next_out = file->buf;
    file->stream->avail_out = SQUASH_FILE_BUF_SIZE;

    switch (operation) {
      case SQUASH_OPERATION_PROCESS:
        res = squash_stream_process (file->stream);
        break;
      case SQUASH_OPERATION_FLUSH:
        res = squash_stream_flush (file->stream);
        break;
      case SQUASH_OPERATION_FINISH:
        res = squash_stream_finish (file->stream);
        break;
      case SQUASH_OPERATION_TERMINATE:
        HEDLEY_UNREACHABLE ();
        break;
    }

    if (res > 0 && file->stream->avail_out != SQUASH_FILE_BUF_SIZE) {
      size_t bytes_written = SQUASH_FWRITE_UNLOCKED(file->buf, 1, SQUASH_FILE_BUF_SIZE - file->stream->avail_out, file->fp);
      if (bytes_written != SQUASH_FILE_BUF_SIZE - file->stream->avail_out) {
        res = SQUASH_IO;
        goto cleanup;
      }
    }
  } while (res == SQUASH_PROCESSING);

 cleanup:

  if (file->stream != NULL) {
    file->stream->next_in = NULL;
    file->stream->avail_in = 0;
    file->stream->next_out = NULL;
    file->stream->avail_out = 0;
  }

  return file->last_status = res;
}