From 75f86b4107f87489efcd7b4ebea230cb8e24dd71 Mon Sep 17 00:00:00 2001 From: Jose Marcial Vieira Bisneto Date: Tue, 29 Nov 2016 20:55:59 -0300 Subject: [PATCH] Implemented encode and decode routines in namesys/proquint --- namesys/proquint.c | 163 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 2 deletions(-) diff --git a/namesys/proquint.c b/namesys/proquint.c index a68f90f..6f0a3df 100644 --- a/namesys/proquint.c +++ b/namesys/proquint.c @@ -1,18 +1,177 @@ #include +#include +#include #include "ipfs/namesys/namesys.h" #include "ipfs/cid/cid.h" #include "ipfs/path/path.h" +const uint8_t conse[] = {'b', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'z'}; +const uint8_t vowse[] = {'a', 'i', 'o', 'u'}; + +// Find decoded number from the encoded consonant. +static inline int consd(char c) +{ + int i; + + for (i = 0 ; i < sizeof(conse) ; i++) { + if (c == conse[i]) { + return i; + } + } + + return 0; +} + +// Find decoded number of encoded vowel. +static inline int vowsd(char c) +{ + int i; + + for (i = 0 ; i < sizeof(vowse) ; i++) { + if (c == vowse[i]) { + return i; + } + } + + return 0; +} + +/** +* Tests if a given string is a Proquint identifier +* +* @param {string} str The candidate string. +* +* @return {bool} Whether or not it qualifies. +* @return {error} Error +*/ +int ProquintIsProquint(char *str) +{ + int i, c; + + // if str is null, or length isn't 11 or don't have - at middle + if (!str || strlen(str) != 11 || str[5] != '-') { + return 0; // it's not a proquint + } + + // run every position + for (i = 0 ; i < 11 ; i++) { + if (i == 5) i++; // skip -, already tested. + switch (i) { + case 1: + case 3: + case 7: + case 9: + // compare with vowse array + c = vowsd(str[i]); + if (str[i] != vowse[c]) { + return 0; // it's not a proquint + } + break; + default: // 0,2,4,6,8,10 + // compare with conse array + c = consd(str[i]); + if (str[i] != conse[c]) { + return 0; // it's not a proquint + } + } + } + + return 1; // passed on every value. +} + +/** +* Encodes an arbitrary byte slice into an identifier. +* +* @param {[]byte} buf Slice of bytes to encode. +* +* @return {string} The given byte slice as an identifier. +*/ +char *ProquintEncode(char *buf) +{ + // TODO: check endianness. + char *ret; + int i, c; + uint16_t n; + + if (!buf) { + return NULL; + } + + ret = malloc(12); + if (!ret) { + return NULL; + } + + for (i = 0, c = 0; i < 4; i += 2) { + n = ((buf[i] & 0xff) << 8) | (buf[i + 1] & 0xff); + + ret[c++] = conse[(n >> 12) & 0x0f]; + ret[c++] = vowse[(n >> 10) & 0x03]; + ret[c++] = conse[(n >> 6) & 0x0f]; + ret[c++] = vowse[(n >> 4) & 0x03]; + ret[c++] = conse[n & 0x0f]; + ret[c++] = '-'; + } + ret[--c] = '\0'; + + return ret; +} + +/** +* Decodes an identifier into its corresponding byte slice. +* +* @param {string} str Identifier to convert. +* +* @return {[]byte} The identifier as a byte slice. +*/ +char *ProquintDecode(char *str) +{ + // TODO: check endianness. + char *ret; + int i, c; + uint16_t x; + + // make sure its a valid Proquint string. + if (!ProquintIsProquint(str)) { + return NULL; + } + + ret = malloc(4); + if (!ret) { + return NULL; + } + + for (i = 0, c = 0 ; i < 11 ; i += 6) { + x =(consd(str[i + 0]) << 12) | \ + (vowsd(str[i + 1]) << 10) | \ + (consd(str[i + 2]) << 6) | \ + (vowsd(str[i + 3]) << 4) | \ + (consd(str[i + 4]) << 0); + + ret[c++] = x >> 8; + ret[c++] = x & 0xff; + } + + return ret; +} + // resolveOnce implements resolver. Decodes the proquint string. int ProquintResolveOnce (char **p, char *name) { - int err = proquintIsProquint(name); + int err = ProquintIsProquint(name); + char buf[500]; if (err) { *p = NULL; err = ErrInvalidProquint; } else { - err = pathFromString(p, proquintDecode(name)); + err = ParsePath(buf, ProquintDecode(name)); + if (!err) { + *p = malloc (strlen(buf) + 1); + if (p) { + strcpy(*p, buf); + } + } } return err; }