add Object::remove, some dox, leak debugging code



git-svn-id: http://skia.googlecode.com/svn/trunk@2957 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/utils/SkJSON.h b/include/utils/SkJSON.h
index 44826ac..215d54a 100644
--- a/include/utils/SkJSON.h
+++ b/include/utils/SkJSON.h
@@ -10,6 +10,7 @@
 
 #include "SkTypes.h"
 
+class SkStream;
 class SkString;
 
 class SkJSON {
@@ -26,34 +27,151 @@
     class Array;
     
     class Object {
+    private:
+        struct Slot;
+
     public:
-        Object() : fHead(NULL), fTail(NULL) {}
+        Object();
         Object(const Object&);
         ~Object();
-        
+
+        /**
+         *  Create a new slot with the specified name and value. The name
+         *  parameter is copied, but ownership of the Object parameter is
+         *  transferred. The Object parameter may be null, but the name must
+         *  not be null.
+         */
         void addObject(const char name[], Object* value);
-        void addArray(const char name[], Array* value);
-        void addString(const char name[], const char value[]);
-        void addInt(const char name[], int32_t value);
-        void addFloat(const char name[], float value);
-        void addBool(const char name[], bool value);
         
+        /**
+         *  Create a new slot with the specified name and value. The name
+         *  parameter is copied, but ownership of the Array parameter is
+         *  transferred. The Array parameter may be null, but the name must
+         *  not be null.
+         */
+        void addArray(const char name[], Array* value);
+        
+        /**
+         *  Create a new slot with the specified name and value. Both parameters
+         *  are copied. The value parameter may be null, but the name must
+         *  not be null.
+         */
+        void addString(const char name[], const char value[]);
+        
+        /**
+         *  Create a new slot with the specified name and value. The name
+         *  parameter is copied, and must not be null.
+         */
+        void addInt(const char name[], int32_t value);
+        
+        /**
+         *  Create a new slot with the specified name and value. The name
+         *  parameter is copied, and must not be null.
+         */
+        void addFloat(const char name[], float value);
+        
+        /**
+         *  Create a new slot with the specified name and value. The name
+         *  parameter is copied, and must not be null.
+         */
+        void addBool(const char name[], bool value);
+
+        /**
+         *  Returns true if a slot matching the name and Type is found.
+         */
+        bool find(const char name[], Type) const;
         bool findObject(const char name[], Object** = NULL) const;
         bool findArray(const char name[], Array** = NULL) const;
         bool findString(const char name[], SkString* = NULL) const;
         bool findInt(const char name[], int32_t* = NULL) const;
         bool findFloat(const char name[], float* = NULL) const;
         bool findBool(const char name[], bool* = NULL) const;
-        
-        void dump() const;
-        
+
+        /**
+         *  Finds the first slot matching the name and Type and removes it.
+         *  Returns true if found, false if not.
+         */
+        bool remove(const char name[], Type);
+
+        void toDebugf() const;
+
+        /**
+         *  Iterator class which returns all of the fields/slots in an Object,
+         *  in the order that they were added.
+         */
+        class Iter {
+        public:
+            Iter(const Object&);
+            
+            /**
+             *  Returns true when there are no more entries in the iterator.
+             *  In this case, no other methods should be called.
+             */
+            bool done() const;
+
+            /**
+             *  Moves the iterator to the next element. Should only be called
+             *  if done() returns false.
+             */
+            void next();
+
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false.
+             */
+            Type type() const;
+            
+            /**
+             *  Returns the name of the current element. Should only be called
+             *  if done() returns false.
+             */
+            const char* name() const;
+            
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false and type() returns kObject.
+             */
+            Object* objectValue() const;
+            
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false and type() returns kArray.
+             */
+            Array* arrayValue() const;
+            
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false and type() returns kString.
+             */
+            const char* stringValue() const;
+            
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false and type() returns kInt.
+             */
+            int32_t intValue() const;
+            
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false and type() returns kFloat.
+             */
+            float floatValue() const;
+            
+            /**
+             *  Returns the type of the current element. Should only be called
+             *  if done() returns false and type() returns kBool.
+             */
+            bool boolValue() const;
+
+        private:
+            Slot* fSlot;
+        };
+
     private:
-        struct Slot;
         Slot* fHead;
         Slot* fTail;
         
-        const Slot* findSlot(const char name[]) const;
-        const Slot* findSlotAndType(const char name[], Type) const;
+        const Slot* findSlot(const char name[], Type) const;
         Slot* addSlot(Slot*);
         void dumpLevel(int level) const;
         
@@ -62,26 +180,90 @@
     
     class Array {
     public:
-        // do I support strings, objects, arrays?
+        /**
+         *  Creates an array with the specified Type and element count. All
+         *  entries are initialized to NULL/0/false.
+         */
         Array(Type, int count);
+
+        /**
+         *  Creates an array of ints, initialized by copying the specified
+         *  values.
+         */
         Array(const int32_t values[], int count);
+        
+        /**
+         *  Creates an array of floats, initialized by copying the specified
+         *  values.
+         */
         Array(const float values[], int count);
+        
+        /**
+         *  Creates an array of bools, initialized by copying the specified
+         *  values.
+         */
         Array(const bool values[], int count);
+        
         Array(const Array&);
         ~Array();
         
         int count() const { return fCount; }
         Type type() const { return fType; }
+
+        /**
+         *  Replace the element at the specified index with the specified
+         *  Object (which may be null). Ownership of the Object is transferred.
+         *  Should only be called if the Array's type is kObject.
+         */
+        void setObject(int index, Object*);
         
-        int32_t* ints() const { return fArray.fInts; }
-        float* floats() const { return fArray.fFloats; }
-        bool* bools() const { return fArray.fBools; }
-        
+        /**
+         *  Replace the element at the specified index with the specified
+         *  Array (which may be null). Ownership of the Array is transferred.
+         *  Should only be called if the Array's type is kArray.
+         */
+        void setArray(int index, Array*);
+
+        /**
+         *  Replace the element at the specified index with a copy of the
+         *  specified string (which may be null). Should only be called if the
+         *  Array's type is kString.
+         */
+        void setString(int index, const char str[]);
+
+        Object* const* objects() const {
+            SkASSERT(kObject == fType);
+            return fArray.fObjects;
+        }
+        Array* const* arrays() const {
+            SkASSERT(kObject == fType);
+            return fArray.fArrays;
+        }
+        const char* const* strings() const {
+            SkASSERT(kString == fType);
+            return fArray.fStrings;
+        }
+        int32_t* ints() const {
+            SkASSERT(kInt == fType);
+            return fArray.fInts;
+        }
+        float* floats() const {
+            SkASSERT(kFloat == fType);
+            return fArray.fFloats;
+        }
+        bool* bools() const {
+            SkASSERT(kBool == fType);
+            return fArray.fBools;
+        }
+
     private:
         int fCount;
         Type fType;
         union {
             void*    fVoids;
+            Object** fObjects;
+            Array**  fArrays;
+            char**   fStrings;
             int32_t* fInts;
             float*   fFloats;
             bool*    fBools;