commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions
@@ -0,0 +1,111 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cstring>
#include "metafile/nml.h"
#include "filesystem/io_handle.h"
#include "filesystem/filesystem.h"
#include "platform.h"
#include "log/log.h"
using namespace GS;
using namespace GS::NML;
//------------------------------------------------------------------------------
bool Parser::SaveBinaryTag(IO::Handle &out, const Tag &tag, File::Binary method)
{
const Variant &v = tag.GetValue();
if (v.GetType() != Variant::VariantNone)
{
out.Write <ushort> ((ushort)tag.name.Len());
out.Write((void *)tag.name.c_str(), tag.name.Len());
}
else
__ERR__(__LOG_W__ << "Ignoring invalid metatag '" << tag.name << "'.\n", true)
// Store tag start size/type.
out.Write <uchar> ((uchar)v.GetType());
size_t tag_length_pos = out.Tell();
switch (v.GetType())
{
case Variant::VariantNone:
case Variant::VariantBinary:
case Variant::VariantString:
out.Write <int> (-1);
break;
default: break;
}
switch (v.GetType())
{
case Variant::VariantNone:
NMLTagForeach(child, tag)
if (!SaveBinaryTag(out, *child, method))
return false;
break;
case Variant::VariantBinary:
out.Write(tag.GetValue().GetBinaryBuffer(), tag.GetValue().GetBinarySize());
break;
case Variant::VariantInteger:
out.Write <int> (tag.GetInteger());
break;
case Variant::VariantFloat:
out.Write <float> (tag.GetReal());
break;
case Variant::VariantString:
out.Write(tag.GetString(), std::strlen(tag.GetString()));
break;
default:
__ERR__(__LOG_E__ << "No method to output tag '" << tag.name << "' type.\n", false)
}
switch (v.GetType())
{
case Variant::VariantNone:
case Variant::VariantBinary:
case Variant::VariantString:
{
size_t tag_end_pos = out.Tell();
out.Seek(tag_length_pos, IO::Base::SeekStart);
out.Write <int> (tag_end_pos - tag_length_pos);
out.Seek(tag_end_pos, IO::Base::SeekStart);
}
break;
default: break;
}
return true;
}
bool Parser::SaveBinary(IO::Handle &h, const File &file)
{
h.Write((const void *)"<BML=1.0>\n", 10);
NMLFileForeach(tag, file)
if (!SaveBinaryTag(h, *tag, file.GetBinaryMethod()))
return false;
return true;
}
bool Parser::SaveBinary(const char *uri, const File &file)
{
if (!uri)
return false;
AutoPtr <IO::Handle> handle;
if (!(handle = Platform::Get().io->Open(uri, IO::ModeWrite)))
__ERR__(__LOG_E__ << "Failed to open metafile output '" << uri << "'.\n", false)
return SaveBinary(*handle, file);
}
//------------------------------------------------------------------------------
+83
View File
@@ -0,0 +1,83 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "metafile/nml.h"
#include "alloc/ialloc.h"
using namespace GS::NML;
//------------------------------------------------------------------------------
bool File::GetBool(const char *path, bool dflt, bool verbose) const {
Tag *t = GetTypedTag(path, Variant::VariantBool, verbose);
return t ? t->GetBool() : dflt;
}
int File::GetInteger(const char *path, int dflt, bool verbose) const {
Tag *t = GetTypedTag(path, Variant::VariantInteger, verbose);
return t ? t->GetInteger() : dflt;
}
float File::GetReal(const char *path, float dflt, bool verbose) const {
Tag *t = GetTypedTag(path, Variant::VariantFloat, verbose);
return t ? t->GetReal() : dflt;
}
const char *File::GetString(const char *path, const char *dflt, bool verbose) const {
Tag *t = GetTypedTag(path, Variant::VariantString, verbose);
return t ? t->GetString() : dflt;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void File::Import(const File &src, bool clear_before_import) {
if (clear_before_import)
Clear();
ListForeachPtr(Tag *, tag, src.GetTags())
AddRoot(tag->Clone());
}
File *File::Clone() const {
File *clone = new File;
if (!clone)
return NULL;
if (!name.IsEmpty())
clone->name = name.c_str();
clone->Import(*this);
return clone;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Tag *File::AddRoot(Tag *t) {
if (!t)
return NULL;
if (!tags.Add(t))
return NULL;
return t;
}
Tag *File::AddRoot(const char *name) { return AddRoot(new Tag(name)); }
Tag *File::AddRoot(const char *name, bool v) { return AddRoot(new Tag(name, v)); }
Tag *File::AddRoot(const char *name, int v) { return AddRoot(new Tag(name, v)); }
Tag *File::AddRoot(const char *name, float v) { return AddRoot(new Tag(name, v)); }
Tag *File::AddRoot(const char *name, const char *s) { return AddRoot(new Tag(name, s)); }
Tag *File::AddRoot(const char *name, void *d, size_t s) { return AddRoot(new Tag(name, d, s)); }
bool File::UnlinkRoot(Tag *t) { return tags.Remove(t); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void File::Free() {
ListDeleteAllPtr(Tag *, tags);
name.Clear();
}
File::~File() { Free(); }
//------------------------------------------------------------------------------
+122
View File
@@ -0,0 +1,122 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "metafile/nml.h"
#include "reflection/c_refl.h"
#include "memory/nauto_ptr.h"
#include "assert/nassert.h"
namespace GS {
namespace NML {
using namespace Reflection;
//------------------------------------------------------------------------------
bool GenericObjectFromMetaTag(Tag &t, void *o, Property *o_prop)
{
NMLTagForeach(pt, t)
for (int n = 0; o_prop[n].name; ++n)
if (pt->name == o_prop[n].name)
{
size_t p_prop = (size_t)o + o_prop[n].offset_of;
switch (o_prop[n].type)
{
case Property::BoolProp:
*(bool *)p_prop = pt->GetBool();
break;
case Property::CharProp:
*(char *)p_prop = (char)pt->GetInteger();
break;
case Property::ShortProp:
*(short *)p_prop = (short)pt->GetInteger();
break;
case Property::IntProp:
*(int *)p_prop = pt->GetInteger();
break;
case Property::FloatProp:
*(float *)p_prop = pt->GetReal();
break;
case Property::StringProp:
*(GS::String *)p_prop = pt->GetString();
break;
case Property::EnumProp:
__ASSERT__(o_prop[n].enum_dict);
*(int *)p_prop = Enum::fromString(pt->GetString(), o_prop[n].enum_dict);
break;
default:
__ASSERT_ALWAYS__;
break;
}
}
return true;
}
Tag *GenericObjectToMetaTag(Tag *t, const void *o, Property *o_prop)
{
if (t)
for (int n = 0; o_prop[n].name; ++n)
{
size_t p_prop = (size_t)o + o_prop[n].offset_of;
switch (o_prop[n].type)
{
case Property::BoolProp:
t->AddChild(o_prop[n].name, *(bool *)p_prop);
break;
case Property::CharProp:
t->AddChild(o_prop[n].name, (int)*(char *)p_prop);
break;
case Property::ShortProp:
t->AddChild(o_prop[n].name, (int)*(short *)p_prop);
break;
case Property::IntProp:
t->AddChild(o_prop[n].name, *(int *)p_prop);
break;
case Property::FloatProp:
t->AddChild(o_prop[n].name, *(float *)p_prop);
break;
case Property::StringProp:
t->AddChild(o_prop[n].name, ((GS::String *)p_prop)->c_str());
break;
case Property::EnumProp:
__ASSERT__(o_prop[n].enum_dict);
t->AddChild(o_prop[n].name, Enum::toString(*(int *)p_prop, o_prop[n].enum_dict));
break;
default:
__ASSERT_ALWAYS__;
break;
}
}
return t;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool GenericObjectFromMetaFile(const char *uri, void *obj, Property *obj_prop, const char *root_name)
{
File file;
if (!Parser::Load(uri, file))
return false;
if (Tag *root = file.GetTag(root_name))
if (!GenericObjectFromMetaTag(*root, obj, obj_prop))
return false;
return true;
}
bool GenericObjectToMetaFile(const char *uri, const void *obj, Property *obj_prop, const char *root_name)
{
File file;
file.AddRoot(GenericObjectToMetaTag(new Tag(root_name), obj, obj_prop));
return Parser::Save(uri, file);
}
//------------------------------------------------------------------------------
} //NML
} // GS
+380
View File
@@ -0,0 +1,380 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cstring>
#include "metafile/nml.h"
#include "ascii/parser.h"
#include "ascii/ascii_encoder.h"
#include "filesystem/io_handle.h"
#include "filesystem/filesystem.h"
#include "platform.h"
#include "log/log.h"
using namespace GS;
using namespace GS::NML;
using namespace GS::AsciiParser;
//------------------------------------------------------------------------------
bool Parser::IsMetafile(const char *name)
{
AutoPtr <IO::Handle> h(Platform::Get().io->Open(name));
if (h.IsNull())
return false;
char header[9];
h->Read(header, 9);
if (Memory::Compare(header, "<Version=", 9) && Memory::Compare(header, "<NML=", 5))
return false;
return true;
}
const char *Parser::ParseTagPreprocessorDirective(Tag &tag, const char *s, const char *e)
{
s++;
// Catch preprocessor directive.
if (!strncmp(s, "include", 7))
{
// Ensure base coherency.
if (tag.GetValue().GetType() != Variant::VariantNone)
__ERR__(__LOG_E__ << "Incoherent type in tag '" << tag.name << "' declaration.\n", NULL)
// Parse directive.
s += SkipSpace(s + 7, e) - s;
if (s[0] != '(')
__ERR__(__LOG_E__ << "Mangled #include directive.\n", NULL);
// Fetch arguments.
String include_path;
forever
{
if (s[0] == ')')
break;
s += SkipSpace(s + 1, e) - s;
// Path.
if (s[0] == '"')
{
s++;
uint len = (uint)(RunToEOS(s, e) - s);
include_path.Set(s, s + len);
s += SkipSpace(s + len + 1, e) - s;
}
else
__ERR__(__LOG_E__ << "Unexpected character in #include directive.\n", NULL);
}
s++;
// Load external metafile.
File tmp_file;
if (Parser::Load(include_path, tmp_file, true))
{
// Then transfer all tags to our current file.
NMLFileForeach(t, tmp_file)
{
if (tmp_file.UnlinkRoot(t))
tag.AddChild(t);
else
__LOG_E__ << "Could not relink root tag from included metafile.\n";
}
}
else
__LOG_E__ << "Failed to include external metafile '" << include_path << "'.\n";
}
else if (!strncmp(s, "append", 6))
__LOG_E__ << "Preprocessor directive #append deprecated.\n";
else
__ERR__(__LOG_E__ << "Unknown preprocessor directive, metatag '" << tag.name << "'.\n", NULL)
return s;
}
bool Parser::ParseTag(Tag &tag, const char *s, const char *e, const char **es)
{
// Safety net.
s += SkipSpace(s, e) - s;
if (s[0] != '<')
return false;
// Get the tag id.
#define MLTAG_ERROR(c) { __LOG_E__ << c; return false; }
const char *etn = s + 1;
etn += SkipEntry(etn, e) - etn;
if (String::strfindchar(s + 1, ':', etn) != etn)
MLTAG_ERROR("':' is a path character and cannot be used in tag name.\n")
if (String::strfindchar(s + 1, ';', etn) != etn)
MLTAG_ERROR("';' is a path character and cannot be used in tag name.\n")
tag.name.Set(s + 1, etn);
s = etn;
// Get tag type.
s += SkipSpace(s, e) - s;
if (s == e)
MLTAG_ERROR("Mangled definition, metatag '" << tag.name << "'.\n")
switch (s[0])
{
case '>':
s++;
break;
// Node/real/integer/string.
case '=':
{
s++;
forever
{
s += SkipSpace(s, e) - s;
if (s == e)
MLTAG_ERROR("Mangled definition, metatag '" << tag.name << "'.\n")
// End of tag.
if (s[0] == '>')
{
s++;
break;
}
// Preprocessor directive.
if (s[0] == '#')
s = ParseTagPreprocessorDirective(tag, s + 1, e);
// Node.
else if (s[0] == '<')
{
if (tag.GetValue().GetType() != Variant::VariantNone)
MLTAG_ERROR("Incoherent type in tag '" << tag.name << "' declaration.\n")
Tag *stag = tag.tags.Add(new Tag)->Object();
if (!ParseTag(*stag, s, e, &s))
MLTAG_ERROR("")
s += SkipSpace(s, e) - s;
}
// Constant.
else
{
if (tag.GetValue().GetType() != Variant::VariantNone)
MLTAG_ERROR("Incoherent type in tag '" << tag.name << "' declaration.\n")
// Binary.
if (s[0] == '=')
{
s++;
if (!(s[0] >= '0' && s[0] <= '9'))
MLTAG_ERROR("Expected encoded size in binary tag '" << tag.name << "' declaration.\n")
const char *ye = s;
while (ye[0] >= '0' && ye[0] <= '9')
ye++;
if (ye[0] != ':')
MLTAG_ERROR("Expected size delimiter in binary tag '" << tag.name << "' declaration.\n")
uint asize = String(s, ye).Integer();
s = ye + 1;
if (!(s[0] >= '0' && s[0] <= '9'))
MLTAG_ERROR("Expected binary size in binary tag '" << tag.name << "' declaration.\n")
ye = s;
while (ye[0] >= '0' && ye[0] <= '9')
ye++;
// Trailing @ means yEnc binary.
File::Binary encoding = File::Binary_UU;
if (ye[0] == '@')
{
encoding = File::Binary_yEnc;
ye++;
}
// Detect EOL
if ((ye[0] != 0x0a) && ((ye[0] != 0x0d) && (ye[1] != 0x0a)))
MLTAG_ERROR("Expected EOL following binary size in binary tag '" << tag.name << "' declaration.\n")
size_t eol_size = (ye[0] == 0x0a) ? 1 : 2;
uint bsize = String(s, ye).Integer();
uchar *astart = (uchar *)(ye + eol_size);
// [EJ] Adjust asize to account for Windows EOL (historically NML only specifies Unix ascii size).
if (eol_size > 1)
{
__LOG_V__ << "CRLF reduces NML binary load performance.\n";
size_t a_size_in = asize;
asize = 0;
for (; a_size_in > 0; --a_size_in)
if ((astart[asize] == 0x0d) && (astart[asize + 1] == 0x0a))
asize += 2;
else
++asize;
}
// Load ASCII encoded data.
Array <uchar> aenc(asize, Alloc::Metatag);
if (!aenc)
MLTAG_ERROR("Failed to allocate binary buffer in binary tag '" << tag.name << "'.\n")
memcpy(&aenc[0], astart, asize);
s = ye + eol_size + asize;
if (s[0] != '>')
MLTAG_ERROR("Expected closing tag in tag '" << tag.name << "'.\n")
Array <uchar> data(bsize, Alloc::Metatag);
if (data)
{
switch (encoding)
{
case File::Binary_UU: nAsciiEncoder::UUDecode(&aenc[0], asize, &data[0], bsize); break;
case File::Binary_yEnc: nAsciiEncoder::yDecode(&aenc[0], asize, &data[0], bsize); break;
}
tag.GetValue().SetBinary(&data[0], bsize);
}
}
// Real/Integer.
else if ((s[0] >= '0' && s[0] <= '9') || (s[0] == '.') || (s[0] == '-'))
{
if (IsConstantFloat(s, e))
tag.GetValue() = String::atof(s, e, true);
else tag.GetValue() = String::atoi(s);
if (s[0] == '-')
s++;
s += SkipEntry(s, e) - s;
if (s[0] != '>')
MLTAG_ERROR("Unexpected trailing expression following value, metatag '" << tag.name << "'.\n")
}
// String.
else if (s[0] == '\"')
{
s++;
ptrdiff_t len = RunToEOS(s, e) - s;
if ((s + len) == e)
MLTAG_ERROR("Mangled string declaration, metatag '" << tag.name << "'.\n")
// Copy string.
tag.GetValue() = String(s, s + len);
s += SkipSpace(s + len + 1, e) - s; // Jump over string.
if (s == e)
MLTAG_ERROR("Unexpected EOF after string declaration, metatag '" << tag.name << "'.\n")
if (s[0] != '>')
MLTAG_ERROR("Unexpected trailing expression following string object, metatag '" << tag.name << "'.\n")
tag.GetValue().s_value.ReplaceAll("\\n", "\n"); // convert CF
}
// Boolean.
else if (!strncmp(s, "True", 4))
{
tag.GetValue() = true;
s += SkipSpace(s + 4, e) - s;
if (s[0] != '>')
MLTAG_ERROR("Unexpected trailing expression following value, metatag '" << tag.name << "'.\n")
}
else if (!strncmp(s, "False", 5))
{
tag.GetValue() = false;
s += SkipSpace(s + 5, e) - s;
if (s[0] != '>')
MLTAG_ERROR("Unexpected trailing expression following value, metatag '" << tag.name << "'.\n")
}
else
MLTAG_ERROR("Unexpected '" << s[0] << "' in assignation, metatag '" << tag.name << "'.\n")
}
}
}
break;
default:
MLTAG_ERROR("Unexpected trailing expression after metatag '" << tag.name << "' name declaration.\n")
}
if (es)
es[0] = s;
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Parser::LoadFromMemory(const char *data, size_t size, File &mfl)
{
mfl.Free();
if (!data)
return false;
// Read header tag, expected to be NML version.
const char *pof = data, *eof = data + size;
#define MEM_MLP_ERROR(c) { (c); return false; }
Tag header_tag;
if (!ParseTag(header_tag, pof, eof, &pof))
MEM_MLP_ERROR(__LOG_E__ << "Invalid metafile.\n")
if ((header_tag.name != "Version") && (header_tag.name != "NML"))
MEM_MLP_ERROR(__LOG_E__ << "Unknown metafile variant.\n")
switch (header_tag.GetValue().GetType())
{
case Variant::VariantInteger:
if (header_tag.GetInteger() > version)
__LOG_W__ << "Newer version NML header found (" << header_tag.GetInteger() << ">" << version << ").\n";
break;
case Variant::VariantFloat:
if (header_tag.GetReal() > version)
__LOG_W__ << "Newer version NML header found (" << header_tag.GetReal() << ">" << version << ").\n";
break;
default:
__LOG_W__ << "Unknown NML header version identification method.\n";
break;
}
// Read all root tags.
while (pof < eof)
{
Tag *tag = mfl.tags.Add(new Tag)->Object();
if (!ParseTag(*tag, pof, eof, &pof))
return false;
pof += SkipSpace(pof, eof) - pof;
}
return true;
}
bool Parser::Load(const char *path, File &file, bool verbose)
{
if (!path)
return false;
Array <char> data;
if (!Platform::Get().io->FileLoad(path, data, verbose))
return false;
try
{
if (!LoadFromMemory(data.c_ptr(), data.GetSize(), file))
return false;
}
catch (char *e)
{
__LOG_E__ << "Failed to load file LoadFromMemory. " << path << "\n";
return false;
}
file.name = path;
return true;
}
File *Parser::Load(const char *metafile, bool verbose)
{
AutoPtr <File> mfl(new File);
if (mfl.IsNull())
__ERR__(__LOG_E__ << "Failed to allocate file.\n", NULL)
return Load(metafile, *mfl, verbose) ? mfl.Detach() : NULL;
}
//------------------------------------------------------------------------------
+97
View File
@@ -0,0 +1,97 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "metafile/nml.h"
#include "log/log.h"
using namespace GS;
using namespace GS::NML;
static bool MetatagNameCompare(const Tag *o, const String &name) { return o->name == name; }
//------------------------------------------------------------------------------
Tag *Tag::GetTagEx(const List <Tag *> &tg, const char *s, const File *, bool verbose)
{
if (!s)
return NULL;
const char *path = s;
const List <Tag *> *list = &tg;
Tag *tag = NULL;
while (s[0])
{
while (s[0] == ':')
s++;
if (s[0] == ';')
break;
const char *t = s;
while ((t[0] != ';') && (t[0] != ':') && t[0])
t++;
if (!t[0] && verbose)
{
if (t > s)
__LOG_W__ << "incomplete path '" << path << "' (missing ';').\n";
else __LOG_E__ << "unexpected end of path'" << path << "'.\n";
}
// No more node to search.
if (!list)
{
if (verbose)
__LOG_W__ << "'" << path << "' is deeper than lowest tree node.\n";
return NULL;
}
String node_name(s, t);
s = t;
tag = ListFindEx(*list, MetatagNameCompare, node_name);
if (tag == NULL)
{
if (verbose)
__LOG__ << "!! Error '" << node_name << "' in '" << path << "' not found.\n";
return NULL;
}
switch (tag->GetValue().GetType())
{
case Variant::VariantNone:
list = &tag->tags;
break;
default:
list = NULL;
break;
}
}
return tag;
}
Tag *Tag::GetTag(const char *path, const File *root, bool verbose) const
{
return GetTagEx(tags, path, root, verbose);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Tag *Tag::GetTypedTag(const char *path, Variant::Type type, const File *root, bool verbose) const
{
Tag *t = Tag::GetTagEx(tags, path, root, verbose);
if ((!t) || (t->GetValue().GetType() != type))
return NULL;
return t;
}
Tag *File::GetTypedTag(const char *path, Variant::Type type, bool verbose) const
{
Tag *t = Tag::GetTagEx(tags, path, this, verbose);
if ((!t) || (t->GetValue().GetType() != type))
return NULL;
return t;
}
//------------------------------------------------------------------------------
+152
View File
@@ -0,0 +1,152 @@
/* -----------------------------------------------------------------------------
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);
}
//------------------------------------------------------------------------------
+65
View File
@@ -0,0 +1,65 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "metafile/nml_string.h"
#include "metafile/nml.h"
#include "filesystem/io_memory.h"
#include "memory/nauto_ptr.h"
#include "nstring/nstring.h"
#include "log/log.h"
namespace GS {
namespace NML {
//-----------------------------------------------------------------------------
bool TagToString(const Tag &tag, String &str)
{
IO::Memory memory_fs;
AutoPtr <IO::Handle> h(memory_fs.Open("file", IO::ModeWrite));
if (h.IsNull() || !Parser::SaveTag(*h, tag))
return false;
h = NULL;
Array <char> data;
if (!memory_fs.FileLoad("file", data))
return false;
str.Set(data.Start(), data.End());
return true;
}
bool TagFromString(const String &str, Tag &tag)
{
return Parser::ParseTag(tag, str.c_str(), &str.c_str()[str.Len()]);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool FileToString(const File &file, String &str)
{
IO::Memory memory_fs;
AutoPtr <IO::Handle> h(memory_fs.Open("file", IO::ModeWrite));
if (h.IsNull() || !Parser::Save(*h, file))
return false;
h = NULL;
Array <char> data;
if (!memory_fs.FileLoad("file", data))
return false;
str.Set(data.Start(), data.End());
return true;
}
bool FileFromString(const String &str, File &file)
{
return Parser::LoadFromMemory(str.c_str(), str.Len(), file);
}
//-----------------------------------------------------------------------------
} // NML
} // GS
+121
View File
@@ -0,0 +1,121 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "metafile/nml.h"
#include "filesystem/io_handle.h"
#include "alloc/ialloc.h"
#include "log/log.h"
using namespace GS::NML;
//------------------------------------------------------------------------------
Tag *Tag::GetParent(Tag *root) const
{
ListForeachPtr(Tag *, child, root->GetTags())
if (child == this)
return root;
Tag *parent = NULL;
ListForeachPtr(Tag *, child, root->GetTags())
if ((parent = GetParent(child)) != NULL)
break;
return parent;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Tag *Tag::AddChild(Tag *t)
{
if (!t)
return NULL;
if (value.type != Variant::VariantNone)
__ERR__(__LOG_E__ << "Cannot add child to tag '" << name << "' as it is neither a pure tag or a node.\n", NULL)
if (!tags.Add(t))
return NULL;
return t;
}
Tag *Tag::AddChild(const char *name)
{ return AddChild(new Tag(name)); }
Tag *Tag::AddChild(const char *name, bool v)
{ return AddChild(new Tag(name, v)); }
Tag *Tag::AddChild(const char *name, int v)
{ return AddChild(new Tag(name, v)); }
Tag *Tag::AddChild(const char *name, uint v)
{ return AddChild(new Tag(name, v)); }
Tag *Tag::AddChild(const char *name, float v)
{ return AddChild(new Tag(name, v)); }
Tag *Tag::AddChild(const char *name, const char *s)
{ return AddChild(new Tag(name, s)); }
Tag *Tag::AddChild(const char *name, void *buffer, size_t size)
{ return AddChild(new Tag(name, buffer, size)); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Tag::Clone(const Tag &src, bool recursive)
{
Free();
value = src.GetValue();
if (recursive)
ListForeachPtr(Tag *, ct, src.GetTags())
AddChild(ct->Clone(true));
return true;
}
Tag *Tag::Clone(bool recursive) const
{
Tag *clone = new Tag(name);
if (!clone)
return NULL;
// Copy tag content.
clone->GetValue() = value;
// Clone children.
if (recursive)
ListForeachPtr(Tag *, ct, tags)
clone->AddChild(ct->Clone(true));
return clone;
}
uint Tag::DeleteChildren(const char *filter)
{
uint count = 0;
if (filter)
{
String _filter(filter);
ListForeachPtr(Tag *, t, tags)
if (t->name == _filter)
{
tags.Remove(t);
_safe_delete(t);
count++;
}
}
else
ListDeleteAllPtr(Tag *, tags)
return count;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Tag::Free()
{
value.Free();
DeleteChildren();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Tag::~Tag()
{ Free(); }
//------------------------------------------------------------------------------