ROSE  0.11.145.0
StaticBuffer.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 #ifndef Sawyer_StaticBuffer_H
9 #define Sawyer_StaticBuffer_H
10 
11 #include <Sawyer/AllocatingBuffer.h>
12 #include <Sawyer/Assert.h>
13 #include <Sawyer/Buffer.h>
14 #include <Sawyer/Sawyer.h>
15 
16 #include <boost/serialization/access.hpp>
17 #include <boost/serialization/array.hpp>
18 #include <boost/serialization/base_object.hpp>
19 #include <boost/serialization/nvp.hpp>
20 #include <boost/serialization/split_member.hpp>
21 
22 namespace Sawyer {
23 namespace Container {
24 
29 template<class A, class T>
30 class StaticBuffer: public Buffer<A, T> {
31 public:
32  typedef A Address;
33  typedef T Value;
34  typedef Buffer<A, T> Super;
36 private:
37  Value *values_;
38  Address size_;
39  bool rdonly_;
40 
41 private:
42  friend class boost::serialization::access;
43 
44  template<class S>
45  void save(S &s, const unsigned /*version*/) const {
46  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
47  s & BOOST_SERIALIZATION_NVP(size_);
48  s & BOOST_SERIALIZATION_NVP(rdonly_);
49  s & boost::serialization::make_nvp("values", boost::serialization::make_array(values_, size_));
50  }
51 
52  template<class S>
53  void load(S &s, const unsigned /*version*/) {
54  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
55  s & BOOST_SERIALIZATION_NVP(size_);
56  s & BOOST_SERIALIZATION_NVP(rdonly_);
57  values_ = new Value[size_];
58  s & boost::serialization::make_nvp("values", boost::serialization::make_array(values_, size_));
59  }
60 
61  BOOST_SERIALIZATION_SPLIT_MEMBER();
62 
63 private:
64  // For serialization only
65  StaticBuffer()
66  : values_(NULL), size_(0), rdonly_(false) {}
67 
68 protected:
69  StaticBuffer(Value *values, Address size)
70  : Super(".StaticBuffer"), values_(values), size_(size), rdonly_(false) {
71  ASSERT_require(size==0 || values!=NULL);
72  }
73  StaticBuffer(const Value *values, Address size)
74  : Super(".StaticBuffer"), values_(const_cast<Value*>(values)), size_(size), rdonly_(true) {
75  ASSERT_require(size==0 || values!=NULL);
76  }
77 
78 public:
85  static typename Buffer<A, T>::Ptr instance(Value *values, Address size) {
86  return typename Buffer<A, T>::Ptr(new StaticBuffer(values, size));
87  }
88  static typename Buffer<A, T>::Ptr instance(const Value *values, Address size) {
89  return typename Buffer<A, T>::Ptr(new StaticBuffer(values, size));
90  }
96  bool isReadOnly() const {
97  return rdonly_;
98  }
99 
100  // It doesn't make sense to exactly copy a static buffer because the point is to create a new buffer that points to data
101  // that is independent of the source buffer. Therefore we create an allocating buffer instead.
102  typename Buffer<A, T>::Ptr copy() const /*override*/ {
103  typename Buffer<A, T>::Ptr newBuffer = AllocatingBuffer<A, T>::instance(size_);
104  Address nWritten = newBuffer->write(values_, 0, size_);
105  if (nWritten != size_) {
106  throw std::runtime_error("StaticBuffer::copy() failed after copying " +
107  boost::lexical_cast<std::string>(nWritten) + " of " +
108  boost::lexical_cast<std::string>(size_) +
109  (1==size_?" value":" values"));
110  }
111  return newBuffer;
112  }
113 
114  Address available(Address start) const /*override*/ {
115  return start < size_ ? size_-start : 0;
116  }
117 
118  void resize(Address newSize) /*override*/ {
119  if (newSize != size_)
120  throw std::runtime_error("unable to resize StaticBuffer");
121  }
122 
123  Address read(Value *buf, Address address, Address n) const /*override*/ {
124  n = std::min(n, available(address));
125  if (buf)
126  memcpy(buf, values_+address, n*sizeof(values_[0]));
127  return n;
128  }
129 
130  Address write(const Value *buf, Address address, Address n) /*override*/ {
131  if (rdonly_)
132  return 0;
133  n = std::min(n, available(address));
134  if (buf)
135  memcpy(values_+address, buf, n*sizeof(values_[0]));
136  return n;
137  }
138 
139  const Value* data() const /*override*/ {
140  return values_;
141  }
142 };
143 
144 } // namespace
145 } // namespace
146 
147 #endif
A Address
Type of addresses.
Definition: StaticBuffer.h:32
Points to static data.
Definition: StaticBuffer.h:30
static Buffer< A, T >::Ptr instance(Address size)
Allocating constructor.
Buffer< A, T >::Ptr copy() const
Create a new copy of buffer data.
Definition: StaticBuffer.h:102
Reference-counting intrusive smart pointer.
Definition: SharedPointer.h:68
Name space for the entire library.
Definition: FeasiblePath.h:767
virtual Address size() const
Size of buffer.
Definition: Buffer.h:76
static Buffer< A, T >::Ptr instance(Value *values, Address size)
Construct from caller-supplied data.
Definition: StaticBuffer.h:85
SharedPointer< Buffer > Ptr
Reference counting smart pointer.
Definition: Buffer.h:45
Base class for all buffers.
Definition: Buffer.h:25
bool isReadOnly() const
True if the buffer is read-only.
Definition: StaticBuffer.h:96
Address read(Value *buf, Address address, Address n) const
Reads data from a buffer.
Definition: StaticBuffer.h:123
void resize(Address newSize)
Change the size of the buffer.
Definition: StaticBuffer.h:118
Buffer< A, T > Super
Type of base class.
Definition: StaticBuffer.h:34
Address available(Address start) const
Distance to end of buffer.
Definition: StaticBuffer.h:114
static Buffer< A, T >::Ptr instance(const Value *values, Address size)
Construct from caller-supplied data.
Definition: StaticBuffer.h:88
const Value * data() const
Data for the buffer.
Definition: StaticBuffer.h:139
Address write(const Value *buf, Address address, Address n)
Writes data to a buffer.
Definition: StaticBuffer.h:130