⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 array.c

📁 3D游戏场景编辑器
💻 C
字号:
/****************************************************************************************/
/*  array.c                                                                             */
/*                                                                                      */
/*  Author:       Jim Mischel                                                           */
/*  Description:  Dynamic Array                                                         */
/*                                                                                      */
/*  The contents of this file are subject to the Genesis3D Public License               */
/*  Version 1.01 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.genesis3d.com                                                            */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  The Original Code is Genesis3D, released March 25, 1999.                            */
/*Genesis3D Version 1.1 released November 15, 1999                            */
/*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
/*                                                                                      */
/*  Prepared for GenEdit-Classic ver. 0.5, Dec. 15, 2000								*/
/****************************************************************************************/
#include "array.h"
#include <assert.h>
#include <malloc.h>

geBoolean Array_Init (Array *pArray, int InitialSize, int ItemSize)
{
	assert (pArray != NULL);
	assert (InitialSize >= 0);
	assert (ItemSize > 0);

	pArray->ItemSize = ItemSize;
	pArray->ItemsAllocated = 0;

	// if user requested initial size, 
	// then allocate memory for the items.
	if (InitialSize == 0)
	{
		pArray->Items = NULL;
	}
	else
	{
		pArray->Items = malloc (InitialSize * ItemSize);
		if (pArray->Items == NULL)
		{
			return GE_FALSE;
		}
		pArray->ItemsAllocated = InitialSize;
	}
	return GE_TRUE;
}

void Array_Uninit (Array *pArray)
{
	assert (pArray != NULL);

	if (pArray->Items != NULL)
	{
		free (pArray->Items);
		pArray->Items = NULL;
	}
	pArray->ItemsAllocated = 0;
}


// Create an array object with given initial size (possibly 0).
Array *Array_Create (int InitialSize, int ItemSize)
{
	Array *pArray;

	assert (InitialSize >= 0);
	assert (ItemSize > 0);

	pArray = malloc (sizeof (Array));
	if (pArray != NULL)
	{
		if (Array_Init (pArray, InitialSize, ItemSize) == GE_FALSE)
		{
			Array_Destroy (&pArray);
		}
	}

	return pArray;
}

// Destroy an array object
void Array_Destroy (Array **ppArray)
{
	assert (ppArray != NULL);
	assert (*ppArray != NULL);

	Array_Uninit (*ppArray);
	free (*ppArray);
	*ppArray = NULL;
}



// Resizes the array to contain NewSize elements.
// Returns new size.
int Array_Resize (Array *pArray, int NewSize)
{
	void *NewItems;

	assert (pArray != NULL);
	assert (NewSize >= 0);

	NewItems = realloc (pArray->Items, (NewSize * pArray->ItemSize));

	// realloc returns NULL in two cases:
	//   1) It was unable to allocate memory
	//   2) The size parameter was 0.
	if ((NewItems != NULL) || (NewSize == 0))
	{
		pArray->Items = NewItems;
		pArray->ItemsAllocated = NewSize;
	}
	return pArray->ItemsAllocated;
}


