changeset 33:3ed337b6a04f Dev_prolog_vers

creating version of dyn array that keeps info in prolog instead of 2nd var
author Sean Halle <seanhalle@yahoo.com>
date Fri, 19 Jul 2013 12:27:43 -0700
parents 958dcb7754ca
children
files DynArray2.c DynArray3.c DynArray3.h __brch__Dev_prolog_vers __brch__Renamed_VMS_to_PR
diffstat 5 files changed, 472 insertions(+), 4 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/DynArray2.c	Fri Jul 19 12:27:43 2013 -0700
     1.3 @@ -0,0 +1,158 @@
     1.4 +/*
     1.5 + * Copyright 2010  OpenSourceCodeStewardshipFoundation
     1.6 + *
     1.7 + * Licensed under BSD
     1.8 + */
     1.9 +
    1.10 +
    1.11 +
    1.12 +#include <stdio.h>
    1.13 +#include <malloc.h>
    1.14 +
    1.15 +#include "DynArray.h"
    1.16 +
    1.17 +//== declarations
    1.18 +#define giveInfoFor( array )   &(((PrivDynArrayInfo*)array)[-1])
    1.19 +//==
    1.20 +
    1.21 +/*This updates the contents of the array variable, by side-effect.  There can
    1.22 + * only ever be one variable that holds a pointer to the dyn array, and all
    1.23 + * accesses must use that variable.  An add can cause the contents of that
    1.24 + * variable to change!  (Meaning the position of the array has moved)
    1.25 + */
    1.26 +void *
    1.27 +makePrivDynArray2( void ***addrOfArrayVar, int32 numElemsToAllocate, int32 sizeOfElem )
    1.28 + { PrivDynArrayInfo *info;
    1.29 +   int32 bytesInArray  = numElemsToAllocate * sizeOfElem;
    1.30 +   
    1.31 +   info = PR_int__malloc( sizeof(PrivDynArrayInfo) + bytesInArray );
    1.32 +   info->addrOfPtrToArray = addrOfArrayVar;
    1.33 +   info->sizeOfArray      = numElemsToAllocate;
    1.34 +   info->sizeOfElem       = sizeOfElem;
    1.35 +   info->numInArray       = 0;
    1.36 +   return &(info[1]); //skip over prolog -- info is prolog
    1.37 + }
    1.38 +
    1.39 +
    1.40 +/*A dynamic array is same as any other array, but add a DynArrayInfo next
    1.41 + * to it.  Accesses and updates of array indexes are done normally, it's
    1.42 + * only when add a new element into array that use the extra info.
    1.43 + * An add can cause the pointer to the normal array to change..  so must
    1.44 + * be protected to single VP at a time.
    1.45 + *
    1.46 + *Only need to use this Fn when need a new index, higher than any previous
    1.47 + */
    1.48 +int32
    1.49 +addToDynArray2( void *value, void **array )
    1.50 + { int32 numInArray, sizeOfArray;
    1.51 +   PrivDynArrayInfo *info = giveInfoFor(array); //go backward to prolog
    1.52 +   
    1.53 +   numInArray  = info->numInArray;
    1.54 +   sizeOfArray = info->sizeOfArray;
    1.55 +
    1.56 +   if( numInArray >= sizeOfArray )
    1.57 +    {
    1.58 +      array = increaseSizeOfDynArrayTo2( array, sizeOfArray * 2 );
    1.59 +      info  = giveInfoFor( array );
    1.60 +    }
    1.61 +
    1.62 +   array[ numInArray ] = value;
    1.63 +   info->numInArray++;
    1.64 +
    1.65 +   return numInArray; //index of last elem is one less than num in array
    1.66 + }
    1.67 +
    1.68 +
    1.69 +/*Sets num in array to exactly value give 
    1.70 + *Use this when know how many things going to add in -- then can do this
    1.71 + * once and use as normal array afterwards.  If later add another chunk,
    1.72 + * do this again.  Note, this makes new size be just big enough to hold
    1.73 + * highest index, so will do a linear number of copies if use only this.
    1.74 + *To cut down on number of copies, can use the increaseSizeTo Fn to
    1.75 + * exponentially increase size..
    1.76 + */
    1.77 +void
    1.78 +makeNumInArrayBe2( void **array, int32 numInArray )
    1.79 + { PrivDynArrayInfo *info = giveInfoFor( array );
    1.80 +   
    1.81 +   if( info->sizeOfArray <= numInArray )
    1.82 +    {
    1.83 +      array = increaseSizeOfDynArrayTo2( array, numInArray );
    1.84 +      info = giveInfoFor( array );
    1.85 +    }
    1.86 +   info->numInArray = numInArray; //num is highest index plus 1
    1.87 + }
    1.88 +
    1.89 +/*Allows highest index to remain higher than index give*/
    1.90 +void
    1.91 +makeHighestDynArrayIndexBeAtLeast2( void **array, int32 index)
    1.92 + { PrivDynArrayInfo *info = giveInfoFor( array );
    1.93 + 
    1.94 +   if( index < info->numInArray ) return; //num added diff than size
    1.95 +   else makeNumInArrayBe2( array, index );
    1.96 + }
    1.97 +
    1.98 +
    1.99 +/*Only use this if certain new size is bigger than current size
   1.100 + */
   1.101 +void **
   1.102 +increaseSizeOfDynArrayTo2( void **oldArray, int32 newSize )
   1.103 + { int32 oldsizeOfArray, i, numBytesToCopy;
   1.104 +   void **newArray;
   1.105 +   PrivDynArrayInfo  *oldInfo = giveInfoFor( oldArray );
   1.106 +   PrivDynArrayInfo  *newInfo;
   1.107 +
   1.108 +   oldsizeOfArray   = oldInfo->sizeOfArray;
   1.109 +   if( newSize <= oldsizeOfArray ) return;
   1.110 +
   1.111 +   newInfo = PR_int__malloc( newSize * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo) );
   1.112 +   newArray = &(newInfo[1]);
   1.113 +   
   1.114 +   numBytesToCopy = oldInfo->numInArray * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo);
   1.115 +   memcpy( newInfo, oldInfo, numBytesToCopy ); //copies info + array contents
   1.116 +   
   1.117 +   *(newInfo->addrOfPtrToArray) = newArray; //change contents of array var
   1.118 +   newInfo->sizeOfArray = newSize;
   1.119 +
   1.120 +   PR_int__free( oldInfo );
   1.121 +   
   1.122 +   return newArray;
   1.123 + }
   1.124 +
   1.125 +
   1.126 +/* Frees the array, plus the info
   1.127 + */
   1.128 +void
   1.129 +freeDynArrayDeep2( void *array, FreeFnPtr freeFnPtr )
   1.130 + { PrivDynArrayInfo  *info = giveInfoFor( array );
   1.131 + 
   1.132 +   forAllInDynArrayDo2( array, freeFnPtr );
   1.133 +   PR_int__free( info );
   1.134 + }
   1.135 +
   1.136 +/* Only frees the info
   1.137 + */
   1.138 +void
   1.139 +freeDynArrayFlat2( void *array )
   1.140 + { PrivDynArrayInfo  *info = giveInfoFor( array );
   1.141 + 
   1.142 +   PR_int__free( info );
   1.143 + }
   1.144 +
   1.145 +
   1.146 +/*The function has a fixed prototype: takes a void * returns void
   1.147 + * So, the function has to internally cast void * to whatever data struc..
   1.148 + */
   1.149 +void
   1.150 +forAllInDynArrayDo2( void *array, DynArrayFnPtr fnPtr )
   1.151 + { PrivDynArrayInfo  *info = giveInfoFor( array );
   1.152 +   int32 idx, sizeOfElem;
   1.153 +   void *addrOfElem;
   1.154 +   
   1.155 +   sizeOfElem = info->sizeOfElem;
   1.156 +   for( idx = 0; idx < info->numInArray; idx++ )
   1.157 +    { addrOfElem = ((int8 *)array) + idx * sizeOfElem;
   1.158 +      (*fnPtr)( addrOfElem );
   1.159 +    }
   1.160 + }
   1.161 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/DynArray3.c	Fri Jul 19 12:27:43 2013 -0700
     2.3 @@ -0,0 +1,213 @@
     2.4 +/*
     2.5 + * Copyright 2010  OpenSourceCodeStewardshipFoundation
     2.6 + *
     2.7 + * Licensed under BSD
     2.8 + */
     2.9 +
    2.10 +
    2.11 +
    2.12 +#include <stdio.h>
    2.13 +
    2.14 +#include "DynArray.h"
    2.15 +
    2.16 +//== declarations
    2.17 +void
    2.18 +increaseSizeOfDynArrayTo_Ext( PtrToPrivDynArray *info, int32 newSize );
    2.19 +//==
    2.20 +
    2.21 +PtrToPrivDynArray *
    2.22 +makePrivDynArrayInfoFrom( void ***addrOfPtrToArray, int32 sizeOfArray )
    2.23 + { PtrToPrivDynArray *info;
    2.24 +
    2.25 +   info = PR_int__malloc( sizeof(PtrToPrivDynArray) );
    2.26 +
    2.27 +   info->addrOfPtrToArray = addrOfPtrToArray;
    2.28 +   info->sizeOfArray      = sizeOfArray;
    2.29 +   info->numInArray       = 0;
    2.30 +   return info;
    2.31 + }
    2.32 +
    2.33 +PtrToPrivDynArray *
    2.34 +makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray )
    2.35 + { PtrToPrivDynArray *info;
    2.36 +
    2.37 +   info = PR_int__malloc( sizeof(PtrToPrivDynArray) );
    2.38 +
    2.39 +   info->addrOfPtrToArray = addrOfPtrToArray;
    2.40 +
    2.41 +   *(addrOfPtrToArray)    = PR_int__malloc( sizeOfArray * sizeof(void *) );
    2.42 +   info->sizeOfArray      = sizeOfArray;
    2.43 +   info->numInArray       = 0;
    2.44 +   return info;
    2.45 + }
    2.46 +
    2.47 +PtrToPrivDynArray *
    2.48 +makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray )
    2.49 + { PtrToPrivDynArray *info;
    2.50 +
    2.51 +   info = malloc( sizeof(PtrToPrivDynArray) );
    2.52 +
    2.53 +   info->addrOfPtrToArray = addrOfPtrToArray;
    2.54 +
    2.55 +   *(addrOfPtrToArray)    = malloc( sizeOfArray * sizeof(void *) );
    2.56 +   info->sizeOfArray      = sizeOfArray;
    2.57 +   info->numInArray       = 0;
    2.58 + }
    2.59 +
    2.60 +
    2.61 +/*A dynamic array is same as any other array, but add a DynArrayInfo next
    2.62 + * to it.  Accesses and updates of array indexes are done normally, it's
    2.63 + * only when add a new element into array that use the extra info.
    2.64 + * An add can cause the pointer to the normal array to change..  so must
    2.65 + * be protected to single VP at a time.
    2.66 + *
    2.67 + *Only need to use this Fn when need a new index, higher than any previous
    2.68 + */
    2.69 +int32
    2.70 +addToDynArray( void *value, PtrToPrivDynArray *info )
    2.71 + { int32 numInArray, sizeOfArray;
    2.72 +   void **array;
    2.73 +
    2.74 +   numInArray = info->numInArray;
    2.75 +   sizeOfArray    = info->sizeOfArray;
    2.76 +
    2.77 +   if( numInArray >= sizeOfArray )
    2.78 +    {
    2.79 +      increaseSizeOfDynArrayTo( info, sizeOfArray * 2 );
    2.80 +    }
    2.81 +
    2.82 +   array = *(info->addrOfPtrToArray);
    2.83 +   array[ numInArray ] = value;
    2.84 +   info->numInArray++;
    2.85 +
    2.86 +   return numInArray; //pre-incr value is the index put value into
    2.87 + }
    2.88 +int32
    2.89 +addToDynArray_Ext( void *value, PtrToPrivDynArray *ptrToArray )
    2.90 + { int32 numInArray, sizeOfArray;
    2.91 +   void **array;
    2.92 +
    2.93 +   numInArray = ptrToArray->numInArray;
    2.94 +   sizeOfArray    = ptrToArray->sizeOfArray;
    2.95 +
    2.96 +   if( numInArray >= sizeOfArray )
    2.97 +    {
    2.98 +      increaseSizeOfDynArrayTo_Ext( ptrToArray, sizeOfArray * 2 );
    2.99 +    }
   2.100 +
   2.101 +   array = *(ptrToArray->addrOfPtrToArray);
   2.102 +   array[ numInArray ] = value;
   2.103 +   ptrToArray->numInArray++;
   2.104 +
   2.105 +   return numInArray; //pre-incr value is the index put value into
   2.106 + }
   2.107 +
   2.108 +
   2.109 +/*Use this when know how many things going to add in -- then can do this
   2.110 + * once and use as normal array afterwards.  If later add another chunk,
   2.111 + * do this again.  Note, this makes new size be just big enough to hold
   2.112 + * highest index, so will do a linear number of copies if use only this.
   2.113 + *To cut down on number of copies, can use the increaseSizeTo Fn to
   2.114 + * exponentially increase size..
   2.115 + */
   2.116 +void
   2.117 +makeHighestDynArrayIndexBe( PtrToPrivDynArray *info, int32 highestIndex )
   2.118 + {
   2.119 +   if( info->sizeOfArray <= highestIndex )
   2.120 +    {
   2.121 +      increaseSizeOfDynArrayTo( info, highestIndex + 1 );
   2.122 +    }
   2.123 +   info->numInArray = highestIndex + 1;
   2.124 + }
   2.125 +
   2.126 +void
   2.127 +makeHighestDynArrayIndexBeAtLeast(PtrToPrivDynArray *info, int32 index)
   2.128 + {
   2.129 +   if( index < info->numInArray ) return;
   2.130 +   else makeHighestDynArrayIndexBe( info, index );
   2.131 + }
   2.132 +
   2.133 +
   2.134 +/*Only use this if certain new size is bigger than current size
   2.135 + */
   2.136 +void
   2.137 +increaseSizeOfDynArrayTo( PtrToPrivDynArray *info, int32 newSize )
   2.138 + { int32 oldSizeOfArray, i;
   2.139 +   void **newArray, **oldArray;
   2.140 +
   2.141 +   oldSizeOfArray   = info->sizeOfArray;
   2.142 +   if( newSize <= oldSizeOfArray ) return;
   2.143 +
   2.144 +   oldArray         = *(info->addrOfPtrToArray);
   2.145 +   newArray         = PR_int__malloc( newSize * sizeof(void *) );
   2.146 +
   2.147 +   for( i = 0; i < oldSizeOfArray; i++ )
   2.148 +    {
   2.149 +      newArray[i] = oldArray[i];
   2.150 +    }
   2.151 +   *(info->addrOfPtrToArray) = newArray; //change location of array-ptr
   2.152 +   info->sizeOfArray = newSize;
   2.153 +
   2.154 +   PR_int__free( oldArray );
   2.155 + }
   2.156 +
   2.157 +/*Can't mix PR_int__malloc locations with external malloc locations -- so use
   2.158 + * this version inside PR, which will perform normal malloc in the core
   2.159 + * loop -- hopefully avoiding the annoying system-stack bugs..
   2.160 + */
   2.161 +void
   2.162 +increaseSizeOfDynArrayTo_Ext( PtrToPrivDynArray *info, int32 newSize )
   2.163 + { int32 oldSizeOfArray, i;
   2.164 +   void **newArray, **oldArray;
   2.165 +
   2.166 +   oldSizeOfArray   = info->sizeOfArray;
   2.167 +   if( newSize <= oldSizeOfArray ) return;
   2.168 +
   2.169 +   oldArray         = *(info->addrOfPtrToArray);
   2.170 +   newArray         = malloc( newSize * sizeof(void *) );
   2.171 +
   2.172 +   for( i = 0; i < oldSizeOfArray; i++ )
   2.173 +    {
   2.174 +      newArray[i] = oldArray[i];
   2.175 +    }
   2.176 +   *(info->addrOfPtrToArray) = newArray; //change location of array-ptr
   2.177 +   info->sizeOfArray = newSize;
   2.178 +
   2.179 +   free( oldArray );
   2.180 + }
   2.181 +
   2.182 +
   2.183 +/* Frees the array, plus the info
   2.184 + */
   2.185 +void
   2.186 +freeDynArrayDeep( PtrToPrivDynArray *info, FreeFnPtr freeFnPtr )
   2.187 + {
   2.188 +   forAllInDynArrayDo( info, freeFnPtr );
   2.189 +   PR_int__free( *(info->addrOfPtrToArray) );
   2.190 +   PR_int__free( info );
   2.191 + }
   2.192 +
   2.193 +/* Only frees the info
   2.194 + */
   2.195 +void
   2.196 +freeDynArrayFlat( PtrToPrivDynArray *info )
   2.197 + {
   2.198 +   PR_int__free( info );
   2.199 + }
   2.200 +
   2.201 +
   2.202 +/*The function has a fixed prototype: takes a void * returns void
   2.203 + * So, the function has to internally cast void * to whatever data struc..
   2.204 + */
   2.205 +void
   2.206 +forAllInDynArrayDo( PtrToPrivDynArray *info, DynArrayFnPtr fnPtr )
   2.207 + { int32 idx;
   2.208 +   void **array;
   2.209 +
   2.210 +   array = *(info->addrOfPtrToArray);
   2.211 +   for( idx = 0; idx < info->numInArray; idx++ )
   2.212 +    {
   2.213 +      (*fnPtr)(array[idx]);
   2.214 +    }
   2.215 + }
   2.216 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/DynArray3.h	Fri Jul 19 12:27:43 2013 -0700
     3.3 @@ -0,0 +1,97 @@
     3.4 +/* 
     3.5 + * File:   Vector.h
     3.6 + * Author: Me
     3.7 + *
     3.8 + * Created on May 14, 2010, 3:08 PM
     3.9 + */
    3.10 +
    3.11 +#ifndef _DYNARRAY_H
    3.12 +#define	_DYNARRAY_H
    3.13 +
    3.14 +#include "PR_impl/PR_primitive_data_types.h"
    3.15 +#include "PR_impl/Services_Offered_by_PR/Memory_Handling/vmalloc.h"
    3.16 +
    3.17 +
    3.18 +/*WARNING: Passing a DynArray as a param is dangerous if add to the DynArray
    3.19 + * inside the function called!   After adding or other operation that might
    3.20 + * change the size, must re-read the addr of the chunk of memory that is the
    3.21 + * array, via the DynArrayInfo.
    3.22 + *Here's why: An array variable is a location, either on the stack
    3.23 + * or in a field of a struct, whose contents is an addr.  That addr is of the
    3.24 + * first location of a chunk of locations.  The DynArray works by changing
    3.25 + * the chunk of locations, then modifying the contents of the original 
    3.26 + * array variable.  It overwrites the addr of the old chunk of locations
    3.27 + * with the addr of the new chunk.
    3.28 + *But when the array variable is passed as a parameter, such as 
    3.29 + * in this: "foo( myDynArray )", then there are now two locations that hold
    3.30 + * the addr of the same chunk of locations.  So when a call is made that
    3.31 + * adds to the DynArray, and inside the DynArray expands, it only updates
    3.32 + * the original location with  the new addr.  Hence, the function will begin
    3.33 + * overwriting memory past the end of the old chunk, because it still has 
    3.34 + * the pointer to the old chunk of locations.
    3.35 + *
    3.36 + *A dynamic array is accessed same as any other array.  However, must use
    3.37 + * dyn array calls, defined in here, in order to add or increase the size.
    3.38 + * Must re-read the original array variable after any size-changing calls.
    3.39 + *To pass a DynArray as a parameter to a function, can only pass the 
    3.40 + * DynArrayInfo, then inside the function, to read the addr of the first 
    3.41 + * location in the chunk of locations that is the array, do this:
    3.42 + * "localArrayCopy = *(myDynArrayInfo->addrOfPtrToArray).  After that, can 
    3.43 + * treat localArrayCopy as a normal array, as long as don't make any calls
    3.44 + * that add or otherwise could increase the size of the array.  If do make
    3.45 + * such a call, then re-copy the array via the above.  Can then use the
    3.46 + * copy up until another add to the array.
    3.47 + * 
    3.48 + */
    3.49 +typedef struct
    3.50 + {
    3.51 +   void ***addrOfPtrToArray; //addr of array of ptrs == triple *
    3.52 +   int32   numInArray;
    3.53 +   int32   sizeOfArray;
    3.54 + }
    3.55 +PrivDynArrayInfo;
    3.56 +
    3.57 +
    3.58 +typedef struct
    3.59 + {
    3.60 +   void  **ptrToLocations;  //must be in first position
    3.61 +   int32   numInArray;
    3.62 +   int32   sizeOfArray;
    3.63 + }
    3.64 +PrivDynArray;
    3.65 +
    3.66 +
    3.67 +PrivDynArrayInfo *
    3.68 +makePrivDynArrayOfSize( int32 sizeOfArray );
    3.69 +
    3.70 +PrivDynArrayInfo *
    3.71 +makePrivDynArrayOfSize_Ext( int32 sizeOfArray );
    3.72 +
    3.73 +int32
    3.74 +addToDynArray( void *value, void *array );
    3.75 +
    3.76 +void
    3.77 +makeHighestDynArrayIndexBe( void *array, int32 highestIndex );
    3.78 +
    3.79 +void
    3.80 +makeHighestDynArrayIndexBeAtLeast( void *array, int32 highestIndex);
    3.81 +
    3.82 +void
    3.83 +increaseSizeOfDynArrayTo( void *array, int32 newSize );
    3.84 +
    3.85 +typedef void  (*FreeFnPtr)  ( void * ); //fn has to cast void * to whatever
    3.86 +
    3.87 +void
    3.88 +freeDynArrayDeep( void *array, FreeFnPtr freeFnPtr );
    3.89 +
    3.90 +void
    3.91 +freeDynArrayFlat( void *array );
    3.92 +
    3.93 +
    3.94 +typedef void  (*DynArrayFnPtr)  ( void * );  //fn has to cast void *
    3.95 +
    3.96 +void
    3.97 +forAllInDynArrayDo( void *array, DynArrayFnPtr fnPtr );
    3.98 +
    3.99 +#endif	/* _DYNARRAY_H */
   3.100 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/__brch__Dev_prolog_vers	Fri Jul 19 12:27:43 2013 -0700
     4.3 @@ -0,0 +1,4 @@
     4.4 +This branch is for the project structure defined Jan 2012..  the #includes reflect this directory structure.
     4.5 +
     4.6 +More importantly, the MC_shared  version of PR requires a separat malloc implemeted by PR code..  so this branch has modified the library to use the PR-specific malloc.
     4.7 +
     5.1 --- a/__brch__Renamed_VMS_to_PR	Fri Mar 08 05:37:45 2013 -0800
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,4 +0,0 @@
     5.4 -This branch is for the project structure defined Jan 2012..  the #includes reflect this directory structure.
     5.5 -
     5.6 -More importantly, the MC_shared  version of PR requires a separat malloc implemeted by PR code..  so this branch has modified the library to use the PR-specific malloc.
     5.7 -