Gamestudio Links
Zorro Links
Newest Posts
Help with plotting multiple ZigZag
by degenerate_762. 04/30/24 23:23
M1 Oversampling
by 11honza11. 04/30/24 08:16
Trading Journey
by howardR. 04/28/24 09:55
Zorro Trader GPT
by TipmyPip. 04/27/24 13:50
Data from CSV not parsed correctly
by jcl. 04/26/24 11:18
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
1 registered members (AndrewAMD), 972 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Newest Members
firatv, wandaluciaia, Mega_Rod, EternallyCurious, howardR
19050 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
dynamic array handling helpers #456671
12/03/15 09:21
12/03/15 09:21
Joined: Mar 2011
Posts: 3,150
Budapest
sivan Offline OP
Expert
sivan  Offline OP
Expert

Joined: Mar 2011
Posts: 3,150
Budapest
Hi folks,

I nearly forgot to share this little dynamic array helper script I made for myself, and an additional demo showing how to use it. You can find comments at nearly all of the demo lines, and the MBarray.h contains detailed descriptions and examples for each function.

Nothing complex, it just helps a bit the basic array operations, with a few safety checks. Everything is tested, but not stupid safe, so normally cannot harm your computer. laugh
- create an array
- create an array and fill with default value
- resize array (both increase and decrease)
- add new element
- free an existing array
- pseudo 2d array rotation (1d with 2d conversions)
- pseudo 3d array rotation (1d with 3d conversions)

Just create 3 script files with the given names to get the demo (Arraytest.c) work.
If you have any idea what to add, please tell me.

Arraytest.c
Code:
/////////////////////////////////////
// includes


// engine
#include <acknex.h>											// A8 game engine
//#include <default.c>										// do not include in this demo, key_esc is used in main loop, and default.c would override it
//#include <windows.h>										// to access GetTickCount for precision timer
//#include <strio.c>											// Win API I/O functions - needed by file handling functions used in wmb compilation

// array helper scripts
#include "MBarray.h"
#include "MBarray.c"


/////////////////////////////////////
// defines


/////////////////////////////////////
// variables


char* 	char_array = NULL;
int		char_array_length = 0;

short*	short_array = NULL;
int		short_array_length = 0;

int*		int_array = NULL;
int		int_array_length = 0;

var*		var_array = NULL;
int		var_array_length = 0;

VECTOR*	vec_array = NULL;
int		vec_array_length = 0;

typedef struct TEST_STRUCT
{
	var variable_var;
	int variable_int;
	VECTOR variable_vec;
	
} TEST_STRUCT;

TEST_STRUCT* 	struct_array = NULL;
int				struct_array_length = 0;


/////////////////////////////////////
// functions


void	main();
	
	// show array content - function overloading does not work in lite-c, similarly to C
	void	ShowArrayElements_char(char* inarray, int arraylength, var posx, var posy);
	void	ShowArrayElements_short(short* inarray, int arraylength, var posx, var posy);
	void	ShowArrayElements_int(int* inarray, int arraylength, var posx, var posy);
	void	ShowArrayElements_var(var* inarray, int arraylength, var posx, var posy);
	void	ShowArrayElements_vec(VECTOR* inarray, int arraylength, var posx, var posy);
	void	ShowArrayElements_struct(TEST_STRUCT* inarray, int arraylength, var posx, var posy);


/////////////////////////////////////
// code


