aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/include/G3D/Any.h
blob: 25af58d1ec3c6ed98d6dff2cd83eb36da9ba6875 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
/**
 \file Any.h
  
 \author Morgan McGuire, Shawn Yarbrough, and Corey Taylor
 \maintainer Morgan McGuire
  
 \created 2006-06-11
 \edited  2013-03-29

 Copyright 2000-2013, Morgan McGuire.
 All rights reserved.
 */

#ifndef G3D_Any_h
#define G3D_Any_h

#include "G3D/platform.h"
#include "G3D/Table.h"
#include "G3D/Array.h"
#include "G3D/AtomicInt32.h"
#include "G3D/stringutils.h"
#include <string>

// needed for Token
#include "G3D/TextInput.h"
#include "G3D/TextOutput.h"

#ifdef verify
#undef verify
#endif

namespace G3D {

class TextOutput;

/** 
\brief 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.

\section Example
Sample File:
<pre>
{
   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")
}
</pre>

Sample code using Any:
<pre>
Any x;
x.load("ball.txt");
if (x["shape"].string() == "round") {
    x["density"] = 3;
}
x.save("ball.txt");
</pre>

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:

<pre>
Any x(Any::ARRAY);
x.array().append(x);    // don't do this!
</pre>

although no exception will be thrown at runtime during that append.

\section includes

When parsing an Any from a file, the syntax 
<code>\#include(<i>filename</i>)</code> allows subsitution of the contents of
<i>filename</i> 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.

\section Parsing

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:

<pre>
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"];
    }
}
</pre>

It is often convenient to iterate through the table portion using G3D::AnyTableReader.

\section BNF
Serialized format BNF:

\htmlonly
<pre>
identifier  ::= (letter | "_") (letter | digit | "_")*
identifier-op ::= "::" | "->" | "."

identifier-exp ::= [identifier-op] identifier (identifier-op identifier)*

comment     ::= C++ single or multi-line comments
separator   ::= "," | ";"

number      ::= <legal C printf number format>
string      ::= <legal C double-quoted or unquoted string; backslashes must be escaped>
boolean     ::= "True" | "False"
nil         ::= "Nil" <not case sensitive> | "None" <case sensitive>
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)
</pre>
\endhtmlonly

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., <code>"[ printf("hello world."); clearScreen();]"</code> 
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.

\sa G3D::AnyTableReader
*/
class Any {
public:

    enum Type {NIL, BOOLEAN, NUMBER, STRING, ARRAY, TABLE, EMPTY_CONTAINER};

    static std::string toString(Type t);

    /** Where an Any came from in a file.  Useful for throwing parsing errors */
    class Source {
    public:
        std::string                 filename;
        int                         line;
        int                         character;

        Source() : line(0), character(0) {}

        void set(const TextInput& ti, const Token& t) {
            filename  = ti.filename();
            line      = t.line();
            character = t.character();
        }
    };

    typedef Array<Any> AnyArray;
    typedef Table<std::string, Any> AnyTable;

private:

    /** Called from deserialize() */
    static void deserializeComment(TextInput& ti, Token& token, std::string& comment);

    /** NIL, BOOLEAN, and NUMBER are stored directly in the Any */
    union SimpleValue {
        bool                        b;
        double                      n;

        inline SimpleValue() : n(0.0) {}
        inline SimpleValue(bool x) : b(x) {}
        inline SimpleValue(double x) : n(x) {}
    };
 
    /** The three options for Data::bracket */
    static const char* PAREN;
    static const char* BRACKET;
    static const char* BRACE;

    class Data {
    public:
        /** ARRAY, TABLE, or STRING value only.  NULL otherwise. */
        union Value {
            std::string*             s;
            Array<Any>*              a;
            AnyTable*                t;
            inline Value() : s(NULL) {}
        };

        // Needed so that the destructor knows what is in Value
        // and can call its destructor. 
        Type                         type;
        
        /** Always points to memory that is allocated with the Data, so
           the destructor does not delete this. */
        Value                        value;
        
