153 lines
3.9 KiB
C++
153 lines
3.9 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#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 <uchar> 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 << "<Version=1.0>\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 <IO::Handle> 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);
|
|
}
|
|
//------------------------------------------------------------------------------
|