//
// Following code active only in debug mode.
// Non-debug mode has all this stuff inline in the header.
#ifdef _DEBUG
	// Returns the array's allocated size.
	int Array_GetSize (const Array *pArray)
	{
		assert (pArray != NULL);

		return pArray->ItemsAllocated;
	}

	int Array_GetItemSize (const Array *pArray)
	{
		assert (pArray != NULL);

		return pArray->ItemSize;
	}


	// Returns a pointer to the item's data.
	void *Array_ItemPtr (Array *pArray, int Index)
	{
		assert (pArray != NULL);
		assert (Index >= 0);
		assert (Index < pArray->ItemsAllocated);

		return (void *)(((long)(pArray->Items)) + (Index * pArray->ItemSize));
	}

	// Copies DataSize bytes from pData to array[Index]
	void Array_PutAt (Array *pArray, int Index, void *pData, int DataSize)
	{
		void *pDest;

		assert (pArray != NULL);
		assert (pData != NULL);
		assert (Index < pArray->ItemsAllocated);
		assert (DataSize <= pArray->ItemSize);
		assert (DataSize >= 0);

		pDest = Array_ItemPtr (pArray, Index);
		memcpy (pDest, pData, DataSize);
	}

	// Inserts an item at the given position, moving all other items
	// down by 1.  This causes the last item in the array to be lost.
	void Array_InsertAt (Array *pArray, int Index, void *pData, int DataSize)
	{
		int MoveSize;
		void *pSrc;
		void *pDest;

		assert (pArray != NULL);
		assert (pData != NULL);
		assert (Index < pArray->ItemsAllocated);
		assert (DataSize <= pArray->ItemSize);
		assert (DataSize >= 0);

		// move everything down by 1
		MoveSize = (pArray->ItemsAllocated - Index - 1) * pArray->ItemSize;
		pSrc = Array_ItemPtr (pArray, Index);
		pDest = Array_ItemPtr (pArray, Index+1);
		memmove (pDest, pSrc, MoveSize);

		// and copy the new item into the spot
		memcpy (pSrc, pData, DataSize);
	}

	// Deletes the item at and moves all following items in the array up
	// to fill in the empty spot.
	void Array_DeleteAt (Array *pArray, int Index)
	{
		int MoveSize;
		void *pSrc;
		void *pDest;

		assert (pArray != NULL);
		assert (Index >= 0);
		assert (Index < pArray->ItemsAllocated);

		MoveSize = (pArray->ItemsAllocated - Index - 1) * pArray->ItemSize;
		pSrc = Array_ItemPtr (pArray, Index+1);
		pDest = Array_ItemPtr (pArray, Index);

		memcpy (pDest, pSrc, MoveSize);
	}
#endif

#ifdef ARRAY_TEST_CODE

#include <stdio.h>
#include <stdlib.h>		// atoi
#include <string.h>

/*
  The test code reads array commands from an input file and applies those
  commands to arrays.  The commands are in a sort of mini scripting language.

  The commands take the form <command> <argument>, where <command> is
  a 1- or 2-letter command (see below), and the argument is a string.
  Commands are stored in the file one per line, with <command> being
  the first two characters, followed by a space, and then the argument
  which takes up the rest of the line.  Blank lines and lines that start 
  with a semicolon are considered comments and are ignored by the
  interpreter.

  For example:

  ;create a new array
  n
  ;append an item
  a Hello, world
  ;print the array from front to back
  pf
  ;destroy the array
  d

  The full list of commands is:

  c		Create a new array	<Initial size> <Item size>
  d		Destroy an array	no argument
  i		Insert an item		<item number> <data>
  p		Put an item			<item number> <data>
  r		Remove an item		<item number>
  g		Resize (grow)array	<new size>
  pn	Print #items		no argument
  pi	Print item			<item number>
  ps	Print item size		no argument
  pr	Print string		<string to print>
*/