        std::string                  comment;

        std::string                  name;

        /** If this Any was created by parsing an #include expression and
            has not been modified since, this is the original comment and
            include statement, as 
            it originally appeared in the file (e.g., it may contain a relative 
            filename).  If this is non-empty, then when serialized, this
            Any will turn into an #include expression instead of unparsing
            its contents of the any.         
          */
        std::string                  includeLine;

        /** For STRING, ARRAY and TABLE types, m_value is shared between
            multiple instances.  Mutation is allowed only if the reference
            count is exactly 1, otherwise the mutating instance must copy
            the value.  This is not used for other types.
        */
        AtomicInt32                  referenceCount;

        Source                       source;

        /** Two-character string of "{}", "[]", or "()"; to be used when unparsing. */
        const char*                  bracket;

        /** ';' or ',' separator to be used when unparsing */
        char                         separator;

    private:

        /** Called by create() */
        inline Data(Type t, const char* b, char s) : type(t), referenceCount(1), bracket(b), separator(s) {}

        /** Called by destroy */
        ~Data();

    public:

        /** Clones the argument */
        static Data* create(const Data* d);
        static Data* create(Type t, const char* b = NULL, char s = '\0');

        /** Free d, invoking its destructor and freeing the memory for
            the value. */
        static void destroy(Data* d);
    };

    /** 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.
    */
    std::string         m_placeholderName;

    Type                m_type;
    SimpleValue         m_simpleValue;
    mutable Data*       m_data;

    /** Called before every read operation. */
    void beforeRead() const;

    /** Called before every write operation to this Any.  Wipes the placeholder
        status and includedFrom entry. */
    void beforeWrite();

    /** Decrements the reference count (if there is one).  If the
    reference count is zero after decrement, calls delete on @a m_data
    and sets it to NULL.
    */
    void dropReference();

    /** Allocate the Data object if it does not exist */
    void ensureData();

    /** 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.*/    
    void ensureMutable();

    /** 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().*/
    void deserializeBody(TextInput& ti, Token& token);

    void deserialize(TextInput& ti, Token& token);

    /** Read the name of a named Array or Table. */
    static void deserializeName(TextInput& ti, Token& token, std::string& name);
    
    /** 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. */
    static void readUntilSeparatorOrClose(TextInput& ti, Token& token);

    /** Construct an Any that is a proxy for a table fetch from \a data.
     This proxy can be copied exactly once on return from operator[].*/
    Any(const std::string& key, Data* data);

    bool isPlaceholder() const {
        return ! m_placeholderName.empty();
    }
    
    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);

public:

    /** Thrown by operator[] when a key is not present in a const table. */
    class KeyNotFound : public ParseError {
    public:
        std::string key;

        KeyNotFound(const Data* data) {
            if (data) {
                filename  = data->source.filename;
                line      = data->source.line;
                character = data->source.character;
            }
        }
    };

    /** Thrown by operator[] when an array index is not present. */
    class IndexOutOfBounds : public ParseError {
    public:
        int     index;
        int     size;
        IndexOutOfBounds() : index(0), size(0) {}
        IndexOutOfBounds(const Data* data, int i, int s) : index(i), size(s) {
            if (data) {
                filename  = data->source.filename;
                line      = data->source.line;
                character = data->source.character;
            }
            message = format("Index out of bounds: index = %d, array size = %d", i, s);
        }
    };

    /** NIL constructor */
    Any();

    /** Deserialize */
    explicit Any(TextInput& t);

    Any(const Any& x);

    /** NUMBER constructor */
    explicit Any(double x);

    explicit Any(float x);

