Cvars: Extend "amxx cvars" command output
This commit is contained in:
		| @@ -10,6 +10,7 @@ | ||||
| #include "CvarManager.h" | ||||
| #include "amxmodx.h" | ||||
| #include <CDetour/detours.h> | ||||
| #include <auto-string.h> | ||||
|  | ||||
| CvarManager g_CvarManager; | ||||
|  | ||||
| @@ -27,20 +28,20 @@ bool Cvar_DirectSet_Custom(cvar_t* var, const char* value) | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	if (info->hasMin || info->hasMax) // cvar_s doesn't have min/max mechanism, so we check things here. | ||||
| 	if (info->bound.hasMin || info->bound.hasMax) // cvar_s doesn't have min/max mechanism, so we check things here. | ||||
| 	{ | ||||
| 		float fvalue = atof(value);  | ||||
| 		bool oob = false; | ||||
|  | ||||
| 		if (info->hasMin && fvalue < info->minVal) | ||||
| 		if (info->bound.hasMin && fvalue < info->bound.minVal) | ||||
| 		{ | ||||
| 			oob = true; | ||||
| 			fvalue = info->minVal; | ||||
| 			fvalue = info->bound.minVal; | ||||
| 		} | ||||
| 		else if (info->hasMax && fvalue > info->maxVal) | ||||
| 		else if (info->bound.hasMax && fvalue > info->bound.maxVal) | ||||
| 		{ | ||||
| 			oob = true; | ||||
| 			fvalue = info->maxVal; | ||||
| 			fvalue = info->bound.maxVal; | ||||
| 		} | ||||
|  | ||||
| 		if (oob) // Found value out of bound, set new value and block original call. | ||||
| @@ -58,7 +59,7 @@ bool Cvar_DirectSet_Custom(cvar_t* var, const char* value) | ||||
| 		{ | ||||
| 			CvarHook* hook = info->hooks[i]; | ||||
|  | ||||
| 			if (hook->forward->state == Forward::FSTATE_OK) // Our callback can be enable/disabled by natives. | ||||
| 			if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives. | ||||
| 			{ | ||||
| 				int result = executeForwards(hook->forward->id, reinterpret_cast<cvar_t*>(var), var->string, value); | ||||
|  | ||||
| @@ -295,7 +296,7 @@ bool CvarManager::CacheLookup(const char* name, CvarInfo** info) | ||||
| 	return m_Cache.retrieve(name, info); | ||||
| } | ||||
|  | ||||
| Forward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback) | ||||
| AutoForward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback) | ||||
| { | ||||
| 	CvarInfo* info = nullptr; | ||||
|  | ||||
| @@ -329,7 +330,7 @@ Forward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const ch | ||||
| 	// Detour is disabled on map change. | ||||
| 	m_HookDetour->EnableDetour(); | ||||
| 	 | ||||
| 	Forward* forward = new Forward(forwardId, *callback); | ||||
| 	AutoForward* forward = new AutoForward(forwardId, *callback); | ||||
| 	info->hooks.append(new CvarHook(g_plugins.findPlugin(amx)->getId(), forward)); | ||||
|  | ||||
| 	return forward; | ||||
| @@ -340,26 +341,141 @@ size_t CvarManager::GetRegCvarsCount() | ||||
| 	return m_AmxmodxCvars; | ||||
| } | ||||
|  | ||||
| AutoString convertFlagsToString(int flags) | ||||
| { | ||||
| 	AutoString flagsName; | ||||
|  | ||||
| 	if (flags > 0) | ||||
| 	{ | ||||
| 		if (flags & FCVAR_ARCHIVE)          flagsName = flagsName + "FCVAR_ARCHIVE "; | ||||
| 		if (flags & FCVAR_USERINFO)         flagsName = flagsName + "FCVAR_USERINFO "; | ||||
| 		if (flags & FCVAR_SERVER)           flagsName = flagsName + "FCVAR_SERVER "; | ||||
| 		if (flags & FCVAR_EXTDLL)           flagsName = flagsName + "FCVAR_EXTDLL "; | ||||
| 		if (flags & FCVAR_CLIENTDLL)        flagsName = flagsName + "FCVAR_CLIENTDLL "; | ||||
| 		if (flags & FCVAR_PROTECTED)        flagsName = flagsName + "FCVAR_PROTECTED "; | ||||
| 		if (flags & FCVAR_SPONLY)           flagsName = flagsName + "FCVAR_SPONLY "; | ||||
| 		if (flags & FCVAR_PRINTABLEONLY)    flagsName = flagsName + "FCVAR_PRINTABLEONLY "; | ||||
| 		if (flags & FCVAR_UNLOGGED)         flagsName = flagsName + "FCVAR_UNLOGGED "; | ||||
| 		if (flags & FCVAR_NOEXTRAWHITEPACE) flagsName = flagsName + "FCVAR_NOEXTRAWHITEPACE "; | ||||
| 	} | ||||
|  | ||||
| 	if (!flagsName.length()) | ||||
| 	{ | ||||
| 		flagsName = "-"; | ||||
| 	} | ||||
|  | ||||
| 	return flagsName; | ||||
| } | ||||
|  | ||||
| void CvarManager::OnConsoleCommand() | ||||
| { | ||||
| 	print_srvconsole("Registered cvars:\n"); | ||||
| 	print_srvconsole("       %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin"); | ||||
|  | ||||
| 	size_t index = 0; | ||||
| 	ke::AString pluginName; | ||||
| 	size_t indexToSearch = 0; | ||||
| 	ke::AString partialName; | ||||
|  | ||||
| 	if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin | ||||
| 	int argcount = CMD_ARGC(); | ||||
|  | ||||
| 	// amxx cvars <partial cvar name> <index from listing> | ||||
| 	// E.g.: | ||||
| 	//   amxx cvars test   <- list all cvars from plugin name starting by "test" | ||||
| 	//   amxx cvars 2      <- show informations about cvar in position 2 from "amxx cvars" list | ||||
| 	//   amxx cvars test 2 <- show informations about cvar in position 2 from "amxx cvars test" list | ||||
|  | ||||
| 	if (argcount > 2) | ||||
| 	{ | ||||
| 		pluginName = CMD_ARGV(2); | ||||
| 		const char* argument = CMD_ARGV(2); | ||||
| 		 | ||||
| 		indexToSearch = atoi(argument); // amxx cvars 2 | ||||
|  | ||||
| 		if (!indexToSearch) | ||||
| 		{ | ||||
| 			partialName = argument; // amxx cvars test | ||||
|  | ||||
| 			if (argcount > 3)       // amxx cvars test 2 | ||||
| 			{ | ||||
| 				indexToSearch = atoi(CMD_ARGV(3)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!indexToSearch) | ||||
| 	{ | ||||
| 		print_srvconsole("\nManaged cvars:\n"); | ||||
| 		print_srvconsole("       %-24.23s %-24.23s %-18.17s %-8.7s %-8.7s %-8.7s\n", "NAME", "VALUE", "PLUGIN", "BINDED", "HOOKED", "BOUNDED"); | ||||
| 		print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n"); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++) | ||||
| 	{ | ||||
| 		CvarInfo* ci = (*iter); | ||||
|  | ||||
| 		if (ci->amxmodx && (!pluginName.length() || strncmp(ci->name.chars(), pluginName.chars(), pluginName.length()) == 0)) | ||||
| 		// List any cvars having a status either created, hooked, binded or bounded by a plugin. | ||||
| 		bool in_list = ci->amxmodx || !ci->binds.empty() || !ci->hooks.empty() || ci->bound.hasMin || ci->bound.hasMax; | ||||
|  | ||||
| 		if (in_list && (!partialName.length() || strncmp(ci->plugin.chars(), partialName.chars(), partialName.length()) == 0)) | ||||
| 		{ | ||||
| 			print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++index, ci->name.chars(), ci->var->string, ci->plugin.chars()); | ||||
| 			if (!indexToSearch) | ||||
| 			{ | ||||
| 				print_srvconsole(" [%3d] %-24.23s %-24.23s %-18.17s %-8.7s %-8.7s %-8.7s\n", ++index, ci->name.chars(), ci->var->string, | ||||
| 								 ci->plugin.length() ? ci->plugin.chars() : "-", | ||||
| 								 ci->binds.empty() ? "no" : "yes", | ||||
| 								 ci->hooks.empty() ? "no" : "yes", | ||||
| 								 ci->bound.hasMin || ci->bound.hasMax ? "yes" : "no"); | ||||
| 			} | ||||
| 			else  | ||||
| 			{	 | ||||
| 				if (++index != indexToSearch) | ||||
| 				{ | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				print_srvconsole("\nCvar details :\n\n"); | ||||
| 				print_srvconsole(" Cvar name   : %s\n", ci->var->name); | ||||
| 				print_srvconsole(" Value       : %s\n", ci->var->string); | ||||
| 				print_srvconsole(" Def. value  : %s\n", ci->defaultval.chars()); | ||||
| 				print_srvconsole(" Description : %s\n", ci->description.chars()); | ||||
| 				print_srvconsole(" Flags       : %s\n\n", convertFlagsToString(ci->var->flags).ptr()); | ||||
|  | ||||
| 				print_srvconsole(" %-12s  %-26.25s %s\n", "STATUS", "PLUGIN", "INFOS"); | ||||
| 				print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"); | ||||
| 			 | ||||
| 				if (ci->amxmodx) | ||||
| 				{ | ||||
| 					print_srvconsole(" Registered    %-26.25s %s\n", ci->plugin.chars(), "-"); | ||||
| 				} | ||||
|  | ||||
| 				if (ci->bound.hasMin) | ||||
| 				{ | ||||
| 					print_srvconsole(" Min Bounded   %-26.25s %f\n", g_plugins.findPlugin(ci->bound.minPluginId)->getName(), ci->bound.minVal); | ||||
| 				} | ||||
|  | ||||
| 				if (ci->bound.hasMax) | ||||
| 				{ | ||||
| 					print_srvconsole(" Max Bounded   %-26.25s %f\n", g_plugins.findPlugin(ci->bound.maxPluginId)->getName(), ci->bound.maxVal); | ||||
| 				} | ||||
|  | ||||
| 				if (!ci->binds.empty()) | ||||
| 				{ | ||||
| 					for (size_t i = 0; i < ci->binds.length(); ++i) | ||||
| 					{ | ||||
| 						print_srvconsole(" Binded        %-26.25s %s\n", g_plugins.findPlugin(ci->binds[i]->pluginId)->getName(), "-"); | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				if (!ci->hooks.empty()) | ||||
| 				{ | ||||
| 					for (size_t i = 0; i < ci->hooks.length(); ++i) | ||||
| 					{ | ||||
| 						CvarHook* hook = ci->hooks[i]; | ||||
|  | ||||
| 						print_srvconsole(" Hooked        %-26.25s %s (%s)\n", g_plugins.findPlugin(hook->pluginId)->getName(), | ||||
| 										 hook->forward->callback.chars(),  | ||||
| 										 hook->forward->state == AutoForward::FSTATE_OK ? "active" : "inactive"); | ||||
| 					} | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -391,6 +507,7 @@ void CvarManager::OnPluginUnloaded() | ||||
| void CvarManager::OnAmxxShutdown() | ||||
| { | ||||
| 	// Free everything. | ||||
|  | ||||
| 	for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar = m_Cvars.erase(cvar)) | ||||
| 	{ | ||||
| 		for (size_t i = 0; i < (*cvar)->binds.length(); ++i) | ||||
|   | ||||
| @@ -23,7 +23,7 @@ enum CvarBounds | ||||
| 	CvarBound_Lower | ||||
| }; | ||||
|  | ||||
| struct Forward | ||||
| struct AutoForward | ||||
| { | ||||
| 	enum fwdstate | ||||
| 	{ | ||||
| @@ -32,10 +32,10 @@ struct Forward | ||||
| 		FSTATE_STOP, | ||||
| 	}; | ||||
|  | ||||
| 	Forward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {}; | ||||
| 	Forward()                             : id(-1) , state(FSTATE_INVALID) {}; | ||||
| 	AutoForward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {}; | ||||
| 	AutoForward()                             : id(-1) , state(FSTATE_INVALID) {}; | ||||
|  | ||||
| 	~Forward() | ||||
| 	~AutoForward() | ||||
| 	{ | ||||
| 		unregisterSPForward(id); | ||||
| 	} | ||||
| @@ -47,11 +47,11 @@ struct Forward | ||||
|  | ||||
| struct CvarHook | ||||
| { | ||||
| 	CvarHook(int id, Forward* fwd) : pluginId(id), forward(fwd) {}; | ||||
| 	CvarHook(int id)               : pluginId(id), forward(new Forward()) {}; | ||||
| 	CvarHook(int id, AutoForward* fwd) : pluginId(id), forward(fwd) {}; | ||||
| 	CvarHook(int id)                   : pluginId(id), forward(new AutoForward()) {}; | ||||
|  | ||||
| 	int pluginId; | ||||
| 	ke::AutoPtr<Forward> forward; | ||||
| 	ke::AutoPtr<AutoForward> forward; | ||||
| }; | ||||
|  | ||||
| struct CvarBind | ||||
| @@ -65,7 +65,10 @@ struct CvarBind | ||||
|  | ||||
| 	CvarBind(int id_, CvarType type_, cell* varAddress_, size_t varLength_) | ||||
| 		:  | ||||
| 		pluginId(id_), type(type_), varAddress(varAddress_), varLength(varLength_) {}; | ||||
| 		pluginId(id_),  | ||||
| 		type(type_),  | ||||
| 		varAddress(varAddress_),  | ||||
| 		varLength(varLength_) {}; | ||||
|  | ||||
| 	int      pluginId; | ||||
| 	CvarType type; | ||||
| @@ -73,8 +76,30 @@ struct CvarBind | ||||
| 	size_t   varLength; | ||||
| }; | ||||
|  | ||||
| struct CvarBound | ||||
| { | ||||
| 	CvarBound(bool hasMin_, float minVal_, bool hasMax_, float maxVal_, int minPluginId_, int maxPluginId_) | ||||
| 		: | ||||
| 		hasMin(hasMin_), hasMax(hasMax_),  | ||||
| 		minVal(minVal_), maxVal(maxVal_), | ||||
| 		minPluginId(minPluginId_),  | ||||
| 		maxPluginId(maxPluginId_) {}; | ||||
|  | ||||
| 	CvarBound() | ||||
| 		: | ||||
| 		hasMin(false), hasMax(false),  | ||||
| 		minVal(0), maxVal(0) {}; | ||||
|  | ||||
| 	bool    hasMin; | ||||
| 	bool    hasMax; | ||||
| 	float   minVal; | ||||
| 	float   maxVal; | ||||
| 	int     minPluginId; | ||||
| 	int     maxPluginId; | ||||
| }; | ||||
|  | ||||
| typedef ke::Vector<CvarHook*> CvarsHook; | ||||
| typedef ke::Vector<CvarBind*>   CvarsBind; | ||||
| typedef ke::Vector<CvarBind*> CvarsBind; | ||||
|  | ||||
| struct CvarInfo : public ke::InlineListNode<CvarInfo> | ||||
| { | ||||
| @@ -83,29 +108,26 @@ struct CvarInfo : public ke::InlineListNode<CvarInfo> | ||||
| 			 const char* plugin_, int pluginId_) | ||||
| 		: | ||||
| 		name(name_), description(helpText),	 | ||||
| 		hasMin(hasMin_), minVal(min_), hasMax(hasMax_), maxVal(max_), | ||||
| 		bound(hasMin_, min_, hasMax_, max_, pluginId_, pluginId_), | ||||
| 		plugin(plugin_), pluginId(pluginId_) {}; | ||||
|  | ||||
| 	CvarInfo(const char* name_) | ||||
| 		: | ||||
| 		name(name_), defaultval(""), description(""),  | ||||
| 		hasMin(false), minVal(0), hasMax(false), maxVal(0), | ||||
| 		plugin(""), pluginId(-1), amxmodx(false) {}; | ||||
| 		bound(), plugin(""), pluginId(-1), amxmodx(false) {}; | ||||
|  | ||||
| 	cvar_t*      var; | ||||
| 	ke::AString  name; | ||||
| 	ke::AString  defaultval; | ||||
| 	ke::AString  description; | ||||
| 	bool         hasMin; | ||||
| 	bool         hasMax; | ||||
| 	float        minVal; | ||||
| 	float        maxVal; | ||||
|  | ||||
| 	ke::AString  plugin; | ||||
| 	int          pluginId; | ||||
|  | ||||
| 	CvarBound    bound; | ||||
| 	CvarsBind    binds; | ||||
| 	CvarsHook    hooks; | ||||
|  | ||||
| 	bool         amxmodx; | ||||
|  | ||||
| 	static inline bool matches(const char *name, const CvarInfo* info) | ||||
| @@ -137,7 +159,7 @@ class CvarManager | ||||
| 		CvarInfo* FindCvar(size_t index); | ||||
| 		bool      CacheLookup(const char* name, CvarInfo** info); | ||||
|  | ||||
| 		Forward*  HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback); | ||||
| 		AutoForward*  HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback); | ||||
|  | ||||
| 		size_t    GetRegCvarsCount(); | ||||
|  | ||||
|   | ||||
| @@ -92,7 +92,7 @@ static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params) | ||||
| 	} | ||||
|  | ||||
| 	const char* callback; | ||||
| 	Forward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback); | ||||
| 	AutoForward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback); | ||||
|  | ||||
| 	if (!forward) | ||||
| 	{ | ||||
| @@ -106,7 +106,7 @@ static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params) | ||||
| // enable_cvar_hook(cvarhook:handle); | ||||
| static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) | ||||
| { | ||||
| 	Forward* forward = reinterpret_cast<Forward*>(params[1]); | ||||
| 	AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]); | ||||
|  | ||||
| 	if (!forward) | ||||
| 	{ | ||||
| @@ -114,7 +114,7 @@ static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	forward->state = Forward::FSTATE_OK; | ||||
| 	forward->state = AutoForward::FSTATE_OK; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| @@ -122,7 +122,7 @@ static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) | ||||
| // disable_cvar_hook(cvarhook:handle); | ||||
| static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params) | ||||
| { | ||||
| 	Forward* forward = reinterpret_cast<Forward*>(params[1]); | ||||
| 	AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]); | ||||
|  | ||||
| 	if (!forward) | ||||
| 	{ | ||||
| @@ -130,7 +130,7 @@ static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params) | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	forward->state =  Forward::FSTATE_STOP; | ||||
| 	forward->state =  AutoForward::FSTATE_STOP; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| @@ -329,12 +329,12 @@ static cell AMX_NATIVE_CALL get_pcvar_bounds(AMX *amx, cell *params) | ||||
| 	switch (params[2]) | ||||
| 	{ | ||||
| 		case CvarBound_Lower: | ||||
| 			hasBound = info->hasMin; | ||||
| 			bound = info->minVal; | ||||
| 			hasBound = info->bound.hasMin; | ||||
| 			bound = info->bound.minVal; | ||||
| 			break; | ||||
| 		case CvarBound_Upper: | ||||
| 			hasBound = info->hasMax; | ||||
| 			bound = info->maxVal; | ||||
| 			hasBound = info->bound.hasMax; | ||||
| 			bound = info->bound.maxVal; | ||||
| 			break; | ||||
| 		default: | ||||
| 			LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]); | ||||
| @@ -520,16 +520,19 @@ static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params) | ||||
| 	} | ||||
|  | ||||
| 	bool set = params[3] > 0 ? true : false; | ||||
| 	int pluginId = g_plugins.findPluginFast(amx)->getId(); | ||||
|  | ||||
| 	switch (params[2]) | ||||
| 	{ | ||||
| 		case CvarBound_Lower: | ||||
| 			info->hasMin = set; | ||||
| 			info->minVal = set ? amx_ctof(params[4]) : 0; | ||||
| 			info->bound.hasMin = set; | ||||
| 			info->bound.minVal = set ? amx_ctof(params[4]) : 0; | ||||
| 			info->bound.minPluginId = pluginId; | ||||
| 			break; | ||||
| 		case CvarBound_Upper: | ||||
| 			info->hasMax = set; | ||||
| 			info->maxVal = set ? amx_ctof(params[4]) : 0; | ||||
| 			info->bound.hasMax = set; | ||||
| 			info->bound.maxVal = set ? amx_ctof(params[4]) : 0; | ||||
| 			info->bound.maxPluginId = pluginId; | ||||
| 			break; | ||||
| 		default: | ||||
| 			LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]); | ||||
|   | ||||
| @@ -232,14 +232,14 @@ void amx_command() | ||||
| 	} else { | ||||
| 		print_srvconsole("Usage: amxx < command > [ argument ]\n"); | ||||
| 		print_srvconsole("Commands:\n"); | ||||
| 		print_srvconsole("   version                - display amxx version info\n"); | ||||
| 		print_srvconsole("   gpl                    - print the license\n"); | ||||
| 		print_srvconsole("   plugins                - list plugins currently loaded\n"); | ||||
| 		print_srvconsole("   modules                - list modules currently loaded\n"); | ||||
| 		print_srvconsole("   cvars [ plugin ]       - list cvars registered by plugins\n"); | ||||
| 		print_srvconsole("   cmds [ plugin ]        - list commands registered by plugins\n"); | ||||
| 		print_srvconsole("   pause < plugin >       - pause a running plugin\n"); | ||||
| 		print_srvconsole("   unpause < plugin >     - unpause a previously paused plugin\n"); | ||||
| 		print_srvconsole("   version                    - display amxx version info\n"); | ||||
| 		print_srvconsole("   gpl                        - print the license\n"); | ||||
| 		print_srvconsole("   plugins                    - list plugins currently loaded\n"); | ||||
| 		print_srvconsole("   modules                    - list modules currently loaded\n"); | ||||
| 		print_srvconsole("   cvars [ plugin ] [ index ] - list cvars handled by amxx or show informations about a cvar if index is provided\n"); | ||||
| 		print_srvconsole("   cmds [ plugin ]            - list commands registered by plugins\n"); | ||||
| 		print_srvconsole("   pause < plugin >           - pause a running plugin\n"); | ||||
| 		print_srvconsole("   unpause < plugin >         - unpause a previously paused plugin\n"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										153
									
								
								public/auto-string.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								public/auto-string.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| /* vim: set ts=2 sw=2 tw=99 et: | ||||
|  * | ||||
|  * Copyright (C) 2012 David Anderson | ||||
|  * | ||||
|  * This file is part of SourcePawn. | ||||
|  * | ||||
|  * SourcePawn 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 3 of the License, or (at your option) | ||||
|  * any later version. | ||||
|  *  | ||||
|  * SourcePawn 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 | ||||
|  * SourcePawn. If not, see http://www.gnu.org/licenses/. | ||||
|  */ | ||||
| #ifndef _include_auto_string_h_ | ||||
| #define _include_auto_string_h_ | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <am-string.h> | ||||
|  | ||||
| using namespace ke; | ||||
|  | ||||
| class AutoString | ||||
| { | ||||
|   public: | ||||
|     AutoString() : ptr_(NULL), length_(0) | ||||
|     { | ||||
|     } | ||||
|     AutoString(AutoString &&other) | ||||
|      : ptr_(other.ptr_), | ||||
|        length_(other.length_) | ||||
|     { | ||||
|       other.ptr_ = nullptr; | ||||
|       other.length_ = 0; | ||||
|     } | ||||
|     AutoString(const char *ptr) | ||||
|     { | ||||
|       assign(ptr); | ||||
|     } | ||||
|     AutoString(const AString &str) | ||||
|     { | ||||
|       assign(str.chars(), str.length()); | ||||
|     } | ||||
|     AutoString(const char *ptr, size_t len) | ||||
|     { | ||||
|       assign(ptr, len); | ||||
|     } | ||||
|     AutoString(const AutoString &other) | ||||
|     { | ||||
|       assign(other.ptr(), other.length()); | ||||
|     } | ||||
|     ~AutoString() | ||||
|     { | ||||
|       free(ptr_); | ||||
|     } | ||||
|  | ||||
|     AutoString &operator =(const char *ptr) { | ||||
|       free(ptr_); | ||||
|       assign(ptr); | ||||
|       return *this; | ||||
|     } | ||||
|     AutoString &operator =(const AutoString &other) { | ||||
|       free(ptr_); | ||||
|       assign(other.ptr(), other.length()); | ||||
|       return *this; | ||||
|     } | ||||
|     AutoString &operator =(AutoString &&other) { | ||||
|       Swap(other.ptr_, ptr_); | ||||
|       Swap(other.length_, length_); | ||||
|       return *this; | ||||
|     } | ||||
|  | ||||
|     AutoString operator +(const AutoString &other) const { | ||||
|       size_t len = length() + other.length(); | ||||
|       char *buf = (char *)malloc(len + 1); | ||||
|       memcpy(buf, ptr(), length()); | ||||
|       memcpy(buf + length(), other.ptr(), other.length()); | ||||
|       buf[len] = '\0'; | ||||
|  | ||||
|       AutoString r; | ||||
|       r.ptr_ = buf; | ||||
|       r.length_ = len; | ||||
|       return r; | ||||
|     } | ||||
|  | ||||
|     AutoString operator +(const char *other) const { | ||||
|       size_t other_length = strlen(other); | ||||
|       size_t len = length() + other_length; | ||||
|       char *buf = (char *)malloc(len + 1); | ||||
|       memcpy(buf, ptr(), length()); | ||||
|       memcpy(buf + length(), other, other_length); | ||||
|       buf[len] = '\0'; | ||||
|  | ||||
|       AutoString r; | ||||
|       r.ptr_ = buf; | ||||
|       r.length_ = len; | ||||
|       return r; | ||||
|     } | ||||
|  | ||||
|     AutoString operator +(unsigned val) const { | ||||
|       char buffer[24]; | ||||
|       _snprintf(buffer, sizeof(buffer), "%d", val); | ||||
|       return *this + buffer; | ||||
|     } | ||||
|  | ||||
|     size_t length() const { | ||||
|       return length_; | ||||
|     } | ||||
|  | ||||
|     bool operator !() const { | ||||
|       return !length_; | ||||
|     } | ||||
|  | ||||
|     const char *ptr() const { | ||||
|       return ptr_ ? ptr_ : ""; | ||||
|     } | ||||
|     operator const char *() const { | ||||
|       return ptr(); | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     void assign(const char *ptr) { | ||||
|       if (!ptr) { | ||||
|         ptr_ = NULL; | ||||
|         length_ = 0; | ||||
|         return; | ||||
|       } | ||||
|       assign(ptr, strlen(ptr)); | ||||
|     } | ||||
|     void assign(const char *ptr, size_t length) { | ||||
|       if (!ptr) { | ||||
|         ptr_ = NULL; | ||||
|         length_ = 0; | ||||
|         return; | ||||
|       } | ||||
|       length_ = length; | ||||
|       ptr_ = (char *)malloc(length_ + 1); | ||||
|       memcpy(ptr_, ptr, length_); | ||||
|       ptr_[length_] = '\0'; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     char *ptr_; | ||||
|     size_t length_; | ||||
| }; | ||||
|  | ||||
| #endif // _include_spcomp_auto_string_h_ | ||||
		Reference in New Issue
	
	Block a user