cpp-mate  0.7
Helpful library for C++.
ReadStream.hpp
1 /*
2  * Copyright (C) 2019-2020 Alexander Kornilov (akornilov.82@gmail.com)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CPP_MATE_READ_STREAM_HPP
18 #define CPP_MATE_READ_STREAM_HPP
19 
20 #include <CppMate/BinaryData.hpp>
21 #include <CppMate/BinarySink.hpp>
22 #include <CppMate/ByteOrder.hpp>
23 #include <CppMate/Checkers.hpp>
24 
25 #include <cstring>
26 
27 #include <memory>
28 #include <string>
29 #include <algorithm>
30 #include <utility>
31 #include <stdexcept>
32 
33 namespace CppMate {
34 
38 class ReadStream final
39 {
40 public:
41 
48  ReadStream(std::shared_ptr<BinaryData> data, ByteOrder byteOrder = ByteOrder::Unknown):
49  _sharedData(std::move(data)),
50  _data(_sharedData.get()),
51  _binary(_data ? _data->getData() : nullptr),
52  _size(_data ? _data->getSize() : 0),
53  _byteOrder(byteOrder != ByteOrder::Unknown ? byteOrder : getNativeByteOrder()),
54  _isNativeByteOrder(_byteOrder == getNativeByteOrder()),
55  _position(0)
56  {
57  checkArg(_binary);
58  }
59 
66  ReadStream(const BinaryData* data, ByteOrder byteOrder = ByteOrder::Unknown) :
67  _data(data),
68  _binary(_data ? _data->getData() : nullptr),
69  _size(_data ? _data->getSize() : 0),
70  _byteOrder(byteOrder != ByteOrder::Unknown ? byteOrder : getNativeByteOrder()),
71  _isNativeByteOrder(_byteOrder == getNativeByteOrder()),
72  _position(0)
73  {
74  checkArg(_binary);
75  }
76 
81  const BinaryData* getData() const { return _data; }
82 
87  uint64_t getSize() const { return _size; }
88 
93  uint64_t getAvailable() const { return _position < _size ? _size - _position : 0; }
94 
99  ByteOrder getByteOrder() const { return _byteOrder; }
100 
105  uint64_t getPosition() const { return _position; }
106 
111  void setPosition(uint64_t position) { _position = position; }
112 
116  void reset() { setPosition(0); }
117 
123  void seek(uint64_t offset, bool forward = true) { setPosition(forward ? _position + offset : _position - offset); }
124 
129  template<typename T>
130  inline void seek(uint64_t count = 1) { seek(sizeof(T) * count); }
131 
136  void seekAlign(unsigned align) { const auto rem = static_cast<unsigned>(getPosition()) % align; if (rem) seek(align - rem); }
137 
143  bool canRead(uint64_t bytes) const { return getAvailable() >= bytes; }
144 
150  template<typename T>
151  inline bool canRead(uint64_t count = 1) const { return canRead(sizeof(T) * count); }
152 
157  template<typename T>
158  inline T read() {
159  T result;
160  if (_isNativeByteOrder || sizeof(T) < 2) {
161  result = *reinterpret_cast<const T *>(_binary + _position);
162  } else {
163  auto const resultPtr = reinterpret_cast<uint8_t *>(&result);
164  switch (sizeof(T)) {
165  case 2:
166  resultPtr[0] = *(_binary + _position + 1);
167  resultPtr[1] = *(_binary + _position);
168  break;
169  case 4:
170  resultPtr[0] = *(_binary + _position + 3);
171  resultPtr[1] = *(_binary + _position + 2);
172  resultPtr[2] = *(_binary + _position + 1);
173  resultPtr[3] = *(_binary + _position);
174  break;
175  case 8:
176  resultPtr[0] = *(_binary + _position + 7);
177  resultPtr[1] = *(_binary + _position + 6);
178  resultPtr[2] = *(_binary + _position + 5);
179  resultPtr[3] = *(_binary + _position + 4);
180  resultPtr[4] = *(_binary + _position + 3);
181  resultPtr[5] = *(_binary + _position + 2);
182  resultPtr[6] = *(_binary + _position + 1);
183  resultPtr[7] = *(_binary + _position);
184  break;
185  default:
186  for (auto i = 0u; i < sizeof(T); i++) {
187  resultPtr[i] = *(_binary + _position + (sizeof(T) - i - 1));
188  }
189  break;
190  }
191  }
192  seek<T>();
193  return result;
194  }
195 
201  std::string readString(uint64_t length) {
202  std::string result(length, '\0');
203  memcpy(&result[0], _binary + _position, length);
204  _position += length;
205  return result;
206  }
207 
215  uint64_t readBytes(uint8_t* buffer, uint64_t bufferSize) {
216  checkArg(buffer);
217  const auto count = std::min(getAvailable(), bufferSize);
218  memcpy(buffer, _binary + _position, static_cast<size_t>(count));
219  _position += count;
220  return count;
221  }
222 
228  void transfer(BinarySink& sink, uint64_t bytes) {
229  sink.write(_binary + _position, bytes);
230  _position += bytes;
231  }
232 
239  template<typename T>
240  inline friend ReadStream& operator>>(ReadStream& stream, T& result);
241 
247  bool operator==(const ReadStream& other) const { return _data == other._data && _position == other._position && _byteOrder == other._byteOrder; }
248 
254  bool operator!=(const ReadStream& other) const { return !(*this == other); }
255 
256 private:
257  std::shared_ptr<BinaryData> _sharedData;
258  const BinaryData* _data;
259  const uint8_t* _binary;
260  const uint64_t _size;
261  const ByteOrder _byteOrder;
262  const bool _isNativeByteOrder;
263  uint64_t _position;
264 };
265 
266 template<typename T>
267 inline ReadStream& operator>>(ReadStream& stream, T& result) {
268  result = stream.read<T>();
269  return stream;
270 }
271 
272 template<>
273 inline uint8_t ReadStream::read<uint8_t>()
274 {
275  return _binary[_position++];
276 }
277 
278 template<>
279 inline char ReadStream::read<char>()
280 {
281  return static_cast<char>(_binary[_position++]);
282 }
283 
284 } // namespace CppMate
285 
286 #endif // CPP_MATE_READ_STREAM_HPP
Represents interface of abstract binary data.
Definition: BinaryData.hpp:34
Represents low-level interface of abstract binary sink.
Definition: BinarySink.hpp:36
virtual void write(const void *data, uint64_t size)=0
Writes data into the sink.
Represents the byte stream reader with custom byte order.
Definition: ReadStream.hpp:39
void reset()
Resets stream position to begin of the source data.
Definition: ReadStream.hpp:116
void setPosition(uint64_t position)
Sets a new absolute position of the stream.
Definition: ReadStream.hpp:111
bool operator!=(const ReadStream &other) const
operator !=
Definition: ReadStream.hpp:254
std::string readString(uint64_t length)
Reads string from the stream.
Definition: ReadStream.hpp:201
uint64_t getAvailable() const
Returns number of bytes available to read.
Definition: ReadStream.hpp:93
uint64_t readBytes(uint8_t *buffer, uint64_t bufferSize)
Reads a particular number of bytes from the stream.
Definition: ReadStream.hpp:215
bool operator==(const ReadStream &other) const
operator ==
Definition: ReadStream.hpp:247
void seekAlign(unsigned align)
Changes position of stream to the closest position divisible by the provided parameter.
Definition: ReadStream.hpp:136
void seek(uint64_t offset, bool forward=true)
Changes position of the stream by increase the offset value with the current position....
Definition: ReadStream.hpp:123
ReadStream(const BinaryData *data, ByteOrder byteOrder=ByteOrder::Unknown)
Constructor.
Definition: ReadStream.hpp:66
T read()
Reads item from the stream. The method doesn't validate bounds, see canRead.
Definition: ReadStream.hpp:158
void transfer(BinarySink &sink, uint64_t bytes)
Transfer arbitrary block of bytes from stream to binary sink.
Definition: ReadStream.hpp:228
uint64_t getPosition() const
Returns current position of the stream.
Definition: ReadStream.hpp:105
ReadStream(std::shared_ptr< BinaryData > data, ByteOrder byteOrder=ByteOrder::Unknown)
Constructor.
Definition: ReadStream.hpp:48
bool canRead(uint64_t count=1) const
Checks the ability to read a specified number of items.
Definition: ReadStream.hpp:151
uint64_t getSize() const
Returns size of the stream.
Definition: ReadStream.hpp:87
ByteOrder getByteOrder() const
Returns byte order of the stream.
Definition: ReadStream.hpp:99
const BinaryData * getData() const
Returns binary data of stream.
Definition: ReadStream.hpp:81
bool canRead(uint64_t bytes) const
Checks the ability to read a specified number of bytes.
Definition: ReadStream.hpp:143
void seek(uint64_t count=1)
Seeks stream over a specified number of items.
Definition: ReadStream.hpp:130
friend ReadStream & operator>>(ReadStream &stream, T &result)
operator >>
Definition: ReadStream.hpp:267
Definition: BinaryData.hpp:28
ByteOrder CPP_MATE_LIB_API getNativeByteOrder()
Returns platform byte order.
ReadStream & operator>>(ReadStream &stream, T &result)
Definition: ReadStream.hpp:267
ByteOrder
The byte order type.
Definition: ByteOrder.hpp:29
@ Unknown
Unknown byte order.