void	main()
{
	//------------------------------------------------------------------------
	// default array length
	
	int newlength = 10;
	
	//------------------------------------------------------------------------
	// initialize arrays
	
	//------------------------------------
	// char array
	
	char_array = array_new(sizeof(char), &char_array_length, newlength);									// default value 0
	
	char_array[0] = 100;																									// 8th element is set to 100
	array_fill_char(&char_array[8], 2, 10);																		// 9-10 elements are set to 10
	array_fillbytes(&char_array[2], sizeof(char), 3, 1);														// 3-5 elements are set to 1, by using void* as fnction parameter, and defining element size
	
	//------------------------------------
	// short array
	
	short_array = array_new(sizeof(short), &short_array_length, newlength, 255);						// default value 65535
	
	short_array[0] = 10000;																								// 10th element is set to 10000
	array_fill_short(&short_array[8], 2, 10);																		// 9-10 elements are set to 10
	array_fillbytes(&short_array[2], sizeof(short), 3, 1);													// all bytes of 3-5 elements are set to 1 = 257, by using void* as fnction parameter, and defining element size
	
	short temp_short = 5000;																							// temp value to be used for array elements
	short_array = array_add(short_array, sizeof(short), &short_array_length, 2, &temp_short);		// add new elements
	
	//------------------------------------
	// int array
	
	int_array = array_new(sizeof(int), &int_array_length, newlength);										// default value 0
	
	array_fill_int(int_array, int_array_length, 111);															// all elements are set to 111 - not per byte setting, thus any value works within integer range
	int_array[7] = 100000;																								// 8th element is set to 100000
	array_fill_int(&int_array[2], 3, 100);																			// 3-5 elements are set to 100 - not per byte setting, thus any value works within integer range
	
	//------------------------------------
	// var array
	
	var_array = array_new(sizeof(var), &var_array_length, newlength);										// default value 0
	
	array_fill_var(var_array, var_array_length, 123.456);														// all elements are set to 100 - not per byte setting, thus any value works within integer range
	
	var_array = array_resize(var_array, sizeof(var), &var_array_length, var_array_length-2);		// decrease size by popping last 2 elements
	
	var temp_var = 100.001;
	array_fill(&var_array[2], sizeof(var), 2, &temp_var);														// 3-4 element set to temp_var, by using void* as fnction parameter, and defining element size
	
	//------------------------------------
	// VECTOR array
	
	vec_array = array_new(sizeof(VECTOR), &vec_array_length, newlength);									// default value 0,0,0
	
	VECTOR temp_vec;																										// temp VECTOR to be used for array elements
	temp_vec.x = 1.1;
	temp_vec.y = 2.2;
	temp_vec.z = 3.3;
	
	array_fill_vec(vec_array, vec_array_length, &temp_vec);													// set all elements to new element value, by using a loop, thus slower than fillbytes
	array_fillbytes(&vec_array[2], sizeof(VECTOR), 3, 0);														// set all bytes of any type or struct 
																																// in case of int, var, or VECTOR, only zero is opractical to be used with fillbytes
	array_fill(&vec_array[7], sizeof(VECTOR), 2, vector(1, 2, 3));											// 8-9 element is set to 1,2,3, by using void* as fnction parameter, and defining element size
	
	temp_vec.x = 4;
	temp_vec.y = 5;
	temp_vec.z = 6;
	
	vec_array = array_add(vec_array, sizeof(VECTOR), &vec_array_length, 2, &temp_vec);				// add new elements
	
	//------------------------------------
	// struct array
	
	struct_array = array_new(sizeof(TEST_STRUCT), &struct_array_length, 5);
	
	struct_array[3].variable_var = 123.456;																		// set 4th struct array element parameters directly
	struct_array[3].variable_int = 100000;
	vec_set(struct_array[3].variable_vec, vector(1.1,2.2,3.3));	
	
	TEST_STRUCT temp_struct;																							// temp struct to be used for array elements	
	temp_struct.variable_var = 111.111;
	temp_struct.variable_int = 111111;
	vec_set(temp_struct.variable_vec, vector(1.111,2.222,3.333));	
	
	struct_array = array_add(struct_array, sizeof(TEST_STRUCT), &struct_array_length, 5, &temp_struct);	// add new elements
	
	//------------------------------------------------------------------------
	// display results
	
	while(1)
		{
			draw_text("char*", 	50, 25, COLOR_WHITE);
			draw_text("short*", 	150, 25, COLOR_BLUE);
			draw_text("int*", 	250, 25, COLOR_RED);
			draw_text("var*", 	350, 25, COLOR_GREEN);
			draw_text("VECTOR*", 450, 25, vector(255, 255, 0));
			
			draw_text("struct*", 50, 300, vector(0, 255, 255));
			draw_text("var", 		50, 325, vector(0, 255, 255));
			draw_text("int", 		150, 325, vector(0, 255, 255));
			draw_text("VECTOR", 	250, 325, vector(0, 255, 255));
			
			ShowArrayElements_char(char_array, char_array_length, 50, 50);
			ShowArrayElements_short(short_array, short_array_length, 150, 50);
			ShowArrayElements_int(int_array, int_array_length, 250, 50);
			ShowArrayElements_var(var_array, var_array_length, 350, 50);
			ShowArrayElements_vec(vec_array, vec_array_length, 450, 50);
			ShowArrayElements_struct(struct_array, struct_array_length, 50, 350);
			
			if (key_esc) break;
			
			wait(1);
		}
	
	//------------------------------------------------------------------------
	// free memory
	
	array_destroy( char_array );
	array_destroy( short_array );
	array_destroy( int_array );
	array_destroy( var_array );
	array_destroy( vec_array );
	array_destroy( struct_array );
	
	//------------------------------------------------------------------------
	
//	wait(-3);
	sys_exit(NULL);
}


/////////////////////////////////////
// show array content


void	ShowArrayElements_char(char* inarray, int arraylength, var posx, var posy)
{
	if (!inarray) return;
	
	int i;
	for (i=0; i<arraylength; ++i)
		{
			draw_text( str_for_int(NULL, (int)inarray[i]), posx, posy + i*20, COLOR_WHITE );
		}
}


void	ShowArrayElements_short(short* inarray, int arraylength, var posx, var posy)
{
	if (!inarray) return;
	
	int i;
	for (i=0; i<arraylength; ++i)
		{
			draw_text( str_for_int(NULL, (int)inarray[i]), posx, posy + i*20, COLOR_BLUE );
		}
}


