//---------------------------------------------------------------------
//
// Copyright (C) 2004 Yingle Jia
//
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// AcfCollectionBase.h
//
// Defines basic collecion traits and collection interfaces.
//
#ifndef __Acf_CollectionBase__
#define __Acf_CollectionBase__
namespace Acf {
namespace Collections {
// Collection Traits
// NOTE: reference types shall be stored as RefPtr<X> in collections.
// Collection Traits Naming Convertion:
// - NullxxxTraits: means no-op (or throw)
// - SimplexxxTraits: for simple types like int
// - StructurexxxTraits: for C++ struct types
//---------------------------------------------------------------------
// ArgTypeTraits: controls how to pass arguments
// General types
template <typename T>
class ArgTypeTraits
{
public:
typedef typename ParamType<T>::Type Type; // T or const T&
};
// Specialization for reference types, e.g. String
template <class T>
class ArgTypeTraits<RefPtr<T> >
{
public:
typedef T* Type; // e.g. String*
};
//---------------------------------------------------------------------
// ClearTraits: controls how to clear elements, see Array<T>::Clear
template <typename T>
class NullClearTraits
{
public:
static void Clear(T* p, int count)
{
}
};
template <typename T>
class SimpleClearTraits // works for simple value types
{
public:
static void Clear(T* p, int count)
{
memset(p, 0, count * sizeof(T));
}
};
template <typename T>
class ClearTraits :
public SelectType<IsArithmatic<T>::Value || IsPointer<T>::Value,
SimpleClearTraits<T>, NullClearTraits<T> >::Type
{
};
// Specialization for reference types, e.g. String
template <class T>
class ClearTraits<RefPtr<T> >
{
public:
static void Clear(RefPtr<T>* p, int count)
{
for (int i = 0; i < count; i++)
*(p++) = null; // release the reference
}
};
//---------------------------------------------------------------------
// CompareTraits: controls how to compare elements and generate hash code
// This is called by the default implementation of Comparer<T>.
template <typename T>
class NullCompareTraits
{
public:
static bool Equals(typename ArgTypeTraits<T>::Type a, typename ArgTypeTraits<T>::Type b)
{
ACFASSERT(false); // don't know how to compare
throw InvalidOperationException();
return false;
}
static int Compare(typename ArgTypeTraits<T>::Type a, typename ArgTypeTraits<T>::Type b)
{
ACFASSERT(false); // don't know how to compare
throw InvalidOperationException();
return 0;
}
static int GetHashCode(typename ArgTypeTraits<T>::Type obj)
{
ACFASSERT(false); // do not know how to generate hash code
throw InvalidOperationException();
return 0;
}
};
template <typename T>
class SimpleCompareTraits // for C++ fundamental types, enums and pointers
{
public:
static bool Equals(T a, T b)
{
return (a == b);
}
static int Compare(T a, T b)
{
if (a < b)
return -1;
else if (a == b)
return 0;
else
return 1;
}
static int GetHashCode(T obj)
{
return GetHashCodeImpl(obj);
}
private:
template <typename T>
static int GetHashCodeImpl(T obj) // default for bool, wchar_t, int16, uint16, int32 and uint32
{
return static_cast<int>(obj);
}
template <typename T>
static int GetHashCodeImpl(T* obj)
{
return PtrToLong(obj);
}
static int GetHashCodeImpl(int64 n)
{
return ((int)n) ^ ((int)(n >> 32));
}
static int GetHashCodeImpl(uint64 n)
{
return ((int)n) ^ ((int)(n >> 32));
}
static int GetHashCodeImpl(float f)
{
return *(int*)(&f);
}
static int GetHashCodeImpl(double d)
{
int64 n = *(int64*)(&d);
return ((int)n) ^ ((int)(n >> 32));
}
};
template <class T>
class StructureCompareTraits
{
public:
static bool Equals(const T& a, const T& b)
{
return (a == b); // works for most types
}
static int Compare(const T& a, const T& b)
{
return T::Compare(a, b); // you should provide a static compare method
}
static int GetHashCode(const T& obj)
{
return obj.GetHashCode(); // you should provide an instance hash method
}
};
template <typename T>
class CompareTraits :
public SelectType<IsArithmatic<T>::Value || IsPointer<T>::Value,
SimpleCompareTraits<T>, NullCompareTraits<T> >::Type
{
};
} // namespace Collections
} // namespace Acf
namespace Acf {
template <typename T, int R = 1>
class Array;
} // namespace Acf
namespace Acf {
namespace Collections {
//---------------------------------------------------------------------
// interface IEnumerator
template <typename T>
interface IEnumerator : public InterfaceBase
{
// Properties
__declspec(property(get=get_Current)) T Current;
virtual T get_Current() = 0;
// Methods
virtual bool MoveNext() = 0;
};
//---------------------------------------------------------------------
// interface IEnumerable
template <typename T>
interface IEnumerable : public InterfaceBase
{
// Methods
virtual RefPtr<IEnumerator<T> > GetEnumerator() = 0;
};
//---------------------------------------------------------------------
// interface ICollection
template <typename T>
interface ICollection : public IEnumerable<T>
{
// Declaractions
typedef typename ArgTypeTraits<T>::Type InArgType;
// Properties
// Count
__declspec(property(get=get_Count)) int Count;
virtual int get_Count() = 0;
// IsReadOnly
__declspec(property(get=get_IsReadOnly)) bool IsReadOnly;
virtual bool get_IsReadOnly() = 0;
// Methods
virtual int Add(InArgType value) = 0;
virtual bool Remove(InArgType value) = 0;
virtual void Clear() = 0;
virtual bool Contains(InArgType value) = 0;
virtual void CopyTo(Array<T>* array, int index) = 0;
};
//---------------------------------------------------------------------
// interface IList
template <typename T>
interface IList : public ICollection<T>
{
// Properties
// Item
__declspec(property(get=get_Item, put=set_Item)) T Item[];
virtual T get_Item(int index) = 0;
virtual void set_Item(int index, InArgType value) = 0;
// Methods
virtual int IndexOf(InArgType value) = 0;
virtual void Insert(int index, InArgType value) = 0;
virtual void RemoveAt(int index) = 0;
};
//---------------------------------------------------------------------
// struct KeyValuePair
template <typename K, typename V>
struct KeyValuePair
{
// Fields
public:
K Key;
V Value;
// Constructors
public:
KeyValuePair() // for use in collections
{
}
KeyValuePair(typename ArgTypeTraits<K>::Type key, typename ArgTypeTraits<V>::Type value) :
Key(key), Value(value)
{
}
};
template <typename K, typename V>
class ClearTraits<KeyValuePair<K, V> >
{
public:
static void Clear(KeyValuePair<K, V>* p, int count)
{
for (int i = 0; i < count; i++, p++)
{
ClearTraits<K>::Clear(&p->Key, 1);
ClearTraits<V>::Clear(&p->Value, 1);
}
}
};
//---------------------------------------------------------------------
// interface IDictionary
template <typename K, typename V>
interface IDictionary : public ICollection<KeyValuePair<K, V> >
{
// Declaractions
typedef typename ArgTypeTraits<K>::Type KeyInArgType;
typedef typename ArgTypeTraits<V>::Type ValueInArgType;
// Properties
// Item
__declspec(property(get=get_Item, put=set_Item)) V Item[];
virtual V get_Item(KeyInArgType key) = 0;
virtual void set_Item(KeyInArgType key, ValueInArgType value) = 0;
// Keys
__declspec(property(get=get_Keys)) RefPtr<ICollection<K> > Keys;
virtual RefPtr<ICollection<K> > get_Keys() = 0;
// Values
__declspec(property(get=get_Values)) RefPtr<ICollection<V> > Values;
virtual RefPtr<ICollection<V> > get_Values() = 0;
// Methods
virtual bool ContainsKey(KeyInArgType key) = 0;
virtual void Add(KeyInArgType key, ValueInArgType value) = 0;
virtual bool Remove(KeyInArgType key) = 0;
};
//---------------------------------------------------------------------
// interface IComparable
template <typename T>
interface IComparable : public InterfaceBase
{
typedef typename ArgTypeTraits<T>::Type InArgType;
virtual int CompareTo(InArgType obj) = 0;
virtual bool Equals(InArgType obj) = 0;
};
//---------------------------------------------------------------------
// interface IComparer
template <typename T>
interface IComparer : public InterfaceBase
{
typedef typename ArgTypeTraits<T>::Type InArgType;
virtual int Compare(InArgType a, InArgType b) = 0;
virtual bool Equals(InArgType a, InArgType b) = 0;
virtual int GetHashCode(InArgType obj) = 0;
};
//---------------------------------------------------------------------
// CompareTraits
// Specialization for reference types, e.g. String
template <class T>
class CompareTraits<RefPtr<T> >
{
public:
static bool Equals(T* a, T* b)
{
return Object::Equals(Acf::Internal::GetObject(a),
Acf::Internal::GetObject(b));
}
static int Compare(T* a, T* b)
{
// Check equal reference and null reference
if (a == b)
return 0;
if (a == null)
return -1;
if (b == null)
return 1;
// This will be a compile-time error if T doesn't implement IComparable<RefPtr<T> >
return CompareImpl(a, b);
}
static int GetHashCode(T* obj)
{
ACFASSERT(obj != null);
return Acf::Internal::GetObject(obj)->GetHashCode();
}
private:
static int CompareImpl(IComparable<RefPtr<T> >* a, T* b)
{
return a->CompareTo(b);
}
};
//---------------------------------------------------------------------
// FOREACH
#define __ACF_ENUM_T(c) Enumerator<sizeof(SelectEnumType(c))>
// c: collection or array, cannot be null, cannot be "this"
#define ACF_FOREACH(Type, var, c) \
if (__ACF_ENUM_T(c)::IteratorType __it = __ACF_ENUM_T(c)::BeginEnum(c)) \
for (Type var; __ACF_ENUM_T(c)::MoveNext(c, __it, var); )
#ifndef FOREACH
#define FOREACH ACF_FOREACH
#endif
typedef char (&IEnumerableType)[1];
typedef char (&ArrayType )[2];
template <int>
struct Enumerator; // no body
// Collection (default)
IEnumerableType SelectEnumType(...);
template <>
struct Enumerator<sizeof(IEnumerableType)>
{
public:
typedef RefPtr<InterfaceBase> IteratorType;
template <typename T>
static RefPtr<InterfaceBase> BeginEnum(IEnumerable<T>* c)
{
return c->GetEnumerator();
}
template <typename T>
static RefPtr<InterfaceBase> BeginEnum(const RefPtr<T>& c)
{
return BeginEnum(c.Pointer);
}
template <typename T, typename U>
static bool MoveNext(IEnumerable<T>* c, RefPtr<InterfaceBase>& it, U& var)
{
IEnumerator<T>* enumerator = static_cast<IEnumerator<T>*>(it.Pointer);
if (!enumerator->MoveNext())
return false;
var = enumerator->Current;
return true;
}
template <typename T, typename U>
static bool MoveNext(const RefPtr<T>& c, RefPtr<InterfaceBase>& it, U& var)
{
return MoveNext(c.Pointer, it, var);
}
};
// Array (single-dimensional)
template <typename T>
struct IteratorWrapper
{
T it;
IteratorWrapper(const T& it)
{
this->it = it;
}
operator bool() const
{
return true;
}
};
template <typename T>
ArrayType SelectEnumType(Acf::Array<T>*);
template <typename T>
ArrayType SelectEnumType(const RefPtr<Acf::Array<T> >&);
template <>
struct Enumerator<sizeof(ArrayType)>
{
public:
typedef IteratorWrapper<int> IntIteratorWrapper;
typedef IntIteratorWrapper IteratorType;
template <typename T>
static IntIteratorWrapper BeginEnum(Acf::Array<T>* array)
{
return 0;
}
template <typename T>
static IntIteratorWrapper BeginEnum(const RefPtr<Acf::Array<T> >& array)
{
return BeginEnum(array.Pointer);
}
template <typename T, typename U>
static bool MoveNext(Acf::Array<T>* array, IntIteratorWrapper& itw, U& var)
{
if (itw.it >= array->Length)
return false;
var = array->GetValue(itw.it);
++itw.it;
return true;
}
template <typename T, typename U>
static bool MoveNext(const RefPtr<Acf::Array<T> >& array, IntIteratorWrapper& itw, U& var)
{
return MoveNext(array.Pointer, itw, var);
}
};
} // namespace Collections
} // namespace Acf
#endif // #ifndef __AcfCollectionBase__