source: trunk/src/core/RpSimpleBuffer.cc @ 1038

Last change on this file since 1038 was 1038, checked in by dkearney, 16 years ago

adding the simple buffer object back to the repository because it was accidentally removed in rev 1018

File size: 11.9 KB
Line 
1/*
2 * ======================================================================
3 *  Rappture::SimpleBuffer
4 *
5 *  AUTHOR:  Derrick Kearney, Purdue University
6 *
7 *  Copyright (c) 2004-2008  Purdue Research Foundation
8 * ----------------------------------------------------------------------
9 *  See the file "license.terms" for information on usage and
10 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * ======================================================================
12 *
13 *  This code is based on the Tcl_DString facility included in the
14 *  Tcl source release, which includes the following copyright:
15 *
16 *  Copyright (c) 1987-1993 The Regents of the University of California.
17 *  Copyright (c) 1994-1998 Sun Microsystems, Inc.
18 *  Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
19 *
20 *  This software is copyrighted by the Regents of the University of
21 *  California, Sun Microsystems, Inc., Scriptics Corporation,
22 *  and other parties.  The following terms apply to all files associated
23 *  with the software unless explicitly disclaimed in individual files.
24 *
25 *  The authors hereby grant permission to use, copy, modify, distribute,
26 *  and license this software and its documentation for any purpose, provided
27 *  that existing copyright notices are retained in all copies and that this
28 *  notice is included verbatim in any distributions. No written agreement,
29 *  license, or royalty fee is required for any of the authorized uses.
30 *  Modifications to this software may be copyrighted by their authors
31 *  and need not follow the licensing terms described here, provided that
32 *  the new terms are clearly indicated on the first page of each file where
33 *  they apply.
34 *
35 *  IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
36 *  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
37 *  ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
38 *  DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
39 *  POSSIBILITY OF SUCH DAMAGE.
40 *
41 *  THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
42 *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
43 *  FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
44 *  IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
45 *  NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
46 *  MODIFICATIONS.
47 *
48 *  GOVERNMENT USE: If you are acquiring this software on behalf of the
49 *  U.S. government, the Government shall have only "Restricted Rights"
50 *  in the software and related documentation as defined in the Federal·
51 *  Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
52 *  are acquiring the software on behalf of the Department of Defense, the
53 *  software shall be classified as "Commercial Computer Software" and the
54 *  Government shall have only "Restricted Rights" as defined in Clause
55 *  252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
56 *  authors grant the U.S. Government and others acting in its behalf
57 *  permission to use and distribute the software in accordance with the
58 *  terms specified in this license.·
59 *
60 * ======================================================================
61 */
62
63#include "RpSimpleBuffer.h"
64
65#ifdef __cplusplus
66    extern "C" {
67#endif // ifdef __cplusplus
68
69using namespace Rappture;
70
71/**
72 * Construct an empty SimpleBuffer.
73 */
74SimpleBuffer::SimpleBuffer()
75{
76    bufferInit();
77}
78
79
80/**
81 * Construct an empty SimpleBuffer of specified size.
82 */
83SimpleBuffer::SimpleBuffer(int nbytes)
84{
85    char* newBuffer = NULL;
86
87    bufferInit();
88
89    if (nbytes == 0) {
90        // ignore requests for sizes equal to zero
91        return;
92    } else if (nbytes < 0) {
93        // sizes less than zero are set to min_size
94        nbytes = RP_SIMPLEBUFFER_MIN_SIZE;
95    } else {
96        // keep nbytes at requested size
97    }
98
99    newBuffer = new char[nbytes];
100    if (newBuffer == NULL) {
101        // memory error
102        _fileState = false;
103    } else {
104        _spaceAvl = nbytes;
105        _size = nbytes;
106        _buf = newBuffer;
107    }
108}
109
110
111/**
112 * Construct a SimpleBuffer loaded with initial data.
113 *
114 * @param bytes pointer to bytes being stored.
115 * @param nbytes number of bytes being stored.
116 */
117SimpleBuffer::SimpleBuffer(const char* bytes, int nbytes)
118{
119    bufferInit();
120    append(bytes,nbytes);
121}
122
123
124/**
125 * Copy constructor
126 * @param SimpleBuffer object to copy
127 */
128SimpleBuffer::SimpleBuffer(const SimpleBuffer& b)
129{
130    bufferInit();
131    append(b.bytes(),b.size());
132}
133
134
135/**
136 * Assignment operator
137 * @param SimpleBuffer object to copy
138 */
139SimpleBuffer&
140SimpleBuffer::operator=(const SimpleBuffer& b)
141{
142    bufferFree();
143    bufferInit();
144    append(b.bytes(),b.size());
145    return *this;
146}
147
148
149/**
150 * Operator +
151 * @param SimpleBuffer object to add
152 */
153SimpleBuffer
154SimpleBuffer::operator+(const SimpleBuffer& b) const
155{
156    SimpleBuffer newBuffer(*this);
157    newBuffer.operator+=(b);
158    return newBuffer;
159}
160
161
162/**
163 * Operator +=
164 * @param SimpleBuffer object to add
165 */
166SimpleBuffer&
167SimpleBuffer::operator+=(const SimpleBuffer& b)
168{
169    append(b.bytes(),b.size());
170    return *this;
171}
172
173
174/**
175 * Destructor
176 */
177SimpleBuffer::~SimpleBuffer()
178{
179    bufferFree();
180}
181
182
183/**
184 * Get the bytes currently stored in the buffer.  These bytes can
185 * be stored, and used later to construct another Buffer to
186 * decode the information.
187 *
188 * @return Pointer to the bytes in the buffer.
189 */
190const char*
191SimpleBuffer::bytes() const
192{
193    return _buf;
194}
195
196
197/**
198 * Get the number of bytes currently stored in the buffer.
199 * @return Number of the bytes used in the buffer.
200 */
201unsigned int
202SimpleBuffer::size() const
203{
204    return _size;
205}
206
207
208/**
209 * Clear the buffer, making it empty.
210 * @return Reference to this buffer.
211 */
212SimpleBuffer&
213SimpleBuffer::clear()
214{
215    bufferFree();
216    bufferInit();
217
218    return *this;
219}
220
221
222/**
223 * Append bytes to the end of this buffer
224 * @param Buffer object to copy
225 * @return Reference to this buffer.
226 */
227int
228SimpleBuffer::append(const char* bytes, int nbytes)
229{
230    unsigned int newSize = 0;
231    char *newBuffer = NULL;
232
233    // User specified NULL buffer to append
234    if ( (bytes == NULL) && (nbytes < 1) ) {
235        return 0;
236    }
237
238    if (nbytes == -1) {
239        // user signaled null terminated string
240        nbytes = strlen(bytes);
241    }
242
243    if (nbytes <= 0) {
244        // no data written, invalid option
245        return nbytes;
246    }
247
248    // Empty internal buffer, make sure its properly initialized.
249    if (_buf == NULL) {
250        bufferInit();
251    }
252
253    newSize = (unsigned int)(_size + nbytes);
254
255    // ensure that our smallest buffer is RP_SIMPLEBUFFER_MIN_SIZE bytes
256    if (newSize < (RP_SIMPLEBUFFER_MIN_SIZE/2)) {
257        newSize = (RP_SIMPLEBUFFER_MIN_SIZE/2);
258    }
259
260    /*
261     * Allocate a larger buffer for the string if the current one isn't
262     * large enough. Allocate extra space in the new buffer so that there
263     * will be room to grow before we have to allocate again.
264     */
265
266    if (newSize >= _spaceAvl) {
267        _spaceAvl = newSize * 2;
268        newBuffer = new char[_spaceAvl];
269        if (newBuffer == NULL) {
270            // return memory error
271            return -1;
272        }
273        if (_buf != NULL) {
274            memcpy((void*) newBuffer, (void*) _buf, (size_t) _size);
275            delete [] _buf;
276            _buf = NULL;
277        }
278        _buf = newBuffer;
279    }
280
281    memcpy((void*) (_buf + _size), (void*) bytes, (size_t) nbytes);
282
283    _size = _size + (unsigned int) nbytes;
284
285    return nbytes;
286}
287
288
289/**
290 * Read data from the buffer into a memory location provided by caller
291 * @param Pointer locating where to place read bytes.
292 * @param Size of the memory location.
293 * @return Number of bytes written to memory location
294 */
295int
296SimpleBuffer::read(const char* bytes, int nbytes)
297{
298    unsigned int bytesRead = 0;
299
300    // SimpleBuffer is empty.
301    if (_buf == NULL) {
302        return 0;
303    }
304
305    // User specified NULL buffer.
306    if (bytes == NULL) {
307        return 0;
308    }
309
310    // User specified negative buffer size
311    if (nbytes <= 0) {
312        return 0;
313    }
314
315    // make sure we don't read off the end of our buffer
316    if ( (_pos + nbytes) >= _size ) {
317        bytesRead = (_size - _pos);
318    }
319    else {
320        bytesRead = (unsigned int) nbytes;
321    }
322
323    if (bytesRead <= 0) {
324        return 0;
325    }
326
327    if (bytesRead > 0) {
328        memcpy((void*) bytes, (void*) (_buf+_pos), (size_t) bytesRead);
329    }
330
331    _pos = (_pos + bytesRead);
332
333    return (int)bytesRead;
334}
335
336
337/**
338 * Set buffer position indicator to spot within the buffer
339 * @param Offset from whence location in buffer.
340 * @param Place from where offset is added or subtracted.
341 * @return 0 on success, anything else is failure
342 */
343int
344SimpleBuffer::seek(int offset, int whence)
345{
346    int retVal = 0;
347
348    if (_buf == NULL) {
349        return -1 ;
350    }
351
352    if (whence == SEEK_SET) {
353        if (offset < 0) {
354            /* dont go off the beginning of data */
355            _pos = 0;
356        }
357        else if (offset >= (int)_size) {
358            /* dont go off the end of data */
359            _pos = _size - 1;
360        }
361        else {
362            _pos = (unsigned int)(_pos + offset);
363        }
364    }
365    else if (whence == SEEK_CUR) {
366        if ( (_pos + offset) < 0) {
367            /* dont go off the beginning of data */
368            _pos = 0;
369        }
370        else if ((_pos + offset) >= _size) {
371            /* dont go off the end of data */
372            _pos = _size - 1;
373        }
374        else {
375            _pos = (unsigned int)(_pos + offset);
376        }
377    }
378    else if (whence == SEEK_END) {
379        if (offset <= (-1*((int)_size))) {
380            /* dont go off the beginning of data */
381            _pos = 0;
382        }
383        else if (offset >= 0) {
384            /* dont go off the end of data */
385            _pos = _size - 1;
386        }
387        else {
388            _pos = (unsigned int)((_size - 1) + offset);
389        }
390    }
391    else {
392        retVal = -1;
393    }
394
395    return retVal;
396}
397
398
399/**
400 * Tell caller the offset of the position indicator from the start of buffer
401 * @return Number of bytes the position indicator is from start of buffer
402 */
403int
404SimpleBuffer::tell() const
405{
406   return (int)_pos;
407}
408
409
410/**
411 * Read data from the buffer into a memory location provided by caller
412 */
413SimpleBuffer&
414SimpleBuffer::rewind()
415{
416    _pos = 0;
417    return *this;
418}
419
420
421/**
422 * Tell if the last file like operation (ie. read()) was successful
423 * or if there was a failure like eof, or bad memory
424 * @return True or false boolean value
425 */
426bool
427SimpleBuffer::good() const
428{
429    return (_fileState);
430}
431
432
433/**
434 * Tell if the last file like operation (ie. read()) failed
435 * Opposite of good()
436 * @return True or false boolean value
437 */
438bool
439SimpleBuffer::bad() const
440{
441    return (!_fileState);
442}
443
444
445/**
446 * Tell if the position flag is at the end of the buffer
447 * @return True or false boolean value
448 */
449bool
450SimpleBuffer::eof() const
451{
452    return (_pos >= _size);
453}
454
455
456/**
457 * Move the data from this SimpleBuffer to the SimpleBuffer provided by
458 * the caller. All data except the _pos is moved and this SimpleBuffer is
459 * re-initialized with bufferInit().
460 * @param SimpleBuffer to move the information to
461 * @return reference to this SimpleBuffer object.
462 */
463SimpleBuffer&
464SimpleBuffer::move(SimpleBuffer& b)
465{
466    bufferFree();
467
468    _buf = b._buf;
469    _pos = b._pos;
470    _size = b._size;
471    _spaceAvl = b._spaceAvl;
472    _fileState = b._fileState;
473
474    b.bufferInit();
475
476    return *this;
477}
478
479
480 /**
481  *  Initializes a dynamic buffer, discarding any previous contents
482  *  of the buffer. bufferFree() should have been called already
483  *  if the dynamic buffer was previously in use.
484  */
485void
486SimpleBuffer::bufferInit()
487{
488    _buf = NULL;
489    _pos = 0;
490    _size = 0;
491    _spaceAvl = 0;
492    _fileState = true;
493}
494
495
496/**
497 *  Frees up any memory allocated for the dynamic buffer and
498 *  reinitializes the buffer to an empty state.
499 */
500void
501SimpleBuffer::bufferFree()
502{
503    if (_buf != NULL) {
504        delete [] _buf;
505        _buf = NULL;
506    }
507    bufferInit();
508}
509
510
511
512#ifdef __cplusplus
513    }
514#endif // ifdef __cplusplus
515
Note: See TracBrowser for help on using the repository browser.