ROSE 0.11.145.147
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://gitlab.com/charger7534/sawyer.git.
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#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
17#include <boost/serialization/array.hpp>
18#endif
19
20#ifdef SAWYER_HAVE_CEREAL
21#include <cereal/types/array.hpp>
22#endif
23
24namespace Sawyer {
25namespace Container {
26
31template<class A, class T>
32class StaticBuffer: public Buffer<A, T> {
33public:
34 typedef A Address;
35 typedef T Value;
38private:
39 Value *values_;
40 Address size_;
41 bool rdonly_;
42
43#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
44private:
45 friend class boost::serialization::access;
46
47 template<class S>
48 void save(S &s, const unsigned /*version*/) const {
49 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
50 s & BOOST_SERIALIZATION_NVP(size_);
51 s & BOOST_SERIALIZATION_NVP(rdonly_);
52 s & boost::serialization::make_nvp("values", boost::serialization::make_array(values_, size_));
53 }
54
55 template<class S>
56 void load(S &s, const unsigned /*version*/) {
57 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
58 s & BOOST_SERIALIZATION_NVP(size_);
59 s & BOOST_SERIALIZATION_NVP(rdonly_);
60 values_ = new Value[size_];
61 s & boost::serialization::make_nvp("values", boost::serialization::make_array(values_, size_));
62 }
63
64 BOOST_SERIALIZATION_SPLIT_MEMBER();
65#endif
66
67#ifdef SAWYER_HAVE_CEREAL
68private:
69 friend class cereal::access;
70
71 template<class Archive>
72 void CEREAL_SAVE_FUNCTION_NAME(Archive &archive) const {
73 archive(cereal::base_class<Super>());
74 archive(CEREAL_NVP(size_));
75 archive(CEREAL_NVP(rdonly_));
76 archive(cereal::binary_data(values_, size_));
77 }
78
79 template<class Archive>
80 void CEREAL_LOAD_FUNCTION_NAME(Archive &archive) {
81 archive(cereal::base_class<Super>());
82 archive(CEREAL_NVP(size_));
83 archive(CEREAL_NVP(rdonly_));
84 values_ = new Value[size_];
85 archive(cereal::binary_data(values_, size_));
86 }
87#endif
88
89private:
90 // For serialization only
91 StaticBuffer()
92 : values_(NULL), size_(0), rdonly_(false) {}
93
94protected:
95 StaticBuffer(Value *values, Address size)
96 : Super(".StaticBuffer"), values_(values), size_(size), rdonly_(false) {
97 ASSERT_require(size==0 || values!=NULL);
98 }
99 StaticBuffer(const Value *values, Address size)
100 : Super(".StaticBuffer"), values_(const_cast<Value*>(values)), size_(size), rdonly_(true) {
101 ASSERT_require(size==0 || values!=NULL);
102 }
103
104public:
111 static typename Buffer<A, T>::Ptr instance(Value *values, Address size) {
112 return typename Buffer<A, T>::Ptr(new StaticBuffer(values, size));
113 }
114 static typename Buffer<A, T>::Ptr instance(const Value *values, Address size) {
115 return typename Buffer<A, T>::Ptr(new StaticBuffer(values, size));
116 }
122 bool isReadOnly() const {
123 return rdonly_;
124 }
125
126 // It doesn't make sense to exactly copy a static buffer because the point is to create a new buffer that points to data
127 // that is independent of the source buffer. Therefore we create an allocating buffer instead.
128 typename Buffer<A, T>::Ptr copy() const /*override*/ {
129 typename Buffer<A, T>::Ptr newBuffer = AllocatingBuffer<A, T>::instance(size_);
130 Address nWritten = newBuffer->write(values_, 0, size_);
131 if (nWritten != size_) {
132 throw std::runtime_error("StaticBuffer::copy() failed after copying " +
133 boost::lexical_cast<std::string>(nWritten) + " of " +
134 boost::lexical_cast<std::string>(size_) +
135 (1==size_?" value":" values"));
136 }
137 return newBuffer;
138 }
139
140 Address available(Address start) const /*override*/ {
141 return start < size_ ? size_-start : 0;
142 }
143
144 void resize(Address newSize) /*override*/ {
145 if (newSize != size_)
146 throw std::runtime_error("unable to resize StaticBuffer");
147 }
148
149 Address read(Value *buf, Address address, Address n) const /*override*/ {
150 n = std::min(n, available(address));
151 if (buf)
152 memcpy(buf, values_+address, n*sizeof(values_[0]));
153 return n;
154 }
155
156 Address write(const Value *buf, Address address, Address n) /*override*/ {
157 if (rdonly_)
158 return 0;
159 n = std::min(n, available(address));
160 if (buf)
161 memcpy(values_+address, buf, n*sizeof(values_[0]));
162 return n;
163 }
164
165 const Value* data() const /*override*/ {
166 return values_;
167 }
168};
169
170} // namespace
171} // namespace
172
173#endif
static Buffer< A, T >::Ptr instance(Address size)
Allocating constructor.
Base class for all buffers.
Definition Buffer.h:23
virtual Address size() const
Size of buffer.
Definition Buffer.h:93
SharedPointer< Buffer > Ptr
Reference counting smart pointer.
Definition Buffer.h:62
Points to static data.
A Address
Type of addresses.
Address write(const Value *buf, Address address, Address n)
Writes data to a buffer.
bool isReadOnly() const
True if the buffer is read-only.
Buffer< A, T > Super
Type of base class.
Buffer< A, T >::Ptr copy() const
Create a new copy of buffer data.
static Buffer< A, T >::Ptr instance(const Value *values, Address size)
Construct from caller-supplied data.
void resize(Address newSize)
Change the size of the buffer.
const Value * data() const
Data for the buffer.
static Buffer< A, T >::Ptr instance(Value *values, Address size)
Construct from caller-supplied data.
Address read(Value *buf, Address address, Address n) const
Reads data from a buffer.
Address available(Address start) const
Distance to end of buffer.
Reference-counting intrusive smart pointer.
Sawyer support library.