Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
unpack_stream.h
Go to the documentation of this file.
1 /// @file detail/unpack_stream.h
2 ///
3 /// A specialization to unpack the bytes from an input stream.
4 ///
5 /// The MIT License(MIT)
6 /// @copyright 2014 Paul M Watt
7 // ****************************************************************************
8 #ifndef UNPACK_STREAM_H_INCLUDED
9 #define UNPACK_STREAM_H_INCLUDED
10 // Private Usage Include Guard ************************************************
11 // Only allow this header file to be included through unpack_message.h
12 #ifndef UNPACK_MESSAGE_H_INCLUDED
13 # error Do not include this file directly. Use <detail/unpack_message.h> instead
14 #endif
15 // Includes *******************************************************************
16 #include <sstream>
17 
18 
19 namespace Hg
20 {
21 
22 namespace detail
23 {
24 // Forward Declarations *******************************************************
25 // ****************************************************************************
26 
27 
28 
29 // ****************************************************************************
30 /// Reads the values of a message from an istream object.
31 ///
32 /// @param is The input stream that will provide the data
33 /// to populate the message.
34 /// @param msg The message to be serialized.
35 ///
36 template< typename T >
37 void unpack_stream_static(std::istream& is, T& msg)
38 {
39  const size_t k_len = Hg::SizeOf<typename T::format_type>::value;
40  byte_t buffer[k_len];
41  is.read(reinterpret_cast<char*>(buffer), k_len);
42 
43  msg.assign(buffer, k_len);
44 }
45 
46 // ****************************************************************************
47 /// Reads the values of a message into an istream object for a dynamic buffer.
48 ///
49 /// @param is The input stream that will provide the data
50 /// to populate the message.
51 /// @param msg The message to be serialized.
52 ///
53 template< typename T >
54 void unpack_stream_dynamic(std::istream& is, T& msg)
55 {
56  // TODO: IN order to do this properly, incremental processing must be done to properly read the dynamically sized field.
57  // This form will only work for formats that have one dynamic field and it is at the end of the message.
58  // Essentially, read in the body of the message, then read the data buffer at the end.
59  const size_t k_static_len = Hg::SizeOf<typename T::format_type>::value;
60  byte_t body[k_static_len];
61  is.read(reinterpret_cast<char*>(body), k_static_len);
62 
63  msg.assign(body, k_static_len);
64 
65  // Now read the dynamic data.
66  size_t len = msg.size();
67  std::vector<byte_t> data(len);
68  ::memcpy(&data[0], body, k_static_len);
69 
70  // Read in 1K chunks
71  const size_t k_one_kb = 1024;
72  size_t remains = len - k_static_len;
73  size_t offset = k_static_len;
74  while (remains != 0)
75  {
76  is.read(reinterpret_cast<char*>(&data[offset]), k_one_kb);
77 
78  remains = remains > k_one_kb
79  ? remains - k_one_kb
80  : 0;
81  offset += k_one_kb;
82  }
83 
84  msg.assign(&data[0], len);
85 }
86 
87 
88 } // namespace detail
89 
90 } // namespace Hg
91 
92 #endif