X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fserializer.cc;fp=src%2Fserializer.cc;h=e2f77340e5481b0269b681477215c6e05f197cbf;hb=79b5f738f2e38acb60cda7e09f54802933a17105;hp=0000000000000000000000000000000000000000;hpb=a891a2dcbbb63d9e771da6efff00a33da614e737;p=chaz%2Fyoink diff --git a/src/serializer.cc b/src/serializer.cc new file mode 100644 index 0000000..e2f7734 --- /dev/null +++ b/src/serializer.cc @@ -0,0 +1,193 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include + +#include + +#include "stringtools.hh" +#include "serializer.hh" + + +namespace dc { + + +class serializer_impl +{ +public: + serializer_impl(const std::string& filePath, const std::string& indent = "") + { + std::ofstream* output = new std::ofstream(filePath.c_str()); + init(*output, true, indent); + } + + serializer_impl(std::ostream& output, const std::string& indent = "") + { + init(output, false, indent); + } + + ~serializer_impl() + { + if (deleteWhenDone) + { + delete out; + } + yajl_gen_free(gen); + } + + static void throwError(yajl_gen_status err) + { + switch (err) + { + case yajl_gen_generation_complete: + throw serializer::generator_error("the archive has already terminated"); + case yajl_gen_keys_must_be_strings: + throw serializer::generator_error("map keys must be strings"); + case yajl_max_depth_exceeded: + throw serializer::generator_error("maximum archive depth exceeded"); + case yajl_gen_in_error_state: + throw serializer::generator_error("serializer already in error state"); + } + } + + yajl_gen gen; + + std::ostream* out; + bool deleteWhenDone; + +private: + void init(std::ostream& output, bool deleteOut, const std::string& indent) + { + yajl_gen_config config; + + out = &output; + deleteWhenDone = deleteOut; + + if (indent != "") + { + config.beautify = true; + config.indentString = 0; + // FIXME: a yajl bug prevents using heap-allocated strings + //config.indentString = indent.c_str(); + } + else + { + config.beautify = false; + } + gen = yajl_gen_alloc(&config, 0); + } +}; + + +serializer::serializer(const std::string& filePath, const std::string& indent) : + impl(new serializer_impl(filePath, indent)) {} + +serializer::serializer(std::ostream& output, const std::string& indent) : + impl(new serializer_impl(output, indent)) {} + +serializer::~serializer() +{ + flush(); +} + + +void serializer::push(long value) +{ + yajl_gen_status stat = yajl_gen_integer(impl->gen, value); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::push(double value) +{ + yajl_gen_status stat = yajl_gen_double(impl->gen, value); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::push(bool value) +{ + yajl_gen_status stat = yajl_gen_bool(impl->gen, value); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::push(const std::string& value) +{ + yajl_gen_status stat = yajl_gen_string(impl->gen, + (const unsigned char*)value.c_str(), value.length()); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::push(const std::wstring& value) +{ + push(wideToMulti(value)); +} + +void serializer::pushNull() +{ + yajl_gen_status stat = yajl_gen_null(impl->gen); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + + +void serializer::pushMapHead() +{ + yajl_gen_status stat = yajl_gen_map_open(impl->gen); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::pushMapTail() +{ + yajl_gen_status stat = yajl_gen_map_close(impl->gen); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::pushArrayHead() +{ + yajl_gen_status stat = yajl_gen_array_open(impl->gen); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + +void serializer::pushArrayTail() +{ + yajl_gen_status stat = yajl_gen_array_close(impl->gen); + if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); +} + + +void serializer::flush() +{ + const unsigned char* buffer; + unsigned length; + + yajl_gen_get_buf(impl->gen, &buffer, &length); + impl->out->write((const char*)buffer, length); + yajl_gen_clear(impl->gen); +} + + +} // namespace dc +