Compare commits

..

10 commits

Author SHA1 Message Date
Agorise
95026b5d1e
Update LICENSE 2019-01-01 10:38:33 -06:00
Agorise
63e06fdf51
Update LICENSE 2018-06-17 16:32:11 +03:00
Agorise
c5f25eec89
Update LICENSE 2017-11-15 13:15:24 +02:00
Agorise
8c7931ea02 Update LICENSE 2017-10-16 14:03:00 +03:00
ken Code
1ee736809a Update LICENSE 2017-01-31 17:12:24 +01:00
xethyrion
6d305686f2 Update README.md 2016-11-25 02:29:30 +02:00
xethyrion
7a95f93924 Not sure if we really need DEEP_EQUAL here. 2016-11-25 02:26:06 +02:00
xethyrion
8a1240e802 Update README.md 2016-11-24 20:08:25 +02:00
xethyrion
2faf9ceb2c Update README.md 2016-11-24 20:08:09 +02:00
xethyrion
90e935af6e Add files via upload 2016-11-24 20:07:19 +02:00
9 changed files with 680 additions and 8 deletions

View file

@ -1,6 +1,9 @@
MIT License
Copyright (c) 2016 BitShares Munich IVS
Copyright (c) 2019 AGORISE, LTD.
An International Business Company, Cyprus Reg# ΗΕ375959
Contains works from BitShares Munich IVS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,2 +1,9 @@
# c-ipld
Implementation of the IPLD spec in C.
### A very simple tutorial is available in ipld_tut.c
### The header has every function documented.
## Uncertain To Do:
------
#### * Formatting links as such: foo/bar : {}
#### * Deep searching nodes

201
base58.c Normal file
View file

