]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Serializer.cc
extreme refactoring
[chaz/yoink] / src / Moof / Serializer.cc
diff --git a/src/Moof/Serializer.cc b/src/Moof/Serializer.cc
new file mode 100644 (file)
index 0000000..a93eb5a
--- /dev/null
@@ -0,0 +1,208 @@
+
+/*******************************************************************************
+
+ 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 "Serializer.hh"
+#include "StringTools.hh"
+
+
+namespace Mf {
+
+
+class Serializer::SerializerImpl
+{
+public:
+       SerializerImpl(const std::string& filePath, const std::string& indent = "")
+       {
+               std::ofstream* output = new std::ofstream(filePath.c_str());
+               init(*output, true, indent);
+       }
+
+       SerializerImpl(std::ostream& output, const std::string& indent = "")
+       {
+               init(output, false, indent);
+       }
+
+       ~SerializerImpl()
+       {
+               if (deleteWhenDone)
+               {
+                       delete out;
+               }
+               yajl_gen_free(gen);
+       }
+
+       static void throwError(yajl_gen_status err)
+       {
+               switch (err)
+               {
+                       case yajl_gen_generation_complete:
+                               throw Serializer::Exception("the archive has already terminated");
+                       case yajl_gen_keys_must_be_strings:
+                               throw Serializer::Exception("map keys must be strings");
+                       case yajl_max_depth_exceeded:
+                               throw Serializer::Exception("maximum archive depth exceeded");
+                       case yajl_gen_in_error_state:
+                               throw Serializer::Exception("serializer already in error state");
+                       case yajl_gen_status_ok:
+                               ; // There is no error here.  Move along...
+               }
+       }
+
+       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) :
+       // pass through
+       impl_(new Serializer::SerializerImpl(filePath, indent)) {}
+
+Serializer::Serializer(std::ostream& output, const std::string& indent) :
+       // pass through
+       impl_(new Serializer::SerializerImpl(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::SerializerImpl::throwError(stat);
+}
+
+void Serializer::push(double value)
+{
+       yajl_gen_status stat = yajl_gen_double(impl_->gen, value);
+       if (stat != yajl_gen_status_ok)
+               Serializer::SerializerImpl::throwError(stat);
+}
+
+void Serializer::push(bool value)
+{
+       yajl_gen_status stat = yajl_gen_bool(impl_->gen, value);
+       if (stat != yajl_gen_status_ok)
+               Serializer::SerializerImpl::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::SerializerImpl::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::SerializerImpl::throwError(stat);
+}
+
+
+void Serializer::pushMapHead()
+{
+       yajl_gen_status stat = yajl_gen_map_open(impl_->gen);
+       if (stat != yajl_gen_status_ok)
+               Serializer::SerializerImpl::throwError(stat);
+}
+
+void Serializer::pushMapTail()
+{
+       yajl_gen_status stat = yajl_gen_map_close(impl_->gen);
+       if (stat != yajl_gen_status_ok)
+               Serializer::SerializerImpl::throwError(stat);
+}
+
+void Serializer::pushArrayHead()
+{
+       yajl_gen_status stat = yajl_gen_array_open(impl_->gen);
+       if (stat != yajl_gen_status_ok)
+               Serializer::SerializerImpl::throwError(stat);
+}
+
+void Serializer::pushArrayTail()
+{
+       yajl_gen_status stat = yajl_gen_array_close(impl_->gen);
+       if (stat != yajl_gen_status_ok)
+               Serializer::SerializerImpl::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 Mf
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
This page took 0.023989 seconds and 4 git commands to generate.