Files
Webcam/include/framework/metafile/nml.h
2026-06-22 11:49:35 +02:00

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__