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 librararies 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>
50 #if defined(USL) && (OSMAJORVERSION == 2)
53 #if defined(USL) && (OSMAJORVERSION == 2)
59 #include <DtMail/Threads.hh>
61 const int Buffer::defaultchunksize = 16 * 1024;
64 // buffer.C -- implement buffer class
69 BufferMemory::initBuffer(int chunksize)
75 _chunksize = chunksize;
80 BufferMemory::BufferMemory()
82 initBuffer(defaultchunksize);
85 BufferMemory::BufferMemory(int chunksize)
87 initBuffer(chunksize);
91 BufferMemory::~BufferMemory()
93 MutexLock mutex(_mutex);
95 // free the data in the buffer
96 Chunk *c = _firstchunk;
100 next = c->_nextchunk;
107 // disassociate us from all the readers
108 BufReaderMemory *r = _firstreader;
115 mutex.unlock_and_destroy();
122 Buffer::~Buffer() { }
123 BufReader::~BufReader() { }
126 // buffer memory class functions
128 BufferMemory::appendData(const char *user_buffer, int length)
133 MutexLock mutex(_mutex);
135 while (numwritten < length) {
136 if (! _lastchunk || _lastchunk->_chunksize <= _lastchunk->_currentend) {
137 // we need to get a new data chunk
138 if (newChunk(length - numwritten) < 0) {
140 // we had an allocation error
145 // number of free bytes in data chunk
146 numbytes = _lastchunk->_chunksize - _lastchunk->_currentend;
148 // don't write more than remaining bytes in user's request
149 if (numbytes > length - numwritten) {
150 numbytes = length - numwritten;
154 (void) memcpy(&_lastchunk->_buffer[_lastchunk->_currentend],
155 user_buffer, numbytes);
157 // update the counters
158 numwritten += numbytes;
159 _totalsize += numbytes;
160 _lastchunk->_currentend += numbytes;
161 user_buffer += numbytes;
169 // add a new data chunk to the buffer
171 BufferMemory::newChunk(int size)
173 // make sure we get at least the default chunksize
174 if (size < _chunksize) size = _chunksize;
176 // allocate the data regions
177 Chunk *d = (Chunk *) malloc(sizeof (Chunk));
178 if (! d) return (-1);
180 d->_buffer = (char *) malloc(size);
186 d->_chunksize = size;
189 // now splice it into the list
190 // lock should already have been called
192 d->_nextchunk = NULL;
193 if (_firstchunk == NULL) _firstchunk = d;
196 _lastchunk->_nextchunk = d;
205 BufferMemory::getReader(void)
209 MutexLock mutex(_mutex);
211 r = new BufReaderMemory(this);
218 BufferMemory::iterate(Buffer::CallBack callback, ...)
221 MutexLock mutex(_mutex);
223 unsigned long ret = 0;
225 va_start(va, callback);
227 // walk through the chunk list, calling the callback for each one
228 for (c = _firstchunk; c; c = c->_nextchunk) {
230 // don't bother with null length chunks
231 if (c->_currentend == 0) continue;
234 ret = (*callback)(c->_buffer, c->_currentend, va);
236 // check for problems
246 //------------- beginning of bufreader code
248 BufReader::BufReader() {}
250 BufReaderMemory::BufReaderMemory(BufferMemory *b)
253 MutexLock mutex(b->_mutex);
256 _nextreader = b->_firstreader;
259 if (b->_firstreader) {
260 b->_firstreader->_prevreader = this;
262 b->_firstreader = this;
265 _currentchunk = NULL;
270 BufferMemory::getSize()
277 BufReaderMemory::getData(char *user_buffer, int length)
283 // the buffer has already been freed
287 MutexLock mutex(_buffer->_mutex);
289 // handle starup case
290 if (_currentchunk == NULL) {
291 _currentchunk = _buffer->_firstchunk;
293 // see if buffer is still empty
294 if (!_currentchunk) {
301 numbytes = _currentchunk->_currentend - _currentoffset;
304 // we are at the end of this data chunk
305 if (_currentchunk->_nextchunk == NULL) {
306 // we are at the end of the valid data
310 // advance to the next chunk
311 _currentchunk = _currentchunk->_nextchunk;
316 // don't read more than user requested
317 if (numbytes > length - numread) {
318 numbytes = length - numread;
322 memcpy(user_buffer, &_currentchunk->_buffer[_currentoffset], numbytes);
324 // update all the pointers
326 user_buffer += numbytes;
327 _currentoffset += numbytes;
329 } while (numread < length);
335 BufReaderMemory::~BufReaderMemory()
338 if (! _buffer) return;
339 MutexLock mutex(_buffer->_mutex);
341 // unlink us from the buffer's list
343 _nextreader->_prevreader = _prevreader;
347 _prevreader->_nextreader = _nextreader;
349 // ASSERT(_buffer->_firstreader == this);
350 _buffer->_firstreader = _nextreader;