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.

832 lines
17 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Wrappers to turn various Source Utl* containers into CLR
  4. // enumerables.
  5. //
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #ifndef UTLCONTAINER_CLI_H
  9. #define UTLCONTAINER_CLI_H
  10. #if defined( _WIN32 )
  11. #pragma once
  12. #endif
  13. /// Handy wrapper to turn any indexing property into
  14. /// an IList (assuming it is numbered 0..count). You
  15. /// need only initialize it with a delegate that yields
  16. /// int->type and another that gets the count.
  17. generic< typename T >
  18. public ref class IndexPropertyToIListReadOnly : public System::Collections::Generic::IList<T>
  19. {
  20. public:
  21. delegate T lGetter( int idx ); // will wrap the indexer
  22. delegate int lCounter( ); // will wrap the counter
  23. IndexPropertyToIListReadOnly( lGetter ^getter, lCounter ^counter )
  24. {
  25. m_getterFunc = getter;
  26. m_counterFunc = counter;
  27. }
  28. /*
  29. virtual ~IndexPropertyToIListReadOnly( ) { !IndexPropertyToIListReadOnly( ); }
  30. virtual !IndexPropertyToIListReadOnly( ) {}
  31. */
  32. property int Count
  33. {
  34. virtual int get() { return m_counterFunc(); }
  35. }
  36. #pragma region IList<T> Members
  37. virtual int IndexOf(T item)
  38. {
  39. int count = Count::get();
  40. for ( int i = 0 ; i < count ; ++i )
  41. {
  42. if ( item->Equals( m_getterFunc(i) ) )
  43. return i;
  44. }
  45. return -1;
  46. }
  47. virtual void Insert(int index, T item)
  48. {
  49. throw gcnew NotSupportedException( "Read-only." );
  50. }
  51. virtual void RemoveAt(int index)
  52. {
  53. throw gcnew NotSupportedException("Read-only.");
  54. }
  55. property T default[int]
  56. {
  57. virtual T get(int index)
  58. {
  59. if ( index < 0 || index > Count::get() )
  60. {
  61. throw gcnew ArgumentOutOfRangeException();
  62. }
  63. else
  64. {
  65. return m_getterFunc(index);
  66. }
  67. }
  68. virtual void set(int index, T to)
  69. {
  70. throw gcnew NotSupportedException("Read-only.");
  71. }
  72. }
  73. #pragma endregion
  74. #pragma region ICollection<T> Members
  75. virtual void Add(T item)
  76. {
  77. throw gcnew NotSupportedException("Read-only.");
  78. }
  79. virtual void Clear()
  80. {
  81. throw gcnew NotSupportedException("Read-only.");
  82. }
  83. virtual bool Contains(T item)
  84. {
  85. return IndexOf(item) != -1;
  86. }
  87. virtual void CopyTo( cli::array<T,1> ^arr, int start)
  88. {
  89. int stop = Count::get();
  90. for (int i = 0 ; i < stop ; ++i )
  91. {
  92. arr->SetValue((*this)[i],start+i);
  93. }
  94. // throw gcnew NotImplementedException();
  95. }
  96. property bool IsReadOnly
  97. {
  98. virtual bool get() { return true; }
  99. }
  100. virtual bool Remove(T item)
  101. {
  102. throw gcnew NotSupportedException("Read-only.");
  103. }
  104. #pragma endregion
  105. #pragma region Enumerator
  106. ref class LinearEnumerator : System::Collections::Generic::IEnumerator<T>
  107. {
  108. // Enumerators are positioned before the first element
  109. // until the first MoveNext() call.
  110. int position;
  111. public:
  112. LinearEnumerator(IndexPropertyToIListReadOnly<T> ^owner)
  113. {
  114. m_owner = owner;
  115. position = -1;
  116. }
  117. ~LinearEnumerator(){};
  118. !LinearEnumerator(){};
  119. virtual bool MoveNext()
  120. {
  121. position++;
  122. return ( position < m_owner->Count );
  123. }
  124. virtual void Reset()
  125. {
  126. position = -1;
  127. }
  128. virtual property T Current
  129. {
  130. virtual T get() = System::Collections::Generic::IEnumerator<T>::Current::get
  131. {
  132. if ( position >= 0 && position < m_owner->Count )
  133. {
  134. return m_owner[position];
  135. }
  136. else
  137. {
  138. throw gcnew InvalidOperationException();
  139. }
  140. }
  141. }
  142. virtual property System::Object^ CurrentAgainBecauseCPP_CLISucks
  143. {
  144. virtual System::Object^ get() = System::Collections::IEnumerator::Current::get
  145. {
  146. if ( position >= 0 && position < m_owner->Count )
  147. {
  148. return m_owner[position];
  149. }
  150. else
  151. {
  152. throw gcnew InvalidOperationException();
  153. }
  154. }
  155. }
  156. IndexPropertyToIListReadOnly<T> ^m_owner;
  157. };
  158. #pragma endregion
  159. #pragma region IEnumerable<T> Members
  160. virtual System::Collections::Generic::IEnumerator<T> ^ GetEnumerator()
  161. {
  162. return gcnew LinearEnumerator(this);
  163. }
  164. virtual System::Collections::IEnumerator^ GetEnumerator2() = System::Collections::IEnumerable::GetEnumerator
  165. {
  166. return gcnew LinearEnumerator(this);
  167. }
  168. #pragma endregion
  169. protected:
  170. lGetter ^m_getterFunc;
  171. lCounter ^m_counterFunc;
  172. };
  173. #if 0
  174. /// <summary>
  175. /// Tiny class that wraps an indexing property in a class with an IList interface
  176. /// so that the WPF databinding can access it.
  177. /// </summary>
  178. /// <remarks>
  179. /// Assumes that all indexes are from 0..count.
  180. /// </remarks>
  181. /// <typeparam name="U"> The type of the class whose property we wrap </typeparam>
  182. /// <typeparam name="T"> The type of the value returned from the class property </typeparam>
  183. public class BindingWrapper<T> : IList<T>, INotifyCollectionChanged
  184. {
  185. // lambda types. You'll pass in one of each of these with the constructor.
  186. /// <summary>
  187. /// Given an int, return the i-th element of wrapper property in owning class.
  188. /// </summary>
  189. public delegate T lGetter( int idx );
  190. /// <summary>
  191. /// Given an int, return the i-th element of wrapper property in owning class.
  192. /// </summary>
  193. public delegate int lCounter( );
  194. public BindingWrapper( /*U owner,*/ lGetter getter, lCounter counter )
  195. {
  196. // m_owner = owner;
  197. m_getterFunc = getter;
  198. m_counterFunc = counter;
  199. }
  200. #region IList<T> Members
  201. public int IndexOf(T item)
  202. {
  203. throw new NotImplementedException();
  204. /*
  205. // hang onto this number
  206. int count = Count;
  207. for (int i = 0 ; i < count ; ++i )
  208. {
  209. if (this[i] == item)
  210. return i;
  211. }
  212. return -1;
  213. */
  214. }
  215. public void Insert(int index, T item)
  216. {
  217. throw new NotSupportedException( "Read-only." );
  218. }
  219. public void RemoveAt(int index)
  220. {
  221. throw new NotSupportedException("Read-only.");
  222. }
  223. public T this[int index]
  224. {
  225. get
  226. {
  227. if (index < 0 || index > Count)
  228. {
  229. throw new ArgumentOutOfRangeException();
  230. }
  231. else
  232. {
  233. return m_getterFunc(index);
  234. }
  235. }
  236. set
  237. {
  238. throw new NotSupportedException("Read-only.");
  239. }
  240. }
  241. #endregion
  242. #region ICollection<T> Members
  243. public void Add(T item)
  244. {
  245. throw new NotSupportedException("Read-only.");
  246. }
  247. public void Clear()
  248. {
  249. throw new NotSupportedException("Read-only.");
  250. }
  251. public bool Contains(T item)
  252. {
  253. throw new NotImplementedException();
  254. }
  255. public void CopyTo(T[] array, int arrayIndex)
  256. {
  257. throw new NotSupportedException("Noncopyable.");
  258. }
  259. public int Count
  260. {
  261. get { return m_counterFunc(); }
  262. }
  263. public bool IsReadOnly
  264. {
  265. get { return true; }
  266. }
  267. public bool Remove(T item)
  268. {
  269. throw new NotSupportedException("Read-only.");
  270. }
  271. #endregion
  272. #region Enumerator
  273. public class LinearEnumerator : System.Collections.IEnumerator
  274. {
  275. // Enumerators are positioned before the first element
  276. // until the first MoveNext() call.
  277. int position = -1;
  278. public LinearEnumerator(BindingWrapper<T> owner)
  279. {
  280. m_owner = owner;
  281. }
  282. public bool MoveNext()
  283. {
  284. position++;
  285. return ( position < m_owner.Count );
  286. }
  287. public void Reset()
  288. {
  289. position = -1;
  290. }
  291. public Object Current
  292. {
  293. get
  294. {
  295. try
  296. {
  297. return m_owner[position];
  298. }
  299. catch (IndexOutOfRangeException)
  300. {
  301. throw new InvalidOperationException();
  302. }
  303. }
  304. }
  305. BindingWrapper<T> m_owner;
  306. }
  307. #endregion
  308. #region IEnumerable<T> Members
  309. public IEnumerator<T> GetEnumerator()
  310. {
  311. throw new NotImplementedException(); // return new LinearEnumerator(this);
  312. }
  313. #endregion
  314. #region IEnumerable Members
  315. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  316. {
  317. return new LinearEnumerator(this);
  318. }
  319. #endregion
  320. #region INotifyCollectionChanged
  321. public event NotifyCollectionChangedEventHandler CollectionChanged;
  322. public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  323. {
  324. if (CollectionChanged != null)
  325. {
  326. CollectionChanged(this, e);
  327. }
  328. }
  329. #endregion
  330. #region Private data
  331. // U m_owner;
  332. lGetter m_getterFunc;
  333. lCounter m_counterFunc;
  334. #endregion
  335. }
  336. #endif
  337. /// Common code for classes that wrap native RR
  338. /// types. You have the option to make a COPY
  339. /// rather than a pointer to the native class:
  340. /// in that case, the constructor here new's a copy
  341. /// of the given type on the heap, and the finalizer
  342. /// deletes it.
  343. /// It may be necessary to specialize the constructor
  344. /// in certain cases where a managed function is not
  345. /// allowed to new the given type.
  346. /// Subclass this with a CLI version of the wrapped
  347. /// class and create whatever accessor properties you
  348. /// would like to expose to the managed side.
  349. template< typename T >
  350. public ref class NativeTypeCopyWrapper
  351. {
  352. public:
  353. NativeTypeCopyWrapper( ) : m_pNative(NULL), m_bIsCopy(true) {};
  354. NativeTypeCopyWrapper( T* from ) // this overload assumes no copy
  355. {
  356. m_bIsCopy = false;
  357. if ( false )
  358. {
  359. m_pNative = new T( *from );
  360. }
  361. else
  362. {
  363. m_pNative = from;
  364. }
  365. }
  366. NativeTypeCopyWrapper( T* from, bool bCopy )
  367. {
  368. m_bIsCopy = bCopy;
  369. if ( bCopy )
  370. {
  371. m_pNative = new T( *from );
  372. }
  373. else
  374. {
  375. m_pNative = from;
  376. }
  377. }
  378. ~NativeTypeCopyWrapper() { this->!NativeTypeCopyWrapper(); }
  379. !NativeTypeCopyWrapper()
  380. {
  381. if ( m_bIsCopy )
  382. delete m_pNative;
  383. m_pNative = NULL;
  384. }
  385. // copy constructor
  386. NativeTypeCopyWrapper(NativeTypeCopyWrapper% r)
  387. {
  388. m_bIsCopy = r->m_bIsCopy;
  389. if (m_bIsCopy)
  390. m_pNative = new T( *r->GetNativePtr() );
  391. else
  392. m_pNative = r->GetNativePtr();
  393. }
  394. inline bool IsValid( ) { return m_pNative != NULL; }
  395. /// use the assignment operator on the internal native type, copying
  396. /// over the one in the given FROM class, and make me point to it.
  397. /// So named to be explicit about what's happening, and because I'm
  398. /// not sure what happens when you = on a ref.
  399. void Assign( NativeTypeCopyWrapper^ from )
  400. {
  401. *m_pNative = *from.m_pNative;
  402. }
  403. /// please be careful
  404. T* GetNativePtr() { return m_pNative; }
  405. protected:
  406. T* m_pNative;
  407. bool m_bIsCopy;
  408. };
  409. // CUtlDict as enumerable.
  410. #include "utldict.h"
  411. /*
  412. template <class T, class I>
  413. class CUtlDict
  414. */
  415. namespace Tier1CLI
  416. {
  417. namespace Containers
  418. {
  419. public interface class INotifiableList
  420. : public System::Collections::IList ,
  421. public System::Collections::Specialized::INotifyCollectionChanged
  422. {
  423. virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e) = 0;
  424. };
  425. }
  426. };
  427. /// <summary>
  428. /// A class that wraps a tier1 CUtlDict in a way that can be iterated over from C#.
  429. /// </summary>
  430. /// <remarks>
  431. /// The CONVERTOR template parameter below shall be the class
  432. /// that wraps the native C++ * type into a CLR reference type.
  433. /// It should have a constructor that takes a parameter of type
  434. /// T* , which will be called like:
  435. /// return gcnew CONVERTOR(T *foo);
  436. /// </remarks>
  437. template <class T, typename I, class CONVERTOR = NativeTypeCopyWrapper<T> >
  438. public ref class CCLIUtlDictEnumerable : // public System::Collections::IEnumerable,
  439. public Tier1CLI::Containers::INotifiableList
  440. {
  441. public:
  442. typedef CUtlDict< T,I > dict_t;
  443. typedef CONVERTOR value_t;
  444. typedef const char * key_t;
  445. #pragma region Enumeration interface
  446. ref struct tuple_t
  447. {
  448. key_t key;
  449. value_t ^val;
  450. I index;
  451. inline tuple_t( const key_t &k, T &v, I i ) : key(k), index(i)
  452. {
  453. val = gcnew CONVERTOR( &v, i );
  454. };
  455. // conversions to CLR types
  456. property System::String^ Name
  457. {
  458. System::String^ get()
  459. {
  460. return gcnew String(key);
  461. }
  462. }
  463. property CONVERTOR^ Val
  464. {
  465. CONVERTOR^ get()
  466. {
  467. return val;
  468. }
  469. }
  470. property I Index
  471. {
  472. I get()
  473. {
  474. return index;
  475. }
  476. }
  477. };
  478. /*
  479. // convenience functions for WPF databindings, which may hand back a
  480. // tuple_t object to C#, which can't get at the typedefs above.
  481. // this can cause trouble with getting at the properties; rather than
  482. // use reflection, you can just use these.
  483. System::String^ NameFor( tuple_t ^ tup )
  484. {
  485. return tup->Name;
  486. }
  487. value_t^ ValFor( tuple_t ^ tup )
  488. {
  489. return tup->Val;
  490. }
  491. */
  492. CONVERTOR ^GetValue( I idx )
  493. {
  494. return gcnew CONVERTOR(m_pInnerDict->Element(idx));
  495. }
  496. CONVERTOR ^GetKey( I idx )
  497. {
  498. return gcnew String(m_pInnerDict->GetElementName(idx));
  499. }
  500. property int Count
  501. {
  502. virtual int get() { return m_pInnerDict->Count(); }
  503. }
  504. /// Iterator type. Walks over the UtlDict in the same order as its
  505. /// internal iterator. Returns a tuple of <key,value>, where key is
  506. /// always a string type (as in the utldict).
  507. /// TODO: can I make this a value struct so it doesn't need to be
  508. /// boxed/unboxed?
  509. ref struct Enumerator : public System::Collections::IEnumerator
  510. {
  511. typedef CCLIUtlDictEnumerable<T,I> owner_t;
  512. Enumerator( dict_t *pDict ) : m_pEnumeratedDict(pDict), m_bIsBefore(true)
  513. {
  514. m_index = dict_t::InvalidIndex();
  515. }
  516. inline bool IsValid()
  517. {
  518. return m_pEnumeratedDict->IsValidIndex(m_index);
  519. }
  520. // IEnumerator interface
  521. virtual void Reset()
  522. {
  523. m_bIsBefore = true;
  524. m_index = m_pEnumeratedDict->First();
  525. }
  526. // return false when falling off the end
  527. virtual bool MoveNext()
  528. {
  529. if (m_bIsBefore)
  530. {
  531. m_bIsBefore = false;
  532. m_index = m_pEnumeratedDict->First();
  533. return IsValid();
  534. }
  535. else
  536. {
  537. if ( !IsValid() )
  538. {
  539. return false;
  540. }
  541. else
  542. {
  543. m_index = m_pEnumeratedDict->Next( m_index );
  544. return IsValid();
  545. }
  546. }
  547. }
  548. property System::Object^ Current
  549. {
  550. virtual System::Object^ get()
  551. {
  552. if ( IsValid() )
  553. {
  554. return gcnew tuple_t( m_pEnumeratedDict->GetElementName(m_index),
  555. m_pEnumeratedDict->Element(m_index),
  556. m_index);
  557. }
  558. else
  559. {
  560. throw gcnew System::InvalidOperationException();
  561. }
  562. }
  563. };
  564. // data:
  565. protected:
  566. I m_index;
  567. dict_t *m_pEnumeratedDict;
  568. bool m_bIsBefore;
  569. };
  570. virtual System::Collections::IEnumerator^ GetEnumerator()
  571. {
  572. return gcnew Enumerator(m_pInnerDict);
  573. }
  574. #pragma endregion
  575. bool IsValidIndex( I idx ) { return m_pInnerDict->IsValidIndex(idx); }
  576. tuple_t ^GetElement( I i )
  577. {
  578. return gcnew tuple_t( m_pInnerDict->GetElementName(i),
  579. m_pInnerDict->Element(i),
  580. i);
  581. }
  582. #pragma region ILIST interface
  583. virtual int IndexOf( System::Object ^obj )
  584. {
  585. tuple_t ^t = dynamic_cast< tuple_t ^>(obj);
  586. if (t)
  587. {
  588. return t->index;
  589. }
  590. else
  591. {
  592. throw gcnew System::ArrayTypeMismatchException();
  593. }
  594. }
  595. virtual bool Contains( System::Object ^obj )
  596. {
  597. tuple_t ^t = dynamic_cast< tuple_t ^>(obj);
  598. if (t)
  599. {
  600. return IsValidIndex(t->index);
  601. }
  602. else
  603. {
  604. throw gcnew System::ArrayTypeMismatchException();
  605. }
  606. }
  607. virtual void Insert(int index, System::Object ^ item)
  608. {
  609. throw gcnew NotSupportedException( "Read-only." );
  610. }
  611. virtual void Remove(System::Object ^)
  612. {
  613. throw gcnew NotSupportedException("Read-only.");
  614. }
  615. virtual void RemoveAt(int index)
  616. {
  617. throw gcnew NotSupportedException("Read-only.");
  618. }
  619. virtual int Add(System::Object ^o)
  620. {
  621. throw gcnew NotSupportedException("Read-only.");
  622. }
  623. virtual void Clear()
  624. {
  625. throw gcnew NotSupportedException("Read-only.");
  626. }
  627. virtual property Object ^ SyncRoot
  628. {
  629. Object ^ get() { return this; }
  630. }
  631. virtual void CopyTo(Array ^arr, int start)
  632. {
  633. int stop = Count::get();
  634. for (int i = 0 ; i < stop ; ++i )
  635. {
  636. arr->SetValue((*this)[i],start+i);
  637. }
  638. // throw gcnew NotImplementedException();
  639. }
  640. property System::Object ^ default[int]
  641. {
  642. virtual System::Object ^get( int index )
  643. {
  644. if (index < 0 || index > Count)
  645. {
  646. throw gcnew ArgumentOutOfRangeException();
  647. }
  648. else
  649. {
  650. return GetElement(index);
  651. }
  652. }
  653. virtual void set(int idx, System::Object ^s)
  654. {
  655. throw gcnew NotSupportedException("Read-only.");
  656. }
  657. }
  658. property bool IsReadOnly
  659. {
  660. virtual bool get() { return true; }
  661. }
  662. property bool IsFixedSize
  663. {
  664. virtual bool get() { return true; }
  665. }
  666. property bool IsSynchronized
  667. {
  668. virtual bool get() { return true; }
  669. }
  670. #pragma endregion
  671. #pragma region INotifyCollectionChanged interface
  672. System::Collections::Specialized::NotifyCollectionChangedEventHandler ^m_CollectionChanged;
  673. virtual event System::Collections::Specialized::NotifyCollectionChangedEventHandler ^CollectionChanged
  674. {
  675. void add(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
  676. m_CollectionChanged += d;
  677. }
  678. void remove(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
  679. m_CollectionChanged -= d;
  680. }
  681. }
  682. virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e)
  683. {
  684. if (m_CollectionChanged != nullptr)
  685. {
  686. m_CollectionChanged(this, e);
  687. }
  688. }
  689. #pragma endregion
  690. /// construct with a pointer at a UtlDict. Does not
  691. /// own the pointer; simply stores it internally.
  692. CCLIUtlDictEnumerable( dict_t *pInnerDict )
  693. //: m_CollectionChanged(gcnew System::Collections::Specialized::NotifyCollectionChangedEventHandler )
  694. {
  695. Init(pInnerDict);
  696. };
  697. CCLIUtlDictEnumerable( ) :m_pInnerDict(NULL)//
  698. //,m_CollectionChanged(gcnew System::Collections::Specialized::NotifyCollectionChangedEventHandler )
  699. { };
  700. void Init( dict_t *pInnerDict )
  701. {
  702. m_pInnerDict = pInnerDict;
  703. }
  704. protected:
  705. dict_t *m_pInnerDict;
  706. };
  707. #endif