@ -0,0 +1,201 @@
/*
* Copyright 2012-2014 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <sys/types.h>
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
static const int8_t b58digits_map[] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
-1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
-1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
};
/**
* convert a base58 encoded string into a binary array
* @param b58 the base58 encoded string
* @param base58_size the size of the encoded string
* @param bin the results buffer
* @param binszp the size of the results buffer
* @returns true(1) on success
*/
int libp2p_crypto_encoding_base58_decode(const char* b58, size_t base58_size, unsigned char** bin, size_t* binszp)
{
size_t binsz = *binszp;
const unsigned char* b58u = (const void*)b58;
unsigned char* binu = *bin;
size_t outisz = (binsz + 3) / 4;
uint32_t outi[outisz];
uint64_t t;
uint32_t c;
size_t i, j;
uint8_t bytesleft = binsz % 4;
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
unsigned zerocount = 0;
size_t b58sz;
b58sz = strlen(b58);
memset(outi, 0, outisz * sizeof(*outi));
// Leading zeros, just count
for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) {
++zerocount;
}
for (; i < b58sz; ++i) {
if (b58u[i] & 0x80) {
// High-bit set on invalid digit
return 0;
}
if (b58digits_map[b58u[i]] == -1) {
// Invalid base58 digit
return 0;
}
c = (unsigned)b58digits_map[b58u[i]];
for (j = outisz; j--;) {
t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff;
}
if (c) {
// Output number too big (carry to the next int32)
memset(outi, 0, outisz * sizeof(*outi));
return 0;
}
if (outi[0] & zeromask) {
// Output number too big (last int32 filled too far)
memset(outi, 0, outisz * sizeof(*outi));
return 0;
}
}
j = 0;
switch (bytesleft) {
case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16;
case 2:
*(binu++) = (outi[0] & 0xff00) >> 8;
case 1:
*(binu++) = (outi[0] & 0xff);
++j;
default:
break;
}
for (; j < outisz; ++j) {
*(binu++) = (outi[j] >> 0x18) & 0xff;
*(binu++) = (outi[j] >> 0x10) & 0xff;
*(binu++) = (outi[j] >> 8) & 0xff;
*(binu++) = (outi[j] >> 0) & 0xff;
}
// Count canonical base58 byte count
binu = *bin;
for (i = 0; i < binsz; ++i) {
if (binu[i]) {
break;
}
--*binszp;
}
*binszp += zerocount;
memset(outi, 0, outisz * sizeof(*outi));
return 1;
}
/**
* encode an array of bytes into a base58 string
* @param binary_data the data to be encoded
* @param binary_data_size the size of the data to be encoded
* @param base58 the results buffer
* @param base58_size the size of the results buffer
* @returns true(1) on success
*/
//int libp2p_crypto_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char* base58, size_t* base58_size)
int libp2p_crypto_encoding_base58_encode(const unsigned char* data, size_t binsz, unsigned char** b58, size_t* b58sz)
{
const uint8_t* bin = data;
int carry;
ssize_t i, j, high, zcount = 0;
size_t size;
while (zcount < (ssize_t)binsz && !bin[zcount]) {
++zcount;
}
size = (binsz - zcount) * 138 / 100 + 1;
uint8_t buf[size];
memset(buf, 0, size);
for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) {
for (carry = bin[i], j = size - 1; (j > high) || carry; --j) {
carry += 256 * buf[j];
buf[j] = carry % 58;
carry /= 58;
}
}
for (j = 0; j < (ssize_t)size && !buf[j]; ++j)
;
if (*b58sz <= zcount + size - j) {
*b58sz = zcount + size - j + 1;
memset(buf, 0, size);
return 0;
}
if (zcount) {
memset(b58, '1', zcount);
}
for (i = zcount; j < (ssize_t)size; ++i, ++j) {
(*b58)[i] = b58digits_ordered[buf[j]];
}
(*b58)[i] = '\0';
*b58sz = i + 1;
memset(buf, 0, size);
return 1;
}
/***
* calculate the size of the binary results based on an incoming base58 string
* @param base58_string the string
* @returns the size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_size(const unsigned char* base58_string) {
size_t string_length = strlen((char*)base58_string);
size_t decoded_length = 0;
size_t radix = strlen(b58digits_ordered);
double bits_per_digit = log2(radix);
decoded_length = floor(string_length * bits_per_digit / 8);
return decoded_length;
}
/**
* calculate the max length in bytes of an encoding of n source bits
* @param base58_string the string
* @returns the maximum size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_max_size(const unsigned char* base58_string) {
size_t string_length = strlen((char*)base58_string);
size_t decoded_length = 0;
size_t radix = strlen(b58digits_ordered);
double bits_per_digit = log2(radix);
decoded_length = ceil(string_length * bits_per_digit / 8);
return decoded_length;
}

47
base58.h Normal file
View file

@ -0,0 +1,47 @@
//
// base58.h
// libp2p_xcode
//
// Created by John Jones on 11/7/16.
// Copyright © 2016 JMJAtlanta. All rights reserved.
//
#ifndef base58_h
#define base58_h
#include "varint.h"
/**
* convert a base58 encoded string into a binary array
* @param base58 the base58 encoded string
* @param base58_size the size of the encoded string
* @param binary_data the results buffer
* @param binary_data_size the size of the results buffer
* @returns true(1) on success
*/
int libp2p_crypto_encoding_base58_decode(const unsigned char* base58, size_t base58_size, unsigned char** binary_data, size_t *binary_data_size);
/**
* encode an array of bytes into a base58 string
* @param binary_data the data to be encoded
* @param binary_data_size the size of the data to be encoded
* @param base58 the results buffer
* @param base58_size the size of the results buffer
* @returns true(1) on success
*/
int libp2p_crypto_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char** base58, size_t* base58_size);
/***
* calculate the size of the binary results based on an incoming base58 string with no initial padding
* @param base58_string the string
* @returns the size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_size(const unsigned char* base58_string);
/**
* calculate the max length in bytes of an encoding of n source bits
* @param base58_string the string
* @returns the maximum size in bytes had the string been decoded
*/
size_t libp2p_crypto_encoding_base58_decode_max_size(const unsigned char* base58_string);
#endif /* base58_h */

