add EventBase-local storage abstraction
[folly.git] / folly / io / Compression.cpp
index cbfaf68c8eb39b5014a05ed49cc87e8362d5ed47..8c8012dab9a9d84952eaaa3bd125e43ab3a36fd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -148,6 +148,8 @@ std::unique_ptr<IOBuf> NoCompressionCodec::doUncompress(
   return data->clone();
 }
 
+#if (FOLLY_HAVE_LIBLZ4 || FOLLY_HAVE_LIBLZMA)
+
 namespace {
 
 void encodeVarintToIOBuf(uint64_t val, folly::IOBuf* out) {
@@ -155,17 +157,26 @@ void encodeVarintToIOBuf(uint64_t val, folly::IOBuf* out) {
   out->append(encodeVarint(val, out->writableTail()));
 }
 
-uint64_t decodeVarintFromCursor(folly::io::Cursor& cursor) {
-  // Must have enough room in *this* buffer.
-  auto p = cursor.peek();
-  folly::ByteRange range(p.first, p.second);
-  uint64_t val = decodeVarint(range);
-  cursor.skip(range.data() - p.first);
+inline uint64_t decodeVarintFromCursor(folly::io::Cursor& cursor) {
+  uint64_t val = 0;
+  int8_t b = 0;
+  for (int shift = 0; shift <= 63; shift += 7) {
+    b = cursor.read<int8_t>();
+    val |= static_cast<uint64_t>(b & 0x7f) << shift;
+    if (b >= 0) {
+      break;
+    }
+  }
+  if (b < 0) {
+    throw std::invalid_argument("Invalid varint value. Too big.");
+  }
   return val;
 }
 
 }  // namespace
 
+#endif  // FOLLY_HAVE_LIBLZ4 || FOLLY_HAVE_LIBLZMA
+
 #if FOLLY_HAVE_LIBLZ4
 
 /**
@@ -295,7 +306,7 @@ std::unique_ptr<IOBuf> LZ4Codec::doUncompress(
                               p.second,
                               actualUncompressedLength);
 
-  if (n != actualUncompressedLength) {
+  if (n < 0 || uint64_t(n) != actualUncompressedLength) {
     throw std::runtime_error(to<std::string>(
         "LZ4 decompression returned invalid value ", n));
   }
@@ -553,21 +564,25 @@ std::unique_ptr<IOBuf> ZlibCodec::doCompress(const IOBuf* data) {
        defaultBufferLength));
 
   for (auto& range : *data) {
-    if (range.empty()) {
-      continue;
-    }
-
-    stream.next_in = const_cast<uint8_t*>(range.data());
-    stream.avail_in = range.size();
-
-    while (stream.avail_in != 0) {
-      if (stream.avail_out == 0) {
-        out->prependChain(addOutputBuffer(&stream, defaultBufferLength));
+    uint64_t remaining = range.size();
+    uint64_t written = 0;
+    while (remaining) {
+      uint32_t step = (remaining > maxSingleStepLength ?
+                       maxSingleStepLength : remaining);
+      stream.next_in = const_cast<uint8_t*>(range.data() + written);
+      stream.avail_in = step;
+      remaining -= step;
+      written += step;
+
+      while (stream.avail_in != 0) {
+        if (stream.avail_out == 0) {
+          out->prependChain(addOutputBuffer(&stream, defaultBufferLength));
+        }
+
+        rc = deflate(&stream, Z_NO_FLUSH);
+
+        CHECK_EQ(rc, Z_OK) << stream.msg;
       }
-
-      rc = deflate(&stream, Z_NO_FLUSH);
-
-      CHECK_EQ(rc, Z_OK) << stream.msg;
     }
   }
 
@@ -904,55 +919,55 @@ std::unique_ptr<IOBuf> LZMA2Codec::doUncompress(const IOBuf* data,
 
 #endif  // FOLLY_HAVE_LIBLZMA
 
-typedef std::unique_ptr<Codec> (*CodecFactory)(int, CodecType);
+}  // namespace
+
+std::unique_ptr<Codec> getCodec(CodecType type, int level) {
+  typedef std::unique_ptr<Codec> (*CodecFactory)(int, CodecType);
 
-CodecFactory gCodecFactories[
+  static CodecFactory codecFactories[
     static_cast<size_t>(CodecType::NUM_CODEC_TYPES)] = {
-  nullptr,  // USER_DEFINED
-  NoCompressionCodec::create,
+    nullptr,  // USER_DEFINED
+    NoCompressionCodec::create,
 
 #if FOLLY_HAVE_LIBLZ4
-  LZ4Codec::create,
+    LZ4Codec::create,
 #else
-  nullptr,
+    nullptr,
 #endif
 
 #if FOLLY_HAVE_LIBSNAPPY
-  SnappyCodec::create,
+    SnappyCodec::create,
 #else
-  nullptr,
+    nullptr,
 #endif
 
 #if FOLLY_HAVE_LIBZ
-  ZlibCodec::create,
+    ZlibCodec::create,
 #else
-  nullptr,
+    nullptr,
 #endif
 
 #if FOLLY_HAVE_LIBLZ4
-  LZ4Codec::create,
+    LZ4Codec::create,
 #else
-  nullptr,
+    nullptr,
 #endif
 
 #if FOLLY_HAVE_LIBLZMA
-  LZMA2Codec::create,
-  LZMA2Codec::create,
+    LZMA2Codec::create,
+    LZMA2Codec::create,
 #else
-  nullptr,
-  nullptr,
+    nullptr,
+    nullptr,
 #endif
-};
-
-}  // namespace
+  };
 
-std::unique_ptr<Codec> getCodec(CodecType type, int level) {
   size_t idx = static_cast<size_t>(type);
   if (idx >= static_cast<size_t>(CodecType::NUM_CODEC_TYPES)) {
     throw std::invalid_argument(to<std::string>(
         "Compression type ", idx, " not supported"));
   }
-  auto factory = gCodecFactories[idx];
+  auto factory = codecFactories[idx];
   if (!factory) {
     throw std::invalid_argument(to<std::string>(
         "Compression type ", idx, " not supported"));
@@ -963,4 +978,3 @@ std::unique_ptr<Codec> getCodec(CodecType type, int level) {
 }
 
 }}  // namespaces
-