nds2-client - ClientAdministrator  0.16.8
 All Functions Typedefs Enumerations Enumerator Groups Pages
basic_io.hh
1 //
2 // Created by jonathan.hanks on 5/4/18.
3 //
4 
5 #ifndef NDS2_CLIENT_BASIC_IO_HH
6 #define NDS2_CLIENT_BASIC_IO_HH
7 
8 #include <cstdint>
9 
10 #include "common/status_codes.hh"
11 
12 namespace nds_impl
13 {
14  namespace nds1
15  {
16  namespace common
17  {
18 
25  template < typename BufferedReader >
26  class Basic_IO
27  {
28  public:
29  Basic_IO( BufferedReader& r ) : r_( r )
30  {
31  }
32 
36  nds_impl::common::status_code
37  read_status_code( )
38  {
39  nds_impl::common::status_code result;
40  r_.read_exactly( result.data( ),
41  result.data( ) + result.size( ) );
42  return result;
43  }
44 
50  std::uint32_t
51  read_uint32_hex( )
52  {
53  uint32_t val = 0;
54  std::array< char, 8 > buf;
55  r_.read_exactly( buf.data( ), buf.data( ) + buf.size( ) );
56  for ( const auto byte : buf )
57  {
58  val = ( val << 4 ) | from_hex_nibble( byte );
59  }
60  return val;
61  }
62 
68  float
69  read_float32_hex( )
70  {
71  uint32_t tmp = read_uint32_hex( );
72  return *reinterpret_cast< float* >( &tmp );
73  }
74 
75  private:
76  BufferedReader& r_;
77 
78  int
79  from_hex_nibble( int nibble )
80  {
81  if ( nibble >= '0' && nibble <= '9' )
82  {
83  return nibble - '0';
84  }
85  if ( nibble >= 'a' && nibble <= 'f' )
86  {
87  return ( nibble - 'a' ) + 10;
88  }
89  if ( nibble >= 'A' && nibble <= 'F' )
90  {
91  return ( nibble - 'A' ) + 10;
92  }
93  throw std::invalid_argument(
94  "Unknown input found while converting a hex value" );
95  }
96  };
97  }
98  }
99 }
100 
102 // Tests only after this point.
104 
105 #ifdef _NDS_IMPL_ENABLE_CATCH_TESTS_
106 
107 #include "common/status_codes.hh"
108 #include "socket/buffered_reader.hh"
109 #include "tests/dummy_socket.hh"
110 #include "catch.hpp"
111 
112 TEST_CASE( "You should be able to create a basic_io object",
113  "[nds2,basic_io,create]" )
114 {
115  using namespace nds_testing;
116 
117  typedef nds_impl::Socket::BufferedReader< DummySocket > sock_type;
118 
119  DummySocket s( "" );
120  sock_type buf_s( s );
121  nds_impl::nds1::common::Basic_IO< sock_type > b( buf_s );
122 }
123 
124 TEST_CASE( "You should be able to read a nds1 status code", "[nds1]" )
125 {
126  using namespace nds_testing;
127  using namespace nds_impl::common;
128 
129  typedef nds_impl::Socket::BufferedReader< DummySocket > sock_type;
130 
131  DummySocket s1( "0000000d" );
132  sock_type buf_s1( s1 );
133  nds_impl::nds1::common::Basic_IO< sock_type > b( buf_s1 );
134 
135  REQUIRE( b.read_status_code( ) == STATUS_DAQD_OK );
136  REQUIRE( b.read_status_code( ) == STATUS_DAQD_NOT_FOUND );
137 }
138 
139 TEST_CASE( "You should be able to read a 32bit ascii/hex value",
140  "[nds1,basic_io,hex]" )
141 {
142  using namespace nds_testing;
143  typedef nds_impl::Socket::BufferedReader< DummySocket > sock_type;
144 
145  DummySocket s1( "0000034000000000f7F8f9aB" );
146  sock_type buf_s1( s1 );
147  nds_impl::nds1::common::Basic_IO< sock_type > b( buf_s1 );
148 
149  REQUIRE( b.read_uint32_hex( ) == 0x340 );
150  REQUIRE( b.read_uint32_hex( ) == 0x0 );
151  REQUIRE( b.read_uint32_hex( ) == 0xf7f8f9ab );
152 }
153 
154 TEST_CASE( "Exceptions are thrown when reading a bad 32bit ascii/hex value",
155  "[nds1,basic_io,hex]" )
156 {
157  using namespace nds_testing;
158  typedef nds_impl::Socket::BufferedReader< DummySocket > sock_type;
159 
160  // two tests, one with an invalid char '&'
161  // another with a short input
162  DummySocket s1( "0000&3400000" );
163  sock_type buf_s1( s1 );
164  nds_impl::nds1::common::Basic_IO< sock_type > b( buf_s1 );
165 
166  REQUIRE_THROWS_AS( b.read_uint32_hex( ), std::invalid_argument );
167  REQUIRE_THROWS( b.read_uint32_hex( ) );
168 }
169 
170 TEST_CASE( "You should be able to read a 32bit float ascii/hex value",
171  "[nds1,basic_io,hex]" )
172 {
173  using namespace nds_testing;
174  typedef nds_impl::Socket::BufferedReader< DummySocket > sock_type;
175 
176  DummySocket s1( "3f800000" );
177  sock_type buf_s1( s1 );
178  nds_impl::nds1::common::Basic_IO< sock_type > b( buf_s1 );
179 
180  REQUIRE( b.read_float32_hex( ) == 1.0f );
181 }
182 
183 TEST_CASE(
184  "Exceptions are thrown when reading a bad 32bit float ascii/hex value",
185  "[nds1,basic_io,hex]" )
186 {
187  using namespace nds_testing;
188  typedef nds_impl::Socket::BufferedReader< DummySocket > sock_type;
189 
190  // two tests, one with an invalid char '&'
191  // another with a short input
192  DummySocket s1( "3f8&0000000" );
193  sock_type buf_s1( s1 );
194  nds_impl::nds1::common::Basic_IO< sock_type > b( buf_s1 );
195 
196  REQUIRE_THROWS_AS( b.read_float32_hex( ), std::invalid_argument );
197  REQUIRE_THROWS( b.read_float32_hex( ) );
198 }
199 
200 #endif // _NDS_IMPL_ENABLE_CATCH_TESTS_
201 
202 #endif // NDS2_CLIENT_BASIC_IO_HH