chiark / gitweb /
4bbf8f67663b54d904512f7f98c4c1921f006829
[chiark-tcl.git] / hbytes / hbytes.c
1 /*
2  *
3  */
4
5 #include <string.h>
6
7 #include "hbytes.h"
8 #include "tables.h"
9 #include "hbintern.h"
10
11 #define COMPLEX(hb) ((HBytes_ComplexValue*)hb->begin_complex)
12 #define SIMPLE_LEN(hb) ((Byte*)(hb)->end_0 - (Byte*)(hb)->begin_complex)
13
14 /* enquirers */
15
16 int hbytes_len(const HBytes_Value *hb) {
17   if (HBYTES_ISEMPTY(hb)) return 0;
18   else if (HBYTES_ISCOMPLEX(hb)) return COMPLEX(hb)->len;
19   else return SIMPLE_LEN(hb);
20 }
21
22 Byte *hbytes_data(const HBytes_Value *hb) {
23   if (HBYTES_ISEMPTY(hb)) return 0;
24   else if (HBYTES_ISCOMPLEX(hb)) return COMPLEX(hb)->dstart;
25   else return hb->begin_complex;
26 }
27
28 int hbytes_issentinel(const HBytes_Value *hb) {
29   return HBYTES_ISCOMPLEX(hb);
30 }
31
32 /* constructors */
33
34 void hbytes_empty(HBytes_Value *returns) {
35   returns->begin_complex= returns->end_0= 0;
36 }
37
38 void hbytes_sentinel(HBytes_Value *returns) {
39   returns->begin_complex= 0;
40   returns->end_0= (void*)&hbytes_type;
41 }
42
43 Byte *hbytes_arrayspace(HBytes_Value *returns, int l) {
44   if (!l) { hbytes_empty(returns); return 0; }
45   returns->begin_complex= TALLOC(l);
46   returns->end_0= returns->begin_complex + l;
47   return returns->begin_complex;
48 }
49   
50 void hbytes_array(HBytes_Value *returns, const Byte *array, int l) {
51   memcpy(hbytes_arrayspace(returns,l), array, l);
52 }
53
54 /* destructor */
55
56 void hbytes_free(HBytes_Value *frees) {
57   if (HBYTES_ISCOMPLEX(frees)) {
58     HBytes_ComplexValue *cx= COMPLEX(frees);
59     TFREE(cx->dstart - cx->prespace);
60   }
61   TFREE(frees->begin_complex);
62 }
63
64 /* mutators */
65
66 static HBytes_ComplexValue *complex(HBytes_Value *hb) {
67   HBytes_ComplexValue *cx;
68
69   if (HBYTES_ISCOMPLEX(hb)) return hb->begin_complex;
70
71   cx= TALLOC(sizeof(*cx));
72   cx->dstart= hb->begin_complex;
73   cx->len= cx->avail= SIMPLE_LEN(hb);
74   cx->prespace= 0;
75
76   hb->begin_complex= cx;
77   hb->end_0= 0;
78
79   return cx;
80 }
81
82 Byte *hbytes_prepend(HBytes_Value *hb, int el) {
83   HBytes_ComplexValue *cx;
84   int new_prespace;
85   Byte *old_block, *new_block, *new_dstart;
86
87   cx= complex(hb);
88   
89   if (cx->prespace < el) {
90     new_prespace= el*2 + cx->len;
91     old_block= cx->dstart - cx->prespace;
92     new_block= Tcl_Realloc(old_block, new_prespace + cx->avail);
93     new_dstart= new_block + new_prespace;
94     memmove(new_dstart, new_block + cx->prespace, cx->len);
95     cx->prespace= new_prespace;
96     cx->dstart= new_dstart;
97   }
98   cx->dstart -= el;
99   cx->prespace -= el;
100   cx->len += el;
101   cx->avail += el;
102   return cx->dstart;
103 }
104
105 Byte *hbytes_append(HBytes_Value *hb, int el) {
106   HBytes_ComplexValue *cx;
107   int new_len, new_avail;
108   Byte *newpart, *new_block, *old_block;
109
110   cx= complex(hb);
111
112   new_len= cx->len + el;
113   if (new_len > cx->avail) {
114     new_avail= new_len*2;
115     old_block= cx->dstart - cx->prespace;
116     new_block= Tcl_Realloc(old_block, cx->prespace + new_avail);
117     cx->dstart= new_block + cx->prespace;
118     cx->avail= new_avail;
119   }
120   newpart= cx->dstart + cx->len;
121   cx->len= new_len;
122   return newpart;
123 }
124
125 HBytes_ComplexValue *prechop(HBytes_Value *hb, int cl, const Byte **rv) {
126   HBytes_ComplexValue *cx;
127
128   if (cl<0) { *rv=0; return 0; }
129   if (cl==0) { *rv= (const void*)&hbytes_type; return 0; }
130   
131   cx= complex(hb);
132   if (cl > cx->len) { *rv=0; return 0; }
133   return cx;
134 }
135
136 const Byte *hbytes_unprepend(HBytes_Value *hb, int pl) {
137   const Byte *chopped;
138   HBytes_ComplexValue *cx= prechop(hb,pl,&chopped);
139   if (!cx) return chopped;
140
141   chopped= cx->dstart;
142   cx->dstart += pl;
143   cx->prespace += pl;
144   cx->len -= pl;
145   cx->avail -= pl;
146   return chopped;
147 }
148
149 const Byte *hbytes_unappend(HBytes_Value *hb, int sl) {
150   const Byte *chopped;
151   HBytes_ComplexValue *cx= prechop(hb,sl,&chopped);
152   if (!cx) return chopped;
153
154   cx->len -= sl;
155   return cx->dstart + cx->len;
156 }