]> Dogcows Code - chaz/yoink/blob - src/Moof/Serializer.cc
570ee5a624c954cc95acd5c2e74ef50196b4a836
[chaz/yoink] / src / Moof / 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 "Serializer.hh"
34 #include "StringTools.hh"
35
36
37 namespace Mf {
38
39
40 struct Serializer::Impl
41 {
42 Impl(const std::string& filePath, const std::string& indent = "")
43 {
44 std::ofstream* output = new std::ofstream(filePath.c_str());
45 init(*output, true, indent);
46 }
47
48 Impl(std::ostream& output, const std::string& indent = "")
49 {
50 init(output, false, indent);
51 }
52
53 ~Impl()
54 {
55 if (deleteWhenDone)
56 {
57 delete out;
58 }
59 yajl_gen_free(gen);
60 }
61
62 static void raise(yajl_gen_status err)
63 {
64 switch (err)
65 {
66 case yajl_gen_generation_complete:
67 throw Serializer::Exception(Exception::ARCHIVE_TERMINATED);
68 case yajl_gen_keys_must_be_strings:
69 throw Serializer::Exception(Exception::KEYS_MUST_BE_STRINGS);
70 case yajl_max_depth_exceeded:
71 throw Serializer::Exception(Exception::RECURSION_TOO_DEEP);
72 case yajl_gen_in_error_state:
73 throw Serializer::Exception(Exception::ALREADY_FAILED);
74 case yajl_gen_status_ok:
75 ; // There is no error here. Move along...
76 }
77 }
78
79 yajl_gen gen;
80
81 std::ostream* out;
82 bool deleteWhenDone;
83
84 private:
85
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::Impl(filePath, indent)) {}
112
113 Serializer::Serializer(std::ostream& output, const std::string& indent) :
114 // pass through
115 impl_(new 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) Serializer::Impl::raise(stat);
127 }
128
129 void Serializer::push(double value)
130 {
131 yajl_gen_status stat = yajl_gen_double(impl_->gen, value);
132 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
133 }
134
135 void Serializer::push(bool value)
136 {
137 yajl_gen_status stat = yajl_gen_bool(impl_->gen, value);
138 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
139 }
140
141 void Serializer::push(const std::string& value)
142 {
143 yajl_gen_status stat = yajl_gen_string(impl_->gen,
144 (const unsigned char*)value.c_str(), value.length());
145 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
146 }
147
148 void Serializer::push(const std::wstring& value)
149 {
150 push(wideToMulti(value));
151 }
152
153 void Serializer::pushNull()
154 {
155 yajl_gen_status stat = yajl_gen_null(impl_->gen);
156 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
157 }
158
159
160 void Serializer::pushMapHead()
161 {
162 yajl_gen_status stat = yajl_gen_map_open(impl_->gen);
163 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
164 }
165
166 void Serializer::pushMapTail()
167 {
168 yajl_gen_status stat = yajl_gen_map_close(impl_->gen);
169 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
170 }
171
172 void Serializer::pushArrayHead()
173 {
174 yajl_gen_status stat = yajl_gen_array_open(impl_->gen);
175 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
176 }
177
178 void Serializer::pushArrayTail()
179 {
180 yajl_gen_status stat = yajl_gen_array_close(impl_->gen);
181 if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat);
182 }
183
184
185 void Serializer::flush()
186 {
187 const unsigned char* buffer;
188 unsigned length;
189
190 yajl_gen_get_buf(impl_->gen, &buffer, &length);
191 impl_->out->write((const char*)buffer, length);
192 yajl_gen_clear(impl_->gen);
193 }
194
195
196 } // namespace Mf
197
198 /** vim: set ts=4 sw=4 tw=80: *************************************************/
199
This page took 0.039266 seconds and 3 git commands to generate.