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.

258 lines
7.4 KiB

  1. #if !defined(FUSION_ARRAYHELP_H_INCLUDED_)
  2. #define FUSION_ARRAYHELP_H_INCLUDED_
  3. #if _MSC_VER > 1000
  4. #pragma once
  5. #endif // _MSC_VER > 1000
  6. #include <windows.h>
  7. #include <oleauto.h>
  8. #include "fusionheap.h"
  9. #include "fusiontrace.h"
  10. //
  11. // arrayhelp.h
  12. //
  13. // Helper function(s) to deal with growable arrays.
  14. //
  15. // Users of this utility should provide explicit template
  16. // specializations for classes for which you can safely (without
  17. // possibility of failure) transfer the contens from a source
  18. // instance to a destination instance, leaving the source "empty".
  19. //
  20. // If moving the data may fail, you must provide a specialization
  21. // of FusionCopyContents() which returns an appropriate HRESULT
  22. // on failure.
  23. //
  24. //
  25. // C++ note:
  26. //
  27. // the C++ syntax for explicit function template specialization
  28. // is:
  29. //
  30. // template <> BOOLEAN FusionCanMoveContents<CFoo>(CFoo *p) { UNUSED(p); return TRUE; }
  31. //
  32. #if !defined(FUSION_UNUSED)
  33. #define FUSION_UNUSED(x) (x)
  34. #endif
  35. //
  36. // The default implementation just does assignment which may not fail;
  37. // you can (and must if assignment may fail) specialize as you like to
  38. // do something that avoids data copies; you may assume that the source
  39. // element will be destroyed momentarily.
  40. //
  41. //
  42. // The FusionCanMemcpyContents() template function is used to determine
  43. // if a class is trivial enough that a raw byte transfer of the old
  44. // contents to the new contents is sufficient. The default is that the
  45. // assignment operator is used as that is the only safe alternative.
  46. //
  47. template <typename T>
  48. inline bool
  49. FusionCanMemcpyContents(
  50. T *ptDummyRequired = NULL
  51. )
  52. {
  53. FUSION_UNUSED(ptDummyRequired);
  54. return false;
  55. }
  56. //
  57. // The FusionCanMoveContents() template function is used by the array
  58. // copy template function to optimize for the case that it should use
  59. // FusionMoveContens<T>().
  60. //
  61. // When overriding this function, the general rule is that if the data
  62. // movement may allocate memory etc. that will fail, we need to use the
  63. // FusionCopyContens() member function instead.
  64. //
  65. // It takes a single parameter which is not used because a C++ template
  66. // function must take at least one parameter using the template type so
  67. // that the decorated name is unique.
  68. //
  69. template <typename T>
  70. inline BOOLEAN
  71. FusionCanMoveContents(
  72. T *ptDummyRequired = NULL
  73. )
  74. {
  75. FUSION_UNUSED(ptDummyRequired);
  76. return FALSE;
  77. }
  78. template <> inline BOOLEAN
  79. FusionCanMoveContents<LPWSTR>(LPWSTR *ptDummyRequired)
  80. {
  81. FUSION_UNUSED(ptDummyRequired);
  82. return TRUE;
  83. }
  84. //
  85. // FusionCopyContents is a default implementation of the assignment
  86. // operation from rtSource to rtDestination, except that it may return a
  87. // failure status. Trivial classes which do define an assignment
  88. // operator may just use the default definition, but any copy implementations
  89. // which do anything non-trivial need to provide an explicit specialization
  90. // of FusionCopyContents<T> for their class.
  91. //
  92. template <typename T>
  93. inline BOOL
  94. FusionWin32CopyContents(
  95. T &rtDestination,
  96. const T &rtSource
  97. )
  98. {
  99. rtDestination = rtSource;
  100. return TRUE;
  101. }
  102. //
  103. // FusionAllocateArray() is a helper function that performs array allocation.
  104. //
  105. // It's a separate function so that users of these helpers may provide an
  106. // explicit specialization of the allocation/default construction mechanism
  107. // for an array without replacing all of FusionExpandArray().
  108. //
  109. template <typename T>
  110. inline BOOL
  111. FusionWin32AllocateArray(
  112. SIZE_T nElements,
  113. T *&rprgtElements
  114. )
  115. {
  116. BOOL fSuccess = FALSE;
  117. FN_TRACE_WIN32(fSuccess);
  118. rprgtElements = NULL;
  119. T *prgtElements = NULL;
  120. if (nElements != 0)
  121. IFALLOCFAILED_EXIT(prgtElements = new T[nElements]);
  122. rprgtElements = prgtElements;
  123. fSuccess = TRUE;
  124. Exit:
  125. return fSuccess;
  126. }
  127. //
  128. // FusionFreeArray() is a helper function that performs array deallocation.
  129. //
  130. // It's a separate function so that users of the array helper functions may
  131. // provide an explicit specialization of the deallocation mechanism for an
  132. // array of some particular type without replacing the whole of FusionExpandArray().
  133. //
  134. // We include nElements in the parameters so that overridden implementations
  135. // may do something over the contents of the array before the deallocation.
  136. // The default implementation just uses operator delete[], so nElements is
  137. // unused.
  138. //
  139. template <typename T>
  140. inline VOID
  141. FusionFreeArray(
  142. SIZE_T nElements,
  143. T *prgtElements
  144. )
  145. {
  146. FUSION_UNUSED(nElements);
  147. ASSERT_NTC((nElements == 0) || (prgtElements != NULL));
  148. if (nElements != 0)
  149. FUSION_DELETE_ARRAY(prgtElements);
  150. }
  151. template <> inline VOID FusionFreeArray<LPWSTR>(SIZE_T nElements, LPWSTR *prgtElements)
  152. {
  153. FUSION_UNUSED(nElements);
  154. ASSERT_NTC((nElements == 0) || (prgtElements != NULL));
  155. for (SIZE_T i = 0; i < nElements; i++)
  156. prgtElements[i] = NULL ;
  157. if (nElements != 0)
  158. FUSION_DELETE_ARRAY(prgtElements);
  159. }
  160. template <typename T>
  161. inline BOOL
  162. FusionWin32ResizeArray(
  163. T *&rprgtArrayInOut,
  164. SIZE_T nOldSize,
  165. SIZE_T nNewSize
  166. )
  167. {
  168. BOOL fSuccess = FALSE;
  169. FN_TRACE_WIN32(fSuccess);
  170. T *prgtTempNewArray = NULL;
  171. //
  172. // nMaxCopy is the number of elements currently in the array which
  173. // need to have their values preserved. If we're actually shrinking
  174. // the array, it's the new size; if we're expanding the array, it's
  175. // the old size.
  176. //
  177. const SIZE_T nMaxCopy = (nOldSize > nNewSize) ? nNewSize : nOldSize;
  178. PARAMETER_CHECK((rprgtArrayInOut != NULL) || (nOldSize == 0));
  179. // If the resize is to the same size, complain in debug builds because
  180. // the caller should have been smarter than to call us, but don't do
  181. // any actual work.
  182. ASSERT(nOldSize != nNewSize);
  183. if (nOldSize != nNewSize)
  184. {
  185. // Allocate the new array:
  186. IFW32FALSE_EXIT(::FusionWin32AllocateArray(nNewSize, prgtTempNewArray));
  187. if (::FusionCanMemcpyContents(rprgtArrayInOut))
  188. {
  189. memcpy(prgtTempNewArray, rprgtArrayInOut, sizeof(T) * nMaxCopy);
  190. }
  191. else if (!::FusionCanMoveContents(rprgtArrayInOut))
  192. {
  193. // Copy the body of the array:
  194. for (SIZE_T i=0; i<nMaxCopy; i++)
  195. IFW32FALSE_EXIT(::FusionWin32CopyContents(prgtTempNewArray[i], rprgtArrayInOut[i]));
  196. }
  197. else
  198. {
  199. // Move each of the elements:
  200. for (SIZE_T i=0; i<nMaxCopy; i++)
  201. {
  202. ::FusionWin32CopyContents(prgtTempNewArray[i], rprgtArrayInOut[i]);
  203. }
  204. }
  205. // We're done. Blow away the old array and put the new one in its place.
  206. ::FusionFreeArray(nOldSize, rprgtArrayInOut);
  207. rprgtArrayInOut = prgtTempNewArray;
  208. prgtTempNewArray = NULL;
  209. }
  210. fSuccess = TRUE;
  211. Exit:
  212. if (prgtTempNewArray != NULL)
  213. ::FusionFreeArray(nNewSize, prgtTempNewArray);
  214. return fSuccess;
  215. }
  216. #define MAKE_CFUSIONARRAY_READY(Typename, CopyFunc) \
  217. template<> inline BOOL FusionWin32CopyContents<Typename>(Typename &rtDest, const Typename &rcSource) { \
  218. FN_PROLOG_WIN32 IFW32FALSE_EXIT(rtDest.CopyFunc(rcSource)); FN_EPILOG } \
  219. #endif // !defined(FUSION_ARRAYHELP_H_INCLUDED_)