コード例 #1
0
ファイル: Compression.cpp プロジェクト: 1Hgm/folly
std::unique_ptr<IOBuf> LZ4Codec::doUncompress(
    const IOBuf* data,
    uint64_t uncompressedLength) {
  std::unique_ptr<IOBuf> clone;
  if (data->isChained()) {
    // LZ4 doesn't support streaming, so we have to coalesce
    clone = data->clone();
    clone->coalesce();
    data = clone.get();
  }

  folly::io::Cursor cursor(data);
  uint64_t actualUncompressedLength;
  if (encodeSize()) {
    actualUncompressedLength = decodeVarintFromCursor(cursor);
    if (uncompressedLength != UNKNOWN_UNCOMPRESSED_LENGTH &&
        uncompressedLength != actualUncompressedLength) {
      throw std::runtime_error("LZ4Codec: invalid uncompressed length");
    }
  } else {
    actualUncompressedLength = uncompressedLength;
    if (actualUncompressedLength == UNKNOWN_UNCOMPRESSED_LENGTH ||
        actualUncompressedLength > maxUncompressedLength()) {
      throw std::runtime_error("LZ4Codec: invalid uncompressed length");
    }
  }

  auto sp = StringPiece{cursor.peekBytes()};
  auto out = IOBuf::create(actualUncompressedLength);
  int n = LZ4_decompress_safe(
      sp.data(),
      reinterpret_cast<char*>(out->writableTail()),
      sp.size(),
      actualUncompressedLength);

  if (n < 0 || uint64_t(n) != actualUncompressedLength) {
    throw std::runtime_error(to<std::string>(
        "LZ4 decompression returned invalid value ", n));
  }
  out->append(actualUncompressedLength);
  return out;
}
コード例 #2
0
ファイル: Encoding.cpp プロジェクト: Grisson/fblualib
void encode(const LuaObject& input, folly::io::CodecType codecType,
            LuaVersionInfo versionInfo, Writer&& writer, int maxVersion,
            uint64_t chunkLength) {
  folly::IOBufQueue dataQueue(folly::IOBufQueue::cacheChainLength());
  apache::thrift::CompactSerializer::serialize(input, &dataQueue);
  auto codec = folly::io::getCodec(codecType);

  // Determine minimum version required for reading
  bool needChunking = false;
  uint64_t codecMaxLength = codec->maxUncompressedLength();
  if (codecMaxLength < chunkLength) {
    chunkLength = codecMaxLength;
  }

  int version = 0;
  if (dataQueue.chainLength() > chunkLength) {
    needChunking = true;
    // Version 2: chunking
    version = 2;
  } else {
    // Version 1: specials, metatables
    for (auto& ref : input.refs) {
      if (ref.__isset.tableVal) {
        auto& table = ref.tableVal;
        if (table.__isset.specialKey ||
            table.__isset.specialValue ||
            table.__isset.metatable) {
          version = 1;
          break;
        }
      }
    }
  }
  DCHECK_LE(version, kMaxSupportedVersion);

  if (version > maxVersion) {
    throw std::invalid_argument(folly::to<std::string>(
        "Version ", version, " required (requested ", maxVersion, ")"));
  }

  ThriftHeader th;
  th.version = version;
  th.codec = static_cast<int32_t>(codecType);
  th.uncompressedLength = dataQueue.chainLength();
  th.luaVersionInfo = std::move(versionInfo);

  auto uncompressed = dataQueue.move();
  std::unique_ptr<folly::IOBuf> compressed;
  if (needChunking) {
    th.__isset.chunks = true;
    compressed = compressChunked(
        codec.get(), uncompressed.get(), chunkLength,
        th.chunks);
  } else {
    compressed = codec->compress(uncompressed.get());
  }
  th.compressedLength = compressed->computeChainDataLength();

  folly::IOBufQueue queue(folly::IOBufQueue::cacheChainLength());
  apache::thrift::CompactSerializer::serialize(th, &queue);

  Header header;
  header.magic = folly::Endian::little(kMagic);
  header.thriftHeaderLength = folly::Endian::little(queue.chainLength());

  writer(folly::IOBuf::copyBuffer(&header, sizeof(header)));
  writer(queue.move());
  writer(std::move(compressed));
}