00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00023 #ifndef __MESSAGE_H
00024 #define __MESSAGE_H
00025
00026 #include <deque>
00027 #include <vector>
00028 #include <cassert>
00029
00030 #include "Shared.h"
00031
00032 #define BUFFER_BLOCK_SIZE 1024
00033
00034 class cMessage
00035 {
00036 class cBlock
00037 {
00038 friend class cMessage;
00039
00040 mutable BYTE *m_pStart, *m_pUsed;
00041
00042 public:
00043
00044 cBlock ();
00045 cBlock ( const cBlock &from );
00046 ~cBlock ();
00047
00048 BOOL pasteData ( BYTE *&pData, int &nBytes );
00049 int getAlign ( int nBoundary ) const;
00050 BOOL pasteAlign ( int &nBytes );
00051
00052 size_t getUsed () const
00053 {
00054 return ( m_pUsed - m_pStart );
00055 }
00056
00057 BOOL getData ( size_t &nOffset, size_t &nLength, BYTE * &pBuffer ) const;
00058
00059 private:
00060
00061 cBlock &operator= ( const cBlock & );
00062 };
00063
00064 typedef std::deque< cBlock > cBlockList;
00065 cBlockList m_blocks;
00066
00067
00068 public:
00069 cMessage ();
00070 cMessage (BYTE* pbPacket, int nSize);
00071 ~cMessage( )
00072 {
00073 while ( !m_blocks.empty( ) )
00074 m_blocks.pop_front( );
00075 }
00076
00077
00078 void pasteData ( BYTE *pData, int nBytes );
00079 void pasteAlign ( int nBoundary );
00080 void pasteString ( const char *str );
00081
00082
00083 size_t getSize () const;
00084 void getData ( size_t nOffset, size_t nLength, BYTE *pBuffer ) const;
00085
00086 template< class DataT >
00087 inline void paste ( DataT dt )
00088 {
00089 pasteData ( reinterpret_cast< BYTE * > ( &dt ), sizeof ( DataT ) );
00090 }
00091
00092
00093 template<>
00094 inline void paste ( char *str )
00095 {
00096 pasteString ( static_cast< const char * >( str ) );
00097 }
00098
00099 template<>
00100 inline void paste ( const char *str )
00101 {
00102 pasteString ( static_cast< const char * >( str ) );
00103 }
00104
00105
00106 template< class ItemT >
00107 void paste ( std::vector< ItemT > &vec )
00108 {
00109 for ( std::vector< ItemT >::iterator i = vec.begin(); i != vec.end(); ++ i )
00110 i->encode ( *this );
00111
00112
00113 pasteAlign ( sizeof ( unsigned long ) );
00114 }
00115
00116 void CannedData( BYTE *pbData, DWORD dwSize )
00117 {
00118 pasteData( pbData, dwSize );
00119 }
00120
00121 inline BYTE& operator[]( int iElem ) const
00122 {
00123
00124
00125
00126
00127 return (m_blocks.begin( ) + (iElem / BUFFER_BLOCK_SIZE))->m_pStart[iElem % BUFFER_BLOCK_SIZE];
00128 }
00129
00130 private:
00131 class cBlockDispenser
00132 {
00133 HANDLE m_hHeap;
00134
00135 public:
00136 cBlockDispenser ();
00137 ~cBlockDispenser ();
00138
00139 BYTE *get ();
00140 void release (BYTE *pBlock);
00141 };
00142
00143 static cBlockDispenser g_dispenser;
00144
00145 friend cBlock;
00146 };
00147
00148 template< class DataT >
00149 cMessage &operator<< ( cMessage &buf, DataT t )
00150 {
00151 buf.paste ( t );
00152 return buf;
00153 }
00154
00155 #endif // #ifndef __MESSAGE_H