void	ShowArrayElements_int(int* inarray, int arraylength, var posx, var posy)
{
	if (!inarray) return;
	
	int i;
	for (i=0; i<arraylength; ++i)
		{
			draw_text( str_for_int(NULL, inarray[i]), posx, posy + i*20, COLOR_RED );
		}
}


void	ShowArrayElements_var(var* inarray, int arraylength, var posx, var posy)
{
	if (!inarray) return;
	
	int i;
	for (i=0; i<arraylength; ++i)
		{
			draw_text( str_for_num(NULL, inarray[i]), posx, posy + i*20, COLOR_GREEN );
		}
}


void	ShowArrayElements_vec(VECTOR* inarray, int arraylength, var posx, var posy)
{
	if (!inarray) return;
	
	int i;
	for (i=0; i<arraylength; ++i)
		{
			draw_text( str_for_num(NULL, inarray[i].x), posx, 			posy + i*20, vector(255, 255, 0) );
			draw_text( str_for_num(NULL, inarray[i].y), posx + 50, 	posy + i*20, vector(255, 255, 0) );
			draw_text( str_for_num(NULL, inarray[i].z), posx + 100, 	posy + i*20, vector(255, 255, 0) );
		}
}


void	ShowArrayElements_struct(TEST_STRUCT* inarray, int arraylength, var posx, var posy)
{
	if (!inarray) return;
	
	int i;
	for (i=0; i<arraylength; ++i)
		{
			draw_text( str_for_num(NULL, inarray[i].variable_var), posx, 				posy + i*20, vector(0, 255, 255) );
			draw_text( str_for_num(NULL, inarray[i].variable_int), posx + 100, 		posy + i*20, vector(0, 255, 255) );			
			
			draw_text( str_for_num(NULL, inarray[i].variable_vec.x), posx + 200, 	posy + i*20, vector(0, 255, 255) );
			draw_text( str_for_num(NULL, inarray[i].variable_vec.y), posx + 300, 	posy + i*20, vector(0, 255, 255) );
			draw_text( str_for_num(NULL, inarray[i].variable_vec.z), posx + 400, 	posy + i*20, vector(0, 255, 255) );
		}
}


/////////////////////////////////////



MBArray.h
Code:
#ifndef MBarray_h
#define MBarray_h


//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// macros


#define new(structtype) sys_malloc(sizeof(structtype))
#define new_array(structtype, length) sys_malloc(length * sizeof(structtype))


//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// functions


//////////////////////////////////////////////////////////////////////////////////////
/*
	array operations	
	
	requirements:
	- the array (initially set to NULL),
	- an int variable storing array length (optional)
	
	if structs contain inner dynamic arrays, they should be separately allocated and freed!
*/


/* 
	allocate memory of a new array with the given number of elements,
	initializes all bytes to zero
	
	(initially MyArray should be NULL)
	(arraylength can be NULL)
	
	returns the array, sets arraylength (optional, if not NULL)
	
	example-1 : MYARRAYTYPE* MyArray = array_new( sizeof(MYARRAYTYPE), NULL, 10 );							
					
	example-2 : int MyArrayLength = 10;
					MYARRAYTYPE* MyArray = array_new( sizeof(MYARRAYTYPE), NULL, MyArrayLength );							
					
	example-3 : int MyArrayLength = 0;
					MYARRAYTYPE* MyArray = array_new( sizeof(MYARRAYTYPE), &MyArrayLength, 10 );	
					(now MyArrayLength is set to 10)
*/
void*		array_new(int elementsize, int* arraylength, int newelementscount);


/*
	same as array_new() but initializes all bytes to (char)defaultvalue (instead of zero)
	
	returns the array, sets arraylength (optional, if not NULL)
	
	example-1 : MyArray = array_new( sizeof(MYARRAYTYPE), NULL, 10, 255 );
	
	example-2 : int MyArrayLength;
					MYARRAYTYPE* MyArray = array_new( sizeof(MYARRAYTYPE), &MyArrayLength, 10, 255 );
*/
void*		array_new(int elementsize, int* arraylength, int newelementscount, int defaultvalue);


/* 
	fill an array with the given value,
	also can be used to fill part of an array, 
	by giving pointer to the starting element, 
	and defining a few element length as arraylength (must not exceed real arraylength)
	
	example : 	array_fill( MyArray, MyArrayLength, 10 );	
*/
void		array_fill_char(char* arrayin, int arraylength, char elementvalue);								// loop and =
void		array_fill_short(short* arrayin, int arraylength, short elementvalue);							// loop and =
void		array_fill_int(int* arrayin, int arraylength, int elementvalue);									// loop and =
void		array_fill_var(var* arrayin, int arraylength, var elementvalue);									// loop and =
void		array_fill_vec(VECTOR* arrayin, int arraylength, VECTOR* elementvalue);							// loop and memcpy