49
ipld.h
View file

@ -5,12 +5,13 @@
#include <stdio.h>
#include <string.h>
#include <jansson.h>
#include "base58.h"
#include "varhexutils.h"
//Predefined values:
#define IDKey "@id"
#define TypeKey "@type"
#define ValueKey "@value"
#define CtxKey "@context"
#define CtxKey "@/home/xethyrion/Desktop/Bak/varint.hcontext"
#define CodecKey "@codec"
#define LinkKey "mlink"
@ -28,7 +29,7 @@ struct NODE
/* LOAD_NODE(@param1)
* Creates a new node from a string.
* @Param1 a json string(char *)
* returns a json_t object! (jansson.h)
* returns a json_t /home/xethyrion/Desktop/Bak/varint.hobject! (jansson.h)
*/
struct NODE LOAD_NODE(char * str)
{
@ -275,9 +276,9 @@ void lType(char * str, struct LINK O)
}
}
/* lType(@param1,@param2)
* Gets the type of the link, of course, it should be an mlink.
* @param1: LINK.type //Storing in type from LINK struct.
/* lHash(@param1,@param2)
* Gets the hash of the link, not b58 decoded
* @param1: LINK.hash //Storing in hash from LINK struct.
* @param2: LINK // The link structure we are using.
*/
void lHash(char * str, struct LINK O)
@ -323,7 +324,40 @@ void lName(char * str, struct LINK O)
strcat(str, key);
}
}
/*B58Hash(@param1, @parunsigned char** binary_dataam2)
*Decodes the hash, and stores it into a char from your link struct
*/
void lb58Hash(char * str, struct LINK X) //Need to find out if prefixed or not!
{
char * hash = X.hash;
size_t hash_length = strlen(hash);
size_t result_buffer_length = libp2p_crypto_encoding_base58_decode_max_size(hash);
unsigned char result_buffer[result_buffer_length];
unsigned char * ptr_2_result = result_buffer;
memset(result_buffer, 0, result_buffer_length);
int valid = libp2p_crypto_encoding_base58_decode(hash,hash_length,&ptr_2_result, &result_buffer_length);
printf("IS_VALID: %d\n",valid);
char HReadable[1000];
bzero(HReadable,1000);
int ilen = 0;
for(int i = 0; i<result_buffer_length;i++)
{
unsigned char c = ptr_2_result[i];
char miu[3];
bzero(miu,3);
sprintf(miu,"%02x",c);
miu[3] = '\0';
strcat(HReadable, miu);
}
//DEBUG
if(NODE_H_DEBUG == 1)
{
printf("Normal hash: %s\n", hash);
printf("Result: %s\n", HReadable);
}
strcat(str, HReadable);
}
/* LOAD_LINK(@param1)
* Creates a new LINK from a string.
* @Param1 a json string(char *)
@ -344,6 +378,7 @@ struct LINK LOAD_LINK(char * str)
lName(X.name, X);
lType(X.type, X);
lHash(X.hash, X);
lb58Hash(X.b58hash, X);
return X;
}
/* Unload_LINK(@param1) - Same as unload_node, makes it easier to avoid leaks and better structuring of your programs

69
ipld_tut.c Normal file
View file

@ -0,0 +1,69 @@
#include "ipld.h"
int main()
{
//TURN DEBUG MODE ON/OFF
NODE_H_DEBUG = 0;
//Load a node from string:
char * str = "{\"@context\": \"/ipfs/Qmf1ec6n9f8kW8JTLjqaZceJVpDpZD4L3aPoJFvssBE7Eb/merkleweb\", \"@type\": \"node\", \"FIELD1\": { \"@value\": \"Qmf1ec6n9f8kW8JTLjqaZceJVpDpZD4L3aPoJFvssBE7Eb\", \"@type\": \"mlink\" }, \"FIELD2\": { \"@value\": \"Qmf1ec6n9f8kW8JTLjqaZceJVpDpZD4L3aPoJFvssBE7Eb\", \"@type\": \"mlink\" } }";
struct NODE A;
A = LOAD_NODE(str);
//Get node contents back to a string:
char * lol;
lol = json_dumps(A.obj, JSON_INDENT(1) | JSON_PRESERVE_ORDER);
printf("NODE CONTENTS: \n------------\n%s\n------------\n", lol);
free(lol); // Never forget to free the char * after being done with it.
//Get type of node, if any.
char typeget[1000]; //Way bigger than needed.
bzero(typeget,1000); //No mem errors ofc.
nType(typeget, A.obj);//Check for type if any
printf("type: %s\n", typeget);
//Get context of node.
char ctxget[1000]; //Way bigger than needed
bzero(ctxget, 1000);
nContext(ctxget, A.obj);
printf("ctx: %s\n", ctxget);
//Extracting Links
char * links[666];
for(int i=0;i<666;i++){ links[i] = NULL;}
size_t linknum;
linknum = nLinks(links, A.obj); //These all need to be freed, hence the linknum!
printf("Linknum: %lu\n", linknum);
for(int i=0; i<linknum; i++)
{
printf("AT %d %s\n",i,links[i]);
}
//Store links in an more accessible version:
struct LINK L;
L = LOAD_LINK(links[0]);
//By now you already have easy access to everything, the key name, the hash, the b58 decoded hash, the type.
//It will reject any links which aren't of type "mlink", you should check this by seeing if it returns valid or not.
char * linkstr;
linkstr = json_dumps(L.obj, JSON_INDENT(1) | JSON_PRESERVE_ORDER);
printf("LINK CONTENTS: \n------------\n%s\n------------\n", linkstr);
free(linkstr);
//Access Name
printf("LINK NAME:\t%s\n", L.name);
//Access Type
printf("LINK TYPE:\t%s\n", L.type);
//Access Hash
printf("LINK HASH:\t%s\n", L.hash);
//Access b58Hash
printf("LINK B58HASH:\t%s\n", L.b58hash);
//Free all nodes, links, link pointer array
for(int i=0; i<linknum;i++){free(links[i]);} //FREE(Link char pointer array)
UNLOAD_LINK(L); // FREE LINK STRUCTURE
UNLOAD_NODE(A); // FREE NODE STRUCTURE // You could've done this earlier as soon as you didn't need any more.
return 0;
}

251
varhexutils.h Normal file
View file

@ -0,0 +1,251 @@
#ifndef VARHEXUTILS
#define VARHEXUTILS
#include <stdio.h>
#include <inttypes.h>
#include "varint.h"
#include <stdlib.h>
#include <string.h>
#include "endian.h"
/*uint8_t * encode_big_endian_32(uint32_t ebex32)
{
uint8_t encbe[10] = {0};
memcpy(encbe, htobe32(ebex32));
return encbe;
}*/
int8_t Var_Bytes_Count(uint8_t * countbytesofthis)
{
static int8_t xrzk_bytescnt = 0;
for(int8_t i=0; i<10; i++)
{
if(countbytesofthis[i] != 0)
{
xrzk_bytescnt++;
}
}
return xrzk_bytescnt;
}
uint8_t * Num_To_Varint_64(uint64_t TOV64INPUT) //UINT64_T TO VARINT
{
static uint8_t buffy_001[60] = {0};
uvarint_encode64(TOV64INPUT, buffy_001, 60);
return buffy_001;
}
uint8_t * Num_To_Varint_32(uint32_t TOV32INPUT) // UINT32_T TO VARINT
{
static uint8_t buffy_032[60] = {0};
uvarint_encode32(TOV32INPUT, buffy_032, 60);
return buffy_032;
}
uint64_t * Varint_To_Num_64(uint8_t TON64INPUT[60]) //VARINT TO UINT64_t
{
static uint64_t varintdecode_001 = 0;
uvarint_decode64(TON64INPUT, 60, &varintdecode_001);
return &varintdecode_001;
}
uint32_t * Varint_To_Num_32(uint8_t TON32INPUT[60]) //VARINT TO UINT32_t
{
static uint32_t varintdecode_032 = 0;
uvarint_decode32(TON32INPUT, 60, &varintdecode_032);
return &varintdecode_032;
}
//
char * Int_To_Hex(uint64_t int2hex) //VAR[binformat] TO HEX
{
static char int2hex_result[800]="\0";
memset(int2hex_result,0,sizeof(int2hex_result));
sprintf (int2hex_result, "%02lX", int2hex);
return int2hex_result;
}
uint64_t Hex_To_Int(char * hax)
{
char * hex = NULL;
hex=hax;
uint64_t val = 0;
while (*hex)
{
// get current character then increment
uint8_t byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
//
void vthconvert(int size, char * crrz01, uint8_t * xbuf)
{
uint8_t buf[400];
bzero(buf,400);
//fixing the buf
for(int cz=0; cz<size;cz++)
{
buf[cz] = xbuf[cz];
}
//
if(crrz01!=NULL)
{
char * crrz1 = NULL;
crrz1 = crrz01;
char conv_proc[800]="\0";
int i;
for(i=0; i < (size*2); i++)
{
if(buf[i]!='\0')
{
sprintf (conv_proc, "%02X", buf[i]);
//printf("%d:%d\n",i, buf[i]);
strcat(crrz1, conv_proc);
}
}
crrz1 = NULL;
}
}
char * Var_To_Hex(int realsize, uint8_t * TOHEXINPUT) //VAR[binformat] TO HEX
{
for(int ix=realsize;ix<400;ix++)
{
TOHEXINPUT[ix] = '\0';
}
if(TOHEXINPUT != NULL)
{
static char convert_resultz1[800]="\0";
bzero(convert_resultz1,800);
vthconvert(realsize, convert_resultz1, TOHEXINPUT);
return convert_resultz1;
}
}
uint8_t * Hex_To_Var(char * Hexstr) //HEX TO VAR[BINFORMAT]
{
static uint8_t buffy_HEX[400] = {0};
bzero(buffy_HEX,400);
int i;
char codo[800] = "\0";
bzero(codo,800);
strcpy(codo, Hexstr);
char code[3];
bzero(code,3);
code[3]='\0';
int x = 0;
int fori001=0;
for(fori001=0;fori001<800;fori001++)
{
strncpy(&code[0],&codo[fori001],1);
strncpy(&code[1],&codo[fori001+1],1);
char *ck = NULL;
uint64_t lu = 0;
lu=strtoul(code, &ck, 16);
buffy_HEX[x] = lu;
//printf("%s - %lu\n",code,lu);
fori001++;
x++;
}
return buffy_HEX;
}
//
void convert(char * convert_result, uint8_t * buf) //Both of them read them properly.
{
char conv_proc[800]="\0";
bzero(conv_proc,800);
int i;
for(i=0; i < 10; i++)
{
sprintf (conv_proc, "%02X", buf[i]);
//printf("%d:%d\n",i, buf[i]);
strcat(convert_result, conv_proc);
}
}
char * Num_To_HexVar_64(uint64_t TOHVINPUT) //UINT64 TO HEXIFIED VAR
{ //Code to varint - py
static char convert_result[800]="\0";//Note that the hex resulted from this will differ from py
bzero(convert_result,800);
memset(convert_result,0,sizeof(convert_result));//But if you make sure the string is always 20 chars in size
uint8_t buf[400] = {0};
bzero(buf,400);
uvarint_encode64(TOHVINPUT, buf, 800);
convert(convert_result,buf);
return convert_result;
}
void convert2(char * convert_result2, uint8_t * bufhx)
{
uint8_t * buf = NULL;
buf = bufhx;
char conv_proc[3]="\0";
conv_proc[3] = '\0';
bzero(conv_proc, 3);
int i;
for(i=0; i == 0; i++)
{
sprintf (conv_proc, "%02X", buf[i]);
//printf("aaaaaaaaaaah%d:%d\n",i, buf[i]);
strcat(convert_result2, conv_proc);
}
buf = NULL;
}
char * Num_To_HexVar_32(uint32_t TOHVINPUT) //UINT32 TO HEXIFIED VAR
{ //Code to varint - py
static char convert_result2[3]="\0";
bzero(convert_result2,3);
convert_result2[2] = '\0';
memset(convert_result2,0,sizeof(convert_result2));
uint8_t buf[1] = {0};
bzero(buf,1);
uvarint_encode32(TOHVINPUT, buf, 1);
convert2(convert_result2,buf);
return convert_result2;
}
uint64_t HexVar_To_Num_64(char * theHEXstring) //HEXIFIED VAR TO UINT64_T
{ //Varint to code - py
uint8_t buffy[400] = {0};
char codo[800] = "\0";
bzero(codo,800);
strcpy(codo, theHEXstring);
char code[3] = "\0";
int x = 0;
for(int i= 0;i<399;i++)
{
strncpy(&code[0],&codo[i],1);
strncpy(&code[1],&codo[i+1],1);
char *ck = NULL;
uint64_t lu = 0;
lu=strtoul(code, &ck, 16);
buffy[x] = lu;
i++;
x++;
}
static uint64_t decoded;
uvarint_decode64 (buffy, 400, &decoded);
return decoded;
}
uint32_t HexVar_To_Num_32(char theHEXstring[]) //HEXIFIED VAR TO UINT32_T
{ //Varint to code py
uint8_t buffy[400] = {0};
bzero(buffy,400);
char codo[800] = "\0";
bzero(codo,800);
strcpy(codo, theHEXstring);
char code[3] = "\0";
bzero(code,3);
code[3] = '\0';
int x = 0;
for(int i= 0;i<399;i++)
{
strncpy(&code[0],&codo[i],1);
strncpy(&code[1],&codo[i+1],1);
char *ck = NULL;
uint32_t lu = {0};
lu=strtoul(code, &ck, 16);
buffy[x] = lu;
i++;
x++;
}
static uint32_t decoded;
uvarint_decode32 (buffy, 10, &decoded);
return decoded;
}
#endif

8
varint.c Normal file
View file

@ -0,0 +1,8 @@
#include "varint.h"
DEFN_ENCODER(32)
DEFN_DECODER(32)
DEFN_ENCODER(64)
DEFN_DECODER(64)

51
varint.h Normal file
View file

@ -0,0 +1,51 @@
#ifndef VARINT
#define VARINT
#include <stddef.h> /* size_t */
#include <stdint.h> /* uint8_t, uint64_t */
#define DEFN_ENCODER(SIZE) \
size_t \
uvarint_encode##SIZE (uint##SIZE##_t val, uint8_t buf[], size_t bufsize) \
{ \
size_t i = 0; \
for (; i < (SIZE/8) && i < bufsize; i++) { \
buf[i] = (uint8_t) ((val & 0xFF) | 0x80); \
val >>= 7; \
if (!val) \
return i + 1; \
} \
return -1; \
}
#define DEFN_DECODER(SIZE) \
size_t \
uvarint_decode##SIZE (uint8_t buf[], size_t bufsize, uint##SIZE##_t *val) \
{ \
*val = 0; \
size_t i = 0; \
for (; i < (SIZE/8) && i < bufsize; i++) { \
*val |= ((buf[i] & 0x7f) << (7 * i)); \
if (!(buf[i] & 0x80)) \
return i + 1; \
} \
return -1; \
}
#define DECL_ENCODER(SIZE) \
size_t \
uvarint_encode##SIZE (uint##SIZE##_t val, uint8_t buf[], size_t bufsize);
#define DECL_DECODER(SIZE) \
size_t \
uvarint_decode##SIZE (uint8_t buf[], size_t bufsize, uint##SIZE##_t *val);
DECL_ENCODER(32)
DECL_DECODER(32)
DECL_ENCODER(64)
DECL_DECODER(64)
#endif