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