    #if defined(G3D_32Bit) || defined(_MSC_VER)
    /** NUMBER constructor */
    explicit Any(int64 x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {}
	#endif

    /** NUMBER constructor */
    explicit Any(long x);

    /** NUMBER constructor */
    explicit Any(int x);

    /** NUMBER constructor */
    explicit Any(char x);

    /** NUMBER constructor */
    explicit Any(short x);

    /** BOOLEAN constructor */
    explicit Any(bool x);

    /** STRING constructor */
    explicit Any(const std::string& x);

    /** STRING constructor */
    explicit Any(const char* x);

    /** \a t must be ARRAY or TABLE
        \param brackets must be "" (defaults to {} for table, () for array), "[]", "()", or "{}"
        \param separator must be ';', ',', or '\0' (defaults to ',' for array and ';' for table)
    */  
    explicit Any(Type t, const std::string& name = "", const std::string& brackets = "", const char separator = '\0');

    /** Extensible constructor: call the toAny() method of any class. */
    template<class T>
    explicit Any(const T& v) : m_type(NIL), m_data(NULL) {
        *this = v.toAny();
    }

    ~Any();

    /** Removes the comment and name */
    Any& operator=(const Any& x);

    /** \a t must be ARRAY, TABLE, or NIL. Removes the comment and name */
    Any& operator=(Type t);

    /** Assigns from an array.  Assumes that T can be converted to Any.  Removes the comment and name */
    template<class T>
    Any& operator=(const Array<T>& array) {
        *this = Any::ARRAY;
        resize(array.size());
        for (int i = 0; i < array.size(); ++i) {
            this->operator [](i) = array[i];
        }
        return *this;
    }

    /** Removes the comment and name */
    template<class T>
    Any& operator=(const T& v) {
        *this = Any(v);
        return *this;
    }

    Type type() const;

    /** Same as deserialize or load, but operates on a string instead
        of a stream or file.

      \sa deserialize, load, unparse
      */
    static Any parse(const std::string& src);

    std::string unparse(const TextOutput::Settings& s = TextOutput::Settings()) const;

    /** \param 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. */
    std::string unparseJSON(const TextOutput::Settings& s = TextOutput::Settings(), bool allowCoercion = true) const;
    
    /** Comments appear before values when they are in serialized form.*/
    const std::string& comment() const;
    void setComment(const std::string& c);

    /** True if this is the NIL value */
    bool isNil() const;

    /** Throws a ParseError exception if this is not a number */
    double number() const;
    float floatValue() const;

    const std::string& string() const;
    bool boolean() const;

    /** If a valid string, takes the string value and creates a fully
        qualified filename.

        The file is searched for the following ways:
        
        - In the directory from which the Any was loaded.
        - By calling System::findDataFile as you would with other data files.

        Strings that begin with '<' and end with '>' are treated as
        escape sequences and are returned unmodifed.
     */
    std::string resolveStringAsFilename(bool errorIfNotFound = true) const;

    /** If this is named ARRAY or TABLE, returns the name. */
    const std::string& name() const;

    /** If this is named ARRAY or TABLE, returns true if the name
        begins with \a s.  The comparision is case insensitive. */
    bool nameBeginsWith(const std::string& s) const;

    /** If this is named ARRAY or TABLE, returns true if the name
        begins with \a s.  The comparision is case insensitive. */
    bool nameBeginsWith(const char* s) const;

    /** If this is named ARRAY or TABLE, returns true if the name is
        \a s.  The comparision is case insensitive. */
    bool nameEquals(const std::string& s) const;

    /** If this is named ARRAY or TABLE, returns true if the name is\a
        s.  The comparision is case insensitive. */
    bool nameEquals(const char* s) const;

    /** \brief Set the name used when serializing an ARRAY or TABLE.
    
       Only legal for ARRAY or TABLE.  The \a name must begin with a letter
       and contain only letters, numbers, underscores and scope operators.

        <pre>
        a2z
        hello
        Foo::bar
        color.red
        this->that
        __x
        </pre>
        
                
        The scope operators "::", "->", and
        ".", may have spaces around them.  The name may not
        contain parentheses.
    */
    void setName(const std::string& name);

    /** Number of elements if this is an ARRAY or TABLE */
    int size() const;
    int length() const;

    /** For an array, returns the ith element */
    const Any& operator[](int i) const;
    Any& operator[](int i);

    const Any& last() const {
        return (*this)[size() - 1];
    }

    Any& last() {
        return (*this)[size() - 1];
    }

    /** Directly exposes the underlying data structure for an ARRAY. */
    const Array<Any>& array() const;

    template<class T0>
    void append(const T0& v0) {
        _append(Any(v0));
    }

    template<class T0, class T1>
    void append(const T0& v0, const T1& v1) {
        _append(Any(v0), Any(v1));
    }

    template<class T0, class T1, class T2>
    void append(const T0& v0, const T1& v1, const T2& v2) {
        _append(Any(v0), Any(v1), Any(v2));
    }

    template<class T0, class T1, class T2, class T3>
    void append(const T0& v0, const T1& v1, const T2& v2, const T3& v3) {
        _append(Any(v0), Any(v1), Any(v2), Any(v3));
    }

    /** Directly exposes the underlying data structure for table.
    \sa G3D::AnyTableReader*/
    const Table<std::string, Any>& table() const;

    /** For a table, returns the element for \a key. Throws KeyNotFound
        exception if the element does not exist.
       */ 
    const Any& operator[](const std::string& key) const;

    // Needed to prevent the operator[](int) overload from catching
    // string literals
    const Any& operator[](const char* key) const {
        return operator[](std::string(key));
    }

    /** 
        Fetch an element from a table.  This can be used as:

        <pre>
        a["key"] = value;  (create the key if it did not exist)
        </pre>
        
        or

        <pre>
        value = a["key"];  (throw an error if the key did not exist)
        </pre>

        <b>Note:</b>
        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.
     */
    Any& operator[](const std::string& key);

    /** \copydoc Any::operator[](const std::string&) */
    inline Any& operator[](const char* key) {
        return operator[](std::string(key));
    }
    
    /** For a table, returns the element for key \a x and \a
        defaultVal if it does not exist. */
    template<class T>
    Any get(const std::string& key, const T& defaultVal) const {
        return _get(key, Any(defaultVal));
    }

    /** Returns true if this key is in the TABLE.  Illegal to call on an object that is not a TABLE. */
    bool containsKey(const std::string& key) const;
    
    /** For a table, assigns the element for key k. */
    template<class T>
    void set(const std::string& key, const T& val) {
        _set(key, Any(val));
    }

    /** for an ARRAY, resizes and returns the last element */
    Any& next();

    /** 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. */
    std::string sourceDirectory() const;

    /** True if the Anys are exactly equal, ignoring comments.  Applies deeply on arrays and tables. */
    bool operator==(const Any& x) const;

    bool operator==(const std::string& s) const {
        return *this == Any(s);
    }

    bool operator==(const double& v) const {
        return *this == Any(v);
    }

    bool operator==(int v) const {
        return *this == Any(v);
    }

    bool operator==(bool v) const {
        return *this == Any(v);
    }

    bool operator!=(const Any& x) const;

    bool operator!=(const std::string& s) const {
        return *this != Any(s);
    }

    bool operator!=(const double& v) const {
        return *this != Any(v);
    }

    bool operator!=(int v) const {
        return *this != Any(v);
    }

    bool operator!=(bool v) const {
        return *this != Any(v);
    }

    operator int() const;
    operator uint32() const;
    operator float() const;
    operator double() const;
    operator bool() const;
    operator std::string() const;

    operator char() const {
        return char(int(*this));
    }

    operator uint8() const {
        return uint8(int(*this));
    }

    operator int16() const {
        return int16(int(*this));
    }

    operator uint16() const {
        return uint16(int(*this));
    }

    /** Resize to \a n elements, where new elements are NIL 
       It is an error to call this method if this is not an Any::ARRAY */
    void resize(int n);

    /** 
       Clears all entries.
       This must be a TABLE or ARRAY */
    void clear();

    /** Parse from a file.
     \sa deserialize, parse, fromFile, loadIfExists
     */
    void load(const std::string& filename);

    /** Load a new Any from \a filename. \sa load, save, loadIfExists */
    static Any fromFile(const std::string& filename);

    /** Load \a filename file if it exists, otherwise do not modify this */
    void loadIfExists(const std::string& filename);

    /** Uses the serialize method. */
    void save(const std::string& filename) const;

    void serialize(TextOutput& to, bool json = false, bool coerce = false) const;

    void serialize(class BinaryOutput& b) const;

    /** Parse from a stream.
     \sa load, parse */
    void deserialize(TextInput& ti);

    void deserialize(class BinaryInput& b);

    const Source& source() const;

    /** Removes this key from the Any, which must be a table. */
    void remove(const std::string& key);

    /** Removes this key from the Any, which must be an array, and
        shifts other elements down to maintain order. */
    void remove(int index);
   
    /** Throws a ParseError if \a value is false.  Useful for quickly
        creating parse rules in classes that deserialize from Any.
    */
    void verify(bool value, const std::string& message = "") const;


    /** Verifies that the name is identifier \a n (case sensitive). 
        It may contain identifier operators after this */
    void verifyName(const std::string& n) const;

    /** Verifies that the name is identifier \a n or \a m (case sensitive). 
        It may contain identifier operators after this */
    void verifyName(const std::string& n, const std::string& m) const;

    /** Verifies that the name is identifier \a n or \a m or \a p (case sensitive). 
        It may contain identifier operators after this */
    void verifyName(const std::string& n, const std::string& m, const std::string& p) const;

    /** Verifies that the name is identifier \a n or \a m or \a p or \a q (case sensitive). 
        It may contain identifier operators after this */
    void verifyName(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const;

    /** Verifies that the name <i>begins with</i> identifier \a n (case sensitive). 
        It may contain identifier operators after this */
    void verifyNameBeginsWith(const std::string& n) const;

    /** Verifies that the name <i>begins with</i> identifier \a n or \a m (case sensitive). 
        It may contain identifier operators after this */
    void verifyNameBeginsWith(const std::string& n, const std::string& m) const;

    /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p (case sensitive). 
        It may contain identifier operators after this */
    void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p) const;

    /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q (case sensitive). 
        It may contain identifier operators after this */
    void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const;

    /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q or \a r (case sensitive). 
        It may contain identifier operators after this */
    void 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 <i>begins with</i> identifier \a n or \a m or \a p or \a q or \a r or \a s (case sensitive). 
        It may contain identifier operators after this */
    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;

    /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q or \a r or \a s or \a t(case sensitive). 
        It may contain identifier operators after this */
    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;

    /** Verifies that the type is \a t. */
    void verifyType(Type t) const;

    /** Throws an exception if the type is not \a t0 or \a t1. */
    void verifyType(Type t0, Type t1) const;

    /** Verifies that the size is between \a low and \a high, inclusive */
    void verifySize(int low, int high) const;

    /** Verifies that the size is exactly \a s */
    void verifySize(int s) const;

    /** Assumes that Any(T) is well-defined, e.g., by T defining a
        T::toAny() method. */
    template<class T>
    explicit Any(const Array<T>& array, const std::string& name = "") : m_type(ARRAY), m_data(NULL) {
        setName(name);
        resize(array.size());
        for (int i = 0; i < array.size(); ++i) {
            (*this)[i] = Any(array[i]);
        }
    }

    /** Assumes that T defines T(const Any&) */
    template<class T>
    void getArray(Array<T>& array) const {
        verifyType(ARRAY);
        array.resize(size());
        for (int i = 0; i < array.size(); ++i) {
            array[i] = T((*this)[i]);
        }
    }

    /** Assumes that T defines T(const Any&) */
    template<class T>
    void getTable(Table<std::string, T>& table) const {
        verifyType(TABLE);
        for (Table<std::string, Any>::Iterator it = this->table().begin(); it.isValid(); ++it) {
            table.set(it.key(), T(it.value()));
        }
    }

private:

    void deserializeTable(TextInput& ti);
    void deserializeArray(TextInput& ti,const std::string& term);

    /** Turns an empty container into a table or an array */
    void become(const Type& t);

};    // class Any




/**
   Convenient iteration over the keys of a Any::TABLE, usually
   for implementing construction of an object from an Any.

   Getting an element using either iteration or explicit requests
   consumes that element from the iterator (but not from the Any!)
   It is an error to consume the same element more than once from
   the same iterator.

    \code
    AnyTableReader r(a);
    r.getIfPresent("enabled", enabled);
    r.getIfPresent("showSamples", showSamples);
    r.get("showTiles", showTiles);

    r.verifyDone();
    \endcode

    \beta
*/
class AnyTableReader {
private:
   Any              m_any;
   Set<std::string> m_alreadyRead;
public:
    
