wibble  1.1
buffer.h
Go to the documentation of this file.
1 #ifndef WIBBLE_SYS_BUFFER_H
2 #define WIBBLE_SYS_BUFFER_H
3 
4 /*
5  * Variable-size, reference-counted memory buffer
6  *
7  * Copyright (C) 2003--2013 Enrico Zini <enrico@debian.org>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 
24 #include <stddef.h> // for size_t
25 #include <ostream>
26 
27 namespace wibble {
28 namespace sys {
29 
33 class Buffer
34 {
35 public:
36  class Data
37  {
38  protected:
39  mutable int _ref;
40  size_t _size;
41  void* _data;
42 
43  public:
44  Data() throw () : _ref(0), _size(0), _data(0) {}
45  Data(size_t size);
46  // if own == true, take possession of the memory buffer, else copy it
47  Data(void* buf, size_t size, bool own = true);
48  Data(const void* buf, size_t size);
49  ~Data();
50 
52  void ref() const throw () { ++_ref; }
53 
56  bool unref() const throw () { return --_ref == 0; }
57 
59  void resize(size_t size);
60 
62  bool operator==(const Data& d) const throw();
63 
65  bool operator<(const Data& d) const throw();
66 
67  friend class Buffer;
68  };
69 
71 
72 public:
74  Buffer() throw () : item(0) {}
75 
77  Buffer(size_t size) : item(0)
78  {
79  if (size)
80  {
81  item = new Data(size);
82  item->ref();
83  }
84  }
85 
98  Buffer(void* buf, size_t size, bool own = true) : item(0)
99  {
100  if (size)
101  {
102  item = new Data(buf, size, own);
103  item->ref();
104  }
105  }
106 
112  Buffer(const void* buf, size_t size) : item(0)
113  {
114  if (size)
115  {
116  item = new Data(buf, size);
117  item->ref();
118  }
119  }
120 
121  Buffer(const Buffer& buf) throw ()
122  {
123  if (buf.item)
124  buf.item->ref();
125  item = buf.item;
126  }
128  {
129  if (item && item->unref())
130  delete item;
131  }
132  Buffer& operator=(const Buffer& buf)
133  {
134  if (buf.item)
135  buf.item->ref(); // Do it early to correctly handle the case of x = x;
136  if (item && item->unref())
137  delete item;
138  item = buf.item;
139  return *this;
140  }
141 
143  void* data() throw () { return item ? item->_data : 0; }
144 
146  const void* data() const throw () { return item ? item->_data : 0; }
147 
149  size_t size() const throw () { return item ? item->_size : 0; }
150 
152  void resize(size_t newSize)
153  {
154  if (size() == newSize)
155  return;
156  if (!newSize)
157  {
158  if (item && item->unref())
159  delete item;
160  item = 0;
161  } else if (item) {
162  item->resize(newSize);
163  } else {
164  item = new Data(newSize);
165  item->ref();
166  }
167  }
168 
170  bool operator==(const Buffer& buf) const throw ()
171  {
172  if (item == 0 && buf.item == 0)
173  return true;
174  if (item == 0 || buf.item == 0)
175  return false;
176  return *item == *buf.item;
177  }
178 
179  bool operator!=(const Buffer& buf) const throw ()
180  {
181  return !operator==(buf);
182  }
183 
185  bool operator<(const Buffer& buf) const throw ()
186  {
187  if (item == 0 && buf.item == 0)
188  return false;
189  if (item == 0)
190  return true;
191  if (buf.item == 0)
192  return false;
193  return *item < *buf.item;
194  }
195 
202  std::string print_preview(unsigned size) const;
203 };
204 
205 std::ostream& operator<<(std::ostream& o, const Buffer& b);
206 
207 }
208 }
209 
210 // vim:set ts=4 sw=4:
211 #endif