/src/tidy-html5/src/buffio.c
Line | Count | Source |
1 | | /* buffio.c -- Treat buffer as an I/O stream. |
2 | | |
3 | | (c) 1998-2007 (W3C) MIT, ERCIM, Keio University |
4 | | See tidy.h for the copyright notice. |
5 | | |
6 | | Requires buffer to automatically grow as bytes are added. |
7 | | Must keep track of current read and write points. |
8 | | |
9 | | */ |
10 | | |
11 | | #include "tidy.h" |
12 | | #include "tidybuffio.h" |
13 | | #include "forward.h" |
14 | | |
15 | | /************** |
16 | | TIDY |
17 | | **************/ |
18 | | |
19 | | static int TIDY_CALL insrc_getByte( void* appData ) |
20 | 0 | { |
21 | 0 | TidyBuffer* buf = (TidyBuffer*) appData; |
22 | 0 | return tidyBufGetByte( buf ); |
23 | 0 | } |
24 | | static Bool TIDY_CALL insrc_eof( void* appData ) |
25 | 0 | { |
26 | 0 | TidyBuffer* buf = (TidyBuffer*) appData; |
27 | 0 | return tidyBufEndOfInput( buf ); |
28 | 0 | } |
29 | | static void TIDY_CALL insrc_ungetByte( void* appData, byte bv ) |
30 | 0 | { |
31 | 0 | TidyBuffer* buf = (TidyBuffer*) appData; |
32 | 0 | tidyBufUngetByte( buf, bv ); |
33 | 0 | } |
34 | | |
35 | | void TIDY_CALL tidyInitInputBuffer( TidyInputSource* inp, TidyBuffer* buf ) |
36 | 0 | { |
37 | 0 | inp->getByte = insrc_getByte; |
38 | 0 | inp->eof = insrc_eof; |
39 | 0 | inp->ungetByte = insrc_ungetByte; |
40 | 0 | inp->sourceData = buf; |
41 | 0 | } |
42 | | |
43 | | static void TIDY_CALL outsink_putByte( void* appData, byte bv ) |
44 | 765M | { |
45 | 765M | TidyBuffer* buf = (TidyBuffer*) appData; |
46 | 765M | tidyBufPutByte( buf, bv ); |
47 | 765M | } |
48 | | |
49 | | void TIDY_CALL tidyInitOutputBuffer( TidyOutputSink* outp, TidyBuffer* buf ) |
50 | 42.9k | { |
51 | 42.9k | outp->putByte = outsink_putByte; |
52 | 42.9k | outp->sinkData = buf; |
53 | 42.9k | } |
54 | | |
55 | | |
56 | | void TIDY_CALL tidyBufInit( TidyBuffer* buf ) |
57 | 64.4k | { |
58 | 64.4k | assert( buf != NULL ); |
59 | 64.4k | tidyBufInitWithAllocator( buf, NULL ); |
60 | 64.4k | } |
61 | | |
62 | | void TIDY_CALL tidyBufAlloc( TidyBuffer* buf, uint allocSize ) |
63 | 0 | { |
64 | 0 | tidyBufAllocWithAllocator( buf, NULL, allocSize ); |
65 | 0 | } |
66 | | |
67 | | void TIDY_CALL tidyBufInitWithAllocator( TidyBuffer* buf, |
68 | | TidyAllocator *allocator ) |
69 | 128k | { |
70 | 128k | assert( buf != NULL ); |
71 | 128k | TidyClearMemory( buf, sizeof(TidyBuffer) ); |
72 | 128k | buf->allocator = allocator ? allocator : &TY_(g_default_allocator); |
73 | 128k | } |
74 | | |
75 | | void TIDY_CALL tidyBufAllocWithAllocator( TidyBuffer* buf, |
76 | | TidyAllocator *allocator, |
77 | | uint allocSize ) |
78 | 0 | { |
79 | 0 | tidyBufInitWithAllocator( buf, allocator ); |
80 | 0 | tidyBufCheckAlloc( buf, allocSize, 0 ); |
81 | 0 | buf->next = 0; |
82 | 0 | } |
83 | | |
84 | | void TIDY_CALL tidyBufFree( TidyBuffer* buf ) |
85 | 64.4k | { |
86 | 64.4k | assert( buf != NULL ); |
87 | 64.4k | TidyFree( buf->allocator, buf->bp ); |
88 | 64.4k | tidyBufInitWithAllocator( buf, buf->allocator ); |
89 | 64.4k | } |
90 | | |
91 | | void TIDY_CALL tidyBufClear( TidyBuffer* buf ) |
92 | 21.4k | { |
93 | 21.4k | assert( buf != NULL ); |
94 | 21.4k | if ( buf->bp ) |
95 | 0 | { |
96 | 0 | TidyClearMemory( buf->bp, buf->allocated ); |
97 | 0 | buf->size = 0; |
98 | 0 | } |
99 | 21.4k | buf->next = 0; |
100 | 21.4k | } |
101 | | |
102 | | /* Many users do not call tidyBufInit() or tidyBufAlloc() or their allocator |
103 | | counterparts. So by default, set the default allocator. |
104 | | */ |
105 | | static void setDefaultAllocator( TidyBuffer* buf ) |
106 | 0 | { |
107 | 0 | buf->allocator = &TY_(g_default_allocator); |
108 | 0 | } |
109 | | |
110 | | /* Avoid thrashing memory by doubling buffer size |
111 | | ** until larger than requested size. |
112 | | buf->allocated is bigger than allocSize+1 so that a trailing null byte is |
113 | | always available. |
114 | | */ |
115 | | void TIDY_CALL tidyBufCheckAlloc( TidyBuffer* buf, uint allocSize, uint chunkSize ) |
116 | 765M | { |
117 | 765M | assert( buf != NULL ); |
118 | | |
119 | 765M | if ( !buf->allocator ) |
120 | 0 | setDefaultAllocator( buf ); |
121 | | |
122 | 765M | if ( 0 == chunkSize ) |
123 | 765M | chunkSize = 256; |
124 | 765M | if ( allocSize+1 > buf->allocated ) |
125 | 144k | { |
126 | 144k | byte* bp; |
127 | 144k | uint allocAmt = chunkSize; |
128 | 144k | if ( buf->allocated > 0 ) |
129 | 80.3k | allocAmt = buf->allocated; |
130 | 225k | while ( allocAmt < allocSize+1 ) |
131 | 80.3k | allocAmt *= 2; |
132 | | |
133 | 144k | bp = (byte*)TidyRealloc( buf->allocator, buf->bp, allocAmt ); |
134 | 144k | if ( bp != NULL ) |
135 | 144k | { |
136 | 144k | TidyClearMemory( bp + buf->allocated, allocAmt - buf->allocated ); |
137 | 144k | buf->bp = bp; |
138 | 144k | buf->allocated = allocAmt; |
139 | 144k | } |
140 | 144k | } |
141 | 765M | } |
142 | | |
143 | | /* Attach buffer to a chunk O' memory w/out allocation */ |
144 | | void TIDY_CALL tidyBufAttach( TidyBuffer* buf, byte* bp, uint size ) |
145 | 0 | { |
146 | 0 | assert( buf != NULL ); |
147 | 0 | buf->bp = bp; |
148 | 0 | buf->size = buf->allocated = size; |
149 | 0 | buf->next = 0; |
150 | 0 | if ( !buf->allocator ) |
151 | 0 | setDefaultAllocator( buf ); |
152 | 0 | } |
153 | | |
154 | | /* Clear pointer to memory w/out deallocation */ |
155 | | void TIDY_CALL tidyBufDetach( TidyBuffer* buf ) |
156 | 0 | { |
157 | 0 | tidyBufInitWithAllocator( buf, buf->allocator ); |
158 | 0 | } |
159 | | |
160 | | |
161 | | /************** |
162 | | OUTPUT |
163 | | **************/ |
164 | | |
165 | | void TIDY_CALL tidyBufAppend( TidyBuffer* buf, void* vp, uint size ) |
166 | 64.4k | { |
167 | 64.4k | assert( buf != NULL ); |
168 | 64.4k | if ( vp != NULL && size > 0 ) |
169 | 64.4k | { |
170 | 64.4k | tidyBufCheckAlloc( buf, buf->size + size, 0 ); |
171 | 64.4k | memcpy( buf->bp + buf->size, vp, size ); |
172 | 64.4k | buf->size += size; |
173 | 64.4k | } |
174 | 64.4k | } |
175 | | |
176 | | void TIDY_CALL tidyBufPutByte( TidyBuffer* buf, byte bv ) |
177 | 765M | { |
178 | 765M | assert( buf != NULL ); |
179 | 765M | tidyBufCheckAlloc( buf, buf->size + 1, 0 ); |
180 | 765M | buf->bp[ buf->size++ ] = bv; |
181 | 765M | } |
182 | | |
183 | | |
184 | | int TIDY_CALL tidyBufPopByte( TidyBuffer* buf ) |
185 | 0 | { |
186 | 0 | int bv = EOF; |
187 | 0 | assert( buf != NULL ); |
188 | 0 | if ( buf->size > 0 ) |
189 | 0 | bv = buf->bp[ --buf->size ]; |
190 | 0 | return bv; |
191 | 0 | } |
192 | | |
193 | | /************** |
194 | | INPUT |
195 | | **************/ |
196 | | |
197 | | int TIDY_CALL tidyBufGetByte( TidyBuffer* buf ) |
198 | 0 | { |
199 | 0 | int bv = EOF; |
200 | 0 | if ( ! tidyBufEndOfInput(buf) ) |
201 | 0 | bv = buf->bp[ buf->next++ ]; |
202 | 0 | return bv; |
203 | 0 | } |
204 | | |
205 | | Bool TIDY_CALL tidyBufEndOfInput( TidyBuffer* buf ) |
206 | 0 | { |
207 | 0 | return ( buf->next >= buf->size ); |
208 | 0 | } |
209 | | |
210 | | void TIDY_CALL tidyBufUngetByte( TidyBuffer* buf, byte bv ) |
211 | 0 | { |
212 | 0 | if ( buf->next > 0 ) |
213 | 0 | { |
214 | 0 | --buf->next; |
215 | | assert( bv == buf->bp[ buf->next ] ); |
216 | 0 | } |
217 | 0 | } |
218 | | |
219 | | /* |
220 | | * local variables: |
221 | | * mode: c |
222 | | * indent-tabs-mode: nil |
223 | | * c-basic-offset: 4 |
224 | | * eval: (c-set-offset 'substatement-open 0) |
225 | | * end: |
226 | | */ |