Merge pull request #94 from Arkshine/adt-stack
Introduce API to create Stack structures
This commit is contained in:
		| @@ -92,7 +92,8 @@ binary.sources = [ | |||||||
|   'datastructs.cpp', |   'datastructs.cpp', | ||||||
|   'trie_natives.cpp', |   'trie_natives.cpp', | ||||||
|   'CDataPack.cpp', |   'CDataPack.cpp', | ||||||
|   'datapacks.cpp' |   'datapacks.cpp', | ||||||
|  |   'stackstructs.cpp', | ||||||
| ] | ] | ||||||
|  |  | ||||||
| if builder.target_platform == 'windows': | if builder.target_platform == 'windows': | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules | |||||||
| 	  CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \ | 	  CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \ | ||||||
| 	  optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \ | 	  optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \ | ||||||
| 	  nongpl_matches.cpp CFlagManager.cpp datastructs.cpp \ | 	  nongpl_matches.cpp CFlagManager.cpp datastructs.cpp \ | ||||||
| 	  trie_natives.cpp CDataPack.cpp datapacks.cpp | 	  trie_natives.cpp CDataPack.cpp datapacks.cpp stackstructs.cpp | ||||||
|  |  | ||||||
| ############################################## | ############################################## | ||||||
| ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### | ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### | ||||||
|   | |||||||
| @@ -85,6 +85,7 @@ extern AMX_NATIVE_INFO msg_Natives[]; | |||||||
| extern AMX_NATIVE_INFO vector_Natives[]; | extern AMX_NATIVE_INFO vector_Natives[]; | ||||||
| extern AMX_NATIVE_INFO g_SortNatives[]; | extern AMX_NATIVE_INFO g_SortNatives[]; | ||||||
| extern AMX_NATIVE_INFO g_DataStructNatives[]; | extern AMX_NATIVE_INFO g_DataStructNatives[]; | ||||||
|  | extern AMX_NATIVE_INFO g_StackNatives[]; | ||||||
|  |  | ||||||
| #if defined(_WIN32) | #if defined(_WIN32) | ||||||
| #define DLLOAD(path) (DLHANDLE)LoadLibrary(path) | #define DLLOAD(path) (DLHANDLE)LoadLibrary(path) | ||||||
|   | |||||||
| @@ -573,6 +573,7 @@ int set_amxnatives(AMX* amx, char error[128]) | |||||||
| 	amx_Register(amx, g_DataStructNatives, -1); | 	amx_Register(amx, g_DataStructNatives, -1); | ||||||
| 	amx_Register(amx, trie_Natives, -1); | 	amx_Register(amx, trie_Natives, -1); | ||||||
| 	amx_Register(amx, g_DatapackNatives, -1); | 	amx_Register(amx, g_DatapackNatives, -1); | ||||||
|  | 	amx_Register(amx, g_StackNatives, -1); | ||||||
| 	 | 	 | ||||||
| 	//we're not actually gonna check these here anymore | 	//we're not actually gonna check these here anymore | ||||||
| 	amx->flags |= AMX_FLAG_PRENIT; | 	amx->flags |= AMX_FLAG_PRENIT; | ||||||
|   | |||||||
| @@ -329,6 +329,7 @@ | |||||||
|     <ClCompile Include="..\power.cpp" /> |     <ClCompile Include="..\power.cpp" /> | ||||||
|     <ClCompile Include="..\sorting.cpp" /> |     <ClCompile Include="..\sorting.cpp" /> | ||||||
|     <ClCompile Include="..\srvcmd.cpp" /> |     <ClCompile Include="..\srvcmd.cpp" /> | ||||||
|  |     <ClCompile Include="..\stackstructs.cpp" /> | ||||||
|     <ClCompile Include="..\string.cpp"> |     <ClCompile Include="..\string.cpp"> | ||||||
|       <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='JITReleaseBinLog|Win32'">All</AssemblerOutput> |       <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='JITReleaseBinLog|Win32'">All</AssemblerOutput> | ||||||
|       <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='JITRelease|Win32'">All</AssemblerOutput> |       <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='JITRelease|Win32'">All</AssemblerOutput> | ||||||
| @@ -400,6 +401,7 @@ | |||||||
|     <ResourceCompile Include="..\version.rc" /> |     <ResourceCompile Include="..\version.rc" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <None Include="..\..\plugins\include\cellstack.inc" /> | ||||||
|     <None Include="..\..\plugins\include\datapack.inc" /> |     <None Include="..\..\plugins\include\datapack.inc" /> | ||||||
|     <None Include="..\amxdefn.asm" /> |     <None Include="..\amxdefn.asm" /> | ||||||
|     <None Include="..\amxexecn.asm" /> |     <None Include="..\amxexecn.asm" /> | ||||||
|   | |||||||
| @@ -174,6 +174,9 @@ | |||||||
|     <ClCompile Include="..\datapacks.cpp"> |     <ClCompile Include="..\datapacks.cpp"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\stackstructs.cpp"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\amx.h"> |     <ClInclude Include="..\amx.h"> | ||||||
| @@ -405,6 +408,9 @@ | |||||||
|     <None Include="..\..\plugins\include\datapack.inc"> |     <None Include="..\..\plugins\include\datapack.inc"> | ||||||
|       <Filter>Pawn Includes</Filter> |       <Filter>Pawn Includes</Filter> | ||||||
|     </None> |     </None> | ||||||
|  |     <None Include="..\..\plugins\include\cellstack.inc"> | ||||||
|  |       <Filter>Pawn Includes</Filter> | ||||||
|  |     </None> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Object Include="..\Jit\helpers-x86.obj"> |     <Object Include="..\Jit\helpers-x86.obj"> | ||||||
|   | |||||||
							
								
								
									
										293
									
								
								amxmodx/stackstructs.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								amxmodx/stackstructs.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | |||||||
