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 *******************************************************************************/
31 #include <yajl/yajl_gen.h>
33 #include "stringtools.hh"
34 #include "serializer.hh"
40 class serializer::serializer_impl
43 serializer_impl(const std::string
& filePath
, const std::string
& indent
= "")
45 std::ofstream
* output
= new std::ofstream(filePath
.c_str());
46 init(*output
, true, indent
);
49 serializer_impl(std::ostream
& output
, const std::string
& indent
= "")
51 init(output
, false, indent
);
63 static void throwError(yajl_gen_status err
)
67 case yajl_gen_generation_complete
:
68 throw serializer::exception("the archive has already terminated");
69 case yajl_gen_keys_must_be_strings
:
70 throw serializer::exception("map keys must be strings");
71 case yajl_max_depth_exceeded
:
72 throw serializer::exception("maximum archive depth exceeded");
73 case yajl_gen_in_error_state
:
74 throw serializer::exception("serializer already in error state");
75 case yajl_gen_status_ok
:
76 ; // There is no error here. Move along...
86 void init(std::ostream
& output
, bool deleteOut
, const std::string
& indent
)
88 yajl_gen_config config
;
91 deleteWhenDone
= deleteOut
;
95 config
.beautify
= true;
96 config
.indentString
= 0;
97 // FIXME: a yajl bug prevents using heap-allocated strings
98 //config.indentString = indent.c_str();
102 config
.beautify
= false;
104 gen
= yajl_gen_alloc(&config
, 0);
109 serializer::serializer(const std::string
& filePath
, const std::string
& indent
) :
111 impl(new serializer::serializer_impl(filePath
, indent
)) {}
113 serializer::serializer(std::ostream
& output
, const std::string
& indent
) :
115 impl(new serializer::serializer_impl(output
, indent
)) {}
117 serializer::~serializer()
123 void serializer::push(long value
)
125 yajl_gen_status stat
= yajl_gen_integer(impl
->gen
, value
);
126 if (stat
!= yajl_gen_status_ok
)
127 serializer::serializer_impl::throwError(stat
);
130 void serializer::push(double value
)
132 yajl_gen_status stat
= yajl_gen_double(impl
->gen
, value
);
133 if (stat
!= yajl_gen_status_ok
)
134 serializer::serializer_impl::throwError(stat
);
137 void serializer::push(bool value
)
139 yajl_gen_status stat
= yajl_gen_bool(impl
->gen
, value
);
140 if (stat
!= yajl_gen_status_ok
)
141 serializer::serializer_impl::throwError(stat
);
144 void serializer::push(const std::string
& value
)
146 yajl_gen_status stat
= yajl_gen_string(impl
->gen
,
147 (const unsigned char*)value
.c_str(), value
.length());
148 if (stat
!= yajl_gen_status_ok
)
149 serializer::serializer_impl::throwError(stat
);
152 void serializer::push(const std::wstring
& value
)
154 push(wideToMulti(value
));
157 void serializer::pushNull()
159 yajl_gen_status stat
= yajl_gen_null(impl
->gen
);
160 if (stat
!= yajl_gen_status_ok
)
161 serializer::serializer_impl::throwError(stat
);
165 void serializer::pushMapHead()
167 yajl_gen_status stat
= yajl_gen_map_open(impl
->gen
);
168 if (stat
!= yajl_gen_status_ok
)
169 serializer::serializer_impl::throwError(stat
);
172 void serializer::pushMapTail()
174 yajl_gen_status stat
= yajl_gen_map_close(impl
->gen
);
175 if (stat
!= yajl_gen_status_ok
)
176 serializer::serializer_impl::throwError(stat
);
179 void serializer::pushArrayHead()
181 yajl_gen_status stat
= yajl_gen_array_open(impl
->gen
);
182 if (stat
!= yajl_gen_status_ok
)
183 serializer::serializer_impl::throwError(stat
);
186 void serializer::pushArrayTail()
188 yajl_gen_status stat
= yajl_gen_array_close(impl
->gen
);
189 if (stat
!= yajl_gen_status_ok
)
190 serializer::serializer_impl::throwError(stat
);
194 void serializer::flush()
196 const unsigned char* buffer
;
199 yajl_gen_get_buf(impl
->gen
, &buffer
, &length
);
200 impl
->out
->write((const char*)buffer
, length
);
201 yajl_gen_clear(impl
->gen
);
207 /** vim: set ts=4 sw=4 tw=80: *************************************************/