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