    /** Verifies that \a is a TABLE with the given \a name. */
    AnyTableReader(const std::string& name, const Any& a);

    /** Verifies that \a is a TABLE. */
    AnyTableReader(const Any& a);

    bool hasMore() const {
        return m_any.size() > m_alreadyRead.size();
    }

    /** Verifies that all keys have been read. */
    void verifyDone() const;

    /** Return the underlying Any. */
    const Any& any() const {
        return m_any;
    }

#if 0
    /** Returns the current key */
    const std::string& key() const;

    /** Returns the current value */
    const Any& value() const;

    AnyKeyIterator& operator++();
#endif   

    /** \copydoc get(const std::string& s, ValueType& v) */
    void get(const std::string& s, std::string& v) {
        v = m_any[s].string();
        m_alreadyRead.insert(s);
    }

    /** \copydoc get(const std::string& s, ValueType& v) */
    void get(const std::string& s, uint8& v) {
        v = uint8(m_any[s].number());
        m_alreadyRead.insert(s);
    }

    /** \copydoc get(const std::string& s, ValueType& v) */
    void get(const std::string& s, uint16& v) {
        v = uint16(m_any[s].number());
        m_alreadyRead.insert(s);
    }

    /** Read an entire array at once.*/
    template<class T>
    void get(const std::string& s, Array<T>& v) {
        m_any[s].getArray(v);
        m_alreadyRead.insert(s);
    }
    
