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

Last change on this file since 1051 was 1051, checked in by dkearney, 15 years ago

templatized the rappture simple buffer object to work with ints, floats, chars, doubles.
adjusted rappture buffer and encode to reflect the changes to the simple buffer.
created a basic dx writer object, currently it handles some uniform rectangular grids with data.
added some c header files to rappture outcome object to stop it from complaining about function headers.
adjusted Makefile to reflect changes to the simple buffer and dx writer object.

File size: 15.4 KB
Line 
1/*
2 * ======================================================================
3 *  Rappture::SimpleBuffer
4 *
5 *  AUTHOR:  Derrick Kearney, Purdue University
6 *
7 *  Copyright (c) 2004-2008  Purdue Research Foundation
8 * ----------------------------------------------------------------------
9 *  See the file "license.terms" for information on usage and
10 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * ======================================================================
12 *
13 *  This code is based on the Tcl_DString facility included in the
14 *  Tcl source release, which includes the following copyright:
15 *
16 *  Copyright (c) 1987-1993 The Regents of the University of California.
17 *  Copyright (c) 1994-1998 Sun Microsystems, Inc.
18 *  Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
19 *
20 *  This software is copyrighted by the Regents of the University of
21 *  California, Sun Microsystems, Inc., Scriptics Corporation,
22 *  and other parties.  The following terms apply to all files associated
23 *  with the software unless explicitly disclaimed in individual files.
24 *
25 *  The authors hereby grant permission to use, copy, modify, distribute,
26 *  and license this software and its documentation for any purpose, provided
27 *  that existing copyright notices are retained in all copies and that this
28 *  notice is included verbatim in any distributions. No written agreement,
29 *  license, or royalty fee is required for any of the authorized uses.
30 *  Modifications to this software may be copyrighted by their authors
31 *  and need not follow the licensing terms described here, provided that
32 *  the new terms are clearly indicated on the first page of each file where
33 *  they apply.
34 *
35 *  IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
36 *  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
37 *  ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
38 *  DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
39 *  POSSIBILITY OF SUCH DAMAGE.
40 *
41 *  THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
42 *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
43 *  FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
44 *  IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
45 *  NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
46 *  MODIFICATIONS.
47 *
48 *  GOVERNMENT USE: If you are acquiring this software on behalf of the
49 *  U.S. government, the Government shall have only "Restricted Rights"
50 *  in the software and related documentation as defined in the Federal·
51 *  Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
52 *  are acquiring the software on behalf of the Department of Defense, the
53 *  software shall be classified as "Commercial Computer Software" and the
54 *  Government shall have only "Restricted Rights" as defined in Clause
55 *  252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
56 *  authors grant the U.S. Government and others acting in its behalf
57 *  permission to use and distribute the software in accordance with the
58 *  terms specified in this license.·
59 *
60 * ======================================================================
61 */
62
63#ifndef RAPPTURE_SIMPLEBUFFER_H
64#define RAPPTURE_SIMPLEBUFFER_H
65
66#include <fstream>
67#include <cstring>
68#include <cstdlib>
69
70namespace Rappture {
71
72template <class T>
73class SimpleBuffer {
74public:
75    SimpleBuffer();
76    SimpleBuffer(size_t nmemb);
77    SimpleBuffer(const T* bytes, int nmemb=-1);
78    SimpleBuffer(const SimpleBuffer& b);
79    SimpleBuffer<T>& operator=(const SimpleBuffer<T>& b);
80    SimpleBuffer     operator+(const SimpleBuffer& b) const;
81    SimpleBuffer<T>& operator+=(const SimpleBuffer<T>& b);
82    virtual ~SimpleBuffer();
83
84    const T* bytes() const;
85    size_t size() const;
86    size_t nmemb() const;
87
88    SimpleBuffer<T>& clear();
89    int append(const T* bytes, int nmemb=-1);
90    size_t read(const T* bytes, size_t nmemb);
91    int seek(long offset, int whence);
92    int tell() const;
93    size_t set(size_t nbytes);
94    SimpleBuffer<T>& rewind();
95    SimpleBuffer<T>& show();
96
97    bool good() const;
98    bool bad() const;
99    bool eof() const;
100
101    SimpleBuffer<T>& move(SimpleBuffer<T>& b);
102
103protected:
104
105    void bufferInit();
106    void bufferFree();
107
108private:
109
110    /// Pointer to the memory that holds our buffer's data
111    T* _buf;
112
113    /// Position offset within the buffer's memory
114    size_t _pos;
115
116    /// Number of members stored in the buffer
117    size_t _nMembStored;
118
119    /// Total number of members available in the buffer
120    size_t _nMembAvl;
121
122    /// State of the last file like operation.
123    bool _fileState;
124
125    /// Minimum number of members is set to the number you can fit in 256 bytes
126    const static int _minMembCnt=(256/sizeof(T));
127
128    size_t __guesslen(const T* bytes);
129
130};
131
132typedef SimpleBuffer<char>   SimpleCharBuffer;
133typedef SimpleBuffer<float>  SimpleFloatBuffer;
134typedef SimpleBuffer<double> SimpleDoubleBuffer;
135
136/**
137 * Construct an empty SimpleBuffer.
138 */
139template<class T>
140SimpleBuffer<T>::SimpleBuffer()
141{
142    bufferInit();
143}
144
145
146/**
147 * Construct an empty SimpleBuffer of specified size.
148 */
149template<class T>
150SimpleBuffer<T>::SimpleBuffer(size_t nmemb)
151{
152    bufferInit();
153
154    if (nmemb == 0) {
155        // ignore requests for sizes equal to zero
156        return;
157    }
158
159    // buffer sizes less than min_size are set to min_size
160    if (nmemb < (size_t) _minMembCnt) {
161        nmemb = _minMembCnt;
162    }
163
164    if (set(nmemb) != nmemb) {
165        return;
166    }
167    _nMembStored = nmemb;
168}
169
170
171/**
172 * Construct a SimpleBuffer loaded with initial data.
173 *
174 * @param bytes pointer to bytes being stored.
175 * @param nbytes number of bytes being stored.
176 */
177template<class T>
178SimpleBuffer<T>::SimpleBuffer(const T* bytes, int nmemb)
179{
180    bufferInit();
181    append(bytes,nmemb);
182}
183
184
185/**
186 * Copy constructor
187 * @param SimpleBuffer object to copy
188 */
189template<class T>
190SimpleBuffer<T>::SimpleBuffer(const SimpleBuffer<T>& b)
191{
192    bufferInit();
193    append(b.bytes(),b.nmemb());
194}
195
196
197/**
198 * Assignment operator
199 * @param SimpleBuffer object to copy
200 */
201template<class T>
202SimpleBuffer<T>&
203SimpleBuffer<T>::operator=(const SimpleBuffer<T>& b)
204{
205    bufferFree();
206    bufferInit();
207    append(b.bytes(),b.nmemb());
208    return *this;
209}
210
211
212/**
213 * Operator +
214 * @param SimpleBuffer object to add
215 */
216template<class T>
217SimpleBuffer<T>
218SimpleBuffer<T>::operator+(const SimpleBuffer<T>& b) const
219{
220    SimpleBuffer<T> newBuffer(*this);
221    newBuffer.operator+=(b);
222    return newBuffer;
223}
224
225
226/**
227 * Operator +=
228 * @param SimpleBuffer object to add
229 */
230template<class T>
231SimpleBuffer<T>&
232SimpleBuffer<T>::operator+=(const SimpleBuffer<T>& b)
233{
234    append(b.bytes(),b.nmemb());
235    return *this;
236}
237
238
239/**
240 * Destructor
241 */
242template<class T>
243SimpleBuffer<T>::~SimpleBuffer()
244{
245    bufferFree();
246}
247
248
249/**
250 * Get the bytes currently stored in the buffer.  These bytes can
251 * be stored, and used later to construct another Buffer to
252 * decode the information.
253 *
254 * @return Pointer to the bytes in the buffer.
255 */
256template<class T>
257const T*
258SimpleBuffer<T>::bytes() const
259{
260    return _buf;
261}
262
263
264/**
265 * Get the number of bytes currently stored in the buffer.
266 * @return Number of the bytes used in the buffer.
267 */
268template<class T>
269size_t
270SimpleBuffer<T>::size() const
271{
272    return _nMembStored*sizeof(T);
273}
274
275
276/**
277 * Get the number of members currently stored in the buffer.
278 * @return Number of the members used in the buffer.
279 */
280template<class T>
281size_t
282SimpleBuffer<T>::nmemb() const
283{
284    return _nMembStored;
285}
286
287
288/**
289 * Clear the buffer, making it empty.
290 * @return Reference to this buffer.
291 */
292template<class T>
293SimpleBuffer<T>&
294SimpleBuffer<T>::clear()
295{
296    bufferFree();
297    bufferInit();
298
299    return *this;
300}
301
302/**
303 * guess the length of a null terminated character buffer
304 * @param pointer to the buffer to guess the length of
305 * @return a guess of the length of the buffer.
306 */
307template<> inline
308size_t
309SimpleBuffer<char>::__guesslen(const char* bytes)
310{
311    return strlen(bytes);
312}
313
314/**
315 * guess the length of a non-null terminated character buffer
316 * @param pointer to the buffer to guess the length of
317 * @return a guess of the length of the buffer.
318 */
319template<class T>
320size_t
321SimpleBuffer<T>::__guesslen(const T* bytes)
322{
323    return (sizeof(T));
324}
325
326/**
327 * Append bytes to the end of this buffer
328 * @param pointer to bytes to be added
329 * @param number of bytes to be added
330 * @return number of bytes appended.
331 */
332template<class T>
333int
334SimpleBuffer<T>::append(const T* bytes, int nmemb)
335{
336    size_t newMembCnt = 0;
337    size_t nbytes = 0;
338
339    void* dest = NULL;
340    void const* src  = NULL;
341    size_t size = 0;
342
343    // User specified NULL buffer to append
344    if ( (bytes == NULL) && (nmemb < 1) ) {
345        return 0;
346    }
347
348    if (nmemb == -1) {
349        // user signaled null terminated string
350        // or that we should make an educated guess
351        // at the length of the object.
352        nbytes = __guesslen(bytes);
353        nmemb = nbytes*sizeof(T);
354    }
355
356    if (nmemb <= 0) {
357        // no data written, invalid option
358        return nmemb;
359    }
360
361    newMembCnt = (size_t)(_nMembStored + nmemb);
362
363    if (newMembCnt > _nMembAvl) {
364
365        // buffer sizes less than min_size are set to min_size
366        if (newMembCnt < (size_t) _minMembCnt) {
367            newMembCnt = (size_t) _minMembCnt;
368        }
369
370        /*
371         * Allocate a larger buffer for the string if the current one isn't
372         * large enough. Allocate extra space in the new buffer so that there
373         * will be room to grow before we have to allocate again.
374         */
375        size_t membAvl;
376        membAvl = (_nMembAvl > 0) ? _nMembAvl : _minMembCnt;
377        while (newMembCnt > membAvl) {
378            membAvl += membAvl;
379        }
380
381        /*
382         * reallocate to a larger buffer
383         */
384        if (set(membAvl) != membAvl) {
385            return 0;
386        }
387    }
388
389    dest = (void*) (_buf + _nMembStored);
390    src  = (void const*) bytes;
391    size = (size_t) (nmemb*sizeof(T));
392    memcpy(dest,src,size);
393
394    _nMembStored += nmemb;
395
396    return nmemb;
397}
398
399
400template<class T>
401size_t
402SimpleBuffer<T>::set(size_t nmemb)
403{
404    T *buf;
405    size_t nbytes = nmemb*sizeof(T);
406
407    if (_buf == NULL) {
408        buf = (T*) malloc(nbytes);
409    } else {
410        buf = (T*) realloc((void*) _buf, nbytes);
411    }
412
413    if (buf == NULL) {
414        fprintf(stderr,"Can't allocate %i bytes of memory\n",nbytes);
415        _fileState = false;
416        return 0;
417    }
418    _buf = buf;
419    _nMembAvl = nmemb;
420    return _nMembAvl;
421}
422
423
424template<class T>
425SimpleBuffer<T>&
426SimpleBuffer<T>::show()
427{
428    size_t curMemb = 0;
429
430    while (curMemb != _nMembStored) {
431        fprintf(stdout,"_buf[%d] = :%#x:\n",curMemb,_buf[curMemb]);
432        curMemb += 1;
433    }
434    fprintf(stdout,"_nMembAvl = :%d:\n",_nMembAvl);
435
436    return *this;
437}
438
439
440/**
441 * Read data from the buffer into a memory location provided by caller
442 * @param Pointer locating where to place read bytes.
443 * @param Size of the memory location.
444 * @return Number of bytes written to memory location
445 */
446template<class T>
447size_t
448SimpleBuffer<T>::read(const T* bytes, size_t nmemb)
449{
450    size_t nMembRead = 0;
451
452    void* dest = NULL;
453    void const* src  = NULL;
454    size_t size = 0;
455
456    // SimpleBuffer is empty.
457    if (_buf == NULL) {
458        return 0;
459    }
460
461    // User specified NULL buffer.
462    if (bytes == NULL) {
463        return 0;
464    }
465
466    // make sure we don't read off the end of our buffer
467    if ( (_pos + nmemb) > _nMembStored ) {
468        nMembRead = _nMembStored - _pos;
469    }
470    else {
471        nMembRead = nmemb;
472    }
473
474    if (nMembRead <= 0) {
475        return 0;
476    }
477
478    dest = (void*) bytes;
479    src  = (void const*) (_buf + _pos);
480    size = nMembRead*sizeof(T);
481    memcpy(dest,src,size);
482
483    _pos = (_pos + nMembRead);
484
485    return nMembRead;
486}
487
488
489/**
490 * Set buffer position indicator to spot within the buffer
491 * @param Offset from whence location in buffer.
492 * @param Place from where offset is added or subtracted.
493 * @return 0 on success, anything else is failure
494 */
495template<class T>
496int
497SimpleBuffer<T>::seek(long offset, int whence)
498{
499    int retVal = 0;
500
501    if (_buf == NULL) {
502        return -1 ;
503    }
504
505    if (whence == SEEK_SET) {
506        if (offset < 0) {
507            /* dont go off the beginning of data */
508            _pos = 0;
509        }
510        else if (offset >= (long)_nMembStored) {
511            /* dont go off the end of data */
512            _pos = _nMembStored - 1;
513        }
514        else {
515            _pos = (size_t)(offset);
516        }
517    }
518    else if (whence == SEEK_CUR) {
519        if ( (_pos + offset) < 0) {
520            /* dont go off the beginning of data */
521            _pos = 0;
522        }
523        else if ((_pos + offset) >= _nMembStored) {
524            /* dont go off the end of data */
525            _pos = _nMembStored - 1;
526        }
527        else {
528            _pos = (size_t)(_pos + offset);
529        }
530    }
531    else if (whence == SEEK_END) {
532        if (offset <= (long)(-1*_nMembStored)) {
533            /* dont go off the beginning of data */
534            _pos = 0;
535        }
536        else if (offset >= 0) {
537            /* dont go off the end of data */
538            _pos = _nMembStored - 1;
539        }
540        else {
541            _pos = (size_t)((_nMembStored - 1) + offset);
542        }
543    }
544    else {
545        retVal = -1;
546    }
547
548    return retVal;
549}
550
551
552/**
553 * Tell caller the offset of the position indicator from the start of buffer
554 * @return Number of bytes the position indicator is from start of buffer
555 */
556template<class T>
557int
558SimpleBuffer<T>::tell() const
559{
560   return (int)_pos;
561}
562
563
564/**
565 * Read data from the buffer into a memory location provided by caller
566 */
567template<class T>
568SimpleBuffer<T>&
569SimpleBuffer<T>::rewind()
570{
571    _pos = 0;
572    return *this;
573}
574
575
576/**
577 * Tell if the last file like operation (ie. read()) was successful
578 * or if there was a failure like eof, or bad memory
579 * @return True or false boolean value
580 */
581template<class T>
582bool
583SimpleBuffer<T>::good() const
584{
585    return (_fileState);
586}
587
588
589/**
590 * Tell if the last file like operation (ie. read()) failed
591 * Opposite of good()
592 * @return True or false boolean value
593 */
594template<class T>
595bool
596SimpleBuffer<T>::bad() const
597{
598    return (!_fileState);
599}
600
601
602/**
603 * Tell if the position flag is at the end of the buffer
604 * @return True or false boolean value
605 */
606template<class T>
607bool
608SimpleBuffer<T>::eof() const
609{
610    return (_pos >= _nMembStored);
611}
612
613
614/**
615 * Move the data from this SimpleBuffer to the SimpleBuffer provided by
616 * the caller. All data except the _pos is moved and this SimpleBuffer is
617 * re-initialized with bufferInit().
618 * @param SimpleBuffer to move the information to
619 * @return reference to this SimpleBuffer object.
620 */
621template<class T>
622SimpleBuffer<T>&
623SimpleBuffer<T>::move(SimpleBuffer<T>& b)
624{
625    bufferFree();
626
627    _buf = b._buf;
628    _pos = b._pos;
629    _fileState = b._fileState;
630    _nMembStored = b._nMembStored;
631    _nMembAvl = b._nMembAvl;
632
633    b.bufferInit();
634
635    return *this;
636}
637
638
639 /**
640  *  Initializes a dynamic buffer, discarding any previous contents
641  *  of the buffer. bufferFree() should have been called already
642  *  if the dynamic buffer was previously in use.
643  */
644template<class T>
645void
646SimpleBuffer<T>::bufferInit()
647{
648    _buf = NULL;
649    _pos = 0;
650    _fileState = true;
651    _nMembStored = 0;
652    _nMembAvl = 0;
653}
654
655
656/**
657 *  Frees up any memory allocated for the dynamic buffer and
658 *  reinitializes the buffer to an empty state.
659 */
660template<class T>
661void
662SimpleBuffer<T>::bufferFree()
663{
664    if (_buf != NULL) {
665        free(_buf);
666        _buf = NULL;
667    }
668    bufferInit();
669}
670
671} // namespace Rappture
672
673#endif // RAPPTURE_SIMPLEBUFFER_H
Note: See TracBrowser for help on using the repository browser.