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 "Serializer.hh"
34 #include "StringTools.hh"
40 struct Serializer::Impl
42 Impl(const std::string
& filePath
, const std::string
& indent
= "")
44 std::ofstream
* output
= new std::ofstream(filePath
.c_str());
45 init(*output
, true, indent
);
48 Impl(std::ostream
& output
, const std::string
& indent
= "")
50 init(output
, false, indent
);
62 static void raise(yajl_gen_status err
)
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...
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::Impl(filePath
, indent
)) {}
113 Serializer::Serializer(std::ostream
& output
, const std::string
& indent
) :
115 impl_(new 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
) Serializer::Impl::raise(stat
);
129 void Serializer::push(double value
)
131 yajl_gen_status stat
= yajl_gen_double(impl_
->gen
, value
);
132 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
135 void Serializer::push(bool value
)
137 yajl_gen_status stat
= yajl_gen_bool(impl_
->gen
, value
);
138 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
141 void Serializer::push(const std::string
& value
)
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
);
148 void Serializer::push(const std::wstring
& value
)
150 push(wideToMulti(value
));
153 void Serializer::pushNull()
155 yajl_gen_status stat
= yajl_gen_null(impl_
->gen
);
156 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
160 void Serializer::pushMapHead()
162 yajl_gen_status stat
= yajl_gen_map_open(impl_
->gen
);
163 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
166 void Serializer::pushMapTail()
168 yajl_gen_status stat
= yajl_gen_map_close(impl_
->gen
);
169 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
172 void Serializer::pushArrayHead()
174 yajl_gen_status stat
= yajl_gen_array_open(impl_
->gen
);
175 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
178 void Serializer::pushArrayTail()
180 yajl_gen_status stat
= yajl_gen_array_close(impl_
->gen
);
181 if (stat
!= yajl_gen_status_ok
) Serializer::Impl::raise(stat
);
185 void Serializer::flush()
187 const unsigned char* buffer
;
190 yajl_gen_get_buf(impl_
->gen
, &buffer
, &length
);
191 impl_
->out
->write((const char*)buffer
, length
);
192 yajl_gen_clear(impl_
->gen
);
198 /** vim: set ts=4 sw=4 tw=80: *************************************************/