1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_IMPL_VISIT_HPP
10  
#ifndef BOOST_JSON_IMPL_VISIT_HPP
11  
#define BOOST_JSON_IMPL_VISIT_HPP
11  
#define BOOST_JSON_IMPL_VISIT_HPP
12  

12  

13  
namespace boost {
13  
namespace boost {
14  
namespace json {
14  
namespace json {
15  

15  

16  
namespace detail {
16  
namespace detail {
17  

17  

18  
extern
18  
extern
19  
BOOST_JSON_DECL
19  
BOOST_JSON_DECL
20  
std::nullptr_t stable_np;
20  
std::nullptr_t stable_np;
21  

21  

22  
} // namespace detail
22  
} // namespace detail
23  

23  

24  
template<class Visitor>
24  
template<class Visitor>
25  
auto
25  
auto
26  
visit(
26  
visit(
27  
    Visitor&& v,
27  
    Visitor&& v,
28  
    value& jv) -> decltype(
28  
    value& jv) -> decltype(
29  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&>() ) )
29  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&>() ) )
30  
{
30  
{
31  
    switch(jv.kind())
31  
    switch(jv.kind())
32  
    {
32  
    {
33  
    default: // unreachable()?
33  
    default: // unreachable()?
34  
    case kind::string:  return static_cast<Visitor&&>(v)( jv.get_string() );
34  
    case kind::string:  return static_cast<Visitor&&>(v)( jv.get_string() );
35  
    case kind::array:   return static_cast<Visitor&&>(v)( jv.get_array() );
35  
    case kind::array:   return static_cast<Visitor&&>(v)( jv.get_array() );
36  
    case kind::object:  return static_cast<Visitor&&>(v)( jv.get_object() );
36  
    case kind::object:  return static_cast<Visitor&&>(v)( jv.get_object() );
37  
    case kind::bool_:   return static_cast<Visitor&&>(v)( jv.get_bool() );
37  
    case kind::bool_:   return static_cast<Visitor&&>(v)( jv.get_bool() );
38  
    case kind::int64:   return static_cast<Visitor&&>(v)( jv.get_int64() );
38  
    case kind::int64:   return static_cast<Visitor&&>(v)( jv.get_int64() );
39  
    case kind::uint64:  return static_cast<Visitor&&>(v)( jv.get_uint64() );
39  
    case kind::uint64:  return static_cast<Visitor&&>(v)( jv.get_uint64() );
40  
    case kind::double_: return static_cast<Visitor&&>(v)( jv.get_double() );
40  
    case kind::double_: return static_cast<Visitor&&>(v)( jv.get_double() );
41  
    case kind::null:    return static_cast<Visitor&&>(v)( detail::stable_np ) ;
41  
    case kind::null:    return static_cast<Visitor&&>(v)( detail::stable_np ) ;
42  
    }
42  
    }
43  
}
43  
}
44  

44  

45  
template<class Visitor>
45  
template<class Visitor>
46  
auto
46  
auto
47  
visit(
47  
visit(
48  
    Visitor&& v,
48  
    Visitor&& v,
49  
    value const& jv) -> decltype(
49  
    value const& jv) -> decltype(
50  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) )
50  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) )
51  
{
51  
{
52  
    detail::scalar const& sc = detail::access::get_scalar(jv);
52  
    detail::scalar const& sc = detail::access::get_scalar(jv);
53  
    switch(jv.kind())
53  
    switch(jv.kind())
54  
    {
54  
    {
55  
    default: // unreachable()?
55  
    default: // unreachable()?
56  
    case kind::string:  return static_cast<Visitor&&>(v)( jv.get_string() );
56  
    case kind::string:  return static_cast<Visitor&&>(v)( jv.get_string() );
57  
    case kind::array:   return static_cast<Visitor&&>(v)( jv.get_array() );
57  
    case kind::array:   return static_cast<Visitor&&>(v)( jv.get_array() );
58  
    case kind::object:  return static_cast<Visitor&&>(v)( jv.get_object() );
58  
    case kind::object:  return static_cast<Visitor&&>(v)( jv.get_object() );
59  
    // local variables work around a bug in older clangs
59  
    // local variables work around a bug in older clangs
60  
    case kind::bool_: {
60  
    case kind::bool_: {
61  
        bool const& b = sc.b;
61  
        bool const& b = sc.b;
62  
        return static_cast<Visitor&&>(v)(b);
62  
        return static_cast<Visitor&&>(v)(b);
63  
    }
63  
    }
64  
    case kind::int64: {
64  
    case kind::int64: {
65  
        std::int64_t const& i = sc.i;
65  
        std::int64_t const& i = sc.i;
66  
        return static_cast<Visitor&&>(v)(i);
66  
        return static_cast<Visitor&&>(v)(i);
67  
    }
67  
    }
68  
    case kind::uint64: {
68  
    case kind::uint64: {
69  
        std::uint64_t const& u =  sc.u;
69  
        std::uint64_t const& u =  sc.u;
70  
        return static_cast<Visitor&&>(v)(u);
70  
        return static_cast<Visitor&&>(v)(u);
71  
    }
71  
    }
72  
    case kind::double_: {
72  
    case kind::double_: {
73  
        double const& d = sc.d;
73  
        double const& d = sc.d;
74  
        return static_cast<Visitor&&>(v)(d);
74  
        return static_cast<Visitor&&>(v)(d);
75  
    }
75  
    }
76  
    case kind::null: {
76  
    case kind::null: {
77  
        auto const& np = detail::stable_np;
77  
        auto const& np = detail::stable_np;
78  
        return static_cast<Visitor&&>(v)(np) ;
78  
        return static_cast<Visitor&&>(v)(np) ;
79  
    }
79  
    }
80  
    }
80  
    }
81  
}
81  
}
82  

