/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #include #include "metafile/nml.h" #include "ascii/ascii_encoder.h" #include "filesystem/filesystem.h" #include "filesystem/io_handle.h" #include "memory/nauto_ptr.h" #include "platform_config.h" #include "platform.h" #include "log/log.h" using namespace GS; using namespace GS::NML; //------------------------------------------------------------------------------ bool Parser::SaveTag(IO::Handle &out, const Tag &tag, File::Binary method, uint idt) { //--------------------------------------------------------------------------- #define OUTPUT_INDENT { for (uint n = 0; n < idt; n++) out << "\t"; } //--------------------------------------------------------------------------- if (tag.name.IsEmpty() && !tag.GetChildCount()) return true; // silently skip this tag OUTPUT_INDENT; out << "<" << tag.name.c_str(); switch (tag.GetValue().GetType()) { case Variant::VariantNone: if (tag.GetChildCount()) { out << "=\n"; NMLTagForeach(child, tag) if (!SaveTag(out, *child, method, idt + 1)) return false; OUTPUT_INDENT; } break; case Variant::VariantBinary: { uint olen = (uint)~0; switch (method) { case File::Binary_UU: olen = nAsciiEncoder::UUEncode((uchar *)tag.GetValue().GetBinaryBuffer(), tag.GetValue().GetBinarySize()); break; case File::Binary_yEnc: olen = nAsciiEncoder::yEncode((uchar *)tag.GetValue().GetBinaryBuffer(), tag.GetValue().GetBinarySize()); break; } if (olen) { Array aenc(olen, Alloc::Metatag); if (aenc.IsValid()) { uint asize = 0; switch (method) { case File::Binary_UU: asize = nAsciiEncoder::UUEncode((uchar *)tag.GetValue().GetBinaryBuffer(), tag.GetValue().GetBinarySize(), &aenc[0], olen); break; case File::Binary_yEnc: asize = nAsciiEncoder::yEncode((uchar *)tag.GetValue().GetBinaryBuffer(), tag.GetValue().GetBinarySize(), &aenc[0], olen); break; } if (asize != olen) __LOG_W__ << "Internal ASCII encoding inconsistency detected while processing tag '" << tag.name << "'.\n"; char str[256]; _snprintf(str, 255, "==%d:%d", asize, tag.GetValue().GetBinarySize()); // ==[encoded size:decoded size] is encoded binary. out << str; if (method == File::Binary_yEnc) // @ marker select yEncoding. out << "@"; out << "\n"; out.Write(aenc, asize); } else __LOG_E__ << "Tag '" << tag.name << "' failed to allocate internal binary buffer.\n"; } // else __LOG_W__ << "NULL size ASCII encoded binary tag '" << tag.id << "'.\n"; } break; case Variant::VariantInteger: { char str[256]; _snprintf(str, 255, "=%d", tag.GetInteger()); out << str; } break; case Variant::VariantFloat: { char str[256]; _snprintf(str, 255, "=%f", tag.GetReal()); out << str; } break; case Variant::VariantString: out << "=\"" << tag.GetString() << "\""; break; case Variant::VariantBool: out << "=" << (tag.GetBool() ? "True" : "False"); break; default: __ERR__(__LOG_E__ << "No method to output tag '" << tag.name << "' type.\n", false) } out << ">\n"; return true; } bool Parser::Save(IO::Handle &h, const File &file) { h << "\n"; NMLFileForeach(tag, file) if (!SaveTag(h, *tag, file.GetBinaryMethod(), 0)) return false; return true; } bool Parser::Save(const char *uri, const File &file) { if (!uri) return false; AutoPtr h(Platform::Get().io->Open(uri, IO::ModeWrite)); if (h.IsNull()) __ERR__(__LOG_E__ << "Failed to open nml output '" << uri << "'.\n", false) return Save(*h, file); } //------------------------------------------------------------------------------