OSVR-Core
Buffer.h
Go to the documentation of this file.
1 
12 // Copyright 2015 Sensics, Inc.
13 //
14 // Licensed under the Apache License, Version 2.0 (the "License");
15 // you may not use this file except in compliance with the License.
16 // You may obtain a copy of the License at
17 //
18 // http://www.apache.org/licenses/LICENSE-2.0
19 //
20 // Unless required by applicable law or agreed to in writing, software
21 // distributed under the License is distributed on an "AS IS" BASIS,
22 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 // See the License for the specific language governing permissions and
24 // limitations under the License.
25 
26 #ifndef INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D
27 #define INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D
28 
29 // Internal Includes
30 #include <osvr/Common/Buffer_fwd.h>
32 
33 // Library/third-party includes
34 #include <boost/version.hpp>
35 #include <boost/type_traits.hpp>
36 
37 #if BOOST_VERSION >= 105600
38 #include <boost/align/aligned_allocator.hpp>
39 #endif
40 
41 // Standard includes
42 #include <vector>
43 #include <stdexcept>
44 #include <algorithm>
45 
46 namespace osvr {
47 namespace common {
49  typedef char BufferElement;
50 
55  static const size_t value = 16;
56  };
57 #if BOOST_VERSION >= 105600
58  // New Boost has code to handle aligned allocation. Alignment is hard to do
59  // portably so we are happy to delegate.
60 
63 
65  typedef boost::alignment::aligned_allocator<
68 
69 #else
70  // Fallback for older boost: unaligned buffer. Want to rely on aligned
71  // buffers? Upgrade Boost and rebuild.
72 
75  static const size_t value = 1;
76  };
77 
79  typedef std::allocator<BufferElement> BufferAllocator;
80 #endif
81 
86  typedef std::vector<BufferElement, BufferAllocator> BufferByteVector;
87 
90  template <typename ElementType = BufferElement>
92  public:
93  typedef ElementType const *const_iterator;
94  typedef ElementType value_type;
95 
96  ExternalBufferReadingWrapper(ElementType const *buf, size_t size)
97  : m_buf(buf), m_size(size) {}
98 
99  const_iterator begin() const { return m_buf; }
100 
101  const_iterator end() const { return m_buf + m_size; }
102 
103  size_t size() const { return m_size; }
104 
105  private:
106  ElementType const *m_buf;
107  size_t m_size;
108  static_assert(sizeof(ElementType) == 1,
109  "Container must have byte-sized elements");
110  };
111 
117  template <typename ContainerType> class BufferReader {
118  public:
119  typedef typename ContainerType::const_iterator const_iterator;
120  typedef typename ContainerType::value_type ElementType;
121 
122  BufferReader(ContainerType const &buf)
123  : m_begin(buf.begin()), m_readIter(buf.begin()), m_end(buf.end()) {}
124 
125  size_t bytesRead() const { return m_readIter - m_begin; }
126  size_t bytesRemaining() const { return m_end - m_readIter; }
128  template <typename T> void read(T &v) {
129  if (bytesRemaining() < sizeof(T)) {
130  throw std::runtime_error(
131  "Not enough data in the buffer to read this type!");
132  }
135  ElementType *dest = reinterpret_cast<ElementType *>(&v);
136 
137  auto readEnd = m_readIter + sizeof(T);
138  std::copy(m_readIter, readEnd, dest);
139  m_readIter = readEnd;
140  }
141 
144  const_iterator readBytes(size_t const n) {
145  if (bytesRemaining() < n) {
146  throw std::runtime_error(
147  "Not enough data in the buffer to read that many bytes!");
148  }
149  auto ret = m_readIter;
150  m_readIter += n;
151  return ret;
152  }
153 
157  template <typename T> void readAligned(T &v, size_t const alignment) {
158  skipPadding(computeAlignmentPadding(alignment, bytesRead()));
159  read(v);
160  }
161 
165  const_iterator readBytesAligned(size_t const n,
166  size_t const alignment) {
167  skipPadding(computeAlignmentPadding(alignment, bytesRead()));
168  return readBytes(n);
169  }
170 
173  void skipPadding(size_t const bytes) {
174  if (bytes == 0) {
175  return;
176  }
177  if (bytesRemaining() < bytes) {
178  throw std::runtime_error("Can't skip that many padding "
179  "bytes, not that many bytes "
180  "left!");
181  }
182  m_readIter += bytes;
183  }
184 
185  private:
186  const_iterator m_begin;
187  const_iterator m_readIter;
188  const_iterator m_end;
189  static_assert(sizeof(ElementType) == 1,
190  "Container must have byte-sized elements");
191  };
192 
196  template <typename CharType>
198  readExternalBuffer(const CharType *buf, size_t len) {
201  }
202 
206  template <typename ContainerType = BufferByteVector> class Buffer {
207  public:
210  typedef typename ContainerType::value_type ElementType;
211 
214 
216  Buffer() {}
217 
220  explicit Buffer(ContainerType const &buf) : m_buf(buf) {}
221 
227  template <typename InputIterator>
228  Buffer(InputIterator beginIt, InputIterator endIt)
229  : m_buf(beginIt, endIt) {}
230 
234  template <typename T> void append(T const v) {
235  static_assert(!boost::is_pointer<T>::value,
236  "Cannot append the value of a pointer!");
239  ElementType const *src = reinterpret_cast<ElementType const *>(&v);
240  m_buf.insert(m_buf.end(), src, src + sizeof(T));
241  }
242 
248  template <typename T>
249  void appendAligned(T const v, size_t const alignment) {
250  appendPadding(computeAlignmentPadding(alignment, size()));
251  append(v);
252  }
253 
255  void append(ElementType const *v, size_t const n) {
256  m_buf.insert(m_buf.end(), v, v + n);
257  }
258 
262  void appendAligned(ElementType const *v, size_t const n,
263  size_t const alignment) {
264  appendPadding(computeAlignmentPadding(alignment, size()));
265  append(v, n);
266  }
267 
269  void appendPadding(size_t const bytes) {
270  if (bytes == 0) {
271  return;
272  }
273  m_buf.insert(m_buf.end(), bytes, '\0');
274  }
275 
279  Reader startReading() const { return Reader(m_buf); }
280 
282  size_t size() const { return m_buf.size(); }
283 
285  ContainerType &getContents() { return m_buf; }
286 
288  ElementType const *data() const { return m_buf.data(); }
289 
290  private:
291  ContainerType m_buf;
292  static_assert(sizeof(ElementType) == 1,
293  "Container must have byte-sized elements");
294  };
295 } // namespace common
296 } // namespace osvr
297 #endif // INCLUDED_Buffer_h_GUID_55EB8AAF_57A7_49A4_3A3A_49293A72211D
Reader startReading() const
Returns a reader object, for making a single read pass over the buffer.
Definition: Buffer.h:279
const_iterator readBytesAligned(size_t const n, size_t const alignment)
Returns an iterator into the buffer valid for n elements, after skipping the necessary number of byte...
Definition: Buffer.h:165
Handles spatial transformations.
Definition: SerializationTraitExample_Complicated.h:40
Buffer(ContainerType const &buf)
Constructs a buffer wrapper by copy-constructing the contained type.
Definition: Buffer.h:220
BufferReader< ContainerType > Reader
The corresponding BufferReader type.
Definition: Buffer.h:213
void skipPadding(size_t const bytes)
Skip reading the given number of bytes, assumed to be padding.
Definition: Buffer.h:173
char BufferElement
The single-byte element in a buffer.
Definition: Buffer.h:49
void appendAligned(ElementType const *v, size_t const n, size_t const alignment)
Append a byte-array&#39;s contents, after adding the necessary number of padding bytes to begin the write...
Definition: Buffer.h:262
Traits class specifying the (potentially platform-specific!) preferred alignment for Buffer...
Definition: Buffer.h:53
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
void readAligned(T &v, size_t const alignment)
Get the binary representation of a type from a buffer, after skipping the necessary number of bytes t...
Definition: Buffer.h:157
ContainerType & getContents()
Provides access to the underlying container.
Definition: Buffer.h:285
size_t computeAlignmentPadding(size_t alignment, size_t currentSize)
Given an alignment in bytes, and a current size of a buffer, return the number of bytes of padding re...
Definition: AlignmentPadding.h:49
detail::size< coerce_list< Ts... >> size
Get the size of a list (number of elements.)
Definition: Size.h:56
Header.
Class wrapping an externally-owned and controlled buffer with the vector-like functionality needed to...
Definition: Buffer.h:91
size_t size() const
Gets the current size, in bytes.
Definition: Buffer.h:282
void append(ElementType const *v, size_t const n)
Append a byte-array&#39;s contents.
Definition: Buffer.h:255
Buffer()
Constructs an empty buffer.
Definition: Buffer.h:216
A buffer of bytes, built on a byte-vector-like container.
Definition: Buffer.h:206
void appendAligned(T const v, size_t const alignment)
Append the binary representation of a value, after adding the necessary number of padding bytes to be...
Definition: Buffer.h:249
std::vector< BufferElement, BufferAllocator > BufferByteVector
A typedef for a vector of bytes usable as a buffer, that might be "over-aligned" in some desirable wa...
Definition: Buffer.h:86
std::allocator< BufferElement > BufferAllocator
Allocator type for Buffer - might be usefully aligned.
Definition: Buffer.h:79
static const size_t value
Alignment in bytes.
Definition: Buffer.h:55
ContainerType::value_type ElementType
The (necessarily byte-size) type of elements in the underlying container.
Definition: Buffer.h:210
Provides for a single reading pass over a buffer.
Definition: Buffer.h:117
void read(T &v)
Get the binary representation of a type from a buffer.
Definition: Buffer.h:128
void append(T const v)
Append the binary representation of a value.
Definition: Buffer.h:234
Buffer(InputIterator beginIt, InputIterator endIt)
Constructs a buffer by copying from two input iterators, representing a half-open range [beginIt...
Definition: Buffer.h:228
Traits class describing actual alignment of Buffer.
Definition: Buffer.h:74
BufferReader< ExternalBufferReadingWrapper< CharType > > readExternalBuffer(const CharType *buf, size_t len)
Constructs and returns a buffer reader for an externally-allocated buffer: it&#39;s on you to supply a va...
Definition: Buffer.h:198
ElementType const * data() const
Provides access to the underlying data.
Definition: Buffer.h:288
void appendPadding(size_t const bytes)
Append the specified number of bytes of padding.
Definition: Buffer.h:269
const_iterator readBytes(size_t const n)
Returns an iterator into the buffer valid for n elements, and assumes you&#39;ll take care of copying the...
Definition: Buffer.h:144