text: #ifndef SCRIPTDICTIONARY_H
  #define SCRIPTDICTIONARY_H
  
  // The dictionary class relies on the script string object, thus the script
  // string type must be registered with the engine before registering the
  // dictionary type
  
  #ifndef ANGELSCRIPT_H 
  // Avoid having to inform include path if header is already include before
  #include <angelscript.h>
  #endif
  
  // By default the CScriptDictionary use the std::string for the keys.
  // If the application uses a custom string type, then this typedef
  // can be changed accordingly.
  #include <string>
  typedef std::string dictKey_t;
  
  // Forward declare CScriptDictValue so we can typedef the internal map type
  BEGIN_AS_NAMESPACE
  class CScriptDictValue;
  END_AS_NAMESPACE
  
  // C++11 introduced the std::unordered_map which is a hash map which is
  // is generally more performatic for lookups than the std::map which is a 
  // binary tree.
  // TODO: memory: The map allocator should use the asAllocMem and asFreeMem
  #if AS_CAN_USE_CPP11
  #include <unordered_map>
  typedef std::unordered_map<dictKey_t, AS_NAMESPACE_QUALIFIER CScriptDictValue> dictMap_t;
  #else
  #include <map>
  typedef std::map<dictKey_t, AS_NAMESPACE_QUALIFIER CScriptDictValue> dictMap_t;
  #endif
  
  
  #ifdef _MSC_VER
  // Turn off annoying warnings about truncated symbol names
  #pragma warning (disable:4786)
  #endif
  
  
  
  
  // Sometimes it may be desired to use the same method names as used by C++ STL.
  // This may for example reduce time when converting code from script to C++ or
  // back.
  //
  //  0 = off
  //  1 = on
  
  #ifndef AS_USE_STLNAMES
  #define AS_USE_STLNAMES 0
  #endif
  
  
  BEGIN_AS_NAMESPACE
  
  class CScriptArray;
  class CScriptDictionary;
  
  class CScriptDictValue
  {
  public:
  	// This class must not be declared as local variable in C++, because it needs 
  	// to receive the script engine pointer in all operations. The engine pointer
  	// is not kept as member in order to keep the size down
  	CScriptDictValue();
  	CScriptDictValue(asIScriptEngine *engine, void *value, int typeId);
  
  	// Destructor must not be called without first calling FreeValue, otherwise a memory leak will occur
  	~CScriptDictValue();
  
  	// Replace the stored value
  	void Set(asIScriptEngine *engine, void *value, int typeId);
  	void Set(asIScriptEngine *engine, const asINT64 &value);
  	void Set(asIScriptEngine *engine, const double &value);
  	void Set(asIScriptEngine *engine, CScriptDictValue &value);
  
  	// Gets the stored value. Returns false if the value isn't compatible with the informed typeId
  	bool Get(asIScriptEngine *engine, void *value, int typeId) const;
  	bool Get(asIScriptEngine *engine, asINT64 &value) const;
  	bool Get(asIScriptEngine *engine, double &value) const;
  
  	// Returns the address of the stored value for inspection
  	const void *GetAddressOfValue() const;
  
  	// Returns the type id of the stored value
  	int  GetTypeId() const;
  
  	// Free the stored value
  	void FreeValue(asIScriptEngine *engine);
  
  	// GC callback
  	void EnumReferences(asIScriptEngine *engine);
  
  protected:
  	friend class CScriptDictionary;
  
  	union
  	{
  		asINT64 m_valueInt;
  		double  m_valueFlt;
  		void   *m_valueObj;
  	};
  	int m_typeId;
  };
  
  class CScriptDictionary
  {
  public:
  	// Factory functions
  	static CScriptDictionary *Create(asIScriptEngine *engine);
  
  	// Called from the script to instantiate a dictionary from an initialization list
  	static CScriptDictionary *Create(asBYTE *buffer);
  
  	// Reference counting
  	void AddRef() const;
  	void Release() const;
  
  	// Reassign the dictionary
  	CScriptDictionary &operator =(const CScriptDictionary &other);
  
  	// Sets a key/value pair
  	void Set(const dictKey_t &key, void *value, int typeId);
  	void Set(const dictKey_t &key, const asINT64 &value);
  	void Set(const dictKey_t &key, const double &value);
  
  	// Gets the stored value. Returns false if the value isn't compatible with the informed typeId
  	bool Get(const dictKey_t &key, void *value, int typeId) const;
  	bool Get(const dictKey_t &key, asINT64 &value) const;
  	bool Get(const dictKey_t &key, double &value) const;
  
  	// Index accessors. If the dictionary is not const it inserts the value if it doesn't already exist
  	// If the dictionary is const then a script exception is set if it doesn't exist and a null pointer is returned
  	CScriptDictValue *operator[](const dictKey_t &key);
  	const CScriptDictValue *operator[](const dictKey_t &key) const;
  
  	// Returns the type id of the stored value, or negative if it doesn't exist
  	int GetTypeId(const dictKey_t &key) const;
  
  	// Returns true if the key is set
  	bool Exists(const dictKey_t &key) const;
  
  	// Returns true if there are no key/value pairs in the dictionary
  	bool IsEmpty() const;
  
  	// Returns the number of key/value pairs in the dictionary
  	asUINT GetSize() const;
  
  	// Deletes the key
  	bool Delete(const dictKey_t &key);
  
  	// Deletes all keys
  	void DeleteAll();
  
  	// Get an array of all keys
  	CScriptArray *GetKeys() const;
  
  	// STL style iterator
  	class CIterator
  	{
  	public:
  		void operator++();    // Pre-increment
  		void operator++(int); // Post-increment
  
  		// This is needed to support C++11 range-for
  		CIterator &operator*();
  
  		bool operator==(const CIterator &other) const;
  		bool operator!=(const CIterator &other) const;
  
  		// Accessors
  		const dictKey_t &GetKey() const;
  		int              GetTypeId() const;
  		bool             GetValue(asINT64 &value) const;
  		bool             GetValue(double &value) const;
  		bool             GetValue(void *value, int typeId) const;
  		const void *     GetAddressOfValue() const;
  
  	protected:
  		friend class CScriptDictionary;
  
  		CIterator();
  		CIterator(const CScriptDictionary &dict,
  		          dictMap_t::const_iterator it);
  
  		CIterator &operator=(const CIterator &) {return *this;} // Not used
  
  		dictMap_t::const_iterator m_it;
  		const CScriptDictionary &m_dict;
  	};
  
  	CIterator begin() const;
  	CIterator end() const;
  	CIterator find(const dictKey_t &key) const;
  
  	// Garbage collections behaviours
  	int GetRefCount();
  	void SetGCFlag();
  	bool GetGCFlag();
  	void EnumReferences(asIScriptEngine *engine);
  	void ReleaseAllReferences(asIScriptEngine *engine);
  
  protected:
  	// Since the dictionary uses the asAllocMem and asFreeMem functions to allocate memory
  	// the constructors are made protected so that the application cannot allocate it 
  	// manually in a different way
  	CScriptDictionary(asIScriptEngine *engine);
  	CScriptDictionary(asBYTE *buffer);
  
  	// We don't want anyone to call the destructor directly, it should be called through the Release method
  	virtual ~CScriptDictionary();
  
  	// Cache the object types needed
  	void Init(asIScriptEngine *engine);
  
  	// Our properties
  	asIScriptEngine *engine;
  	mutable int      refCount;
  	mutable bool     gcFlag;
  	dictMap_t        dict;
  };
  
  // This function will determine the configuration of the engine
  // and use one of the two functions below to register the dictionary object
  void RegisterScriptDictionary(asIScriptEngine *engine);
  
  // Call this function to register the math functions
  // using native calling conventions
  void RegisterScriptDictionary_Native(asIScriptEngine *engine);
  
  // Use this one instead if native calling conventions
  // are not supported on the target platform
  void RegisterScriptDictionary_Generic(asIScriptEngine *engine);
  
  END_AS_NAMESPACE
  
  #endif
  