source: trunk/src/core/RpSimpleBuffer.h @ 2460

Last change on this file since 2460 was 2460, checked in by gah, 13 years ago
File size: 22.2 KB
Line 
1
2/*
3 * ======================================================================
4 *  Rappture::SimpleBuffer
5 *
6 *  AUTHOR:  Derrick Kearney, Purdue University
7 *
8 *  Copyright (c) 2004-2008  Purdue Research Foundation
9 * ----------------------------------------------------------------------
10 *  See the file "license.terms" for information on usage and
11 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * ======================================================================
13 *
14 *  This code is based on the Tcl_DString facility included in the
15 *  Tcl source release, which includes the following copyright:
16 *
17 *  Copyright (c) 1987-1993 The Regents of the University of California.
18 *  Copyright (c) 1994-1998 Sun Microsystems, Inc.
19 *  Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
20 *
21 *  This software is copyrighted by the Regents of the University of
22 *  California, Sun Microsystems, Inc., Scriptics Corporation,
23 *  and other parties.  The following terms apply to all files associated
24 *  with the software unless explicitly disclaimed in individual files.
25 *
26 *  The authors hereby grant permission to use, copy, modify, distribute,
27 *  and license this software and its documentation for any purpose, provided
28 *  that existing copyright notices are retained in all copies and that this
29 *  notice is included verbatim in any distributions. No written agreement,
30 *  license, or royalty fee is required for any of the authorized uses.
31 *  Modifications to this software may be copyrighted by their authors
32 *  and need not follow the licensing terms described here, provided that
33 *  the new terms are clearly indicated on the first page of each file where
34 *  they apply.
35 *
36 *  IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
37 *  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
38 *  ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
39 *  DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
40 *  POSSIBILITY OF SUCH DAMAGE.
41 *
42 *  THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
43 *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
44 *  FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
45 *  IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
46 *  NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
47 *  MODIFICATIONS.
48 *
49 *  GOVERNMENT USE: If you are acquiring this software on behalf of the
50 *  U.S. government, the Government shall have only "Restricted Rights"
51 *  in the software and related documentation as defined in the Federal·
52 *  Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
53 *  are acquiring the software on behalf of the Department of Defense, the
54 *  software shall be classified as "Commercial Computer Software" and the
55 *  Government shall have only "Restricted Rights" as defined in Clause
56 *  252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
57 *  authors grant the U.S. Government and others acting in its behalf
58 *  permission to use and distribute the software in accordance with the
59 *  terms specified in this license.·
60 *
61 * ======================================================================
62 */
63
64#ifndef RAPPTURE_SIMPLEBUFFER_H
65#define RAPPTURE_SIMPLEBUFFER_H
66
67#include <fstream>
68#include <cstring>
69#include <cstdlib>
70#include <cstdarg>
71
72/*
73 * Note: I think I would redo this class to deal only with unsigned byte
74 *       arrays, instead of arrays of <T>.  I would create other classes
75 *       that arrays of <T> that used the lower level byte array.
76 *
77 *       It would make it cleaner if the class only dealt with bytes
78 *       instead of elements (of various sizes). 
79 *
80 *       Specific implementations of <T> could perform data alignment on
81 *       word/double word/quad word boundaries.  This is an optimization
82 *       that should could done for double arrays.
83 *
84 * Note: The signed int argument on append() should be replaced with a
85 *       size_t.  This limits the length of strings to appended.  It
86 *       silently truncates bigger sizes to the lower 32-bits. 
87 */
88namespace Rappture {
89
90template <class T>
91class SimpleBuffer {
92public:
93    /**
94     * Construct an empty SimpleBuffer.
95     */
96    SimpleBuffer() {
97        Initialize();
98    }
99    /**
100     * Construct a SimpleBuffer loaded with initial data.
101     *
102     * @param bytes pointer to bytes being stored.
103     * @param nbytes number of bytes being stored.
104     */
105    SimpleBuffer(const T* bytes, int numElems=-1) {
106        Initialize();
107        append(bytes, numElems);
108    }
109    SimpleBuffer(size_t nmemb);
110   
111    /**
112     * Copy constructor
113     * @param SimpleBuffer object to copy
114     */
115    SimpleBuffer(const SimpleBuffer& b);
116   
117    SimpleBuffer<T>& operator=(const SimpleBuffer<T>& b);
118    SimpleBuffer     operator+(const SimpleBuffer& b) const;
119    SimpleBuffer<T>& operator+=(const SimpleBuffer<T>& b);
120    T operator[](size_t offset);
121   
122    /**
123     * Destructor
124     */
125    virtual ~SimpleBuffer() {
126        Release();
127    }
128   
129    /**
130     * Get the bytes currently stored in the buffer.  These bytes can
131     * be stored, and used later to construct another Buffer to
132     * decode the information.
133     *
134     * @return Pointer to the bytes in the buffer.
135     */
136    const T* bytes() const {
137        return _buf;
138    }
139    /**
140     * Get the number of bytes currently stored in the buffer.
141     * @return Number of the bytes used in the buffer.
142     */
143    size_t size() const {
144        return _numElemsUsed * sizeof(T);
145    }
146    /**
147     * Get the number of members currently stored in the buffer.
148     * @return Number of the members used in the buffer.
149     */
150    size_t nmemb() const {
151        return _numElemsUsed;
152    }
153    /**
154     * Get the number of members currently stored in the buffer.
155     * @return Number of the members used in the buffer.
156     */
157    size_t count() const {
158        return _numElemsUsed;
159    }
160    /**
161     * Set the number of members currently stored in the buffer.
162     * @return Number of the members used in the buffer.
163     */
164    size_t count(size_t newCount) {
165        _numElemsUsed = newCount;
166        return _numElemsUsed;
167    }
168    /**
169     * Clear the buffer, making it empty.
170     * @return Reference to this buffer.
171     */
172    SimpleBuffer<T>& clear() {
173        Release();
174        return *this;
175    }
176    size_t extend(size_t extraElems);
177    int append(const T* bytes, int nmemb=-1);
178    int appendf(const char *format, ...);
179    int remove(int nmemb);
180    size_t read(const T* bytes, size_t nmemb);
181    int seek(long offset, int whence);
182    int tell() const;
183    size_t set(size_t nmemb);
184    SimpleBuffer<T>& rewind();
185    SimpleBuffer<T>& show();
186   
187    bool good() const;
188    bool bad() const;
189    bool eof() const;
190   
191    SimpleBuffer<T>& move(SimpleBuffer<T>& b);
192   
193protected:
194   
195    void Initialize();
196    void Release();
197   
198private:
199   
200    /// Pointer to the memory that holds our buffer's data
201    T* _buf;
202   
203    /// Position offset within the buffer's memory
204    size_t _pos;
205   
206    /// Number of members stored in the buffer
207    size_t _numElemsUsed;
208   
209    /// Total number of members available in the buffer
210    size_t _numElemsAllocated;
211   
212    /// State of the last file like operation.
213    bool _fileState;
214   
215    /// Minimum number of members is set to the number you can fit in 256 bytes
216    const static size_t _minNumElems = (256/sizeof(T));
217   
218    size_t __guesslen(const T* bytes);
219   
220};
221   
222typedef SimpleBuffer<char>   SimpleCharBuffer;
223typedef SimpleBuffer<float>  SimpleFloatBuffer;
224typedef SimpleBuffer<double> SimpleDoubleBuffer;
225
226/**
227 * Construct an empty SimpleBuffer of specified size.
228 */
229template<class T>
230SimpleBuffer<T>::SimpleBuffer(size_t numElems)
231{
232    Initialize();
233
234    if (numElems == 0) {
235        // ignore requests for sizes equal to zero
236        return;
237    }
238
239    // buffer sizes less than min_size are set to min_size
240    if (numElems < (size_t) _minNumElems) {
241        numElems = _minNumElems;
242    }
243
244    if (set(numElems) != numElems) {
245        return;
246    }
247    _numElemsUsed = numElems;
248}
249
250
251/**
252 * Copy constructor
253 * @param SimpleBuffer object to copy
254 */
255template<class T>
256SimpleBuffer<T>::SimpleBuffer(const SimpleBuffer<T>& b)
257{
258    Initialize();
259    append(b.bytes(), b.nmemb());
260}
261
262
263/**
264 * Assignment operator
265 * @param SimpleBuffer object to copy
266 */
267template<class T>
268SimpleBuffer<T>&
269SimpleBuffer<T>::operator=(const SimpleBuffer<T>& b)
270{
271    Release();
272    append(b.bytes(),b.nmemb());
273    return *this;
274}
275
276
277/**
278 * Operator +
279 * @param SimpleBuffer object to add
280 */
281template<class T>
282SimpleBuffer<T>
283SimpleBuffer<T>::operator+(const SimpleBuffer<T>& b) const
284{
285    SimpleBuffer<T> newBuffer(*this);
286    newBuffer.operator+=(b);
287    return newBuffer;
288}
289
290
291/**
292 * Operator +=
293 * @param SimpleBuffer object to add
294 */
295template<class T>
296SimpleBuffer<T>&
297SimpleBuffer<T>::operator+=(const SimpleBuffer<T>& b)
298{
299    append(b.bytes(),b.nmemb());
300    return *this;
301}
302
303
304/**
305 * Operator []
306 * @param index into the buffer
307 */
308template<class T>
309T
310SimpleBuffer<T>::operator[](size_t index)
311{
312    return (_buf + index);              // Rely on pointer arithmetic
313}
314
315
316
317/**
318 * guess the length of a null terminated character buffer
319 * @param pointer to the buffer to guess the length of
320 * @return a guess of the length of the buffer.
321 */
322template<> inline
323size_t
324SimpleBuffer<char>::__guesslen(const char* bytes)
325{
326    return strlen(bytes);
327}
328
329/* FIXME:       Change the signed int to size_t.  Move the -1 copy string
330 *              up to the SimpleCharBuffer class.   There needs to be both
331 *              a heavy duty class that can take a string bigger than
332 *              2^31-1 in length, and a convenient class that doesn't make
333 *              you add call strlen(s).
334 *             
335 */
336
337/**
338 * guess the length of a non-null terminated character buffer
339 * @param pointer to the buffer to guess the length of
340 * @return a guess of the length of the buffer.
341 */
342template<class T>
343size_t
344SimpleBuffer<T>::__guesslen(const T* bytes)
345{
346    return (sizeof(T));
347}
348
349/**
350 * Append bytes to the end of this buffer
351 * @param pointer to bytes to be added
352 * @param number of bytes to be added
353 * @return number of bytes appended.
354 */
355template<class T>
356int
357SimpleBuffer<T>::append(const T* bytes, int numElems)
358{
359
360    // User specified NULL buffer to append
361    if (bytes == NULL) {
362        return 0;                       // Should not give append a NULL
363                                        // buffer pointer.
364    }
365
366    // FIXME: i think this needs to be division,
367    // need to create test case with array of ints
368    // i'm not sure we can even guess the number
369    // bytes in *bytes.
370
371    size_t numBytes = 0;
372    if (numElems == -1) {
373        /* This should be moved into the SimpleCharBuffer.  It doesn't make
374         * sense to look for a NUL byte unless it's a string buffer. We
375         * can then change numElems to be size_t. */
376        numBytes = __guesslen(bytes);
377        numElems = numBytes / sizeof(T);
378    }
379    if (numElems <= 0) {
380        return numElems;
381    }
382
383    size_t newSize;
384    newSize = _numElemsUsed + numElems;
385    if (newSize > _numElemsAllocated) {
386
387        // buffer sizes less than min_size are set to min_size
388        if (newSize < _minNumElems) {
389            newSize = _minNumElems;
390        }
391
392        /*
393         * Allocate a larger buffer for the string if the current one isn't
394         * large enough. Allocate extra space in the new buffer so that there
395         * will be room to grow before we have to allocate again.
396         */
397        size_t size;
398        size = (_numElemsAllocated > 0) ? _numElemsAllocated : _minNumElems;
399        while (newSize > size) {
400            size += size;
401        }
402
403        /*
404         * reallocate to a larger buffer
405         */
406        if (set(size) != size) {
407            return 0;
408        }
409    }
410    memcpy(_buf + _numElemsUsed, bytes, numElems * sizeof(T));
411    _numElemsUsed += numElems;
412    return numElems;
413}
414
415/**
416 * Append bytes to the end of this buffer
417 * @param pointer to bytes to be added
418 * @param number of bytes to be added
419 * @return number of bytes appended.
420 */
421template<class T>
422size_t
423SimpleBuffer<T>::extend(size_t numExtraElems)
424{
425    size_t newSize;
426
427    newSize = _numElemsUsed + numExtraElems;
428    if (newSize > _numElemsAllocated) {
429
430        /* Enforce a minimum buffer size. */
431        if (newSize < (size_t) _minNumElems) {
432            newSize = (size_t) _minNumElems;
433        }
434
435        size_t size;
436        size = (_numElemsAllocated > 0) ? _numElemsAllocated : _minNumElems;
437
438        /* Keep doubling the size of the buffer until we have enough space to
439         * hold the extra elements. */
440        while (newSize > size) {
441            size += size;
442        }
443        /* Reallocate to a larger buffer. */
444        if (set(size) != size) {
445            return 0;
446        }
447    }
448    return _numElemsAllocated;
449}
450
451/**
452 * Append formatted bytes to the end of this buffer
453 * @param pointer to bytes to be added
454 * @param number of bytes to be added
455 * @return number of bytes appended.
456 */
457template<class T>
458int
459SimpleBuffer<T>::appendf(const char *format, ...)
460{
461    size_t newMembCnt = 0;
462    size_t nbytes = 0;
463    int nmemb = 0;
464
465    char* dest = NULL;
466    size_t size = 0;
467    size_t bytesAdded = 0;
468    va_list arg;
469
470    // User specified NULL format
471    if (format == NULL) {
472        return 0;
473    }
474
475    // FIXME: i think this needs to be division,
476    // need to create test case with array of ints
477    // i'm not sure we can even guess the number
478    // bytes in *bytes.
479
480
481    // add one for terminating null character
482    nbytes = strlen(format) + 1;
483
484    if (nbytes <= 0) {
485        // no data written, invalid option
486        return nbytes;
487    }
488
489    // FIXME: we need ceil of nbytes/sizeof(T), instead we add 1 for safety
490
491    nmemb = nbytes/sizeof(T);
492    if (nmemb == 0) {
493        nmemb++;
494    }
495
496    newMembCnt = (size_t)(_numElemsUsed + nmemb);
497
498    if (newMembCnt > _numElemsAllocated) {
499
500        // buffer sizes less than min_size are set to min_size
501        if (newMembCnt < (size_t) _minNumElems) {
502            newMembCnt = (size_t) _minNumElems;
503        }
504
505        /*
506         * Allocate a larger buffer for the string if the current one isn't
507         * large enough. Allocate extra space in the new buffer so that there
508         * will be room to grow before we have to allocate again.
509         */
510        size_t membAvl;
511        membAvl = (_numElemsAllocated > 0) ? _numElemsAllocated : _minNumElems;
512        while (newMembCnt > membAvl) {
513            membAvl += membAvl;
514        }
515
516        /*
517         * reallocate to a larger buffer
518         */
519        if (set(membAvl) != membAvl) {
520            return 0;
521        }
522    }
523
524    dest = (char*) (_buf + _numElemsUsed);
525    size = (_numElemsAllocated-_numElemsUsed)*sizeof(T);
526
527    va_start(arg,format);
528    bytesAdded = vsnprintf(dest,size,format,arg);
529    va_end(arg);
530
531    // bytesAdded contains the number of bytes that would have
532    // been placed in the buffer if the call was successful.
533    // this value does not include the trailing null character.
534    // so we add one to account for it.
535
536    bytesAdded++;
537    nmemb = bytesAdded/sizeof(T);
538
539    if (bytesAdded > size) {
540        // we did not fit everything in the original buffer
541        // resize and try again.
542
543        // FIXME: round the new size up to the nearest multiple of 256?
544        set(_numElemsUsed+nmemb);
545
546        // reset dest because it may have moved during reallocation
547        dest = (char*) (_buf + _numElemsUsed);
548        size = bytesAdded;
549
550        va_start(arg,format);
551        bytesAdded = vsnprintf(dest,size,format,arg);
552        va_end(arg);
553
554        if (bytesAdded > size) {
555            // crystals grow, people grow, data doesn't grow...
556            // issue error
557            fprintf(stderr,"error in appendf while appending data");
558        }
559    }
560
561    _numElemsUsed += nmemb;
562
563    // remove the null character added by vsnprintf()
564    // we do this because if we are appending strings,
565    // the embedded null acts as a terminating null char.
566    // this is a generic buffer so if user wants a
567    // terminating null, they should append it.
568    remove(1);
569
570    return nmemb;
571}
572
573/**
574 * Remove bytes from the end of this buffer
575 * @param number of bytes to be removed
576 * @return number of bytes removed.
577 */
578template<class T>
579int
580SimpleBuffer<T>::remove(int nmemb)
581{
582    if ((_numElemsUsed - nmemb) < 0){
583        _numElemsUsed = 0;
584        _pos = 0;
585    } else {
586        _numElemsUsed -= nmemb;
587        if (_pos >= _numElemsUsed) {
588            // move _pos back to the new end of the buffer.
589            _pos = _numElemsUsed-1;
590        }
591    }
592
593
594    return nmemb;
595}
596
597template<class T>
598size_t
599SimpleBuffer<T>::set(size_t nmemb)
600{
601    T *buf;
602    size_t nbytes = nmemb*sizeof(T);
603
604    if (_buf == NULL) {
605        buf = (T*) malloc(nbytes);
606    } else {
607        buf = (T*) realloc((void*) _buf, nbytes);
608    }
609
610    if (buf == NULL) {
611        fprintf(stderr,"Can't allocate %lu bytes of memory\n",
612            (long unsigned int)nbytes);
613        _fileState = false;
614        return 0;
615    }
616    _buf = buf;
617    _numElemsAllocated = nmemb;
618    return _numElemsAllocated;
619}
620
621template<> inline
622SimpleBuffer<char>&
623SimpleBuffer<char>::show()
624{
625    size_t curMemb = 0;
626
627    while (curMemb != _numElemsUsed) {
628        fprintf(stdout,"_buf[%lu] = :%c:\n", (long unsigned int)curMemb,
629                _buf[curMemb]);
630        curMemb += 1;
631    }
632    fprintf(stdout,"_numElemsAllocated = :%lu:\n",
633            (long unsigned int)_numElemsAllocated);
634
635    return *this;
636}
637
638
639template<class T>
640SimpleBuffer<T>&
641SimpleBuffer<T>::show()
642{
643    size_t curMemb = 0;
644
645    while (curMemb != _numElemsUsed) {
646        fprintf(stdout,"_buf[%lu] = :%#x:\n", (long unsigned int)curMemb,
647                (unsigned long)_buf[curMemb]);
648        curMemb += 1;
649    }
650    fprintf(stdout,"_numElemsAllocated = :%lu:\n", (long unsigned int)_numElemsAllocated);
651
652    return *this;
653}
654
655
656/**
657 * Read data from the buffer into a memory location provided by caller
658 * @param Pointer locating where to place read bytes.
659 * @param Size of the memory location.
660 * @return Number of bytes written to memory location
661 */
662template<class T>
663size_t
664SimpleBuffer<T>::read(const T* bytes, size_t nmemb)
665{
666    size_t nMembRead = 0;
667
668    void* dest = NULL;
669    void const* src  = NULL;
670    size_t size = 0;
671
672    // SimpleBuffer is empty.
673    if (_buf == NULL) {
674        return 0;
675    }
676
677    // User specified NULL buffer.
678    if (bytes == NULL) {
679        return 0;
680    }
681
682    // make sure we don't read off the end of our buffer
683    if ( (_pos + nmemb) > _numElemsUsed ) {
684        nMembRead = _numElemsUsed - _pos;
685    }
686    else {
687        nMembRead = nmemb;
688    }
689
690    if (nMembRead <= 0) {
691        return 0;
692    }
693
694    dest = (void*) bytes;
695    src  = (void const*) (_buf + _pos);
696    size = nMembRead*sizeof(T);
697    memcpy(dest,src,size);
698
699    _pos = (_pos + nMembRead);
700
701    return nMembRead;
702}
703
704
705/**
706 * Set buffer position indicator to spot within the buffer
707 * @param Offset from whence location in buffer.
708 * @param Place from where offset is added or subtracted.
709 * @return 0 on success, anything else is failure
710 */
711template<class T>
712int
713SimpleBuffer<T>::seek(long offset, int whence)
714{
715    int retVal = 0;
716
717    if (_buf == NULL) {
718        return -1 ;
719    }
720
721    if (whence == SEEK_SET) {
722        if (offset < 0) {
723            /* dont go off the beginning of data */
724            _pos = 0;
725        }
726        else if (offset >= (long)_numElemsUsed) {
727            /* dont go off the end of data */
728            _pos = _numElemsUsed - 1;
729        }
730        else {
731            _pos = (size_t)(offset);
732        }
733    }
734    else if (whence == SEEK_CUR) {
735        if ( (_pos + offset) < 0) {
736            /* dont go off the beginning of data */
737            _pos = 0;
738        }
739        else if ((_pos + offset) >= _numElemsUsed) {
740            /* dont go off the end of data */
741            _pos = _numElemsUsed - 1;
742        }
743        else {
744            _pos = (size_t)(_pos + offset);
745        }
746    }
747    else if (whence == SEEK_END) {
748        if (offset <= (long)(-1*_numElemsUsed)) {
749            /* dont go off the beginning of data */
750            _pos = 0;
751        }
752        else if (offset >= 0) {
753            /* dont go off the end of data */
754            _pos = _numElemsUsed - 1;
755        }
756        else {
757            _pos = (size_t)((_numElemsUsed - 1) + offset);
758        }
759    }
760    else {
761        retVal = -1;
762    }
763
764    return retVal;
765}
766
767
768/**
769 * Tell caller the offset of the position indicator from the start of buffer
770 * @return Number of bytes the position indicator is from start of buffer
771 */
772template<class T>
773int
774SimpleBuffer<T>::tell() const
775{
776   return (int)_pos;
777}
778
779
780/**
781 * Move the internal position tracker to the beginning of the buffer.
782 */
783template<class T>
784SimpleBuffer<T>&
785SimpleBuffer<T>::rewind()
786{
787    _pos = 0;
788    return *this;
789}
790
791
792/**
793 * Tell if the last file like operation (ie. read()) was successful
794 * or if there was a failure like eof, or bad memory
795 * @return True or false boolean value
796 */
797template<class T>
798bool
799SimpleBuffer<T>::good() const
800{
801    return (_fileState);
802}
803
804
805/**
806 * Tell if the last file like operation (ie. read()) failed
807 * Opposite of good()
808 * @return True or false boolean value
809 */
810template<class T>
811bool
812SimpleBuffer<T>::bad() const
813{
814    return (!_fileState);
815}
816
817
818/**
819 * Tell if the position flag is at the end of the buffer
820 * @return True or false boolean value
821 */
822template<class T>
823bool
824SimpleBuffer<T>::eof() const
825{
826    return (_pos >= _numElemsUsed);
827}
828
829
830/**
831 * Move the data from this SimpleBuffer to the SimpleBuffer provided by
832 * the caller. All data except the _pos is moved and this SimpleBuffer is
833 * re-initialized with Initialize().
834 * @param SimpleBuffer to move the information to
835 * @return reference to this SimpleBuffer object.
836 */
837template<class T>
838SimpleBuffer<T>&
839SimpleBuffer<T>::move(SimpleBuffer<T>& b)
840{
841    Release();
842
843    _buf = b._buf;
844    _pos = b._pos;
845    _fileState = b._fileState;
846    _numElemsUsed = b._numElemsUsed;
847    _numElemsAllocated = b._numElemsAllocated;
848
849    b.Initialize();
850
851    return *this;
852}
853
854
855 /**
856  *  Initializes a dynamic buffer, discarding any previous contents
857  *  of the buffer. Release() should have been called already
858  *  if the dynamic buffer was previously in use.
859  */
860template<class T>
861void
862SimpleBuffer<T>::Initialize()
863{
864    _buf = NULL;
865    _pos = 0;
866    _fileState = true;
867    _numElemsUsed = 0;
868    _numElemsAllocated = 0;
869}
870
871
872/**
873 *  Frees up any memory allocated for the dynamic buffer and
874 *  reinitializes the buffer to an empty state.
875 */
876template<class T>
877void
878SimpleBuffer<T>::Release()
879{
880    if (_buf != NULL) {
881        free(_buf);
882        _buf = NULL;
883    }
884    Initialize();
885}
886
887} // namespace Rappture
888
889#endif // RAPPTURE_SIMPLEBUFFER_H
Note: See TracBrowser for help on using the repository browser.