/* 
	same as array_fill_xxx, but okay for any type, using a locally created element,
	
	example : 	short NewElement = 10;
					array_fill( MyArray, sizeof(short), MyArrayLength, &NewElement );	
*/	
void		array_fill(void* arrayin, int elementsize, int arraylength, void* elementvalue);				// loop and memcpy, for any types or structs


/* 
	fills all bytes of the array with the given char value,
	
	example : 	array_fillbytes( MyArray, sizeof(int), MyArrayLength, (char)10 );	
*/
void		array_fillbytes(void* arrayin, int elementsize, int arraylength, char bytevalue);			// memset, for any types or structs


/* 
	increase or decrease array size,
	reallocate memory of an existing array to the new size,
	if length is increased, all bytes of new elements are set to zero
	
	returns the array, sets arraylength (must not be NULL!)
	
	example : MyArray = array_resize( MyArray, sizeof(MYARRAYTYPE), &MyArrayLength, 10 );
*/
void*		array_resize(void* arrayin, int elementsize, int* arraylength, int newsize);


/* 
	increase or decrease array size,
	reallocate memory of an existing array with a given number of new elements,
	fill new elements with default value given by one locally created element,
	or decrease array length if newelementscount is negative
	
	returns the array, sets arraylength (must not be NULL!)
	
	example : 	short newelement = 10;
					MyArray = array_add( MyArray, sizeof(short), &MyArrayLength, 3, &newelement );	
*/
void*		array_add(void* arrayin, int elementsize, int* arraylength, int newelementscount, void* newelement);


/*
	free array memory, set it to NULL for future usage,
	and set the corresponding length to zero if given
	
	example : array_destroy( MyArray, &MyArrayLength );	
*/
void		array_destroy(void* arrayin);
void		array_destroy(void* arrayin, int* arraylength);

void		array_destroy2(void** arrayin);
void		array_destroy2(void** arrayin, int* arraylength);


//////////////////////////////////////////////////////////////////////////////////////
// pseudo 2D array operations
//	elements are supposed to be organized similarly to coordinates, (X=0;Y=0) element is the bottom left one


// helpers
int		array2d_getx(int sizex, int sizey, int abspos);
int		array2d_gety(int sizex, int sizey, int abspos);
int		array2d_getabs(int sizex, int sizey, int posx, int posy);


/*
	reposition array elements as it would be rotated as a 2D matrix
	to the given direction (angle/45), assuming currently looking towards 0
	
	returns the new array
	
	example : 	int* MyArray is the existing array to be rotated
					int MyRotateArrayLength = MyArrayLength;
					int MyRotateSizeX = MySizeX;
					int MyRotateSizeY = MySizeY;
					MYARRAYTYPE* MyRotatedArray = array2d_rotate( MyArray, sizeof(MYARRAYTYPE), &MyRotateArrayLength, 2, &MyRotateSizeX, &MyRotateSizeY );	
	(direction 2 means rotation by 90 degrees)
	(no diagonal rotation supported i.e. 1,3,5,7)
*/	
void*		array2d_rotate(void* arrayin, int elementsize, int* arraylength, int direction, int* sizex, int* sizey);


//////////////////////////////////////////////////////////////////////////////////////
// pseudo 3D array operations
// the first X*Y elements corresponds to Z=0


// helpers
int		array3d_getx(int sizex, int sizey, int sizez, int abspos);
int		array3d_gety(int sizex, int sizey, int sizez, int abspos);
int		array3d_getabs(int sizex, int sizey, int posx, int posy, int posz);


/*
	same as array2d_rotate() but supports 3D arrays organized level by level
*/
void*		array3d_rotate(void* arrayin, int elementsize, int* arraylength, int direction, int* sizex, int* sizey);


//////////////////////////////////////////////////////////////////////////////////////


#endif



MBArray.c
Code:
#ifndef MBarray_c
#define MBarray_c


///////////////////////////////////////////////////////////////////////////////////////////
// array helpers


void*		array_new(int elementsize, int* arraylength, int newelementscount)
{
	if (elementsize <= 0)			return NULL;
	if (newelementscount <= 0)		return NULL;
	
	int newsize = newelementscount;																				// cannot be smaller than 0
	
	void* arrayout = (void*)sys_malloc(elementsize * newsize);
	
	if (!arrayout) 
		{
//			printf( "array_new error!" );																			// error			
			return NULL;
		}
	else
		{
//			memset(arrayout, (char)0, elementsize * newsize);												// set everything to 0, char based! - not essential, sys_malloc sets them to 0
			
			if (arraylength)
				{
					*arraylength = newelementscount;
				}
		} 
	
	return(arrayout);
}


void*		array_new(int elementsize, int* arraylength, int newelementscount, int defaultvalue)
{
	if (elementsize <= 0)			return NULL;
	if (newelementscount <= 0)		return NULL;
	
	int newsize = newelementscount;																				// cannot be smaller than 0
	
	void* arrayout = (void*)sys_malloc(elementsize * newsize);
	
	if (!arrayout) 
		{
//			printf( "array_new with default byte value error!" );	
			return NULL;
		}
	else
		{
			memset(arrayout, (char)defaultvalue, elementsize * newsize);								// set everything to defaultvalue, char based!
			
			if (arraylength)
				{
					*arraylength = newelementscount;
				}
		} 
	
	return(arrayout);
}


