Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
static_msg_buffer.h
Go to the documentation of this file.
1 /// @file Hg/static_msg_buffer.h
2 ///
3 /// A fixed-size messagge buffer that uses memory allocated by the user.
4 /// This message buffer is compatible with the Hg message.
5 ///
6 /// The MIT License(MIT)
7 /// @copyright 2014 Paul M Watt
8 // ****************************************************************************
9 #ifndef STATIC_MSG_BUFFER_H_INCLUDED
10 #define STATIC_MSG_BUFFER_H_INCLUDED
11 // Includes *******************************************************************
12 #include <Hg/msg_buffer.h>
14 
15 namespace Hg
16 {
17 
18 // ****************************************************************************
19 /// (Static) MsgBuffer Template Definition.
20 /// This class is a specialization of the template MsgBuffer, and uses
21 /// a static_storage_policy.
22 ///
23 template<>
25 {
26 public:
27  // Typedefs *****************************************************************
29  typedef storage_type::data_type data_type;
30  typedef storage_type::s_pointer s_pointer;
31  typedef storage_type::w_pointer w_pointer;
32 
33  typedef data_type* pointer;
34  typedef const data_type* const_pointer;
35 
36  // Construction *************************************************************
37  // **************************************************************************
38  /// Default Constructor
39  ///
41  : m_pData(0)
42  , m_size(0)
43  , m_offset(0)
44  {
45  // No current operations
46  }
47 
48  // Status *******************************************************************
49  // **************************************************************************
50  /// Indicates if memory is currently managed by this buffer.
51  ///
52  /// @return true - The buffer is empty.
53  /// false- There is memory allocated and managed by this buffer.
54  ///
55  bool empty() const
56  {
57  return !m_pData
58  || !size();
59  }
60 
61  // **************************************************************************
62  /// Return the number of bytes reserved for use by this buffer.
63  ///
64  /// @return The allocated buffer size is returned. This packet buffer
65  /// must be valid for a non-zero value to be returned.
66  ///
67  size_t capacity() const
68  {
69  return size();
70  }
71 
72  // **************************************************************************
73  /// Reports the current size of the buffer in use.
74  ///
75  /// @return The number of bytes in use in the allocated buffer.
76  /// If there is no internal buffer, 0 is returned.
77  ///
78  size_t size() const
79  {
80  return m_size;
81  }
82 
83  // Methods ******************************************************************
84  // **************************************************************************
85  /// Releases any resources associated with this object.
86  ///
87  void clear()
88  {
89  m_pData = 0;
90  m_size = 0;
91  m_offset = 0;
92  }
93 
94  // **************************************************************************
95  /// Resizes the buffer to contain n elements.
96  /// This function is not supported for this fixed size buffer.
97  ///
98  /// @param n The number of elements to allocate for the buffer.
99  /// @param val Optional value to be copied into each element allocated.
100  ///
101  void resize(size_t n)
102  {
103  // Not supported
104  }
105 
106  // **************************************************************************
107  void resize(size_t n, byte_t val)
108  {
109  // Not supported
110  }
111 
112  // **************************************************************************
113  /// Provides access to the packed memory buffer.
114  ///
115  /// @return Returns a constant pointer to the buffer that contains the
116  /// packed memory.
117  /// 0 is returned if there is no memory associated with the buffer.
118  ///
119  const_pointer data() const
120  {
121  return m_pData;
122  }
123 
124  // **************************************************************************
125  /// Zeroes the contents of the buffer if they have been assigned.
126  ///
127  void zero()
128  {
129  std::fill(m_pData, m_pData + size(), 0);
130  }
131 
132  // **************************************************************************
133  /// Assigns the contents of an incoming raw memory buffer to the message buffer.
134  ///
135  /// @param pBuffer A memory buffer whose contents will be assigned to
136  /// this message object. The values of the buffer are
137  /// copied into the message.
138  /// @param n The number of bytes held in p_buffer.
139  ///
140  void assign(const_pointer pBuffer, size_t n)
141  {
142  m_pData = const_cast<pointer>(pBuffer);
143  m_size = n;
144  }
145 
146  // **************************************************************************
147  /// Returns the offset used to access the buffer.
148  ///
149  /// Returns the offset used to access the buffer relative to the first index
150  /// in the buffer. The default offset is zero. Alternate offsets are allowed
151  /// to facilitate nested packet structures as well as dynamically formatted
152  /// structures.
153  ///
154  /// @return A number of bytes greater than 0 is returned.
155  ///
156  std::ptrdiff_t offset() const
157  {
158  return m_offset;
159  }
160 
161  // **************************************************************************
162  /// Assigns a new base offset for memory access to this object.
163  ///
164  /// @param new_offset The offset from the beginning of the supplied buffer.
165  ///
166  void offset(std::ptrdiff_t new_offset)
167  {
168  m_offset = new_offset;
169  }
170 
171  // **************************************************************************
172  /// Parameterized function that returns data from a specified offset in the buffer.
173  ///
174  /// @tparam T [typename] The parameterized type to be returned
175  /// to the caller.
176  /// @param value Accepts the value read from the packet buffer.
177  /// @param pos The offset from the beginning of the buffer to
178  /// read the output value.
179  ///
180  /// @return The number of bytes read from the buffer is returned.
181  /// It is possible for a successful case to return 0.
182  ///
183  template <typename T>
184  size_t get_data(T& value, std::ptrdiff_t pos) const
185  {
186  if (empty())
187  {
188  return 0;
189  }
190 
191  // Read from the user supplied offset as well as the base offset
192  // configured for this Packet Buffer.
193  std::ptrdiff_t total_offset = offset() + pos;
194 
195  // Verify the requested data can be read from the buffer.
196  size_t bytes_read = 0;
197  if ( total_offset >= 0
198  && total_offset + sizeof(value) <= size())
199  {
200  bytes_read =
201  storage_type::read( data(),
202  &value,
203  sizeof(T),
204  total_offset)
205  ? sizeof(T)
206  : 0;
207  }
208 
209  return bytes_read;
210  }
211 
212  // **************************************************************************
213  /// Parameterized function that reads a range of data from the buffer.
214  ///
215  /// @tparam T [typename] The parameterized type to be read
216  /// by the caller.
217  /// @param pBuffer Pointer to the first element in the array to
218  /// be written into.
219  ///
220  /// @param length The number of bytes to read in.
221  /// pBuffer must contain at least length number of
222  /// bytes.
223  ///
224  /// @param pos The offset from the beginning of the buffer to
225  /// read the input value.
226  ///
227  /// @return The number of bytes read from the buffer is returned.
228  /// It is possible for a successful case to return 0.
229  ///
230  size_t get_range(void* pBuffer, size_t length, size_t pos) const
231  {
232  if ( empty()
233  || 0 == pBuffer
234  || 0 == length)
235  {
236  return 0;
237  }
238 
239  // Read from the user supplied offset as well as the base offset
240  // configured for this Packet Buffer.
241  size_t total_offset = static_cast<size_t>(offset()) + pos;
242 
243  // Verify the data can be safely written within the bounds of the buffer.
244  size_t bytes_read = 0;
245  size_t total_size = this->size();
246  if ( (total_offset >= 0)
247  && (total_offset + length) <= total_size)
248  {
249  bytes_read =
250  storage_type::read( data(),
251  pBuffer,
252  length,
253  total_offset)
254  ? length
255  : 0;
256  }
257 
258  return bytes_read;
259  }
260 
261  // **************************************************************************
262  /// Parameterized function that writes data to a specified offset in the buffer.
263  ///
264  /// @tparam T [typename] The parameterized type to be written
265  /// by the caller.
266  /// @param value Contains the value to write to the packet buffer.
267  /// @param pos The offset from the beginning of the buffer to
268  /// write the input value.
269  ///
270  /// @return The number of bytes written to the buffer is returned.
271  /// It is possible for a successful case to return 0.
272  ///
273  template <typename T>
274  size_t set_data(const T& value, size_t pos)
275  {
276  if (empty())
277  {
278  return 0;
279  }
280 
281  // Read from the user supplied offset as well as the base offset
282  // configured for this Packet Buffer.
283  size_t total_offset = static_cast<size_t>(offset()) + pos;
284 
285  // Verify the data can be safely written within the bounds of the buffer.
286  size_t bytes_written = 0;
287  size_t total_size = size();
288  if ( (total_offset >= 0)
289  && (total_offset + Hg::SizeOf<T>::value) <= total_size)
290  {
291  bytes_written =
292  storage_type::write ( raw_data(),
293  &value,
295  total_offset)
297  : 0;
298  }
299 
300  return bytes_written;
301  }
302 
303  // **************************************************************************
304  /// Parameterized function that writes a range of data to the buffer.
305  ///
306  /// @tparam T [typename] The parameterized type to be written
307  /// by the caller.
308  /// @param first Contains the first item to write to the buffer.
309  ///
310  /// @param last Contains the item one past the last item to write.
311  /// This item may point to an element that is not
312  /// valid to de-reference. Similar to C+++ Standard Library.
313  ///
314  /// Last must be greater than than the first time,
315  /// and they must be part of the same range of elements
316  /// otherwise the behavior is undefined.
317  ///
318  /// @param pos The offset from the beginning of the buffer to
319  /// write the input value.
320  ///
321  /// @return The number of bytes written to the buffer is returned.
322  /// It is possible for a successful case to return 0.
323  ///
324  template <typename InputIt>
325  size_t set_range(InputIt first, InputIt last, size_t pos)
326  {
327  if (empty())
328  {
329  return 0;
330  }
331 
332  // Return if first and last are the same.
333  if (first == last)
334  {
335  return 0;
336  }
337 
338  // Read from the user supplied offset as well as the base offset
339  // configured for this Packet Buffer.
340  size_t total_offset = static_cast<size_t>(offset()) + pos;
341  size_t range_size = std::distance(first, last);
342 
343  // Verify the data can be safely written within the bounds of the buffer.
344  size_t bytes_written = 0;
345  size_t total_size = size();
346  if ( (total_offset >= 0)
347  && (total_offset + range_size) <= total_size)
348  {
349  bytes_written =
350  storage_type::write ( raw_data(),
351  first,
352  range_size,
353  total_offset)
354  ? range_size
355  : 0;
356  }
357 
358  return bytes_written;
359  }
360 
361 private:
362  // Private Member Data *******************************************************
363  pointer m_pData; ///< A pointer to the static memory
364  /// buffer supplied by the user.
365  size_t m_size; ///< The size if the buffer.
366  std::ptrdiff_t m_offset; ///< The number of bytes from the
367  /// beginning of the buffer that
368  /// all data reads should occur from.
369 
370  // **************************************************************************
371  /// Provides access to the packed memory buffer.
372  ///
373  /// @return A pointer to the buffer that contains the packed memory.
374  /// 0 is returned if there is no memory associated with the buffer.
375  ///
376  pointer raw_data()
377  {
378  return m_pData;
379  }
380 
381  // Let all message buffer objects be friends for data transfer.
382  template< typename T>
383  friend
384  class MsgBuffer;
385 };
386 
387 } // namespace Hg
388 
389 
390 #endif