Skip to content

Commit e26022e

Browse files
committed
Added msgpack decode.
1 parent e8a4b53 commit e26022e

File tree

7 files changed

+392
-1
lines changed

7 files changed

+392
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The Art of C++ / JSON is a zero-dependency C++11 header-only library that provid
2020
* Experimental support for [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) (local URI fragments only).
2121
* Experimental support for [JSON Schema](http://json-schema.org/documentation.html) (draft v4).
2222
* Experimental support for [Universal Binary JSON (UBJSON)](http://ubjson.org) (encode only).
23-
* Experimental support for [Message Pack](http://msgpack.org) (encode only).
23+
* Experimental support for [Message Pack](http://msgpack.org) (no extensions).
2424

2525
* General
2626

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey
2+
// Please see LICENSE for license or visit https://github.com/taocpp/json/
3+
4+
#ifndef TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_FROM_STRING_HPP
5+
#define TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_FROM_STRING_HPP
6+
7+
#include "../../external/pegtl/parse.hpp"
8+
9+
#include "grammar.hpp"
10+
11+
namespace tao
12+
{
13+
namespace json
14+
{
15+
namespace events
16+
{
17+
namespace msgpack
18+
{
19+
template< typename Consumer >
20+
void from_string( const char* data, const std::size_t size, Consumer& consumer, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 )
21+
{
22+
json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::msgpack::from_string", byte, line, byte_in_line );
23+
json_pegtl::parse< msgpack::grammar >( in, consumer );
24+
}
25+
26+
template< typename Consumer >
27+
void from_string( const std::string& data, Consumer& consumer, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 )
28+
{
29+
msgpack::from_string( data.data(), data.size(), consumer, source.c_str(), byte, line, byte_in_line );
30+
}
31+
32+
} // namespace msgpack
33+
34+
} // namespace events
35+
36+
} // namespace json
37+
38+
} // namespace tao
39+
40+
#endif
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey
2+
// Please see LICENSE for license or visit https://github.com/taocpp/json/
3+
4+
#ifndef TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_GRAMMAR_HPP
5+
#define TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_GRAMMAR_HPP
6+
7+
#include <cstdint>
8+
9+
#include "../../byte.hpp"
10+
#include "../../internal/endian.hpp"
11+
12+
namespace tao
13+
{
14+
namespace json
15+
{
16+
namespace events
17+
{
18+
namespace msgpack
19+
{
20+
struct data
21+
{
22+
using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >;
23+
24+
template< json_pegtl::apply_mode A,
25+
json_pegtl::rewind_mode M,
26+
template< typename... > class Action,
27+
template< typename... > class Control,
28+
typename Input,
29+
typename Consumer >
30+
static bool match( Input& in, Consumer& consumer )
31+
{
32+
// This rule never returns false unless the input is empty.
33+
return ( !in.empty() ) && match_impl( in, consumer );
34+
}
35+
36+
template< typename Input, typename Consumer >
37+
static bool match_impl( Input& in, Consumer& consumer )
38+
{
39+
const auto b = in.peek_byte();
40+
if( b <= 0x7f ) {
41+
consumer.number( std::uint64_t( b ) );
42+
in.bump_in_this_line();
43+
return true;
44+
}
45+
else if( b >= 0xe0 ) {
46+
consumer.number( std::int64_t( std::int8_t( b ) ) );
47+
in.bump_in_this_line();
48+
return true;
49+
}
50+
else if( ( 0x80 <= b ) && ( b <= 0x8f ) ) {
51+
in.bump_in_this_line();
52+
return match_object( in, consumer, b - 0x80 );
53+
}
54+
else if( ( 0x90 <= b ) && ( b <= 0x9f ) ) {
55+
in.bump_in_this_line();
56+
return match_array( in, consumer, b - 0x90 );
57+
}
58+
else if( ( 0xa0 <= b ) && ( b <= 0xbf ) ) {
59+
in.bump_in_this_line();
60+
consumer.string( read_container< std::string >( in, b - 0xa0 ) );
61+
return true;
62+
}
63+
switch( b ) {
64+
case 0xc0:
65+
consumer.null();
66+
in.bump_in_this_line();
67+
return true;
68+
case 0xc1:
69+
throw json_pegtl::parse_error( "unused msgpack first byte 0xc1", in );
70+
case 0xc2:
71+
case 0xc3:
72+
consumer.boolean( b & 1 );
73+
in.bump_in_this_line();
74+
return true;
75+
case 0xc4:
76+
consumer.binary( read_container< std::vector< byte > >( in, read_number< std::size_t, std::uint8_t >( in ) ) );
77+
return true;
78+
case 0xc5:
79+
consumer.binary( read_container< std::vector< byte > >( in, read_number< std::size_t, std::uint16_t >( in ) ) );
80+
return true;
81+
case 0xc6:
82+
consumer.binary( read_container< std::vector< byte > >( in, read_number< std::size_t, std::uint32_t >( in ) ) );
83+
return true;
84+
case 0xc7:
85+
discard( in, read_number< std::size_t, std::uint8_t >( in ) + 1 );
86+
return true;
87+
case 0xc8:
88+
discard( in, read_number< std::size_t, std::uint16_t >( in ) + 1 );
89+
return true;
90+
case 0xc9:
91+
discard( in, read_number< std::size_t, std::uint32_t >( in ) + 1 );
92+
return true;
93+
case 0xca:
94+
consumer.number( read_number< double, float >( in ) );
95+
return true;
96+
case 0xcb:
97+
consumer.number( read_number< double, double >( in ) );
98+
return true;
99+
case 0xcc:
100+
consumer.number( read_number< std::uint64_t, std::uint8_t >( in ) );
101+
return true;
102+
case 0xcd:
103+
consumer.number( read_number< std::uint64_t, std::uint16_t >( in ) );
104+
return true;
105+
case 0xce:
106+
consumer.number( read_number< std::uint64_t, std::uint32_t >( in ) );
107+
return true;
108+
case 0xcf:
109+
consumer.number( read_number< std::uint64_t, std::uint64_t >( in ) );
110+
return true;
111+
case 0xd0:
112+
consumer.number( read_number< std::int64_t, std::int8_t >( in ) );
113+
return true;
114+
case 0xd1:
115+
consumer.number( read_number< std::int64_t, std::int16_t >( in ) );
116+
return true;
117+
case 0xd2:
118+
consumer.number( read_number< std::int64_t, std::int32_t >( in ) );
119+
return true;
120+
case 0xd3:
121+
consumer.number( read_number< std::int64_t, std::int64_t >( in ) );
122+
return true;
123+
case 0xd4:
124+
discard( in, 3 );
125+
return true;
126+
case 0xd5:
127+
discard( in, 4 );
128+
return true;
129+
case 0xd6:
130+
discard( in, 6 );
131+
return true;
132+
case 0xd7:
133+
discard( in, 10 );
134+
return true;
135+
case 0xd8:
136+
discard( in, 18 );
137+
return true;
138+
case 0xd9:
139+
consumer.string( read_container< std::string >( in, read_number< std::size_t, std::uint8_t >( in ) ) );
140+
return true;
141+
case 0xda:
142+
consumer.string( read_container< std::string >( in, read_number< std::size_t, std::uint16_t >( in ) ) );
143+
return true;
144+
case 0xdb:
145+
consumer.string( read_container< std::string >( in, read_number< std::size_t, std::uint32_t >( in ) ) );
146+
return true;
147+
case 0xdc:
148+
return match_array( in, consumer, read_number< std::size_t, std::uint16_t >( in ) );
149+
case 0xdd:
150+
return match_array( in, consumer, read_number< std::size_t, std::uint32_t >( in ) );
151+
case 0xde:
152+
return match_object( in, consumer, read_number< std::size_t, std::uint16_t >( in ) );
153+
case 0xdf:
154+
return match_object( in, consumer, read_number< std::size_t, std::uint32_t >( in ) );
155+
}
156+
assert( !"unreachable" );
157+
}
158+
159+
template< typename Input >
160+
static void discard( Input& in, const std::size_t count )
161+
{
162+
if( in.size( count ) < count ) {
163+
throw json_pegtl::parse_error( "unexpected end of input", in );
164+
}
165+
in.bump_in_this_line( count );
166+
}
167+
168+
template< typename Result, typename Number, typename Input >
169+
static std::uint64_t read_number( Input& in )
170+
{
171+
if( in.size( sizeof( Number ) ) > sizeof( Number ) ) {
172+
const Result result = json::internal::be_to_h< Number >( in.current() + 1 );
173+
in.bump_in_this_line( 1 + sizeof( Number ) );
174+
return result;
175+
}
176+
throw json_pegtl::parse_error( "unexpected end of msgpack input", in );
177+
}
178+
179+
template< typename Result, typename Input >
180+
static Result read_container( Input& in, const std::size_t size )
181+
{
182+
using value_t = typename Result::value_type;
183+
if( in.size( size ) < size ) {
184+
throw json_pegtl::parse_error( "unexpected end of input", in );
185+
}
186+
const value_t* pointer = reinterpret_cast< const value_t* >( in.current() );
187+
Result result( pointer, pointer + size );
188+
in.bump_in_this_line( size );
189+
return result;
190+
}
191+
192+
template< typename Input >
193+
static std::string read_key( Input& in )
194+
{
195+
if( in.empty() ) {
196+
throw json_pegtl::parse_error( "unexpected end of input", in );
197+
}
198+
switch( in.peek_byte() ) {
199+
case 0xd9:
200+
return read_container< std::string >( in, read_number< std::size_t, std::uint8_t >( in ) );
201+
case 0xda:
202+
return read_container< std::string >( in, read_number< std::size_t, std::uint16_t >( in ) );
203+
case 0xdb:
204+
return read_container< std::string >( in, read_number< std::size_t, std::uint32_t >( in ) );
205+
}
206+
throw json_pegtl::parse_error( "unexpected key type", in );
207+
}
208+
209+
template< typename Input, typename Consumer >
210+
static bool match_array( Input& in, Consumer& consumer, const std::size_t size )
211+
{
212+
consumer.begin_array( size );
213+
for( std::size_t i = 0; i < size; ++i ) {
214+
if( in.empty() ) {
215+
throw json_pegtl::parse_error( "unexpected end of input", in );
216+
}
217+
match_impl( in, consumer );
218+
consumer.element();
219+
}
220+
consumer.end_array( size );
221+
return true;
222+
}
223+
224+
template< typename Input, typename Consumer >
225+
static bool match_object( Input& in, Consumer& consumer, const std::size_t size )
226+
{
227+
consumer.begin_object( size );
228+
for( std::size_t i = 0; i < size; ++i ) {
229+
consumer.key( read_key( in ) );
230+
if( in.empty() ) {
231+
throw json_pegtl::parse_error( "unexpected end of input", in );
232+
}
233+
match_impl( in, consumer );
234+
consumer.member();
235+
}
236+
consumer.end_object( size );
237+
return true;
238+
}
239+
};
240+
241+
struct grammar : json_pegtl::must< data, json_pegtl::eof >
242+
{
243+
};
244+
245+
} // namespace msgpack
246+
247+
} // namespace events
248+
249+
} // namespace json
250+
251+
} // namespace tao
252+
253+
#endif

include/tao/json/internal/endian_gcc.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,21 @@ namespace tao
3434
{
3535
return n;
3636
}
37+
38+
static std::int8_t convert( const std::int8_t n ) noexcept
39+
{
40+
return n;
41+
}
3742
};
3843

3944
template<>
4045
struct to_and_from_le< 2 >
4146
{
47+
static std::int16_t convert( const std::int16_t n ) noexcept
48+
{
49+
return __builtin_bswap16( n );
50+
}
51+
4252
static std::uint16_t convert( const std::uint16_t n ) noexcept
4353
{
4454
return __builtin_bswap16( n );
@@ -57,6 +67,11 @@ namespace tao
5767
return n;
5868
}
5969

70+
static std::int32_t convert( const std::int32_t n ) noexcept
71+
{
72+
return __builtin_bswap32( n );
73+
}
74+
6075
static std::uint32_t convert( const std::uint32_t n ) noexcept
6176
{
6277
return __builtin_bswap32( n );
@@ -75,6 +90,11 @@ namespace tao
7590
return n;
7691
}
7792

93+
static std::int64_t convert( const std::int64_t n ) noexcept
94+
{
95+
return __builtin_bswap64( n );
96+
}
97+
7898
static std::uint64_t convert( const std::uint64_t n ) noexcept
7999
{
80100
return __builtin_bswap64( n );
@@ -99,6 +119,11 @@ namespace tao
99119
template<>
100120
struct to_and_from_be< 1 >
101121
{
122+
static std::int8_t convert( const std::int8_t n ) noexcept
123+
{
124+
return n;
125+
}
126+
102127
static std::uint8_t convert( const std::uint8_t n ) noexcept
103128
{
104129
return n;
@@ -108,6 +133,11 @@ namespace tao
108133
template<>
109134
struct to_and_from_be< 2 >
110135
{
136+
static std::int16_t convert( const std::int16_t n ) noexcept
137+
{
138+
return __builtin_bswap16( n );
139+
}
140+
111141
static std::uint16_t convert( const std::uint16_t n ) noexcept
112142
{
113143
return __builtin_bswap16( n );
@@ -126,6 +156,11 @@ namespace tao
126156
return n;
127157
}
128158

159+
static std::int32_t convert( const std::int32_t n ) noexcept
160+
{
161+
return __builtin_bswap32( n );
162+
}
163+
129164
static std::uint32_t convert( const std::uint32_t n ) noexcept
130165
{
131166
return __builtin_bswap32( n );
@@ -148,6 +183,11 @@ namespace tao
148183
{
149184
return __builtin_bswap64( n );
150185
}
186+
187+
static std::int64_t convert( const std::int64_t n ) noexcept
188+
{
189+
return __builtin_bswap64( n );
190+
}
151191
};
152192

153193
#else

0 commit comments

Comments
 (0)