//////////////////////////////////////////////////////////////////////////////////////


void		array_fill_char(char* arrayin, int arraylength, char elementvalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
		
	int i;								
	for(i=0; i<arraylength; ++i)
		{
			arrayin[i] = elementvalue;
		}
}


void		array_fill_short(short* arrayin, int arraylength, short elementvalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
	
	int i;								
	for(i=0; i<arraylength; ++i)
		{
			arrayin[i] = elementvalue;
		}
}


void		array_fill_int(int* arrayin, int arraylength, int elementvalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
	
	int i;								
	for(i=0; i<arraylength; ++i)
		{
			arrayin[i] = elementvalue;
		}
}


void		array_fill_var(var* arrayin, int arraylength, var elementvalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
	
	int i;								
	for(i=0; i<arraylength; ++i)
		{
			arrayin[i] = elementvalue;
		}
}


void		array_fill_vec(VECTOR* arrayin, int arraylength, VECTOR* elementvalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
	if (!elementvalue)			return;
	
	int i;								
	for(i=0; i<arraylength; ++i)
		{
			memcpy( &arrayin[i] , elementvalue , sizeof(VECTOR) );
//			memcpy( arrayin + i * sizeof(VECTOR) , elementvalue , sizeof(VECTOR) );					// not working...
		}
}


//////////////////////////////////////////////////////////////////////////////////////


void		array_fill(void* arrayin, int elementsize, int arraylength, void* elementvalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
	if (!elementvalue)			return;
	
	int i;								
	for(i=0; i<arraylength; ++i)
		{
			char* j = (char*)arrayin + i * elementsize;														// char* casting is required!
			memcpy( j , elementvalue , elementsize ); 
		}
}


//////////////////////////////////////////////////////////////////////////////////////


void		array_fillbytes(void* arrayin, int elementsize, int arraylength, char bytevalue)
{
	if (!arrayin)					return;
	if (arraylength <= 0)		return;
	
	memset(arrayin, bytevalue, elementsize * arraylength);
}


//////////////////////////////////////////////////////////////////////////////////////


void*		array_resize(void* arrayin, int elementsize, int* arraylength, int newsize)
{
	//--------------------------------------------------------------
	
	if (!arrayin)					return arrayin;
	if (elementsize <= 0)		return arrayin;
	if (!arraylength)				return arrayin;
	
	//--------------------------------------------------------------
	
	int oldsize = *arraylength;
	
	//--------------------------------------------------------------
	
	if (newsize <= 0)				return arrayin;
	if (newsize == oldsize)		return arrayin;
	
	//--------------------------------------------------------------
	
	int sizetocopy = 0;
	if (newsize > oldsize)
		{
			sizetocopy = oldsize;
		}
	else
		{
			sizetocopy = newsize;
		}
	
	//--------------------------------------------------------------
		
	void* arrayout = (void*)sys_malloc(elementsize * newsize);
	
	//--------------------------------------------------------------
	
	if (!arrayout) 
		{
//			printf( "array_resize error!" );
			return arrayin;
		}
	else
		{
			memcpy( arrayout, arrayin, sizetocopy * elementsize);										// copy old content						
			
			*arraylength = newsize;																				// set array length
		}
	
	//--------------------------------------------------------------
	
	sys_free(arrayin);
	arrayin = NULL;
	
	return arrayout;
	
	//--------------------------------------------------------------
}


void*		array_add(void* arrayin, int elementsize, int* arraylength, int newelementscount, void* newelement)
{
	//--------------------------------------------------------------
	
	if (!arrayin)					return arrayin;
	if (elementsize <= 0)		return arrayin;
	if (!arraylength)				return arrayin;
		
	//--------------------------------------------------------------
	
	int oldsize = *arraylength;
	int newsize = *arraylength + newelementscount;																	// can be smaller than arraylength!
	
	//--------------------------------------------------------------
	
	if (newsize <= 0)				return arrayin;
	if (newsize == oldsize)		return arrayin;
	
	//--------------------------------------------------------------
	
	int sizetocopy = 0;
	if (newsize > oldsize)
		{
			sizetocopy = oldsize;
		}
	else
		{
			sizetocopy = newsize;
		}
	
	//--------------------------------------------------------------
	
	void* arrayout = (void*)sys_malloc(elementsize * newsize);
	
	//--------------------------------------------------------------
	
	if (!arrayout) 
		{
//			printf( "array_add error!" );			
			return arrayin;
		}
	else
		{
			memcpy( arrayout, arrayin, sizetocopy * elementsize);													// copy old content
			
			if (newelementscount > 0)																						// add new content if needed
				{
					if (newelement)
						{
							int i;								
							for(i=0; i<newelementscount; ++i)
								{
									char* j = (char*)arrayout + oldsize * elementsize + i * elementsize;		// char* casting is required!
									memcpy( j , newelement , elementsize ); 	
								}
						}
//					else
//						{
//							memset( &arrayout[oldsize], (char)0, elementsize * abs(newsize-oldsize));		// set all bytes of new elements to 0, char based! - not essential, sys_malloc sets them to 0
//						}
				}
			
			*arraylength += newelementscount;																			// increase array length
		}
	
	//--------------------------------------------------------------
	
	sys_free(arrayin);
	arrayin = NULL;
	
	return arrayout;
	
	//--------------------------------------------------------------
}


