5 * $XConsortium: Buffer.C /main/6 1996/04/21 19:47:10 drk $
7 * RESTRICTED CONFIDENTIAL INFORMATION:
9 * The information in this document is subject to special
10 * restrictions in a confidential disclosure agreement between
11 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
12 * document outside HP, IBM, Sun, USL, SCO, or Univel without
13 * Sun's specific written approval. This document and all copies
14 * and derivative works thereof must be returned or destroyed at
17 * Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
22 #include <DtMail/Buffer.hh>
28 #if defined(USL) && (OSMAJORVERSION == 2)
32 #if defined(USL) && (OSMAJORVERSION == 2)
38 #include <DtMail/Threads.hh>
40 const int Buffer::defaultchunksize = 16 * 1024;
43 // buffer.C -- implement buffer class
48 BufferMemory::initBuffer(int chunksize)
54 _chunksize = chunksize;
59 BufferMemory::BufferMemory()
61 initBuffer(defaultchunksize);
64 BufferMemory::BufferMemory(int chunksize)
66 initBuffer(chunksize);
70 BufferMemory::~BufferMemory()
72 MutexLock mutex(_mutex);
74 // free the data in the buffer
75 Chunk *c = _firstchunk;
86 // disassociate us from all the readers
87 BufReaderMemory *r = _firstreader;
94 mutex.unlock_and_destroy();
101 Buffer::~Buffer() { }
102 BufReader::~BufReader() { }
105 // buffer memory class functions
107 BufferMemory::appendData(const char *user_buffer, int length)
112 MutexLock mutex(_mutex);
114 while (numwritten < length) {
115 if (! _lastchunk || _lastchunk->_chunksize <= _lastchunk->_currentend) {
116 // we need to get a new data chunk
117 if (newChunk(length - numwritten) < 0) {
119 // we had an allocation error
124 // number of free bytes in data chunk
125 numbytes = _lastchunk->_chunksize - _lastchunk->_currentend;
127 // don't write more than remaining bytes in user's request
128 if (numbytes > length - numwritten) {
129 numbytes = length - numwritten;
133 (void) memcpy(&_lastchunk->_buffer[_lastchunk->_currentend],
134 user_buffer, numbytes);
136 // update the counters
137 numwritten += numbytes;
138 _totalsize += numbytes;
139 _lastchunk->_currentend += numbytes;
140 user_buffer += numbytes;
148 // add a new data chunk to the buffer
150 BufferMemory::newChunk(int size)
152 // make sure we get at least the default chunksize
153 if (size < _chunksize) size = _chunksize;
155 // allocate the data regions
156 Chunk *d = (Chunk *) malloc(sizeof (Chunk));
157 if (! d) return (-1);
159 d->_buffer = (char *) malloc(size);
165 d->_chunksize = size;
168 // now splice it into the list
169 // lock should already have been called
171 d->_nextchunk = NULL;
172 if (_firstchunk == NULL) _firstchunk = d;
175 _lastchunk->_nextchunk = d;
184 BufferMemory::getReader(void)
188 MutexLock mutex(_mutex);
190 r = new BufReaderMemory(this);
197 BufferMemory::iterate(Buffer::CallBack callback, ...)
200 MutexLock mutex(_mutex);
202 unsigned long ret = 0;
204 va_start(va, callback);
206 // walk through the chunk list, calling the callback for each one
207 for (c = _firstchunk; c; c = c->_nextchunk) {
209 // don't bother with null length chunks
210 if (c->_currentend == 0) continue;
213 ret = (*callback)(c->_buffer, c->_currentend, va);
215 // check for problems
225 //------------- beginning of bufreader code
227 BufReader::BufReader() {}
229 BufReaderMemory::BufReaderMemory(BufferMemory *b)
232 MutexLock mutex(b->_mutex);
235 _nextreader = b->_firstreader;
238 if (b->_firstreader) {
239 b->_firstreader->_prevreader = this;
241 b->_firstreader = this;
244 _currentchunk = NULL;
249 BufferMemory::getSize()
256 BufReaderMemory::getData(char *user_buffer, int length)
262 // the buffer has already been freed
266 MutexLock mutex(_buffer->_mutex);
268 // handle starup case
269 if (_currentchunk == NULL) {
270 _currentchunk = _buffer->_firstchunk;
272 // see if buffer is still empty
273 if (!_currentchunk) {
280 numbytes = _currentchunk->_currentend - _currentoffset;
283 // we are at the end of this data chunk
284 if (_currentchunk->_nextchunk == NULL) {
285 // we are at the end of the valid data
289 // advance to the next chunk
290 _currentchunk = _currentchunk->_nextchunk;
295 // don't read more than user requested
296 if (numbytes > length - numread) {
297 numbytes = length - numread;
301 memcpy(user_buffer, &_currentchunk->_buffer[_currentoffset], numbytes);
303 // update all the pointers
305 user_buffer += numbytes;
306 _currentoffset += numbytes;
308 } while (numread < length);
314 BufReaderMemory::~BufReaderMemory()
317 if (! _buffer) return;
318 MutexLock mutex(_buffer->_mutex);
320 // unlink us from the buffer's list
322 _nextreader->_prevreader = _prevreader;
326 _prevreader->_nextreader = _nextreader;
328 // ASSERT(_buffer->_firstreader == this);
329 _buffer->_firstreader = _nextreader;