home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 1.ddi / MWHC.001 / C < prev    next >
Encoding:
Text File  |  1992-12-09  |  5.1 KB  |  139 lines

  1. ///////////////////////////////////////////////////////////////////////
  2. // Copyright 1991, 1992 MetaWare Incorporated.  All rights reserved. //
  3. ///////////////////////////////////////////////////////////////////////
  4. // new/delete and array new/delete for C++.
  5.  
  6. #define DEBUG 0
  7. #include <stdlib.h>
  8.  
  9. // Array init initializes an array and, if required, allocates it
  10. // as well.  The allocation occurs only as a request from "new".
  11. // Correspondingly a "delete" request may come for that same array.
  12. // For an array allocation we allocate the array and possibly some extra
  13. // space.  The extra space stores the array count and is needed in certain
  14. // circumstances.
  15.  
  16. // Here is how the size is stored:
  17. // If the array alignment is 4 bytes or less and the number of elements
  18. // is <= 65536:
  19. //    struct {
  20. //          ushort nelts;
  21. //          ushort magic;    // 0xabcd
  22. //          char user_array[];
  23. //          };
  24. // If the array alignment is > 4 bytes or the # elements is > 65536:
  25. //    struct {    
  26. //          ulong nelts;        // # elements
  27. //          short how_much_pad; // # how much padding above user array?
  28. //          short magic;        // 0xabce
  29. //          char user_array[];
  30. //          }
  31. // Thus, for the typical case we use only 4 bytes.  For non-typical case
  32. // we use 8 (for <= 8 align) and 16 (for <= 16 align).  Such severe
  33. // alignments are relevant only for machines for which alignemnt is
  34. // enforced, such as 860 or sun4.
  35. // A simpler scheme would have been to put elemcount*2 in the preceding
  36. // word, and if there was more space than 4 bytes, or in bit 1 in that
  37. // word.  This doesn't work as well on the 286 and also we don't get
  38. // the checking with the magic number.
  39.  
  40. #define AL 1    // Define 0 if you don't want it.
  41. #if _I386 || _I286
  42. #define MAXALIGN 4
  43. #elif _I860
  44. #define MAXALIGN 16
  45. #else
  46. #define MAXALIGN 8
  47. #endif
  48. static const int magic_meaning_4_bytes = 0xabcd,
  49.          magic_meaning_more = 0xabce;
  50.  
  51. // We used to pass "as_base", but arrays are always constructed at
  52. // the top, so that's not necessary.
  53. // Format of mode:
  54. //    mode << 8 = alignment (1,2,4,8,16,32)
  55. //    mode & 1 = please store the count; the class type has destructors
  56. //           and so we'll be calling array_dest later.
  57. //    mode & 2 = please call passed function.  We need this because 0
  58. //           may in fact be a valid function address!
  59. //    mode & 4 = please deallocate this storage when done.  Should
  60. //           be set only when the count was stored.
  61. enum {ARRAY_STORE_SIZE=1, ARRAY_CALL_FUNC=2, ARRAY_DEALLOCATE=4,};
  62. #define ALIGN_OF(x) ((x)>>8)
  63.  
  64. typedef unsigned short ushort;
  65.  
  66. extern "C" void *__array_init(char *base, 
  67.     unsigned elemcount, int elemsize, void (*f)(char *,int),
  68.     unsigned mode) {
  69.     unsigned extra_space = 0;
  70.     if (mode & ARRAY_STORE_SIZE) {
  71.         unsigned alignment = ALIGN_OF(mode);
  72.          extra_space = _max(4,_min(MAXALIGN,alignment));
  73.         if (elemcount > 65535) extra_space = _max(extra_space,8);
  74.         }
  75.     // If the pointer is 0, allocate it as well.
  76.     // ARRAY_STORE_SIZE should not be requested for a non-newed array,
  77.     // so that extra space will be 0 for such.
  78.     if (base == 0) base = new char[elemcount*elemsize+extra_space];
  79.     if (extra_space) {
  80.         base += extra_space;
  81.         ushort *q = (ushort*)base; 
  82.         if (extra_space == 4) {
  83.             q[-1] = magic_meaning_4_bytes;
  84.             q[-2] = elemcount;
  85.             }
  86.         else {
  87.             q[-1] = magic_meaning_more;
  88.             q[-2] = extra_space;
  89.             long *p = (long*)base;
  90.             p[-2] = elemcount;
  91.             }
  92.         }
  93.     char *p = base;
  94.     if (DEBUG) printf("array_init(%x,%d,%d,%x,%d,%d)\n", 
  95.         base,elemcount,elemsize,f,mode,extra_space);
  96.     // Sorry, we may be given an address of 0 because the constructor
  97.     // is the first thing in the program executable!  Anyway, the compiler
  98.     // always guarantees a valid procedure.
  99.     if ((mode & ARRAY_CALL_FUNC) && base) {
  100.         for (int i = 0; i < elemcount; i++) {
  101.             if (DEBUG) printf("init %p elemsize=%d\n",p,elemsize);
  102.              f(p,0), p+=elemsize;
  103.              }
  104.          }
  105.     return base;
  106.     }
  107.  
  108. extern "C" void *__array_dest(char *base, 
  109.     unsigned elemcount, int elemsize, void (*f)(char *, int), 
  110.     unsigned mode) {
  111.     if (DEBUG) printf("array_dest(%x,%d,%d,%x,%d)\n",
  112.         base,elemcount,elemsize,f,mode);
  113.     unsigned extra_space = 0;
  114.     if (mode & ARRAY_STORE_SIZE) {    
  115.         ushort *q = (ushort*)base;
  116.         if (q[-1] == magic_meaning_4_bytes) {
  117.             extra_space = 4;
  118.             elemcount = q[-2];
  119.             }
  120.         else if (q[-2] == magic_meaning_more) {
  121.             extra_space = q[-2];
  122.             long *p = (long*)base;
  123.             elemcount = p[-2];
  124.             }
  125.         else {
  126.             printf("Array deletion:  non-array or corrupted array passed.\n");
  127.             exit(1);
  128.             }
  129.         }
  130.     char *p = ((char *)base)+elemsize*elemcount;
  131.     if (mode & ARRAY_CALL_FUNC) 
  132.         for (int i = 0; i < elemcount; i++) {
  133.             if (DEBUG) printf("dest %p elemsize=%d\n",p,elemsize);
  134.             p-=elemsize, f(p,0);
  135.             }
  136.     if (mode & ARRAY_DEALLOCATE) free(base-extra_space), base = 0;
  137.     return base;
  138.     }
  139.