//////////////////////////////////////////////////////////////////////////////////////


void		array_destroy(void* arrayin)
{
	if (arrayin)
		{
			sys_free(arrayin);
			arrayin = NULL;
		}	
}


void		array_destroy(void* arrayin, int* arraylength)
{	
	if (arrayin)
		{
			sys_free(arrayin);
			arrayin = NULL;
		}
	
	if (arraylength)
		{
			*arraylength = 0;
		}	
}


void		array_destroy2(void** arrayin)
{
	if (*arrayin)
		{
			sys_free(*arrayin);
			*arrayin = NULL;
		}	
}


void		array_destroy2(void** arrayin, int* arraylength)
{
	if (*arrayin)
		{
			sys_free(*arrayin);
			*arrayin = NULL;
		}
	
	if (arraylength)
		{
			*arraylength = 0;
		}
}


//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// 2D array helpers


int		array2d_getx(int sizex, int sizey, int abspos)
{
	return abspos % sizex;
}


int		array2d_gety(int sizex, int sizey, int abspos)
{
	return integer(abspos / sizex);
}


int		array2d_getabs(int sizex, int sizey, int posx, int posy)
{
	return posx + posy * sizex;
}


//////////////////////////////////////////////////////////////////////////////////////
// 2D array operations


void*		array2d_rotate(void* arrayin, int elementsize, int* arraylength, int direction, int* sizex, int* sizey)
{
sys_marker("sro");

	//--------------------------------
	// convert to 1..7 range - for safety
	
	while (direction < 0)
		{
			direction = direction + 8;
		}
	
	while (direction > 7)
		{
			direction = direction - 8;
		}
	
	if (direction == 0)		return arrayin;
	
	//--------------------------------
	// store original values
	
	int	old_sizex 			= *sizex;
	int	old_sizey 			= *sizey;
	int	old_size 			= old_sizex * old_sizey;
	
	int	old_arraylength	= *arraylength;
		
	//--------------------------------
	// temp array parameters
	
	void* temp_array 			= NULL;
	int   temp_arraylength 	= 0;												// actual array length is 0, will be set to temp_size by array_new()
	
	int	temp_sizex 			= old_sizex;
	int	temp_sizey 			= old_sizey;
	
	//--------------------------------
	// rotation area
	
	// cardinal / diagonal
	if (direction % 2 > 0)
		{
			return arrayin;														// currently not supported			
		}
	
	// swap x-y if rotated by 90 or 270 degree
	if ((direction == 2) || (direction == 6))
		{
			temp_sizex 			= old_sizey;
			temp_sizey 			= old_sizex;
		}			
	
	int	temp_size 			= old_arraylength;	
	
	//--------------------------------
	// temp array		
	
	temp_array 					= array_new( elementsize, &temp_arraylength, temp_size );	
	
	//--------------------------------
	
	if (!temp_array)
		{
//			printf("temp_array == NULL !!!");
			return arrayin;
		}
	
	if (temp_arraylength <= 0)
		{
//			printf("temp_arraylength <= 0 !!!");
			return arrayin;
		}
		
	//--------------------------------
	// valid rotation
	
	int i;			// x
	int j;			// y
	int k = 0;		// abs
	
	// cardinal directions : k counts in new array, i-j loops through old array positions, thus old_sizex-y needed to be used!
	if (direction == 0)																						// 0°
		{
			for (j=0; j<old_sizey; ++j)		
				{
					for (i=0; i<old_sizex; ++i)	
						{
							int temp = array2d_getabs(old_sizex, old_sizey, i, j);							
							
//							temp_array[k] = arrayin[temp];												// wrong, void size cannot be determined
//							memcpy( &temp_array[k] , &arrayin[temp] , elementsize ); 			// copy new values - wrong
							
							char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
							char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
							memcpy( newaddress , oldaddress , elementsize ); 
							
							++k;
						}
				}
		}
	else if (direction == 2)																				// 90°
		{
			for (i=0; i<old_sizex; ++i)			
				{
					for (j=0; j<old_sizey; ++j)	
						{
							int temp = array2d_getabs(old_sizex, old_sizey, i, old_sizey-1-j);
							
							char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
							char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
							memcpy( newaddress , oldaddress , elementsize ); 
							
							++k;
						}
				}
		}
	else if (direction == 4)																				// 180°
		{
			for (j=0; j<old_sizey; ++j)	
				{
					for (i=0; i<old_sizex; ++i)
						{
							int temp = array2d_getabs(old_sizex, old_sizey, old_sizex-1-i, old_sizey-1-j);
							
							char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
							char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
							memcpy( newaddress , oldaddress , elementsize ); 
							
							++k;
						}
				}
		}
	else if (direction == 6)																				// 270°
		{
			for (i=0; i<old_sizex; ++i)
				{
					for (j=0; j<old_sizey; ++j)	
						{
							int temp = array2d_getabs(old_sizex, old_sizey, old_sizex-1-i, j);
							
							char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
							char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
							memcpy( newaddress , oldaddress , elementsize ); 
							
							++k;
						}
				}
		}

	//--------------------------------
	// set parameters if were modified
	
	if (arraylength)
		{
			*arraylength 	= temp_arraylength;
		}
	*sizex 			= temp_sizex;
	*sizey 			= temp_sizey;
	
	//--------------------------------
	
	sys_free(arrayin);
	arrayin = NULL;
	
sys_marker(NULL);
	
	return temp_array;
}


