home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / bcpp / file19 / vector.mth < prev   
Encoding:
Text File  |  1995-05-19  |  8.8 KB  |  301 lines

  1. //////////////////////////////////////////////////////////////////
  2. // vector.mth: Template methods for fixed-length shared vectors.
  3. // Copyright(c) 1993 Azarona Software. All rights reserved.
  4. //////////////////////////////////////////////////////////////////
  5. #include "placenew.h"
  6.  
  7. template<class TYPE>
  8. void *VecRep<TYPE>::operator new(size_t n, unsigned d)
  9. // The new operator overloaded for VecRep, so
  10. // that the vector elements are stored immediately
  11. // after the reference count. Here, n is sizeof(VecRep)
  12. // and d is the number of elements to be allocated in the
  13. // vector. If allocation fails or d == 0, we reference 
  14. // null_rep, the null VecRep object.
  15. {
  16.   // Compute what pointer to object should be.
  17.   // Note: One element already accounted for in n.
  18.   void *p = (d == 0) ? 0 : new char[n+(d-1)*sizeof(TYPE)];
  19.   if (p == 0) { // If pointer is null, bind to null_rep
  20.      p = &null_rep;
  21.      null_rep.refcnt++;
  22.   }
  23.   return p;
  24. }
  25.  
  26. template<class TYPE>
  27. void VecRep<TYPE>::operator delete(void *p)
  28. // The delete operator is overloaded to delete
  29. // all of the vector data, as well as the
  30. // refcnt and alloclen fields.
  31. {
  32.   // Since null_rep is allocated statically,
  33.   // p should never point to null_rep.
  34.   // However, it might under the following conditions:
  35.   // (1) A vector is declared in the static segment,
  36.   // (2) the allocation of dynamic memory for the
  37.   // vector fails, (3) the null_rep object hasn't
  38.   // been constructed yet. This condition occurs
  39.   // very rarely, but it can happen.
  40.   if (p != &null_rep) delete[] (char *)p;
  41. }
  42.  
  43. template<class TYPE>
  44. VecRep<TYPE>::VecRep(unsigned d)
  45. // Constructor to initialize a shared vector rep.
  46. {
  47.   if (this != &null_rep) {
  48.      // We only want to do the following if we're
  49.      // not referencing null_rep.
  50.      alloclen = d;
  51.      refcnt = 1;
  52.      // We must call the placement constructor for
  53.      // all but the first element
  54.      TYPE *q = data + 1;
  55.      for(unsigned i = 1; i<d; i++, q++) new(q) TYPE;
  56.   }
  57. }
  58.  
  59.  
  60. template<class TYPE>
  61. void VecRep<TYPE>::~VecRep()
  62. // Destructor to explicitly destroy all elements 
  63. // of the vector, except the first. Note that this
  64. // effectively keeps null_rep's only element from 
  65. // being destroyed too many times.
  66. {
  67.   TYPE *q = data + 1;
  68.   for(unsigned i = 1; i<alloclen; i++, q++) q->TYPE::~TYPE();
  69. }
  70.  
  71.  
  72. template<class TYPE>
  73. void Vector<TYPE>::Bind(const Vector<TYPE> &v)
  74. // This function binds us to the same data that
  75. // v is bound to, thus sharing v's data.
  76. // ASSUMES vector not already bound.
  77. {
  78.   rep = v.rep;
  79.   rep->refcnt++;
  80. }
  81.  
  82. template<class TYPE>
  83. void Vector<TYPE>::Unbind()
  84. // Unbinds this vector from the shared data. The data 
  85. // is disposed of properly if reference count goes to 0.
  86. // WARNING: This function should only be called by the
  87. // destructor, or be immediately followed by a call to
  88. // Bind(). That's because our internal pointers might
  89. // be left pointing to freed memory.
  90. {
  91.   rep->refcnt--;
  92.   // Note: delete handles the possibility of trying to
  93.   // delete null_rep.
  94.   if (rep->refcnt == 0) delete rep;
  95. }
  96.  
  97. template<class TYPE>
  98. void Vector<TYPE>::NewBinding(const Vector<TYPE> &v)
  99. // Unbinds this vector from the data it shares, and
  100. // then binds it to the data shared by v.
  101. {
  102.   // Check for already sharing the same data
  103.   if (rep == v.rep) return;
  104.   Unbind();
  105.   Bind(v);
  106. }
  107.  
  108. template<class TYPE>
  109. int Vector<TYPE>::Alloc(unsigned n)
  110. // Allocates a block of n elements for this vector.
  111. // If n == 0 or allocation fails, we bind to the null rep.
  112. // ASSUMES TYPE has a default constructor.
  113. // NOTE: This vector better not be bound at this time!
  114. // Returns 0 if we've bound to null_rep, else 1.
  115. {
  116.   // You might not think we need this if statement. 
  117.   // Couldn't we do the new() even if n = 0? The
  118.   // answer is no, things get all fouled up, cause
  119.   // multiple reps that are actually null get created
  120.   // but we want only one, and it should be static.
  121.   if (n) {
  122.      rep = new(n) VecRep<TYPE>(n);
  123.   }
  124.   else {
  125.     rep = &VecRep<TYPE>::null_rep;
  126.     rep->refcnt++;
  127.   }
  128.   start = rep->data;
  129.   if (rep != &VecRep<TYPE>::null_rep) {
  130.      len = n;
  131.      stride = 1;
  132.      return 1;
  133.   }
  134.   else {
  135.      len = 0;
  136.      stride = 1;
  137.      return 0;
  138.   }
  139. }
  140.  
  141. template<class TYPE>
  142. Vector<TYPE>::Vector(unsigned n, const TYPE *s) 
  143. // Constructor to allocate space for a n element vector,
  144. // and, if s != 0, to copy low-level C array into it.
  145. // If n == 0 or allocation fails, we bind to null rep, 
  146. // and do no copying.
  147.   if (Alloc(n) && s) CopyN(s, n); 
  148. }
  149.  
  150. template<class TYPE>
  151. Vector<TYPE>::Vector(const Vector<TYPE> &v)
  152. // Copy constructor that shares all of the vector v. 
  153. {
  154.   Bind(v);
  155.   len = v.len;
  156.   stride = v.stride;
  157.   start = v.start;
  158. }
  159.  
  160. template<class TYPE>
  161. Vector<TYPE>::Vector(const Vector<TYPE> &v, SliceType styp, 
  162.                      unsigned n, unsigned str, unsigned ofs)
  163. // Constructor used to share or copy a slice of an existing
  164. // vector. If styp = SHARED, then the new vector of
  165. // length n shares its data with the old vector with the
  166. // desired stride and offset. Otherwise, a copy is made 
  167. // with a length of n, stride of 1, and offset of 0.
  168. // If n == 0, it means use v.len for the length.
  169. // If copying and allocation fails, no copy takes place.
  170. {
  171.   len = (n) ? n : v.len;
  172. #ifndef NO_RANGE_CHECK
  173.   // NOTE: This range check code here not shown in book!
  174.   // Keep offset in range, and compute number of
  175.   // elements available, given offset.
  176.   unsigned vlen = v.len;
  177.   if (ofs >= vlen) ofs = vlen ? (vlen-1) : 0;
  178.   unsigned elemavl = vlen - ofs;
  179.   // Keep new stride in range, determine desired length
  180.   // and keep it in range too. Note that elemavl is 
  181.   // rounded up so that it covers whole strides.
  182.   if (str == 0) str = 1;
  183.   if (str > elemavl) str = elemavl;
  184.   elemavl += str - (elemavl % str); // Round up to whole strides
  185.   if (len * str > elemavl) len = elemavl / str;
  186. #endif
  187.   if (styp == SHARED) {
  188.      // Share existing data in v, accumulating offset
  189.      // and stride as needed. Note how stride and
  190.      // starting offset are computed in units of the 
  191.      // elements of the real underlying vector.
  192.      Bind(v);
  193.      start = v.start + ofs * v.stride;
  194.      stride = str * v.stride;
  195.   }
  196.   else {
  197.     // Allocate data, then copy the desired slice of the
  198.     // source vector into the destination vector.
  199.     // Note clever recursive call to constructor.
  200.     if (Alloc(len)) Copy(Vector<TYPE>(v, SHARED, len, str, ofs));
  201.   }
  202. }
  203.  
  204. #ifndef NO_RANGE_CHECK
  205.  
  206. template<class TYPE>
  207. unsigned Vector<TYPE>::CheckIndx(unsigned i) const
  208. // Check for index being in bounds. If not in
  209. // bounds, call the error handler.
  210. {
  211.   if (i >= len) i = HandleRangeErr(i, len);
  212.   return i;
  213. }
  214.  
  215. #endif
  216.  
  217. template<class TYPE>
  218. void Vector<TYPE>::CopyN(const TYPE *src, unsigned n)
  219. // Copies as much data as possible from src
  220. // into this vector, truncating if need be.
  221. {
  222.   unsigned tlen = len;
  223.   if (tlen > n) tlen = n;
  224.   VecPtr<TYPE> dest(start, stride);
  225.   for (unsigned i=0; i<tlen; i++) {
  226.       *dest = src[i];
  227.       dest++;
  228.   }
  229.   len = tlen; // We have a new logical length!
  230. }
  231.  
  232. template<class TYPE>
  233. void Vector<TYPE>::Copy(const Vector<TYPE> &v)
  234. // Copies as much data as possible from v into this
  235. // vector, truncating if need be.
  236. {
  237.   unsigned tlen = len;
  238.   unsigned vlen = v.len;
  239.   if (tlen > vlen) tlen = vlen;
  240.   VecPtr<const TYPE> src(v.start, v.stride);
  241.   VecPtr<TYPE> dest(start, stride);
  242.   for (unsigned i=0; i<tlen; i++) {
  243.       *dest = *src;
  244.       src++;
  245.       dest++;
  246.   }
  247.   len = tlen; // We have a new logical length!
  248. }
  249.  
  250.  
  251. template<class TYPE>
  252. Vector<TYPE> Vector<TYPE>::Clone() const
  253. // Return a clone of this vector. This clone will
  254. // be unique, (with vector rep refcnt = 1), and
  255. // will have a stride of 1.
  256. // Note: If allocation fails, a null vector is returned.
  257. {
  258.   Vector<TYPE> temp(len);
  259.   temp.Copy(*this);
  260.   return temp;
  261. }
  262.  
  263. template<class TYPE>
  264. int Vector<TYPE>::EnsureUnique()
  265. // Ensures that this vector uniquely owns its vector
  266. // rep, (ie. the reference count is 1).
  267. // Might have to copy vector rep data to ensure this.
  268. // Returns 1 if can make unique, 0 if can't (allocation
  269. // for copy failed.)
  270. {
  271.   if (!IsUnique()) {            // Need to copy to make unique
  272.      Vector<TYPE> &c = Clone(); // Attempt to copy
  273.      if (c.IsNull()) return 0;  // Couldn't copy
  274.      Share(c);                  // Share with copy
  275.   }
  276.   return 1;
  277. }
  278.  
  279.  
  280. template<class TYPE>
  281. void Vector<TYPE>::Share(const Vector<TYPE> &v)
  282. // Shares with the elements in vector v. 
  283. {
  284.   NewBinding(v);
  285.   len = v.len;
  286.   stride = v.stride;
  287.   start = v.start;
  288. }
  289.  
  290. template<class TYPE>
  291. void Vector<TYPE>::SetElements(const TYPE &x)
  292. // Sets every element of this vector to x.
  293. {
  294.   VecPtr<TYPE> cursor(start, stride);
  295.   for (unsigned i = 0; i<len; i++) {
  296.       *cursor = x;
  297.       cursor++;
  298.   }
  299. }
  300.