LCOV - code coverage report
Current view: directory - other-licenses/snappy/src - snappy-stubs-internal.h (source / functions) Found Hit Coverage
Test: app.info Lines: 86 46 53.5 %
Date: 2012-06-02 Functions: 18 9 50.0 %

       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 <iostream>
      39                 : #include <string>
      40                 : 
      41                 : #include <assert.h>
      42                 : #include <stdlib.h>
      43                 : #include <string.h>
      44                 : 
      45                 : #ifdef HAVE_SYS_MMAN_H
      46                 : #include <sys/mman.h>
      47                 : #endif
      48                 : 
      49                 : #include "snappy-stubs-public.h"
      50                 : 
      51                 : #if defined(__x86_64__)
      52                 : 
      53                 : // Enable 64-bit optimized versions of some routines.
      54                 : #define ARCH_K8 1
      55                 : 
      56                 : #endif
      57                 : 
      58                 : // Needed by OS X, among others.
      59                 : #ifndef MAP_ANONYMOUS
      60                 : #define MAP_ANONYMOUS MAP_ANON
      61                 : #endif
      62                 : 
      63                 : // Pull in std::min, std::ostream, and the likes. This is safe because this
      64                 : // header file is never used from any public header files.
      65                 : using namespace std;
      66                 : 
      67                 : // The size of an array, if known at compile-time.
      68                 : // Will give unexpected results if used on a pointer.
      69                 : // We undefine it first, since some compilers already have a definition.
      70                 : #ifdef ARRAYSIZE
      71                 : #undef ARRAYSIZE
      72                 : #endif
      73                 : #define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
      74                 : 
      75                 : // Static prediction hints.
      76                 : #ifdef HAVE_BUILTIN_EXPECT
      77                 : #define PREDICT_FALSE(x) (__builtin_expect(x, 0))
      78                 : #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
      79                 : #else
      80                 : #define PREDICT_FALSE(x) x
      81                 : #define PREDICT_TRUE(x) x
      82                 : #endif
      83                 : 
      84                 : // This is only used for recomputing the tag byte table used during
      85                 : // decompression; for simplicity we just remove it from the open-source
      86                 : // version (anyone who wants to regenerate it can just do the call
      87                 : // themselves within main()).
      88                 : #define DEFINE_bool(flag_name, default_value, description) \
      89                 :   bool FLAGS_ ## flag_name = default_value
      90                 : #define DECLARE_bool(flag_name) \
      91                 :   extern bool FLAGS_ ## flag_name
      92                 : 
      93                 : namespace snappy {
      94                 : 
      95                 : static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
      96                 : static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
      97                 : 
      98                 : // Logging.
      99                 : 
     100                 : #define LOG(level) LogMessage()
     101                 : #define VLOG(level) true ? (void)0 : \
     102                 :     snappy::LogMessageVoidify() & snappy::LogMessage()
     103                 : 
     104                 : class LogMessage {
     105                 :  public:
     106               0 :   LogMessage() { }
     107                 :   ~LogMessage() {
     108                 :     cerr << endl;
     109                 :   }
     110                 : 
     111               0 :   LogMessage& operator<<(const std::string& msg) {
     112               0 :     cerr << msg;
     113               0 :     return *this;
     114                 :   }
     115               0 :   LogMessage& operator<<(int x) {
     116               0 :     cerr << x;
     117               0 :     return *this;
     118                 :   }
     119                 : };
     120                 : 
     121                 : // Asserts, both versions activated in debug mode only,
     122                 : // and ones that are always active.
     123                 : 
     124                 : #define CRASH_UNLESS(condition) \
     125                 :     PREDICT_TRUE(condition) ? (void)0 : \
     126                 :     snappy::LogMessageVoidify() & snappy::LogMessageCrash()
     127                 : 
     128                 : class LogMessageCrash : public LogMessage {
     129                 :  public:
     130               0 :   LogMessageCrash() { }
     131               0 :   ~LogMessageCrash() {
     132               0 :     cerr << endl;
     133               0 :     abort();
     134                 :   }
     135                 : };
     136                 : 
     137                 : // This class is used to explicitly ignore values in the conditional
     138                 : // logging macros.  This avoids compiler warnings like "value computed
     139                 : // is not used" and "statement has no effect".
     140                 : 
     141                 : class LogMessageVoidify {
     142                 :  public:
     143               0 :   LogMessageVoidify() { }
     144                 :   // This has to be an operator with a precedence lower than << but
     145                 :   // higher than ?:
     146               0 :   void operator&(const LogMessage&) { }
     147                 : };
     148                 : 
     149                 : #define CHECK(cond) CRASH_UNLESS(cond)
     150                 : #define CHECK_LE(a, b) CRASH_UNLESS((a) <= (b))
     151                 : #define CHECK_GE(a, b) CRASH_UNLESS((a) >= (b))
     152                 : #define CHECK_EQ(a, b) CRASH_UNLESS((a) == (b))
     153                 : #define CHECK_NE(a, b) CRASH_UNLESS((a) != (b))
     154                 : #define CHECK_LT(a, b) CRASH_UNLESS((a) < (b))
     155                 : #define CHECK_GT(a, b) CRASH_UNLESS((a) > (b))
     156                 : 
     157                 : #ifdef NDEBUG
     158                 : 
     159                 : #define DCHECK(cond) CRASH_UNLESS(true)
     160                 : #define DCHECK_LE(a, b) CRASH_UNLESS(true)
     161                 : #define DCHECK_GE(a, b) CRASH_UNLESS(true)
     162                 : #define DCHECK_EQ(a, b) CRASH_UNLESS(true)
     163                 : #define DCHECK_NE(a, b) CRASH_UNLESS(true)
     164                 : #define DCHECK_LT(a, b) CRASH_UNLESS(true)
     165                 : #define DCHECK_GT(a, b) CRASH_UNLESS(true)
     166                 : 
     167                 : #else
     168                 : 
     169                 : #define DCHECK(cond) CHECK(cond)
     170                 : #define DCHECK_LE(a, b) CHECK_LE(a, b)
     171                 : #define DCHECK_GE(a, b) CHECK_GE(a, b)
     172                 : #define DCHECK_EQ(a, b) CHECK_EQ(a, b)
     173                 : #define DCHECK_NE(a, b) CHECK_NE(a, b)
     174                 : #define DCHECK_LT(a, b) CHECK_LT(a, b)
     175                 : #define DCHECK_GT(a, b) CHECK_GT(a, b)
     176                 : 
     177                 : #endif
     178                 : 
     179                 : // Potentially unaligned loads and stores.
     180                 : 
     181                 : #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
     182                 : 
     183                 : #define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
     184                 : #define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
     185                 : #define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
     186                 : 
     187                 : #define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
     188                 : #define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
     189                 : #define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
     190                 : 
     191                 : #else
     192                 : 
     193                 : // These functions are provided for architectures that don't support
     194                 : // unaligned loads and stores.
     195                 : 
     196                 : inline uint16 UNALIGNED_LOAD16(const void *p) {
     197                 :   uint16 t;
     198                 :   memcpy(&t, p, sizeof t);
     199                 :   return t;
     200                 : }
     201                 : 
     202                 : inline uint32 UNALIGNED_LOAD32(const void *p) {
     203                 :   uint32 t;
     204                 :   memcpy(&t, p, sizeof t);
     205                 :   return t;
     206                 : }
     207                 : 
     208                 : inline uint64 UNALIGNED_LOAD64(const void *p) {
     209                 :   uint64 t;
     210                 :   memcpy(&t, p, sizeof t);
     211                 :   return t;
     212                 : }
     213                 : 
     214                 : inline void UNALIGNED_STORE16(void *p, uint16 v) {
     215                 :   memcpy(p, &v, sizeof v);
     216                 : }
     217                 : 
     218                 : inline void UNALIGNED_STORE32(void *p, uint32 v) {
     219                 :   memcpy(p, &v, sizeof v);
     220                 : }
     221                 : 
     222                 : inline void UNALIGNED_STORE64(void *p, uint64 v) {
     223                 :   memcpy(p, &v, sizeof v);
     224                 : }
     225                 : 
     226                 : #endif
     227                 : 
     228                 : // The following guarantees declaration of the byte swap functions.
     229                 : #ifdef WORDS_BIGENDIAN
     230                 : 
     231                 : #ifdef HAVE_SYS_BYTEORDER_H
     232                 : #include <sys/byteorder.h>
     233                 : #endif
     234                 : 
     235                 : #ifdef HAVE_SYS_ENDIAN_H
     236                 : #include <sys/endian.h>
     237                 : #endif
     238                 : 
     239                 : #ifdef _MSC_VER
     240                 : #include <stdlib.h>
     241                 : #define bswap_16(x) _byteswap_ushort(x)
     242                 : #define bswap_32(x) _byteswap_ulong(x)
     243                 : #define bswap_64(x) _byteswap_uint64(x)
     244                 : 
     245                 : #elif defined(__APPLE__)
     246                 : // Mac OS X / Darwin features
     247                 : #include <libkern/OSByteOrder.h>
     248                 : #define bswap_16(x) OSSwapInt16(x)
     249                 : #define bswap_32(x) OSSwapInt32(x)
     250                 : #define bswap_64(x) OSSwapInt64(x)
     251                 : 
     252                 : #elif defined(HAVE_BYTESWAP_H)
     253                 : #include <byteswap.h>
     254                 : 
     255                 : #elif defined(bswap32)
     256                 : // FreeBSD defines bswap{16,32,64} in <sys/endian.h> (already #included).
     257                 : #define bswap_16(x) bswap16(x)
     258                 : #define bswap_32(x) bswap32(x)
     259                 : #define bswap_64(x) bswap64(x)
     260                 : 
     261                 : #elif defined(BSWAP_64)
     262                 : // Solaris 10 defines BSWAP_{16,32,64} in <sys/byteorder.h> (already #included).
     263                 : #define bswap_16(x) BSWAP_16(x)
     264                 : #define bswap_32(x) BSWAP_32(x)
     265                 : #define bswap_64(x) BSWAP_64(x)
     266                 : 
     267                 : #else
     268                 : 
     269                 : inline uint16 bswap_16(uint16 x) {
     270                 :   return (x << 8) | (x >> 8);
     271                 : }
     272                 : 
     273                 : inline uint32 bswap_32(uint32 x) {
     274                 :   x = ((x & 0xff00ff00UL) >> 8) | ((x & 0x00ff00ffUL) << 8);
     275                 :   return (x >> 16) | (x << 16);
     276                 : }
     277                 : 
     278                 : inline uint64 bswap_64(uint64 x) {
     279                 :   x = ((x & 0xff00ff00ff00ff00ULL) >> 8) | ((x & 0x00ff00ff00ff00ffULL) << 8);
     280                 :   x = ((x & 0xffff0000ffff0000ULL) >> 16) | ((x & 0x0000ffff0000ffffULL) << 16);
     281                 :   return (x >> 32) | (x << 32);
     282                 : }
     283                 : 
     284                 : #endif
     285                 : 
     286                 : #endif  // WORDS_BIGENDIAN
     287                 : 
     288                 : // Convert to little-endian storage, opposite of network format.
     289                 : // Convert x from host to little endian: x = LittleEndian.FromHost(x);
     290                 : // convert x from little endian to host: x = LittleEndian.ToHost(x);
     291                 : //
     292                 : //  Store values into unaligned memory converting to little endian order:
     293                 : //    LittleEndian.Store16(p, x);
     294                 : //
     295                 : //  Load unaligned values stored in little endian converting to host order:
     296                 : //    x = LittleEndian.Load16(p);
     297                 : class LittleEndian {
     298                 :  public:
     299                 :   // Conversion functions.
     300                 : #ifdef WORDS_BIGENDIAN
     301                 : 
     302                 :   static uint16 FromHost16(uint16 x) { return bswap_16(x); }
     303                 :   static uint16 ToHost16(uint16 x) { return bswap_16(x); }
     304                 : 
     305                 :   static uint32 FromHost32(uint32 x) { return bswap_32(x); }
     306                 :   static uint32 ToHost32(uint32 x) { return bswap_32(x); }
     307                 : 
     308                 :   static bool IsLittleEndian() { return false; }
     309                 : 
     310                 : #else  // !defined(WORDS_BIGENDIAN)
     311                 : 
     312              57 :   static uint16 FromHost16(uint16 x) { return x; }
     313                 :   static uint16 ToHost16(uint16 x) { return x; }
     314                 : 
     315                 :   static uint32 FromHost32(uint32 x) { return x; }
     316            4250 :   static uint32 ToHost32(uint32 x) { return x; }
     317                 : 
     318            6477 :   static bool IsLittleEndian() { return true; }
     319                 : 
     320                 : #endif  // !defined(WORDS_BIGENDIAN)
     321                 : 
     322                 :   // Functions to do unaligned loads and stores in little-endian order.
     323                 :   static uint16 Load16(const void *p) {
     324                 :     return ToHost16(UNALIGNED_LOAD16(p));
     325                 :   }
     326                 : 
     327              57 :   static void Store16(void *p, uint16 v) {
     328              57 :     UNALIGNED_STORE16(p, FromHost16(v));
     329              57 :   }
     330                 : 
     331            4250 :   static uint32 Load32(const void *p) {
     332            4250 :     return ToHost32(UNALIGNED_LOAD32(p));
     333                 :   }
     334                 : 
     335                 :   static void Store32(void *p, uint32 v) {
     336                 :     UNALIGNED_STORE32(p, FromHost32(v));
     337                 :   }
     338                 : };
     339                 : 
     340                 : // Some bit-manipulation functions.
     341                 : class Bits {
     342                 :  public:
     343                 :   // Return floor(log2(n)) for positive integer n.  Returns -1 iff n == 0.
     344                 :   static int Log2Floor(uint32 n);
     345                 : 
     346                 :   // Return the first set least / most significant bit, 0-indexed.  Returns an
     347                 :   // undefined value if n == 0.  FindLSBSetNonZero() is similar to ffs() except
     348                 :   // that it's 0-indexed.
     349                 :   static int FindLSBSetNonZero(uint32 n);
     350                 :   static int FindLSBSetNonZero64(uint64 n);
     351                 : 
     352                 :  private:
     353                 :   DISALLOW_COPY_AND_ASSIGN(Bits);
     354                 : };
     355                 : 
     356                 : #ifdef HAVE_BUILTIN_CTZ
     357                 : 
     358                 : inline int Bits::Log2Floor(uint32 n) {
     359                 :   return n == 0 ? -1 : 31 ^ __builtin_clz(n);
     360                 : }
     361                 : 
     362                 : inline int Bits::FindLSBSetNonZero(uint32 n) {
     363                 :   return __builtin_ctz(n);
     364                 : }
     365                 : 
     366                 : inline int Bits::FindLSBSetNonZero64(uint64 n) {
     367                 :   return __builtin_ctzll(n);
     368                 : }
     369                 : 
     370                 : #else  // Portable versions.
     371                 : 
     372            1837 : inline int Bits::Log2Floor(uint32 n) {
     373            1837 :   if (n == 0)
     374               0 :     return -1;
     375            1837 :   int log = 0;
     376            1837 :   uint32 value = n;
     377           11022 :   for (int i = 4; i >= 0; --i) {
     378            9185 :     int shift = (1 << i);
     379            9185 :     uint32 x = value >> shift;
     380            9185 :     if (x != 0) {
     381            1837 :       value = x;
     382            1837 :       log += shift;
     383                 :     }
     384                 :   }
     385            1837 :   assert(value == 1);
     386            1837 :   return log;
     387                 : }
     388                 : 
     389            1657 : inline int Bits::FindLSBSetNonZero(uint32 n) {
     390            1657 :   int rc = 31;
     391            9942 :   for (int i = 4, shift = 1 << 4; i >= 0; --i) {
     392            8285 :     const uint32 x = n << shift;
     393            8285 :     if (x != 0) {
     394            4985 :       n = x;
     395            4985 :       rc -= shift;
     396                 :     }
     397            8285 :     shift >>= 1;
     398                 :   }
     399            1657 :   return rc;
     400                 : }
     401                 : 
     402                 : // FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
     403                 : inline int Bits::FindLSBSetNonZero64(uint64 n) {
     404                 :   const uint32 bottombits = static_cast<uint32>(n);
     405                 :   if (bottombits == 0) {
     406                 :     // Bottom bits are zero, so scan in top bits
     407                 :     return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
     408                 :   } else {
     409                 :     return FindLSBSetNonZero(bottombits);
     410                 :   }
     411                 : }
     412                 : 
     413                 : #endif  // End portable versions.
     414                 : 
     415                 : // Variable-length integer encoding.
     416                 : class Varint {
     417                 :  public:
     418                 :   // Maximum lengths of varint encoding of uint32.
     419                 :   static const int kMax32 = 5;
     420                 : 
     421                 :   // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
     422                 :   // Never reads a character at or beyond limit.  If a valid/terminated varint32
     423                 :   // was found in the range, stores it in *OUTPUT and returns a pointer just
     424                 :   // past the last byte of the varint32. Else returns NULL.  On success,
     425                 :   // "result <= limit".
     426                 :   static const char* Parse32WithLimit(const char* ptr, const char* limit,
     427                 :                                       uint32* OUTPUT);
     428                 : 
     429                 :   // REQUIRES   "ptr" points to a buffer of length sufficient to hold "v".
     430                 :   // EFFECTS    Encodes "v" into "ptr" and returns a pointer to the
     431                 :   //            byte just past the last encoded byte.
     432                 :   static char* Encode32(char* ptr, uint32 v);
     433                 : 
     434                 :   // EFFECTS    Appends the varint representation of "value" to "*s".
     435                 :   static void Append32(string* s, uint32 value);
     436                 : };
     437                 : 
     438            1970 : inline const char* Varint::Parse32WithLimit(const char* p,
     439                 :                                             const char* l,
     440                 :                                             uint32* OUTPUT) {
     441            1970 :   const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
     442            1970 :   const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
     443                 :   uint32 b, result;
     444            1970 :   if (ptr >= limit) return NULL;
     445            1970 :   b = *(ptr++); result = b & 127;          if (b < 128) goto done;
     446             224 :   if (ptr >= limit) return NULL;
     447             224 :   b = *(ptr++); result |= (b & 127) <<  7; if (b < 128) goto done;
     448               0 :   if (ptr >= limit) return NULL;
     449               0 :   b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
     450               0 :   if (ptr >= limit) return NULL;
     451               0 :   b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
     452               0 :   if (ptr >= limit) return NULL;
     453               0 :   b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
     454               0 :   return NULL;       // Value is too long to be a varint32
     455                 :  done:
     456            1970 :   *OUTPUT = result;
     457            1970 :   return reinterpret_cast<const char*>(ptr);
     458                 : }
     459                 : 
     460            1837 : inline char* Varint::Encode32(char* sptr, uint32 v) {
     461                 :   // Operate on characters as unsigneds
     462            1837 :   unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
     463                 :   static const int B = 128;
     464            1837 :   if (v < (1<<7)) {
     465            1792 :     *(ptr++) = v;
     466              45 :   } else if (v < (1<<14)) {
     467              45 :     *(ptr++) = v | B;
     468              45 :     *(ptr++) = v>>7;
     469               0 :   } else if (v < (1<<21)) {
     470               0 :     *(ptr++) = v | B;
     471               0 :     *(ptr++) = (v>>7) | B;
     472               0 :     *(ptr++) = v>>14;
     473               0 :   } else if (v < (1<<28)) {
     474               0 :     *(ptr++) = v | B;
     475               0 :     *(ptr++) = (v>>7) | B;
     476               0 :     *(ptr++) = (v>>14) | B;
     477               0 :     *(ptr++) = v>>21;
     478                 :   } else {
     479               0 :     *(ptr++) = v | B;
     480               0 :     *(ptr++) = (v>>7) | B;
     481               0 :     *(ptr++) = (v>>14) | B;
     482               0 :     *(ptr++) = (v>>21) | B;
     483               0 :     *(ptr++) = v>>28;
     484                 :   }
     485            1837 :   return reinterpret_cast<char*>(ptr);
     486                 : }
     487                 : 
     488                 : // If you know the internal layout of the std::string in use, you can
     489                 : // replace this function with one that resizes the string without
     490                 : // filling the new space with zeros (if applicable) --
     491                 : // it will be non-portable but faster.
     492               0 : inline void STLStringResizeUninitialized(string* s, size_t new_size) {
     493               0 :   s->resize(new_size);
     494               0 : }
     495                 : 
     496                 : // Return a mutable char* pointing to a string's internal buffer,
     497                 : // which may not be null-terminated. Writing through this pointer will
     498                 : // modify the string.
     499                 : //
     500                 : // string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
     501                 : // next call to a string method that invalidates iterators.
     502                 : //
     503                 : // As of 2006-04, there is no standard-blessed way of getting a
     504                 : // mutable reference to a string's internal buffer. However, issue 530
     505                 : // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)
     506                 : // proposes this as the method. It will officially be part of the standard
     507                 : // for C++0x. This should already work on all current implementations.
     508               0 : inline char* string_as_array(string* str) {
     509               0 :   return str->empty() ? NULL : &*str->begin();
     510                 : }
     511                 : 
     512                 : }  // namespace snappy
     513                 : 
     514                 : #endif  // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_

Generated by: LCOV version 1.7