    template<class T>
    void get(const std::string& s, Table<std::string, T>& v) {
        m_any[s].getTable(v);
        m_alreadyRead.insert(s);
    }

    /** If key \a s appears in the any, reads its value into \a v and 
        removes that key from the ones available to iterate over.

        If key \a s does not appear in the any, throws a G3D::ParseError.

        Assumes that if key \a s appears in the any it has not already been extracted
        by this iterator.  If it has been read before, an assertion will fail in debug mode.

      */
    template<class ValueType>
    void get(const std::string& s, ValueType& v) {
        v = ValueType(m_any[s]);
        m_alreadyRead.insert(s);
    }

    /** Same as get() */
    const Any& operator[](const std::string& s) {
        m_alreadyRead.insert(s);
        return m_any[s];
    }

    /** Get the value associated with a key only if the key is actually present.
    
        If key \a s appears in the any, reads its value into \a v and 
        removes that key from the ones available to iterate over.

        If key \a s does not appear in the any, does nothing.

        Assumes that if key \a s appears in the any it has not already been extracted
        by this iterator.  If it has been read before, an assertion will fail in debug mode.

        \return True if the value was read.
      */
    template<class ValueType>
    bool getIfPresent(const std::string& s, ValueType& v) {
        if (m_any.containsKey(s)) {
            debugAssertM(! m_alreadyRead.contains(s), "read twice");

            get(s, v);
            return true;
        } else {
            return false;
        }
    }

    /** \return True if \a s is in the table and has not yet been read
        using get() or getIfPresent(). */
    bool containsUnread(const std::string& s) const {
        return m_any.containsKey(s) && ! m_alreadyRead.contains(s);
    }

};

}    // namespace G3D


/**
  \def PARSE_ANY(expression)
  
  \brief Create an G3D::Any from an unquoted string.

  e.g.,
  \code
     Any x = PARSE_ANY( { a = 3.0; b = false; } );
  \endcode
 */
#define PARSE_ANY(x) Any::parse(#x)


#endif