1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
#ifndef WIBBLE_SYS_BUFFER_H
#define WIBBLE_SYS_BUFFER_H
/*
* Variable-size, reference-counted memory buffer
*
* Copyright (C) 2003--2006 Enrico Zini <enrico@debian.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stddef.h> // for size_t
namespace wibble {
namespace sys {
/**
* Variable-size, reference-counted memory buffer
*/
class Buffer
{
public:
class Data
{
protected:
mutable int _ref;
size_t _size;
void* _data;
public:
Data() throw () : _ref(0), _size(0), _data(0) {}
Data(size_t size) throw ();
// if own == true, take possession of the memory buffer, else copy it
Data(void* buf, size_t size, bool own = true) throw ();
Data(const void* buf, size_t size) throw ();
~Data() throw ();
/// Increment the reference count for this object
void ref() const throw () { ++_ref; }
/// Decrement the reference count for this object, returning true when it
/// reaches 0
bool unref() const throw () { return --_ref == 0; }
/// Resize (enlarging or shrinking it) the buffer to `size' bytes
void resize(size_t size) throw ();
friend class Buffer;
};
Data* item;
public:
/// Create a 0-lenght buffer
Buffer() throw () : item(new Data()) { item->ref(); }
/// Create a buffer with the specified size
Buffer(size_t size) throw () : item(new Data(size)) { item->ref(); }
/**
* Create a buffer from existing data
*
* @param buf
* The data to put in this buffer
* @param size
* The dimension of buf
* @param own
* If true, take ownership of buf, else make a copy of it.
*/
Buffer(void* buf, size_t size, bool own = true) throw ()
: item(new Data(buf, size, own)) { item->ref(); }
/**
* Create a buffer with a copy of the given data
*
* It will always make a copy of the contents of buf.
*/
Buffer(const void* buf, size_t size) throw ()
: item(new Data(buf, size)) { item->ref(); }
Buffer(const Buffer& buf) throw ()
{
if (buf.item)
buf.item->ref();
item = buf.item;
}
~Buffer() throw ()
{
if (item && item->unref())
delete item;
}
Buffer& operator=(const Buffer& buf) throw ()
{
if (buf.item)
buf.item->ref(); // Do it early to correctly handle the case of x = x;
if (item && item->unref())
delete item;
item = buf.item;
return *this;
}
/// Return a pointer to the buffer
void* data() const throw () { return item->_data; }
/// Return the buffer size
size_t size() const throw () { return item->_size; }
/// Resize the buffer to hold exactly the specified amount of bytes
void resize(size_t size) throw () { item->resize(size); }
};
}
}
// vim:set ts=4 sw=4:
#endif
|