|  | /* AMX Mod X | ||||||
|  |  * | ||||||
|  |  * by the AMX Mod X Development Team | ||||||
|  |  *  originally developed by OLO | ||||||
|  |  * | ||||||
|  |  *  This program is free software; you can redistribute it and/or modify it | ||||||
|  |  *  under the terms of the GNU General Public License as published by the | ||||||
|  |  *  Free Software Foundation; either version 2 of the License, or (at | ||||||
|  |  *  your option) any later version. | ||||||
|  |  * | ||||||
|  |  *  This program is distributed in the hope that it will be useful, but | ||||||
|  |  *  WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||||
|  |  *  General Public License for more details. | ||||||
|  |  * | ||||||
|  |  *  You should have received a copy of the GNU General Public License | ||||||
|  |  *  along with this program; if not, write to the Free Software Foundation, | ||||||
|  |  *   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||||
|  |  * | ||||||
|  |  *  In addition, as a special exception, the author gives permission to | ||||||
|  |  *  link the code of this program with the Half-Life Game Engine ("HL | ||||||
|  |  *  Engine") and Modified Game Libraries ("MODs") developed by Valve, | ||||||
|  |  *  L.L.C ("Valve"). You must obey the GNU General Public License in all | ||||||
|  |  *  respects for all of the code used other than the HL Engine and MODs | ||||||
|  |  *  from Valve. If you modify this file, you may extend this exception | ||||||
|  |  *  to your version of the file, but you are not obligated to do so. If | ||||||
|  |  *  you do not wish to do so, delete this exception statement from your | ||||||
|  |  *  version. | ||||||
|  |  */ | ||||||
|  | #include "amxmodx.h" | ||||||
|  | #include "datastructs.h" | ||||||
|  |  | ||||||
|  | // native Stack:CreateStack(blocksize = 1); | ||||||
|  | static cell AMX_NATIVE_CALL CreateStack(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	int cellsize = params[1]; | ||||||
|  |  | ||||||
|  | 	if (cellsize <= 0) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Invalid block size (must be > 0)", cellsize); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Scan through the vector list to see if any are NULL. | ||||||
|  | 	// NULL means the vector was previously destroyed. | ||||||
|  | 	for (unsigned int i = 0; i < VectorHolder.length(); ++i) | ||||||
|  | 	{ | ||||||
|  | 		if (VectorHolder[i] == NULL) | ||||||
|  | 		{ | ||||||
|  | 			VectorHolder[i] = new CellArray(cellsize); | ||||||
|  | 			return i + 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// None are NULL, create a new vector | ||||||
|  | 	CellArray* NewVector = new CellArray(cellsize); | ||||||
|  |  | ||||||
|  | 	VectorHolder.append(NewVector); | ||||||
|  |  | ||||||
|  | 	return VectorHolder.length(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native PushStackCell(Stack:handle, any:value); | ||||||
|  | static cell AMX_NATIVE_CALL PushStackCell(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cell *blk = vec->push(); | ||||||
|  |  | ||||||
|  | 	if (!blk) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Failed to grow stack"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	*blk = params[2]; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native PushStackString(Stack:handle, const value[]); | ||||||
|  | static cell AMX_NATIVE_CALL PushStackString(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cell *blk = vec->push(); | ||||||
|  |  | ||||||
|  | 	if (!blk) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Failed to grow stack"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	int len; | ||||||
|  | 	const char *value = get_amxstring(amx, params[2], 0, len); | ||||||
|  |  | ||||||
|  | 	strncopy(blk, value, vec->blocksize()); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native PushStackArray(Stack:handle, const any:values[], size= -1); | ||||||
|  | static cell AMX_NATIVE_CALL PushStackArray(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cell *blk = vec->push(); | ||||||
|  |  | ||||||
|  | 	if (!blk) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Failed to grow stack"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cell *addr = get_amxaddr(amx, params[2]); | ||||||
|  | 	size_t indexes = vec->blocksize(); | ||||||
|  |  | ||||||
|  | 	if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) | ||||||
|  | 	{ | ||||||
|  | 		indexes = params[3]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	memcpy(blk, addr, indexes * sizeof(cell)); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native bool:PopStackCell(Stack:handle, &any:value, block = 0, bool:asChar = false); | ||||||
|  | static cell AMX_NATIVE_CALL PopStackCell(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (vec->size() == 0) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cell *buffer = get_amxaddr(amx, params[2]); | ||||||
|  | 	size_t index = params[3]; | ||||||
|  |  | ||||||
|  | 	cell *blk = vec->at(vec->size() - 1); | ||||||
|  | 	size_t idx = (size_t)params[3]; | ||||||
|  |  | ||||||
|  | 	if (params[4] == 0) | ||||||
|  | 	{ | ||||||
|  | 		if (idx >= vec->blocksize()) | ||||||
|  | 		{ | ||||||
|  | 			LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize()); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		*buffer = blk[idx]; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		if (idx >= vec->blocksize() * 4) | ||||||
|  | 		{ | ||||||
|  | 			LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		*buffer = (cell)*((char *)blk + idx); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	vec->remove(vec->size() - 1); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native bool:PopStackString(Stack:handle, buffer[], maxlength, &written = 0); | ||||||
|  | static cell AMX_NATIVE_CALL PopStackString(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (vec->size() == 0) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	size_t idx = vec->size() - 1; | ||||||
|  | 	cell *blk = vec->at(idx); | ||||||
|  |  | ||||||
|  | 	int numWritten = set_amxstring_utf8(amx, params[2], blk, amxstring_len(blk), params[3] + 1); | ||||||
|  | 	*get_amxaddr(amx, params[4]) = numWritten; | ||||||
|  |  | ||||||
|  | 	vec->remove(idx); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native bool:PopStackArray(Stack:handle, any:buffer[], size=-1); | ||||||
|  | static cell AMX_NATIVE_CALL PopStackArray(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (vec->size() == 0) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	size_t idx = vec->size() - 1; | ||||||
|  | 	cell *blk = vec->at(idx); | ||||||
|  | 	size_t indexes = vec->blocksize(); | ||||||
|  |  | ||||||
|  | 	if (params[3] != -1 && (size_t)params[3] <= vec->blocksize()) | ||||||
|  | 	{ | ||||||
|  | 		indexes = params[3]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cell *addr = get_amxaddr(amx, params[2]); | ||||||
|  | 	memcpy(addr, blk, indexes * sizeof(cell)); | ||||||
|  |  | ||||||
|  | 	vec->remove(idx); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native bool:IsStackEmpty(Stack:handle); | ||||||
|  | static cell AMX_NATIVE_CALL IsStackEmpty(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	CellArray* vec = HandleToVector(amx, params[1]); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return vec->size() == 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // native DestroyStack(&Stack:which); | ||||||
|  | static cell AMX_NATIVE_CALL DestroyStack(AMX* amx, cell* params) | ||||||
|  | { | ||||||
|  | 	cell *handle = get_amxaddr(amx, params[1]); | ||||||
|  | 	CellArray *vec = HandleToVector(amx, *handle); | ||||||
|  |  | ||||||
|  | 	if (vec == NULL) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	delete vec; | ||||||
|  |  | ||||||
|  | 	VectorHolder[*handle - 1] = NULL; | ||||||
|  |  | ||||||
|  | 	*handle = 0; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AMX_NATIVE_INFO g_StackNatives[] = | ||||||
|  | { | ||||||
|  | 	{ "CreateStack",     CreateStack     }, | ||||||
|  | 	{ "IsStackEmpty",    IsStackEmpty    }, | ||||||
|  | 	{ "PopStackArray",   PopStackArray   }, | ||||||
|  | 	{ "PopStackCell",    PopStackCell    }, | ||||||
|  | 	{ "PopStackString",  PopStackString  }, | ||||||
|  | 	{ "PushStackArray",  PushStackArray  }, | ||||||
|  | 	{ "PushStackCell",   PushStackCell   }, | ||||||
|  | 	{ "PushStackString", PushStackString }, | ||||||
|  | 	{ "DestroyStack",    DestroyStack    }, | ||||||
|  | 	{ NULL,              NULL            }, | ||||||
|  | }; | ||||||
| @@ -22,6 +22,7 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
| #include <sorting> | #include <sorting> | ||||||
| #include <cellarray> | #include <cellarray> | ||||||
|  | #include <cellstack> | ||||||
| #include <celltrie> | #include <celltrie> | ||||||
| #include <datapack> | #include <datapack> | ||||||
| #include <newmenus> | #include <newmenus> | ||||||
|   | |||||||
							
								
								
									
										146
									
								
								plugins/include/cellstack.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								plugins/include/cellstack.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | |||||||
|  |  | ||||||
|  | #if defined _cellstack_included | ||||||
|  | 	#endinput | ||||||
|  | #endif | ||||||
|  | #define _cellstack_included | ||||||
|  |  | ||||||
|  | enum Stack | ||||||
|  | { | ||||||
|  | 	Invalid_Stack = 0 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Creates a stack structure.  A stack is a LIFO (last in, first out) | ||||||
|  |  * vector (array) of items.  It has O(1) insertion and O(1) removal. | ||||||
|  |  * | ||||||
|  |  * Stacks have two operations: Push (adding an item) and Pop (removes | ||||||
|  |  * items in reverse-push order). | ||||||
|  |  * | ||||||
|  |  * The contents of the stack are uniform; i.e. storing a string and then | ||||||
|  |  * retrieving it as an integer is NOT the same as StringToInt()! | ||||||
|  |  * | ||||||
|  |  * The "blocksize" determines how many cells each slot has; it cannot | ||||||
|  |  * be changed after creation. | ||||||
|  |  * | ||||||
|  |  * @param blocksize     The number of cells each entry in the stack can | ||||||
|  |  *                      hold.  For example, 32 cells is equivalent to: | ||||||
|  |  *                      new Array[X][32] | ||||||
|  |  * | ||||||
|  |  * @return              New stack Handle. | ||||||
|  |  * @error               Invalid block size. | ||||||
|  |  */ | ||||||
|  | native Stack:CreateStack(blocksize = 1); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pushes a value onto the end of the stack, adding a new index. | ||||||
|  |  * | ||||||
|  |  * This may safely be used even if the stack has a blocksize | ||||||
|  |  * greater than 1. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * @param value         Value to push. | ||||||
|  |  * | ||||||
|  |  * @noreturn | ||||||
|  |  * @error               Invalid handle or out of memory. | ||||||
|  |  */ | ||||||
|  | native PushStackCell(Stack:handle, any:value); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pushes a string onto the end of a stack, truncating it if it is | ||||||
|  |  * too big. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * @param value         String to push. | ||||||
|  |  * | ||||||
|  |  * @noreturn | ||||||
|  |  * @error               Invalid handle or out of memory. | ||||||
|  |  */ | ||||||
|  | native PushStackString(Stack:handle, const value[]); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pushes an array of cells onto the end of a stack.  The cells | ||||||
|  |  * are pushed as a block (i.e. the entire array takes up one stack slot), | ||||||
|  |  * rather than pushing each cell individually. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * @param values        Block of values to copy. | ||||||
|  |  * @param size          If not set, the number of elements copied from the array | ||||||
|  |  *                      will be equal to the blocksize.  If set higher than the | ||||||
|  |  *                      blocksize, the operation will be truncated. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error               Invalid handle or out of memory. | ||||||
|  |  */ | ||||||
|  | native PushStackArray(Stack:handle, const any:values[], size= -1); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pops a cell value from a stack. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * @param value         Variable to store the value. | ||||||
|  |  * @param block         Optionally specify which block to read from | ||||||
|  |  *                      (useful if the blocksize > 0). | ||||||
|  |  * @param asChar        Optionally read as a byte instead of a cell. | ||||||
|  |  * | ||||||
|  |  * @return              True on success, false if the stack is empty. | ||||||
|  |  * @error               Invalid handle, Invalid block or Invalid byte. | ||||||
|  |  */ | ||||||
|  | native bool:PopStackCell(Stack:handle, &any:value, block = 0, bool:asChar = false); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pops a string value from a stack. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * @param buffer        Buffer to store string. | ||||||
|  |  * @param maxlength     Maximum size of the buffer. | ||||||
|  |  * @param written       Number of characters copied. | ||||||
|  |  * | ||||||
|  |  * @return              True on success, false if the stack is empty. | ||||||
|  |  * @error               Invalid handle. | ||||||
|  |  */ | ||||||
|  | native bool:PopStackString(Stack:handle, buffer[], maxlength, &written = 0); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pops an array of cells from a stack. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * @param buffer        Buffer to store the array in. | ||||||
|  |  * @param size          If not set, assumes the buffer size is equal to the | ||||||
|  |  *                      blocksize.  Otherwise, the size passed is used. | ||||||
|  |  * | ||||||
|  |  * @return              True on success, false if the stack is empty. | ||||||
|  |  * @error               Invalid handle. | ||||||
|  |  */ | ||||||
|  | native bool:PopStackArray(Stack:handle, any:buffer[], size = -1); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Checks if a stack is empty. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * | ||||||
|  |  * @return              True if empty, false if not empty. | ||||||
|  |  * @error               Invalid handle. | ||||||
|  |  */ | ||||||
|  | native bool:IsStackEmpty(Stack:handle); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Pops a value off a stack, ignoring it completely. | ||||||
|  |  * | ||||||
|  |  * @param handle        Stack handle. | ||||||
|  |  * | ||||||
|  |  * @return              True if something was popped, false otherwise. | ||||||
|  |  * @error               Invalid handle. | ||||||
|  |  */ | ||||||
|  | stock PopStack(Stack:handle) | ||||||
|  | { | ||||||
|  | 	new value; | ||||||
|  | 	return PopStackCell(handle, value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Destroys the stack, and resets the handle to 0 to prevent accidental usage after it is destroyed. | ||||||
|  |  * | ||||||
|  |  * @param which         The stack to destroy. | ||||||
|  |  * | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native DestroyStack(&Stack:handle); | ||||||
							
								
								
									
										73
									
								
								plugins/testsuite/stacktest.sma
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								plugins/testsuite/stacktest.sma
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | |||||||
|  | #include <amxmodx> | ||||||
|  |  | ||||||
|  | new FailCount; | ||||||
|  | new PassCount; | ||||||
|  |  | ||||||
|  | public plugin_init() | ||||||
|  | { | ||||||
|  | 	register_plugin("Stack Tests", AMXX_VERSION_STR, "AMXX Dev Team"); | ||||||
|  | 	register_srvcmd("test_stack", "ServerCommand_TestStack"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | assertEqual(const testname[], bool:pass) | ||||||
|  | { | ||||||
|  | 	if (!pass) | ||||||
|  | 	{ | ||||||
|  | 		server_print("[FAIL] %s", testname); | ||||||
|  | 		FailCount++; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		server_print("[PASS] %s", testname); | ||||||
|  | 		PassCount++; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | done() | ||||||
|  | { | ||||||
|  | 	server_print("Finished. %d tests, %d failed", FailCount + PassCount, FailCount); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public ServerCommand_TestStack() | ||||||
|  | { | ||||||
|  | 	new Stack:stack; | ||||||
|  | 	new test[20]; | ||||||
|  | 	new buffer[42]; | ||||||
|  |  | ||||||
|  | 	test[0] = 5; | ||||||
|  | 	test[1] = 7; | ||||||
|  |  | ||||||
|  | 	stack = CreateStack(30); | ||||||
|  | 	{ | ||||||
|  | 		PushStackCell(stack, 50); | ||||||
|  | 		PushStackArray(stack, test, 2); | ||||||
|  | 		PushStackArray(stack, test, 2); | ||||||
|  | 		PushStackString(stack, "space craaab"); | ||||||
|  | 		PushStackCell(stack, 12); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	assertEqual("Size test #1", IsStackEmpty(stack) == false); | ||||||
|  |  | ||||||
|  | 	PopStack(stack); | ||||||
|  | 	PopStackString(stack, buffer, charsmax(buffer)); | ||||||
|  | 	assertEqual("String test", bool:equal(buffer, "space craaab")); | ||||||
|  |  | ||||||
|  | 	test[0] = 0; | ||||||
|  | 	test[1] = 0; | ||||||
|  | 	assertEqual("Array test #1", test[0] == 0 && test[1] == 0); | ||||||
|  |  | ||||||
|  | 	PopStackArray(stack, test, 2); | ||||||
|  | 	assertEqual("Array test #1", test[0] == 5 && test[1] == 7); | ||||||
|  |  | ||||||
|  | 	PopStackCell(stack, test[0], 1); | ||||||
|  | 	assertEqual("Value test #1", test[0] == 7); | ||||||
|  |  | ||||||
|  | 	PopStackCell(stack, test[0]); | ||||||
|  | 	assertEqual("Value test #2", test[0] == 50); | ||||||
|  |  | ||||||
|  | 	assertEqual("Size test #2", IsStackEmpty(stack) == true); | ||||||
|  |  | ||||||
|  | 	DestroyStack(stack); | ||||||
|  |  | ||||||
|  | 	done(); | ||||||
|  | } | ||||||
| @@ -233,6 +233,7 @@ scripting_files = [ | |||||||
|   'testsuite/sqlxtest.sql', |   'testsuite/sqlxtest.sql', | ||||||
|   'testsuite/trietest.sma', |   'testsuite/trietest.sma', | ||||||
|   'testsuite/utf8test.sma', |   'testsuite/utf8test.sma', | ||||||
|  |   'testsuite/stacktest.sma', | ||||||
|   'include/amxconst.inc', |   'include/amxconst.inc', | ||||||
|   'include/amxmisc.inc', |   'include/amxmisc.inc', | ||||||
|   'include/amxmodx.inc', |   'include/amxmodx.inc', | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user