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.

966 lines
22 KiB

  1. //===== Copyright � Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Resource Stream is conceptually memory file where you write the data
  4. // that you want to live both on disk and in memory. The constraint then is
  5. // that the data must be movable in memory, since you don't know in advance,
  6. // when you're creating the data, what will be its start address once it gets
  7. // loaded. To accomplish this, we use CResourcePointer and CResourceArray
  8. // in places of pointers and dynamic arrays. They store offsets rather than
  9. // absolute addresses of the referenced objects, thus they are moveable.
  10. // On Intel, the available addressing modes make the access to CResourcePointer
  11. // as fast as pointer dereferencing in most cases. On architectures with
  12. // rigid addressing, adding the base address is still virtually free.
  13. //
  14. // $NoKeywords: $
  15. //===========================================================================//
  16. #include "resourcefile/schema.h"
  17. #ifndef RESOURCESTREAM_H
  18. #define RESOURCESTREAM_H
  19. #ifdef COMPILER_MSVC
  20. #pragma once
  21. #endif
  22. #include "tier0/platform.h"
  23. #include "tier0/basetypes.h"
  24. #include "tier0/dbg.h"
  25. #include "tier1/strtools.h"
  26. class CResourceStream;
  27. inline byte *ResolveOffset( const int32 *pOffset )
  28. {
  29. int offset = *pOffset;
  30. return offset ? ( ( byte* )pOffset ) + offset : NULL;
  31. }
  32. inline byte *ResolveOffsetFast( const int32 *pOffset )
  33. {
  34. int offset = *pOffset;
  35. AssertDbg( offset != 0 );
  36. return ( ( byte* )pOffset ) + offset;
  37. }
  38. template <typename T>
  39. class CLockedResource
  40. {
  41. private:
  42. T *m_pData; // data; may be const
  43. uint m_nCount; // number of allocated data elements
  44. //uint m_nStride; // normally sizeof(T), but may be not
  45. //uint m_nClassCRC;
  46. public:
  47. CLockedResource(): m_pData( NULL ), m_nCount( 0 ) {}
  48. CLockedResource( T *pData, uint nCount ): m_pData( pData ), m_nCount( nCount ) {}
  49. // emulates pointer arithmetics
  50. CLockedResource<T> operator + ( int nOffset ) { Assert( m_nCount <= (uint)nOffset); return CLockedResource<T>( m_pData + nOffset, m_nCount - (uint)nOffset ); }
  51. operator const T* ()const { return m_pData; }
  52. operator T* () { return m_pData; }
  53. T* operator ->() { return m_pData; }
  54. const T* operator ->() const { return m_pData; }
  55. uint Count()const {return m_nCount;}
  56. };
  57. template <typename T>
  58. class CUnlockedResource
  59. {
  60. private:
  61. CResourceStream *m_pStream; // data; may be const
  62. uint32 m_nOffset;
  63. uint32 m_nCount; // number of allocated data elements
  64. //uint m_nStride; // normally sizeof(T), but may be not
  65. //uint m_nClassCRC;
  66. public:
  67. CUnlockedResource( ): m_pStream( NULL ), m_nOffset( 0 ), m_nCount( 0 ) {}
  68. CUnlockedResource( CResourceStream *pStream, T *pData, uint nCount );
  69. bool IsValid( )const { return m_pStream != NULL; }
  70. void Reset( ) { m_pStream = NULL; }
  71. // emulates pointer arithmetics
  72. CUnlockedResource<T> operator + ( int nOffset )
  73. {
  74. Assert( m_nCount <= ( uint ) nOffset );
  75. return CUnlockedResource<T>( m_pStream, GetPtr() + nOffset, m_nCount - ( uint ) nOffset );
  76. }
  77. operator const T* ( )const { return GetPtr(); }
  78. operator T* ( ) { return GetPtr(); }
  79. T* operator ->( ) { return GetPtr(); }
  80. const T* operator ->( ) const { return GetPtr(); }
  81. uint Count( )const { return m_nCount; }
  82. T* GetPtr( );
  83. const T* GetPtr( )const;
  84. };
  85. // AT RUN-TIME ONLY the offset converts automatically into pointers to the appropritate type
  86. // at tool-time, you should use LinkSource_t and LinkTarget_t
  87. class CResourcePointerBase
  88. {
  89. protected:
  90. int32 m_nOffset;
  91. public:
  92. CResourcePointerBase() : m_nOffset( 0 ) {}
  93. bool operator == ( int zero )const
  94. {
  95. AssertDbg( zero == 0 );
  96. return m_nOffset == zero;
  97. }
  98. bool IsNull()const
  99. {
  100. return m_nOffset == 0;
  101. }
  102. int32 NotNull()const
  103. {
  104. return m_nOffset;
  105. }
  106. int32 GetOffset() const
  107. {
  108. return m_nOffset;
  109. }
  110. const byte* GetUncheckedRawPtr() const
  111. {
  112. // assumes non-null; returns garbage if this is a null pointer
  113. return ResolveOffsetFast( &m_nOffset );
  114. }
  115. byte* GetUncheckedRawPtr()
  116. {
  117. // assumes non-null; returns garbage if this is a null pointer
  118. return ResolveOffsetFast( &m_nOffset );
  119. }
  120. const byte* GetRawPtr() const
  121. {
  122. return ResolveOffset( &m_nOffset );
  123. }
  124. byte* GetRawPtr()
  125. {
  126. return ResolveOffset( &m_nOffset );
  127. }
  128. void SetRawPtr( const void* p )
  129. {
  130. if ( p == NULL )
  131. {
  132. m_nOffset = 0;
  133. }
  134. else
  135. {
  136. intp nOffset = ( intp )p - ( intp )&m_nOffset;
  137. m_nOffset = ( int32 )nOffset;
  138. AssertDbg( m_nOffset == nOffset );
  139. }
  140. }
  141. void SetNull()
  142. {
  143. m_nOffset = 0;
  144. }
  145. };
  146. template <typename T>
  147. class CResourcePointer: public CResourcePointerBase
  148. {
  149. public:
  150. FORCEINLINE const T* GetUncheckedPtr() const
  151. {
  152. // assumes non-null; returns garbage if this is a null pointer
  153. AssertDbg( m_nOffset != 0 );
  154. byte *ptr = ResolveOffsetFast( &m_nOffset );
  155. return ( const T* )ptr;
  156. }
  157. FORCEINLINE const T* GetPtr() const
  158. {
  159. byte *ptr = ResolveOffset( &m_nOffset );
  160. return ( const T* )ptr;
  161. }
  162. FORCEINLINE operator const T*() const
  163. {
  164. return GetPtr();
  165. }
  166. FORCEINLINE const T* operator->() const
  167. {
  168. return GetPtr();
  169. }
  170. void operator = ( const T* pT )
  171. {
  172. SetRawPtr( pT );
  173. }
  174. void SetPtr( const T* pT )
  175. {
  176. SetRawPtr( pT );
  177. }
  178. // FIXME: Should these be in a 'CResourceWritablePointer' subclass?
  179. // There are plenty of cases where we know that a CResourcePointer should be read-only
  180. public:
  181. FORCEINLINE T* GetUncheckedPtr()
  182. {
  183. // assumes non-null; returns garbage if this is a null pointer
  184. Assert( m_nOffset != 0 );
  185. byte *ptr = ResolveOffsetFast( &m_nOffset );
  186. return ( T* )ptr;
  187. }
  188. FORCEINLINE T* GetPtr()
  189. {
  190. byte *ptr = ResolveOffset( &m_nOffset );
  191. return ( T* )ptr;
  192. }
  193. FORCEINLINE operator T*()
  194. {
  195. return GetPtr();
  196. }
  197. FORCEINLINE T* operator->()
  198. {
  199. return GetPtr();
  200. }
  201. public:
  202. void Unsafe_OutOfBoundsAllocate()
  203. {
  204. SetPtr( new T() );
  205. }
  206. void Unsafe_OutOfBoundsFree()
  207. {
  208. delete GetPtr();
  209. }
  210. void SwapBytes()
  211. {
  212. m_nOffset = DWordSwapC( m_nOffset );
  213. }
  214. };
  215. // never construct this - only the Resource stream may construct or load data that contains ResourceArray or ResourcePointer; use LockedResource or naked pointer or CUtlBuffer or something like that instead
  216. class CResourceArrayBase
  217. {
  218. public:
  219. CResourceArrayBase()
  220. {
  221. m_nOffset = 0;
  222. m_nCount = 0;
  223. }
  224. bool operator == ( int zero )const
  225. {
  226. AssertDbg( zero == 0 );
  227. return m_nOffset == zero;
  228. }
  229. bool IsNull()const
  230. {
  231. return m_nOffset == 0;
  232. }
  233. int32 NotNull()const
  234. {
  235. return m_nOffset;
  236. }
  237. const byte* GetRawPtr() const
  238. {
  239. // validate
  240. return ResolveOffset( &m_nOffset );
  241. }
  242. byte* GetRawPtr()
  243. {
  244. // validate
  245. return ResolveOffset( &m_nOffset );
  246. }
  247. int Count() const
  248. {
  249. return m_nCount;
  250. }
  251. void WriteDirect( int nCount, void *pData )
  252. {
  253. if ( pData == NULL )
  254. {
  255. AssertDbg( nCount == 0 );
  256. m_nOffset = 0;
  257. m_nCount = 0;
  258. }
  259. else
  260. {
  261. m_nOffset = ((intp)pData) - (intp)&m_nOffset;
  262. m_nCount = nCount;
  263. }
  264. }
  265. void SwapMemberBytes()
  266. {
  267. m_nCount = DWordSwapC( m_nCount );
  268. m_nOffset = DWordSwapC( m_nOffset );
  269. }
  270. private:
  271. CResourceArrayBase(const CResourceArrayBase&rThat ){} // private: we don't want to recompute offsets every time we copy a structure
  272. protected:
  273. int32 m_nOffset;
  274. uint32 m_nCount;
  275. };
  276. template < typename T >
  277. class CResourceArray: public CResourceArrayBase
  278. {
  279. public:
  280. CResourceArray(): CResourceArrayBase() {}
  281. private:
  282. CResourceArray( const CResourceArray<T>&rThat ){} // private: we don't want to recompute offsets every time we copy a structure
  283. public:
  284. const T& operator []( int nIndex ) const
  285. {
  286. AssertDbg( (uint)nIndex < m_nCount );
  287. return this->GetPtr()[nIndex];
  288. }
  289. T& operator []( int nIndex )
  290. {
  291. AssertDbg( (uint)nIndex < m_nCount );
  292. return this->GetPtr()[nIndex];
  293. }
  294. const T& Element( int nIndex ) const
  295. {
  296. AssertDbg( (uint)nIndex < m_nCount );
  297. return this->GetPtr()[nIndex];
  298. }
  299. T& Element( int nIndex )
  300. {
  301. AssertDbg( (uint)nIndex < m_nCount );
  302. return this->GetPtr()[nIndex];
  303. }
  304. CResourceArray<T>& operator = ( const CLockedResource<T> & lockedResource )
  305. {
  306. m_nOffset = ( lockedResource.Count() ) ? ( ((intp)(const T*)lockedResource) - (intp)&m_nOffset ) : 0;
  307. m_nCount = lockedResource.Count();
  308. return *this;
  309. }
  310. CResourceArray<T>& operator = ( const CResourceArray<T> & that )
  311. {
  312. m_nOffset = ( that.Count() ) ? ( ((intp)(const T*)that.GetPtr()) - (intp)&m_nOffset ) : 0;
  313. m_nCount = that.Count();
  314. return *this;
  315. }
  316. const T* GetPtr() const
  317. {
  318. return ( const T* )GetRawPtr();
  319. }
  320. T* GetPtr()
  321. {
  322. return ( T* )GetRawPtr();
  323. }
  324. const T* Base() const
  325. {
  326. return ( const T* )GetRawPtr();
  327. }
  328. T* Base()
  329. {
  330. return ( T* )GetRawPtr();
  331. }
  332. bool IsEmpty() const
  333. {
  334. return m_nCount == 0;
  335. }
  336. operator CLockedResource<T> () {return CLockedResource<T>( GetPtr(), Count() ) ; }
  337. // Temporary functions
  338. void Unsafe_OutOfBoundsAllocate( int nCount )
  339. {
  340. const T* pAlloc = new T[nCount];
  341. m_nOffset = ((intp)(const T*)pAlloc) - (intp)&m_nOffset;
  342. m_nCount = nCount;
  343. }
  344. void Unsafe_OutOfBoundsPurgeAndFreeRPs()
  345. {
  346. for ( uint32 i = 0; i < m_nCount; ++i )
  347. {
  348. Element(i).Unsafe_OutOfBoundsFree();
  349. }
  350. delete[] GetPtr();
  351. }
  352. // Remove all the NULL pointers from this resource array and shorten it (without changing any allocations)
  353. // (assumes that the elements of the array can be equality-tested with NULL)
  354. inline void CoalescePointerArrayInPlace()
  355. {
  356. int nValidElements = 0;
  357. int nArrayLen = Count();
  358. T* pBase = GetPtr();
  359. for ( int i = 0; i < nArrayLen; ++i )
  360. {
  361. if ( pBase[i] == 0 )
  362. continue;
  363. if ( nValidElements != i )
  364. {
  365. pBase[nValidElements].SetRawPtr( pBase[i].GetRawPtr() );
  366. }
  367. nValidElements++;
  368. }
  369. m_nCount = nValidElements;
  370. }
  371. // Enable support for range-based loops in C++ 11
  372. inline T* begin()
  373. {
  374. return GetPtr();
  375. }
  376. inline const T* begin() const
  377. {
  378. return GetPtr( );
  379. }
  380. inline T* end()
  381. {
  382. return GetPtr() + m_nCount;
  383. }
  384. inline const T* end() const
  385. {
  386. return GetPtr( ) + m_nCount;
  387. }
  388. };
  389. //////////////////////////////////////////////////////////////////////////
  390. // this class may be useful at runtime to use fast serialize interface (without data linking)
  391. //
  392. class CResourceStream
  393. {
  394. public:
  395. // Constructor, destructor
  396. CResourceStream( );
  397. virtual ~CResourceStream( ) {} // make sure to implement proper cleanup in derived classes
  398. // Methods used to allocate space in the stream
  399. // just use Allocate<uint8>(100) to simply allocate 100 bytes of crap
  400. void *AllocateBytes( uint nCount );
  401. template <typename T> CLockedResource<T> Allocate( uint count = 1 );
  402. template <typename T> CUnlockedResource<T> AllocateUnaligned( uint count = 1 );
  403. // Methods that write data into the stream
  404. template <typename T> CLockedResource<T> Write( const T &x );
  405. template <typename T> CUnlockedResource<T> WriteUnaligned( const T &x );
  406. CLockedResource<float> WriteFloat( float x );
  407. CLockedResource<uint64> WriteU64( uint64 x );
  408. CLockedResource<uint32> WriteU32( uint32 x );
  409. CLockedResource<uint16> WriteU16( uint16 x );
  410. CLockedResource<uint8> WriteByte( byte x );
  411. CLockedResource<char> WriteString( const char *pString );
  412. CLockedResource<char> WriteStringMaxLen( const char *pString, int nMaxLen ); // will never read beyond pString[nMaxLen-1] and will force-null-terminate if necessary
  413. // Methods to force alignment of the next data written into the stream
  414. void Align( uint nAlignment, int nOffset = 0 );
  415. void AlignPointer();
  416. // How much data have we written into the stream?
  417. uint32 Tell() const;
  418. uint32 Tell( const void * pPast )const;
  419. const void *TellPtr() const;
  420. void Rollback( uint32 nPreviousTell );
  421. void Rollback( const void *pPreviousTell );
  422. void* Compile( );
  423. template <class Memory>
  424. void* CompileToMemory( Memory &memory );
  425. uint GetTotalSize() const;
  426. void Barrier() {} // no pointers crossing barriers allowed! all pointers are invalidated
  427. void PrintStats();
  428. void ClearStats();
  429. // This is the max alignment ever used within the stream
  430. uint GetStreamAlignment() const;
  431. void* GetDataPtr( uint Offset = 0 );
  432. template <typename T> T* GetDataPtrTypeAligned( uint Offset );
  433. void Clear();
  434. protected:
  435. void EnsureAvailable( uint nAddCapacity )
  436. {
  437. Assert( nAddCapacity < 0x40000000 ); // we don't support >1Gb of data yet
  438. uint nNewCommit = m_nUsed + nAddCapacity;
  439. if ( nNewCommit > m_nCommitted )
  440. {
  441. Commit( nNewCommit ); // Commit is only called when necessary, as it may be expensive
  442. }
  443. }
  444. // the only logic entry the derived class needs to reimplement, besides constructor+destructor pair.
  445. // depending on how expensive it is to call this function, it may commit (allocate) large chunks of extra memory, that's totally ok
  446. virtual void Commit( uint nNewCommit ) = 0;
  447. template <typename T> friend class CUnlockedResource;
  448. protected:
  449. uint8 *m_pData; // the reserved virtual address space address; or just the start of allocated block of memory if virtual memory is not being used
  450. uint m_nCommitted; // how much memory was already committed (or allocated, in case no virtual memory is being used)
  451. uint m_nUsed; // this is the amount of currently used/allocated data, in bytes; may be unaligned
  452. uint m_nAlignBits; // the ( max alignment - 1 ) of the current block of data
  453. uint m_nMaxAlignment;
  454. };
  455. class CResourceStreamVM: public CResourceStream
  456. {
  457. public:
  458. // Constructor, destructor
  459. CResourceStreamVM( uint nReserveSize = 16 * 1024 * 1024 );
  460. virtual ~CResourceStreamVM( ) OVERRIDE;
  461. void CloneStream( CResourceStreamVM& copyFromStream );
  462. protected:
  463. virtual void Commit( uint nNewCommit ) OVERRIDE;
  464. void ReserveVirtualMemory( uint nAddressSize );
  465. void ReleaseVirtualMemory( );
  466. enum
  467. {
  468. COMMIT_STEP = 64 * 1024
  469. };
  470. protected:
  471. uint m_nReserved; // the reserved virtual address space for the block of data
  472. };
  473. // use this class to create resources efficiently in runtime using your own allocator
  474. // supply a fixed buffer; it belongs to the caller
  475. class CResourceStreamFixed: public CResourceStream
  476. {
  477. private:
  478. bool m_bOwnMemory;
  479. public:
  480. CResourceStreamFixed( uint nPreallocateDataSize );// NOTE: the preallocated data is Zeroed in this constructor
  481. CResourceStreamFixed( void *pPreallocatedData, uint nPreallocatedDataSize ); // NOTE: the preallocated data is Zeroed in this constructor
  482. virtual ~CResourceStreamFixed() OVERRIDE;
  483. int GetSlack(); // remaining bytes
  484. virtual void Commit( uint nNewCommit );
  485. };
  486. class CResourceStreamGrowable: public CResourceStream
  487. {
  488. public:
  489. CResourceStreamGrowable( uint nReserveDataSize );
  490. ~CResourceStreamGrowable( );
  491. virtual void Commit( uint nNewCommit );
  492. uint8 *Detach( )
  493. {
  494. uint8 *pData = m_pData;
  495. m_pData = 0;
  496. m_nCommitted = 0;
  497. m_nUsed = 0;
  498. m_pData = NULL;
  499. return pData;
  500. }
  501. };
  502. class CLockedResourceAutoAggregator
  503. {
  504. protected:
  505. CResourceStreamVM *m_pStream;
  506. const void * m_pTellStart;
  507. uint m_nTellStart;
  508. public:
  509. CLockedResourceAutoAggregator( CResourceStreamVM *pStream, const void * pTellStart )
  510. {
  511. m_pStream = pStream;
  512. m_pTellStart = pTellStart;
  513. m_nTellStart = pStream->Tell( pTellStart );
  514. }
  515. CLockedResource<uint8> GetAggregate()
  516. {
  517. return CLockedResource<uint8>( ( uint8* )m_pTellStart, m_pStream->Tell() - m_nTellStart );
  518. }
  519. };
  520. //-----------------------------------------------------------------------------
  521. // Specialization for strings
  522. //-----------------------------------------------------------------------------
  523. class CResourceString: public CResourcePointer<char>
  524. {
  525. public:
  526. CResourceString& operator = ( const CLockedResource<char> & lockedCharResource )
  527. {
  528. SetPtr( (const char*)lockedCharResource );
  529. return *this;
  530. }
  531. CResourceString& operator = ( const CResourcePointerBase & lockedCharResource )
  532. {
  533. SetPtr( ( const char* )lockedCharResource.GetRawPtr() );
  534. return *this;
  535. }
  536. // empty strings can be serialized as a null pointer (instead of a pointer to '\0')
  537. const char* GetPtr() const
  538. {
  539. if ( GetRawPtr() == NULL )
  540. {
  541. return "";
  542. }
  543. else
  544. {
  545. return ( const char* )GetRawPtr();
  546. }
  547. }
  548. char* GetPtr()
  549. {
  550. if ( GetRawPtr() == NULL )
  551. {
  552. return ( char* )"";
  553. }
  554. else
  555. {
  556. return ( char* )GetRawPtr();
  557. }
  558. }
  559. operator const char* ()const
  560. {
  561. if ( GetRawPtr() == NULL )
  562. {
  563. return "";
  564. }
  565. else
  566. {
  567. return ( char* )GetRawPtr();
  568. }
  569. }
  570. void Unsafe_OutOfBoundsCopy( const char* pStr )
  571. {
  572. int nLen = V_strlen(pStr);
  573. char* pAlloc = new char[nLen+1];
  574. V_strcpy( pAlloc, pStr );
  575. SetPtr( pAlloc );
  576. }
  577. bool IsEmpty() const
  578. {
  579. return IsNull() || !*GetUncheckedRawPtr();
  580. }
  581. private:
  582. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  583. // Disable comparison operators for ResourceStrings, otherwise they'll
  584. // be implicitly converted to char* (we don't want to actually implement
  585. // these because it's ambiguous whether it's case-sensitive or not.
  586. bool operator==( const CResourceString &rhs ) const;
  587. bool operator!=( const CResourceString &rhs ) const;
  588. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  589. };
  590. //-----------------------------------------------------------------------------
  591. // Inline methods
  592. //-----------------------------------------------------------------------------
  593. template <typename T>
  594. inline CLockedResource<T> CResourceStream::Allocate( uint nCount )
  595. {
  596. // TODO: insert reflection code here
  597. uint nAlignment = VALIGNOF( T );
  598. Align( nAlignment );
  599. T *ptr = AllocateUnaligned< T >( nCount );
  600. // Construct
  601. for ( uint i = 0; i < nCount; i++ )
  602. {
  603. Construct< T >( &ptr[ i ] );
  604. }
  605. return CLockedResource<T>( ptr, nCount );
  606. }
  607. template <typename T>
  608. inline CUnlockedResource<T> CResourceStream::AllocateUnaligned( uint nCount )
  609. {
  610. // Allocate
  611. return CUnlockedResource< T >( this, ( T* )AllocateBytes( nCount * sizeof( T ) ), nCount );
  612. }
  613. inline void CResourceStream::AlignPointer()
  614. {
  615. Align( sizeof( intp ) );
  616. }
  617. template <typename T>
  618. inline CUnlockedResource<T> CResourceStream::WriteUnaligned( const T &x )
  619. {
  620. CUnlockedResource<T> pMemory = AllocateUnaligned<T>( );
  621. V_memcpy( pMemory, &x, sizeof( T ) );
  622. return pMemory;
  623. }
  624. template <typename T>
  625. inline CLockedResource<T> CResourceStream::Write( const T &x )
  626. {
  627. CLockedResource<T> memory = Allocate<T>();
  628. *memory = x;
  629. return memory;
  630. }
  631. inline CLockedResource<float> CResourceStream::WriteFloat( float x )
  632. {
  633. return Write( x );
  634. }
  635. inline CLockedResource<uint64> CResourceStream::WriteU64( uint64 x )
  636. {
  637. return Write( x );
  638. }
  639. inline CLockedResource<uint32> CResourceStream::WriteU32( uint32 x )
  640. {
  641. return Write( x );
  642. }
  643. inline CLockedResource<uint16> CResourceStream::WriteU16( uint16 x )
  644. {
  645. return Write( x );
  646. }
  647. inline CLockedResource<uint8> CResourceStream::WriteByte( byte x )
  648. {
  649. return Write( x );
  650. }
  651. inline CLockedResource<char> CResourceStream::WriteString( const char *pString )
  652. {
  653. int nLength = pString ? V_strlen( pString ) : 0;
  654. if ( nLength == 0 )
  655. {
  656. return CLockedResource<char>( NULL, 0 );
  657. }
  658. else
  659. {
  660. CLockedResource<char> memory = Allocate<char>(nLength+1);
  661. memcpy( (char*)memory, pString, nLength+1 );
  662. return memory;
  663. }
  664. }
  665. inline CLockedResource<char> CResourceStream::WriteStringMaxLen( const char *pString, int nMaxLen )
  666. {
  667. int nStrLen = 0;
  668. while ( pString && nStrLen < nMaxLen && pString[nStrLen] != '\0' )
  669. {
  670. nStrLen++;
  671. }
  672. if ( nStrLen == 0 )
  673. {
  674. return CLockedResource<char>( NULL, 0 );
  675. }
  676. else
  677. {
  678. CLockedResource<char> memory = Allocate<char>( nStrLen + 1 ); // +1 for null term
  679. memcpy( (char*)memory, pString, nStrLen );
  680. ((char*)memory)[nStrLen] = '\0';
  681. return memory;
  682. }
  683. }
  684. inline uint32 CResourceStream::Tell() const
  685. {
  686. return m_nUsed;
  687. }
  688. inline void CResourceStream::Rollback( uint32 nPreviousTell )
  689. {
  690. Assert( nPreviousTell <= m_nUsed );
  691. m_nUsed = nPreviousTell;
  692. }
  693. inline void CResourceStream::Rollback( const void *pPreviousTell )
  694. {
  695. Assert( pPreviousTell > m_pData && pPreviousTell <= m_pData + m_nUsed );
  696. m_nUsed = ( ( uint8* ) pPreviousTell ) - m_pData;
  697. }
  698. inline uint32 CResourceStream::Tell( const void * pPast )const
  699. {
  700. // we do not reallocate the reserved memory , so the pointers do not invalidate and m_pData stays the same, and all absolute addresses stay the same in memory
  701. uint nTell = uintp( pPast ) - uintp( m_pData );
  702. AssertDbg( nTell <= m_nUsed );
  703. return nTell;
  704. }
  705. inline const void *CResourceStream::TellPtr() const
  706. {
  707. return m_pData + m_nUsed;
  708. }
  709. inline void* CResourceStream::Compile( )
  710. {
  711. return m_pData;
  712. }
  713. template< class Memory >
  714. inline void* CResourceStream::CompileToMemory( Memory &memory )
  715. {
  716. memory.Init( 0, GetTotalSize() );
  717. V_memcpy( memory.Base(), Compile(), GetTotalSize() );
  718. return memory.Base();
  719. }
  720. inline uint CResourceStream::GetTotalSize() const
  721. {
  722. return m_nUsed;
  723. }
  724. inline uint CResourceStream::GetStreamAlignment() const
  725. {
  726. return m_nMaxAlignment;
  727. }
  728. inline void* CResourceStream::GetDataPtr( uint nOffset )
  729. {
  730. if ( nOffset > m_nUsed )
  731. {
  732. return NULL;
  733. }
  734. else
  735. {
  736. return m_pData + nOffset;
  737. }
  738. }
  739. inline void CResourceStream::Clear()
  740. {
  741. V_memset( m_pData, 0, m_nCommitted );
  742. m_nUsed = 0;
  743. }
  744. template <typename T>
  745. inline T* CResourceStream::GetDataPtrTypeAligned( uint Offset )
  746. {
  747. uint nAlignment = VALIGNOF( T );
  748. Offset += ( ( 0 - Offset ) & ( nAlignment - 1 ) );
  749. return ( T* ) GetDataPtr( Offset );
  750. }
  751. template <typename T>
  752. inline const T* OffsetPointer( const T *p, intp nOffsetBytes )
  753. {
  754. return p ? ( const T* )( intp( p ) + nOffsetBytes ) : NULL;
  755. }
  756. template <typename T>
  757. inline T* ConstCastOffsetPointer( const T *p, intp nOffsetBytes )
  758. {
  759. return p ? ( T* ) ( intp( p ) + nOffsetBytes ) : NULL;
  760. }
  761. template < typename T >
  762. inline CLockedResource< T > CloneArray( CResourceStream *pStream, const T *pArray, uint nCount )
  763. {
  764. if ( nCount > 0 && pArray )
  765. {
  766. CLockedResource< T > pOut = pStream->Allocate< T >( nCount );
  767. V_memcpy( pOut, pArray, nCount * sizeof( T ) );
  768. return pOut;
  769. }
  770. else
  771. {
  772. return CLockedResource< T >( );
  773. }
  774. }
  775. inline int CResourceStreamFixed::GetSlack( )
  776. {
  777. return m_nCommitted - m_nUsed;
  778. }
  779. template < typename T >
  780. CUnlockedResource< T >::CUnlockedResource( CResourceStream *pStream, T *pData, uint nCount ):
  781. m_pStream( pStream ),
  782. m_nOffset( ( ( uint8* ) pData ) - pStream->m_pData ),
  783. m_nCount( nCount )
  784. {
  785. AssertDbg( ( ( uint8* ) pData ) >= pStream->m_pData && ( ( uint8* ) ( pData + nCount ) <= pStream->m_pData + pStream->m_nUsed ) );
  786. AssertDbg( m_nOffset <= pStream->m_nUsed && m_nOffset + nCount * sizeof( T ) <= pStream->m_nUsed );
  787. }
  788. template < typename T >
  789. inline T* CUnlockedResource< T >::GetPtr( )
  790. {
  791. return ( T* )m_pStream->GetDataPtr( m_nOffset );
  792. }
  793. template < typename T >
  794. inline const T* CUnlockedResource< T >::GetPtr( )const
  795. {
  796. return ( const T * )m_pStream->GetDataPtr( m_nOffset );
  797. }
  798. #endif // RESOURCESTREAM_H