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