]> Dogcows Code - chaz/yoink/blobdiff - src/serializer.cc
new classes; yajl library
[chaz/yoink] / src / serializer.cc
diff --git a/src/serializer.cc b/src/serializer.cc
new file mode 100644 (file)
index 0000000..e2f7734
--- /dev/null
@@ -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 <fstream>
+
+#include <yajl/yajl_gen.h>
+
+#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
+
This page took 0.025361 seconds and 4 git commands to generate.