Source code of Windows XP (NT5)
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.

270 lines
6.5 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. buffer.hxx
  5. Abstract:
  6. This file contains declaration of BUFFER and BUFFER_CHAIN classes.
  7. Author:
  8. Murali R. Krishnan (MuraliK) 9-July-1996 Recreated from old buffer.hxx
  9. Revision History:
  10. --*/
  11. #ifndef _BUFFER_HXX_
  12. #define _BUFFER_HXX_
  13. # include <nt.h>
  14. # include <ntrtl.h>
  15. # include <nturtl.h>
  16. # include <windows.h>
  17. # if !defined( dllexp)
  18. # define dllexp __declspec( dllexport)
  19. # endif // !defined( dllexp)
  20. /*************************************************************************
  21. NAME: BUFFER (buf)
  22. SYNOPSIS: A resizable object which lives in the application heap.
  23. It uses a local inlined buffer object to cache the commonly
  24. used allocation units and allows storage of
  25. INLINED_BUFFER_LEN bytes.
  26. Upon construction, the buffer takes a requested size in
  27. bytes; it allocates storage sufficient to hold that size.
  28. The client can later change this size with Resize, Trim,
  29. and FillOut. QuerySize returns the current size of
  30. the buffer; QueryPtr returns a pointer to its storage.
  31. Note that a buffer may have size 0, in which case it
  32. keeps no allocated storage.
  33. INTERFACE: BUFFER() - Constructor, naming initial size in bytes
  34. QuerySize() - return size in bytes
  35. QueryPtr() - return pointer to data buffer
  36. Resize() - resize the object to the given number
  37. of bytes. Returns TRUE if the resize was
  38. successful; otherwise returns FALSE (use
  39. GetLastError for error code)
  40. **************************************************************************/
  41. /*
  42. I picked up the INLINED_BUFFER_LEN based on following factors
  43. 1) W3svc was using buffers of length < 16 bytes for 70% of transactions
  44. 2) A cache line is usually 32 bytes or multiples thereof and
  45. it may have subblocking of about 16/32 bytes.
  46. Choice of 16 bytes allows the BUFFER & STR objects to fit into
  47. even a conservative L1 cache line
  48. August 1999: upped from 16 to 32
  49. */
  50. # define INLINED_BUFFER_LEN (32)
  51. class dllexp BUFFER {
  52. private:
  53. BYTE * m_pb; // pointer to storage
  54. UINT m_cb; // size of storage, as requested by client
  55. DWORD m_fIsDynAlloced : 1; // is m_pb dynamically allocated ?
  56. DWORD m_fValid : 1; // is this object valid
  57. // Created this union so that m_rgb is aligned on 8byte boundary (to correctly align pointers stored in rgb data).
  58. union {
  59. BYTE m_rgb[INLINED_BUFFER_LEN]; // the default buffer object
  60. VOID * pVoid;
  61. };
  62. BOOL GetNewStorage( UINT cbRequested );
  63. BOOL ReallocStorage( UINT cbNewlyRequested );
  64. VOID VerifyState(VOID) const;
  65. BOOL IsDynAlloced(VOID) const { return ( m_fIsDynAlloced); }
  66. protected:
  67. VOID SetValid( BOOL fValid) { m_fValid = ((fValid) ? 1 : 0); }
  68. BOOL IsValid( VOID) const { return ( m_fValid); }
  69. public:
  70. BUFFER( UINT cbRequested = 0 )
  71. : m_pb (m_rgb),
  72. m_cb (INLINED_BUFFER_LEN),
  73. m_fIsDynAlloced (0),
  74. m_fValid (1)
  75. {
  76. m_rgb[0] = '\0';
  77. if ( cbRequested > INLINED_BUFFER_LEN ) {
  78. GetNewStorage(cbRequested);
  79. }
  80. }
  81. // This constructor is used for most scratch BUFFER objects on stack
  82. // BUFFER does not free this pbInit on its own.
  83. BUFFER( BYTE * pbInit, UINT cbInit)
  84. : m_pb (pbInit),
  85. m_cb (cbInit),
  86. m_fIsDynAlloced (0),
  87. m_fValid (1)
  88. {
  89. m_pb[0] = '\0';
  90. }
  91. ~BUFFER(void);
  92. VOID * QueryPtr() const { return ( static_cast <VOID *> (m_pb) ); }
  93. UINT QuerySize() const { return m_cb; }
  94. //
  95. // If a resize is needed, added cbSlop to it
  96. //
  97. BOOL Resize( UINT cbNewSize )
  98. {
  99. if ( cbNewSize <= QuerySize() )
  100. {
  101. return TRUE;
  102. }
  103. return ReallocStorage( cbNewSize );
  104. }
  105. BOOL Resize( UINT cbNewSize,
  106. UINT cbSlop )
  107. {
  108. if ( cbNewSize <= QuerySize() )
  109. {
  110. return TRUE;
  111. }
  112. return ReallocStorage( cbNewSize + cbSlop );
  113. }
  114. VOID FreeMemory( VOID );
  115. private:
  116. BOOL ResizeAux( UINT cbNewReqestedSize,
  117. UINT cbSlop);
  118. }; // class BUFFER
  119. //
  120. // Quick macro for declaring a BUFFER that will use stack memory of <size>
  121. // bytes. If the buffer overflows then a heap buffer will be allocated
  122. //
  123. #define STACK_BUFFER( name, size ) \
  124. BYTE __ab##name[size]; \
  125. BUFFER name( __ab##name, sizeof( __ab##name ))
  126. //
  127. // Unlike the STACK_BUFFER macro, this template can be used for member
  128. // variables in classes.
  129. //
  130. template <size_t N>
  131. class dllexp BUFFER_N : public BUFFER
  132. {
  133. private:
  134. BYTE m_abData[N]; // Actual data
  135. public:
  136. BUFFER_N()
  137. : BUFFER(m_abData, N)
  138. {}
  139. }; // class BUFFER_N<N>
  140. //
  141. // NYI: This should be probably moved over to ODBC which is the only user.
  142. // BUFFER_CHAIN_ITEM is a single item in a chain of buffers
  143. //
  144. class dllexp BUFFER_CHAIN_ITEM : public BUFFER
  145. {
  146. friend class BUFFER_CHAIN;
  147. public:
  148. BUFFER_CHAIN_ITEM( UINT cbReq = 0 )
  149. : BUFFER( cbReq ),
  150. _cbUsed( 0 )
  151. { _ListEntry.Flink = NULL; }
  152. ~BUFFER_CHAIN_ITEM()
  153. { if ( _ListEntry.Flink )
  154. RemoveEntryList( &_ListEntry );
  155. }
  156. DWORD QueryUsed( VOID ) const
  157. { return _cbUsed; }
  158. VOID SetUsed( DWORD cbUsed )
  159. { _cbUsed = cbUsed; }
  160. private:
  161. LIST_ENTRY _ListEntry;
  162. DWORD _cbUsed; // Bytes of valid data in this buffer
  163. VOID VerifyState() const;
  164. }; // class BUFFER_CHAIN_ITEM
  165. class dllexp BUFFER_CHAIN
  166. {
  167. public:
  168. BUFFER_CHAIN()
  169. { InitializeListHead( &_ListHead ); }
  170. ~BUFFER_CHAIN()
  171. { DeleteChain(); }
  172. BOOL AppendBuffer( BUFFER_CHAIN_ITEM * pBCI );
  173. //
  174. // Returns total number of bytes freed by deleting all of the buffer
  175. // chain items
  176. //
  177. DWORD DeleteChain();
  178. //
  179. // Enums buffer chain. Pass pBCI as NULL on first call, pass return
  180. // value till NULL on subsequent calls
  181. //
  182. BUFFER_CHAIN_ITEM * NextBuffer( BUFFER_CHAIN_ITEM * pBCI );
  183. //
  184. // Gives back total number of bytes allocated by chain (includes unused
  185. // bytes)
  186. //
  187. DWORD CalcTotalSize( BOOL fUsed = FALSE ) const;
  188. private:
  189. LIST_ENTRY _ListHead;
  190. }; // class BUFFER_CHAIN
  191. #endif // _BUFFER_HXX_