//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// 3D array helpers


int		array3d_getx(int sizex, int sizey, int sizez, int abspos)
{
	return (abspos % (sizex * sizey)) % sizex;
}


int		array3d_gety(int sizex, int sizey, int sizez, int abspos)
{
	return (integer((abspos % (sizex * sizey)) / sizex));
}


int		array3d_getabs(int sizex, int sizey, int posx, int posy, int posz)
{
	return (posx + posy * sizex) + (sizex * sizey * posz);
}


//////////////////////////////////////////////////////////////////////////////////////
// 3D array operations


void*		array3d_rotate(void* arrayin, int elementsize, int* arraylength, int direction, int* sizex, int* sizey)
{
sys_marker("sro");

	//--------------------------------
	// convert to 1..7 range - for safety
	
	while (direction < 0)
		{
			direction = direction + 8;
		}
	
	while (direction > 7)
		{
			direction = direction - 8;
		}
	
//	if (direction == 0)		return arrayin;
	
	//--------------------------------
	// store original values
	
	int	old_sizex 			= *sizex;
	int	old_sizey 			= *sizey;
	int	old_size 			= old_sizex * old_sizey;
	
	int	old_arraylength	= *arraylength;
	
	int	old_sizez			= old_arraylength / old_size;
	
	//--------------------------------
	// temp array parameters
	
	void* temp_array 			= NULL;
	int   temp_arraylength 	= 0;												// actual array length is 0, will be set to temp_size by array_new()
	
	int	temp_sizex 			= old_sizex;
	int	temp_sizey 			= old_sizey;
	
	//--------------------------------
	// rotation area
	
	// cardinal / diagonal
	if (direction % 2 > 0)
		{
			return arrayin;														// currently not supported			
		}
	
	// swap x-y if rotated by 90 or 270 degree
	if ((direction == 2) || (direction == 6))
		{
			temp_sizex 			= old_sizey;
			temp_sizey 			= old_sizex;
		}			
	
	int	temp_size 			= old_arraylength;	
	
	//--------------------------------
	// temp array		
	
	temp_array 					= array_new( elementsize, &temp_arraylength, temp_size );	
	
	// same as
//	temp_arraylength 			= temp_size;
//	void* temp_array 			= (void*)sys_malloc(elementsize * temp_size);
	
	//--------------------------------
	
	if (!temp_array)
		{
//			printf("temp_array == NULL !!!");
			return arrayin;
		}
	
	if (temp_arraylength <= 0)
		{
//			printf("temp_arraylength <= 0 !!!");
			return arrayin;
		}
		
	//--------------------------------
	// valid rotation
	
	int i;			// x
	int j;			// y
	int k = 0;		// abs
	int m;			// z
	
	// cardinal directions : k counts in new array, i-j loops through old array positions, thus old_sizex-y needed to be used!
	if (direction == 0)																								// 0°
		{
			for (m=0; m<old_sizez; ++m)			
				{
					for (j=0; j<old_sizey; ++j)		
						{
							for (i=0; i<old_sizex; ++i)	
								{
									int temp = array3d_getabs(old_sizex, old_sizey, i, j, m);
									
//									temp_array[k] = arrayin[temp];												// wrong, void size cannot be determined
//									memcpy( &temp_array[k] , &arrayin[temp] , elementsize ); 			// copy new values - wrong
									
									char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
									char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
									memcpy( newaddress , oldaddress , elementsize ); 
									
									++k;
								}
						}
				}
		}
	else if (direction == 2)																						// 90°
		{
			for (m=0; m<old_sizez; ++m)			
				{
					for (i=0; i<old_sizex; ++i)			
						{
							for (j=0; j<old_sizey; ++j)	
								{
									int temp = array3d_getabs(old_sizex, old_sizey, i, old_sizey-1-j, m);
									
									char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
									char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
									memcpy( newaddress , oldaddress , elementsize ); 
									
									++k;
								}
						}
				}
		}
	else if (direction == 4)																						// 180°
		{
			for (m=0; m<old_sizez; ++m)			
				{
					for (j=0; j<old_sizey; ++j)	
						{
							for (i=0; i<old_sizex; ++i)
								{
									int temp = array3d_getabs(old_sizex, old_sizey, old_sizex-1-i, old_sizey-1-j, m);
									
									char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
									char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
									memcpy( newaddress , oldaddress , elementsize ); 
									
									++k;
								}
						}
				}
		}
	else if (direction == 6)																						// 270°
		{
			for (m=0; m<old_sizez; ++m)			
				{
					for (i=0; i<old_sizex; ++i)
						{
							for (j=0; j<old_sizey; ++j)	
								{
									int temp = array3d_getabs(old_sizex, old_sizey, old_sizex-1-i, j, m);
									
									char* newaddress = (char*)temp_array + k * elementsize;				// char* casting is required!
									char* oldaddress = (char*)arrayin + temp * elementsize;				// char* casting is required!
									memcpy( newaddress , oldaddress , elementsize ); 
									
									++k;
								}
						}
				}
		}

	//--------------------------------
	// set parameters if were modified
	
	if (arraylength)
		{
			*arraylength 	= temp_arraylength;
		}
	*sizex 			= temp_sizex;
	*sizey 			= temp_sizey;
	
	//--------------------------------
	
	sys_free(arrayin);
	arrayin = NULL;
	
sys_marker(NULL);
	
	return temp_array;
}


