Leaked source code of windows server 2003
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.

218 lines
6.0 KiB

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