static geBoolean ParseCommand
	(
	  char *InputLine,
	  int LineNo,
	  Array **ppArray
	)
{
	short intcmd;
	char *sarg;
	geBoolean rslt;
	char *c;
	int Index;
	int nItems, ItemSize;

	if ((InputLine[0] == '\0') || (InputLine[0] == ';'))
	{
		// it's a comment line
		return GE_TRUE;
	}
	if ((InputLine[1] == ' ') || (InputLine[1] == '\0') || (InputLine[1] == '\n'))
	{
		intcmd = InputLine[0];
	}
	else if ((InputLine[2] == ' ') || (InputLine[2] == '\0') || (InputLine[2] == '\n'))
	{
		short temp;

		intcmd = *((short *)&InputLine[0]);
		// swap the bytes
		temp = (short)(intcmd & 0xff);
		intcmd = (short)((intcmd >> 8) | (temp << 8));
	}
	else
	{
		printf ("Parse error on line %d\n", LineNo);
		return GE_FALSE;
	}

	rslt = GE_TRUE;
	switch (intcmd)
	{
		case 'c' :
		{
			// need to get size and item size from sarg
			sarg = &InputLine[2];
			c = strchr (sarg, ' ');
			if (c == NULL)
			{
				puts ("Expected <nItems> <ItemSize>");
				rslt = GE_FALSE;
				break;
			}
			*c = '\0';
			++c;
			nItems = atoi (sarg);
			ItemSize = atoi (c);
						
			if (*ppArray != NULL)
			{
				puts ("Warning:  Deleting old array.");
				Array_Destroy (ppArray);
			}
			printf ("Creating array with %d items of size %d\n", nItems, ItemSize);
			*ppArray = Array_Create (nItems, ItemSize);
			if (*ppArray == NULL)
			{
				puts ("Error creating array");
				rslt = GE_FALSE;
			}
			else
			{
				puts ("Created array");
			}
			break;
		}

		case 'd' :
			if (*ppArray == NULL)
			{
				puts ("Warning:  Trying to destroy NULL array.");
			}
			else
			{
				puts ("Destroy array");
				Array_Destroy (ppArray);
			}
			break;

		case 'i' :
			sarg = &InputLine[2];
			c = strchr (sarg, ' ');
			if (c == NULL)
			{
				puts ("Expected <ItemNo> <String>");
				rslt = GE_FALSE;
				break;
			}
			*c = '\0';
			++c;
			Index = atoi (sarg);
			printf ("Insert (%s) at item %d\n", c, Index);
			Array_InsertAt (*ppArray, Index, c, strlen (c)+1);
			break;

		case 'p' :
			sarg = &InputLine[2];
			c = strchr (sarg, ' ');
			if (c == NULL)
			{
				puts ("Expected <ItemNo> <String>");
				rslt = GE_FALSE;
				break;
			}
			*c = '\0';
			++c;
			Index = atoi (sarg);
			printf ("Put (%s) at item %d\n", c, Index);
			Array_PutAt (*ppArray, Index, c, strlen (c)+1);
			break;

		case 'r' :
			sarg = &InputLine[2];
			Index = atoi (sarg);
			c = Array_ItemPtr (*ppArray, Index);
			printf ("Remove item %d (%s)\n", Index, c);
			Array_DeleteAt (*ppArray, Index);
			break;

		case 'g' :
			sarg = &InputLine[2];
			nItems = atoi (sarg);
			printf ("Resize to %d items\n", nItems);
			Array_Resize (*ppArray, nItems);
			break;

		case 'pn' :
			nItems = Array_GetSize (*ppArray);
			printf ("Number of items = %d\n", nItems);
			break;

		case 'ps' :
			ItemSize = Array_GetSize (*ppArray);
			printf ("Item size = %d\n", ItemSize);
			break;

		case 'pr' :
			puts (&InputLine[3]);
			break;
		
		case 'pi' :
			sarg = &InputLine[2];
			Index = atoi (sarg);
			c = Array_ItemPtr (*ppArray, Index);
			printf ("Item #%d = (%s)\n", Index, c);
			break;

		default :
			printf ("Unknown command on line %d\n", LineNo);
			rslt = GE_FALSE;
			break;
	}
	if (!rslt)
	{
		printf ("Error on line %d\n", LineNo);
		printf ("Line = (%s)\n", InputLine);
	}
	return rslt;
}

int main 
	(
	  int argc,
	  char *argv[]
	)
{
	Array *pArray;
	char *InputFilename;
	FILE *infile;
	int LineNo;
	geBoolean rslt;

	puts ("Array test version 1.0");
	puts ("---------------------");
	if (argc != 2)
	{
		puts ("Usage is Array <scriptname>");
		puts ("See source for scripting information.");
		return 0;
	}


	InputFilename = argv[1];
	infile = fopen (InputFilename, "rt");
	if (infile == NULL)
	{
		printf ("Can't open input file: '%s'\n", InputFilename);
		return 0;
	}

	LineNo = 0;
	pArray = NULL;
	rslt = GE_TRUE;
	while (rslt && !feof (infile))
	{
		char InputLine[256];
		char *c;

		if (fgets (InputLine, sizeof (InputLine), infile) == NULL)
		{
			// Why is this test necessary?
			// Why doesn't feof return TRUE above?
			if (!feof (infile))
			{
				puts ("Input error");
			}
			break;
		}
		// strip newline
		c = strchr (InputLine, '\n');
		if (c != NULL)
		{
			*c = '\0';
		}
		++LineNo;
		rslt = ParseCommand (InputLine, LineNo, &pArray);
	}

	if (pArray != NULL)
	{
		Array_Destroy (&pArray);
	}

	fclose (infile);
	return 0;
}


#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -