Commit aeb5ee5a by David Turner Committed by David Turner

varint: Add varint encoding/decoding

This code is ported from git.git

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: David Turner <dturner@twopensource.com>
parent 26a8617d
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "varint.h"
uintmax_t git_decode_varint(const unsigned char *bufp, size_t *varint_len)
{
const unsigned char *buf = bufp;
unsigned char c = *buf++;
uintmax_t val = c & 127;
while (c & 128) {
val += 1;
if (!val || MSB(val, 7)) {
/* This is not a valid varint_len, so it signals
the error */
*varint_len = 0;
return 0; /* overflow */
}
c = *buf++;
val = (val << 7) + (c & 127);
}
*varint_len = buf - bufp;
return val;
}
int git_encode_varint(unsigned char *buf, size_t bufsize, uintmax_t value)
{
unsigned char varint[16];
unsigned pos = sizeof(varint) - 1;
varint[pos] = value & 127;
while (value >>= 7)
varint[--pos] = 128 | (--value & 127);
if (buf) {
if (bufsize < pos)
return -1;
memcpy(buf, varint + pos, sizeof(varint) - pos);
}
return sizeof(varint) - pos;
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_varint_h__
#define INCLUDE_varint_h__
#include <stdint.h>
extern int git_encode_varint(unsigned char *, size_t, uintmax_t);
extern uintmax_t git_decode_varint(const unsigned char *, size_t *);
#endif
#include "clar_libgit2.h"
#include "varint.h"
void test_core_encoding__decode(void)
{
const unsigned char *buf = (unsigned char *)"AB";
size_t size;
cl_assert(git_decode_varint(buf, &size) == 65);
cl_assert(size == 1);
buf = (unsigned char *)"\xfe\xdc\xbaXY";
cl_assert(git_decode_varint(buf, &size) == 267869656);
cl_assert(size == 4);
buf = (unsigned char *)"\xaa\xaa\xfe\xdc\xbaXY";
cl_assert(git_decode_varint(buf, &size) == 1489279344088ULL);
cl_assert(size == 6);
buf = (unsigned char *)"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xfe\xdc\xbaXY";
cl_assert(git_decode_varint(buf, &size) == 0);
cl_assert(size == 0);
}
void test_core_encoding__encode(void)
{
unsigned char buf[100];
cl_assert(git_encode_varint(buf, 100, 65) == 1);
cl_assert(buf[0] == 'A');
cl_assert(git_encode_varint(buf, 100, 267869656) == 4);
cl_assert(!memcmp(buf, "\xfe\xdc\xbaX", 4));
cl_assert(git_encode_varint(buf, 100, 1489279344088ULL) == 6);
cl_assert(!memcmp(buf, "\xaa\xaa\xfe\xdc\xbaX", 6));
cl_assert(git_encode_varint(buf, 1, 1489279344088ULL) == -1);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment