source: branches/1.3/src/core/RpSimpleBuffer.h @ 5348

Last change on this file since 5348 was 3604, checked in by ldelgass, 11 years ago

Buffer ctor that takes a size to reserve should not set any elts as used, only
as allocated.

File size: 22.2 KB
Line 
1
2/*
3 * ======================================================================
4 *  Rappture::SimpleBuffer
5 *
6 *  AUTHOR:  Derrick Kearney, Purdue University
7 *
8 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
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}
248
249
250/**
251 * Copy constructor
252 * @param SimpleBuffer object to copy
253 */
254template<class T>
255SimpleBuffer<T>::SimpleBuffer(const SimpleBuffer<T>& b)
256{
257    Initialize();
258    append(b.bytes(), b.nmemb());
259}
260
261
262/**
263 * Assignment operator
264 * @param SimpleBuffer object to copy
265 */
266template<class T>
267SimpleBuffer<T>&
268SimpleBuffer<T>::operator=(const SimpleBuffer<T>& b)
269{
270    Release();
271    append(b.bytes(),b.nmemb());
272    return *this;
273}
274
275
276/**
277 * Operator +
278 * @param SimpleBuffer object to add
279 */
280template<class T>
281SimpleBuffer<T>
282SimpleBuffer<T>::operator+(const SimpleBuffer<T>& b) const
283{
284    SimpleBuffer<T> newBuffer(*this);
285    newBuffer.operator+=(b);
286    return newBuffer;
287}
288
289
290/**
291 * Operator +=
292 * @param SimpleBuffer object to add
293 */
294template<class T>
295SimpleBuffer<T>&
296SimpleBuffer<T>::operator+=(const SimpleBuffer<T>& b)
297{
298    append(b.bytes(),b.nmemb());
299    return *this;
300}
301
302
303/**
304 * Operator []
305 * @param index into the buffer
306 */
307template<class T>
308T
309SimpleBuffer<T>::operator[](size_t index)
310{
311    return (_buf + index);              // Rely on pointer arithmetic
312}
313
314
315
316/**
317 * guess the length of a null terminated character buffer
318 * @param pointer to the buffer to guess the length of
319 * @return a guess of the length of the buffer.
320 */
321template<> inline
322size_t
323SimpleBuffer<char>::__guesslen(const char* bytes)
324{
325    return strlen(bytes);
326}
327
328/* FIXME:       Change the signed int to size_t.  Move the -1 copy string
329 *              up to the SimpleCharBuffer class.   There needs to be both
330 *              a heavy duty class that can take a string bigger than
331 *              2^31-1 in length, and a convenient class that doesn't make
332 *              you add call strlen(s).
333 *             
334 */
335
336/**
337 * guess the length of a non-null terminated character buffer
338 * @param pointer to the buffer to guess the length of
339 * @return a guess of the length of the buffer.
340 */
341template<class T>
342size_t
343SimpleBuffer<T>::__guesslen(const T* bytes)
344{
345    return (sizeof(T));
346}
347
348/**
349 * Append bytes to the end of this buffer
350 * @param pointer to bytes to be added
351 * @param number of bytes to be added
352 * @return number of bytes appended.
353 */
354template<class T>
355int
356SimpleBuffer<T>::append(const T* bytes, int numElems)
357{
358
359    // User specified NULL buffer to append
360    if (bytes == NULL) {
361        return 0;                       // Should not give append a NULL
362                                        // buffer pointer.
363    }
364
365    // FIXME: i think this needs to be division,
366    // need to create test case with array of ints
367    // i'm not sure we can even guess the number
368    // bytes in *bytes.
369
370    size_t numBytes = 0;
371    if (numElems == -1) {
372        /* This should be moved into the SimpleCharBuffer.  It doesn't make
373         * sense to look for a NUL byte unless it's a string buffer. We
374         * can then change numElems to be size_t. */
375        numBytes = __guesslen(bytes);
376        numElems = numBytes / sizeof(T);
377    }
378    if (numElems <= 0) {
379        return numElems;
380    }
381
382    size_t newSize;
383    newSize = _numElemsUsed + numElems;
384    if (newSize > _numElemsAllocated) {
385
386        // buffer sizes less than min_size are set to min_size
387        if (newSize < _minNumElems) {
388            newSize = _minNumElems;
389        }
390
391        /*
392         * Allocate a larger buffer for the string if the current one isn't
393         * large enough. Allocate extra space in the new buffer so that there
394         * will be room to grow before we have to allocate again.
395         */
396        size_t size;
397        size = (_numElemsAllocated > 0) ? _numElemsAllocated : _minNumElems;
398        while (newSize > size) {
399            size += size;
400        }
401
402        /*
403         * reallocate to a larger buffer
404         */
405        if (set(size) != size) {
406            return 0;
407        }
408    }
409    memcpy(_buf + _numElemsUsed, bytes, numElems * sizeof(T));
410    _numElemsUsed += numElems;
411    return numElems;
412}
413
414/**
415 * Append bytes to the end of this buffer
416 * @param pointer to bytes to be added
417 * @param number of bytes to be added
418 * @return number of bytes appended.
419 */
420template<class T>
421size_t
422SimpleBuffer<T>::extend(size_t numExtraElems)
423{
424    size_t newSize;
425
426    newSize = _numElemsUsed + numExtraElems;
427    if (newSize > _numElemsAllocated) {
428
429        /* Enforce a minimum buffer size. */
430        if (newSize < (size_t) _minNumElems) {
431            newSize = (size_t) _minNumElems;
432        }
433
434        size_t size;
435        size = (_numElemsAllocated > 0) ? _numElemsAllocated : _minNumElems;
436
437        /* Keep doubling the size of the buffer until we have enough space to
438         * hold the extra elements. */
439        while (newSize > size) {
440            size += size;
441        }
442        /* Reallocate to a larger buffer. */
443        if (set(size) != size) {
444            return 0;
445        }
446    }
447    return _numElemsAllocated;
448}
449
450/**
451 * Append formatted bytes to the end of this buffer
452 * @param pointer to bytes to be added
453 * @param number of bytes to be added
454 * @return number of bytes appended.
455 */
456template<class T>
457int
458SimpleBuffer<T>::appendf(const char *format, ...)
459{
460    size_t newMembCnt = 0;
461    size_t nbytes = 0;
462    int nmemb = 0;
463
464    char* dest = NULL;
465    size_t size = 0;
466    size_t bytesAdded = 0;
467    va_list arg;
468
469    // User specified NULL format
470    if (format == NULL) {
471        return 0;
472    }
473
474    // FIXME: i think this needs to be division,
475    // need to create test case with array of ints
476    // i'm not sure we can even guess the number
477    // bytes in *bytes.
478
479
480    // add one for terminating null character
481    nbytes = strlen(format) + 1;
482
483    if (nbytes <= 0) {
484        // no data written, invalid option
485        return nbytes;
486    }
487
488    // FIXME: we need ceil of nbytes/sizeof(T), instead we add 1 for safety
489
490    nmemb = nbytes/sizeof(T);
491    if (nmemb == 0) {
492        nmemb++;
493    }
494
495    newMembCnt = (size_t)(_numElemsUsed + nmemb);
496
497    if (newMembCnt > _numElemsAllocated) {
498
499        // buffer sizes less than min_size are set to min_size
500        if (newMembCnt < (size_t) _minNumElems) {
501            newMembCnt = (size_t) _minNumElems;
502        }
503
504        /*
505         * Allocate a larger buffer for the string if the current one isn't
506         * large enough. Allocate extra space in the new buffer so that there
507         * will be room to grow before we have to allocate again.
508         */
509        size_t membAvl;
510        membAvl = (_numElemsAllocated > 0) ? _numElemsAllocated : _minNumElems;
511        while (newMembCnt > membAvl) {
512            membAvl += membAvl;
513        }
514
515        /*
516         * reallocate to a larger buffer
517         */
518        if (set(membAvl) != membAvl) {
519            return 0;
520        }
521    }
522
523    dest = (char*) (_buf + _numElemsUsed);
524    size = (_numElemsAllocated-_numElemsUsed)*sizeof(T);
525
526    va_start(arg,format);
527    bytesAdded = vsnprintf(dest,size,format,arg);
528    va_end(arg);
529
530    // bytesAdded contains the number of bytes that would have
531    // been placed in the buffer if the call was successful.
532    // this value does not include the trailing null character.
533    // so we add one to account for it.
534
535    bytesAdded++;
536    nmemb = bytesAdded/sizeof(T);
537
538    if (bytesAdded > size) {
539        // we did not fit everything in the original buffer
540        // resize and try again.
541
542        // FIXME: round the new size up to the nearest multiple of 256?
543        set(_numElemsUsed+nmemb);
544
545        // reset dest because it may have moved during reallocation
546        dest = (char*) (_buf + _numElemsUsed);
547        size = bytesAdded;
548
549        va_start(arg,format);
550        bytesAdded = vsnprintf(dest,size,format,arg);
551        va_end(arg);
552
553        if (bytesAdded > size) {
554            // crystals grow, people grow, data doesn't grow...
555            // issue error
556            fprintf(stderr,"error in appendf while appending data");
557        }
558    }
559
560    _numElemsUsed += nmemb;
561
562    // remove the null character added by vsnprintf()
563    // we do this because if we are appending strings,
564    // the embedded null acts as a terminating null char.
565    // this is a generic buffer so if user wants a
566    // terminating null, they should append it.
567    remove(1);
568
569    return nmemb;
570}
571
572/**
573 * Remove bytes from the end of this buffer
574 * @param number of bytes to be removed
575 * @return number of bytes removed.
576 */
577template<class T>
578int
579SimpleBuffer<T>::remove(int nmemb)
580{
581    if ((_numElemsUsed - nmemb) < 0){
582        _numElemsUsed = 0;
583        _pos = 0;
584    } else {
585        _numElemsUsed -= nmemb;
586        if (_pos >= _numElemsUsed) {
587            // move _pos back to the new end of the buffer.
588            _pos = _numElemsUsed-1;
589        }
590    }
591
592
593    return nmemb;
594}
595
596template<class T>
597size_t
598SimpleBuffer<T>::set(size_t nmemb)
599{
600    T *buf;
601    size_t nbytes = nmemb*sizeof(T);
602
603    if (_buf == NULL) {
604        buf = (T*) malloc(nbytes);
605    } else {
606        buf = (T*) realloc((void*) _buf, nbytes);
607    }
608
609    if (buf == NULL) {
610        fprintf(stderr,"Can't allocate %lu bytes of memory\n",
611            (long unsigned int)nbytes);
612        _fileState = false;
613        return 0;
614    }
615    _buf = buf;
616    _numElemsAllocated = nmemb;
617    return _numElemsAllocated;
618}
619
620template<> inline
621SimpleBuffer<char>&
622SimpleBuffer<char>::show()
623{
624    size_t curMemb = 0;
625
626    while (curMemb != _numElemsUsed) {
627        fprintf(stdout,"_buf[%lu] = :%c:\n", (long unsigned int)curMemb,
628                _buf[curMemb]);
629        curMemb += 1;
630    }
631    fprintf(stdout,"_numElemsAllocated = :%lu:\n",
632            (long unsigned int)_numElemsAllocated);
633
634    return *this;
635}
636
637
638template<class T>
639SimpleBuffer<T>&
640SimpleBuffer<T>::show()
641{
642    size_t curMemb = 0;
643
644    while (curMemb != _numElemsUsed) {
645        fprintf(stdout,"_buf[%lu] = :%#lx:\n", (long unsigned int)curMemb,
646                (unsigned long)_buf[curMemb]);
647        curMemb += 1;
648    }
649    fprintf(stdout,"_numElemsAllocated = :%lu:\n", (long unsigned int)_numElemsAllocated);
650
651    return *this;
652}
653
654
655/**
656 * Read data from the buffer into a memory location provided by caller
657 * @param Pointer locating where to place read bytes.
658 * @param Size of the memory location.
659 * @return Number of bytes written to memory location
660 */
661template<class T>
662size_t
663SimpleBuffer<T>::read(const T* bytes, size_t nmemb)
664{
665    size_t nMembRead = 0;
666
667    void* dest = NULL;
668    void const* src  = NULL;
669    size_t size = 0;
670
671    // SimpleBuffer is empty.
672    if (_buf == NULL) {
673        return 0;
674    }
675
676    // User specified NULL buffer.
677    if (bytes == NULL) {
678        return 0;
679    }
680
681    // make sure we don't read off the end of our buffer
682    if ( (_pos + nmemb) > _numElemsUsed ) {
683        nMembRead = _numElemsUsed - _pos;
684    }
685    else {
686        nMembRead = nmemb;
687    }
688
689    if (nMembRead <= 0) {
690        return 0;
691    }
692
693    dest = (void*) bytes;
694    src  = (void const*) (_buf + _pos);
695    size = nMembRead*sizeof(T);
696    memcpy(dest,src,size);
697
698    _pos = (_pos + nMembRead);
699
700    return nMembRead;
701}
702
703
704/**
705 * Set buffer position indicator to spot within the buffer
706 * @param Offset from whence location in buffer.
707 * @param Place from where offset is added or subtracted.
708 * @return 0 on success, anything else is failure
709 */
710template<class T>
711int
712SimpleBuffer<T>::seek(long offset, int whence)
713{
714    int retVal = 0;
715
716    if (_buf == NULL) {
717        return -1 ;
718    }
719
720    if (whence == SEEK_SET) {
721        if (offset < 0) {
722            /* dont go off the beginning of data */
723            _pos = 0;
724        }
725        else if (offset >= (long)_numElemsUsed) {
726            /* dont go off the end of data */
727            _pos = _numElemsUsed - 1;
728        }
729        else {
730            _pos = (size_t)(offset);
731        }
732    }
733    else if (whence == SEEK_CUR) {
734        if ( (_pos + offset) < 0) {
735            /* dont go off the beginning of data */
736            _pos = 0;
737        }
738        else if ((_pos + offset) >= _numElemsUsed) {
739            /* dont go off the end of data */
740            _pos = _numElemsUsed - 1;
741        }
742        else {
743            _pos = (size_t)(_pos + offset);
744        }
745    }
746    else if (whence == SEEK_END) {
747        if (offset <= (long)(-1*_numElemsUsed)) {
748            /* dont go off the beginning of data */
749            _pos = 0;
750        }
751        else if (offset >= 0) {
752            /* dont go off the end of data */
753            _pos = _numElemsUsed - 1;
754        }
755        else {
756            _pos = (size_t)((_numElemsUsed - 1) + offset);
757        }
758    }
759    else {
760        retVal = -1;
761    }
762
763    return retVal;
764}
765
766
767/**
768 * Tell caller the offset of the position indicator from the start of buffer
769 * @return Number of bytes the position indicator is from start of buffer
770 */
771template<class T>
772int
773SimpleBuffer<T>::tell() const
774{
775   return (int)_pos;
776}
777
778
779/**
780 * Move the internal position tracker to the beginning of the buffer.
781 */
782template<class T>
783SimpleBuffer<T>&
784SimpleBuffer<T>::rewind()
785{
786    _pos = 0;
787    return *this;
788}
789
790
791/**
792 * Tell if the last file like operation (ie. read()) was successful
793 * or if there was a failure like eof, or bad memory
794 * @return True or false boolean value
795 */
796template<class T>
797bool
798SimpleBuffer<T>::good() const
799{
800    return (_fileState);
801}
802
803
804/**
805 * Tell if the last file like operation (ie. read()) failed
806 * Opposite of good()
807 * @return True or false boolean value
808 */
809template<class T>
810bool
811SimpleBuffer<T>::bad() const
812{
813    return (!_fileState);
814}
815
816
817/**
818 * Tell if the position flag is at the end of the buffer
819 * @return True or false boolean value
820 */
821template<class T>
822bool
823SimpleBuffer<T>::eof() const
824{
825    return (_pos >= _numElemsUsed);
826}
827
828
829/**
830 * Move the data from this SimpleBuffer to the SimpleBuffer provided by
831 * the caller. All data except the _pos is moved and this SimpleBuffer is
832 * re-initialized with Initialize().
833 * @param SimpleBuffer to move the information to
834 * @return reference to this SimpleBuffer object.
835 */
836template<class T>
837SimpleBuffer<T>&
838SimpleBuffer<T>::move(SimpleBuffer<T>& b)
839{
840    Release();
841
842    _buf = b._buf;
843    _pos = b._pos;
844    _fileState = b._fileState;
845    _numElemsUsed = b._numElemsUsed;
846    _numElemsAllocated = b._numElemsAllocated;
847
848    b.Initialize();
849
850    return *this;
851}
852
853
854 /**
855  *  Initializes a dynamic buffer, discarding any previous contents
856  *  of the buffer. Release() should have been called already
857  *  if the dynamic buffer was previously in use.
858  */
859template<class T>
860void
861SimpleBuffer<T>::Initialize()
862{
863    _buf = NULL;
864    _pos = 0;
865    _fileState = true;
866    _numElemsUsed = 0;
867    _numElemsAllocated = 0;
868}
869
870
871/**
872 *  Frees up any memory allocated for the dynamic buffer and
873 *  reinitializes the buffer to an empty state.
874 */
875template<class T>
876void
877SimpleBuffer<T>::Release()
878{
879    if (_buf != NULL) {
880        free(_buf);
881        _buf = NULL;
882    }
883    Initialize();
884}
885
886} // namespace Rappture
887
888#endif // RAPPTURE_SIMPLEBUFFER_H
Note: See TracBrowser for help on using the repository browser.