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.

568 lines
30 KiB

  1. /**********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1987-1990 **/
  4. /**********************************************************************/
  5. /*
  6. ARRAY.HXX
  7. LM 3.0 Generic array class module
  8. This module contains type generic implementations of static
  9. and dynamic arrays that provide bounds checking.
  10. FILE HISTORY:
  11. Johnl 02-Aug-90 Created
  12. Johnl 05-Dec-90 Changed Size to QuerySize, changed Cassert to
  13. UIASSERT
  14. RustanL 05-Dec-90 Added ARRAY_LIST
  15. RustanL 06-Dec-90 Split DECLARE_ARRAY_OF into itself and
  16. DEFINE_ARRAY_OF
  17. RustanL 07-Dec-90 Added several enhancements to ARRAY class
  18. RustanL 31-Dec-90 Removed 'inline' from ARRAY_LIST::Remove
  19. */
  20. #ifndef _ARRAY_HXX_
  21. #define _ARRAY_HXX_
  22. /*************************************************************************
  23. NAME: ARRAY
  24. SYNOPSIS: Generic array implementation that provides bounds checking
  25. INTERFACE:
  26. DECLARE_ARRAY_OF( ) - Declares array package (interface) for type
  27. DEFINE_ARRAY_OF() - Defines array package (implementation) for type
  28. ARRAY_OF() - Declares an array object of type "type"
  29. ARRAY_type( ) - Constructor, takes a suggested size of array,
  30. and attempts to allocate the array of that
  31. size. If the allocation fails, the size is
  32. set to 0, but the array is still in a valid
  33. state. In fact, the array will always be in
  34. a valid state.
  35. Initial allocations of size 0 are always
  36. guaranteed to succeed. Hence, the client
  37. can always check if QueryCount returns a
  38. different value than was passed to the
  39. constructor in order to determine the
  40. space actually allocated. (Please note that
  41. checking QueryCount for being is, in general,
  42. not enough to determine if the allocation
  43. was successful.)
  44. An alternate version of the constructor accepts
  45. an existing vector of objects. This version can
  46. either use that vector as its own storage,
  47. resizing as needed - in which case the creator
  48. must surrender all rights to the presumably
  49. dynamically allocated vector - or else treats
  50. it as nonresizable. The default is never to
  51. resize such, since the vector might not come
  52. from freestore, or else may be shared with
  53. another object.
  54. ~ARRAY_type() - Deletes the array
  55. operator[] - Gives random access to array with bounds checking
  56. (asserts out if you go out of bounds)
  57. operator= - Copies one array to another (note, they must be of
  58. the same size).
  59. QueryCount() - Returns the count of elements of this array.
  60. Resize() - Resizes the array to the number of elements
  61. specified by size. (NOTE: the array only
  62. reallocates memory if the size changes by more
  63. than ARRAY_RESIZE_MEM bytes or when the new
  64. size exceeds the current.) Returns TRUE if
  65. successful. If FALSE is returned, then a memory
  66. error occurred, and the array remains untouched.
  67. Resize is guaranteed to work whenever the new
  68. size does not exceed the previous.
  69. CAVEATS:
  70. NOTES:
  71. CODEWORK. The Resize method could be made much more efficient if it
  72. used a proper buffer object that could be realloced, rather than
  73. having to allocate a brand new chunk of memory, call the
  74. constructor on each item in this array, copy items into the new
  75. array, call the destructor on every previously allocated item,
  76. and finally deallocate the previous chunk of memory. This should
  77. become a new class (BUFFER_ARRAY_OF or the like).
  78. HISTORY:
  79. Johnl 15-Jul-1990 Created
  80. RustanL 06-Dec-1990 Created DEFINE_ARRAY_OF from DECLARE_ARRAY_OF
  81. RustanL 07-Dec-1990 Added several enhancements
  82. beng 14-Aug-1991 Added vector-adopt mode; renamed QCount;
  83. op= relaxed; enhanced further
  84. Yi-HsinS 28-Oct-1992 Add a flag to Resize indicating not to
  85. downsize
  86. **************************************************************************/
  87. #define ARRAY_OF(type) ARRAY_##type
  88. #define ARRAY_RESIZE_MEM 4096 // If the array loses more than 4096 bytes
  89. // on a resize, then go ahead and reallocate
  90. // memory etc., else just change _carray
  91. /************************************************************/
  92. #define DECL_ARRAY_OF(type,dec) \
  93. \
  94. class dec ARRAY_OF(type) \
  95. { \
  96. private: \
  97. type *_parray; \
  98. UINT _carray; \
  99. UINT _carrayAlloc; \
  100. BOOL _fMayResize; \
  101. \
  102. BOOL WithinRange( UINT iIndex ) const; \
  103. \
  104. public: \
  105. ARRAY_OF(type)( UINT cElem ); \
  106. ARRAY_OF(type)( type* ptype, UINT ctype, \
  107. BOOL fMayResize = FALSE); \
  108. \
  109. ~ARRAY_OF(type)(); \
  110. \
  111. type& operator[]( UINT iIndex ) const \
  112. { \
  113. ASSERT( WithinRange(iIndex) ); \
  114. return _parray[ iIndex ]; \
  115. } \
  116. \
  117. UINT QueryCount() const \
  118. { \
  119. return _carray; \
  120. } \
  121. \
  122. ARRAY_OF(type) & operator=( ARRAY_OF(type)& a ); \
  123. \
  124. BOOL Resize( UINT cElemNew, BOOL fDownSize = TRUE ); \
  125. };
  126. /************************************************************************/
  127. #define DEFINE_ARRAY_OF( type ) \
  128. \
  129. ARRAY_OF(type)::ARRAY_OF(type)( UINT cElem ) \
  130. : _parray(NULL), \
  131. _carray(0), \
  132. _carrayAlloc(0), \
  133. _fMayResize(TRUE) \
  134. { \
  135. if ( cElem > 0 ) \
  136. { \
  137. _parray = new type[ cElem ]; \
  138. } \
  139. \
  140. if ( _parray != NULL ) \
  141. { \
  142. _carray = _carrayAlloc = cElem; \
  143. } \
  144. } \
  145. \
  146. \
  147. ARRAY_OF(type)::ARRAY_OF(type)(type *px, UINT cx, BOOL fMayResize) \
  148. : _parray(px), \
  149. _carray(cx), \
  150. _carrayAlloc(cx), \
  151. _fMayResize(fMayResize) \
  152. { \
  153. /* nothing doing. */ \
  154. } \
  155. \
  156. \
  157. ARRAY_OF(type)::~ARRAY_OF(type)() \
  158. { \
  159. if ( _fMayResize && _carrayAlloc > 0 ) \
  160. delete [ _carrayAlloc ] _parray; \
  161. } \
  162. \
  163. \
  164. ARRAY_OF(type) & ARRAY_OF(type)::operator=( ARRAY_OF(type)& a ) \
  165. { \
  166. ASSERT(_carrayAlloc <= a.QueryCount()); \
  167. \
  168. UINT iLim = ( a.QueryCount() <= _carrayAlloc) \
  169. ? a.QueryCount() \
  170. : _carrayAlloc; \
  171. \
  172. for ( UINT i = 0; i < iLim; i++ ) \
  173. _parray[i] = a._parray[i]; \
  174. \
  175. _carray = iLim; \
  176. return *this; \
  177. } \
  178. \
  179. \
  180. BOOL ARRAY_OF(type)::WithinRange( UINT iIndex ) const \
  181. { \
  182. return (iIndex < _carray); \
  183. } \
  184. \
  185. \
  186. BOOL ARRAY_OF(type)::Resize( UINT cElemNew, BOOL fDownSize ) \
  187. { \
  188. /* Prevent resizing owner-alloc arrays */ \
  189. if (!_fMayResize) \
  190. return FALSE; \
  191. \
  192. if ( ( cElemNew > _carrayAlloc ) \
  193. || ( fDownSize && \
  194. (( _carrayAlloc - cElemNew )*sizeof(type) > ARRAY_RESIZE_MEM))\
  195. ) \
  196. { \
  197. type * parrayNew; \
  198. if ( cElemNew > 0 ) \
  199. { \
  200. parrayNew = new type[ cElemNew ]; \
  201. if ( parrayNew == NULL ) \
  202. { \
  203. /* Memory failure */ \
  204. if ( cElemNew > _carrayAlloc ) \
  205. { \
  206. /* The array has been not been modified */ \
  207. return FALSE; \
  208. } \
  209. else \
  210. { \
  211. /* Guarantee: resizing the array for */ \
  212. /* new sizes not exceeding the current */ \
  213. /* will always succeed. */ \
  214. _carray = cElemNew; \
  215. return TRUE; \
  216. } \
  217. } \
  218. \
  219. /* Copy each existing item */ \
  220. /* that will fit into the new array */ \
  221. for ( UINT i = 0 ; \
  222. i < ( _carray < cElemNew ? _carray : cElemNew); \
  223. i++ ) \
  224. { \
  225. parrayNew[i] = _parray[i]; \
  226. } \
  227. \
  228. } \
  229. else \
  230. { \
  231. parrayNew = NULL; \
  232. } \
  233. \
  234. if ( _carrayAlloc > 0 ) \
  235. { \
  236. delete[ _carrayAlloc ] _parray; \
  237. } \
  238. else \
  239. { \
  240. ASSERT( _parray == NULL ); \
  241. } \
  242. _parray = parrayNew; \
  243. _carray = _carrayAlloc = cElemNew; \
  244. } \
  245. else \
  246. { \
  247. /* (Array does not report errors.) New size is less */ \
  248. /* than current size, but not so much less that we want */ \
  249. /* to realloc to save memory. */ \
  250. _carray = cElemNew; \
  251. } \
  252. \
  253. return TRUE; \
  254. }
  255. /*************************************************************************
  256. NAME: ARRAY_LIST
  257. SYNOPSIS: Generic unordered array collection implementation
  258. which provides bounds checking, easy ways to add/remove
  259. items, etc. In some respects, this collection can be
  260. thought of as an efficient singly linked list, for singly
  261. linked lists which don't change a lot dynamically. Hence
  262. the name "array list".
  263. INTERFACE:
  264. DECLARE_ARRAY_LIST_OF( )
  265. Declares array list package for type 'type'
  266. DEFINE_ARRAY_LIST_OF()
  267. Defines array list package for type 'type', excluding
  268. the Sort and BinarySearch methods (see Notes below)
  269. DEFINE_EXT_ARRAY_LIST_OF()
  270. Defines the entire array list package for type 'type'
  271. WARNING: If you use EXT_ARRAY_LIST, the Compare()
  272. method for the parameter class must be _CRTAPI1.
  273. Otherwise the underlying qsort() or BinarySearch() will fail.
  274. ARRAY_LIST_OF()
  275. Declares an array list object of type 'type'
  276. ARRAY_LIST_type()
  277. Constructor. Takes an optional parameter, nInitialSize,
  278. which specifies the initial allocation size of the array
  279. list in number of array list items. Note, any call to
  280. Add or AddIdemp may cause the allocated size to be
  281. enlarged, and any call to Remove may reduce the allocated
  282. size. These allocations, however, are all kept away
  283. from the user, except for the nInitialSize parameter to
  284. the constructor.
  285. Add()
  286. Adds an item to the array list. Note, this will
  287. not sort the list.
  288. AddIdemp()
  289. Idempotently adds an item to the array list. Note,
  290. this will not sort the list.
  291. Remove()
  292. Removes an item from the array list. This may
  293. result in shrinking the allocated size of the array,
  294. and will not sort the list.
  295. Find()
  296. Finds the first occurrence of a given item in the array
  297. list. Since the list is not assumed to be sorted, a
  298. linear search is performed.
  299. Clear()
  300. Clears the array list of all of items items
  301. operator[]()
  302. Same as for the ARRAY class
  303. operator=()
  304. Same as for the ARRAY class
  305. QueryCount()
  306. Same as for the ARRAY class
  307. Sort()
  308. Sorts the array (see Notes below for Sort definition)
  309. BinarySearch()
  310. Works like Find, but performs a binary search rather
  311. than a linear. This method assumes that the list is
  312. sorted. (See Notes below for BinarySearch definition.)
  313. CAVEATS:
  314. Add and Remove will alter the ordering of the list in ways
  315. unexpected. See the implementation of Remove for details.
  316. The Sort routine calls qsort, which may swap the items.
  317. Although qsort is given a pointer to the Compare function,
  318. it does not have access to, or knowledge of, the assignment
  319. operator; rather, it performs a straight binary copy of each
  320. item. Hence, all types which require a custom assignment
  321. operation should not use the Sort method.
  322. CODEWORK. The debug version of BinarySearch could assert that
  323. the array list is sorted. This, however, would require adding
  324. an operator=( ARRAY ) and an operator=( ARRAY_LIST ) to this
  325. class, since these would function differently with an additional
  326. member keeping track of whether the array list is sorted.
  327. CODEWORK. We have a C++ heapsort, which we could emend to
  328. recognize type::Compare.
  329. NOTES:
  330. The array list declaration and definitions automatically
  331. take care of declaring and defining, respectively, the
  332. superclass ARRAY or the same type, since ARRAY_LIST inherits
  333. from ARRAY.
  334. The Find, Sort, and BinarySearch functions require the 'type'
  335. class to define a Compare method.
  336. The retail version of this class does not claim nor attempt to
  337. keep track of if the list is sorted. Thus, it is always up to
  338. the client to keep track of this. For the same reason, Remove
  339. and AddIdemp always call Find, rather than BinarySearch. The
  340. debug version could assert out if BinarySearch is called when
  341. the list is not sorted (see Caveats above).
  342. Since the Sort and BinarySearch definitions methods depend on
  343. definitions in stdlib.h and search.h, the definitions for these
  344. methods are only provided in the extended definition macro.
  345. This way, clients who do not wish to make use of Sort and
  346. BinarySearch, need not include stdlib.h and search.h.
  347. HISTORY:
  348. RustanL 5-Dec-1990 Created
  349. beng 14-Aug-1991 Remove inlines; changes in ARRAY
  350. Yi-HsinS 28-Oct-1992 Add a flag to Resize indicating not to
  351. downsize
  352. **************************************************************************/
  353. #define ARRAY_LIST_OF(type) ARRAY_LIST_##type
  354. /************************************************************/
  355. #define DECL_ARRAY_LIST_OF(type,dec) \
  356. \
  357. DECL_ARRAY_OF(type,dec); \
  358. \
  359. class dec ARRAY_LIST_OF( type ) : public ARRAY_OF( type ) \
  360. { \
  361. public: \
  362. ARRAY_LIST_OF( type )( UINT cAlloc = 0 ); \
  363. \
  364. BOOL Add( const type & t ); \
  365. BOOL AddIdemp( const type & t ); \
  366. BOOL Remove( const type & t ); \
  367. INT Find( const type & t ) const; \
  368. VOID Clear(); \
  369. \
  370. VOID Sort(); \
  371. INT BinarySearch( const type & t ) const; \
  372. static int __cdecl SortFunc ( \
  373. const void * p1, const void * p2 ) ; \
  374. };
  375. /********************************************************************/
  376. #define DEFINE_ARRAY_LIST_OF( type ) \
  377. \
  378. DEFINE_ARRAY_OF( type ); \
  379. \
  380. ARRAY_LIST_OF( type )::ARRAY_LIST_OF( type )( UINT cAlloc ) \
  381. : ARRAY_OF(type) ( cAlloc ) \
  382. { \
  383. Resize(0, FALSE); /* do not downsize */ \
  384. } \
  385. \
  386. BOOL ARRAY_LIST_OF( type )::Add( const type & t ) \
  387. { \
  388. UINT n = QueryCount(); \
  389. \
  390. if ( ! Resize( n + 1 )) \
  391. return FALSE; /* Out of memory */ \
  392. \
  393. (*this)[n] = t; \
  394. return TRUE; \
  395. } \
  396. \
  397. \
  398. BOOL ARRAY_LIST_OF( type )::AddIdemp( const type & t ) \
  399. { \
  400. return (( Find( t ) >= 0 ) || Add( t )); \
  401. } \
  402. \
  403. \
  404. BOOL ARRAY_LIST_OF( type )::Remove( const type & t ) \
  405. { \
  406. INT i = Find( t ); \
  407. if ( i < 0 ) \
  408. return FALSE; /* item not found */ \
  409. \
  410. /* Since Find was able to find the item, the array list */ \
  411. /* cannot be empty. */ \
  412. ASSERT(QueryCount() > 0); \
  413. UINT n = QueryCount() - 1; \
  414. if ( (UINT)i < n ) \
  415. (*this)[i] = (*this)[n]; \
  416. \
  417. /* Reducing the size of an array always succeeds */ \
  418. REQUIRE( Resize( n )); \
  419. \
  420. return TRUE; \
  421. } \
  422. \
  423. \
  424. INT ARRAY_LIST_OF( type )::Find( const type & t ) const \
  425. { \
  426. for ( UINT i = 0; i < QueryCount(); i++ ) \
  427. { \
  428. if ( t.Compare( &(operator[]( i ))) == 0 ) \
  429. return i; \
  430. } \
  431. \
  432. return -1; /* not found */ \
  433. } \
  434. \
  435. \
  436. VOID ARRAY_LIST_OF( type )::Clear() \
  437. { \
  438. /* Resizing to size 0 is guaranteed always to work. */ \
  439. REQUIRE( Resize( 0 )); \
  440. }
  441. /********************************************************************/
  442. #define DEFINE_EXT_ARRAY_LIST_OF( type ) \
  443. \
  444. DEFINE_ARRAY_LIST_OF( type ); \
  445. \
  446. int __cdecl ARRAY_LIST_OF( type )::SortFunc ( \
  447. const void * p1, const void * p2 ) \
  448. { \
  449. const type * pt1 = (const type *) p1 ; \
  450. const type * pt2 = (const type *) p2 ; \
  451. return pt1->Compare( pt2 ) ; \
  452. } \
  453. \
  454. VOID ARRAY_LIST_OF( type )::Sort() \
  455. { \
  456. qsort( &((*this)[0]), QueryCount(), sizeof( type ), \
  457. ARRAY_LIST_OF( type )::SortFunc ); \
  458. } \
  459. \
  460. \
  461. INT ARRAY_LIST_OF( type )::BinarySearch( const type & t ) const \
  462. { \
  463. type * ptBase = &((*this)[0]); \
  464. type * pt = (type *)bsearch( (VOID *)&t, \
  465. (VOID *)ptBase, \
  466. QueryCount(), \
  467. sizeof( type ), \
  468. ARRAY_LIST_OF( type)::SortFunc ); \
  469. \
  470. return (( pt == NULL ) ? -1 : (INT)(pt - ptBase) ); \
  471. }
  472. // Helper macros for code preservation
  473. #define DECLARE_ARRAY_OF(type) \
  474. DECL_ARRAY_OF(type,DLL_TEMPLATE)
  475. #define DECLARE_ARRAY_LIST_OF(type) \
  476. DECL_ARRAY_LIST_OF(type,DLL_TEMPLATE)
  477. #endif //_ARRAY_HXX_