2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *******************************************************************************/
32 #include <yajl/yajl_parse.h>
34 #include "serializable.hh"
35 #include "deserializer.hh"
41 class deserializer::deserializer_impl
44 deserializer_impl(const std::string
& filePath
, bool comments
= false,
47 std::ifstream
* input
= new std::ifstream(filePath
.c_str());
48 init(*input
, true, comments
, check
);
51 deserializer_impl(std::istream
& input
, bool comments
= false,
54 init(input
, false, comments
, check
);
59 while (!parsed
.empty())
61 delete parsed
.front();
74 unsigned char* errorMsg
= yajl_get_error(hand
, 0, 0, 0);
75 deserializer::exception
problem((char*)errorMsg
);
76 yajl_free_error(hand
, errorMsg
);
81 static int parsedNull(void* ctx
)
83 ((deserializer_impl
*)ctx
)->parsed
.push(new null
);
87 static int parsedBoolean(void* ctx
, int value
)
89 ((deserializer_impl
*)ctx
)->parsed
.push(new wrapped_boolean(value
));
93 static int parsedInteger(void* ctx
, long value
)
95 ((deserializer_impl
*)ctx
)->parsed
.push(new wrapped_integer(value
));
99 static int parsedFloat(void* ctx
, double value
)
101 ((deserializer_impl
*)ctx
)->parsed
.push(new wrapped_real(value
));
105 static int parsedString(void* ctx
, const unsigned char* value
,
108 wrapped_string
* parsed
= new wrapped_string(std::string((char*)value
,
110 ((deserializer_impl
*)ctx
)->parsed
.push(parsed
);
114 static int parsedBeginMap(void* ctx
)
116 ((deserializer_impl
*)ctx
)->parsed
.push(new wrapped_dictionary
);
120 static int parsedMapKey(void* ctx
, const unsigned char* value
,
123 return parsedString(ctx
, value
, length
);
126 static int parsedEndMap(void* ctx
)
128 ((deserializer_impl
*)ctx
)->parsed
.push(0);
132 static int parsedBeginArray(void* ctx
)
134 ((deserializer_impl
*)ctx
)->parsed
.push(new wrapped_array
);
138 static int parsedEndArray(void* ctx
)
140 ((deserializer_impl
*)ctx
)->parsed
.push(0);
147 unsigned char buffer
[4096];
151 while (parsed
.empty() && in
->good())
153 in
->read((char*)buffer
, sizeof(buffer
));
154 unsigned readIn
= in
->gcount();
158 stat
= yajl_parse(hand
, buffer
, readIn
);
162 stat
= yajl_parse_complete(hand
);
165 if (stat
!= yajl_status_ok
&&
166 stat
!= yajl_status_insufficient_data
)
179 std::queue
<serializable
*> parsed
;
182 void init(std::istream
& input
, bool deleteIn
, bool comments
, bool check
)
184 const yajl_callbacks callbacks
=
186 deserializer_impl::parsedNull
,
187 deserializer_impl::parsedBoolean
,
188 deserializer_impl::parsedInteger
,
189 deserializer_impl::parsedFloat
,
191 deserializer_impl::parsedString
,
192 deserializer_impl::parsedBeginMap
,
193 deserializer_impl::parsedMapKey
,
194 deserializer_impl::parsedEndMap
,
195 deserializer_impl::parsedBeginArray
,
196 deserializer_impl::parsedEndArray
200 deleteWhenDone
= deleteIn
;
202 yajl_parser_config config
= {comments
, check
};
203 hand
= yajl_alloc(&callbacks
, &config
, NULL
, this);
208 deserializer::deserializer(const std::string
& filePath
, bool comments
,
211 impl(new deserializer::deserializer_impl(filePath
, comments
, check
)) {}
213 deserializer::deserializer(std::istream
& input
, bool comments
, bool check
) :
215 impl(new deserializer::deserializer_impl(input
, comments
, check
)) {}
218 serializable_ptr
deserializer::deserialize()
220 serializable
* ptr
= pullNext();
223 ptr
->deserialize(*this);
225 return serializable_ptr(ptr
);
229 serializable
* deserializer::pullNext()
232 if (!impl
->parsed
.empty())
234 serializable
* ptr
= impl
->parsed
.front();
240 void deserializer::pop()
249 /** vim: set ts=4 sw=4 tw=80: *************************************************/