Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

varint.h

Go to the documentation of this file.
00001 //***************************************************************************
00002 // This source code is copyrighted 2002 by Google Inc.  All rights
00003 // reserved.  You are given a limited license to use this source code for
00004 // purposes of participating in the Google programming contest.  If you
00005 // choose to use or distribute the source code for any other purpose, you
00006 // must either (1) first obtain written approval from Google, or (2)
00007 // prominently display the foregoing copyright notice and the following
00008 // warranty and liability disclaimer on each copy used or distributed.
00009 // 
00010 // The source code and repository (the "Software") is provided "AS IS",
00011 // with no warranty, express or implied, including but not limited to the
00012 // implied warranties of merchantability and fitness for a particular
00013 // use.  In no event shall Google Inc. be liable for any damages, direct
00014 // or indirect, even if advised of the possibility of such damages.
00015 //***************************************************************************
00016 
00017 //
00018 // Raw support for varint encoding.  Higher level interfaces are
00019 // provided by Encoder/Decoder.  Clients should typically use
00020 // those interfaces, unless speed is paramount.
00021 //
00022 // Provided routines:
00023 //      vi_parse32_unchecked
00024 //      vi_parse64_unchecked
00025 //      vi_encode32_unchecked
00026 //      vi_encode64_unchecked
00027 
00028 #ifndef _VARINT_H
00029 #define _VARINT_H
00030 
00031 #include "basictypes.h"
00032 
00033 // Just a namespace, not a real class
00034 class Varint {
00035  public:
00036   // Maximum lengths of varint encoding of uint32 and uint64
00037   static const int kMax32 = 5;
00038   static const int kMax64 = 10;
00039 
00040   // REQUIRES   "ptr" points to a buffer of length at least kVarintMaxXX
00041   // EFFECTS    Scan next varint from "ptr" and store in OUTPUT.
00042   //            Returns pointer just past last read byte.  Returns
00043   //            NULL if a valid varint value was not found.
00044   static const char* Parse32(const char* ptr, uint32* OUTPUT);
00045   static const char* Parse64(const char* ptr, uint64* OUTPUT);
00046 
00047   // REQUIRES   "ptr" points to a buffer of length sufficient to hold "v".
00048   // EFFECTS    Encodes "v" into "ptr" and returns a pointer to the
00049   //            byte just past the last encoded byte.
00050   static char* Encode32(char* ptr, uint32 v);
00051   static char* Encode64(char* ptr, uint64 v);
00052 
00053   // EFFECTS    Returns the encoding length of the specified value.
00054   static int Length32(uint32 v);
00055   static int Length64(uint64 v);
00056 };
00057 
00058 /***** Implementation details; clients should ignore *****/
00059   
00060 inline const char* Varint::Parse32(const char* ptr, uint32* OUTPUT) {
00061   // Fast path
00062   uint32 byte, result;
00063   byte = *(ptr++); result = byte & 127;          if (byte < 128) goto done;
00064   byte = *(ptr++); result |= (byte & 127) <<  7; if (byte < 128) goto done;
00065   byte = *(ptr++); result |= (byte & 127) << 14; if (byte < 128) goto done;
00066   byte = *(ptr++); result |= (byte & 127) << 21; if (byte < 128) goto done;
00067   byte = *(ptr++); result |= (byte & 127) << 28; if (byte < 128) goto done;
00068   return NULL;       // Value is too long to be a varint32
00069  done:
00070   *OUTPUT = result;
00071   return ptr;
00072 }
00073 
00074 inline const char* Varint::Parse64(const char* ptr, uint64* OUTPUT) {
00075   // Fast path: need to accumulate data in upto three result fragments
00076   //    res1    bits 0..27
00077   //    res2    bits 28..55
00078   //    res3    bits 56..63
00079   uint32 byte, res1, res2=0, res3=0;
00080   
00081   byte = *(ptr++); res1 = byte & 127;          if (byte < 128) goto done;
00082   byte = *(ptr++); res1 |= (byte & 127) <<  7; if (byte < 128) goto done;
00083   byte = *(ptr++); res1 |= (byte & 127) << 14; if (byte < 128) goto done;
00084   byte = *(ptr++); res1 |= (byte & 127) << 21; if (byte < 128) goto done;
00085   
00086   byte = *(ptr++); res2 = byte & 127;          if (byte < 128) goto done;
00087   byte = *(ptr++); res2 |= (byte & 127) <<  7; if (byte < 128) goto done;
00088   byte = *(ptr++); res2 |= (byte & 127) << 14; if (byte < 128) goto done;
00089   byte = *(ptr++); res2 |= (byte & 127) << 21; if (byte < 128) goto done;
00090   
00091   byte = *(ptr++); res3 = byte & 127;          if (byte < 128) goto done;
00092   byte = *(ptr++); res3 |= (byte & 127) <<  7; if (byte < 128) goto done;
00093   
00094   return NULL;       // Value is too long to be a varint64
00095   
00096  done:
00097   *OUTPUT = res1 | (uint64(res2) << 28) | (uint64(res3) << 56);
00098   return ptr;
00099 }
00100 
00101 inline int Varint::Length32(uint32 v) {
00102   // Each byte of output stores 7 bits of "v" until "v" becomes zero
00103   int nbytes = 0;
00104   do {
00105     nbytes++;
00106     v >>= 7;
00107   } while (v != 0);
00108   return nbytes;
00109 }
00110 
00111 inline int Varint::Length64(uint64 v) {
00112   // Each byte of output stores 7 bits of "v" until "v" becomes zero
00113   int nbytes = 0;
00114   do {
00115     nbytes++;
00116     v >>= 7;
00117   } while (v != 0);
00118   return nbytes;
00119 }
00120 
00121 #endif /* _VARINT_H */

Generated on Wed May 29 11:37:16 2002 for MarkovPR by doxygen1.2.15