Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

833 lines
17 KiB

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Wrappers to turn various Source Utl* containers into CLR
// enumerables.
//
// $NoKeywords: $
//=============================================================================//
#ifndef UTLCONTAINER_CLI_H
#define UTLCONTAINER_CLI_H
#if defined( _WIN32 )
#pragma once
#endif
/// Handy wrapper to turn any indexing property into
/// an IList (assuming it is numbered 0..count). You
/// need only initialize it with a delegate that yields
/// int->type and another that gets the count.
generic< typename T >
public ref class IndexPropertyToIListReadOnly : public System::Collections::Generic::IList<T>
{
public:
delegate T lGetter( int idx ); // will wrap the indexer
delegate int lCounter( ); // will wrap the counter
IndexPropertyToIListReadOnly( lGetter ^getter, lCounter ^counter )
{
m_getterFunc = getter;
m_counterFunc = counter;
}
/*
virtual ~IndexPropertyToIListReadOnly( ) { !IndexPropertyToIListReadOnly( ); }
virtual !IndexPropertyToIListReadOnly( ) {}
*/
property int Count
{
virtual int get() { return m_counterFunc(); }
}
#pragma region IList<T> Members
virtual int IndexOf(T item)
{
int count = Count::get();
for ( int i = 0 ; i < count ; ++i )
{
if ( item->Equals( m_getterFunc(i) ) )
return i;
}
return -1;
}
virtual void Insert(int index, T item)
{
throw gcnew NotSupportedException( "Read-only." );
}
virtual void RemoveAt(int index)
{
throw gcnew NotSupportedException("Read-only.");
}
property T default[int]
{
virtual T get(int index)
{
if ( index < 0 || index > Count::get() )
{
throw gcnew ArgumentOutOfRangeException();
}
else
{
return m_getterFunc(index);
}
}
virtual void set(int index, T to)
{
throw gcnew NotSupportedException("Read-only.");
}
}
#pragma endregion
#pragma region ICollection<T> Members
virtual void Add(T item)
{
throw gcnew NotSupportedException("Read-only.");
}
virtual void Clear()
{
throw gcnew NotSupportedException("Read-only.");
}
virtual bool Contains(T item)
{
return IndexOf(item) != -1;
}
virtual void CopyTo( cli::array<T,1> ^arr, int start)
{
int stop = Count::get();
for (int i = 0 ; i < stop ; ++i )
{
arr->SetValue((*this)[i],start+i);
}
// throw gcnew NotImplementedException();
}
property bool IsReadOnly
{
virtual bool get() { return true; }
}
virtual bool Remove(T item)
{
throw gcnew NotSupportedException("Read-only.");
}
#pragma endregion
#pragma region Enumerator
ref class LinearEnumerator : System::Collections::Generic::IEnumerator<T>
{
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position;
public:
LinearEnumerator(IndexPropertyToIListReadOnly<T> ^owner)
{
m_owner = owner;
position = -1;
}
~LinearEnumerator(){};
!LinearEnumerator(){};
virtual bool MoveNext()
{
position++;
return ( position < m_owner->Count );
}
virtual void Reset()
{
position = -1;
}
virtual property T Current
{
virtual T get() = System::Collections::Generic::IEnumerator<T>::Current::get
{
if ( position >= 0 && position < m_owner->Count )
{
return m_owner[position];
}
else
{
throw gcnew InvalidOperationException();
}
}
}
virtual property System::Object^ CurrentAgainBecauseCPP_CLISucks
{
virtual System::Object^ get() = System::Collections::IEnumerator::Current::get
{
if ( position >= 0 && position < m_owner->Count )
{
return m_owner[position];
}
else
{
throw gcnew InvalidOperationException();
}
}
}
IndexPropertyToIListReadOnly<T> ^m_owner;
};
#pragma endregion
#pragma region IEnumerable<T> Members
virtual System::Collections::Generic::IEnumerator<T> ^ GetEnumerator()
{
return gcnew LinearEnumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() = System::Collections::IEnumerable::GetEnumerator
{
return gcnew LinearEnumerator(this);
}
#pragma endregion
protected:
lGetter ^m_getterFunc;
lCounter ^m_counterFunc;
};
#if 0
/// <summary>
/// Tiny class that wraps an indexing property in a class with an IList interface
/// so that the WPF databinding can access it.
/// </summary>
/// <remarks>
/// Assumes that all indexes are from 0..count.
/// </remarks>
/// <typeparam name="U"> The type of the class whose property we wrap </typeparam>
/// <typeparam name="T"> The type of the value returned from the class property </typeparam>
public class BindingWrapper<T> : IList<T>, INotifyCollectionChanged
{
// lambda types. You'll pass in one of each of these with the constructor.
/// <summary>
/// Given an int, return the i-th element of wrapper property in owning class.
/// </summary>
public delegate T lGetter( int idx );
/// <summary>
/// Given an int, return the i-th element of wrapper property in owning class.
/// </summary>
public delegate int lCounter( );
public BindingWrapper( /*U owner,*/ lGetter getter, lCounter counter )
{
// m_owner = owner;
m_getterFunc = getter;
m_counterFunc = counter;
}
#region IList<T> Members
public int IndexOf(T item)
{
throw new NotImplementedException();
/*
// hang onto this number
int count = Count;
for (int i = 0 ; i < count ; ++i )
{
if (this[i] == item)
return i;
}
return -1;
*/
}
public void Insert(int index, T item)
{
throw new NotSupportedException( "Read-only." );
}
public void RemoveAt(int index)
{
throw new NotSupportedException("Read-only.");
}
public T this[int index]
{
get
{
if (index < 0 || index > Count)
{
throw new ArgumentOutOfRangeException();
}
else
{
return m_getterFunc(index);
}
}
set
{
throw new NotSupportedException("Read-only.");
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
throw new NotSupportedException("Read-only.");
}
public void Clear()
{
throw new NotSupportedException("Read-only.");
}
public bool Contains(T item)
{
throw new NotImplementedException();
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotSupportedException("Noncopyable.");
}
public int Count
{
get { return m_counterFunc(); }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(T item)
{
throw new NotSupportedException("Read-only.");
}
#endregion
#region Enumerator
public class LinearEnumerator : System.Collections.IEnumerator
{
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
public LinearEnumerator(BindingWrapper<T> owner)
{
m_owner = owner;
}
public bool MoveNext()
{
position++;
return ( position < m_owner.Count );
}
public void Reset()
{
position = -1;
}
public Object Current
{
get
{
try
{
return m_owner[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
BindingWrapper<T> m_owner;
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException(); // return new LinearEnumerator(this);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new LinearEnumerator(this);
}
#endregion
#region INotifyCollectionChanged
public event NotifyCollectionChangedEventHandler CollectionChanged;
public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
{
CollectionChanged(this, e);
}
}
#endregion
#region Private data
// U m_owner;
lGetter m_getterFunc;
lCounter m_counterFunc;
#endregion
}
#endif
/// Common code for classes that wrap native RR
/// types. You have the option to make a COPY
/// rather than a pointer to the native class:
/// in that case, the constructor here new's a copy
/// of the given type on the heap, and the finalizer
/// deletes it.
/// It may be necessary to specialize the constructor
/// in certain cases where a managed function is not
/// allowed to new the given type.
/// Subclass this with a CLI version of the wrapped
/// class and create whatever accessor properties you
/// would like to expose to the managed side.
template< typename T >
public ref class NativeTypeCopyWrapper
{
public:
NativeTypeCopyWrapper( ) : m_pNative(NULL), m_bIsCopy(true) {};
NativeTypeCopyWrapper( T* from ) // this overload assumes no copy
{
m_bIsCopy = false;
if ( false )
{
m_pNative = new T( *from );
}
else
{
m_pNative = from;
}
}
NativeTypeCopyWrapper( T* from, bool bCopy )
{
m_bIsCopy = bCopy;
if ( bCopy )
{
m_pNative = new T( *from );
}
else
{
m_pNative = from;
}
}
~NativeTypeCopyWrapper() { this->!NativeTypeCopyWrapper(); }
!NativeTypeCopyWrapper()
{
if ( m_bIsCopy )
delete m_pNative;
m_pNative = NULL;
}
// copy constructor
NativeTypeCopyWrapper(NativeTypeCopyWrapper% r)
{
m_bIsCopy = r->m_bIsCopy;
if (m_bIsCopy)
m_pNative = new T( *r->GetNativePtr() );
else
m_pNative = r->GetNativePtr();
}
inline bool IsValid( ) { return m_pNative != NULL; }
/// use the assignment operator on the internal native type, copying
/// over the one in the given FROM class, and make me point to it.
/// So named to be explicit about what's happening, and because I'm
/// not sure what happens when you = on a ref.
void Assign( NativeTypeCopyWrapper^ from )
{
*m_pNative = *from.m_pNative;
}
/// please be careful
T* GetNativePtr() { return m_pNative; }
protected:
T* m_pNative;
bool m_bIsCopy;
};
// CUtlDict as enumerable.
#include "utldict.h"
/*
template <class T, class I>
class CUtlDict
*/
namespace Tier1CLI
{
namespace Containers
{
public interface class INotifiableList
: public System::Collections::IList ,
public System::Collections::Specialized::INotifyCollectionChanged
{
virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e) = 0;
};
}
};
/// <summary>
/// A class that wraps a tier1 CUtlDict in a way that can be iterated over from C#.
/// </summary>
/// <remarks>
/// The CONVERTOR template parameter below shall be the class
/// that wraps the native C++ * type into a CLR reference type.
/// It should have a constructor that takes a parameter of type
/// T* , which will be called like:
/// return gcnew CONVERTOR(T *foo);
/// </remarks>
template <class T, typename I, class CONVERTOR = NativeTypeCopyWrapper<T> >
public ref class CCLIUtlDictEnumerable : // public System::Collections::IEnumerable,
public Tier1CLI::Containers::INotifiableList
{
public:
typedef CUtlDict< T,I > dict_t;
typedef CONVERTOR value_t;
typedef const char * key_t;
#pragma region Enumeration interface
ref struct tuple_t
{
key_t key;
value_t ^val;
I index;
inline tuple_t( const key_t &k, T &v, I i ) : key(k), index(i)
{
val = gcnew CONVERTOR( &v, i );
};
// conversions to CLR types
property System::String^ Name
{
System::String^ get()
{
return gcnew String(key);
}
}
property CONVERTOR^ Val
{
CONVERTOR^ get()
{
return val;
}
}
property I Index
{
I get()
{
return index;
}
}
};
/*
// convenience functions for WPF databindings, which may hand back a
// tuple_t object to C#, which can't get at the typedefs above.
// this can cause trouble with getting at the properties; rather than
// use reflection, you can just use these.
System::String^ NameFor( tuple_t ^ tup )
{
return tup->Name;
}
value_t^ ValFor( tuple_t ^ tup )
{
return tup->Val;
}
*/
CONVERTOR ^GetValue( I idx )
{
return gcnew CONVERTOR(m_pInnerDict->Element(idx));
}
CONVERTOR ^GetKey( I idx )
{
return gcnew String(m_pInnerDict->GetElementName(idx));
}
property int Count
{
virtual int get() { return m_pInnerDict->Count(); }
}
/// Iterator type. Walks over the UtlDict in the same order as its
/// internal iterator. Returns a tuple of <key,value>, where key is
/// always a string type (as in the utldict).
/// TODO: can I make this a value struct so it doesn't need to be
/// boxed/unboxed?
ref struct Enumerator : public System::Collections::IEnumerator
{
typedef CCLIUtlDictEnumerable<T,I> owner_t;
Enumerator( dict_t *pDict ) : m_pEnumeratedDict(pDict), m_bIsBefore(true)
{
m_index = dict_t::InvalidIndex();
}
inline bool IsValid()
{
return m_pEnumeratedDict->IsValidIndex(m_index);
}
// IEnumerator interface
virtual void Reset()
{
m_bIsBefore = true;
m_index = m_pEnumeratedDict->First();
}
// return false when falling off the end
virtual bool MoveNext()
{
if (m_bIsBefore)
{
m_bIsBefore = false;
m_index = m_pEnumeratedDict->First();
return IsValid();
}
else
{
if ( !IsValid() )
{
return false;
}
else
{
m_index = m_pEnumeratedDict->Next( m_index );
return IsValid();
}
}
}
property System::Object^ Current
{
virtual System::Object^ get()
{
if ( IsValid() )
{
return gcnew tuple_t( m_pEnumeratedDict->GetElementName(m_index),
m_pEnumeratedDict->Element(m_index),
m_index);
}
else
{
throw gcnew System::InvalidOperationException();
}
}
};
// data:
protected:
I m_index;
dict_t *m_pEnumeratedDict;
bool m_bIsBefore;
};
virtual System::Collections::IEnumerator^ GetEnumerator()
{
return gcnew Enumerator(m_pInnerDict);
}
#pragma endregion
bool IsValidIndex( I idx ) { return m_pInnerDict->IsValidIndex(idx); }
tuple_t ^GetElement( I i )
{
return gcnew tuple_t( m_pInnerDict->GetElementName(i),
m_pInnerDict->Element(i),
i);
}
#pragma region ILIST interface
virtual int IndexOf( System::Object ^obj )
{
tuple_t ^t = dynamic_cast< tuple_t ^>(obj);
if (t)
{
return t->index;
}
else
{
throw gcnew System::ArrayTypeMismatchException();
}
}
virtual bool Contains( System::Object ^obj )
{
tuple_t ^t = dynamic_cast< tuple_t ^>(obj);
if (t)
{
return IsValidIndex(t->index);
}
else
{
throw gcnew System::ArrayTypeMismatchException();
}
}
virtual void Insert(int index, System::Object ^ item)
{
throw gcnew NotSupportedException( "Read-only." );
}
virtual void Remove(System::Object ^)
{
throw gcnew NotSupportedException("Read-only.");
}
virtual void RemoveAt(int index)
{
throw gcnew NotSupportedException("Read-only.");
}
virtual int Add(System::Object ^o)
{
throw gcnew NotSupportedException("Read-only.");
}
virtual void Clear()
{
throw gcnew NotSupportedException("Read-only.");
}
virtual property Object ^ SyncRoot
{
Object ^ get() { return this; }
}
virtual void CopyTo(Array ^arr, int start)
{
int stop = Count::get();
for (int i = 0 ; i < stop ; ++i )
{
arr->SetValue((*this)[i],start+i);
}
// throw gcnew NotImplementedException();
}
property System::Object ^ default[int]
{
virtual System::Object ^get( int index )
{
if (index < 0 || index > Count)
{
throw gcnew ArgumentOutOfRangeException();
}
else
{
return GetElement(index);
}
}
virtual void set(int idx, System::Object ^s)
{
throw gcnew NotSupportedException("Read-only.");
}
}
property bool IsReadOnly
{
virtual bool get() { return true; }
}
property bool IsFixedSize
{
virtual bool get() { return true; }
}
property bool IsSynchronized
{
virtual bool get() { return true; }
}
#pragma endregion
#pragma region INotifyCollectionChanged interface
System::Collections::Specialized::NotifyCollectionChangedEventHandler ^m_CollectionChanged;
virtual event System::Collections::Specialized::NotifyCollectionChangedEventHandler ^CollectionChanged
{
void add(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
m_CollectionChanged += d;
}
void remove(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
m_CollectionChanged -= d;
}
}
virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e)
{
if (m_CollectionChanged != nullptr)
{
m_CollectionChanged(this, e);
}
}
#pragma endregion
/// construct with a pointer at a UtlDict. Does not
/// own the pointer; simply stores it internally.
CCLIUtlDictEnumerable( dict_t *pInnerDict )
//: m_CollectionChanged(gcnew System::Collections::Specialized::NotifyCollectionChangedEventHandler )
{
Init(pInnerDict);
};
CCLIUtlDictEnumerable( ) :m_pInnerDict(NULL)//
//,m_CollectionChanged(gcnew System::Collections::Specialized::NotifyCollectionChangedEventHandler )
{ };
void Init( dict_t *pInnerDict )
{
m_pInnerDict = pInnerDict;
}
protected:
dict_t *m_pInnerDict;
};
#endif