1/* 2 * bufFix.c -- 3 * 4 * Implementations of a fixed size buffer. 5 * 6 * Copyright (c) 2000-2009 by Andreas Kupries <a.kupries@westend.com> 7 * 8 * See the file "license.terms" for information on usage and redistribution 9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 10 * 11 * RCS: @(#) $Id: bufFix.c,v 1.3 2009/03/16 18:51:00 andreas_kupries Exp $ 12 */ 13 14#include "memchanInt.h" 15#include "buf.h" 16 17/* 18 * Forward declarations of all internal procedures. 19 */ 20 21static int ReadProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData, 22 VOID* outbuf, int size)); 23static int WriteProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData, 24 CONST VOID* inbuf, int size)); 25static Buf_Buffer DupProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData)); 26static void FreeProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData)); 27static int SizeProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData)); 28static int TellProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData)); 29static char* DataProc _ANSI_ARGS_ ((Buf_Buffer buf, ClientData clientData)); 30 31 32/* Internal structure used to hold the buffer information. 33 */ 34 35typedef struct FixedBuffer_ { 36 Buf_Buffer buf; /* The buffer token containing this structure. */ 37 int size; /* Size of the area for data, maximal amount of 38 * bytes storable in the buffer. */ 39 char* readLoc; /* The location till which data was read from the 40 * buffer. */ 41 char* writeLoc; /* The location at which new data can be appended to 42 * the buffer. */ 43 char* limit; /* A pointer behind the last character in the buffer. */ 44 char data [1]; /* Each structure is allocated big enough to hold the 45 * required information. This element is the mark to 46 * the offset in the structure from which it will 47 * contain data. */ 48} FixedBuffer; 49 50/* Declaration of the buffer type. 51 */ 52 53 54 55static Buf_BufferType fix = { 56 "fixed-buffer", /* Buffer of a fixed size */ 57 ReadProc, /* Reading from a buffer */ 58 WriteProc, /* Writing to a buffer */ 59 DupProc, /* Duplicating a buffer */ 60 FreeProc, /* Freeing all allocated resources of a buffer */ 61 SizeProc, /* Number of bytes currently in the buffer. */ 62 TellProc, /* Return current location */ 63 DataProc /* Return start of data */ 64}; 65 66 67/* 68 *------------------------------------------------------* 69 * 70 * FreeProc -- 71 * 72 * Deallocates the resources of the buffer. 73 * 74 * Sideeffects: 75 * See above. 76 * 77 * Result: 78 * None. 79 * 80 *------------------------------------------------------* 81 */ 82 83void 84FreeProc (buf, clientData) 85 Buf_Buffer buf; 86 ClientData clientData; 87{ 88 FixedBuffer* iBuf = (FixedBuffer*) clientData; 89 Tcl_Free ((char*) iBuf); 90} 91 92/* 93 *------------------------------------------------------* 94 * 95 * SizeProc -- 96 * 97 * Returns the number of bytes currently stored in 98 * the buffer. 99 * 100 * Sideeffects: 101 * None. 102 * 103 * Result: 104 * See above. 105 * 106 *------------------------------------------------------* 107 */ 108 109int 110SizeProc (buf, clientData) 111 Buf_Buffer buf; 112 ClientData clientData; 113{ 114 FixedBuffer* iBuf = (FixedBuffer*) clientData; 115 return (iBuf->writeLoc - iBuf->readLoc); 116} 117 118/* 119 *------------------------------------------------------* 120 * 121 * TellProc -- 122 * 123 * Returns the offset of the current read location 124 * relative to the start of the data. 125 * 126 * Sideeffects: 127 * None. 128 * 129 * Result: 130 * See above. 131 * 132 *------------------------------------------------------* 133 */ 134 135int 136TellProc (buf, clientData) 137 Buf_Buffer buf; 138 ClientData clientData; 139{ 140 FixedBuffer* iBuf = (FixedBuffer*) clientData; 141 return iBuf->readLoc - iBuf->data; 142} 143 144/* 145 *------------------------------------------------------* 146 * 147 * DataProc -- 148 * 149 * Returns the start of the data area. 150 * (Here: Start of the data area in the underlying buffer) 151 * 152 * Sideeffects: 153 * None. 154 * 155 * Result: 156 * See above. 157 * 158 *------------------------------------------------------* 159 */ 160 161char* 162DataProc (buf, clientData) 163 Buf_Buffer buf; 164 ClientData clientData; 165{ 166 FixedBuffer* iBuf = (FixedBuffer*) clientData; 167 return iBuf->data; 168} 169 170/* 171 *------------------------------------------------------* 172 * 173 * DupProc -- 174 * 175 * Duplicates a buffer and its contents. 176 * 177 * Sideeffects: 178 * Allocates memory. 179 * 180 * Result: 181 * A new buffer token. 182 * 183 *------------------------------------------------------* 184 */ 185 186Buf_Buffer 187DupProc (buf, clientData) 188 Buf_Buffer buf; 189 ClientData clientData; 190{ 191 FixedBuffer* iBuf = (FixedBuffer*) clientData; 192 FixedBuffer* newBuf = (FixedBuffer*) Tcl_Alloc (sizeof(FixedBuffer) + iBuf->size); 193 Buf_Buffer new = Buf_Create (&fix, (ClientData) newBuf); 194 195 newBuf->buf = new; 196 newBuf->size = iBuf->size; 197 newBuf->readLoc = newBuf->data + (iBuf->readLoc - iBuf->data); 198 newBuf->writeLoc = newBuf->data + (iBuf->writeLoc - iBuf->data); 199 newBuf->limit = newBuf->data + newBuf->size; 200 201 if ((iBuf->writeLoc - iBuf->readLoc) > 0) { 202 /* Copy just that part of container which was not read already 203 */ 204 memcpy (newBuf->readLoc, iBuf->readLoc, iBuf->writeLoc - iBuf->readLoc); 205 } 206 207 return new; 208} 209 210/* 211 *------------------------------------------------------* 212 * 213 * ReadProc -- 214 * 215 * Reads at most size bytes from the current location 216 * in the buffer and stores it into outbuf. 217 * 218 * Sideeffects: 219 * Moves the read pointer behind the bytes 220 * just read from the buffer. 221 * 222 * Result: 223 * The number of bytes actually read from 224 * the buffer. 225 * 226 *------------------------------------------------------* 227 */ 228 229int 230ReadProc (buf, clientData, outbuf, size) 231 Buf_Buffer buf; 232 ClientData clientData; 233 VOID* outbuf; 234 int size; 235{ 236 FixedBuffer* iBuf = (FixedBuffer*) clientData; 237 int bSize = iBuf->writeLoc - iBuf->readLoc; 238 239 if ((bSize <= 0) || (size <= 0)) { 240 return 0; 241 } 242 243 if (bSize < size) { 244 size = bSize; 245 } 246 247 memcpy (outbuf, iBuf->readLoc, size); 248 iBuf->readLoc += size; 249 250 return size; 251} 252 253/* 254 *------------------------------------------------------* 255 * 256 * WriteProc -- 257 * 258 * Writes at most size bytes from inbuf and appends 259 * it the buffer 260 * 261 * Sideeffects: 262 * Moves the write pointer behind the bytes 263 * just written into the buffer. 264 * 265 * Result: 266 * The number of bytes actually written 267 * into the buffer. 268 * 269 *------------------------------------------------------* 270 */ 271 272int 273WriteProc (buf, clientData, inbuf, size) 274 Buf_Buffer buf; 275 ClientData clientData; 276 CONST void* inbuf; 277 int size; 278{ 279 FixedBuffer* iBuf = (FixedBuffer*) clientData; 280 int bSize = iBuf->limit - iBuf->writeLoc; 281 282 if ((bSize <= 0) || (size <= 0)) { 283 return 0; 284 } 285 286 if (bSize < size) { 287 size = bSize; 288 } 289 290 memcpy (iBuf->writeLoc, inbuf, size); 291 iBuf->writeLoc += size; 292 293 return size; 294} 295 296 297/* 298 * ------------------------------------------------------------ 299 */ 300 301Buf_Buffer 302Buf_CreateFixedBuffer (size) 303 int size; 304{ 305 FixedBuffer* newBuf = (FixedBuffer*) Tcl_Alloc (sizeof(FixedBuffer) + size); 306 Buf_Buffer new = Buf_Create (&fix, (ClientData) newBuf); 307 308 newBuf->buf = new; 309 newBuf->size = size; 310 newBuf->readLoc = newBuf->data; 311 newBuf->writeLoc = newBuf->data; 312 newBuf->limit = newBuf->data + size; 313 314 return new; 315} 316 317