retdec
dynamic_buffer.h
Go to the documentation of this file.
1 
7 #ifndef RETDEC_UNPACKER_DYNAMIC_BUFFER_H
8 #define RETDEC_UNPACKER_DYNAMIC_BUFFER_H
9 
10 #include <cstdint>
11 #include <cstring>
12 #include <functional>
13 #include <vector>
14 
16 
17 namespace retdec {
18 namespace utils {
19 
36 {
37 public:
39  retdec::utils::Endianness endianness
41  );
43  uint32_t capacity,
44  retdec::utils::Endianness endianness
46  );
48  const std::vector<uint8_t>& data,
49  retdec::utils::Endianness endianness
51  );
52  DynamicBuffer(const DynamicBuffer& dynamicBuffer);
54  const DynamicBuffer& dynamicBuffer,
55  uint32_t startPos,
56  uint32_t amount
57  );
58 
59  DynamicBuffer& operator =(DynamicBuffer dynamicBuffer);
60 
61  void setCapacity(uint32_t capacity);
62  uint32_t getCapacity() const;
63 
66 
67  uint32_t getRealDataSize() const;
68 
69  void erase(uint32_t startPos, uint32_t amount);
70 
71  const uint8_t* getRawBuffer() const;
72  std::vector<uint8_t> getBuffer() const;
73 
74  void forEach(const std::function<void(uint8_t&)>& func);
75  void forEachReverse(const std::function<void(uint8_t&)>& func);
76 
92  template <typename T> T read(
93  uint32_t pos,
94  retdec::utils::Endianness endianness
96  {
97  static_assert(
98  std::is_integral<T>::value,
99  "retdec::utils::DynamicBuffer::read can only accept integral types"
100  );
101 
102  // In case of non-specified endianness, use the default one assigned
103  // to DynamicBuffer itself
104  if (endianness == retdec::utils::Endianness::UNKNOWN)
105  endianness = _endianness;
106 
107  return readImpl<T>(pos, endianness);
108  }
109 
110  std::string readString(uint32_t pos, uint32_t maxLength = 0) const;
111 
126  template <typename T> void write(
127  const T& data,
128  uint32_t pos,
129  retdec::utils::Endianness endianness
131  {
132  static_assert(
133  std::is_integral<T>::value,
134  "retdec::utils::DynamicBuffer::write can only accept integral types"
135  );
136 
137  // In case of non-specified endianness, use the default one
138  // assigned to DynamicBuffer itself
139  if (endianness == retdec::utils::Endianness::UNKNOWN)
140  endianness = _endianness;
141 
142  writeImpl(data, pos, endianness);
143  }
144 
145  void writeRepeatingByte(uint8_t byte, uint32_t pos, uint32_t repeatAmount);
146 
147 private:
148  template <typename T> void writeImpl(
149  const T& data,
150  uint32_t pos,
151  retdec::utils::Endianness endianness)
152  {
153  // If the writing position is completely out of bounds, we just end
154  if (pos >= _capacity)
155  return;
156 
157  // Buffer would overlap the capacity, copy just the chunk that fits
158  uint32_t bytesToWrite = sizeof(T);
159  if (pos + bytesToWrite > getCapacity())
160  bytesToWrite = getCapacity() - pos;
161 
162  if (bytesToWrite == 0)
163  return;
164 
165  // Check whether there is enough space allocated
166  if (pos + bytesToWrite > getRealDataSize())
167  _data.resize(pos + bytesToWrite);
168 
169  for (uint32_t i = 0; i < bytesToWrite; ++i)
170  {
171  switch (endianness)
172  {
174  _data[pos + i] = (data >> (i << 3)) & 0xFF;
175  break;
177  _data[pos + i] = (data >> ((bytesToWrite - i - 1) << 3)) & 0xFF;
178  break;
179  default:
180  break;
181  }
182  }
183  }
184 
185  template <typename T> T readImpl(
186  uint32_t pos,
187  retdec::utils::Endianness endianness) const
188  {
189  // We are at the end, we are unable to read anything
190  if (pos >= _data.size())
191  return T{};
192 
193  // We are at the end, we are unable to read anything
194  if (pos >= _capacity)
195  return T{};
196 
197  // If reading overlaps over the size, make sure we don't access
198  // uninitialized memory
199  uint32_t bytesToRead = sizeof(T);
200  if (pos + bytesToRead > getCapacity())
201  bytesToRead = getCapacity() - pos;
202 
203  if (pos + bytesToRead > getRealDataSize())
204  bytesToRead = getRealDataSize() - pos;
205 
206  T ret = T{};
207  for (uint32_t i = 0; i < bytesToRead; ++i)
208  {
209  switch (endianness)
210  {
212  ret |= static_cast<uint64_t>(_data[pos + i]) << (i << 3);
213  break;
215  ret |= static_cast<uint64_t>(_data[pos + i]) << ((bytesToRead - i - 1) << 3);
216  break;
217  default:
218  break;
219  }
220  }
221 
222  return ret;
223  }
224 
225  mutable std::vector<uint8_t> _data;
227  uint32_t _capacity;
228 };
229 
230 } // namespace utils
231 } // namespace retdec
232 
233 #endif
Declaration of ByteValueStorage.
The class for dynamic buffered data manipulation taking the endianness of the data in account.
Definition: dynamic_buffer.h:36
uint32_t _capacity
Definition: dynamic_buffer.h:227
void writeRepeatingByte(uint8_t byte, uint32_t pos, uint32_t repeatAmount)
Definition: dynamic_buffer.cpp:254
void setCapacity(uint32_t capacity)
Definition: dynamic_buffer.cpp:112
void write(const T &data, uint32_t pos, retdec::utils::Endianness endianness=retdec::utils::Endianness::UNKNOWN)
Definition: dynamic_buffer.h:126
void writeImpl(const T &data, uint32_t pos, retdec::utils::Endianness endianness)
Definition: dynamic_buffer.h:148
uint32_t getRealDataSize() const
Definition: dynamic_buffer.cpp:156
T readImpl(uint32_t pos, retdec::utils::Endianness endianness) const
Definition: dynamic_buffer.h:185
uint32_t getCapacity() const
Definition: dynamic_buffer.cpp:123
void forEachReverse(const std::function< void(uint8_t &)> &func)
Definition: dynamic_buffer.cpp:213
void forEach(const std::function< void(uint8_t &)> &func)
Definition: dynamic_buffer.cpp:201
retdec::utils::Endianness getEndianness() const
Definition: dynamic_buffer.cpp:145
std::string readString(uint32_t pos, uint32_t maxLength=0) const
Definition: dynamic_buffer.cpp:234
void setEndianness(retdec::utils::Endianness endianness)
Definition: dynamic_buffer.cpp:135
const uint8_t * getRawBuffer() const
Definition: dynamic_buffer.cpp:191
T read(uint32_t pos, retdec::utils::Endianness endianness=retdec::utils::Endianness::UNKNOWN) const
Definition: dynamic_buffer.h:92
DynamicBuffer & operator=(DynamicBuffer dynamicBuffer)
Definition: dynamic_buffer.cpp:99
std::vector< uint8_t > _data
Definition: dynamic_buffer.h:225
retdec::utils::Endianness _endianness
Definition: dynamic_buffer.h:226
DynamicBuffer(retdec::utils::Endianness endianness=retdec::utils::Endianness::LITTLE)
Definition: dynamic_buffer.cpp:20
std::vector< uint8_t > getBuffer() const
Definition: dynamic_buffer.cpp:181
void erase(uint32_t startPos, uint32_t amount)
Definition: dynamic_buffer.cpp:167
Endianness
Definition: byte_value_storage.h:21
Definition: archive_wrapper.h:19