//////////////////////////////////////////////////////////////////////////////////////


#endif



Free world editor for 3D Gamestudio: MapBuilder Editor
Re: dynamic array handling helpers [Re: sivan] #456672
12/03/15 09:24
12/03/15 09:24
Joined: Mar 2011
Posts: 3,150
Budapest
sivan Offline OP
Expert
sivan  Offline OP
Expert

Joined: Mar 2011
Posts: 3,150
Budapest
Moreover, if you need a much more professional approach you can take Sid's script from this thread

Not tested, I remember there is one or two tiny mistakes in it, but I was lazy to test it:
Code:
typedef struct
{
	void *_buffer; // Actual data
	size_t _size; // Number of elements
	size_t _capacity; // Allocated number of elements
	size_t _elementSize; // Element size
} array_t;

array_t *array_create(size_t elementSize)
{
	array_t *array = malloc(sizeof(array_t));
	array->_elementSize = elementSize;
	array->_size = 0;
	array->_capacity = 5; // start out with 5 elements. Tweak if desired. This just makes the life easier since there is always a buffer and we don't have to care about cases where it's NULL
	array->_buffer = malloc(array->_capacity * array->_elementSize);

	return array;
}
void array_delete(array_t *array)
{
	free(array->_buffer);
	free(array);
}

void __array_assert_size(array_t *array, size_t required) // Makes sure that the array fits
{
	size_t toCopy = array->_size;
	if(toCopy > size)
		toCopy = size;

	if(required > array->_capacity)
	{
		size_t nextCapacity = array->_capacity * 1.5; // Gives a nice grow curve. Alternatively doubling also works, gets messy with large arrays though
		if(nextCapacity < required)
			nextCapacity = required;

		void *buffer = malloc(nextCapacity * array->_elementSize); // TODO: Handle errors
		memcpy(buffer, array->_buffer, toCopy * array->_elementSize);
		free(array->_buffer);

		array->_buffer = buffer;
		array->_capacity = nextCapacity;
	}
	else
	{
		size_t nextCapacity = array->_capacity >> 1;
		if(nextCapacity >= required && nextCapacity > 5) // Keep at least space for 5 elements
		{
			void *buffer = malloc(nextCapacity * array->_elementSize); // TODO: Handle errors
			memcpy(buffer, array->_buffer, toCopy * array->_elementSize);
			free(array->_buffer);

			array->_buffer = buffer;
			array->_capacity = nextCapacity;
		}
	}
}


void array_copyin_data(array_t *array, void *data, size_t elements)
{
	__array_assert_size(array, array->_size + elements);
	memcpy(((char *)array->_buffer) + array->_size * array->_elementSize, data, elements * array->_elementSize);
	array->_size += elements;
}
void array_copyout_data(array_t *array, void *data, size_t start, size_t elements)
{
	if(start + elements >= array->_size)
	{
		printf("Trying to access elements [%d, %d) in array with only %d elements", start, start + elements, array->_size);
		return;
	}

	memcpy((data, (char *)array->_buffer) + start * array->_elementSize, elements * array->_elementSize);
}

// Alternatively, you can also work with single elements at a time... Something like this:
void array_add_object(array_t *array, void *object)
{
	__array_assert_size(array, array->_size + 1);
	memcpy(((char *)array->_buffer) + array->_size * array->_elementSize, data, array->_elementSize);
	array->_size ++;
}



Free world editor for 3D Gamestudio: MapBuilder Editor

Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1