Windows NT 4.0 source code leak
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.

188 lines
3.3 KiB

4 years ago
  1. // implementation of class Buffer
  2. #include <stdlib.h>
  3. #include "pool.h"
  4. class Buffer {
  5. public:
  6. Buffer(void (*pfn)(void*, void*, void*) = 0, void* pfnArg = 0)
  7. : cb(0), pbStart(0), pbEnd(0), pfnMove(pfn), pfnMoveArg(pfnArg) {}
  8. ~Buffer();
  9. BOOL Alloc(CB cbIn);
  10. BOOL Append(PB pbIn, CB cbIn, OUT PB* ppbOut = 0);
  11. BOOL AppendFmt(SZ szFmt, ...);
  12. BOOL Reserve(CB cbIn, OUT PB* ppbOut = 0);
  13. PB Start() const { return pbStart; }
  14. PB End() const { return pbEnd; }
  15. CB Size() const { return pbEnd - pbStart; }
  16. void Free();
  17. void Clear()
  18. {
  19. if (pbStart)
  20. {
  21. memset(pbStart, 0, pbEnd - pbStart);
  22. setPbExtent(pbStart, pbStart);
  23. }
  24. }
  25. private:
  26. enum { cbPage = 4096 };
  27. CB cbRoundUp(CB cb, CB cbMult) { return (cb + cbMult-1) & ~(cbMult-1); }
  28. BOOL grow(CB dcbGrow);
  29. BOOL setPbExtent(PB pbStartNew, PB pbEndNew) {
  30. if (!pbStartNew)
  31. return FALSE;
  32. PB pbStartOld = pbStart;
  33. pbStart = pbStartNew;
  34. pbEnd = pbEndNew;
  35. if (pbStartOld != pbStartNew && pfnMove)
  36. (*pfnMove)(pfnMoveArg, pbStartOld, pbStartNew);
  37. return TRUE;
  38. }
  39. PB pbStart;
  40. PB pbEnd;
  41. CB cb;
  42. void (*pfnMove)(void* pArg, void* pOld, void* pNew);
  43. void* pfnMoveArg;
  44. };
  45. inline Buffer::~Buffer()
  46. {
  47. if (pbStart) {
  48. Free();
  49. }
  50. }
  51. inline BOOL Buffer::Alloc(CB cbNew)
  52. {
  53. dassert(cbNew > 0);
  54. if (pbStart)
  55. return FALSE;
  56. PB pbNew = new (zeroed) BYTE[cbNew];
  57. if (setPbExtent(pbNew, pbNew)) {
  58. cb = cbNew;
  59. return TRUE;
  60. }
  61. return FALSE;
  62. }
  63. inline BOOL Buffer::grow(CB dcbGrow)
  64. {
  65. CB cbNew = cbRoundUp(cb + __max(cbPage + dcbGrow, cb/2), cbPage);
  66. PB pbNew = new BYTE[cbNew];
  67. if (pbNew) {
  68. cb = cbNew;
  69. CB cbUsed = pbEnd - pbStart;
  70. memcpy(pbNew, pbStart, cbUsed);
  71. memset(pbNew + cbUsed, 0, cb - cbUsed);
  72. delete [] pbStart;
  73. setPbExtent(pbNew, pbNew + cbUsed);
  74. return TRUE;
  75. }
  76. return FALSE;
  77. }
  78. inline void Buffer::Free()
  79. {
  80. delete [] pbStart;
  81. setPbExtent(0, 0);
  82. cb = 0;
  83. }
  84. inline BOOL Buffer::Reserve(CB cbIn, OUT PB* ppbOut)
  85. {
  86. if (cbIn < 0)
  87. return FALSE;
  88. #if 0 // backout bryant's alignment
  89. cbIn = (cbIn + 3) & ~3; // Round up for alignment
  90. #endif
  91. if (pbEnd + cbIn > pbStart + cb) {
  92. if (!grow(cbIn)) {
  93. return FALSE;
  94. }
  95. }
  96. if (ppbOut)
  97. *ppbOut = pbEnd;
  98. setPbExtent(pbStart, pbEnd + cbIn);
  99. return TRUE;
  100. }
  101. inline BOOL Buffer::Append(PB pbIn, CB cbIn, OUT PB* ppbOut)
  102. {
  103. if (!pbIn)
  104. return FALSE;
  105. PB pb;
  106. if (!Reserve(cbIn, &pb))
  107. return FALSE;
  108. if (ppbOut)
  109. *ppbOut = pb;
  110. memcpy(pb, pbIn, cbIn);
  111. return TRUE;
  112. }
  113. inline BOOL Buffer::AppendFmt(SZ szFmt, ...)
  114. {
  115. va_list args;
  116. va_start(args, szFmt);
  117. for (;;) {
  118. switch (*szFmt++) {
  119. case 0:
  120. va_end(args);
  121. return TRUE;
  122. case 'b': {
  123. BYTE b = va_arg(args, BYTE);
  124. if (!Append(&b, sizeof b, 0))
  125. goto fail;
  126. break;
  127. }
  128. case 's': {
  129. USHORT us = va_arg(args, USHORT);
  130. if (!Append((PB)&us, sizeof us, 0))
  131. goto fail;
  132. break;
  133. }
  134. case 'l': {
  135. ULONG ul = va_arg(args, ULONG);
  136. if (!Append((PB)&ul, sizeof ul, 0))
  137. goto fail;
  138. break;
  139. }
  140. case 'f': {
  141. static BYTE zeroes[3] = { 0, 0, 0 };
  142. int cb = va_arg(args, int);
  143. assert(cb <= sizeof(zeroes));
  144. if (cb != 0 && !Append(zeroes, cb, 0))
  145. goto fail;
  146. break;
  147. }
  148. case 'z': {
  149. SZ sz = va_arg(args, SZ);
  150. int cb = strlen(sz);
  151. if (!Append((PB)sz, cb, 0))
  152. goto fail;
  153. break;
  154. }
  155. default:
  156. assert(0);
  157. break;
  158. }
  159. }
  160. fail:
  161. va_end(args);
  162. return FALSE;
  163. }