X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=lib%2Futils.c;h=33e55c7eadfe9338b36715f29fcb905e4e701a64;hb=59c94590b849529da4021750018833221bdfab5b;hp=27344100f3aa8a1d1a7c2c516dcc1a6db20c19de;hpb=d422fdfd62d851b345562ad4d093465d2bec604b;p=ashd.git diff --git a/lib/utils.c b/lib/utils.c index 2734410..33e55c7 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -26,6 +26,26 @@ #endif #include +static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static int base64rev[] = { + -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, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -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, -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, -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, +}; + void _sizebuf(struct buffer *buf, size_t wanted, size_t el) { size_t n; @@ -163,6 +183,8 @@ void freeca(char **ca) { char **c; + if(ca == NULL) + return; for(c = ca; *c; c++) free(*c); free(ca); @@ -201,3 +223,246 @@ void bprintf(struct charbuf *buf, char *format, ...) bvprintf(buf, format, args); va_end(args); } + +void replstr(char **p, char *n) +{ + char *tmp; + + tmp = *p; + if(n) + *p = sstrdup(n); + else + *p = NULL; + if(tmp) + free(tmp); +} + +char *base64encode(char *data, size_t datalen) +{ + struct charbuf buf; + + if(datalen == 0) + return(sstrdup("")); + bufinit(buf); + while(datalen >= 3) + { + bufadd(buf, base64set[(data[0] & 0xfc) >> 2]); + bufadd(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]); + bufadd(buf, base64set[((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6)]); + bufadd(buf, base64set[data[2] & 0x3f]); + datalen -= 3; + data += 3; + } + if(datalen == 1) + { + bufadd(buf, base64set[(data[0] & 0xfc) >> 2]); + bufadd(buf, base64set[(data[0] & 0x03) << 4]); + bufcat(buf, "==", 2); + } + if(datalen == 2) + { + bufadd(buf, base64set[(data[0] & 0xfc) >> 2]); + bufadd(buf, base64set[((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4)]); + bufadd(buf, base64set[(data[1] & 0x0f) << 2]); + bufadd(buf, '='); + } + bufadd(buf, 0); + return(buf.b); +} + +char *base64decode(char *data, size_t *datalen) +{ + int b, c; + char cur; + struct charbuf buf; + + bufinit(buf); + cur = 0; + b = 8; + for(; *data > 0; data++) + { + c = (int)(unsigned char)*data; + if(c == '=') + break; + if(c == '\n') + continue; + if(base64rev[c] == -1) + { + buffree(buf); + return(NULL); + } + b -= 6; + if(b <= 0) + { + cur |= base64rev[c] >> -b; + bufadd(buf, cur); + b += 8; + cur = 0; + } + cur |= base64rev[c] << b; + } + if(datalen != NULL) + *datalen = buf.d; + bufadd(buf, 0); + return(buf.b); +} + +static int btheight(struct btree *tree) +{ + if(tree == NULL) + return(0); + return(tree->h); +} + +static void btsetheight(struct btree *tree) +{ + if(tree == NULL) + return; + tree->h = max(btheight(tree->l), btheight(tree->r)) + 1; +} + +static void bbtrl(struct btree **tree); + +static void bbtrr(struct btree **tree) +{ + struct btree *m, *l, *r; + + if(btheight((*tree)->l->r) > btheight((*tree)->l->l)) + bbtrl(&(*tree)->l); + r = (*tree); + l = r->l; + m = l->r; + r->l = m; + btsetheight(r); + l->r = r; + btsetheight(l); + *tree = l; +} + +static void bbtrl(struct btree **tree) +{ + struct btree *m, *l, *r; + + if(btheight((*tree)->r->l) > btheight((*tree)->r->r)) + bbtrr(&(*tree)->r); + l = (*tree); + r = l->r; + m = r->l; + l->r = m; + btsetheight(l); + r->l = l; + btsetheight(r); + *tree = r; +} + +static int ptrcmp(void *a, void *b) +{ + if(a < b) + return(-1); + else if(a > b) + return(1); + return(0); +} + +int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *)) +{ + int c, r; + struct btree *s, **sp, *o; + + if(cmp == NULL) + cmp = ptrcmp; + if(*tree == NULL) + return(0); + if((c = cmp(item, (*tree)->d)) < 0) { + r = bbtreedel(&(*tree)->l, item, cmp); + } else if(c > 0) { + r = bbtreedel(&(*tree)->r, item, cmp); + } else { + r = 1; + o = *tree; + if(((*tree)->r != NULL) && ((*tree)->l != NULL)) { + sp = &(*tree)->r; + s = *sp; + while(s->l != NULL) { + sp = &(s->l); + s = *sp; + } + *sp = (*sp)->r; + s->l = (*tree)->l; + s->r = (*tree)->r; + *tree = s; + } else if((*tree)->l != NULL) { + *tree = (*tree)->l; + } else if((*tree)->r != NULL) { + *tree = (*tree)->r; + } else { + *tree = NULL; + } + free(o); + } + if(*tree != NULL) { + btsetheight(*tree); + if(btheight((*tree)->l) > btheight((*tree)->r) + 1) + bbtrr(tree); + if(btheight((*tree)->r) > btheight((*tree)->l) + 1) + bbtrl(tree); + } + return(r); +} + +void freebtree(struct btree **tree, void (*ffunc)(void *)) +{ + if(*tree == NULL) + return; + freebtree(&(*tree)->l, ffunc); + freebtree(&(*tree)->r, ffunc); + if(ffunc != NULL) + ffunc((*tree)->d); + free(*tree); + *tree = NULL; +} + +int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *)) +{ + int c, r; + + if(cmp == NULL) + cmp = ptrcmp; + if(*tree == NULL) { + *tree = szmalloc(sizeof(**tree)); + (*tree)->d = item; + (*tree)->h = 1; + return(1); + } + if((c = cmp(item, (*tree)->d)) < 0) + r = bbtreeput(&(*tree)->l, item, cmp); + else if(c > 0) + r = bbtreeput(&(*tree)->r, item, cmp); + else + return(0); + btsetheight(*tree); + if(btheight((*tree)->l) > btheight((*tree)->r) + 1) + bbtrr(tree); + if(btheight((*tree)->r) > btheight((*tree)->l) + 1) + bbtrl(tree); + return(r); +} + +void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *)) +{ + int c; + + if(cmp == NULL) + cmp = ptrcmp; + while(1) { + if(tree == NULL) + return(NULL); + c = cmp(key, tree->d); + if(c < 0) + tree = tree->l; + else if(c > 0) + tree = tree->r; + else + return(tree->d); + } +}