github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/include/snappy-stubs-internal.h (about)

     1  // Copyright 2011 Google Inc. All Rights Reserved.
     2  //
     3  // Redistribution and use in source and binary forms, with or without
     4  // modification, are permitted provided that the following conditions are
     5  // met:
     6  //
     7  //     * Redistributions of source code must retain the above copyright
     8  // notice, this list of conditions and the following disclaimer.
     9  //     * Redistributions in binary form must reproduce the above
    10  // copyright notice, this list of conditions and the following disclaimer
    11  // in the documentation and/or other materials provided with the
    12  // distribution.
    13  //     * Neither the name of Google Inc. nor the names of its
    14  // contributors may be used to endorse or promote products derived from
    15  // this software without specific prior written permission.
    16  //
    17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    28  //
    29  // Various stubs for the open-source version of Snappy.
    30  
    31  #ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
    32  #define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
    33  
    34  #ifdef HAVE_CONFIG_H
    35  #include "config.h"
    36  #endif
    37  
    38  #include <string>
    39  
    40  #include <assert.h>
    41  #include <stdlib.h>
    42  #include <string.h>
    43  
    44  #ifdef HAVE_SYS_MMAN_H
    45  #include <sys/mman.h>
    46  #endif
    47  
    48  #include "snappy-stubs-public.h"
    49  
    50  #if defined(__x86_64__)
    51  
    52  // Enable 64-bit optimized versions of some routines.
    53  #define ARCH_K8 1
    54  
    55  #endif
    56  
    57  // Needed by OS X, among others.
    58  #ifndef MAP_ANONYMOUS
    59  #define MAP_ANONYMOUS MAP_ANON
    60  #endif
    61  
    62  // Pull in std::min, std::ostream, and the likes. This is safe because this
    63  // header file is never used from any public header files.
    64  using namespace std;
    65  
    66  // The size of an array, if known at compile-time.
    67  // Will give unexpected results if used on a pointer.
    68  // We undefine it first, since some compilers already have a definition.
    69  #ifdef ARRAYSIZE
    70  #undef ARRAYSIZE
    71  #endif
    72  #define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
    73  
    74  // Static prediction hints.
    75  #ifdef HAVE_BUILTIN_EXPECT
    76  #define PREDICT_FALSE(x) (__builtin_expect(x, 0))
    77  #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
    78  #else
    79  #define PREDICT_FALSE(x) x
    80  #define PREDICT_TRUE(x) x
    81  #endif
    82  
    83  // This is only used for recomputing the tag byte table used during
    84  // decompression; for simplicity we just remove it from the open-source
    85  // version (anyone who wants to regenerate it can just do the call
    86  // themselves within main()).
    87  #define DEFINE_bool(flag_name, default_value, description) \
    88    bool FLAGS_ ## flag_name = default_value
    89  #define DECLARE_bool(flag_name) \
    90    extern bool FLAGS_ ## flag_name
    91  
    92  namespace snappy {
    93  
    94  static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
    95  static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
    96  
    97  // Potentially unaligned loads and stores.
    98  
    99  // x86 and PowerPC can simply do these loads and stores native.
   100  
   101  #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
   102  
   103  #define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
   104  #define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
   105  #define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
   106  
   107  #define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
   108  #define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
   109  #define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
   110  
   111  // ARMv7 and newer support native unaligned accesses, but only of 16-bit
   112  // and 32-bit values (not 64-bit); older versions either raise a fatal signal,
   113  // do an unaligned read and rotate the words around a bit, or do the reads very
   114  // slowly (trip through kernel mode). There's no simple #define that says just
   115  // “ARMv7 or higher”, so we have to filter away all ARMv5 and ARMv6
   116  // sub-architectures.
   117  //
   118  // This is a mess, but there's not much we can do about it.
   119  
   120  #elif defined(__arm__) && \
   121        !defined(__ARM_ARCH_4__) && \
   122        !defined(__ARM_ARCH_4T__) && \
   123        !defined(__ARM_ARCH_5__) && \
   124        !defined(__ARM_ARCH_5T__) && \
   125        !defined(__ARM_ARCH_5TE__) && \
   126        !defined(__ARM_ARCH_5TEJ__) && \
   127        !defined(__ARM_ARCH_6__) && \
   128        !defined(__ARM_ARCH_6J__) && \
   129        !defined(__ARM_ARCH_6K__) && \
   130        !defined(__ARM_ARCH_6Z__) && \
   131        !defined(__ARM_ARCH_6ZK__) && \
   132        !defined(__ARM_ARCH_6T2__)
   133  
   134  #define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
   135  #define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
   136  
   137  #define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
   138  #define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
   139  
   140  // TODO(user): NEON supports unaligned 64-bit loads and stores.
   141  // See if that would be more efficient on platforms supporting it,
   142  // at least for copies.
   143  
   144  inline uint64 UNALIGNED_LOAD64(const void *p) {
   145    uint64 t;
   146    memcpy(&t, p, sizeof t);
   147    return t;
   148  }
   149  
   150  inline void UNALIGNED_STORE64(void *p, uint64 v) {
   151    memcpy(p, &v, sizeof v);
   152  }
   153  
   154  #else
   155  
   156  // These functions are provided for architectures that don't support
   157  // unaligned loads and stores.
   158  
   159  inline uint16 UNALIGNED_LOAD16(const void *p) {
   160    uint16 t;
   161    memcpy(&t, p, sizeof t);
   162    return t;
   163  }
   164  
   165  inline uint32 UNALIGNED_LOAD32(const void *p) {
   166    uint32 t;
   167    memcpy(&t, p, sizeof t);
   168    return t;
   169  }
   170  
   171  inline uint64 UNALIGNED_LOAD64(const void *p) {
   172    uint64 t;
   173    memcpy(&t, p, sizeof t);
   174    return t;
   175  }
   176  
   177  inline void UNALIGNED_STORE16(void *p, uint16 v) {
   178    memcpy(p, &v, sizeof v);
   179  }
   180  
   181  inline void UNALIGNED_STORE32(void *p, uint32 v) {
   182    memcpy(p, &v, sizeof v);
   183  }
   184  
   185  inline void UNALIGNED_STORE64(void *p, uint64 v) {
   186    memcpy(p, &v, sizeof v);
   187  }
   188  
   189  #endif
   190  
   191  // This can be more efficient than UNALIGNED_LOAD64 + UNALIGNED_STORE64
   192  // on some platforms, in particular ARM.
   193  inline void UnalignedCopy64(const void *src, void *dst) {
   194    if (sizeof(void *) == 8) {
   195      UNALIGNED_STORE64(dst, UNALIGNED_LOAD64(src));
   196    } else {
   197      const char *src_char = reinterpret_cast<const char *>(src);
   198      char *dst_char = reinterpret_cast<char *>(dst);
   199  
   200      UNALIGNED_STORE32(dst_char, UNALIGNED_LOAD32(src_char));
   201      UNALIGNED_STORE32(dst_char + 4, UNALIGNED_LOAD32(src_char + 4));
   202    }
   203  }
   204  
   205  // The following guarantees declaration of the byte swap functions.
   206  #ifdef WORDS_BIGENDIAN
   207  
   208  #ifdef HAVE_SYS_BYTEORDER_H
   209  #include <sys/byteorder.h>
   210  #endif
   211  
   212  #ifdef HAVE_SYS_ENDIAN_H
   213  #include <sys/endian.h>
   214  #endif
   215  
   216  #ifdef _MSC_VER
   217  #include <stdlib.h>
   218  #define bswap_16(x) _byteswap_ushort(x)
   219  #define bswap_32(x) _byteswap_ulong(x)
   220  #define bswap_64(x) _byteswap_uint64(x)
   221  
   222  #elif defined(__APPLE__)
   223  // Mac OS X / Darwin features
   224  #include <libkern/OSByteOrder.h>
   225  #define bswap_16(x) OSSwapInt16(x)
   226  #define bswap_32(x) OSSwapInt32(x)
   227  #define bswap_64(x) OSSwapInt64(x)
   228  
   229  #elif defined(HAVE_BYTESWAP_H)
   230  #include <byteswap.h>
   231  
   232  #elif defined(bswap32)
   233  // FreeBSD defines bswap{16,32,64} in <sys/endian.h> (already #included).
   234  #define bswap_16(x) bswap16(x)
   235  #define bswap_32(x) bswap32(x)
   236  #define bswap_64(x) bswap64(x)
   237  
   238  #elif defined(BSWAP_64)
   239  // Solaris 10 defines BSWAP_{16,32,64} in <sys/byteorder.h> (already #included).
   240  #define bswap_16(x) BSWAP_16(x)
   241  #define bswap_32(x) BSWAP_32(x)
   242  #define bswap_64(x) BSWAP_64(x)
   243  
   244  #else
   245  
   246  inline uint16 bswap_16(uint16 x) {
   247    return (x << 8) | (x >> 8);
   248  }
   249  
   250  inline uint32 bswap_32(uint32 x) {
   251    x = ((x & 0xff00ff00UL) >> 8) | ((x & 0x00ff00ffUL) << 8);
   252    return (x >> 16) | (x << 16);
   253  }
   254  
   255  inline uint64 bswap_64(uint64 x) {
   256    x = ((x & 0xff00ff00ff00ff00ULL) >> 8) | ((x & 0x00ff00ff00ff00ffULL) << 8);
   257    x = ((x & 0xffff0000ffff0000ULL) >> 16) | ((x & 0x0000ffff0000ffffULL) << 16);
   258    return (x >> 32) | (x << 32);
   259  }
   260  
   261  #endif
   262  
   263  #endif  // WORDS_BIGENDIAN
   264  
   265  // Convert to little-endian storage, opposite of network format.
   266  // Convert x from host to little endian: x = LittleEndian.FromHost(x);
   267  // convert x from little endian to host: x = LittleEndian.ToHost(x);
   268  //
   269  //  Store values into unaligned memory converting to little endian order:
   270  //    LittleEndian.Store16(p, x);
   271  //
   272  //  Load unaligned values stored in little endian converting to host order:
   273  //    x = LittleEndian.Load16(p);
   274  class LittleEndian {
   275   public:
   276    // Conversion functions.
   277  #ifdef WORDS_BIGENDIAN
   278  
   279    static uint16 FromHost16(uint16 x) { return bswap_16(x); }
   280    static uint16 ToHost16(uint16 x) { return bswap_16(x); }
   281  
   282    static uint32 FromHost32(uint32 x) { return bswap_32(x); }
   283    static uint32 ToHost32(uint32 x) { return bswap_32(x); }
   284  
   285    static bool IsLittleEndian() { return false; }
   286  
   287  #else  // !defined(WORDS_BIGENDIAN)
   288  
   289    static uint16 FromHost16(uint16 x) { return x; }
   290    static uint16 ToHost16(uint16 x) { return x; }
   291  
   292    static uint32 FromHost32(uint32 x) { return x; }
   293    static uint32 ToHost32(uint32 x) { return x; }
   294  
   295    static bool IsLittleEndian() { return true; }
   296  
   297  #endif  // !defined(WORDS_BIGENDIAN)
   298  
   299    // Functions to do unaligned loads and stores in little-endian order.
   300    static uint16 Load16(const void *p) {
   301      return ToHost16(UNALIGNED_LOAD16(p));
   302    }
   303  
   304    static void Store16(void *p, uint16 v) {
   305      UNALIGNED_STORE16(p, FromHost16(v));
   306    }
   307  
   308    static uint32 Load32(const void *p) {
   309      return ToHost32(UNALIGNED_LOAD32(p));
   310    }
   311  
   312    static void Store32(void *p, uint32 v) {
   313      UNALIGNED_STORE32(p, FromHost32(v));
   314    }
   315  };
   316  
   317  // Some bit-manipulation functions.
   318  class Bits {
   319   public:
   320    // Return floor(log2(n)) for positive integer n.  Returns -1 iff n == 0.
   321    static int Log2Floor(uint32 n);
   322  
   323    // Return the first set least / most significant bit, 0-indexed.  Returns an
   324    // undefined value if n == 0.  FindLSBSetNonZero() is similar to ffs() except
   325    // that it's 0-indexed.
   326    static int FindLSBSetNonZero(uint32 n);
   327    static int FindLSBSetNonZero64(uint64 n);
   328  
   329   private:
   330    DISALLOW_COPY_AND_ASSIGN(Bits);
   331  };
   332  
   333  #ifdef HAVE_BUILTIN_CTZ
   334  
   335  inline int Bits::Log2Floor(uint32 n) {
   336    return n == 0 ? -1 : 31 ^ __builtin_clz(n);
   337  }
   338  
   339  inline int Bits::FindLSBSetNonZero(uint32 n) {
   340    return __builtin_ctz(n);
   341  }
   342  
   343  inline int Bits::FindLSBSetNonZero64(uint64 n) {
   344    return __builtin_ctzll(n);
   345  }
   346  
   347  #else  // Portable versions.
   348  
   349  inline int Bits::Log2Floor(uint32 n) {
   350    if (n == 0)
   351      return -1;
   352    int log = 0;
   353    uint32 value = n;
   354    for (int i = 4; i >= 0; --i) {
   355      int shift = (1 << i);
   356      uint32 x = value >> shift;
   357      if (x != 0) {
   358        value = x;
   359        log += shift;
   360      }
   361    }
   362    assert(value == 1);
   363    return log;
   364  }
   365  
   366  inline int Bits::FindLSBSetNonZero(uint32 n) {
   367    int rc = 31;
   368    for (int i = 4, shift = 1 << 4; i >= 0; --i) {
   369      const uint32 x = n << shift;
   370      if (x != 0) {
   371        n = x;
   372        rc -= shift;
   373      }
   374      shift >>= 1;
   375    }
   376    return rc;
   377  }
   378  
   379  // FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
   380  inline int Bits::FindLSBSetNonZero64(uint64 n) {
   381    const uint32 bottombits = static_cast<uint32>(n);
   382    if (bottombits == 0) {
   383      // Bottom bits are zero, so scan in top bits
   384      return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
   385    } else {
   386      return FindLSBSetNonZero(bottombits);
   387    }
   388  }
   389  
   390  #endif  // End portable versions.
   391  
   392  // Variable-length integer encoding.
   393  class Varint {
   394   public:
   395    // Maximum lengths of varint encoding of uint32.
   396    static const int kMax32 = 5;
   397  
   398    // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
   399    // Never reads a character at or beyond limit.  If a valid/terminated varint32
   400    // was found in the range, stores it in *OUTPUT and returns a pointer just
   401    // past the last byte of the varint32. Else returns NULL.  On success,
   402    // "result <= limit".
   403    static const char* Parse32WithLimit(const char* ptr, const char* limit,
   404                                        uint32* OUTPUT);
   405  
   406    // REQUIRES   "ptr" points to a buffer of length sufficient to hold "v".
   407    // EFFECTS    Encodes "v" into "ptr" and returns a pointer to the
   408    //            byte just past the last encoded byte.
   409    static char* Encode32(char* ptr, uint32 v);
   410  
   411    // EFFECTS    Appends the varint representation of "value" to "*s".
   412    static void Append32(string* s, uint32 value);
   413  };
   414  
   415  inline const char* Varint::Parse32WithLimit(const char* p,
   416                                              const char* l,
   417                                              uint32* OUTPUT) {
   418    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
   419    const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
   420    uint32 b, result;
   421    if (ptr >= limit) return NULL;
   422    b = *(ptr++); result = b & 127;          if (b < 128) goto done;
   423    if (ptr >= limit) return NULL;
   424    b = *(ptr++); result |= (b & 127) <<  7; if (b < 128) goto done;
   425    if (ptr >= limit) return NULL;
   426    b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
   427    if (ptr >= limit) return NULL;
   428    b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
   429    if (ptr >= limit) return NULL;
   430    b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
   431    return NULL;       // Value is too long to be a varint32
   432   done:
   433    *OUTPUT = result;
   434    return reinterpret_cast<const char*>(ptr);
   435  }
   436  
   437  inline char* Varint::Encode32(char* sptr, uint32 v) {
   438    // Operate on characters as unsigneds
   439    unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
   440    static const int B = 128;
   441    if (v < (1<<7)) {
   442      *(ptr++) = v;
   443    } else if (v < (1<<14)) {
   444      *(ptr++) = v | B;
   445      *(ptr++) = v>>7;
   446    } else if (v < (1<<21)) {
   447      *(ptr++) = v | B;
   448      *(ptr++) = (v>>7) | B;
   449      *(ptr++) = v>>14;
   450    } else if (v < (1<<28)) {
   451      *(ptr++) = v | B;
   452      *(ptr++) = (v>>7) | B;
   453      *(ptr++) = (v>>14) | B;
   454      *(ptr++) = v>>21;
   455    } else {
   456      *(ptr++) = v | B;
   457      *(ptr++) = (v>>7) | B;
   458      *(ptr++) = (v>>14) | B;
   459      *(ptr++) = (v>>21) | B;
   460      *(ptr++) = v>>28;
   461    }
   462    return reinterpret_cast<char*>(ptr);
   463  }
   464  
   465  // If you know the internal layout of the std::string in use, you can
   466  // replace this function with one that resizes the string without
   467  // filling the new space with zeros (if applicable) --
   468  // it will be non-portable but faster.
   469  inline void STLStringResizeUninitialized(string* s, size_t new_size) {
   470    s->resize(new_size);
   471  }
   472  
   473  // Return a mutable char* pointing to a string's internal buffer,
   474  // which may not be null-terminated. Writing through this pointer will
   475  // modify the string.
   476  //
   477  // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
   478  // next call to a string method that invalidates iterators.
   479  //
   480  // As of 2006-04, there is no standard-blessed way of getting a
   481  // mutable reference to a string's internal buffer. However, issue 530
   482  // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)
   483  // proposes this as the method. It will officially be part of the standard
   484  // for C++0x. This should already work on all current implementations.
   485  inline char* string_as_array(string* str) {
   486    return str->empty() ? NULL : &*str->begin();
   487  }
   488  
   489  }  // namespace snappy
   490  
   491  #endif  // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_