Google group varint無損圧縮解凍アルゴリズムの効率的な実現改善版


以前はgoogle group varint無損圧縮解凍アルゴリズムの効率的な実現を実現した.
最近、性能が20%向上し、テストデータは以下の通りである:100万個の整数(4 M)の新しいバージョンを圧縮し、解凍する:encode time consumed:0.003252 s;decode time consumed:0.003769 s旧バージョン:encode time consumed:0.005198 s;decode time consumed: 0.004909 s
これで1秒で1 Gのデータを解凍できるなんて、驚くべきことでしょう.
くだらないことを言わないで、コードをつけて、興味のある自分で見て、もし私の注釈がはっきりしていないならば、私に連絡して修正してください


/******************************************************************
 *  Created on: 2011-4-26
 *      Author: [email protected] [email protected]
 *
 *      Desc  :   uint32   varint        
 *                group varint     
 *
 ******************************************************************/

#ifndef VARINT_H_
#define VARINT_H_

#include <stdint.h>
#include <stddef.h>

#include "common.h"

namespace ups_util
{

#pragma pack(1)
typedef struct
{
    uint32_t value : 24;
}UINT24_T;

#pragma pack()

/**
 * group varint     ,    :(byte)
 *
 *  0 :  2                    
 *  1 :  3                    
 *  2 :  4                    
 *  3 :  1         
 *  4 :  2         
 *  5 :  3         
 *  6 :  4         
 *  7 :        (4   )                 
 *
 *                  1
 */
static const uint8_t GROUP_VARINT_IDX_ARR[256][8] =
{
        /* 00 00 00 00 */ { 2, 3, 4, 1, 1, 1, 1, 5},
        /* 00 00 00 01 */ { 2, 3, 4, 1, 1, 1, 2, 6},
        /* 00 00 00 10 */ { 2, 3, 4, 1, 1, 1, 3, 7},
        /* 00 00 00 11 */ { 2, 3, 4, 1, 1, 1, 4, 8},

        /* 00 00 01 00 */ { 2, 3, 5, 1, 1, 2, 1, 6},
        /* 00 00 01 01 */ { 2, 3, 5, 1, 1, 2, 2, 7},
        /* 00 00 01 10 */ { 2, 3, 5, 1, 1, 2, 3, 8},
        /* 00 00 01 11 */ { 2, 3, 5, 1, 1, 2, 4, 9},

        /* 00 00 10 00 */ { 2, 3, 6, 1, 1, 3, 1, 7},
        /* 00 00 10 01 */ { 2, 3, 6, 1, 1, 3, 2, 8},
        /* 00 00 10 10 */ { 2, 3, 6, 1, 1, 3, 3, 9},
        /* 00 00 10 11 */ { 2, 3, 6, 1, 1, 3, 4, 10},

        /* 00 00 11 00 */ { 2, 3, 7, 1, 1, 4, 1, 8},
        /* 00 00 11 01 */ { 2, 3, 7, 1, 1, 4, 2, 9},
        /* 00 00 11 10 */ { 2, 3, 7, 1, 1, 4, 3, 10},
        /* 00 00 11 11 */ { 2, 3, 7, 1, 1, 4, 4, 11},

        /* 00 01 00 00 */ { 2, 4, 5, 1, 2, 1, 1, 6},
        /* 00 01 00 01 */ { 2, 4, 5, 1, 2, 1, 2, 7},
        /* 00 01 00 10 */ { 2, 4, 5, 1, 2, 1, 3, 8},
        /* 00 01 00 11 */ { 2, 4, 5, 1, 2, 1, 4, 9},

        /* 00 01 01 00 */ { 2, 4, 6, 1, 2, 2, 1, 7},
        /* 00 01 01 01 */ { 2, 4, 6, 1, 2, 2, 2, 8},
        /* 00 01 01 10 */ { 2, 4, 6, 1, 2, 2, 3, 9},
        /* 00 01 01 11 */ { 2, 4, 6, 1, 2, 2, 4, 10},

        /* 00 01 10 00 */ { 2, 4, 7, 1, 2, 3, 1, 8},
        /* 00 01 10 01 */ { 2, 4, 7, 1, 2, 3, 2, 9},
        /* 00 01 10 10 */ { 2, 4, 7, 1, 2, 3, 3, 10},
        /* 00 01 10 11 */ { 2, 4, 7, 1, 2, 3, 4, 11},

        /* 00 01 11 00 */ { 2, 4, 8, 1, 2, 4, 1, 9},
        /* 00 01 11 01 */ { 2, 4, 8, 1, 2, 4, 2, 10},
        /* 00 01 11 10 */ { 2, 4, 8, 1, 2, 4, 3, 11},
        /* 00 01 11 11 */ { 2, 4, 8, 1, 2, 4, 4, 12},

        /* 00 10 00 00 */ { 2, 5, 6, 1, 3, 1, 1, 7},
        /* 00 10 00 01 */ { 2, 5, 6, 1, 3, 1, 2, 8},
        /* 00 10 00 10 */ { 2, 5, 6, 1, 3, 1, 3, 9},
        /* 00 10 00 11 */ { 2, 5, 6, 1, 3, 1, 4, 10},

        /* 00 10 01 00 */ { 2, 5, 7, 1, 3, 2, 1, 8},
        /* 00 10 01 01 */ { 2, 5, 7, 1, 3, 2, 2, 9},
        /* 00 10 01 10 */ { 2, 5, 7, 1, 3, 2, 3, 10},
        /* 00 10 01 11 */ { 2, 5, 7, 1, 3, 2, 4, 11},

        /* 00 10 10 00 */ { 2, 5, 8, 1, 3, 3, 1, 9},
        /* 00 10 10 01 */ { 2, 5, 8, 1, 3, 3, 2, 10},
        /* 00 10 10 10 */ { 2, 5, 8, 1, 3, 3, 3, 11},
        /* 00 10 10 11 */ { 2, 5, 8, 1, 3, 3, 4, 12},

        /* 00 10 11 00 */ { 2, 5, 9, 1, 3, 4, 1, 10},
        /* 00 10 11 01 */ { 2, 5, 9, 1, 3, 4, 2, 11},
        /* 00 10 11 10 */ { 2, 5, 9, 1, 3, 4, 3, 12},
        /* 00 10 11 11 */ { 2, 5, 9, 1, 3, 4, 4, 13},

        /* 00 11 00 00 */ { 2, 6, 7, 1, 4, 1, 1, 8},
        /* 00 11 00 01 */ { 2, 6, 7, 1, 4, 1, 2, 9},
        /* 00 11 00 10 */ { 2, 6, 7, 1, 4, 1, 3, 10},
        /* 00 11 00 11 */ { 2, 6, 7, 1, 4, 1, 4, 11},

        /* 00 11 01 00 */ { 2, 6, 8, 1, 4, 2, 1, 9},
        /* 00 11 01 01 */ { 2, 6, 8, 1, 4, 2, 2, 10},
        /* 00 11 01 10 */ { 2, 6, 8, 1, 4, 2, 3, 11},
        /* 00 11 01 11 */ { 2, 6, 8, 1, 4, 2, 4, 12},

        /* 00 11 10 00 */ { 2, 6, 9, 1, 4, 3, 1, 10},
        /* 00 11 10 01 */ { 2, 6, 9, 1, 4, 3, 2, 11},
        /* 00 11 10 10 */ { 2, 6, 9, 1, 4, 3, 3, 12},
        /* 00 11 10 11 */ { 2, 6, 9, 1, 4, 3, 4, 13},

        /* 00 11 11 00 */ { 2, 6, 10 , 1, 4, 4, 1, 11},
        /* 00 11 11 01 */ { 2, 6, 10 , 1, 4, 4, 2, 12 },
        /* 00 11 11 10 */ { 2, 6, 10 , 1, 4, 4, 3, 13 },
        /* 00 11 11 11 */ { 2, 6, 10 , 1, 4, 4, 4, 14 },

        /* 01 00 00 00 */ { 3, 4, 5, 2, 1, 1, 1, 6},
        /* 01 00 00 01 */ { 3, 4, 5, 2, 1, 1, 2, 7},
        /* 01 00 00 10 */ { 3, 4, 5, 2, 1, 1, 3, 8},
        /* 01 00 00 11 */ { 3, 4, 5, 2, 1, 1, 4, 9},

        /* 01 00 01 00 */ { 3, 4, 6, 2, 1, 2, 1, 7},
        /* 01 00 01 01 */ { 3, 4, 6, 2, 1, 2, 2, 8},
        /* 01 00 01 10 */ { 3, 4, 6, 2, 1, 2, 3, 9},
        /* 01 00 01 11 */ { 3, 4, 6, 2, 1, 2, 4, 10},

        /* 01 00 10 00 */ { 3, 4, 7, 2, 1, 3, 1, 8},
        /* 01 00 10 01 */ { 3, 4, 7, 2, 1, 3, 2, 9},
        /* 01 00 10 10 */ { 3, 4, 7, 2, 1, 3, 3, 10},
        /* 01 00 10 11 */ { 3, 4, 7, 2, 1, 3, 4, 11},

        /* 01 00 11 00 */ { 3, 4, 8, 2, 1, 4, 1, 9},
        /* 01 00 11 01 */ { 3, 4, 8, 2, 1, 4, 2, 10},
        /* 01 00 11 10 */ { 3, 4, 8, 2, 1, 4, 3, 11},
        /* 01 00 11 11 */ { 3, 4, 8, 2, 1, 4, 4, 12},

        /* 01 01 00 00 */ { 3, 5, 6, 2, 2, 1, 1, 7},
        /* 01 01 00 01 */ { 3, 5, 6, 2, 2, 1, 2, 8},
        /* 01 01 00 10 */ { 3, 5, 6, 2, 2, 1, 3, 9},
        /* 01 01 00 11 */ { 3, 5, 6, 2, 2, 1, 4, 10},

        /* 01 01 01 00 */ { 3, 5, 7, 2, 2, 2, 1, 8},
        /* 01 01 01 01 */ { 3, 5, 7, 2, 2, 2, 2, 9},
        /* 01 01 01 10 */ { 3, 5, 7, 2, 2, 2, 3, 10},
        /* 01 01 01 11 */ { 3, 5, 7, 2, 2, 2, 4, 11},

        /* 01 01 10 00 */ { 3, 5, 8, 2, 2, 3, 1, 9},
        /* 01 01 10 01 */ { 3, 5, 8, 2, 2, 3, 2, 10},
        /* 01 01 10 10 */ { 3, 5, 8, 2, 2, 3, 3, 11},
        /* 01 01 10 11 */ { 3, 5, 8, 2, 2, 3, 4, 12},

        /* 01 01 11 00 */ { 3, 5, 9, 2, 2, 4, 1, 10},
        /* 01 01 11 01 */ { 3, 5, 9, 2, 2, 4, 2, 11},
        /* 01 01 11 10 */ { 3, 5, 9, 2, 2, 4, 3, 12},
        /* 01 01 11 11 */ { 3, 5, 9, 2, 2, 4, 4, 13},

        /* 01 10 00 00 */ { 3, 6, 7, 2, 3, 1, 1, 8},
        /* 01 10 00 01 */ { 3, 6, 7, 2, 3, 1, 2, 9},
        /* 01 10 00 10 */ { 3, 6, 7, 2, 3, 1, 3, 10},
        /* 01 10 00 11 */ { 3, 6, 7, 2, 3, 1, 4, 11},

        /* 01 10 01 00 */ { 3, 6, 8, 2, 3, 2, 1, 9},
        /* 01 10 01 01 */ { 3, 6, 8, 2, 3, 2, 2, 10},
        /* 01 10 01 10 */ { 3, 6, 8, 2, 3, 2, 3, 11},
        /* 01 10 01 11 */ { 3, 6, 8, 2, 3, 2, 4, 12},

        /* 01 10 10 00 */ { 3, 6, 9, 2, 3, 3, 1, 10},
        /* 01 10 10 01 */ { 3, 6, 9, 2, 3, 3, 2, 11},
        /* 01 10 10 10 */ { 3, 6, 9, 2, 3, 3, 3, 12},
        /* 01 10 10 11 */ { 3, 6, 9, 2, 3, 3, 4, 13},

        /* 01 10 11 00 */ { 3, 6, 10 , 2, 3, 4, 1 , 11},
        /* 01 10 11 01 */ { 3, 6, 10 , 2, 3, 4, 2 , 12},
        /* 01 10 11 10 */ { 3, 6, 10 , 2, 3, 4, 3 , 13},
        /* 01 10 11 11 */ { 3, 6, 10 , 2, 3, 4, 4 , 14},

        /* 01 11 00 00 */ { 3, 7, 8, 2, 4, 1, 1, 9},
        /* 01 11 00 01 */ { 3, 7, 8, 2, 4, 1, 2, 10},
        /* 01 11 00 10 */ { 3, 7, 8, 2, 4, 1, 3, 11},
        /* 01 11 00 11 */ { 3, 7, 8, 2, 4, 1, 4, 12},

        /* 01 11 01 00 */ { 3, 7, 9, 2, 4, 2, 1, 10},
        /* 01 11 01 01 */ { 3, 7, 9, 2, 4, 2, 2, 11},
        /* 01 11 01 10 */ { 3, 7, 9, 2, 4, 2, 3, 12},
        /* 01 11 01 11 */ { 3, 7, 9, 2, 4, 2, 4, 13},

        /* 01 11 10 00 */ { 3, 7, 10 , 2, 4, 3, 1 , 11},
        /* 01 11 10 01 */ { 3, 7, 10 , 2, 4, 3, 2 , 12},
        /* 01 11 10 10 */ { 3, 7, 10 , 2, 4, 3, 3 , 13},
        /* 01 11 10 11 */ { 3, 7, 10 , 2, 4, 3, 4 , 14},

        /* 01 11 11 00 */ { 3, 7, 11 , 2, 4, 4, 1 , 12},
        /* 01 11 11 01 */ { 3, 7, 11 , 2, 4, 4, 2 , 13},
        /* 01 11 11 10 */ { 3, 7, 11 , 2, 4, 4, 3 , 14},
        /* 01 11 11 11 */ { 3, 7, 11 , 2, 4, 4, 4 , 15},

        /* 10 00 00 00 */ { 4, 5, 6, 3, 1, 1, 1, 7},
        /* 10 00 00 01 */ { 4, 5, 6, 3, 1, 1, 2, 8},
        /* 10 00 00 10 */ { 4, 5, 6, 3, 1, 1, 3, 9},
        /* 10 00 00 11 */ { 4, 5, 6, 3, 1, 1, 4, 10},

        /* 10 00 01 00 */ { 4, 5, 7, 3, 1, 2, 1, 8},
        /* 10 00 01 01 */ { 4, 5, 7, 3, 1, 2, 2, 9},
        /* 10 00 01 10 */ { 4, 5, 7, 3, 1, 2, 3, 10},
        /* 10 00 01 11 */ { 4, 5, 7, 3, 1, 2, 4, 11},

        /* 10 00 10 00 */ { 4, 5, 8, 3, 1, 3, 1, 9},
        /* 10 00 10 01 */ { 4, 5, 8, 3, 1, 3, 2, 10},
        /* 10 00 10 10 */ { 4, 5, 8, 3, 1, 3, 3, 11},
        /* 10 00 10 11 */ { 4, 5, 8, 3, 1, 3, 4, 12},

        /* 10 00 11 00 */ { 4, 5, 9, 3, 1, 4, 1, 10},
        /* 10 00 11 01 */ { 4, 5, 9, 3, 1, 4, 2, 11},
        /* 10 00 11 10 */ { 4, 5, 9, 3, 1, 4, 3, 12},
        /* 10 00 11 11 */ { 4, 5, 9, 3, 1, 4, 4, 13},

        /* 10 01 00 00 */ { 4, 6, 7, 3, 2, 1, 1, 8},
        /* 10 01 00 01 */ { 4, 6, 7, 3, 2, 1, 2, 9},
        /* 10 01 00 10 */ { 4, 6, 7, 3, 2, 1, 3, 10},
        /* 10 01 00 11 */ { 4, 6, 7, 3, 2, 1, 4, 11},

        /* 10 01 01 00 */ { 4, 6, 8, 3, 2, 2, 1, 9},
        /* 10 01 01 01 */ { 4, 6, 8, 3, 2, 2, 2, 10},
        /* 10 01 01 10 */ { 4, 6, 8, 3, 2, 2, 3, 11},
        /* 10 01 01 11 */ { 4, 6, 8, 3, 2, 2, 4, 12},

        /* 10 01 10 00 */ { 4, 6, 9, 3, 2, 3, 1, 10},
        /* 10 01 10 01 */ { 4, 6, 9, 3, 2, 3, 2, 11},
        /* 10 01 10 10 */ { 4, 6, 9, 3, 2, 3, 3, 12},
        /* 10 01 10 11 */ { 4, 6, 9, 3, 2, 3, 4, 13},

        /* 10 01 11 00 */ { 4, 6, 10 , 3, 2, 4, 1, 11 },
        /* 10 01 11 01 */ { 4, 6, 10 , 3, 2, 4, 2, 12 },
        /* 10 01 11 10 */ { 4, 6, 10 , 3, 2, 4, 3, 13 },
        /* 10 01 11 11 */ { 4, 6, 10 , 3, 2, 4, 4, 14 },

        /* 10 10 00 00 */ { 4, 7, 8, 3, 3, 1, 1, 9},
        /* 10 10 00 01 */ { 4, 7, 8, 3, 3, 1, 2, 10},
        /* 10 10 00 10 */ { 4, 7, 8, 3, 3, 1, 3, 11},
        /* 10 10 00 11 */ { 4, 7, 8, 3, 3, 1, 4, 12},

        /* 10 10 01 00 */ { 4, 7, 9, 3, 3, 2, 1, 10},
        /* 10 10 01 01 */ { 4, 7, 9, 3, 3, 2, 2, 11},
        /* 10 10 01 10 */ { 4, 7, 9, 3, 3, 2, 3, 12},
        /* 10 10 01 11 */ { 4, 7, 9, 3, 3, 2, 4, 13},

        /* 10 10 10 00 */ { 4, 7, 10 , 3, 3, 3, 1, 11 },
        /* 10 10 10 01 */ { 4, 7, 10 , 3, 3, 3, 2, 12 },
        /* 10 10 10 10 */ { 4, 7, 10 , 3, 3, 3, 3, 13 },
        /* 10 10 10 11 */ { 4, 7, 10 , 3, 3, 3, 4, 14 },

        /* 10 10 11 00 */ { 4, 7, 11 , 3, 3, 4, 1, 12 },
        /* 10 10 11 01 */ { 4, 7, 11 , 3, 3, 4, 2, 13 },
        /* 10 10 11 10 */ { 4, 7, 11 , 3, 3, 4, 3, 14 },
        /* 10 10 11 11 */ { 4, 7, 11 , 3, 3, 4, 4, 15 },

        /* 10 11 00 00 */ { 4, 8, 9, 3, 4, 1, 1, 10},
        /* 10 11 00 01 */ { 4, 8, 9, 3, 4, 1, 2, 11},
        /* 10 11 00 10 */ { 4, 8, 9, 3, 4, 1, 3, 12},
        /* 10 11 00 11 */ { 4, 8, 9, 3, 4, 1, 4, 13},

        /* 10 11 01 00 */ { 4, 8, 10 , 3, 4, 2, 1, 11 },
        /* 10 11 01 01 */ { 4, 8, 10 , 3, 4, 2, 2, 12 },
        /* 10 11 01 10 */ { 4, 8, 10 , 3, 4, 2, 3, 13 },
        /* 10 11 01 11 */ { 4, 8, 10 , 3, 4, 2, 4, 14 },

        /* 10 11 10 00 */ { 4, 8, 11 , 3, 4, 3, 1, 12 },
        /* 10 11 10 01 */ { 4, 8, 11 , 3, 4, 3, 2, 13 },
        /* 10 11 10 10 */ { 4, 8, 11 , 3, 4, 3, 3, 14 },
        /* 10 11 10 11 */ { 4, 8, 11 , 3, 4, 3, 4, 15 },

        /* 10 11 11 00 */ { 4, 8, 12 , 3, 4, 4, 1, 13 },
        /* 10 11 11 01 */ { 4, 8, 12 , 3, 4, 4, 2, 14 },
        /* 10 11 11 10 */ { 4, 8, 12 , 3, 4, 4, 3, 15 },
        /* 10 11 11 11 */ { 4, 8, 12 , 3, 4, 4, 4, 16 },

        /* 11 00 00 00 */ { 5, 6, 7, 4, 1, 1, 1, 8},
        /* 11 00 00 01 */ { 5, 6, 7, 4, 1, 1, 2, 9},
        /* 11 00 00 10 */ { 5, 6, 7, 4, 1, 1, 3, 10},
        /* 11 00 00 11 */ { 5, 6, 7, 4, 1, 1, 4, 11},

        /* 11 00 01 00 */ { 5, 6, 8, 4, 1, 2, 1, 9},
        /* 11 00 01 01 */ { 5, 6, 8, 4, 1, 2, 2, 10},
        /* 11 00 01 10 */ { 5, 6, 8, 4, 1, 2, 3, 11},
        /* 11 00 01 11 */ { 5, 6, 8, 4, 1, 2, 4, 12},

        /* 11 00 10 00 */ { 5, 6, 9, 4, 1, 3, 1, 10},
        /* 11 00 10 01 */ { 5, 6, 9, 4, 1, 3, 2, 11},
        /* 11 00 10 10 */ { 5, 6, 9, 4, 1, 3, 3, 12},
        /* 11 00 10 11 */ { 5, 6, 9, 4, 1, 3, 4, 13},

        /* 11 00 11 00 */ { 5, 6, 10 , 4, 1, 4, 1, 11 },
        /* 11 00 11 01 */ { 5, 6, 10 , 4, 1, 4, 2, 12 },
        /* 11 00 11 10 */ { 5, 6, 10 , 4, 1, 4, 3, 13 },
        /* 11 00 11 11 */ { 5, 6, 10 , 4, 1, 4, 4, 14 },

        /* 11 01 00 00 */ { 5, 7, 8, 4, 2, 1, 1, 9},
        /* 11 01 00 01 */ { 5, 7, 8, 4, 2, 1, 2, 10},
        /* 11 01 00 10 */ { 5, 7, 8, 4, 2, 1, 3, 11},
        /* 11 01 00 11 */ { 5, 7, 8, 4, 2, 1, 4, 12},

        /* 11 01 01 00 */ { 5, 7, 9, 4, 2, 2, 1, 10},
        /* 11 01 01 01 */ { 5, 7, 9, 4, 2, 2, 2, 11},
        /* 11 01 01 10 */ { 5, 7, 9, 4, 2, 2, 3, 12},
        /* 11 01 01 11 */ { 5, 7, 9, 4, 2, 2, 4, 13},

        /* 11 01 10 00 */ { 5, 7, 10 , 4, 2, 3, 1 , 11},
        /* 11 01 10 01 */ { 5, 7, 10 , 4, 2, 3, 2 , 12},
        /* 11 01 10 10 */ { 5, 7, 10 , 4, 2, 3, 3 , 13},
        /* 11 01 10 11 */ { 5, 7, 10 , 4, 2, 3, 4 , 14},

        /* 11 01 11 00 */ { 5, 7, 11 , 4, 2, 4, 1 , 12},
        /* 11 01 11 01 */ { 5, 7, 11 , 4, 2, 4, 2 , 13},
        /* 11 01 11 10 */ { 5, 7, 11 , 4, 2, 4, 3 , 14},
        /* 11 01 11 11 */ { 5, 7, 11 , 4, 2, 4, 4 , 15},

        /* 11 10 00 00 */ { 5, 8, 9, 4, 3, 1, 1, 10},
        /* 11 10 00 01 */ { 5, 8, 9, 4, 3, 1, 2, 11},
        /* 11 10 00 10 */ { 5, 8, 9, 4, 3, 1, 3, 12},
        /* 11 10 00 11 */ { 5, 8, 9, 4, 3, 1, 4, 13},

        /* 11 10 01 00 */ { 5, 8, 10 , 4, 3, 2, 1 , 11},
        /* 11 10 01 01 */ { 5, 8, 10 , 4, 3, 2, 2 , 12},
        /* 11 10 01 10 */ { 5, 8, 10 , 4, 3, 2, 3 , 13},
        /* 11 10 01 11 */ { 5, 8, 10 , 4, 3, 2, 4 , 14},

        /* 11 10 10 00 */ { 5, 8, 11 , 4, 3, 3, 1 , 12},
        /* 11 10 10 01 */ { 5, 8, 11 , 4, 3, 3, 2 , 13},
        /* 11 10 10 10 */ { 5, 8, 11 , 4, 3, 3, 3 , 14},
        /* 11 10 10 11 */ { 5, 8, 11 , 4, 3, 3, 4 , 15},

        /* 11 10 11 00 */ { 5, 8, 12 , 4, 3, 4, 1, 13 },
        /* 11 10 11 01 */ { 5, 8, 12 , 4, 3, 4, 2, 14 },
        /* 11 10 11 10 */ { 5, 8, 12 , 4, 3, 4, 3, 15 },
        /* 11 10 11 11 */ { 5, 8, 12 , 4, 3, 4, 4, 16 },

        /* 11 11 00 00 */ { 5, 9, 10 , 4, 4, 1, 1, 11 },
        /* 11 11 00 01 */ { 5, 9, 10 , 4, 4, 1, 2, 12 },
        /* 11 11 00 10 */ { 5, 9, 10 , 4, 4, 1, 3, 13 },
        /* 11 11 00 11 */ { 5, 9, 10 , 4, 4, 1, 4, 14 },

        /* 11 11 01 00 */ { 5, 9, 11 , 4, 4, 2, 1, 12 },
        /* 11 11 01 01 */ { 5, 9, 11 , 4, 4, 2, 2, 13 },
        /* 11 11 01 10 */ { 5, 9, 11 , 4, 4, 2, 3, 14 },
        /* 11 11 01 11 */ { 5, 9, 11 , 4, 4, 2, 4, 15 },

        /* 11 11 10 00 */ { 5, 9, 12 , 4, 4, 3, 1, 13 },
        /* 11 11 10 01 */ { 5, 9, 12 , 4, 4, 3, 2, 14 },
        /* 11 11 10 10 */ { 5, 9, 12 , 4, 4, 3, 3, 15 },
        /* 11 11 10 11 */ { 5, 9, 12 , 4, 4, 3, 4, 16 },

        /* 11 11 11 00 */ { 5, 9, 13 , 4, 4, 4, 1, 14 },
        /* 11 11 11 01 */ { 5, 9, 13 , 4, 4, 4, 2, 15 },
        /* 11 11 11 10 */ { 5, 9, 13 , 4, 4, 4, 3, 16 },
        /* 11 11 11 11 */ { 5, 9, 13 , 4, 4, 4, 4, 17}
};

/**
 *    uint32     varint        buf 
 *
 * @param value           
 * @param target            ,    buf       
 *
 * @return  target           
 */
inline uint8_t *
varint_encode_uint32 ( uint32_t value, uint8_t * target )
{
    if ( value >= (1 << 7) )
    {
        target[0] = (uint8_t)(value | 0x80);               //   7 ,     1

        if ( value >= (1 << 14) )
        {
            target[1] = (uint8_t)( (value >> 7) | 0x80 );  //    7 ,    1

            if ( value >= (1 << 21) )
            {
                //   3   7 ,    1
                target[2] = (uint8_t)( (value >> 14) | 0x80 );

                if ( value >= (1 << 28) )
                {
                    //   4   7 ,    1
                    target[3] = (uint8_t)((value >> 21) | 0x80);

                    //     4 
                    target[4] = (uint8_t)(value >> 28);

                    return target + 5;
                }
                else
                {
                    target[3] = (uint8_t)( value >> 21 );
                    return target + 4;
                }
            }
            else
            {
                target[2] = (uint8_t)( value >> 14 );
                return target + 3;
            }
        }
        else
        {
            target[1] = (uint8_t)( value >> 7 );
            return target + 2;
        }
    }
    else
    {
        target[0] = (uint8_t) value;
        return target + 1;
    }
}

/**
 *  buf    varint             
 *        buf                5 byte,     core
 *           
 *
 * @param buffer       buf
 * @param value         
 *
 * @return  target           
 */
inline const uint8_t *
varint_decode_uint32( const uint8_t * buffer, uint32_t & value )
{
    register const uint8_t * ptr = buffer;

    //  7 ,    128    
    register uint8_t   b0  = ptr[ 0 ];
    register uint32_t  r0  = (b0 & 0x7F);

    if (UNLIKELY( !(b0 & 0x80) ))
    {
        value = r0;
        return ptr + 1;
    }

    //  14 ,     16384    
    register uint8_t   b1  = ptr[ 1 ];
    register uint32_t  r1  = (b1 & 0x7F) << 7;

    if (UNLIKELY( !(b1 & 0x80) ))
    {
        value = ( r1 | r0 );
        return ptr + 2;
    }

    //  21 ,    2097152    
    register uint8_t   b2  = ptr[ 2 ];
    register uint32_t  r2  = (b2 & 0x7F) << 14;

    if (UNLIKELY( !(b2 & 0x80) ))
    {
        value = ( r2 | r1 | r0 );
        return ptr + 3;
    }

    //  28 ,    268435456    
    register uint8_t   b3  = ptr[ 3 ];
    register uint32_t  r3  = (b3 & 0x7F) << 21;

    if ( !(b3 & 0x80) )
    {
        value = ( r3 | r2 | r1 | r0 );
        return ptr + 4;
    }

    //    32 
    value = ( ((ptr[ 4 ]) << 28) | r3 | r2 | r1 | r0 );

    return ptr + 5;
}

/**
 *  buf               varint             
 *                ,   :     ,      NULL
 *
 * @param buffer       buf
 * @param value         
 *
 * @return  target           ,   buffer     NULL
 */
inline const uint8_t *
varint_decode_uint32( const uint8_t * buffer, uint32_t len, uint32_t & value )
{
    if ( len >= 5 )                                        // len == 0      
        return varint_decode_uint32( buffer, value );

    register const uint8_t * ptr = buffer;

    //  7 ,    128    
    register uint8_t   b0  = ptr[ 0 ];
    register uint32_t  r0  = (b0 & 0x7F);

    if (UNLIKELY( !(b0 & 0x80) ))
    {
        value = r0;
        return ptr + 1;
    }

    if (UNLIKELY( len < 2 ))  return NULL;

    //  14 ,     16384    
    register uint8_t   b1  = ptr[ 1 ];
    register uint32_t  r1  = (b1 & 0x7F) << 7;

    if (UNLIKELY( !(b1 & 0x80) ))
    {
        value = ( r1 | r0 );
        return ptr + 2;
    }

    if (UNLIKELY( len < 3 ))  return NULL;

    //  21 ,    2097152    
    register uint8_t   b2  = ptr[ 2 ];
    register uint32_t  r2  = (b2 & 0x7F) << 14;

    if (UNLIKELY( !(b2 & 0x80) ))
    {
        value = ( r2 | r1 | r0 );
        return ptr + 3;
    }

    if (UNLIKELY( len < 4 ))  return NULL;

    //  28 ,    268435456    
    register uint8_t   b3  = ptr[ 3 ];
    register uint32_t  r3  = (b3 & 0x7F) << 21;

    if ( !(b3 & 0x80) )
    {
        value = ( r3 | r2 | r1 | r0 );
        return ptr + 4;
    }

    if ( len < 5 )  return NULL;

    //    32 
    value = ( ((ptr[ 4 ]) << 28) | r3 | r2 | r1 | r0 );

    return ptr + 5;
}

/**             ,            ,      1  uint32 */
inline const uint8_t *
varint_decode_uint32_skip( const uint8_t * buffer )
{
    if (UNLIKELY( !(buffer[ 0 ] & 0x80) ))   return buffer + 1;
    if (UNLIKELY( !(buffer[ 1 ] & 0x80) ))   return buffer + 2;
    if (UNLIKELY( !(buffer[ 2 ] & 0x80) ))   return buffer + 3;
    if (          !(buffer[ 3 ] & 0x80) )    return buffer + 4;

    return buffer + 5;
}

/**
 *    uint64     varint        buf 
 *
 * @param value           
 * @param target            ,    buf       
 *
 * @return  target           
 */
inline uint8_t *
varint_encode_uint64 ( uint64_t value, uint8_t * target )
{
    //     32   32 
    target = varint_encode_uint32( value >> 32, target );

    return varint_encode_uint32( value & 0xFFFFFFFF, target );
}

/**
 *  buf    varint             
 *        buf                5 byte,     core
 *           
 *
 * @param buffer       buf
 * @param value         
 *
 * @return  target           
 */
inline const uint8_t *
varint_decode_uint64(const uint8_t * buffer, uint64_t & value)
{
    uint32_t  high = 0;
    uint32_t  low  = 0;

    buffer = varint_decode_uint32( buffer, high );
    buffer = varint_decode_uint32( buffer, low  );

    value = ((uint64_t)high << 32) + low ;

    return buffer;
}

/**             ,            ,       1 uint64 */
inline const uint8_t *
varint_decode_uint64_skip( const uint8_t * buffer )
{
    buffer = varint_decode_uint32_skip( buffer );

    return varint_decode_uint32_skip( buffer );
}

/**
 *         group varint  ,      4   
 *
 * @param valueArr                 ,    4   。      
 * @param target          buf .       ,  4       17 byte
 *
 * @return  target     byte
 */
inline uint8_t *
group_varint_encode_uint32( const uint32_t * valueArr, uint8_t * target)
{
    register uint8_t len1;                  //    1          
    register uint8_t len2;                  //    2          
    register uint8_t len3;                  //    3          
    register uint8_t len4;                  //   4          

    register uint32_t  val1 = valueArr[0];
    register uint32_t  val2 = valueArr[1];
    register uint32_t  val3 = valueArr[2];
    register uint32_t  val4 = valueArr[3];

    register uint8_t * buf = target + 1;

    if ( val1 > UINT24_MAX )
    {
        len1 = 4;
        ((uint32_t *)(buf))[0] = val1;
    }
    else if ( val1 > UINT16_MAX )
    {
        len1 = 3;
        ((uint32_t *)(buf))[0] = val1;
    }
    else if ( val1 > UINT8_MAX )
    {
        len1 = 2;
        ((uint16_t *)(buf))[0] = (uint16_t) val1;
    }
    else
    {
        len1   = 1;
        buf[0] = (uint8_t) val1;
    }

    register uint8_t len = len1;                 // 4           

    /*            */
    if (UNLIKELY( val2 > UINT24_MAX ))
    {
        len2 = 4;
        ((uint32_t *)(buf + len))[0] = val2;
    }
    else if ( val2 > UINT16_MAX )
    {
        len2 = 3;
        ((uint32_t *)(buf + len))[0] = val2;
    }
    else if ( val2 > UINT8_MAX )
    {
        len2 = 2;
        ((uint16_t *)(buf + len))[0] = (uint16_t) val2;
    }
    else
    {
        len2 = 1;
        buf[len] = (uint8_t) val2;
    }

    len += len2;

    /*     3      */
    if (UNLIKELY( val3 > UINT24_MAX ))
    {
        len3 = 4;
        ((uint32_t *)(buf + len))[0] = val3;
    }
    else if ( val3 > UINT16_MAX )
    {
        len3 = 3;
        ((uint32_t *)(buf + len))[0] = val3;
    }
    else if ( val3 > UINT8_MAX )
    {
        len3 = 2;
        ((uint16_t *)(buf + len))[0] = (uint16_t) val3;
    }
    else
    {
        len3 = 1;
        buf[len] = (uint8_t) val3;
    }

    len += len3;

    /*     4      */
    if (UNLIKELY( val4 > UINT24_MAX ))
    {
        len4 = 4;
        ((uint32_t *)(buf + len))[0] = val4;
    }
    else if ( val4 > UINT16_MAX )
    {
        len4 = 3;
        ((uint32_t *)(buf + len))[0] = val4;
    }
    else if ( val4 > UINT8_MAX )
    {
        len4 = 2;
        ((uint16_t *)(buf + len))[0] = (uint16_t) val4;
    }
    else
    {
        len4 = 1;
        buf[len] = (uint8_t) val4;
    }

    len += len4;

    /*           */
    target[0] = ((len1 - 1) << 6) | ((len2 - 1) << 4) | ((len3 - 1) << 2) | (len4 - 1);

    return buf + len;
}

/**
 *     buf    ,        4   
 *
 * @param buf            buf
 * @param valueArr         ,         4      
 *
 * @return target     byte
 */
inline const uint8_t *
group_varint_decode_uint32 ( const uint8_t * buf, uint32_t * valueArr)
{
    register uint8_t   idx   = buf[ 0 ];
    const    uint8_t * star1 = buf + 1;
    const    uint8_t * star2 = buf + GROUP_VARINT_IDX_ARR[idx][0];
    const    uint8_t * star3 = buf + GROUP_VARINT_IDX_ARR[idx][1];
    const    uint8_t * star4 = buf + GROUP_VARINT_IDX_ARR[idx][2];

    switch ( GROUP_VARINT_IDX_ARR[idx][3] )
    {
        case 1 : valueArr[ 0 ] = *(uint8_t *)  star1;   break;
        case 2 : valueArr[ 0 ] = *(uint16_t *) star1;   break;
        case 3 : valueArr[ 0 ] = (*(UINT24_T *)star1).value ; break;
        default:
            valueArr[ 0 ] = *(uint32_t *) star1;
    }

    switch ( GROUP_VARINT_IDX_ARR[idx][4] )
    {
        case 1 : valueArr[ 1 ] = *(uint8_t *)  star2;   break;
        case 2 : valueArr[ 1 ] = *(uint16_t *) star2;   break;
        case 3 : valueArr[ 1 ] = (*(UINT24_T *)star2).value; break;
        default:
            valueArr[ 1 ] = *(uint32_t *) star2;
    }

    switch ( GROUP_VARINT_IDX_ARR[idx][5] )
    {
        case 1 : valueArr[ 2 ] = *(uint8_t *)  star3;   break;
        case 2 : valueArr[ 2 ] = *(uint16_t *) star3;   break;
        case 3 : valueArr[ 2 ] = (*(UINT24_T *)star3).value; break;
        default:
            valueArr[ 2 ] = *(uint32_t *) star3;
    }

    switch ( GROUP_VARINT_IDX_ARR[idx][6] )
    {
        case 1 : valueArr[ 3 ] = *(uint8_t *)  star4;   break;
        case 2 : valueArr[ 3 ] = *(uint16_t *) star4;   break;
        case 3 : valueArr[ 3 ] = (*(UINT24_T *)star4).value; break;
        default:
            valueArr[ 3 ] = *(uint32_t *) star4;
    }

    return buf + GROUP_VARINT_IDX_ARR[ idx ][ 7 ];
}

/**             ,            ,      4 uint32 */
inline const uint8_t *
group_varint_decode_uint32_skip ( const uint8_t * buf )
{
    return buf + GROUP_VARINT_IDX_ARR[ buf[ 0 ] ][ 7 ];
}

/**
 *         group varint  ,       2   uint64  
 *
 * @param valueArr                 ,    2   。      
 * @param target          buf .       ,  2 uint64      17 byte
 *
 * @return  target     byte
 */
inline uint8_t *
group_varint_encode_uint64 ( const uint64_t * valueArr, uint8_t * target)
{
    uint32_t arr[ 4 ] = { valueArr[0] >> 32,
                          (valueArr[0] << 32) >> 32,
                          valueArr[1] >> 32,
                          (valueArr[1] << 32) >> 32 };

    return group_varint_encode_uint32( arr, target);

}

inline uint8_t *
group_varint_encode_uint32 ( uint32_t v1,uint32_t v2, uint32_t v3, uint32_t v4, uint8_t * target)
{
    uint32_t valueArr[ 4 ] = {v1, v2 ,v3 ,v4};

    return group_varint_encode_uint32( valueArr, target);
}

inline uint8_t *
group_varint_encode_uint64 ( uint64_t v1, uint64_t v2, uint8_t * target)
{
    uint32_t valueArr[ 4 ] = { v1 >> 32, (v1 << 32) >> 32, v2 >> 32, (v2 << 32) >> 32 };

    return group_varint_encode_uint32( valueArr, target);
}

/**
 *     buf    ,        2 uint64  
 *
 * @param buf            buf
 * @param valueArr         ,         2 uint64     
 *
 * @return buf      byte
 */
inline const uint8_t *
group_varint_decode_uint64 ( const uint8_t * buf, uint64_t * valueArr )
{
    uint32_t int_arr[ 4 ] = {0};

    buf = group_varint_decode_uint32 ( buf, int_arr );

    valueArr[ 0 ] = (((uint64_t)(int_arr[0])) << 32) + int_arr[1];
    valueArr[ 1 ] = (((uint64_t)(int_arr[2])) << 32) + int_arr[3];

    return buf;
}

/**             ,             ,     2   uint64 */
inline const uint8_t *
group_varint_decode_uint64_skip( const uint8_t * buf )
{
    return group_varint_decode_uint32_skip ( buf );
}

/**
 *       zigZag  ,               
 *
 * @param n      
 *
 * @return       
 */
inline uint32_t zigZag_encode32(int32_t  n) { return (n << 1) ^ (n >> 31); }
inline uint64_t zigZag_encode64(int64_t  n) { return (n << 1) ^ (n >> 63); }

/**
 *       zigZag   ,               
 *
 * @param n      
 *
 * @return       
 */
inline int32_t  zigZag_decode32(uint32_t n) { return (n >> 1) ^ -(int32_t)(n & 1); }
inline int64_t  zigZag_decode64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); }

}

#endif /* VARINT_H_ */