225 lines
6.7 KiB
C++
225 lines
6.7 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#ifndef __NMETALANG__
|
|
#define __NMETALANG__
|
|
|
|
|
|
#include "data/nvariant.h"
|
|
#include "container/nlist.h"
|
|
|
|
|
|
namespace GS {
|
|
namespace IO { class Handle; }
|
|
|
|
namespace NML {
|
|
class Tag;
|
|
class File;
|
|
|
|
static const int version = 1;
|
|
|
|
/// Metatag.
|
|
class Tag
|
|
{
|
|
friend struct Parser;
|
|
friend class File;
|
|
|
|
protected:
|
|
|
|
/// Locate a tag through its path.
|
|
static Tag *GetTagEx(const List <Tag *> &tag, const char *path, const File *root = 0, bool verbose = false);
|
|
|
|
List <Tag *> tags;
|
|
|
|
Variant value;
|
|
|
|
public:
|
|
|
|
NPLACEMENT_NEW(Metatag)
|
|
|
|
String name;
|
|
|
|
/// Get this tag parent by exploring a given tag hierarchy.
|
|
Tag *GetParent(Tag *) const;
|
|
|
|
/// Get value.
|
|
Variant &GetValue() { return value; }
|
|
const Variant &GetValue() const { return value; }
|
|
|
|
/// Remove a child tag from this tag.
|
|
bool RemoveTag(Tag *t) { return tags.Remove(t); }
|
|
/// Delete all child tags.
|
|
uint DeleteChildren(const char *filter = 0);
|
|
/// Get child count.
|
|
uint GetChildCount() const { return tags.GetCount(); }
|
|
/// Return the tag children list.
|
|
const List <Tag *> &GetTags() const { return tags; }
|
|
|
|
/// Add child to tag.
|
|
Tag *AddChild(Tag *);
|
|
Tag *AddChild(const char *);
|
|
Tag *AddChild(const char *, bool);
|
|
Tag *AddChild(const char *, int);
|
|
Tag *AddChild(const char *, uint);
|
|
Tag *AddChild(const char *, float);
|
|
Tag *AddChild(const char *, const char *);
|
|
Tag *AddChild(const char *, void *, size_t);
|
|
|
|
/// Return tag child.
|
|
Tag *GetTag(const char *path, const File * = 0, bool verbose = false) const;
|
|
/// Return the tag at a given path only if it matches the required type.
|
|
Tag *GetTypedTag(const char *path, Variant::Type, const File * = 0, bool verbose = false) const;
|
|
|
|
bool GetBool() const { bool v; if (value.Get(v)) return v; return false; }
|
|
int GetInteger() const { return value.i_value; }
|
|
uint GetUnsigned() const { return value.u_value; }
|
|
const char *GetString() const { return value.s_value; }
|
|
float GetReal() const { return value.f_value; }
|
|
|
|
void SetBool(bool v) { value = v; }
|
|
void SetInteger(int v) { value = v; }
|
|
void SetUnsigned(uint v) { value = v; }
|
|
void SetString(const char *v) { value = v; }
|
|
void SetReal(float v) { value = v; }
|
|
|
|
Variant::Type GetType() const { return value.GetType(); }
|
|
|
|
/// Clone a tag and optionally recurse and clone its children.
|
|
bool Clone(const Tag &src, bool recursive = true);
|
|
/// Clone this tag and optionally recurse and clone its children.
|
|
Tag *Clone(bool recursive = true) const;
|
|
|
|
/// Free the tag data, set its type to nVariant::VariantNone.
|
|
void Free();
|
|
|
|
Tag() {}
|
|
Tag(const char *n) : name(n) {}
|
|
Tag(const char *n, bool v) : name(n), value(v) {}
|
|
Tag(const char *n, int v) : name(n), value(v) {}
|
|
Tag(const char *n, uint v) : name(n), value(v) {}
|
|
Tag(const char *n, float v) : name(n), value(v) {}
|
|
Tag(const char *n, const char *v) : name(n), value(v) {}
|
|
Tag(const char *n, void *data, size_t size) : name(n), value(data, size) {}
|
|
|
|
~Tag();
|
|
};
|
|
|
|
/*!
|
|
@short Meta file.
|
|
|
|
A metafile contain the whole database in memory.
|
|
This class is not meant to be used with heavy databases.
|
|
|
|
Tags can be accessed using tag paths. A tag path is formatted as follow:
|
|
"root:node:...:tag;".
|
|
|
|
@note The closing hyphen is not required but warnings will be sent to the
|
|
log if you don't use it. The node delimiter ':' can be repeated any
|
|
number of time between nodes with no effect (eg: ":::node1::node2:;").
|
|
By definition a file is a node tag and cannot have a value.
|
|
|
|
@author Emmanuel Julien (ejulien@gsworks.fr)
|
|
*/
|
|
class File
|
|
{
|
|
friend struct Parser;
|
|
|
|
public:
|
|
|
|
enum Binary
|
|
{
|
|
Binary_UU = 0, ///< UUEncoded.
|
|
Binary_yEnc ///< yEncoded.
|
|
};
|
|
|
|
protected:
|
|
|
|
List <Tag *> tags;
|
|
Binary binary_method; ///< Binary encoding method.
|
|
|
|
public:
|
|
|
|
String name;
|
|
|
|
/// Get the file ASCII binary encoding method.
|
|
Binary GetBinaryMethod() const { return binary_method; }
|
|
|
|
const List <Tag *> &GetTags() const { return tags; }
|
|
|
|
uint GetRootCount() const { return tags.GetCount(); }
|
|
|
|
void Clear() { ListDeleteAllPtr(Tag *, tags); }
|
|
bool isEmpty() const { return asbool(GetRootCount() == 0); }
|
|
|
|
/// Add a root tag to the file.
|
|
Tag *AddRoot(Tag *);
|
|
Tag *AddRoot(const char *);
|
|
Tag *AddRoot(const char *, bool);
|
|
Tag *AddRoot(const char *, int);
|
|
Tag *AddRoot(const char *, float);
|
|
Tag *AddRoot(const char *, const char *);
|
|
Tag *AddRoot(const char *, void *, size_t);
|
|
|
|
/// Unlink a root tag from file.
|
|
bool UnlinkRoot(Tag *);
|
|
|
|
/// Return the tag at a given path.
|
|
Tag *GetTag(const char *path, bool verbose = false) const
|
|
{ return Tag::GetTagEx(tags, path, this, verbose); }
|
|
|
|
/// Return the tag at a given path only if it match the required type.
|
|
Tag *GetTypedTag(const char *path, Variant::Type, bool verbose = false) const;
|
|
|
|
bool GetBool(const char *path, bool _default = false, bool verbose = false) const;
|
|
int GetInteger(const char *path, int _default = -1, bool verbose = false) const;
|
|
float GetReal(const char *path, float _default = -1.f, bool verbose = false) const;
|
|
const char *GetString(const char *path, const char *_default = 0, bool verbose = false) const;
|
|
|
|
/// Duplicate the structure of a source file into this file.
|
|
void Import(const File &, bool clear_before_import = true);
|
|
/// Clone a file and all its tags.
|
|
File *Clone() const;
|
|
|
|
void Free();
|
|
|
|
File() : binary_method(Binary_yEnc) {}
|
|
~File();
|
|
};
|
|
|
|
/*!
|
|
@short Meta file parser.
|
|
@author Emmanuel Julien (ejulien@gsworks.fr)
|
|
*/
|
|
struct Parser
|
|
{
|
|
static const char *ParseTagPreprocessorDirective(Tag &tag, const char *s, const char *e);
|
|
|
|
static bool IsMetafile(const char *);
|
|
|
|
static bool SaveBinaryTag(IO::Handle &, const Tag &, File::Binary = File::Binary_yEnc);
|
|
static bool SaveTag(IO::Handle &, const Tag &, File::Binary = File::Binary_yEnc, uint idt = 0);
|
|
|
|
static bool ParseTag(Tag &, const char *s, const char *e, const char **r = 0);
|
|
|
|
static bool LoadFromMemory(const char *, size_t, File &);
|
|
static File *Load(const char *, bool verbose = true);
|
|
static bool Load(const char *, File &, bool verbose = true);
|
|
|
|
static bool Save(IO::Handle &, const File &);
|
|
static bool Save(const char *, const File &);
|
|
static bool SaveBinary(IO::Handle &, const File &);
|
|
static bool SaveBinary(const char *, const File &);
|
|
};
|
|
|
|
#define NMLTagForeach(__I__, __T__) ListForeachPtr(GS::NML::Tag *, __I__, (__T__).GetTags())
|
|
#define NMLFileForeach(__I__, __F__) ListForeachPtr(GS::NML::Tag *, __I__, (__F__).GetTags())
|
|
|
|
} // NML
|
|
} // GS
|
|
|
|
|
|
#endif // __NMETALANG__
|