-
Notifications
You must be signed in to change notification settings - Fork 85
/
token_parser.hpp
105 lines (88 loc) · 1.99 KB
/
token_parser.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#pragma once
#include <kapok/Kapok.hpp>
class token_parser
{
public:
void parse(const char* s, std::size_t length)
{
v_.clear();
dr_.Parse(s, length);
Document& doc = dr_.GetDocument();
auto it = doc.MemberBegin();
v_.push_back(it->name.GetString());
StringBuffer buf;
rapidjson::Writer<StringBuffer> wr(buf);
if (it->value.IsArray())
{
for (size_t i = 0; i < it->value.Size(); i++)
{
put_str(it->value[i], wr, buf);
}
}
else
{
put_str(it->value, wr, buf);
}
}
template<typename RequestedType>
typename std::decay<RequestedType>::type get()
{
if (v_.empty())
throw std::invalid_argument("unexpected end of input");
try
{
typedef typename std::decay<RequestedType>::type result_type;
auto it = v_.begin();
result_type result = lexical_cast<typename std::decay<result_type>::type>(*it);
v_.erase(it);
return result;
}
catch (std::exception& e)
{
v_.clear();
throw std::invalid_argument(std::string("invalid argument: ") + e.what());
}
}
bool empty() const { return v_.empty(); }
std::size_t param_size()
{
return v_.size();
}
token_parser() = default;
private:
token_parser(const token_parser&) = delete;
token_parser(token_parser&&) = delete;
template<typename T>
typename std::enable_if<is_basic_type<T>::value, T>::type lexical_cast(const std::string& str)
{
return boost::lexical_cast<T>(str);
}
template<typename T>
typename std::enable_if<!is_basic_type<T>::value, T>::type lexical_cast(const std::string& str)
{
dr_.Parse(str);
T t;
dr_.Deserialize<T>(t, false);
return t;
}
void put_str(Value& val, rapidjson::Writer<StringBuffer>& wr, StringBuffer& buf)
{
if (val.IsString())
{
v_.push_back(val.GetString());
return;
}
val.Accept(wr);
const char* js = buf.GetString();
const int len = strlen(js);
if (len == 0)
return;
if (len == 2 && js[0] == '"')
return;
v_.push_back(js);
wr.Reset(buf);
buf.Clear();
}
DeSerializer dr_;
std::vector<std::string> v_;
};