From 0705909f4c3cda8786808b2d972394612d311a28 Mon Sep 17 00:00:00 2001 From: xethyrion Date: Tue, 1 Nov 2016 16:52:58 +0200 Subject: [PATCH] Update Almost finished --- STATUS | 21 +++ base58.h | 104 +++++++++++++++ endian.h | 111 ++++++++++++++++ proto-dat | 15 +++ protocols.h | 208 +++++++++++++++++++++++++++++ protoutils.h | 357 ++++++++++++++++++++++++++++++++++++++++++++++++++ varhexutils.h | 186 ++++++++++++++++++++++++++ varint.c | 8 ++ varint.h | 51 ++++++++ 9 files changed, 1061 insertions(+) create mode 100644 STATUS create mode 100644 base58.h create mode 100644 endian.h create mode 100644 proto-dat create mode 100644 protocols.h create mode 100644 protoutils.h create mode 100644 varhexutils.h create mode 100644 varint.c create mode 100644 varint.h diff --git a/STATUS b/STATUS new file mode 100644 index 0000000..bd284c7 --- /dev/null +++ b/STATUS @@ -0,0 +1,21 @@ +STATUS: +Compatibility: Windows/Mac/Linux/Openbsd based systems (probably more) +-Finished Base58.h Encryption/Decryption Algorhytm +-Finished Endian.h Library for automating compiling for Linux/Mac/Windows +-Finished Varhexutils - Different conversion algorhytms between bytes and strings etc. +-Finsihed Varint.h - Conversion from Hex +-Finished Protocols.h - Library for loading protocols & manipulating them easily. +What needs to be done (known so far): + +-Not finished: protoutils.h (performs final byte encodings and checks for validity + +-Not started: Multiaddr.h +(The actual thing that makes everything simple, encapsulating different protocols easily for lower +internet consumption and higher overall efficiency.) (Basically simulating classes from other languages for easy development) + +Other things to do: +Add conversion for bigendian machines (doubt anyone will actually need them tbh but portability was requested.) +Should work on all platforms so far. +Add proper documentation in case anyone needs to add protocols etc. + +So far it's almost finished. diff --git a/base58.h b/base58.h new file mode 100644 index 0000000..f7fc520 --- /dev/null +++ b/base58.h @@ -0,0 +1,104 @@ +#ifndef __BASE58_H__ +#define __BASE58_H__ +#include +#include + + +#define BASE58_DECODE_BASE 0 +#define BASE58_ENCODE_BASE 0 +#define BASE58_DECODE_OUT_OF_RANGE 1 + +void print_array(unsigned char* arr, int len){ + int i = 0; + for (i=0; i=0;j--) + { + tmp = output[j] * 256 + c; + c = tmp/58; + output[j] = tmp%58; + } + } + for(j=0; j=0;j--) + { + tmp = buf[j] * 58 + c; + c = (tmp & (~0xff)) >> 8; + buf[j] = tmp & (0xff); + } + } + + return BASE58_DECODE_BASE; +} +#endif +/*int main() +{ + //char addr[]="1NQEQ7fkCQQiVKDohBGuE3zSYs7xfDobbg"; + char addr[]="Qmaa4Rw81a3a1VEx4LxB7HADUAXvZFhCoRdBzsMZyZmqHD"; + + //char addr[]="5R1"; + //char addr[]="113YAvwi1V9WV9GEykK6XQ1UypmFPhVyh1"; + const int addrLen = sizeof(addr)-1; + //char addr[]="115R"; + //const int addrLen = 4; + const int bufLen = 40; + char buf[bufLen]; + char addr2[addrLen]; + memset(buf,0,bufLen); + printf("%s in Array[i] \BYTES AS HEX:", addr); + print_array(addr,addrLen); + printf("DECODED:"); + base58Decode(addr, addrLen, buf, bufLen); + print_array(buf,bufLen); + + printf("ENCODED:"); + base58Encode(buf, bufLen, addr2, addrLen); + print_array(addr2,addrLen); + + return 0; +}*/ \ No newline at end of file diff --git a/endian.h b/endian.h new file mode 100644 index 0000000..d076b63 --- /dev/null +++ b/endian.h @@ -0,0 +1,111 @@ +#ifndef PORTABLE_ENDIAN_H__ +#define PORTABLE_ENDIAN_H__ + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define be16toh(x) betoh16(x) +# define le16toh(x) letoh16(x) + +# define be32toh(x) betoh32(x) +# define le32toh(x) letoh32(x) + +# define be64toh(x) betoh64(x) +# define le64toh(x) letoh64(x) + +#elif defined(__WINDOWS__) + +# include +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error platform not supported + +#endif + +#endif \ No newline at end of file diff --git a/proto-dat b/proto-dat new file mode 100644 index 0000000..5bc098c --- /dev/null +++ b/proto-dat @@ -0,0 +1,15 @@ +hex-code dec-code size name +84000000000000000000 4 32 ip4 +A9000000000000000000 41 128 ip6 +86000000000000000000 6 16 tcp +91000000000000000000 17 16 udp +A1000000000000000000 33 16 dccp +84810000000000000000 132 16 sctp +AD820000000000000000 301 0 udt +AE820000000000000000 302 0 utp +AA000000000000000000 42 -1 ipfs +E0830000000000000000 480 0 http +BB830000000000000000 443 0 https +DD830000000000000000 477 0 ws +BC830000000000000000 444 10 onion +93820000000000000000 275 0 libp2p-webrtc-star diff --git a/protocols.h b/protocols.h new file mode 100644 index 0000000..03300d6 --- /dev/null +++ b/protocols.h @@ -0,0 +1,208 @@ +#ifndef PROTOCOLS +#define PROTOCOLS + +#include +#include +#include +#include +#include +#include "varhexutils.h" +int CNT_PROTOCOLNUM=0; +struct protocol +{ + char hexcode[21]; + int deccode; + int size; + char name[30]; +}; +struct protocol *protocol_P; //Pointer for holding multiple structures +int protocol_REMOVE_id(int remid)//Function to remove & shift back all data, sort of like c++ vectors. +{ + + if(remid < CNT_PROTOCOLNUM && remid >= 0&&CNT_PROTOCOLNUM!=0) //Checking to see if remid actually exists. + { + for(int i=remid; ihexcode, (protocol_P+i+1)->hexcode); //shift memory to the user we want to remove. + (protocol_P+i)->deccode = (protocol_P+i+1)->deccode; //Same as above + (protocol_P+i)->size = (protocol_P+i+1)->size; //Same as above + strcpy((protocol_P+i)->name, (protocol_P+i+1)->name); //Same as above + }//Overwriting user done. Time to get rid of that extra memory. + protocol_P = (struct protocol*) realloc(protocol_P, (CNT_PROTOCOLNUM-1) * sizeof(struct protocol)); + //Memory erased, + CNT_PROTOCOLNUM--; //Since the record no longer exists, we should decrease the ammount of users. + return 1; //Purely for error checking, in case someone ever wants it/ + } //1 = Success + else + { + if(CNT_PROTOCOLNUM == 0) + { + perror("ERROR: 0 PROTOCOLS... Did you load protocols?"); + } + else + { + perror("ERROR: No such protocol!"); + } + return 0; + } +} +void unload_protocols() +{ + free(protocol_P); +} +void load_protocols() +{ + FILE *FPROC_POINT; //File pointer. + FPROC_POINT = fopen("proto-dat", "r");//Opening proto-dat Or protocols.csv, I just formatted it to my liking. + if(FPROC_POINT != NULL) //While pointer is not null. + { + char W_BUFF[20] = "\0";//Char array to parse file. + for(int i=0; fscanf(FPROC_POINT, "%s", W_BUFF) != EOF; i++) // Scanning file and incrementing for processing. + { + switch(i) + { + case 0: //First word - HEXCODE + { + //ADD MEMORY FOR NEW PROTOCOL + if(CNT_PROTOCOLNUM==0) //If there are no registered protocols yet, allocate memory to pointer. + { + protocol_P = (struct protocol*) malloc (sizeof(struct protocol)); + } + else //Reallocate memory to fit one more protocol + { + protocol_P = (struct protocol*) realloc(protocol_P, (CNT_PROTOCOLNUM+1) * sizeof(struct protocol)); + } + strcpy((protocol_P+CNT_PROTOCOLNUM)->hexcode, W_BUFF); //Copy word to structure at hexcode A hexcode is a string so we keep it as such + break; + } + case 1://Second word - DECCODE + { + (protocol_P+CNT_PROTOCOLNUM)->deccode= atoi(W_BUFF); //Copy word to structure at deccode after converting it to int. + break; + } + case 2://Third word - SIZE + { + (protocol_P+CNT_PROTOCOLNUM)->size= atoi(W_BUFF); //Copy word to structure at size after converting it to int. + break; + } + case 3://Fourth word - NAME + { + strcpy((protocol_P+CNT_PROTOCOLNUM)->name, W_BUFF); //Copy word to structure at name // String + i=-1; + CNT_PROTOCOLNUM++; + break; + } + default: + { + printf("HOUSTON WE HAVE A BIG PROBLEM!!!!\nPROTOCOLS.H-REACHED DEFAULT CASE IN READING FILE!\nREPORT TO SYSTEMS ADMIN!\n"); + break; + } + } + } + fclose(FPROC_POINT); + protocol_REMOVE_id(0); + } + else + { + perror("Fatal Error:"); + } +} +struct protocol * proto_with_name(char proto_w_name[]) //Search for protocol with inputted name +{ + + for(int i=0; iname) == 0) + { + return (protocol_P+i); + } + } + return NULL; +} +struct protocol * proto_with_deccode(int proto_w_deccode) //Search for protocol with inputted deccode +{ + for(int i=0; ideccode == proto_w_deccode) + { + return (protocol_P+i); + } + } +} +void pp() //Purely for debugging purposes, prints the entire loaded protocols. +{ + for(int i=0;i=9) + {printf("=========== ~%d~ ===========\n", i+1);} + else + {printf("=========== ~0%d~ ===========\n", i+1);} + printf(">> HEX-CODE: %s\n", (protocol_P+i)->hexcode); + printf(">> DEC-CODE: %d\n", (protocol_P+i)->deccode); + printf(">> SIZE: %d\n", (protocol_P+i)->size); + printf(">> NAME: %s\n", (protocol_P+i)->name); + } + printf("----------------------------\n"); + printf("TOTAL PROTOCOLS: %d\n",CNT_PROTOCOLNUM); +} +void protocols_with_string(char * meee,int sizi) // NOT FINISHED, DO NOT USE! +{ + int finalsize = 0; + + if(!isalnum(meee[sizi-1]) && !isalnum(meee[sizi-1])) + { + //Everything is alright, it's nul terminated!; + finalsize = sizi; + } + else + { + //Well houston we have a problem. + finalsize = sizi+2; + } + char mestring[finalsize]; + strcpy(mestring, meee); + if(sizi!=finalsize) + { + strcpy(mestring,"\0"); + } + + char * words[50] = { NULL }; + int atword = 0; + int mem = 0; + for(int i=0; i +#include +#include +#include +//IP2INT + +//IPv4 VALIDATOR +#define DELIM "." + +/* return 1 if string contain only digits, else return 0 */ +int valid_digit(char *ip_str) +{ + while (*ip_str) { + if (*ip_str >= '0' && *ip_str <= '9') + ++ip_str; + else + return 0; + } + return 1; +} + +/* return 1 if IP string is valid, else return 0 */ +int is_valid_ipv4(char *ip_str) +{ + int i, num, dots = 0; + char *ptr; + + if (ip_str == NULL) + return 0; + + // See following link for strtok() + // http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok_r.html + ptr = strtok(ip_str, DELIM); + + if (ptr == NULL) + return 0; + + while (ptr) { + + /* after parsing string, it must contain only digits */ + if (!valid_digit(ptr)) + return 0; + + num = atoi(ptr); + + /* check for valid IP */ + if (num >= 0 && num <= 255) { + /* parse remaining string */ + ptr = strtok(NULL, DELIM); + if (ptr != NULL) + ++dots; + } else + return 0; + } + + /* valid IP string must contain 3 dots */ + if (dots != 3) + return 0; + return 1; +} + + +//////////////IPv6 Validator +#define MAX_HEX_NUMBER_COUNT 8 + +int ishexdigit(char ch) +{ + if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F')) + return(1); + return(0); +} + +int is_valid_ipv6(char *str) +{ + int hdcount=0; + int hncount=0; + int err=0; + int packed=0; + + if(*str==':') + { + str++; + if(*str!=':') + return(0); + else + { + packed=1; + hncount=1; + str++; + + if(*str==0) + return(1); + } + } + + if(ishexdigit(*str)==0) + { + return(0); + } + + hdcount=1; + hncount=1; + str++; + + while(err==0&&*str!=0) + { + if(*str==':') + { + str++; + if(*str==':') + { + if(packed==1) + err=1; + else + { + str++; + + if(ishexdigit(*str)||*str==0&&hncountdeccode; + switch(code) + { + case 4://IPv4 + { + if(is_valid_ipv4(abc)) + { + uint64_t iip = ip2int(abc); + strcpy(astb__stringy,Int_To_Hex(iip)); + return astb__stringy; + } + else + { + return "ERR"; + } + break; + } + case 41://IPv6 + { + printf("IP6\n"); + break; + } + case 6: //Tcp + { + printf("TCP!\n"); + break; + } + case 17: //Udp + { + break; + } + case 33://dccp + { + break; + } + case 132://sctp + { + break; + } + case 301://udt + { + break; + } + case 302://utp + { + break; + } + case 42://IPFS - !!! + { + break; + } + case 480://http + { + break; + } + case 443://https + { + break; + } + case 477://ws + { + break; + } + case 444://onion + { + break; + } + case 275://libp2p-webrtc-star + { + break; + } + default: + { + printf("NO SUCH PROTOCOL!\n"); + break; + } + } +} +uint8_t * string_to_bytes(char * strx, size_t strsize) +{ + char str[strsize]; //This string will be bad later. + strcpy(str,strx); + if(str[0] == '/') + { + char * pch; + static char xxx[40] = "\0"; + printf ("Splitting string \"%s\" into tokens:\n",str); + pch = strtok (str,"/"); + load_protocols(); + while (pch != NULL) + { + if(proto_with_name(pch)) + { + struct protocol * protx; + protx = proto_with_name(pch); + char cut[20]="\0"; + strcat(cut,Int_To_Hex(protx->deccode)); + cut[2] = '\0'; + strcat(xxx,cut); + pch = strtok (NULL, "/"); + printf("ADDRESS: %s\n", pch); + if(address_string_to_bytes(protx, pch) != "ERR") + { + } + else + { + return 0; + } + } + else + { + pch = strtok (NULL, "/"); + } + } + unload_protocols(); + printf("S2B_RESULT: %s\n", xxx); + } + else + { + printf("ERROR, Multiaddr needs to start with '/'\n"); + } +} +#endif \ No newline at end of file diff --git a/varhexutils.h b/varhexutils.h new file mode 100644 index 0000000..63db85e --- /dev/null +++ b/varhexutils.h @@ -0,0 +1,186 @@ +#ifndef VARHEXUTILS +#define VARHEXUTILS + +#include +#include +#include "varint.h" +#include +#include +#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[10]) +{ + 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[10] = {0}; + uvarint_encode64(TOV64INPUT, buffy_001, 10); + return buffy_001; +} +uint8_t * Num_To_Varint_32(uint32_t TOV32INPUT) // UINT32_T TO VARINT +{ + static uint8_t buffy_032[10] = {0}; + uvarint_encode32(TOV32INPUT, buffy_032, 10); + return buffy_032; +} +uint64_t * Varint_To_Num_64(uint8_t TON64INPUT[10]) //VARINT TO UINT64_t +{ + static uint64_t varintdecode_001 = 0; + uvarint_decode64(TON64INPUT, 10, &varintdecode_001); + return &varintdecode_001; +} +uint32_t * Varint_To_Num_32(uint8_t TON32INPUT[10]) //VARINT TO UINT32_t +{ + static uint32_t varintdecode_032 = 0; + uvarint_decode32(TON32INPUT, 10, &varintdecode_032); + return &varintdecode_032; +} +// +char * Int_To_Hex(uint64_t int2hex) //VAR[binformat] TO HEX +{ + static char int2hex_result[10]="\0"; + memset(int2hex_result,0,sizeof(int2hex_result)); + sprintf (int2hex_result, "%02lX", int2hex); + return int2hex_result; +} +// +char * Var_To_Hex(uint8_t TOHEXINPUT[10]) //VAR[binformat] TO HEX +{ + static char convert_resultz1[20]="\0"; + memset(convert_resultz1,0,sizeof(convert_resultz1)); + void convert(uint8_t buf[10]) + { + char conv_proc[10]="\0"; + for(int i=0; i < 10; i++) + { + sprintf (conv_proc, "%02X", buf[i]); + //printf("%d:%d\n",i, buf[i]); + strcat(convert_resultz1, conv_proc); + } + } + convert(TOHEXINPUT); + return convert_resultz1; +} +uint8_t * Hex_To_Var(char * Hexstr) //HEX TO VAR[BINFORMAT] +{ + static uint8_t buffy_HEX[10] = {0}; + char codo[20] = "\0"; + strcpy(codo, Hexstr); + char code[3] = "\0"; + int x = 0; + for(int i= 0;i<20;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_HEX[x] = lu; + i++; + x++; + } + return buffy_HEX; +} +// +char * Num_To_HexVar_64(uint64_t TOHVINPUT) //UINT64 TO HEXIFIED VAR +{ //Code to varint - py + static char convert_result[10]="\0";//Note that the hex resulted from this will differ from py + memset(convert_result,0,sizeof(convert_result));//But if you make sure the string is always 20 chars in size + void convert(uint8_t buf[10]) //Both of them read them properly. + { + char conv_proc[10]="\0"; + int i=0; + for(; i < 10; i++) + { + sprintf (conv_proc, "%02X", buf[i]); + //printf("%d:%d\n",i, buf[i]); + strcat(convert_result, conv_proc); + } + } + uint8_t buf[10] = {0}; + uvarint_encode64(TOHVINPUT, buf, 10); + convert(buf); + + return convert_result; +} +char * Num_To_HexVar_32(uint32_t TOHVINPUT) //UINT32 TO HEXIFIED VAR +{ //Code to varint - py + static char convert_result2[20]="\0"; + memset(convert_result2,0,sizeof(convert_result2)); + void convert(uint8_t buf[10]) + { + char conv_proc[10]="\0"; + int i=0; + for(; i < 10; i++) + { + sprintf (conv_proc, "%02X", buf[i]); + printf("%d:%d\n",i, buf[i]); + strcat(convert_result2, conv_proc); + } + } + uint8_t buf[10] = {0}; + uvarint_encode32(TOHVINPUT, buf, 10); + convert(buf); + + return convert_result2; +} + +uint64_t HexVar_To_Num_64(char * theHEXstring) //HEXIFIED VAR TO UINT64_T +{ //Varint to code - py + uint8_t buffy[10] = {0}; + char codo[20] = "\0"; + strcpy(codo, theHEXstring); + char code[3] = "\0"; + int x = 0; + for(int i= 0;i<20;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, 10, &decoded); + return decoded; +} +uint32_t HexVar_To_Num_32(char theHEXstring[]) //HEXIFIED VAR TO UINT32_T +{ //Varint to code py + uint8_t buffy[10] = {0}; + char codo[20] = "\0"; + strcpy(codo, theHEXstring); + char code[2] = "\0"; + int x = 0; + for(int i= 0;i<20;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 \ No newline at end of file diff --git a/varint.c b/varint.c new file mode 100644 index 0000000..a8fd1cc --- /dev/null +++ b/varint.c @@ -0,0 +1,8 @@ +#include "varint.h" + + +DEFN_ENCODER(32) +DEFN_DECODER(32) + +DEFN_ENCODER(64) +DEFN_DECODER(64) \ No newline at end of file diff --git a/varint.h b/varint.h new file mode 100644 index 0000000..69616cc --- /dev/null +++ b/varint.h @@ -0,0 +1,51 @@ +#ifndef VARINT +#define VARINT +#include /* size_t */ +#include /* 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 \ No newline at end of file