wibble  0.1.28
buffer.h
Go to the documentation of this file.
00001 #ifndef WIBBLE_SYS_BUFFER_H
00002 #define WIBBLE_SYS_BUFFER_H
00003 
00004 /*
00005  * Variable-size, reference-counted memory buffer
00006  *
00007  * Copyright (C) 2003--2006  Enrico Zini <enrico@debian.org>
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00022  */
00023 
00024 #include <stddef.h> // for size_t
00025 
00026 namespace wibble {
00027 namespace sys {
00028 
00032 class Buffer
00033 {
00034 public:
00035     class Data
00036     {
00037     protected:
00038         mutable int _ref;
00039         size_t _size;
00040         void* _data;
00041 
00042     public:
00043         Data() throw () : _ref(0), _size(0), _data(0) {}
00044         Data(size_t size);
00045         // if own == true, take possession of the memory buffer, else copy it
00046         Data(void* buf, size_t size, bool own = true);
00047         Data(const void* buf, size_t size);
00048         ~Data();
00049 
00051         void ref() const throw () { ++_ref; }
00052 
00055         bool unref() const throw () { return --_ref == 0; }
00056 
00058         void resize(size_t size);
00059 
00061         bool operator==(const Data& d) const throw();
00062 
00064         bool operator<(const Data& d) const throw();
00065 
00066         friend class Buffer;
00067     };
00068 
00069     Data* item;
00070     
00071 public:
00073     Buffer() throw () : item(0) {}
00074 
00076     Buffer(size_t size) : item(0)
00077     {
00078         if (size)
00079         {
00080             item = new Data(size);
00081             item->ref();
00082         }
00083     }
00084 
00095     Buffer(void* buf, size_t size, bool own = true) : item(0)
00096     {
00097         if (size)
00098         {
00099             item = new Data(buf, size, own);
00100             item->ref();
00101         }
00102     }
00103 
00109     Buffer(const void* buf, size_t size) : item(0)
00110     {
00111         if (size)
00112         {
00113             item = new Data(buf, size);
00114             item->ref();
00115         }
00116     }
00117 
00118     Buffer(const Buffer& buf) throw ()
00119     {
00120         if (buf.item)
00121             buf.item->ref();
00122         item = buf.item;
00123     }
00124     ~Buffer()
00125     {
00126         if (item && item->unref())
00127             delete item;
00128     }
00129     Buffer& operator=(const Buffer& buf)
00130     {
00131         if (buf.item)
00132             buf.item->ref();  // Do it early to correctly handle the case of x = x;
00133         if (item && item->unref())
00134             delete item;
00135         item = buf.item;
00136         return *this;
00137     }
00138 
00140     void* data() throw () { return item ? item->_data : 0; }
00141 
00143     const void* data() const throw () { return item ? item->_data : 0; }
00144 
00146     size_t size() const throw () { return item ? item->_size : 0; }
00147 
00149     void resize(size_t newSize)
00150     {
00151         if (size() == newSize)
00152             return;
00153         if (!newSize)
00154         {
00155             if (item && item->unref())
00156                 delete item;
00157             item = 0;
00158         } else if (item) {
00159             item->resize(newSize);
00160         } else {
00161             item = new Data(newSize);
00162             item->ref();
00163         }
00164     }
00165 
00167     bool operator==(const Buffer& buf) const throw ()
00168     {
00169         if (item == 0 && buf.item == 0)
00170             return true;
00171         if (item == 0 || buf.item == 0)
00172             return false;
00173         return *item == *buf.item;
00174     }
00175 
00176     bool operator!=(const Buffer& buf) const throw ()
00177     {
00178         return !operator==(buf);
00179     }
00180 
00182     bool operator<(const Buffer& buf) const throw ()
00183     {
00184         if (item == 0 && buf.item == 0)
00185             return false;
00186         if (item == 0)
00187             return true;
00188         if (buf.item == 0)
00189             return false;
00190         return *item < *buf.item;
00191     }
00192 };
00193 
00194 }
00195 }
00196 
00197 // vim:set ts=4 sw=4:
00198 #endif