// Copyright 2011 Google Inc. All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Various stubs for the open-source version of Snappy. #ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_ #define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_ #if HAVE_CONFIG_H #include "config.h" #endif #include <stdint.h> #include <cassert> #include <cstdlib> #include <cstring> #include <limits> #include <string> #if HAVE_SYS_MMAN_H #include <sys/mman.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if defined(_MSC_VER) #include <intrin.h> #endif // defined(_MSC_VER) #ifndef __has_feature #define __has_feature … #endif #if __has_feature(memory_sanitizer) #include <sanitizer/msan_interface.h> #define SNAPPY_ANNOTATE_MEMORY_IS_INITIALIZED … #else #define SNAPPY_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) … #endif // __has_feature(memory_sanitizer) #include "snappy-stubs-public.h" // Used to enable 64-bit optimized versions of some routines. #if defined(__PPC64__) || defined(__powerpc64__) #define ARCH_PPC … #elif defined(__aarch64__) || defined(_M_ARM64) #define ARCH_ARM … #endif // Needed by OS X, among others. #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS … #endif // The size of an array, if known at compile-time. // Will give unexpected results if used on a pointer. // We undefine it first, since some compilers already have a definition. #ifdef ARRAYSIZE #undef ARRAYSIZE #endif #define ARRAYSIZE(a) … // Static prediction hints. #if HAVE_BUILTIN_EXPECT #define SNAPPY_PREDICT_FALSE(x) … #define SNAPPY_PREDICT_TRUE(x) … #else #define SNAPPY_PREDICT_FALSE … #define SNAPPY_PREDICT_TRUE … #endif // HAVE_BUILTIN_EXPECT // Inlining hints. #if HAVE_ATTRIBUTE_ALWAYS_INLINE #define SNAPPY_ATTRIBUTE_ALWAYS_INLINE … #else #define SNAPPY_ATTRIBUTE_ALWAYS_INLINE #endif // HAVE_ATTRIBUTE_ALWAYS_INLINE #if HAVE_BUILTIN_PREFETCH #define SNAPPY_PREFETCH … #else #define SNAPPY_PREFETCH(ptr) … #endif // Stubbed version of ABSL_FLAG. // // In the open source version, flags can only be changed at compile time. #define SNAPPY_FLAG(flag_type, flag_name, default_value, help) … namespace snappy { // Stubbed version of absl::GetFlag(). template <typename T> inline T GetFlag(T flag) { … } static const uint32_t kuint32max = …; static const int64_t kint64max = …; // Potentially unaligned loads and stores. inline uint16_t UNALIGNED_LOAD16(const void *p) { … } inline uint32_t UNALIGNED_LOAD32(const void *p) { … } inline uint64_t UNALIGNED_LOAD64(const void *p) { … } inline void UNALIGNED_STORE16(void *p, uint16_t v) { … } inline void UNALIGNED_STORE32(void *p, uint32_t v) { … } inline void UNALIGNED_STORE64(void *p, uint64_t v) { … } // Convert to little-endian storage, opposite of network format. // Convert x from host to little endian: x = LittleEndian.FromHost(x); // convert x from little endian to host: x = LittleEndian.ToHost(x); // // Store values into unaligned memory converting to little endian order: // LittleEndian.Store16(p, x); // // Load unaligned values stored in little endian converting to host order: // x = LittleEndian.Load16(p); class LittleEndian { … }; // Some bit-manipulation functions. class Bits { … }; #if HAVE_BUILTIN_CTZ inline int Bits::Log2FloorNonZero(uint32_t n) { … } inline int Bits::Log2Floor(uint32_t n) { … } inline int Bits::FindLSBSetNonZero(uint32_t n) { … } #elif defined(_MSC_VER) inline int Bits::Log2FloorNonZero(uint32_t n) { assert(n != 0); // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long. unsigned long where; _BitScanReverse(&where, n); return static_cast<int>(where); } inline int Bits::Log2Floor(uint32_t n) { // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long. unsigned long where; if (_BitScanReverse(&where, n)) return static_cast<int>(where); return -1; } inline int Bits::FindLSBSetNonZero(uint32_t n) { assert(n != 0); // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long. unsigned long where; if (_BitScanForward(&where, n)) return static_cast<int>(where); return 32; } #else // Portable versions. inline int Bits::Log2FloorNonZero(uint32_t n) { assert(n != 0); int log = 0; uint32_t value = n; for (int i = 4; i >= 0; --i) { int shift = (1 << i); uint32_t x = value >> shift; if (x != 0) { value = x; log += shift; } } assert(value == 1); return log; } inline int Bits::Log2Floor(uint32_t n) { return (n == 0) ? -1 : Bits::Log2FloorNonZero(n); } inline int Bits::FindLSBSetNonZero(uint32_t n) { assert(n != 0); int rc = 31; for (int i = 4, shift = 1 << 4; i >= 0; --i) { const uint32_t x = n << shift; if (x != 0) { n = x; rc -= shift; } shift >>= 1; } return rc; } #endif // End portable versions. #if HAVE_BUILTIN_CTZ inline int Bits::FindLSBSetNonZero64(uint64_t n) { … } #elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) // _BitScanForward64() is only available on x64 and ARM64. inline int Bits::FindLSBSetNonZero64(uint64_t n) { assert(n != 0); // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long. unsigned long where; if (_BitScanForward64(&where, n)) return static_cast<int>(where); return 64; } #else // Portable version. // FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero(). inline int Bits::FindLSBSetNonZero64(uint64_t n) { assert(n != 0); const uint32_t bottombits = static_cast<uint32_t>(n); if (bottombits == 0) { // Bottom bits are zero, so scan the top bits. return 32 + FindLSBSetNonZero(static_cast<uint32_t>(n >> 32)); } else { return FindLSBSetNonZero(bottombits); } } #endif // HAVE_BUILTIN_CTZ // Variable-length integer encoding. class Varint { … }; inline const char* Varint::Parse32WithLimit(const char* p, const char* l, uint32_t* OUTPUT) { … } inline char* Varint::Encode32(char* sptr, uint32_t v) { … } // If you know the internal layout of the std::string in use, you can // replace this function with one that resizes the string without // filling the new space with zeros (if applicable) -- // it will be non-portable but faster. inline void STLStringResizeUninitialized(std::string* s, size_t new_size) { … } // Return a mutable char* pointing to a string's internal buffer, // which may not be null-terminated. Writing through this pointer will // modify the string. // // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the // next call to a string method that invalidates iterators. // // As of 2006-04, there is no standard-blessed way of getting a // mutable reference to a string's internal buffer. However, issue 530 // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530) // proposes this as the method. It will officially be part of the standard // for C++0x. This should already work on all current implementations. inline char* string_as_array(std::string* str) { … } } // namespace snappy #endif // THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_