6 #include "chiark_tcl_hbytes.h"
8 int cht_do_hbytes_rep_info(ClientData cd, Tcl_Interp *ip,
9 Tcl_Obj *obj, Tcl_Obj **result) {
14 if (obj->typePtr == &cht_hbytes_type) {
15 HBytes_Value *v= OBJ_HBYTES(obj);
16 memset(nums,0,sizeof(nums));
17 nums[1]= cht_hb_len(v);
19 if (HBYTES_ISEMPTY(v)) tn= "empty";
20 else if (HBYTES_ISSENTINEL(v)) tn= "sentinel!";
21 else if (HBYTES_ISSIMPLE(v)) tn= "simple";
23 HBytes_ComplexValue *cx= v->begin_complex;
25 nums[0]= cx->prespace;
26 nums[2]= cx->avail - cx->len;
34 objl[0]= Tcl_NewStringObj((char*)tn,-1);
35 for (i=0; i<lnl; i++) objl[i+1]= Tcl_NewIntObj(nums[i]);
36 *result= Tcl_NewListObj(lnl+1,objl);
41 static void hbytes_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
42 cht_hb_array(OBJ_HBYTES(dup),
43 cht_hb_data(OBJ_HBYTES(src)),
44 cht_hb_len(OBJ_HBYTES(src)));
45 dup->typePtr= &cht_hbytes_type;
48 static void hbytes_t_free(Tcl_Obj *o) {
49 cht_hb_free(OBJ_HBYTES(o));
52 void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
53 int l, const char *prefix) {
59 str= o->bytes= TALLOC(o->length+1);
61 memcpy(str,prefix,pl);
65 sprintf(str,"%02x",*byte);
71 void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
72 obj_updatestr_array_prefix(o,byte,l,"");
75 static void hbytes_t_ustr(Tcl_Obj *o) {
76 obj_updatestr_array(o,
77 cht_hb_data(OBJ_HBYTES(o)),
78 cht_hb_len(OBJ_HBYTES(o)));
81 static int hbytes_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
83 Byte *startbytes, *bytes;
87 if (o->typePtr == &cht_ulong_type) {
90 ul= htonl(*(const uint32_t*)&o->internalRep.longValue);
91 cht_hb_array(OBJ_HBYTES(o), (const Byte*)&ul, 4);
95 os= str= Tcl_GetStringFromObj(o,&l); assert(str);
98 if (l & 1) return cht_staticerr(ip, "hbytes: conversion from hex:"
99 " odd length in hex", "HBYTES SYNTAX");
101 startbytes= bytes= cht_hb_arrayspace(OBJ_HBYTES(o), l/2);
107 *bytes++= strtoul(cbuf,&ep,16);
109 cht_hb_free(OBJ_HBYTES(o));
110 return cht_staticerr(ip, "hbytes: conversion from hex:"
111 " bad hex digit", "HBYTES SYNTAX");
118 o->typePtr = &cht_hbytes_type;
122 Tcl_ObjType cht_hbytes_type = {
124 hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa
127 int cht_do_hbytes_raw2h(ClientData cd, Tcl_Interp *ip,
128 Tcl_Obj *binary, HBytes_Value *result) {
129 const unsigned char *str;
132 str= Tcl_GetByteArrayFromObj(binary,&l);
133 cht_hb_array(result, str, l);
137 int cht_do_hbytes_h2raw(ClientData cd, Tcl_Interp *ip,
138 HBytes_Value hex, Tcl_Obj **result) {
139 *result= Tcl_NewByteArrayObj(cht_hb_data(&hex), cht_hb_len(&hex));
143 int cht_do_hbytes_length(ClientData cd, Tcl_Interp *ip,
144 HBytes_Value v, int *result) {
145 *result= cht_hb_len(&v);
149 int cht_do_hbytes_random(ClientData cd, Tcl_Interp *ip,
150 int length, HBytes_Value *result) {
154 space= cht_hb_arrayspace(result, length);
155 rc= cht_get_urandom(ip, space, length);
156 if (rc) { cht_hb_free(result); return rc; }
160 int cht_do_hbytes_overwrite(ClientData cd, Tcl_Interp *ip,
161 HBytes_Var v, int start, HBytes_Value sub) {
164 sub_l= cht_hb_len(&sub);
166 return cht_staticerr(ip, "hbytes overwrite start -ve",
167 "HBYTES LENGTH RANGE");
168 if (start + sub_l > cht_hb_len(v.hb))
169 return cht_staticerr(ip, "hbytes overwrite out of range",
170 "HBYTES LENGTH UNDERRUN");
171 memcpy(cht_hb_data(v.hb) + start, cht_hb_data(&sub), sub_l);
175 int cht_do_hbytes_trimleft(ClientData cd, Tcl_Interp *ip, HBytes_Var v) {
176 const Byte *o, *p, *e;
177 o= p= cht_hb_data(v.hb);
178 e= p + cht_hb_len(v.hb);
180 while (p<e && !*p) p++;
182 cht_hb_unprepend(v.hb, p-o);
187 int cht_do_hbytes_repeat(ClientData cd, Tcl_Interp *ip,
188 HBytes_Value sub, int count, HBytes_Value *result) {
193 sub_l= cht_hb_len(&sub);
194 if (count < 0) return cht_staticerr(ip, "hbytes repeat count -ve",
195 "HBYTES LENGTH RANGE");
196 if (count > INT_MAX/sub_l) return cht_staticerr(ip, "hbytes repeat too long", 0);
198 data= cht_hb_arrayspace(result, sub_l*count);
199 sub_d= cht_hb_data(&sub);
201 memcpy(data, sub_d, sub_l);
202 count--; data += sub_l;
207 int cht_do_hbytes_xor(ClientData cd, Tcl_Interp *ip,
208 HBytes_Var v, HBytes_Value d) {
214 if (cht_hb_len(&d) != l) return
215 cht_staticerr(ip, "hbytes xor lengths do not match", "HBYTES LENGTH MISMATCH");
217 dest= cht_hb_data(v.hb);
218 source= cht_hb_data(&d);
219 memxor(dest,source,l);
223 int cht_do_hbytes_zeroes(ClientData cd, Tcl_Interp *ip,
224 int length, HBytes_Value *result) {
226 space= cht_hb_arrayspace(result, length);
227 memset(space,0,length);
231 int cht_do_hbytes_compare(ClientData cd, Tcl_Interp *ip,
232 HBytes_Value a, HBytes_Value b, int *result) {
237 minl= al<bl ? al : bl;
239 r= memcmp(cht_hb_data(&a), cht_hb_data(&b), minl);
241 if (r<0) *result= -2;
242 else if (r>0) *result= +2;
244 if (al<bl) *result= -1;
245 else if (al>bl) *result= +1;
251 int cht_do_hbytes_range(ClientData cd, Tcl_Interp *ip,
252 HBytes_Value v, int start, int size,
253 HBytes_Value *result) {
258 if (start<0 || size<0)
259 return cht_staticerr(ip,"hbytes range subscript(s) -ve","HBYTES LENGTH RANGE");
261 return cht_staticerr(ip, "hbytes range subscripts too big",
262 "HBYTES LENGTH UNDERRUN");
264 data= cht_hb_data(&v);
265 cht_hb_array(result, data+start, size);
269 /* hbytes representing uint16_t's */
271 int cht_do_hbytes_h2ushort(ClientData cd, Tcl_Interp *ip,
272 HBytes_Value hex, long *result) {
278 return cht_staticerr(ip, "hbytes h2ushort input more than 4 hex digits",
279 "HBYTES VALUE OVERFLOW");
281 data= cht_hb_data(&hex);
282 *result= data[l-1] | (l>1 ? data[0]<<8 : 0);
286 int cht_do_hbytes_ushort2h(ClientData cd, Tcl_Interp *ip,
287 long input, HBytes_Value *result) {
291 return cht_staticerr(ip, "hbytes ushort2h input >2^16",
292 "HBYTES VALUE OVERFLOW");
295 cht_hb_array(result,(const Byte*)&us,2);
299 /* toplevel functions */
301 int cht_do_hbytestoplevel_hbytes(ClientData cd, Tcl_Interp *ip,
302 const HBytes_SubCommand *subcmd,
303 int objc, Tcl_Obj *const *objv) {
304 return subcmd->func(0,ip,objc,objv);
307 int cht_do_hbytestoplevel_ulong(ClientData cd, Tcl_Interp *ip,
308 const ULong_SubCommand *subcmd,
309 int objc, Tcl_Obj *const *objv) {
310 return subcmd->func(0,ip,objc,objv);
313 int Chiark_tcl_hbytes_Init(Tcl_Interp *ip) {
316 return cht_initextension(ip, cht_hbytestoplevel_entries, &initd,