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 -
namespace detail {
 
16 -

 
17 -
extern
 
18 -
BOOST_JSON_DECL
 
19 -
std::nullptr_t stable_np;
 
20 -

 
21 -
} // namespace detail
 
22  

15  

23  

16  

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

40  

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

64  

83  

65  

84  
template<class Visitor>
66  
template<class Visitor>
85  
auto
67  
auto
86  
visit(
68  
visit(
87  
    Visitor&& v,
69  
    Visitor&& v,
88  
    value&& jv) -> decltype(
70  
    value&& jv) -> decltype(
89  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) )
71  
        static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) )
90  
{
72  
{
91  
    switch(jv.kind())
73  
    switch(jv.kind())
92  
    {
74  
    {
93  
    default: // unreachable()?
75  
    default: // unreachable()?
94 -
    case kind::string:  return static_cast<Visitor&&>(v)(std::move( jv.get_string() ));
76 +
    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() ));
77 +
    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() ));
78 +
    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 ));
79 +
    case kind::bool_:   return static_cast<Visitor&&>(v)( std::move( jv.get_bool() ) );
98 -
    case kind::int64:   return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).i ));
80 +
    case kind::int64:   return static_cast<Visitor&&>(v)( std::move( jv.get_int64() ) );
99 -
    case kind::uint64:  return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).u ));
81 +
    case kind::uint64:  return static_cast<Visitor&&>(v)( std::move( jv.get_uint64() ) );
100 -
    case kind::double_: return static_cast<Visitor&&>(v)(std::move( detail::access::get_scalar(jv).d ));
82 +
    case kind::double_: return static_cast<Visitor&&>(v)( std::move( jv.get_double() ) );
101 -
    case kind::null:    return static_cast<Visitor&&>(v)(std::move( detail::stable_np )) ;
83 +
    case kind::null:    return static_cast<Visitor&&>(v)( std::nullptr_t() ) ;
102  
    }
84  
    }
103  
}
85  
}
104  

86  

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

89  

108  
#endif
90  
#endif