evio  6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ByteBuffer.h
Go to the documentation of this file.
1 //
2 // Copyright 2020, Jefferson Science Associates, LLC.
3 // Subject to the terms in the LICENSE file found in the top-level directory.
4 //
5 // EPSCI Group
6 // Thomas Jefferson National Accelerator Facility
7 // 12000, Jefferson Ave, Newport News, VA 23606
8 // (757)-269-7100
9 
10 
11 #ifndef EVIO_6_0_BYTEBUFFER_H
12 #define EVIO_6_0_BYTEBUFFER_H
13 
14 
15 #include <cstdlib>
16 #include <cstdint>
17 #include <cstring>
18 #include <memory>
19 #include <iostream>
20 #include <cstdio>
21 #include <vector>
22 #include <stdexcept>
23 #include <sys/mman.h>
24 
25 
26 #include "ByteOrder.h"
27 #include "EvioException.h"
28 
29 
30 namespace evio {
31 
32 
42  class ByteBuffer {
43 
44  private:
45 
48  mutable size_t pos = 0;
49 
51  mutable size_t lim = 0;
52 
54  mutable ssize_t mrk = -1;
55 
58  size_t off = 0;
59 
61  size_t cap = 0;
62 
68  size_t totalSize = 0;
69 
74  std::shared_ptr<uint8_t> buf = nullptr;
75 
78 
80  bool isHostEndian = false;
81 
83  bool isLittleEndian = false;
84 
88  bool isMappedMemory = false;
89 
90  public:
91 
92  ByteBuffer();
93  explicit ByteBuffer(size_t size);
94  ByteBuffer(const ByteBuffer & srcBuf);
95  ByteBuffer(ByteBuffer && srcBuf) noexcept;
96  ByteBuffer(char* byteArray, size_t len, bool isMappedMem = false);
97  ByteBuffer(uint8_t* byteArray, size_t len, bool isMappedMem = false);
98 
99  ~ByteBuffer();
100 
101  bool operator== (const ByteBuffer& rhs) noexcept;
102  bool operator!= (const ByteBuffer& rhs) noexcept;
103  ByteBuffer & operator=(ByteBuffer&& other) noexcept;
104  ByteBuffer & operator=(const ByteBuffer& other);
105  uint8_t & operator[] (size_t index);
106  uint8_t operator[] (size_t index) const;
107  ByteBuffer & compact();
108  ByteBuffer & zero();
109 
110  static std::shared_ptr<ByteBuffer> copyBuffer(const std::shared_ptr<const ByteBuffer> & srcBuf);
111  void copyData(const std::shared_ptr<const ByteBuffer> & srcBuf, size_t pos, size_t limit);
112  void copy(const ByteBuffer & srcBuf);
113  void copy(const std::shared_ptr<const ByteBuffer> & srcBuf);
114  bool equals(const ByteBuffer & other);
115  void expand(size_t newSize);
116 
117  bool isDirect() const;
118  bool hasArray() const;
119  bool hasRemaining() const;
120  bool isReadOnly() const;
121  const ByteOrder & order() const;
122  uint8_t * array() const;
123  std::shared_ptr<uint8_t> getData() const;
124 
125  size_t arrayOffset() const;
126  size_t remaining() const;
127  size_t capacity() const;
128  size_t limit() const;
129  size_t position() const;
130 
131  ByteBuffer & mark();
132  ByteBuffer & clear();
133  ByteBuffer & flip();
134  ByteBuffer & reset();
135  ByteBuffer & rewind();
136  ByteBuffer & position(size_t p);
137  ByteBuffer & limit(size_t l);
138 
139  ByteBuffer & order(ByteOrder const & order);
140  ByteBuffer & duplicate(ByteBuffer & destBuf);
141  std::shared_ptr<ByteBuffer> & duplicate(std::shared_ptr<ByteBuffer> & destBuf);
142  std::shared_ptr<ByteBuffer> duplicate();
143  ByteBuffer & slice(ByteBuffer & destBuf);
144  std::shared_ptr<ByteBuffer> & slice(std::shared_ptr<ByteBuffer> & destBuf);
145  std::shared_ptr<ByteBuffer> slice();
146 
147  // Read
148 
149  const ByteBuffer & getBytes(uint8_t * dst, size_t length) const;
150  const ByteBuffer & getBytes(std::vector<uint8_t> & dst, size_t offset, size_t length) const;
151 
152  uint8_t peek() const;
153  uint8_t getByte() const;
154  uint8_t getByte(size_t index) const;
155 
156  wchar_t getChar() const; // Relative
157  wchar_t getChar(size_t index) const; // Absolute
158 
159  int16_t getShort() const;
160  int16_t getShort(size_t index) const;
161  uint16_t getUShort() const;
162  uint16_t getUShort(size_t index) const;
163 
164  int32_t getInt() const;
165  int32_t getInt(size_t index) const;
166  uint32_t getUInt() const;
167  uint32_t getUInt(size_t index) const;
168 
169  int64_t getLong() const;
170  int64_t getLong(size_t index) const;
171  uint64_t getULong() const;
172  uint64_t getULong(size_t index) const;
173 
174  float getFloat() const;
175  float getFloat(size_t index) const;
176  double getDouble() const;
177  double getDouble(size_t index) const;
178 
179  // Write
180 
181  // Bulk byte writes
182  ByteBuffer & put(const ByteBuffer & src);
183  ByteBuffer & put(const std::shared_ptr<ByteBuffer> & src);
184  ByteBuffer & put(const uint8_t * src, size_t length);
185  ByteBuffer & put(const std::vector<uint8_t> & src, size_t offset, size_t length);
186 
187  ByteBuffer & put(uint8_t val); // Relative write
188  ByteBuffer & put(size_t index, uint8_t val); // Absolute write at index
189 
190  ByteBuffer & putChar(wchar_t val);
191  ByteBuffer & putChar(size_t index, wchar_t val);
192 
193  ByteBuffer & putShort(uint16_t val);
194  ByteBuffer & putShort(size_t index, uint16_t val);
195  // TODO: is this OK to use with int32_t ???????
196  ByteBuffer & putInt(uint32_t val);
197  ByteBuffer & putInt(size_t index, uint32_t val);
198 
199  ByteBuffer & putLong(uint64_t val);
200  ByteBuffer & putLong(size_t index, uint64_t val);
201 
202  ByteBuffer & putFloat(float val);
203  ByteBuffer & putFloat(size_t index, float val);
204 
205  ByteBuffer & putDouble(double val);
206  ByteBuffer & putDouble(size_t index, double val);
207 
208  // Utility Methods
209  void printBytes(size_t offset, size_t bytes, std::string const & label);
210  std::string toString() const;
211 
212  private:
213 
215  template<typename T> T read() const {
216  T data = read<T>(pos);
217  pos += sizeof(T);
218  return data;
219  }
220 
222  template<typename T> T read(size_t index) const {
223  if (index + sizeof(T) <= lim) {
224  return *((T *) &(buf.get())[index + off]);
225  }
226  // Read would exceed limit
227  throw std::underflow_error("buffer underflow");
228  }
229 
231  template<typename T> void write(T & data) {
232  size_t s = sizeof(data);
233 
234  if (lim < (pos + s)) {
235  // Write would exceeded limit
236  throw std::overflow_error("buffer overflow");
237  }
238  memcpy((void *) (&(buf.get())[pos + off]), (void *) (&data), s);
239 
240  pos += s;
241  }
242 
244  template<typename T> void write(T & data, size_t index) {
245  size_t s = sizeof(data);
246  if ((index + s) > lim) {
247  throw std::overflow_error("buffer overflow");
248  }
249 
250  memcpy((void *) (&(buf.get())[index + off]), (void *) (&data), s);
251  }
252 
253  // Follwing methods are a little more efficient for 1 byte transfers.
254 
260  void write(uint8_t & data) {
261  if (lim < (pos + 1)) {
262  throw std::overflow_error("buffer overflow");
263  }
264  buf.get()[off + pos++] = data;
265  }
266 
272  void write(char & data) {
273  if (lim < (pos + 1)) {
274  throw std::overflow_error("buffer overflow");
275  }
276  buf.get()[off + pos++] = data;
277  }
278 
279  void write(uint8_t & data, size_t index) {
280  if ((index + 1) > lim) {
281  throw std::overflow_error("buffer overflow");
282  }
283  buf.get()[index + off] = data;
284  }
285 
286  void write(char & data, size_t index) {
287  if ((index + 1) > lim) {
288  throw std::overflow_error("buffer overflow");
289  }
290  buf.get()[index + off] = data;
291  }
292 
293 
294  uint8_t read() const {
295  if (pos + 1 <= lim) {
296  return buf.get()[pos + off];
297  }
298  throw std::underflow_error("buffer underflow");
299  }
300 
301  uint8_t read(size_t index) const {
302  if (index + 1 <= lim) {
303  return buf.get()[index + off];
304  }
305  throw std::underflow_error("buffer underflow");
306  }
307 
308  };
309 
310 
311 } // namespace evio
312 
313 
314 
315 #endif //EVIO_6_0_BYTEBUFFER_H
ByteBuffer & putShort(uint16_t val)
Relative put method for writing a short value.
Definition: ByteBuffer.cpp:1525
This class is copied from one of the same name in the Java programming language.
Definition: ByteBuffer.h:42
void expand(size_t newSize)
This method expands the size of this buffer if it&#39;s less than the given size.
Definition: ByteBuffer.cpp:386
const ByteOrder & order() const
Get the byte order of the data.
Definition: ByteBuffer.cpp:466
bool isDirect() const
This method has no relevance to this C++ library.
Definition: ByteBuffer.cpp:436
ByteBuffer & rewind()
Rewinds this buffer.
Definition: ByteBuffer.cpp:576
ByteBuffer & put(const ByteBuffer &src)
Relative bulk put method.
Definition: ByteBuffer.cpp:1325
size_t remaining() const
Returns the number of bytes from the current position to the end of the data.
Definition: ByteBuffer.cpp:497
Numerical values associated with endian byte order.
Definition: ByteOrder.h:53
ByteBuffer & putLong(uint64_t val)
Relative put method for writing a long long value.
Definition: ByteBuffer.cpp:1615
ByteBuffer & operator=(ByteBuffer &&other) noexcept
Move assignment operator.
Definition: ByteBuffer.cpp:121
void printBytes(size_t offset, size_t bytes, std::string const &label)
This method prints out the desired number of data bytes starting from the given index without regard ...
Definition: ByteBuffer.cpp:1753
std::string toString() const
Obtain a string representation of the buffer.
Definition: ByteBuffer.cpp:1777
ByteBuffer & flip()
Flips this buffer.
Definition: ByteBuffer.cpp:549
uint32_t getUInt() const
Relative get method for reading an unsigned int value.
Definition: ByteBuffer.cpp:1115
ByteBuffer & putInt(uint32_t val)
Relative put method for writing an int value.
Definition: ByteBuffer.cpp:1570
bool equals(const ByteBuffer &other)
This method tests for data equivilancy.
Definition: ByteBuffer.cpp:411
bool operator!=(const ByteBuffer &rhs) noexcept
Inequality operator.
Definition: ByteBuffer.cpp:191
const ByteBuffer & getBytes(uint8_t *dst, size_t length) const
Relative bulk get method.
Definition: ByteBuffer.cpp:877
ByteBuffer & putDouble(double val)
Relative put method for writing a double value.
Definition: ByteBuffer.cpp:1705
std::shared_ptr< uint8_t > getData() const
Get a shared pointer to this buffer&#39;s backing array which contains the data.
Definition: ByteBuffer.cpp:483
size_t capacity() const
Returns the total available bytes in this buffer.
Definition: ByteBuffer.cpp:504
ByteBuffer & mark()
Sets the buffer&#39;s mark at its position.
Definition: ByteBuffer.cpp:525
bool hasRemaining() const
Returns whether there are bytes remaining between the position and limit, i.e.
Definition: ByteBuffer.cpp:452
static std::shared_ptr< ByteBuffer > copyBuffer(const std::shared_ptr< const ByteBuffer > &srcBuf)
Copy the given buffer into a new buffer which is accessed thru shared pointer.
Definition: ByteBuffer.cpp:257
size_t arrayOffset() const
Get the offset within this buffer&#39;s backing array of the first element of the buffer.
Definition: ByteBuffer.cpp:490
bool operator==(const ByteBuffer &rhs) noexcept
Equality operator.
Definition: ByteBuffer.cpp:180
std::shared_ptr< ByteBuffer > slice()
Creates a new byte buffer whose content is a shared subsequence of this buffer&#39;s content.
Definition: ByteBuffer.cpp:770
wchar_t getChar() const
Relative get method for reading a 16-bit unicode character value which is by nature unsigned...
Definition: ByteBuffer.cpp:961
int64_t getLong() const
Relative get method for reading a long long value.
Definition: ByteBuffer.cpp:1156
int32_t getInt() const
Relative get method for reading an int value.
Definition: ByteBuffer.cpp:1074
ByteBuffer()
Default constructor, size of 4096 bytes.
Definition: ByteBuffer.cpp:22
uint8_t & operator[](size_t index)
Subscript operator for absolute access to data bytes without limit check.
Definition: ByteBuffer.cpp:202
void copy(const ByteBuffer &srcBuf)
Copy data and everything else from arg.
Definition: ByteBuffer.cpp:222
size_t position() const
Returns the position of the buffer.
Definition: ByteBuffer.cpp:518
bool hasArray() const
Tells whether or not this buffer is backed by an array.
Definition: ByteBuffer.cpp:444
ByteBuffer & putChar(wchar_t val)
Relative put method for writing a wide char value.
Definition: ByteBuffer.cpp:1480
uint8_t peek() const
Relative get method.
Definition: ByteBuffer.cpp:926
ByteBuffer & reset()
Resets this buffer&#39;s position to the previously-marked position.
Definition: ByteBuffer.cpp:562
ByteBuffer & zero()
This method writes zeroes into the buffer memory (from pos = 0 to capacity).
Definition: ByteBuffer.cpp:319
ByteBuffer & putFloat(float val)
Relative put method for writing a float value.
Definition: ByteBuffer.cpp:1660
ByteBuffer & compact()
This method compacts this buffer.
Definition: ByteBuffer.cpp:339
uint8_t * array() const
Get a pointer to this buffer&#39;s backing array which contains the data.
Definition: ByteBuffer.cpp:475
uint8_t getByte() const
Relative get method.
Definition: ByteBuffer.cpp:936
uint16_t getUShort() const
Relative get method for reading an unsigned short value.
Definition: ByteBuffer.cpp:1032
double getDouble() const
Relative get method for reading a double value.
Definition: ByteBuffer.cpp:1273
std::shared_ptr< ByteBuffer > duplicate()
Returns a byte buffer that shares this buffer&#39;s content.
Definition: ByteBuffer.cpp:737
void copyData(const std::shared_ptr< const ByteBuffer > &srcBuf, size_t pos, size_t limit)
Copy the source buffer&#39;s data (position to limit) into this buffer starting at local position 0...
Definition: ByteBuffer.cpp:283
ByteBuffer & clear()
Clears this buffer.
Definition: ByteBuffer.cpp:536
size_t limit() const
Returns the limit, the position of the last valid data byte.
Definition: ByteBuffer.cpp:511
int16_t getShort() const
Relative get method for reading a short value.
Definition: ByteBuffer.cpp:989
float getFloat() const
Relative get method for reading a float value.
Definition: ByteBuffer.cpp:1238
uint64_t getULong() const
Relative get method for reading an unsigned long long value.
Definition: ByteBuffer.cpp:1197
static const ByteOrder ENDIAN_LOCAL
Local host&#39;s byte order.
Definition: ByteOrder.h:61
~ByteBuffer()
Destructor.
Definition: ByteBuffer.cpp:108
bool isReadOnly() const
Returns whether this buffer is read only.
Definition: ByteBuffer.cpp:459