*
*/
+#include <string.h>
+
#include "hbytes.h"
#include "tables.h"
-int staticerr(Tcl_Interp *ip, const char *m) {
- Tcl_SetResult(ip, (char*)m, TCL_STATIC);
- return TCL_ERROR;
-}
+#define COMPLEX(hb) ((HBytes_ComplexValue*)hb->begin_complex)
+#define SIMPLE_LEN(hb) ((Byte*)(hb)->end_0 - (Byte*)(hb)->begin_complex)
-void hbytes_set(HBytes_Value *upd, const Byte *array, int l) {
- Byte *np;
+/* enquirers */
- upd->start= np= l ? TALLOC(l) : 0;
- memcpy(np, array, l);
- upd->end= np + l;
+int hbytes_len(const HBytes_Value *hb) {
+ if (HBYTES_ISEMPTY(hb)) return 0;
+ else if (HBYTES_ISCOMPLEX(hb)) return COMPLEX(hb)->len;
+ else return SIMPLE_LEN(hb);
}
-static void hbytes_setintern(Tcl_Obj *o, const Byte *array, int l) {
- hbytes_set(&HBYTES(o), array, l);
- o->typePtr = &hbytes_type;
+Byte *hbytes_data(const HBytes_Value *hb) {
+ if (HBYTES_ISEMPTY(hb)) return 0;
+ else if (HBYTES_ISCOMPLEX(hb)) return COMPLEX(hb)->dstart;
+ else return hb->begin_complex;
}
-static void hbytes_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
- hbytes_setintern(src, HBYTES(src).start, HBYTES_LEN(HBYTES(src)));
+int hbytes_issentinel(const HBytes_Value *hb) {
+ return HBYTES_ISSENTINEL(hb);
}
-Tcl_Obj *hbytes_set_obj(Tcl_Obj *overwrite, const Byte *array, int l) {
- if (!overwrite) overwrite= Tcl_NewObj();
- objfreeir(overwrite);
- Tcl_InvalidateStringRep(overwrite);
- hbytes_setintern(overwrite, array, l);
- return overwrite;
+/* constructors */
+
+void hbytes_empty(HBytes_Value *returns) {
+ returns->begin_complex= returns->end_0= 0;
}
-static void hbytes_t_free(Tcl_Obj *o) {
- TFREE(HBYTES(o).start);
+void hbytes_sentinel(HBytes_Value *returns) {
+ returns->begin_complex= 0;
+ returns->end_0= (void*)&hbytes_type;
}
-static void hbytes_t_ustr(Tcl_Obj *o) {
- int l;
- char *str;
- const Byte *byte;
-
- l= HBYTES_LEN(HBYTES(o));
- byte= HBYTES(o).start;
- str= o->bytes= TALLOC(l*2+1);
- o->length= l*2;
- while (l>0) {
- sprintf(str,"%02x",*byte);
- str+=2; byte++; l--;
- }
+Byte *hbytes_arrayspace(HBytes_Value *returns, int l) {
+ if (!l) { hbytes_empty(returns); return 0; }
+ returns->begin_complex= TALLOC(l);
+ returns->end_0= returns->begin_complex + l;
+ return returns->begin_complex;
+}
+
+void hbytes_array(HBytes_Value *returns, const Byte *array, int l) {
+ memcpy(hbytes_arrayspace(returns,l), array, l);
}
-void objfreeir(Tcl_Obj *o) {
- if (o->typePtr && o->typePtr->freeIntRepProc)
- o->typePtr->freeIntRepProc(o);
-}
-
-static int hbytes_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
- char *str, *ep, *os;
- Byte *startbytes, *bytes;
- int l;
- char cbuf[3];
-
- os= str= Tcl_GetStringFromObj(o,&l); assert(str);
- if (l & 1) return staticerr(ip, "hbytes: conversion from hex:"
- " odd length in hex");
-
- startbytes= bytes= l ? TALLOC(l*2) : 0;
- cbuf[2]= 0;
- while (l>0) {
- cbuf[0]= *str++;
- cbuf[1]= *str++;
- *bytes++= strtoul(cbuf,&ep,16);
- if (ep != cbuf+2) {
- TFREE(startbytes);
-fprintf(stderr,">%d|%s|%s<\n",l,os,cbuf);
- return staticerr(ip, "hbytes: conversion from hex:"
- " bad hex digit");
- }
- l -= 2;
- }
- objfreeir(o);
+/* destructor */
- HBYTES(o).start= startbytes;
- HBYTES(o).end= bytes;
- o->typePtr = &hbytes_type;
- return TCL_OK;
+void hbytes_free(const HBytes_Value *frees) {
+ if (HBYTES_ISCOMPLEX(frees)) {
+ HBytes_ComplexValue *cx= COMPLEX(frees);
+ TFREE(cx->dstart - cx->prespace);
+ }
+ TFREE(frees->begin_complex);
}
-Tcl_ObjType hbytes_type = {
- "hbytes",
- hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa
-};
+/* mutators */
+
+static HBytes_ComplexValue *complex(HBytes_Value *hb) {
+ HBytes_ComplexValue *cx;
+
+ if (HBYTES_ISCOMPLEX(hb)) return hb->begin_complex;
-int do_hbytes_raw2h(ClientData cd, Tcl_Interp *ip,
- Tcl_Obj *binary, HBytes_Value *result) {
- const char *str;
- int l;
+ cx= TALLOC(sizeof(*cx));
+ cx->dstart= hb->begin_complex;
+ cx->len= cx->avail= SIMPLE_LEN(hb);
+ cx->prespace= 0;
- str= Tcl_GetStringFromObj(binary,&l);
- hbytes_set(result, str, l);
- return TCL_OK;
+ hb->begin_complex= cx;
+ hb->end_0= 0;
+
+ return cx;
}
-int do_hbytes_h2raw(ClientData cd, Tcl_Interp *ip,
- HBytes_Value hex, Tcl_Obj **result) {
- *result= Tcl_NewStringObj(hex.start, HBYTES_LEN(hex));
- return TCL_OK;
+Byte *hbytes_prepend(HBytes_Value *hb, int el) {
+ HBytes_ComplexValue *cx;
+ int new_prespace;
+ Byte *old_block, *new_block, *new_dstart;
+
+ cx= complex(hb);
+
+ if (cx->prespace < el) {
+ new_prespace= el*2 + cx->len;
+ old_block= cx->dstart - cx->prespace;
+ new_block= Tcl_Realloc(old_block, new_prespace + cx->avail);
+ new_dstart= new_block + new_prespace;
+ memmove(new_dstart, new_block + cx->prespace, cx->len);
+ cx->prespace= new_prespace;
+ cx->dstart= new_dstart;
+ }
+ cx->dstart -= el;
+ cx->prespace -= el;
+ cx->len += el;
+ cx->avail += el;
+ return cx->dstart;
}
-#if 0
-HC_DEFINE(pkcs5) {
- static const PadKindInfo padkindinfos[0]= {
- { "pa", 1, 1 },
- { "pn", 1, 0 },
- { "ua", 0, 1 },
- { "un", 0, 0 },
- { 0 }
- };
-
- HC_DECLS_HBV;
- Tcl_Obj *v;
- int blocksize;
- const PadKindInfo *pk;
- const BlockCipherInfo *bc;
-
- HC_ARG_ENUM(pk, padkindinfos);
- HC_ARG_HBV;
- if (!pk->algname) HC_ARG_INTRANGE(blocksize, 1,255);
- else { HC_ARG_ENUM(bc, blockciphers); blocksize= bc->blocksize; }
- HC_ARGS_E;
-
- /* do nothing :-) */
-
- HC_FINI_HBV;
+Byte *hbytes_append(HBytes_Value *hb, int el) {
+ HBytes_ComplexValue *cx;
+ int new_len, new_avail;
+ Byte *newpart, *new_block, *old_block;
+
+ cx= complex(hb);
+
+ new_len= cx->len + el;
+ if (new_len > cx->avail) {
+ new_avail= new_len*2;
+ old_block= cx->dstart - cx->prespace;
+ new_block= Tcl_Realloc(old_block, cx->prespace + new_avail);
+ cx->dstart= new_block + cx->prespace;
+ cx->avail= new_avail;
+ }
+ newpart= cx->dstart + cx->len;
+ cx->len= new_len;
+ return newpart;
}
-#endif
-int do__hbytes(ClientData cd, Tcl_Interp *ip,
- const HBytes_SubCommand *subcmd,
- int objc, Tcl_Obj *const *objv) {
- return subcmd->func(0,ip,objc,objv);
+static HBytes_ComplexValue*
+prechop(HBytes_Value *hb, int cl, const Byte **rv) {
+ HBytes_ComplexValue *cx;
+
+ if (cl<0) { *rv=0; return 0; }
+ if (cl==0) { *rv= (const void*)&hbytes_type; return 0; }
+
+ cx= complex(hb);
+ if (cl > cx->len) { *rv=0; return 0; }
+ return cx;
+}
+
+const Byte *hbytes_unprepend(HBytes_Value *hb, int pl) {
+ const Byte *chopped;
+ HBytes_ComplexValue *cx= prechop(hb,pl,&chopped);
+ if (!cx) return chopped;
+
+ chopped= cx->dstart;
+ cx->dstart += pl;
+ cx->prespace += pl;
+ cx->len -= pl;
+ cx->avail -= pl;
+ return chopped;
}
-int Hbytes_Init(Tcl_Interp *ip) {
- Tcl_RegisterObjType(&hbytes_type);
- Tcl_RegisterObjType(&enum_nearlytype);
- Tcl_RegisterObjType(&enum1_nearlytype);
- Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0);
- return TCL_OK;
+const Byte *hbytes_unappend(HBytes_Value *hb, int sl) {
+ const Byte *chopped;
+ HBytes_ComplexValue *cx= prechop(hb,sl,&chopped);
+ if (!cx) return chopped;
+
+ cx->len -= sl;
+ return cx->dstart + cx->len;
}