//***************************************************************************
// This source code is copyrighted 2002 by Google Inc.  All rights
// reserved.  You are given a limited license to use this source code for
// purposes of participating in the Google programming contest.  If you
// choose to use or distribute the source code for any other purpose, you
// must either (1) first obtain written approval from Google, or (2)
// prominently display the foregoing copyright notice and the following
// warranty and liability disclaimer on each copy used or distributed.
// 
// The source code and repository (the "Software") is provided "AS IS",
// with no warranty, express or implied, including but not limited to the
// implied warranties of merchantability and fitness for a particular
// use.  In no event shall Google Inc. be liable for any damages, direct
// or indirect, even if advised of the possibility of such damages.
//***************************************************************************


#include <string>
#include <limits.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/param.h>
#include "goo-netutil.h"

int Encoder::varint32_length(uint32 v) {
  return Varint::Length32(v);
}

int Encoder::varint64_length(uint64 v) {
  return Varint::Length64(v);
}

// Special optimized version: does not use Varint
bool Decoder::get_varint32(uint32* v) {
  uint32 result;
  unsigned char byte;
  const unsigned char* ptr = buf_;
  const unsigned char* limit = limit_;
  if (Encoder::kVarintMax32 == 5 && ptr + Encoder::kVarintMax32 < limit) {
    // Byte 1
    result = *(ptr++);
    if (result < 128) { buf_ = ptr; *v = result; return true; }
    result &= 127;

    // Byte 2
    byte = *(ptr++);
    result |= static_cast<uint32>(byte & 127) << 7;
    if ((byte & 128) == 0) { buf_ = ptr; *v = result; return true; }
    
    // Byte 3
    byte = *(ptr++);
    result |= static_cast<uint32>(byte & 127) << 14;
    if ((byte & 128) == 0) { buf_ = ptr; *v = result; return true; }
    
    // Byte 4
    byte = *(ptr++);
    result |= static_cast<uint32>(byte & 127) << 21;
    if ((byte & 128) == 0) { buf_ = ptr; *v = result; return true; }
    
    // Byte 5
    byte = *(ptr++);
    result |= static_cast<uint32>(byte & 127) << 28;
    buf_ = ptr; 
    *v = result; 
    return ((byte & 128) == 0);  // We're done, whether we succeeded or not
    
  } else {
    // A slow path when we are near the end of the decoding buffer.
    int shift = 0;        // How much to shift next set of bits
    result = 0;
    do {
      if ((shift >= 32) || (ptr >= limit_)) {
        // Out of range
        return false;
      }

      // Get 7 bits from next byte
      byte = *(ptr++);
      result |= static_cast<uint32>(byte & 127) << shift;
      shift += 7;
    } while ((byte & 128) != 0);
    buf_ = ptr;
    *v = result;
    return true;
  }
}

// Special optimized version: does not use Varint
bool Decoder::get_varint64(uint64* v) {
  uint64 result = 0;
  int shift = 0;        // How much to shift next set of bits
  unsigned char byte;
  do {
    if ((shift >= 64) || (buf_ >= limit_)) {
      // Out of range
      return false;
    }

    // Get 7 bits from next byte
    byte = *(buf_++);
    result |= static_cast<uint64>(byte & 127) << shift;
    shift += 7;
  } while ((byte & 128) != 0);
  *v = result;
  return true;
}

