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_VALUE_REF_IPP
10  
#ifndef BOOST_JSON_IMPL_VALUE_REF_IPP
11  
#define BOOST_JSON_IMPL_VALUE_REF_IPP
11  
#define BOOST_JSON_IMPL_VALUE_REF_IPP
12  

12  

13  
#include <boost/json/value_ref.hpp>
13  
#include <boost/json/value_ref.hpp>
14  
#include <boost/json/array.hpp>
14  
#include <boost/json/array.hpp>
15  
#include <boost/json/value.hpp>
15  
#include <boost/json/value.hpp>
16  

16  

17  
namespace boost {
17  
namespace boost {
18  
namespace json {
18  
namespace json {
19  

19  

20  
value_ref::
20  
value_ref::
21  
operator
21  
operator
22  
value() const
22  
value() const
23  
{
23  
{
24  
    return make_value({});
24  
    return make_value({});
25  
}
25  
}
26  

26  

27  
value
27  
value
28  
value_ref::
28  
value_ref::
29  
from_init_list(
29  
from_init_list(
30  
    void const* p,
30  
    void const* p,
31  
    storage_ptr sp)
31  
    storage_ptr sp)
32  
{
32  
{
33  
    return make_value(
33  
    return make_value(
34  
        *reinterpret_cast<
34  
        *reinterpret_cast<
35  
            init_list const*>(p),
35  
            init_list const*>(p),
36  
        std::move(sp));
36  
        std::move(sp));
37  
}
37  
}
38  

38  

39  
bool
39  
bool
40  
value_ref::
40  
value_ref::
41  
is_key_value_pair() const noexcept
41  
is_key_value_pair() const noexcept
42  
{
42  
{
43  
    if(what_ != what::ini)
43  
    if(what_ != what::ini)
44  
        return false;
44  
        return false;
45  
    if(arg_.init_list_.size() != 2)
45  
    if(arg_.init_list_.size() != 2)
46  
        return false;
46  
        return false;
47  
    auto const& e =
47  
    auto const& e =
48  
        *arg_.init_list_.begin();
48  
        *arg_.init_list_.begin();
49  
    if( e.what_ != what::str &&
49  
    if( e.what_ != what::str &&
50  
        e.what_ != what::strfunc)
50  
        e.what_ != what::strfunc)
51  
        return false;
51  
        return false;
52  
    return true;
52  
    return true;
53  
}
53  
}
54  

54  

55  
bool
55  
bool
56  
value_ref::
56  
value_ref::
57  
maybe_object(
57  
maybe_object(
58  
    std::initializer_list<
58  
    std::initializer_list<
59  
        value_ref> init) noexcept
59  
        value_ref> init) noexcept
60  
{
60  
{
61  
    for(auto const& e : init)
61  
    for(auto const& e : init)
62  
        if(! e.is_key_value_pair())
62  
        if(! e.is_key_value_pair())
63  
            return false;
63  
            return false;
64  
    return true;
64  
    return true;
65  
}
65  
}
66  

66  

67  
string_view
67  
string_view
68  
value_ref::
68  
value_ref::
69  
get_string() const noexcept
69  
get_string() const noexcept
70  
{
70  
{
71  
    BOOST_ASSERT(
71  
    BOOST_ASSERT(
72  
        what_ == what::str ||
72  
        what_ == what::str ||
73  
        what_ == what::strfunc);
73  
        what_ == what::strfunc);
74  
    if (what_ == what::strfunc)
74  
    if (what_ == what::strfunc)
75  
        return *static_cast<const string*>(f_.p);
75  
        return *static_cast<const string*>(f_.p);
76  
    return arg_.str_;
76  
    return arg_.str_;
77  
}
77  
}
78  

78  

79  
value
79  
value
80  
value_ref::
80  
value_ref::
81  
make_value(
81  
make_value(
82  
    storage_ptr sp) const
82  
    storage_ptr sp) const
83  
{
83  
{
84  
    switch(what_)
84  
    switch(what_)
85  
    {
85  
    {
86  
    default:
86  
    default:
87  
    case what::str:
87  
    case what::str:
88  
        return string(
88  
        return string(
89  
            arg_.str_,
89  
            arg_.str_,
90  
            std::move(sp));
90  
            std::move(sp));
91  

91  

92  
    case what::ini:
92  
    case what::ini:
93  
        return make_value(
93  
        return make_value(
94  
            arg_.init_list_,
94  
            arg_.init_list_,
95  
            std::move(sp));
95  
            std::move(sp));
96  

96  

97  
    case what::func:
97  
    case what::func:
98  
        return f_.f(f_.p,
98  
        return f_.f(f_.p,
99  
            std::move(sp));
99  
            std::move(sp));
100  
    
100  
    
101  
    case what::strfunc:
101  
    case what::strfunc:
102  
        return f_.f(f_.p,
102  
        return f_.f(f_.p,
103  
            std::move(sp));
103  
            std::move(sp));
104  
    
104  
    
105  
    case what::cfunc:
105  
    case what::cfunc:
106  
        return cf_.f(cf_.p,
106  
        return cf_.f(cf_.p,
107  
            std::move(sp));
107  
            std::move(sp));
108  
    }
108  
    }
109  
}
109  
}
110  

110  

111  
value
111  
value
112  
value_ref::
112  
value_ref::
113  
make_value(
113  
make_value(
114  
    std::initializer_list<
114  
    std::initializer_list<
115  
        value_ref> init,
115  
        value_ref> init,
116  
    storage_ptr sp)
116  
    storage_ptr sp)
117  
{
117  
{
118  
    if(maybe_object(init))
118  
    if(maybe_object(init))
119  
        return make_object(
119  
        return make_object(
120  
            init, std::move(sp));
120  
            init, std::move(sp));
121  
    return make_array(
121  
    return make_array(
122  
        init, std::move(sp));
122  
        init, std::move(sp));
123  
}
123  
}
124  

124  

125  
object
125  
object
126  
value_ref::
126  
value_ref::
127  
make_object(
127  
make_object(
128  
    std::initializer_list<value_ref> init,
128  
    std::initializer_list<value_ref> init,
129  
    storage_ptr sp)
129  
    storage_ptr sp)
130  
{
130  
{
131  
    object obj(std::move(sp));
131  
    object obj(std::move(sp));
132  
    obj.reserve(init.size());
132  
    obj.reserve(init.size());
133  
    for(auto const& e : init)
133  
    for(auto const& e : init)
134  
        obj.emplace(
134  
        obj.emplace(
135  
            e.arg_.init_list_.begin()[0].get_string(),
135  
            e.arg_.init_list_.begin()[0].get_string(),
136  
            e.arg_.init_list_.begin()[1].make_value(
136  
            e.arg_.init_list_.begin()[1].make_value(
137  
                obj.storage()));
137  
                obj.storage()));
138  
    return obj;
138  
    return obj;
139  
}
139  
}
140  

140  

141  
array
141  
array
142  
value_ref::
142  
value_ref::
143  
make_array(
143  
make_array(
144  
    std::initializer_list<
144  
    std::initializer_list<
145  
        value_ref> init,
145  
        value_ref> init,
146  
    storage_ptr sp)
146  
    storage_ptr sp)
147  
{
147  
{
148  
    array arr(std::move(sp));
148  
    array arr(std::move(sp));
149  
    arr.reserve(init.size());
149  
    arr.reserve(init.size());
150  
    for(auto const& e : init)
150  
    for(auto const& e : init)
151  
        arr.emplace_back(
151  
        arr.emplace_back(
152  
            e.make_value(
152  
            e.make_value(
153  
                arr.storage()));
153  
                arr.storage()));
154  
    return arr;
154  
    return arr;
155  
}
155  
}
156  

156  

157  
void
157  
void
158  
value_ref::
158  
value_ref::
159  
write_array(
159  
write_array(
160  
    value* dest,
160  
    value* dest,
161  
    std::initializer_list<
161  
    std::initializer_list<
162  
        value_ref> init,
162  
        value_ref> init,
163  
    storage_ptr const& sp)
163  
    storage_ptr const& sp)
164  
{
164  
{
165  
    struct undo
165  
    struct undo
166  
    {
166  
    {
167  
        value* const base;
167  
        value* const base;
168  
        value* pos;
168  
        value* pos;
169  
        ~undo()
169  
        ~undo()
170  
        {
170  
        {
171  
            if(pos)
171  
            if(pos)
172  
                while(pos > base)
172  
                while(pos > base)
173  
                    (--pos)->~value();
173  
                    (--pos)->~value();
174  
        }
174  
        }
175  
    };
175  
    };
176  
    undo u{dest, dest};
176  
    undo u{dest, dest};
177  
    for(auto const& e : init)
177  
    for(auto const& e : init)
178  
    {
178  
    {
179  
        ::new(u.pos) value(
179  
        ::new(u.pos) value(
180  
            e.make_value(sp));
180  
            e.make_value(sp));
181  
        ++u.pos;
181  
        ++u.pos;
182  
    }
182  
    }
183  
    u.pos = nullptr;
183  
    u.pos = nullptr;
184  
}
184  
}
185  

185  

186  
} // namespace json
186  
} // namespace json
187  
} // namespace boost
187  
} // namespace boost
188  

188  

189  
#endif
189  
#endif