TrinityCore
|
Easy loading and saving of human-readable configuration files. More...
#include <Any.h>
Classes | |
class | Data |
class | IndexOutOfBounds |
class | KeyNotFound |
union | SimpleValue |
class | Source |
Public Types | |
enum | Type { NIL, BOOLEAN, NUMBER, STRING, ARRAY, TABLE, EMPTY_CONTAINER } |
typedef Array< Any > | AnyArray |
typedef Table< std::string, Any > | AnyTable |
Public Member Functions | |
Any () | |
Any (TextInput &t) | |
Any (const Any &x) | |
Any (double x) | |
Any (float x) | |
Any (long x) | |
Any (int x) | |
Any (char x) | |
Any (short x) | |
Any (bool x) | |
Any (const std::string &x) | |
Any (const char *x) | |
Any (Type t, const std::string &name="", const std::string &brackets="", const char separator= '\0') | |
template<class T > | |
Any (const T &v) | |
~Any () | |
Any & | operator= (const Any &x) |
Any & | operator= (Type t) |
template<class T > | |
Any & | operator= (const Array< T > &array) |
template<class T > | |
Any & | operator= (const T &v) |
Type | type () const |
std::string | unparse (const TextOutput::Settings &s=TextOutput::Settings()) const |
std::string | unparseJSON (const TextOutput::Settings &s=TextOutput::Settings(), bool allowCoercion=true) const |
const std::string & | comment () const |
void | setComment (const std::string &c) |
bool | isNil () const |
double | number () const |
float | floatValue () const |
const std::string & | string () const |
bool | boolean () const |
std::string | resolveStringAsFilename (bool errorIfNotFound=true) const |
const std::string & | name () const |
bool | nameBeginsWith (const std::string &s) const |
bool | nameBeginsWith (const char *s) const |
bool | nameEquals (const std::string &s) const |
bool | nameEquals (const char *s) const |
void | setName (const std::string &name) |
Set the name used when serializing an ARRAY or TABLE. More... | |
int | size () const |
int | length () const |
const Any & | operator[] (int i) const |
Any & | operator[] (int i) |
const Any & | last () const |
Any & | last () |
const Array< Any > & | array () const |
template<class T0 > | |
void | append (const T0 &v0) |
template<class T0 , class T1 > | |
void | append (const T0 &v0, const T1 &v1) |
template<class T0 , class T1 , class T2 > | |
void | append (const T0 &v0, const T1 &v1, const T2 &v2) |
template<class T0 , class T1 , class T2 , class T3 > | |
void | append (const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3) |
const Table< std::string, Any > & | table () const |
const Any & | operator[] (const std::string &key) const |
const Any & | operator[] (const char *key) const |
Any & | operator[] (const std::string &key) |
Any & | operator[] (const char *key) |
template<class T > | |
Any | get (const std::string &key, const T &defaultVal) const |
bool | containsKey (const std::string &key) const |
template<class T > | |
void | set (const std::string &key, const T &val) |
Any & | next () |
std::string | sourceDirectory () const |
bool | operator== (const Any &x) const |
bool | operator== (const std::string &s) const |
bool | operator== (const double &v) const |
bool | operator== (int v) const |
bool | operator== (bool v) const |
bool | operator!= (const Any &x) const |
bool | operator!= (const std::string &s) const |
bool | operator!= (const double &v) const |
bool | operator!= (int v) const |
bool | operator!= (bool v) const |
operator int () const | |
operator uint32 () const | |
operator float () const | |
operator double () const | |
operator bool () const | |
operator std::string () const | |
operator char () const | |
operator uint8 () const | |
operator int16 () const | |
operator uint16 () const | |
void | resize (int n) |
void | clear () |
void | load (const std::string &filename) |
void | loadIfExists (const std::string &filename) |
void | save (const std::string &filename) const |
void | serialize (TextOutput &to, bool json=false, bool coerce=false) const |
void | serialize (class BinaryOutput &b) const |
void | deserialize (TextInput &ti) |
void | deserialize (class BinaryInput &b) |
const Source & | source () const |
void | remove (const std::string &key) |
void | remove (int index) |
void | verify (bool value, const std::string &message="") const |
void | verifyName (const std::string &n) const |
void | verifyName (const std::string &n, const std::string &m) const |
void | verifyName (const std::string &n, const std::string &m, const std::string &p) const |
void | verifyName (const std::string &n, const std::string &m, const std::string &p, const std::string &q) const |
void | verifyNameBeginsWith (const std::string &n) const |
void | verifyNameBeginsWith (const std::string &n, const std::string &m) const |
void | verifyNameBeginsWith (const std::string &n, const std::string &m, const std::string &p) const |
void | verifyNameBeginsWith (const std::string &n, const std::string &m, const std::string &p, const std::string &q) const |
void | verifyNameBeginsWith (const std::string &n, const std::string &m, const std::string &p, const std::string &q, const std::string &r) const |
void | verifyNameBeginsWith (const std::string &n, const std::string &m, const std::string &p, const std::string &q, const std::string &r, const std::string &s) const |
void | verifyNameBeginsWith (const std::string &n, const std::string &m, const std::string &p, const std::string &q, const std::string &r, const std::string &s, const std::string &t) const |
void | verifyType (Type t) const |
void | verifyType (Type t0, Type t1) const |
void | verifySize (int low, int high) const |
void | verifySize (int s) const |
template<class T > | |
Any (const Array< T > &array, const std::string &name="") | |
template<class T > | |
void | getArray (Array< T > &array) const |
template<class T > | |
void | getTable (Table< std::string, T > &table) const |
Static Public Member Functions | |
static std::string | toString (Type t) |
static Any | parse (const std::string &src) |
static Any | fromFile (const std::string &filename) |
Private Member Functions | |
void | beforeRead () const |
void | beforeWrite () |
void | dropReference () |
void | ensureData () |
void | ensureMutable () |
void | deserializeBody (TextInput &ti, Token &token) |
void | deserialize (TextInput &ti, Token &token) |
Any (const std::string &key, Data *data) | |
bool | isPlaceholder () const |
void | _append (const Any &v0) |
void | _append (const Any &v0, const Any &v1) |
void | _append (const Any &v0, const Any &v1, const Any &v2) |
void | _append (const Any &v0, const Any &v1, const Any &v2, const Any &v3) |
Any | _get (const std::string &key, const Any &defaultVal) const |
void | _set (const std::string &key, const Any &val) |
void | _parse (const std::string &src) |
void | deserializeTable (TextInput &ti) |
void | deserializeArray (TextInput &ti, const std::string &term) |
void | become (const Type &t) |
Static Private Member Functions | |
static void | deserializeComment (TextInput &ti, Token &token, std::string &comment) |
static void | deserializeName (TextInput &ti, Token &token, std::string &name) |
static void | readUntilSeparatorOrClose (TextInput &ti, Token &token) |
Private Attributes | |
std::string | m_placeholderName |
Type | m_type |
SimpleValue | m_simpleValue |
Data * | m_data |
Static Private Attributes | |
static const char * | PAREN = "()" |
static const char * | BRACKET = "[]" |
static const char * | BRACE = "{}" |
Easy loading and saving of human-readable configuration files.
Any encodes typed, structured data and can serialize it to a human readable format that is very similar to the Python language's data syntax, and fully supports Python's data syntax as well. It is well-suited for quickly creating human-readable file formats, especially since deserialization and serialization preserve comments and an Any can tell you what file and line it came from. The syntax allows most C++ editors to properly highlight Any files, and makes it easy to design little ad-hoc C-like languages in configuration files.
The class is designed so that copying Anys generally is fast, even if it is a large array or table. This is because data is shared between copies until it is mutated, at which point an actual copy occurs.
Sample File:
{ shape = "round",
// in meters radius = 3.7,
position = Vector3(1.0, -1.0, 0.0), video = { format = "RGB8", size = (320, 200)},
material = #include("rocks.mat") }
Sample code using Any:
Any x; x.load("ball.txt"); if (x["shape"].string() == "round") { x["density"] = 3; } x.save("ball.txt");
The custom serialization format was chosen to be terse, easy for humans to read, and easy for machines to parse. It was specifically chosen over formats like XML, YAML, JSON, S-expressions, and Protocol Buffers, although there is no reason you could not write readers and writers for G3D::Any that support those. Any also currently supports the JSON format.
G3D::Any assumes that structures do not contain cycles; it is an error to create a structure like:
Any x(Any::ARRAY); x.array().append(x); // don't do this!
although no exception will be thrown at runtime during that append.
When parsing an Any from a file, the syntax #include(filename)
allows subsitution of the contents of filename for any single expression in an Any. The filename is interpreted relative to the file being parsed, and inside of the included file, relative filenames are interpreted with respect to the included file (and so on, recursively for nested inclusion).
Filenames are resolved with System::resolve and then System::findDataFile if not found, so they may contain environment variables.
The primary use of Any is to create your own text file formats. The Vector3 constructor is a good example of how to use the Any::verify methods to provide good error checking while parsing such formats:
Vector3::Vector3(const Any& any) { any.verifyName("Vector3"); any.verifyType(Any::TABLE, Any::ARRAY); any.verifySize(3);
if (any.type() == Any::ARRAY) { x = any[0]; y = any[1]; z = any[2]; } else { // Table x = any["x"]; y = any["y"]; z = any["z"]; } }
It is often convenient to iterate through the table portion using G3D::AnyTableReader.
Serialized format BNF:
identifier ::= (letter | "_") (letter | digit | "_")* identifier-op ::= "::" | "->" | "." identifier-exp ::= [identifier-op] identifier (identifier-op identifier)* comment ::= C++ single or multi-line comments separator ::= "," | ";" number ::=string ::= boolean ::= "True" | "False" nil ::= "Nil" | "None" array ::= ("(" | "[" | "{") [value (separator value)* [separator] ] (")" | "]" | "}") pair ::= (identifier | string) ("=" | ":") value table ::= ("(" | "[" | "{") [ pair (separator pair)* [separator] ] (")" | "]" | "}") named-array ::= identifier-exp array named-table ::= identifier-exp table include ::= "#" "include" "(" string ")" value ::= [comment] (nil | number | boolean | string | array | table | named-array | named-table | include)
Except for single-line comments, whitespace is not significant. All parsing is case-insensitive.
The include expression pastes the contents of the named file in as if they appeared in the original source. Note that an include expression can only appear in the locations where a value is expected. This means that it cannot yield more than one element of an array and cannot serve as the pair in a table.
The deserializer allows the substitution of [] or {} for () when writing tuples and ";" for ",". These are convenient when mimicing a programming language, e.g., "[ printf("hello world."); clearScreen();]"
parses as an array containing two named arrays within it. The deserializer also allows a trailing comma inside any array or table, which also convenient when commenting out the last element.
The serializer indents four spaces for each level of nesting. Tables are written with the keys in alphabetic order.
typedef Array<Any> G3D::Any::AnyArray |
typedef Table<std::string, Any> G3D::Any::AnyTable |
enum G3D::Any::Type |
Construct an Any that is a proxy for a table fetch from data. This proxy can be copied exactly once on return from operator[].
G3D::Any::Any | ( | ) |
NIL constructor
|
explicit |
Deserialize
|
explicit |
NUMBER constructor
|
explicit |
|
explicit |
NUMBER constructor
|
explicit |
NUMBER constructor
|
explicit |
NUMBER constructor
|
explicit |
NUMBER constructor
|
explicit |
BOOLEAN constructor
|
explicit |
STRING constructor
|
explicit |
STRING constructor
|
explicit |
t must be ARRAY or TABLE
brackets | must be "" (defaults to {} for table, () for array), "[]", "()", or "{}" |
separator | must be ';', ',', or '\0' (defaults to ',' for array and ';' for table) |
|
inlineexplicit |
Extensible constructor: call the toAny() method of any class.
G3D::Any::~Any | ( | ) |
|
inlineexplicit |
Assumes that Any(T) is well-defined, e.g., by T defining a T::toAny() method.
|
private |
|
inline |
|
inline |
|
inline |
Directly exposes the underlying data structure for an ARRAY.
Turns an empty container into a table or an array
|
private |
Called before every read operation.
|
private |
Called before every write operation to this Any. Wipes the placeholder status and includedFrom entry.
bool G3D::Any::boolean | ( | ) | const |
void G3D::Any::clear | ( | ) |
Clears all entries. This must be a TABLE or ARRAY
const std::string & G3D::Any::comment | ( | ) | const |
Comments appear before values when they are in serialized form.
Returns true if this key is in the TABLE. Illegal to call on an object that is not a TABLE.
void G3D::Any::deserialize | ( | TextInput & | ti | ) |
Parse from a stream.
void G3D::Any::deserialize | ( | class BinaryInput & | b | ) |
Read an unnamed a TABLE or ARRAY. Token should be the open paren token; it is the next token after the close on return. Called from deserialize().
|
staticprivate |
Called from deserialize()
|
private |
|
private |
Decrements the reference count (if there is one). If the reference count is zero after decrement, calls delete on m_data and sets it to NULL.
|
private |
Allocate the Data object if it does not exist
|
private |
If m_data is not NULL, ensure that it has a unique reference and contains a valid m_data. This has a race condition if two threads are both trying to modify the same Any simultaneously.
float G3D::Any::floatValue | ( | ) | const |
Load a new Any from filename.
For a table, returns the element for key x and defaultVal if it does not exist.
|
inline |
Assumes that T defines T(const Any&)
|
inline |
Assumes that T defines T(const Any&)
bool G3D::Any::isNil | ( | ) | const |
True if this is the NIL value
|
inlineprivate |
|
inline |
int G3D::Any::length | ( | ) | const |
void G3D::Any::load | ( | const std::string & | filename | ) |
Parse from a file.
void G3D::Any::loadIfExists | ( | const std::string & | filename | ) |
Load filename file if it exists, otherwise do not modify this
const std::string & G3D::Any::name | ( | ) | const |
If this is named ARRAY or TABLE, returns the name.
If this is named ARRAY or TABLE, returns true if the name begins with s. The comparision is case insensitive.
If this is named ARRAY or TABLE, returns true if the name begins with s. The comparision is case insensitive.
If this is named ARRAY or TABLE, returns true if the name is s. The comparision is case insensitive.
If this is named ARRAY or TABLE, returns true if the name iss. The comparision is case insensitive.
Any & G3D::Any::next | ( | ) |
for an ARRAY, resizes and returns the last element
double G3D::Any::number | ( | ) | const |
Throws a ParseError exception if this is not a number
G3D::Any::operator bool | ( | ) | const |
G3D::Any::operator double | ( | ) | const |
G3D::Any::operator float | ( | ) | const |
G3D::Any::operator int | ( | ) | const |
|
inline |
G3D::Any::operator std::string | ( | ) | const |
|
inline |
G3D::Any::operator uint32 | ( | ) | const |
|
inline |
|
inline |
Removes the comment and name
t must be ARRAY, TABLE, or NIL. Removes the comment and name
Assigns from an array. Assumes that T can be converted to Any. Removes the comment and name
Removes the comment and name
True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables.
|
inline |
For an array, returns the ith element
Any & G3D::Any::operator[] | ( | int | i | ) |
For a table, returns the element for key. Throws KeyNotFound exception if the element does not exist.
Fetch an element from a table. This can be used as:
a["key"] = value; (create the key if it did not exist)
or
value = a["key"]; (throw an error if the key did not exist)
Note: In order to cause elements to be correctly created in the first case while still providing "key not found" errors in the second case, the Any returned is a special object that delays the actual fetch until the following assignment or method call. This means that in the event of an error, the exception may be thrown from a line other than the actual fetch. Use the Any::get() or the const Any::operator[]() methods to avoid this behavior and ensure error-checking at fetch time.
Fetch an element from a table. This can be used as:
a["key"] = value; (create the key if it did not exist)
or
value = a["key"]; (throw an error if the key did not exist)
Note: In order to cause elements to be correctly created in the first case while still providing "key not found" errors in the second case, the Any returned is a special object that delays the actual fetch until the following assignment or method call. This means that in the event of an error, the exception may be thrown from a line other than the actual fetch. Use the Any::get() or the const Any::operator[]() methods to avoid this behavior and ensure error-checking at fetch time.
Same as deserialize or load, but operates on a string instead of a stream or file.
Read until a separator is consumed or a close paren is hit, and return that token. Considers the passed in token to be the first value read.
void G3D::Any::remove | ( | const std::string & | key | ) |
Removes this key from the Any, which must be a table.
void G3D::Any::remove | ( | int | index | ) |
Removes this key from the Any, which must be an array, and shifts other elements down to maintain order.
void G3D::Any::resize | ( | int | n | ) |
Resize to n elements, where new elements are NIL It is an error to call this method if this is not an Any::ARRAY
If a valid string, takes the string value and creates a fully qualified filename.
The file is searched for the following ways:
Strings that begin with '<' and end with '>' are treated as escape sequences and are returned unmodifed.
void G3D::Any::save | ( | const std::string & | filename | ) | const |
Uses the serialize method.
void G3D::Any::serialize | ( | TextOutput & | to, |
bool | json = false , |
||
bool | coerce = false |
||
) | const |
void G3D::Any::serialize | ( | class BinaryOutput & | b | ) | const |
For a table, assigns the element for key k.
void G3D::Any::setComment | ( | const std::string & | c | ) |
void G3D::Any::setName | ( | const std::string & | name | ) |
Set the name used when serializing an ARRAY or TABLE.
Only legal for ARRAY or TABLE. The name must begin with a letter and contain only letters, numbers, underscores and scope operators.
a2z hello Foo::bar color.red this->that __x
The scope operators "::", "->", and ".", may have spaces around them. The name may not contain parentheses.
int G3D::Any::size | ( | ) | const |
Number of elements if this is an ARRAY or TABLE
const Any::Source & G3D::Any::source | ( | ) | const |
std::string G3D::Any::sourceDirectory | ( | ) | const |
The parent directory of the location from which this Any was loaded. This is useful for interpreting filenames relative to the Any's source location, which may not match the current directory if the Any was from an included file.
const std::string & G3D::Any::string | ( | ) | const |
Directly exposes the underlying data structure for table.
|
static |
Any::Type G3D::Any::type | ( | ) | const |
std::string G3D::Any::unparse | ( | const TextOutput::Settings & | s = TextOutput::Settings() | ) | const |
std::string G3D::Any::unparseJSON | ( | const TextOutput::Settings & | s = TextOutput::Settings() , |
bool | allowCoercion = true |
||
) | const |
allowCoercion | If false, throws an error if the Any uses features that are not supported by JSON such as named arrays. Otherwise, silently coerces to JSON. |
Throws a ParseError if value is false. Useful for quickly creating parse rules in classes that deserialize from Any.
void G3D::Any::verifyName | ( | const std::string & | n | ) | const |
Verifies that the name is identifier n (case sensitive). It may contain identifier operators after this
Verifies that the name is identifier n or m (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyName | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p | ||
) | const |
Verifies that the name is identifier n or m or p (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyName | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p, | ||
const std::string & | q | ||
) | const |
Verifies that the name is identifier n or m or p or q (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyNameBeginsWith | ( | const std::string & | n | ) | const |
Verifies that the name begins with identifier n (case sensitive). It may contain identifier operators after this
Verifies that the name begins with identifier n or m (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyNameBeginsWith | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p | ||
) | const |
Verifies that the name begins with identifier n or m or p (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyNameBeginsWith | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p, | ||
const std::string & | q | ||
) | const |
Verifies that the name begins with identifier n or m or p or q (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyNameBeginsWith | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p, | ||
const std::string & | q, | ||
const std::string & | r | ||
) | const |
Verifies that the name begins with identifier n or m or p or q or r (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyNameBeginsWith | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p, | ||
const std::string & | q, | ||
const std::string & | r, | ||
const std::string & | s | ||
) | const |
Verifies that the name begins with identifier n or m or p or q or r or s (case sensitive). It may contain identifier operators after this
void G3D::Any::verifyNameBeginsWith | ( | const std::string & | n, |
const std::string & | m, | ||
const std::string & | p, | ||
const std::string & | q, | ||
const std::string & | r, | ||
const std::string & | s, | ||
const std::string & | t | ||
) | const |
Verifies that the name begins with identifier n or m or p or q or r or s or t(case sensitive). It may contain identifier operators after this
void G3D::Any::verifySize | ( | int | low, |
int | high | ||
) | const |
Verifies that the size is between low and high, inclusive
void G3D::Any::verifySize | ( | int | s | ) | const |
Verifies that the size is exactly s
void G3D::Any::verifyType | ( | Type | t | ) | const |
Verifies that the type is t.
Throws an exception if the type is not t0 or t1.
|
staticprivate |
|
staticprivate |
|
mutableprivate |
|
private |
If not empty, this Any was created from operator[] on a table and perhaps was not intended to exist. The name is needed to format the error message if it is read from before it is written to.
The source of a placeholder object is that of the parent object until it is written.
|
private |
|
private |
|
staticprivate |
The three options for Data::bracket