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

Last change on this file since 2458 was 2458, checked in by gah, 13 years ago

fix putfile to handle files > 232-1 bytes

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