82  

83  

83  

84  
template<class Visitor>
84  
template<class Visitor>
85  
auto
85  
auto
86  
visit(
86  
visit(
87  
    Visitor&& v,
87  
    Visitor&& v,
88  
    value&& jv) -> decltype(
88  
    value&& jv) -> decltype(
89  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) )
89  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) )
90  
{
90  
{
91  
    switch(jv.kind())
91  
    switch(jv.kind())
92  
    {
92  
    {
93  
    default: // unreachable()?
93  
    default: // unreachable()?
94  
    case kind::string:  return static_cast<Visitor&&>(v)(std::move( jv.get_string() ));
94  
    case kind::string:  return static_cast<Visitor&&>(v)(std::move( jv.get_string() ));
95  
    case kind::array:   return static_cast<Visitor&&>(v)(std::move( jv.get_array() ));
95  
    case kind::array:   return static_cast<Visitor&&>(v)(std::move( jv.get_array() ));
96  
    case kind::object:  return static_cast<Visitor&&>(v)(std::move( jv.get_object() ));
96  
    case kind::object:  return static_cast<Visitor&&>(v)(std::move( jv.get_object() ));
97  
    case kind::bool_:   return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).b ));
97  
    case kind::bool_:   return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).b ));
98  
    case kind::int64:   return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).i ));
98  
    case kind::int64:   return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).i ));
99  
    case kind::uint64:  return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).u ));
99  
    case kind::uint64:  return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).u ));
100  
    case kind::double_: return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).d ));
100  
    case kind::double_: return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).d ));
101  
    case kind::null:    return static_cast<Visitor&&>(v)(std::move( detail::stable_np )) ;
101  
    case kind::null:    return static_cast<Visitor&&>(v)(std::move( detail::stable_np )) ;
102  
    }
102  
    }
103  
}
103  
}
104  

104  

105  
} // namespace json
105  
} // namespace json
106  
} // namespace boost
106  
} // namespace boost
107  

107  

108  
#endif
108  
#endif