2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
27 * $XConsortium: Buffer.C /main/6 1996/04/21 19:47:10 drk $
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special
32 * restrictions in a confidential disclosure agreement between
33 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 * document outside HP, IBM, Sun, USL, SCO, or Univel without
35 * Sun's specific written approval. This document and all copies
36 * and derivative works thereof must be returned or destroyed at
39 * Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
44 #include <DtMail/Buffer.hh>
52 #include <DtMail/Threads.hh>
54 const int Buffer::defaultchunksize = 16 * 1024;
57 // buffer.C -- implement buffer class
62 BufferMemory::initBuffer(int chunksize)
68 _chunksize = chunksize;
73 BufferMemory::BufferMemory()
75 initBuffer(defaultchunksize);
78 BufferMemory::BufferMemory(int chunksize)
80 initBuffer(chunksize);
84 BufferMemory::~BufferMemory()
86 MutexLock mutex(_mutex);
88 // free the data in the buffer
89 Chunk *c = _firstchunk;
100 // disassociate us from all the readers
101 BufReaderMemory *r = _firstreader;
108 mutex.unlock_and_destroy();
115 Buffer::~Buffer() { }
116 BufReader::~BufReader() { }
119 // buffer memory class functions
121 BufferMemory::appendData(const char *user_buffer, int length)
126 MutexLock mutex(_mutex);
128 while (numwritten < length) {
129 if (! _lastchunk || _lastchunk->_chunksize <= _lastchunk->_currentend) {
130 // we need to get a new data chunk
131 if (newChunk(length - numwritten) < 0) {
133 // we had an allocation error
138 // number of free bytes in data chunk
139 numbytes = _lastchunk->_chunksize - _lastchunk->_currentend;
141 // don't write more than remaining bytes in user's request
142 if (numbytes > length - numwritten) {
143 numbytes = length - numwritten;
147 (void) memcpy(&_lastchunk->_buffer[_lastchunk->_currentend],
148 user_buffer, numbytes);
150 // update the counters
151 numwritten += numbytes;
152 _totalsize += numbytes;
153 _lastchunk->_currentend += numbytes;
154 user_buffer += numbytes;
162 // add a new data chunk to the buffer
164 BufferMemory::newChunk(int size)
166 // make sure we get at least the default chunksize
167 if (size < _chunksize) size = _chunksize;
169 // allocate the data regions
170 Chunk *d = (Chunk *) malloc(sizeof (Chunk));
171 if (! d) return (-1);
173 d->_buffer = (char *) malloc(size);
179 d->_chunksize = size;
182 // now splice it into the list
183 // lock should already have been called
185 d->_nextchunk = NULL;
186 if (_firstchunk == NULL) _firstchunk = d;
189 _lastchunk->_nextchunk = d;
198 BufferMemory::getReader(void)
202 MutexLock mutex(_mutex);
204 r = new BufReaderMemory(this);
211 BufferMemory::iterate(Buffer::CallBack callback, ...)
214 MutexLock mutex(_mutex);
216 unsigned long ret = 0;
218 va_start(va, callback);
220 // walk through the chunk list, calling the callback for each one
221 for (c = _firstchunk; c; c = c->_nextchunk) {
223 // don't bother with null length chunks
224 if (c->_currentend == 0) continue;
227 ret = (*callback)(c->_buffer, c->_currentend, va);
229 // check for problems
241 //------------- beginning of bufreader code
243 BufReader::BufReader() {}
245 BufReaderMemory::BufReaderMemory(BufferMemory *b)
248 MutexLock mutex(b->_mutex);
251 _nextreader = b->_firstreader;
254 if (b->_firstreader) {
255 b->_firstreader->_prevreader = this;
257 b->_firstreader = this;
260 _currentchunk = NULL;
265 BufferMemory::getSize()
272 BufReaderMemory::getData(char *user_buffer, int length)
278 // the buffer has already been freed
282 MutexLock mutex(_buffer->_mutex);
284 // handle starup case
285 if (_currentchunk == NULL) {
286 _currentchunk = _buffer->_firstchunk;
288 // see if buffer is still empty
289 if (!_currentchunk) {
296 numbytes = _currentchunk->_currentend - _currentoffset;
299 // we are at the end of this data chunk
300 if (_currentchunk->_nextchunk == NULL) {
301 // we are at the end of the valid data
305 // advance to the next chunk
306 _currentchunk = _currentchunk->_nextchunk;
311 // don't read more than user requested
312 if (numbytes > length - numread) {
313 numbytes = length - numread;
317 memcpy(user_buffer, &_currentchunk->_buffer[_currentoffset], numbytes);
319 // update all the pointers
321 user_buffer += numbytes;
322 _currentoffset += numbytes;
324 } while (numread < length);
330 BufReaderMemory::~BufReaderMemory()
333 if (! _buffer) return;
334 MutexLock mutex(_buffer->_mutex);
336 // unlink us from the buffer's list
338 _nextreader->_prevreader = _prevreader;
342 _prevreader->_nextreader = _nextreader;
344 // ASSERT(_buffer->_firstreader == this);
345 _buffer->_firstreader = _nextreader;