folly/folly/GroupVarint.h

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>
#include <limits>

#include <glog/logging.h>

#include <folly/Portability.h>
#include <folly/Range.h>
#include <folly/detail/GroupVarintDetail.h>
#include <folly/lang/Bits.h>
#include <folly/portability/Builtins.h>

#if !defined(__GNUC__) && !defined(_MSC_VER)
#error GroupVarint.h requires GCC or MSVC
#endif

#if FOLLY_X64 || defined(__i386__) || FOLLY_PPC64 || FOLLY_AARCH64 || \
    FOLLY_RISCV64
#define FOLLY_HAVE_GROUP_VARINT
#else
#define FOLLY_HAVE_GROUP_VARINT
#endif

#if FOLLY_HAVE_GROUP_VARINT

#if FOLLY_SSE >= 4
#include <nmmintrin.h>
namespace folly {
namespace detail {
extern const std::array<std::array<std::uint32_t, 4>, 256> groupVarintSSEMasks;
} // namespace detail
} // namespace folly
#endif

namespace folly {
namespace detail {
extern const std::array<std::uint8_t, 256> groupVarintLengths;
} // namespace detail
} // namespace folly

namespace folly {

template <typename T>
class GroupVarint;

/**
 * GroupVarint encoding for 32-bit values.
 *
 * Encodes 4 32-bit integers at once, each using 1-4 bytes depending on size.
 * There is one byte of overhead.  (The first byte contains the lengths of
 * the four integers encoded as two bits each; 00=1 byte .. 11=4 bytes)
 *
 * This implementation assumes little-endian and does unaligned 32-bit
 * accesses, so it's basically not portable outside of the x86[_64] world.
 */
template <>
class GroupVarint<uint32_t> : public detail::GroupVarintBase<uint32_t> {};

/**
 * GroupVarint encoding for 64-bit values.
 *
 * Encodes 5 64-bit integers at once, each using 1-8 bytes depending on size.
 * There are two bytes of overhead.  (The first two bytes contain the lengths
 * of the five integers encoded as three bits each; 000=1 byte .. 111 = 8 bytes)
 *
 * This implementation assumes little-endian and does unaligned 64-bit
 * accesses, so it's basically not portable outside of the x86[_64] world.
 */
template <>
class GroupVarint<uint64_t> : public detail::GroupVarintBase<uint64_t> {};

GroupVarint32;
GroupVarint64;

/**
 * Simplify use of GroupVarint* for the case where data is available one
 * entry at a time (instead of one group at a time).  Handles buffering
 * and an incomplete last chunk.
 *
 * Output is a function object that accepts character ranges:
 * out(StringPiece) appends the given character range to the output.
 */
template <class T, class Output>
class GroupVarintEncoder {};

/**
 * Simplify use of GroupVarint* for the case where the last group in the
 * input may be incomplete (but the exact size of the input is known).
 * Allows for extracting values one at a time.
 */
template <typename T>
class GroupVarintDecoder {};

GroupVarint32Decoder;
GroupVarint64Decoder;

} // namespace folly

#endif // FOLLY_HAVE_GROUP_VARINT