00001 // 00002 //------------------------------------------------------------------------ 00003 // 00004 // File : KokoBuffer.h 00005 // Author : Patrick McCormick (pat@acl.lanl.gov) 00006 // 00007 // $Date: 2003/08/04 04:57:49 $ 00008 // $Revision: 1.7 $ 00009 // 00010 // This class implements a fairly straight-forward wrapper around an 00011 // unsigned char buffer. This might be a good place to implement 00012 // compression routines in the future. 00013 // 00014 // This code has similar features to the MPI pack and unpack routines. 00015 // 00016 // TODO NOTE: It may be necessary to use MPI_Alloc() for memory allocation if 00017 // you plan on using these buffers as contents for messages. Is 00018 // this only an issue with MPIPro??? 00019 // 00020 //------------------------------------------------------------------------ 00021 // 00022 #ifndef KOKO_BUFFER_H_ 00023 #define KOKO_BUFFER_H_ 00024 00025 #include "koko.h" 00026 00027 class KokoBuffer { 00028 00029 public: 00030 KokoBuffer(void); 00031 KokoBuffer(unsigned int size); 00032 KokoBuffer(unsigned char *buf, unsigned int size, bool pad = false); 00033 KokoBuffer(const KokoBuffer &kbuf); 00034 00035 inline ~KokoBuffer(void) 00036 { delete []_start; }; 00037 00038 //================================================================= 00039 // Get at or set the internal buffer. If you modify the data in 00040 // the buffer, make sure you call setCurSize() to update the 00041 // number of bytes (of true data) now stored in the buffer. It is 00042 // also important to do this if you cast to an unsigned char * or 00043 // a void * and then write to the buffer directly. 00044 inline unsigned char *GetData(void) 00045 { return _buf; }; 00046 00047 inline unsigned char *GetBuffer(void) 00048 { return _start; }; 00049 00050 inline operator unsigned char *(void) 00051 { return _buf; }; 00052 00053 inline operator void *(void) 00054 { return (void *)_buf; }; 00055 00056 inline bool SetCurSize(unsigned int csize) 00057 { 00058 if (csize <= (_size + sizeof(KokoTag))) { 00059 _cursize = csize; 00060 return true; 00061 } else { 00062 return false; 00063 } 00064 }; 00065 00066 ///================================================================ 00067 /// Copy the given buffer into the KokoBuffer. This completely 00068 /// replaces any data in the buffer. 00069 void Memcopy(unsigned char *bufp, unsigned int size); 00070 00071 ///================================================================ 00072 /// Pack the given data to end of the current buffer. If you want 00073 /// to force the packing operation to start at the begining of the 00074 /// buffer call Pack() with no arguments. 00075 /// 00076 inline void Pack(void) // Enable pack mode. 00077 { 00078 _aptr = _buf; 00079 _cursize = 0; 00080 }; 00081 00082 bool Pack(unsigned char *bufp, unsigned int size); 00083 00084 ///================================================================ 00085 /// Unpack/extract chunks of data from the buffer. If you want to 00086 /// force the packing operations to start at the begining of the 00087 /// buffer call Unpack() with no arguments. 00088 inline void Unpack(void) // Enable extraction mode. 00089 { _eptr = _buf; }; 00090 00091 bool Unpack(unsigned char *dest, unsigned int size); 00092 00093 ///================================================================ 00094 /// What size is the buffer (available and total). 00095 inline unsigned int Size(void) // Actual bytes in buffer. 00096 { return _cursize; }; 00097 00098 inline unsigned int TotalSize(void) // Full buffer size. 00099 { return _size + sizeof(KokoTag); }; 00100 00101 inline void Resize(unsigned int size) 00102 { this->grow(size); }; 00103 00104 ///================================================================= 00105 /// Simple buffer locking -- not thread safe... Warning! For the 00106 /// most part the Lock() and Unlock methods are intended to be used 00107 /// by code that knows the buffer is not safe for use yet (in this 00108 /// case the Comminicator class in the Koko Library). Be extremely 00109 /// careful with these two routines if you are not implementing a 00110 /// feature inside a communicator. 00111 inline bool Locked(void) 00112 { return _locked; }; 00113 00114 inline void Lock(void) 00115 { 00116 _locked = true; 00117 }; 00118 00119 inline void Unlock(void) 00120 { 00121 _locked = false; 00122 }; 00123 00124 ///================================================================= 00125 /// Tag handling routines. This routines are here as one possible 00126 /// work-around of some message passing libraries not formally 00127 /// supporting tagged messages. 00128 void SetTag(KokoTag &tag); 00129 00130 KokoTag GetTag(void); 00131 00132 protected: 00133 00134 ///================================================================= 00135 /// How many bytes free to have to work with in this buffer? 00136 inline unsigned int bytes_free(void) 00137 { return _size - _cursize; }; 00138 00139 inline unsigned int bytes_remain(unsigned char *ucp) 00140 { return ucp - _buf; }; 00141 00142 ///================================================================= 00143 /// Grow the buffer to accomodate the given new size. This keeps the 00144 /// current buffer data. 00145 void grow(unsigned int new_size); 00146 00147 private: 00148 bool _locked; // To help out with async messaging. 00149 unsigned int _size; // Total size of the buffer. 00150 unsigned char *_start; // The true start of the buffer. 00151 unsigned char *_buf; // The start of the user buffer. 00152 unsigned char *_aptr; // Pointer to next insertion point. 00153 unsigned char *_eptr; // Pointer to extraction point. 00154 unsigned int _cursize; // Byte size of items currently 00155 // stored in buffer. 00156 float _growfact; // Growth factor for buffer allocation. 00157 }; 00158 00159 #endif 00160