]> Dogcows Code - chaz/yoink/blob - src/serializer.cc
7b7596d7b3eb99c8054df4a62250fac5eb66746f
[chaz/yoink] / src / serializer.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
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.
15
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.
26
27 *******************************************************************************/
28
29 #include <fstream>
30
31 #include <yajl/yajl_gen.h>
32
33 #include "stringtools.hh"
34 #include "serializer.hh"
35
36
37 namespace dc {
38
39
40 class serializer::serializer_impl
41 {
42 public:
43 serializer_impl(const std::string& filePath, const std::string& indent = "")
44 {
45 std::ofstream* output = new std::ofstream(filePath.c_str());
46 init(*output, true, indent);
47 }
48
49 serializer_impl(std::ostream& output, const std::string& indent = "")
50 {
51 init(output, false, indent);
52 }
53
54 ~serializer_impl()
55 {
56 if (deleteWhenDone)
57 {
58 delete out;
59 }
60 yajl_gen_free(gen);
61 }
62
63 static void throwError(yajl_gen_status err)
64 {
65 switch (err)
66 {
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...
77 }
78 }
79
80 yajl_gen gen;
81
82 std::ostream* out;
83 bool deleteWhenDone;
84
85 private:
86 void init(std::ostream& output, bool deleteOut, const std::string& indent)
87 {
88 yajl_gen_config config;
89
90 out = &output;
91 deleteWhenDone = deleteOut;
92
93 if (indent != "")
94 {
95 config.beautify = true;
96 config.indentString = 0;
97 // FIXME: a yajl bug prevents using heap-allocated strings
98 //config.indentString = indent.c_str();
99 }
100 else
101 {
102 config.beautify = false;
103 }
104 gen = yajl_gen_alloc(&config, 0);
105 }
106 };
107
108
109 serializer::serializer(const std::string& filePath, const std::string& indent) :
110 // pass through
111 impl(new serializer::serializer_impl(filePath, indent)) {}
112
113 serializer::serializer(std::ostream& output, const std::string& indent) :
114 // pass through
115 impl(new serializer::serializer_impl(output, indent)) {}
116
117 serializer::~serializer()
118 {
119 flush();
120 }
121
122
123 void serializer::push(long value)
124 {
125 yajl_gen_status stat = yajl_gen_integer(impl->gen, value);
126 if (stat != yajl_gen_status_ok)
127 serializer::serializer_impl::throwError(stat);
128 }
129
130 void serializer::push(double value)
131 {
132 yajl_gen_status stat = yajl_gen_double(impl->gen, value);
133 if (stat != yajl_gen_status_ok)
134 serializer::serializer_impl::throwError(stat);
135 }
136
137 void serializer::push(bool value)
138 {
139 yajl_gen_status stat = yajl_gen_bool(impl->gen, value);
140 if (stat != yajl_gen_status_ok)
141 serializer::serializer_impl::throwError(stat);
142 }
143
144 void serializer::push(const std::string& value)
145 {
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);
150 }
151
152 void serializer::push(const std::wstring& value)
153 {
154 push(wideToMulti(value));
155 }
156
157 void serializer::pushNull()
158 {
159 yajl_gen_status stat = yajl_gen_null(impl->gen);
160 if (stat != yajl_gen_status_ok)
161 serializer::serializer_impl::throwError(stat);
162 }
163
164
165 void serializer::pushMapHead()
166 {
167 yajl_gen_status stat = yajl_gen_map_open(impl->gen);
168 if (stat != yajl_gen_status_ok)
169 serializer::serializer_impl::throwError(stat);
170 }
171
172 void serializer::pushMapTail()
173 {
174 yajl_gen_status stat = yajl_gen_map_close(impl->gen);
175 if (stat != yajl_gen_status_ok)
176 serializer::serializer_impl::throwError(stat);
177 }
178
179 void serializer::pushArrayHead()
180 {
181 yajl_gen_status stat = yajl_gen_array_open(impl->gen);
182 if (stat != yajl_gen_status_ok)
183 serializer::serializer_impl::throwError(stat);
184 }
185
186 void serializer::pushArrayTail()
187 {
188 yajl_gen_status stat = yajl_gen_array_close(impl->gen);
189 if (stat != yajl_gen_status_ok)
190 serializer::serializer_impl::throwError(stat);
191 }
192
193
194 void serializer::flush()
195 {
196 const unsigned char* buffer;
197 unsigned length;
198
199 yajl_gen_get_buf(impl->gen, &buffer, &length);
200 impl->out->write((const char*)buffer, length);
201 yajl_gen_clear(impl->gen);
202 }
203
204
205 } // namespace dc
206
207 /** vim: set ts=4 sw=4 tw=80: *************************************************/
208
This page took 0.037466 seconds and 3 git commands to generate.