2 * hbytes - hex-stringrep efficient byteblocks for Tcl
3 * Copyright 2006-2012 Ian Jackson
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 #define COMPLEX(hb) ((HBytes_ComplexValue*)hb->begin_complex)
25 #define SIMPLE_LEN(hb) ((Byte*)(hb)->end_0 - (Byte*)(hb)->begin_complex)
29 int cht_hb_len(const HBytes_Value *hb) {
30 if (HBYTES_ISEMPTY(hb)) return 0;
31 else if (HBYTES_ISCOMPLEX(hb)) return COMPLEX(hb)->len;
32 else return SIMPLE_LEN(hb);
35 Byte *cht_hb_data(const HBytes_Value *hb) {
36 if (HBYTES_ISEMPTY(hb)) return 0;
37 else if (HBYTES_ISCOMPLEX(hb)) return COMPLEX(hb)->dstart;
38 else return hb->begin_complex;
41 int cht_hb_issentinel(const HBytes_Value *hb) {
42 return HBYTES_ISSENTINEL(hb);
47 void cht_hb_empty(HBytes_Value *returns) {
48 returns->begin_complex= returns->end_0= 0;
51 void cht_hb_sentinel(HBytes_Value *returns) {
52 returns->begin_complex= 0;
53 returns->end_0= (void*)&cht_hbytes_type;
56 Byte *cht_hb_arrayspace(HBytes_Value *returns, int l) {
57 if (!l) { cht_hb_empty(returns); return 0; }
58 returns->begin_complex= TALLOC(l);
59 returns->end_0= returns->begin_complex + l;
60 return returns->begin_complex;
63 void cht_hb_array(HBytes_Value *returns, const Byte *array, int l) {
64 memcpy(cht_hb_arrayspace(returns,l), array, l);
69 void cht_hb_free(const HBytes_Value *frees) {
70 if (HBYTES_ISCOMPLEX(frees)) {
71 HBytes_ComplexValue *cx= COMPLEX(frees);
72 TFREE(cx->dstart - cx->prespace);
74 TFREE(frees->begin_complex);
79 static HBytes_ComplexValue *complex(HBytes_Value *hb) {
80 HBytes_ComplexValue *cx;
82 if (HBYTES_ISCOMPLEX(hb)) return hb->begin_complex;
84 cx= TALLOC(sizeof(*cx));
85 cx->dstart= hb->begin_complex;
86 cx->len= cx->avail= SIMPLE_LEN(hb);
89 hb->begin_complex= cx;
95 Byte *cht_hb_prepend(HBytes_Value *hb, int el) {
96 HBytes_ComplexValue *cx;
98 Byte *old_block, *new_block, *new_dstart;
102 assert(el < INT_MAX/4 && cx->len < INT_MAX/2);
104 if (cx->prespace < el) {
105 new_prespace= el*2 + cx->len;
106 old_block= cx->dstart - cx->prespace;
107 new_block= Tcl_Realloc(old_block, new_prespace + cx->avail);
108 new_dstart= new_block + new_prespace;
109 memmove(new_dstart, new_block + cx->prespace, cx->len);
110 cx->prespace= new_prespace;
111 cx->dstart= new_dstart;
120 Byte *cht_hb_append(HBytes_Value *hb, int el) {
121 HBytes_ComplexValue *cx;
122 int new_len, new_avail;
123 Byte *newpart, *new_block, *old_block;
126 assert(el < INT_MAX/4 && cx->len < INT_MAX/4);
128 new_len= cx->len + el;
129 if (new_len > cx->avail) {
130 new_avail= new_len*2;
131 old_block= cx->dstart - cx->prespace;
132 new_block= Tcl_Realloc(old_block, cx->prespace + new_avail);
133 cx->dstart= new_block + cx->prespace;
134 cx->avail= new_avail;
136 newpart= cx->dstart + cx->len;
141 static HBytes_ComplexValue*
142 prechop(HBytes_Value *hb, int cl, const Byte **rv) {
143 HBytes_ComplexValue *cx;
145 if (cl<0) { *rv=0; return 0; }
146 if (cl==0) { *rv= (const void*)&cht_hbytes_type; return 0; }
149 if (cl > cx->len) { *rv=0; return 0; }
153 const Byte *cht_hb_unprepend(HBytes_Value *hb, int pl) {
155 HBytes_ComplexValue *cx= prechop(hb,pl,&chopped);
156 if (!cx) return chopped;
166 const Byte *cht_hb_unappend(HBytes_Value *hb, int sl) {
168 HBytes_ComplexValue *cx= prechop(hb,sl,&chopped);
169 if (!cx) return chopped;
172 return cx->dstart + cx->len;
175 void memxor(Byte *dest, const Byte *src, int l) {
176 while (l--) *dest++ ^= *src++;