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

Last change on this file since 3177 was 3177, checked in by mmc, 10 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

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    _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.