Category : C++ Source Code
Archive   : BLFMATH.ZIP
Filename : VECTOR.MTH
// vector.mth: Template methods for fixed-length shared vectors.
// Copyright(c) 1993 Azarona Software. All rights reserved.
//////////////////////////////////////////////////////////////////
#include "placenew.h"
template
void *VecRep
// The new operator overloaded for VecRep, so
// that the vector elements are stored immediately
// after the reference count. Here, n is sizeof(VecRep)
// and d is the number of elements to be allocated in the
// vector. If allocation fails or d == 0, we reference
// null_rep, the null VecRep object.
{
// Compute what pointer to object should be.
// Note: One element already accounted for in n.
void *p = (d == 0) ? 0 : new char[n+(d-1)*sizeof(TYPE)];
if (p == 0) { // If pointer is null, bind to null_rep
p = &null_rep;
null_rep.refcnt++;
}
return p;
}
template
void VecRep
// The delete operator is overloaded to delete
// all of the vector data, as well as the
// refcnt and alloclen fields.
{
// Since null_rep is allocated statically,
// p should never point to null_rep.
// However, it might under the following conditions:
// (1) A vector is declared in the static segment,
// (2) the allocation of dynamic memory for the
// vector fails, (3) the null_rep object hasn't
// been constructed yet. This condition occurs
// very rarely, but it can happen.
if (p != &null_rep) delete[] (char *)p;
}
template
VecRep
// Constructor to initialize a shared vector rep.
{
if (this != &null_rep) {
// We only want to do the following if we're
// not referencing null_rep.
alloclen = d;
refcnt = 1;
// We must call the placement constructor for
// all but the first element
TYPE *q = data + 1;
for(unsigned i = 1; i
}
template
void VecRep
// Destructor to explicitly destroy all elements
// of the vector, except the first. Note that this
// effectively keeps null_rep's only element from
// being destroyed too many times.
{
TYPE *q = data + 1;
for(unsigned i = 1; i
}
template
void Vector
// This function binds us to the same data that
// v is bound to, thus sharing v's data.
// ASSUMES vector not already bound.
{
rep = v.rep;
rep->refcnt++;
}
template
void Vector
// Unbinds this vector from the shared data. The data
// is disposed of properly if reference count goes to 0.
// WARNING: This function should only be called by the
// destructor, or be immediately followed by a call to
// Bind(). That's because our internal pointers might
// be left pointing to freed memory.
{
rep->refcnt--;
// Note: delete handles the possibility of trying to
// delete null_rep.
if (rep->refcnt == 0) delete rep;
}
template
void Vector
// Unbinds this vector from the data it shares, and
// then binds it to the data shared by v.
{
// Check for already sharing the same data
if (rep == v.rep) return;
Unbind();
Bind(v);
}
template
int Vector
// Allocates a block of n elements for this vector.
// If n == 0 or allocation fails, we bind to the null rep.
// ASSUMES TYPE has a default constructor.
// NOTE: This vector better not be bound at this time!
// Returns 0 if we've bound to null_rep, else 1.
{
// You might not think we need this if statement.
// Couldn't we do the new() even if n = 0? The
// answer is no, things get all fouled up, cause
// multiple reps that are actually null get created
// but we want only one, and it should be static.
if (n) {
rep = new(n) VecRep
}
else {
rep = &VecRep
rep->refcnt++;
}
start = rep->data;
if (rep != &VecRep
len = n;
stride = 1;
return 1;
}
else {
len = 0;
stride = 1;
return 0;
}
}
template
Vector
// Constructor to allocate space for a n element vector,
// and, if s != 0, to copy low-level C array into it.
// If n == 0 or allocation fails, we bind to null rep,
// and do no copying.
{
if (Alloc(n) && s) CopyN(s, n);
}
template
Vector
// Copy constructor that shares all of the vector v.
{
Bind(v);
len = v.len;
stride = v.stride;
start = v.start;
}
template
Vector
unsigned n, unsigned str, unsigned ofs)
// Constructor used to share or copy a slice of an existing
// vector. If styp = SHARED, then the new vector of
// length n shares its data with the old vector with the
// desired stride and offset. Otherwise, a copy is made
// with a length of n, stride of 1, and offset of 0.
// If n == 0, it means use v.len for the length.
// If copying and allocation fails, no copy takes place.
{
len = (n) ? n : v.len;
#ifndef NO_RANGE_CHECK
// NOTE: This range check code here not shown in book!
// Keep offset in range, and compute number of
// elements available, given offset.
unsigned vlen = v.len;
if (ofs >= vlen) ofs = vlen ? (vlen-1) : 0;
unsigned elemavl = vlen - ofs;
// Keep new stride in range, determine desired length
// and keep it in range too. Note that elemavl is
// rounded up so that it covers whole strides.
if (str == 0) str = 1;
if (str > elemavl) str = elemavl;
elemavl += str - (elemavl % str); // Round up to whole strides
if (len * str > elemavl) len = elemavl / str;
#endif
if (styp == SHARED) {
// Share existing data in v, accumulating offset
// and stride as needed. Note how stride and
// starting offset are computed in units of the
// elements of the real underlying vector.
Bind(v);
start = v.start + ofs * v.stride;
stride = str * v.stride;
}
else {
// Allocate data, then copy the desired slice of the
// source vector into the destination vector.
// Note clever recursive call to constructor.
if (Alloc(len)) Copy(Vector
}
}
#ifndef NO_RANGE_CHECK
template
unsigned Vector
// Check for index being in bounds. If not in
// bounds, call the error handler.
{
if (i >= len) i = HandleRangeErr(i, len);
return i;
}
#endif
template
void Vector
// Copies as much data as possible from src
// into this vector, truncating if need be.
{
unsigned tlen = len;
if (tlen > n) tlen = n;
VecPtr
for (unsigned i=0; i
dest++;
}
len = tlen; // We have a new logical length!
}
template
void Vector
// Copies as much data as possible from v into this
// vector, truncating if need be.
{
unsigned tlen = len;
unsigned vlen = v.len;
if (tlen > vlen) tlen = vlen;
VecPtr
VecPtr
for (unsigned i=0; i
src++;
dest++;
}
len = tlen; // We have a new logical length!
}
template
Vector
// Return a clone of this vector. This clone will
// be unique, (with vector rep refcnt = 1), and
// will have a stride of 1.
// Note: If allocation fails, a null vector is returned.
{
Vector
temp.Copy(*this);
return temp;
}
template
int Vector
// Ensures that this vector uniquely owns its vector
// rep, (ie. the reference count is 1).
// Might have to copy vector rep data to ensure this.
// Returns 1 if can make unique, 0 if can't (allocation
// for copy failed.)
{
if (!IsUnique()) { // Need to copy to make unique
Vector
if (c.IsNull()) return 0; // Couldn't copy
Share(c); // Share with copy
}
return 1;
}
template
void Vector
// Shares with the elements in vector v.
{
NewBinding(v);
len = v.len;
stride = v.stride;
start = v.start;
}
template
void Vector
// Sets every element of this vector to x.
{
VecPtr
for (unsigned i = 0; i
cursor++;
}
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/