home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / w3_prog / vbarrays.arj / HUGEARR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-30  |  12.9 KB  |  370 lines

  1. /************************************************************************
  2. *                                    *
  3. *                HUGEARR.DLL                *
  4. *                                    *
  5. *        Huge array support for Microsoft Visual Basic        *
  6. *                                    *
  7. *           from Microsoft Product Support Services            *
  8. *                                    *
  9. ************************************************************************/
  10.  
  11. #include <memory.h>
  12. #include <windows.h>
  13. #include "hugearr.h"
  14.  
  15. HANDLE            hLocalMem;        // handle to local memory
  16. int            NumArrays;        // total number of arrays
  17.  
  18. /************************************************************************
  19. * LibMain -                                *
  20. *   Standard DLL constructor.  Allocates all of local heap to store    *
  21. * array descriptors and then set the total number of arrays possible.    *
  22. ************************************************************************/
  23. int FAR pascal
  24.      LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  25. {
  26.     if (cbHeapSize > 0)
  27.     UnlockData(0);
  28.                     // Allocate memory for array descrips.
  29.     hLocalMem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  30.                          LocalCompact((WORD) 65500));
  31.     if (hLocalMem == NULL)
  32.     return 0;            // Something happened, bomb out
  33.                     // calc total number of arrays
  34.     NumArrays = (int) (LocalSize(hLocalMem) / sizeof(struct ArrayDesc));
  35.     return (1);
  36. }
  37.  
  38. /************************************************************************
  39. * WEP -                                 *
  40. *   Standard DLL destructor.  Free up local memory and quit.        *
  41. ************************************************************************/
  42. int FAR pascal WEP(int bSystemExit)
  43. {
  44.     LocalFree(hLocalMem);
  45.     return (1);
  46. }
  47.  
  48. /************************************************************************
  49. * HugeDim -                                *
  50. *   Dimensions a new array.  The size of the array is            *
  51. * (recsize * ubound+1).    Recsize is the size in bytes of each element in *
  52. * the array and ubound is the upper bound of the array.    All arrays have *
  53. * a lower bound of 0.                            *
  54. *                                    *
  55. * Note: If total size of the array is greater than 64K, recsize should    *
  56. *    be an integer power of two (1,2,4,8,16,etc.)  Otherwise, the    *
  57. *    huge pointers will not be added correctly.            *
  58. ************************************************************************/
  59. int FAR pascal HugeDim(int recsize, long ubound)
  60. {
  61.     int     hArray;            // handle to array to dimension
  62.     pDescrip    pArray;         // pointer to array descriptor
  63.  
  64.     pArray = (pDescrip) LocalLock(hLocalMem);    // find a free array
  65.     if ((hArray = GetFreeArray(pArray)) == HA_TOMANYARRAYS)  {
  66.     LocalUnlock(hLocalMem);         // couldn't find one,
  67.     return (HA_TOMANYARRAYS);        // return error.
  68.     }
  69.                     // allocate new array
  70.     hArray = HugeAlloc(pArray + hArray, recsize, ubound, FALSE);
  71.     LocalUnlock(hLocalMem);
  72.     return (hArray);
  73. }
  74.  
  75. /************************************************************************
  76. * HugeRedim -                                *
  77. *   Redimenions the given array to have the new 'ubound'.  The old    *
  78. * recsize is kept.  All data in the array is preserved and any new data *
  79. * (created by expanding the array) is initialized to 0.         *
  80. *                                    *
  81. * Note: The recsize must be an integer power of two if the total array    *
  82. *    size is greater than 64K.                    *
  83. ************************************************************************/
  84. int FAR pascal HugeRedim(int hArray, long ubound)
  85. {
  86.     pDescrip    pArray;         // pointer to array desciptor
  87.     register    ret;            // return code of HugeAlloc
  88.  
  89.     if (hArray < 0 | hArray >= NumArrays)
  90.     return (HA_BADARRAY);        // illegal array handle
  91.  
  92.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  93.  
  94.     if (pArray -> handle != NULL)    // reallocate array
  95.     ret = HugeAlloc(pArray, pArray -> recsize, ubound, TRUE);
  96.     else
  97.     ret = HA_BADARRAY;        // array has never been allocated
  98.  
  99.     LocalUnlock(hLocalMem);
  100.     return (ret);
  101. }
  102.  
  103.  
  104. /********************************************************************
  105. * GetFreeArray -                            *
  106. *   Searches the array descriptor table looking for a free entry.   *
  107. * It returns the index into the table if an entry is free or        *
  108. * HA_TOMANYARRAYS otherwise.  pArray is the pointer to the start of *
  109. * the table.                                *
  110. ********************************************************************/
  111. int GetFreeArray(pDescrip pArray)
  112. {
  113.     int i = 0;
  114.                     // loop until found or out of entries
  115.     while ((i < NumArrays) && (pArray -> handle != NULL))  {
  116.     ++pArray;
  117.     ++i;
  118.     }
  119.  
  120.     if (i == NumArrays)         // didn't find a spot
  121.     return (HA_TOMANYARRAYS);
  122.  
  123.     return (i);             // found one, return index to it
  124. }
  125.  
  126. /********************************************************************
  127. * GetHugeEl -                                *
  128. *   Retrieves an element of the array storing it into the buffer    *
  129. * pointed to by 'buffer'.  hArray is the index into the    descriptor  *
  130. * table of the array, element is the element to get.            *
  131. *                                    *
  132. * NOTE: there is absolutely no type checking done on the buffer.    *
  133. *    It is up to the programmer to make sure it points to the    *
  134. *    correct data type.                        *
  135. ********************************************************************/
  136. int FAR pascal GetHugeEl(int hArray, long element, BYTE FAR *buffer)
  137. {
  138.     BYTE _huge        *ptr;            // pointer to array element
  139.     pDescrip        pArray;            // pointer to array descriptor
  140.  
  141.     if (hArray < 0 || hArray >= NumArrays)
  142.     return (HA_BADARRAY);            // illegal array handle
  143.  
  144.                         // point to proper descriptor
  145.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  146.  
  147.     if (pArray -> handle == NULL)  {
  148.     LocalUnlock(hLocalMem);
  149.     return (HA_BADARRAY);            // array hasn't been allocated
  150.     }
  151.     if ((pArray -> ubound < element) || (element < 0))    {
  152.     LocalUnlock(hLocalMem);
  153.     return (HA_SUBSCRIPT);            // subscript out of range
  154.     }
  155.                         // calculate pointer to element
  156.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  157.     ptr = ptr + element * pArray->recsize;
  158.     _fmemcpy(buffer, ptr, pArray -> recsize);    // copy data
  159.  
  160.     GlobalUnlock(pArray -> handle);
  161.     LocalUnlock(hLocalMem);
  162.     return (HA_OK);
  163. }
  164.  
  165. /********************************************************************
  166. * SetHugeEl -                                *
  167. *   Sets the value of an array element.  This routine is exactly    *
  168. * the same as 'GetHugeEl' except that the memory copy is reversed. *
  169. ********************************************************************/
  170. int FAR pascal SetHugeEl(int hArray, long element, BYTE FAR *buffer)
  171. {
  172.     BYTE _huge        *ptr;            // pointer to array element
  173.     pDescrip        pArray;            // pointer to array descriptor
  174.  
  175.     if (hArray < 0 || hArray >= NumArrays)
  176.     return (HA_BADARRAY);            // illegal array handle
  177.  
  178.                         // point to proper descriptor
  179.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  180.  
  181.     if (pArray -> handle == NULL)  {
  182.     LocalUnlock(hLocalMem);
  183.     return (HA_BADARRAY);            // array hasn't been allocated
  184.     }
  185.     if ((pArray -> ubound < element) || (element < 0))    {
  186.     LocalUnlock(hLocalMem);
  187.     return (HA_SUBSCRIPT);            // subscript out of range
  188.     }
  189.                         // calculate pointer to element
  190.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  191.     ptr = ptr + element * pArray->recsize;
  192.     _fmemcpy(ptr, buffer, pArray -> recsize);    // copy data
  193.  
  194.     GlobalUnlock(pArray -> handle);
  195.     LocalUnlock(hLocalMem);
  196.     return (HA_OK);
  197. }
  198.  
  199. /********************************************************************
  200. * HugeErase -                                *
  201. *   Deletes an array and marks it as free in the descriptor table.  *
  202. * 'hArray' is the array to erase.                    *
  203. ********************************************************************/
  204. int FAR pascal HugeErase(int hArray)
  205. {
  206.     pDescrip    pArray;                // pointer to array descriptor
  207.  
  208.     if (hArray < 0 || hArray >= NumArrays)
  209.     return (HA_BADARRAY);            // illegal array handle
  210.  
  211.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  212.     if (pArray -> handle == NULL)  {
  213.     LocalUnlock(hLocalMem);
  214.     return (HA_BADARRAY);            // array hasn't been allocated yet
  215.     }
  216.  
  217.     GlobalFree(pArray -> handle);        // free the memory
  218.     pArray -> handle = NULL;
  219.  
  220.     LocalUnlock(hLocalMem);
  221.     return (HA_OK);
  222. }
  223.  
  224. /********************************************************************
  225. * NumHugeArrays -                            *
  226. *   Returns the number of free entries in the array descriptor table*
  227. ********************************************************************/
  228. int FAR pascal NumHugeArrays(void)
  229. {
  230.     pDescrip        pArray;            // pointer to current descriptor
  231.     int         num, i;         // number free so far
  232.  
  233.     pArray = (pDescrip) LocalLock(hLocalMem);
  234.     for (i = 0, num = 0; i < NumArrays; i++, pArray++)
  235.     if (pArray -> handle == NULL)
  236.         ++num;
  237.  
  238.     LocalUnlock(hLocalMem);
  239.     return (num);
  240. }
  241.  
  242.  
  243. /********************************************************************
  244. * HugeUbound -                                *
  245. *   Returns the upper bound of a given array                *
  246. ********************************************************************/
  247. int FAR pascal HugeUbound(int hArray)
  248. {
  249.     pDescrip    pArray;                // pointer to array descriptor
  250.     register    ubound;             // upper bound of array
  251.  
  252.     if (hArray < 0 || hArray >= NumArrays)
  253.     return (HA_BADARRAY);            // illegal array handle
  254.  
  255.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  256.     if (pArray -> handle == NULL)  {
  257.     LocalUnlock(hLocalMem);
  258.     return (HA_BADARRAY);            // array hasn't been allocated yet
  259.     }
  260.  
  261.     ubound = pArray -> ubound;
  262.     LocalUnlock(hLocalMem);
  263.  
  264.     return (ubound);
  265. }
  266.  
  267.  
  268. /********************************************************************
  269. * HugeInt -                                *
  270. *   Same as GetHugeEl except that it explicitly returns an integer. *
  271. * Use this function when you are in an expression such as:        *
  272. *        i% = 5 * HugeInt(4, 5)                    *
  273. *                                    *
  274. * NOTE: Because the user could store anything in the array element, *
  275. *    they will not know if the value returned is a real value or *
  276. *    if an error occured.  Use GetHugeEl if the error code must  *
  277. *    be checked.                            *
  278. ********************************************************************/
  279. int FAR pascal HugeInt(int hArray, long element)
  280. {
  281.     int     retval;
  282.  
  283.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  284.     return (retval);
  285. }
  286.  
  287.  
  288. /********************************************************************
  289. * HugeLong -                                *
  290. *   Returns an element of a long integer array.  (re. HugeInt)        *
  291. ********************************************************************/
  292. long FAR pascal HugeLong(int hArray, long element)
  293. {
  294.     long    retval;
  295.  
  296.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  297.     return (retval);
  298. }
  299.  
  300.  
  301.  
  302. /********************************************************************
  303. * HugeSingle -                                *
  304. *   Returns an element of a single precesion array.  (re. HugeInt)  *
  305. ********************************************************************/
  306. float FAR pascal HugeSingle(int hArray, long element)
  307. {
  308.     float  retval;
  309.  
  310.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  311.     return (retval);
  312. }
  313.  
  314.  
  315. /********************************************************************
  316. * HugeDouble -                                *
  317. *   Returns an element of a double precision array.  (re. HugeInt)  *
  318. ********************************************************************/
  319. double FAR pascal HugeDouble(int hArray, long element)
  320. {
  321.     double  retval;
  322.  
  323.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  324.     return (retval);
  325. }
  326.  
  327.  
  328. /********************************************************************
  329. * HugeCurrency -                            *
  330. *   Returns an element of a Currency array.  (re. HugeInt)        *
  331. ********************************************************************/
  332. currency FAR pascal HugeCurrency(int hArray, long element)
  333. {
  334.     return((currency) HugeDouble(hArray, element));
  335. }
  336.  
  337. /********************************************************************
  338. *   HugeAlloc -                             *
  339. * Allocates (or reallocates) global memory for an array.  The size  *
  340. * of the array is recsize * (ubound + 1) bytes.  The information    *
  341. * for the array is stored in the array descriptor pointed to by     *
  342. * 'pArray'.                                *
  343. *                                    *
  344. * Note:  See HugeDim for a discussion on array size limitations.    *
  345. ********************************************************************/
  346. int HugeAlloc(pDescrip pArray,int recsize,long ubound, BOOL realloc)
  347. {
  348.     HANDLE        handle;         // temp handle for alloc
  349.  
  350.     ++ubound;                    // ubound = #elements - 1
  351.     if (recsize * ubound > 0xffff)        // is size integer power two?
  352.     if ((recsize <= 0) || (((recsize - 1) & recsize) != 0))
  353.         return (HA_BADELEMENTSIZE);
  354.  
  355.     if (realloc)                // allocate array
  356.     handle = GlobalReAlloc(pArray -> handle, recsize * ubound,
  357.                            GMEM_MOVEABLE || GMEM_ZEROINIT);
  358.     else
  359.     handle = GlobalAlloc(GMEM_MOVEABLE || GMEM_ZEROINIT, recsize * ubound);
  360.  
  361.     if (handle == NULL)
  362.     return (HA_OUTOFMEMORY);        // out of memory
  363.  
  364.     pArray -> handle = handle;            // save new handle
  365.     pArray -> recsize = recsize;        // record element size
  366.     pArray -> ubound = ubound - 1;
  367.  
  368.     return (HA_OK);
  369. }
  370.