core/smn_keyvalues.cpp
author David Anderson <dvander@alliedmods.net>
Sun Feb 08 15:40:48 2009 -0500 (2009-02-08)
changeset 2571 5c995a647735
parent 2416 4400dd5bc470
child 3872 4c93f74cae51
permissions -rw-r--r--
Fixed documentation typos in dbi.inc (bug 3587).
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sourcemod.h"
    33 #include "sourcemm_api.h"
    34 #include "sm_stringutil.h"
    35 #include "HandleSys.h"
    36 #include "HalfLife2.h"
    37 #include <KeyValues.h>
    38 #include "utlbuffer.h"
    39 
    40 HandleType_t g_KeyValueType;
    41 
    42 struct KeyValueStack 
    43 {
    44 	KeyValues *pBase;
    45 	CStack<KeyValues *> pCurRoot;
    46 };
    47 
    48 class KeyValueNatives : 
    49 	public SMGlobalClass,
    50 	public IHandleTypeDispatch
    51 {
    52 public:
    53 	void OnSourceModAllInitialized()
    54 	{
    55 		g_KeyValueType = g_HandleSys.CreateType("KeyValues", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    56 	}
    57 	void OnSourceModShutdown()
    58 	{
    59 		g_HandleSys.RemoveType(g_KeyValueType, g_pCoreIdent);
    60 		g_KeyValueType = 0;
    61 	}
    62 	void OnHandleDestroy(HandleType_t type, void *object)
    63 	{
    64 		KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
    65 		pStk->pBase->deleteThis();
    66 		delete pStk;
    67 	}
    68 	int CalcKVSizeR(KeyValues *pv)
    69 	{
    70 		CUtlBuffer buf;
    71 		int size;
    72 
    73 		pv->RecursiveSaveToFile(buf, 0);
    74 		size = buf.TellMaxPut();
    75 
    76 		buf.Purge();
    77 
    78 		return size;
    79 	}
    80 	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
    81 	{
    82 		KeyValueStack *pStk = (KeyValueStack *)object;
    83 		unsigned int size = sizeof(KeyValueStack) + (pStk->pCurRoot.size() * sizeof(KeyValues *));
    84 
    85 		/* Check how much memory the actual thing takes up */		
    86 		size += CalcKVSizeR(pStk->pBase);
    87 
    88 		*pSize = size;
    89 
    90 		return true;
    91 	}
    92 };
    93 
    94 KeyValues *SourceModBase::ReadKeyValuesHandle(Handle_t hndl, HandleError *err, bool root)
    95 {
    96 	HandleError herr;
    97 	HandleSecurity sec;
    98 	KeyValueStack *pStk;
    99 
   100 	sec.pOwner = NULL;
   101 	sec.pIdentity = g_pCoreIdent;
   102 
   103 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   104 		!= HandleError_None)
   105 	{
   106 		if (err)
   107 		{
   108 			*err = herr;
   109 		}
   110 		return NULL;
   111 	}
   112 
   113 	if (err)
   114 	{
   115 		*err = HandleError_None;
   116 	}
   117 
   118 	return (root) ? pStk->pBase : pStk->pCurRoot.front();
   119 }
   120 
   121 static cell_t smn_KvSetString(IPluginContext *pCtx, const cell_t *params)
   122 {
   123 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   124 	HandleError herr;
   125 	HandleSecurity sec;
   126 	KeyValueStack *pStk;
   127 
   128 	sec.pOwner = NULL;
   129 	sec.pIdentity = g_pCoreIdent;
   130 
   131 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   132 		!= HandleError_None)
   133 	{
   134 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   135 	}
   136 
   137 	char *key, *value;
   138 	pCtx->LocalToStringNULL(params[2], &key);
   139 	pCtx->LocalToString(params[3], &value);
   140 
   141 	pStk->pCurRoot.front()->SetString(key, value);
   142 
   143 	return 1;
   144 }
   145 
   146 static cell_t smn_KvSetNum(IPluginContext *pCtx, const cell_t *params)
   147 {
   148 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   149 	HandleError herr;
   150 	HandleSecurity sec;
   151 	KeyValueStack *pStk;
   152 
   153 	sec.pOwner = NULL;
   154 	sec.pIdentity = g_pCoreIdent;
   155 
   156 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   157 		!= HandleError_None)
   158 	{
   159 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   160 	}
   161 
   162 	char *key;
   163 	pCtx->LocalToStringNULL(params[2], &key);
   164 
   165 	pStk->pCurRoot.front()->SetInt(key, params[3]);
   166 
   167 	return 1;
   168 }
   169 
   170 static cell_t smn_KvSetUInt64(IPluginContext *pCtx, const cell_t *params)
   171 {
   172 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   173 	HandleError herr;
   174 	HandleSecurity sec;
   175 	KeyValueStack *pStk;
   176 
   177 	sec.pOwner = NULL;
   178 	sec.pIdentity = g_pCoreIdent;
   179 
   180 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   181 		!= HandleError_None)
   182 	{
   183 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   184 	}
   185 
   186 	char *key;
   187 	cell_t *addr;
   188 	uint64 value;
   189 	pCtx->LocalToStringNULL(params[2], &key);
   190 	pCtx->LocalToPhysAddr(params[3], &addr);
   191 
   192 	value = static_cast<uint64>(*addr);
   193 	pStk->pCurRoot.front()->SetUint64(key, value);
   194 
   195 	return 1;
   196 }
   197 
   198 static cell_t smn_KvSetFloat(IPluginContext *pCtx, const cell_t *params)
   199 {
   200 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   201 	HandleError herr;
   202 	HandleSecurity sec;
   203 	KeyValueStack *pStk;
   204 
   205 	sec.pOwner = NULL;
   206 	sec.pIdentity = g_pCoreIdent;
   207 
   208 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   209 		!= HandleError_None)
   210 	{
   211 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   212 	}
   213 
   214 	char *key;
   215 	pCtx->LocalToStringNULL(params[2], &key);
   216 
   217 	pStk->pCurRoot.front()->SetFloat(key, sp_ctof(params[3]));
   218 
   219 	return 1;
   220 }
   221 
   222 static cell_t smn_KvSetColor(IPluginContext *pCtx, const cell_t *params)
   223 {
   224 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   225 	HandleError herr;
   226 	HandleSecurity sec;
   227 	KeyValueStack *pStk;
   228 
   229 	sec.pOwner = NULL;
   230 	sec.pIdentity = g_pCoreIdent;
   231 
   232 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   233 		!= HandleError_None)
   234 	{
   235 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   236 	}
   237 
   238 	char *key;
   239 	pCtx->LocalToStringNULL(params[2], &key);
   240 
   241 	Color color(params[3], params[4], params[5], params[6]);
   242 	pStk->pCurRoot.front()->SetColor(key, color);
   243 
   244 	return 1;
   245 }
   246 
   247 static cell_t smn_KvSetVector(IPluginContext *pCtx, const cell_t *params)
   248 {
   249 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   250 	HandleError herr;
   251 	HandleSecurity sec;
   252 	KeyValueStack *pStk;
   253 
   254 	sec.pOwner = NULL;
   255 	sec.pIdentity = g_pCoreIdent;
   256 
   257 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   258 		!= HandleError_None)
   259 	{
   260 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   261 	}
   262 
   263 	char *key;
   264 	char buffer[64];
   265 	cell_t *vector;
   266 	pCtx->LocalToStringNULL(params[2], &key);
   267 	pCtx->LocalToPhysAddr(params[3], &vector);
   268 
   269 	UTIL_Format(buffer, sizeof(buffer), "%f %f %f", sp_ctof(vector[0]), sp_ctof(vector[1]), sp_ctof(vector[2]));
   270 
   271 	pStk->pCurRoot.front()->SetString(key, buffer);
   272 
   273 	return 1;
   274 }
   275 
   276 static cell_t smn_KvGetString(IPluginContext *pCtx, const cell_t *params)
   277 {
   278 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   279 	HandleError herr;
   280 	HandleSecurity sec;
   281 	KeyValueStack *pStk;
   282 
   283 	sec.pOwner = NULL;
   284 	sec.pIdentity = g_pCoreIdent;
   285 
   286 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   287 		!= HandleError_None)
   288 	{
   289 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   290 	}
   291 
   292 	const char *value;
   293 	char *key, *defvalue;
   294 	pCtx->LocalToStringNULL(params[2], &key);
   295 	pCtx->LocalToString(params[5], &defvalue);
   296 
   297 	value = pStk->pCurRoot.front()->GetString(key, defvalue);
   298 	pCtx->StringToLocalUTF8(params[3], params[4], value, NULL);
   299 
   300 	return 1;
   301 }
   302 
   303 static cell_t smn_KvGetNum(IPluginContext *pCtx, const cell_t *params)
   304 {
   305 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   306 	HandleError herr;
   307 	HandleSecurity sec;
   308 	KeyValueStack *pStk;
   309 
   310 	sec.pOwner = NULL;
   311 	sec.pIdentity = g_pCoreIdent;
   312 
   313 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   314 		!= HandleError_None)
   315 	{
   316 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   317 	}
   318 
   319 	int value;
   320 	char *key;
   321 	pCtx->LocalToStringNULL(params[2], &key);
   322 
   323 	value = pStk->pCurRoot.front()->GetInt(key, params[3]);
   324 
   325 	return value;
   326 }
   327 
   328 static cell_t smn_KvGetFloat(IPluginContext *pCtx, const cell_t *params)
   329 {
   330 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   331 	HandleError herr;
   332 	HandleSecurity sec;
   333 	KeyValueStack *pStk;
   334 
   335 	sec.pOwner = NULL;
   336 	sec.pIdentity = g_pCoreIdent;
   337 
   338 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   339 		!= HandleError_None)
   340 	{
   341 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   342 	}
   343 
   344 	float value;
   345 	char *key;
   346 	pCtx->LocalToStringNULL(params[2], &key);
   347 
   348 	value = pStk->pCurRoot.front()->GetFloat(key, sp_ctof(params[3]));
   349 
   350 	return sp_ftoc(value);
   351 }
   352 
   353 static cell_t smn_KvGetColor(IPluginContext *pCtx, const cell_t *params)
   354 {
   355 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   356 	HandleError herr;
   357 	HandleSecurity sec;
   358 	KeyValueStack *pStk;
   359 
   360 	sec.pOwner = NULL;
   361 	sec.pIdentity = g_pCoreIdent;
   362 
   363 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   364 		!= HandleError_None)
   365 	{
   366 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   367 	}
   368 
   369 	Color color;
   370 	char *key;
   371 	cell_t *r, *g, *b, *a;
   372 	pCtx->LocalToStringNULL(params[2], &key);
   373 	pCtx->LocalToPhysAddr(params[3], &r);
   374 	pCtx->LocalToPhysAddr(params[4], &g);
   375 	pCtx->LocalToPhysAddr(params[5], &b);
   376 	pCtx->LocalToPhysAddr(params[6], &a);
   377 
   378 	color = pStk->pCurRoot.front()->GetColor(key);
   379 	*r = color.r();
   380 	*g = color.g();
   381 	*b = color.b();
   382 	*a = color.a();
   383 
   384 	return 1;
   385 }
   386 
   387 static cell_t smn_KvGetUInt64(IPluginContext *pCtx, const cell_t *params)
   388 {
   389 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   390 	HandleError herr;
   391 	HandleSecurity sec;
   392 	KeyValueStack *pStk;
   393 
   394 	sec.pOwner = NULL;
   395 	sec.pIdentity = g_pCoreIdent;
   396 
   397 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   398 		!= HandleError_None)
   399 	{
   400 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   401 	}
   402 
   403 	char *key;
   404 	cell_t *addr, *defvalue;
   405 	uint64 value;
   406 	pCtx->LocalToStringNULL(params[2], &key);
   407 	pCtx->LocalToPhysAddr(params[3], &addr);
   408 	pCtx->LocalToPhysAddr(params[4], &defvalue);
   409 
   410 	value = pStk->pCurRoot.front()->GetUint64(key, static_cast<uint64>(*defvalue));
   411 	*reinterpret_cast<uint64 *>(addr) = value;
   412 
   413 	return 1;
   414 }
   415 
   416 static cell_t smn_KvGetVector(IPluginContext *pCtx, const cell_t *params)
   417 {
   418 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   419 	HandleError herr;
   420 	HandleSecurity sec;
   421 	KeyValueStack *pStk;
   422 
   423 	sec.pOwner = NULL;
   424 	sec.pIdentity = g_pCoreIdent;
   425 
   426 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   427 		!= HandleError_None)
   428 	{
   429 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   430 	}
   431 
   432 	char *key;
   433 	const char *value;
   434 	cell_t *defvector, *outvector;
   435 	char buffer[64];
   436 	pCtx->LocalToStringNULL(params[2], &key);
   437 	pCtx->LocalToPhysAddr(params[3], &outvector);
   438 	pCtx->LocalToPhysAddr(params[4], &defvector);
   439 
   440 	UTIL_Format(buffer, sizeof(buffer), "%f %f %f", sp_ctof(defvector[0]), sp_ctof(defvector[1]), sp_ctof(defvector[2]));
   441 
   442 	value = pStk->pCurRoot.front()->GetString(key, buffer);
   443 
   444 	float out;
   445 	int components = 0;
   446 	while (*value && components < 3)
   447 	{
   448 		while ((*value) && (*value == ' '))
   449 		{
   450 			value++;
   451 		}
   452 
   453 		out = 0.0f;
   454 		bool isnegative;
   455 		if (*value == '-')
   456 		{
   457 			isnegative = true;
   458 			value++;
   459 		}
   460 		else
   461 		{
   462 			isnegative = false;
   463 		}
   464 
   465 		for (; *value && isdigit(*value); ++value)
   466 		{
   467 			out *= 10.0f;
   468 			out += *value - '0';
   469 		}
   470 
   471 		if (*value == '.')
   472 		{
   473 			value++;
   474 			float factor = 0.1f;
   475 			for (; *value && isdigit(*value); ++value)
   476 			{
   477 				out += (*value - '0') * factor;
   478 				factor *= 0.1f;
   479 			}
   480 		}
   481 
   482 		out = (isnegative) ? -out : out;
   483 		outvector[components++] = sp_ftoc(out);
   484 	}
   485 
   486 	return 1;
   487 }
   488 
   489 static cell_t smn_CreateKeyValues(IPluginContext *pCtx, const cell_t *params)
   490 {
   491 	KeyValueStack *pStk;
   492 	char *name, *firstkey, *firstvalue;
   493 	bool is_empty;
   494 
   495 	pCtx->LocalToString(params[1], &name);
   496 	pCtx->LocalToString(params[2], &firstkey);
   497 	pCtx->LocalToString(params[3], &firstvalue);
   498 
   499 	is_empty = (firstkey[0] == '\0');
   500 	pStk = new KeyValueStack;
   501 	pStk->pBase = new KeyValues(name, is_empty ? NULL : firstkey, (is_empty||(firstvalue[0]=='\0')) ? NULL : firstvalue);
   502 	pStk->pCurRoot.push(pStk->pBase);
   503 
   504 	return g_HandleSys.CreateHandle(g_KeyValueType, pStk, pCtx->GetIdentity(), g_pCoreIdent, NULL);
   505 }
   506 
   507 static cell_t smn_KvJumpToKey(IPluginContext *pCtx, const cell_t *params)
   508 {
   509 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   510 	HandleError herr;
   511 	HandleSecurity sec;
   512 	char *name;	
   513 	KeyValueStack *pStk;
   514 
   515 	sec.pOwner = NULL;
   516 	sec.pIdentity = g_pCoreIdent;
   517 
   518 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   519 		!= HandleError_None)
   520 	{
   521 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   522 	}
   523 
   524 	pCtx->LocalToString(params[2], &name);
   525 
   526 	KeyValues *pSubKey = pStk->pCurRoot.front();
   527 	pSubKey = pSubKey->FindKey(name, (params[3]) ? true : false);
   528 	if (!pSubKey)
   529 	{
   530 		return 0;
   531 	}
   532 	pStk->pCurRoot.push(pSubKey);
   533 
   534 	return 1;
   535 }
   536 
   537 static cell_t smn_KvJumpToKeySymbol(IPluginContext *pCtx, const cell_t *params)
   538 {
   539 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   540 	HandleError herr;
   541 	HandleSecurity sec;
   542 	KeyValueStack *pStk;
   543 
   544 	sec.pOwner = NULL;
   545 	sec.pIdentity = g_pCoreIdent;
   546 
   547 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   548 		!= HandleError_None)
   549 	{
   550 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   551 	}
   552 
   553 	KeyValues *pSubKey = pStk->pCurRoot.front();
   554 	pSubKey = pSubKey->FindKey(params[2]);
   555 	if (!pSubKey)
   556 	{
   557 		return 0;
   558 	}
   559 	pStk->pCurRoot.push(pSubKey);
   560 
   561 	return 1;
   562 }
   563 
   564 static cell_t smn_KvGotoFirstSubKey(IPluginContext *pCtx, const cell_t *params)
   565 {
   566 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   567 	HandleError herr;
   568 	HandleSecurity sec;
   569 	KeyValueStack *pStk;
   570 
   571 	sec.pOwner = NULL;
   572 	sec.pIdentity = g_pCoreIdent;
   573 
   574 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   575 		!= HandleError_None)
   576 	{
   577 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   578 	}
   579 
   580 	KeyValues *pSubKey = pStk->pCurRoot.front();
   581 	KeyValues *pFirstSubKey;
   582 	if (params[2])
   583 	{
   584 		pFirstSubKey = pSubKey->GetFirstTrueSubKey();
   585 	} else {
   586 		pFirstSubKey = pSubKey->GetFirstSubKey();
   587 	}
   588 
   589 	if (!pFirstSubKey)
   590 	{
   591 		return 0;
   592 	}
   593 	pStk->pCurRoot.push(pFirstSubKey);
   594 
   595 	return 1;
   596 }
   597 
   598 static cell_t smn_KvGotoNextKey(IPluginContext *pCtx, const cell_t *params)
   599 {
   600 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   601 	HandleError herr;
   602 	HandleSecurity sec;
   603 	KeyValueStack *pStk;
   604 
   605 	sec.pOwner = NULL;
   606 	sec.pIdentity = g_pCoreIdent;
   607 
   608 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   609 		!= HandleError_None)
   610 	{
   611 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   612 	}
   613 
   614 	KeyValues *pSubKey = pStk->pCurRoot.front();
   615 	if (params[2])
   616 	{
   617 		pSubKey = pSubKey->GetNextTrueSubKey();
   618 	} else {
   619 		pSubKey = pSubKey->GetNextKey();
   620 	}
   621 	if (!pSubKey)
   622 	{
   623 		return 0;
   624 	}
   625 	pStk->pCurRoot.pop();
   626 	pStk->pCurRoot.push(pSubKey);
   627 
   628 	return 1;	
   629 }
   630 
   631 static cell_t smn_KvGoBack(IPluginContext *pCtx, const cell_t *params)
   632 {
   633 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   634 	HandleError herr;
   635 	HandleSecurity sec;
   636 	KeyValueStack *pStk;
   637 
   638 	sec.pOwner = NULL;
   639 	sec.pIdentity = g_pCoreIdent;
   640 
   641 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   642 		!= HandleError_None)
   643 	{
   644 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   645 	}
   646 
   647 	if (pStk->pCurRoot.size() == 1)
   648 	{
   649 		return 0;
   650 	}
   651 	pStk->pCurRoot.pop();
   652 
   653 	return 1;
   654 }
   655 
   656 static cell_t smn_KvRewind(IPluginContext *pCtx, const cell_t *params)
   657 {
   658 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   659 	HandleError herr;
   660 	HandleSecurity sec;
   661 	KeyValueStack *pStk;
   662 
   663 	sec.pOwner = NULL;
   664 	sec.pIdentity = g_pCoreIdent;
   665 
   666 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   667 		!= HandleError_None)
   668 	{
   669 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   670 	}
   671 
   672 	while (pStk->pCurRoot.size() > 1)
   673 	{
   674 		pStk->pCurRoot.pop();
   675 	}
   676 
   677 	return 1;
   678 }
   679 
   680 static cell_t smn_KvGetSectionName(IPluginContext *pCtx, const cell_t *params)
   681 {
   682 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   683 	HandleError herr;
   684 	HandleSecurity sec;
   685 	KeyValueStack *pStk;
   686 
   687 	sec.pOwner = NULL;
   688 	sec.pIdentity = g_pCoreIdent;
   689 
   690 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   691 		!= HandleError_None)
   692 	{
   693 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   694 	}
   695 
   696 	KeyValues *pSection = pStk->pCurRoot.front();
   697 	const char *name = pSection->GetName();
   698 	if (!name)
   699 	{
   700 		return 0;
   701 	}
   702 	pCtx->StringToLocalUTF8(params[2], params[3], name, NULL);
   703 
   704 	return 1;
   705 }
   706 
   707 static cell_t smn_KvSetSectionName(IPluginContext *pCtx, const cell_t *params)
   708 {
   709 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   710 	HandleError herr;
   711 	HandleSecurity sec;
   712 	char *name;
   713 	KeyValueStack *pStk;
   714 
   715 	sec.pOwner = NULL;
   716 	sec.pIdentity = g_pCoreIdent;
   717 
   718 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   719 		!= HandleError_None)
   720 	{
   721 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   722 	}
   723 
   724 	pCtx->LocalToString(params[2], &name);
   725 
   726 	KeyValues *pSection = pStk->pCurRoot.front();
   727 	pSection->SetName(name);
   728 
   729 	return 1;
   730 }
   731 
   732 static cell_t smn_KvGetDataType(IPluginContext *pCtx, const cell_t *params)
   733 {
   734 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   735 	HandleError herr;
   736 	HandleSecurity sec;
   737 	char *name;
   738 	KeyValueStack *pStk;
   739 
   740 	sec.pOwner = NULL;
   741 	sec.pIdentity = g_pCoreIdent;
   742 
   743 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   744 		!= HandleError_None)
   745 	{
   746 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   747 	}
   748 
   749 	pCtx->LocalToString(params[2], &name);
   750 
   751 	return pStk->pCurRoot.front()->GetDataType(name);
   752 }
   753 
   754 static cell_t smn_KeyValuesToFile(IPluginContext *pCtx, const cell_t *params)
   755 {
   756 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   757 	HandleError herr;
   758 	HandleSecurity sec;
   759 	char *path;
   760 	KeyValueStack *pStk;
   761 
   762 	sec.pOwner = NULL;
   763 	sec.pIdentity = g_pCoreIdent;
   764 
   765 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   766 		!= HandleError_None)
   767 	{
   768 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   769 	}
   770 
   771 	pCtx->LocalToString(params[2], &path);
   772 
   773 	return pStk->pCurRoot.front()->SaveToFile(basefilesystem, path);
   774 }
   775 
   776 static cell_t smn_FileToKeyValues(IPluginContext *pCtx, const cell_t *params)
   777 {
   778 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   779 	HandleError herr;
   780 	HandleSecurity sec;
   781 	char *path;
   782 	KeyValueStack *pStk;
   783 	KeyValues *kv;
   784 
   785 	sec.pOwner = NULL;
   786 	sec.pIdentity = g_pCoreIdent;
   787 
   788 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   789 		!= HandleError_None)
   790 	{
   791 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   792 	}
   793 
   794 	pCtx->LocalToString(params[2], &path);
   795 
   796 	kv = pStk->pCurRoot.front();
   797 	return g_HL2.KVLoadFromFile(kv, basefilesystem, path);
   798 }
   799 
   800 static cell_t smn_KvSetEscapeSequences(IPluginContext *pCtx, const cell_t *params)
   801 {
   802 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   803 	HandleError herr;
   804 	HandleSecurity sec;
   805 	KeyValueStack *pStk;
   806 
   807 	sec.pOwner = NULL;
   808 	sec.pIdentity = g_pCoreIdent;
   809 
   810 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   811 		!= HandleError_None)
   812 	{
   813 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   814 	}
   815 
   816 	pStk->pCurRoot.front()->UsesEscapeSequences(params[2] ? true : false);
   817 
   818 	return 1;
   819 }
   820 
   821 static cell_t smn_KvNodesInStack(IPluginContext *pCtx, const cell_t *params)
   822 {
   823 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   824 	HandleError herr;
   825 	HandleSecurity sec;
   826 	KeyValueStack *pStk;
   827 
   828 	sec.pOwner = NULL;
   829 	sec.pIdentity = g_pCoreIdent;
   830 
   831 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   832 		!= HandleError_None)
   833 	{
   834 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   835 	}
   836 
   837 	return pStk->pCurRoot.size() - 1;
   838 }
   839 
   840 static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params)
   841 {
   842 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   843 	HandleError herr;
   844 	HandleSecurity sec;
   845 	KeyValueStack *pStk;
   846 
   847 	sec.pOwner = NULL;
   848 	sec.pIdentity = g_pCoreIdent;
   849 
   850 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   851 		!= HandleError_None)
   852 	{
   853 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   854 	}
   855 
   856 	if (pStk->pCurRoot.size() < 2)
   857 	{
   858 		return 0;
   859 	}
   860 
   861 	KeyValues *pValues = pStk->pCurRoot.front();
   862 	pStk->pCurRoot.pop();
   863 	KeyValues *pRoot = pStk->pCurRoot.front();
   864 
   865 	/* We have to manually verify this since Valve sucks
   866 	 * :TODO: make our own KeyValues.h file and make
   867 	 * the sub stuff private so we can do this ourselves!
   868  	 */
   869 	KeyValues *sub = pRoot->GetFirstSubKey();
   870 	while (sub)
   871 	{
   872 		if (sub == pValues)
   873 		{
   874 			KeyValues *pNext = pValues->GetNextKey();
   875 			pRoot->RemoveSubKey(pValues);
   876 			pValues->deleteThis();
   877 			if (pNext)
   878 			{
   879 				pStk->pCurRoot.push(pNext);
   880 				return 1;
   881 			} else {
   882 				return -1;
   883 			}
   884 		}
   885 		sub = sub->GetNextKey();
   886 	}
   887 
   888 	/* Push this back on :( */
   889 	pStk->pCurRoot.push(pValues);
   890 
   891 	return 0;
   892 }
   893 
   894 static cell_t smn_KvDeleteKey(IPluginContext *pContext, const cell_t *params)
   895 {
   896 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   897 	HandleError herr;
   898 	HandleSecurity sec;
   899 	KeyValueStack *pStk;
   900 
   901 	sec.pOwner = NULL;
   902 	sec.pIdentity = g_pCoreIdent;
   903 
   904 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   905 		!= HandleError_None)
   906 	{
   907 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   908 	}
   909 
   910 	if (pStk->pCurRoot.size() < 2)
   911 	{
   912 		return 0;
   913 	}
   914 
   915 	char *keyName;
   916 	pContext->LocalToString(params[2], &keyName);
   917 
   918 	KeyValues *pRoot = pStk->pCurRoot.front();
   919 	KeyValues *pValues = pRoot->FindKey(keyName);
   920 	if (!pValues)
   921 	{
   922 		return 0;
   923 	}
   924 
   925 	pRoot->RemoveSubKey(pValues);
   926 	pValues->deleteThis();
   927 
   928 	return 1;
   929 }
   930 
   931 static cell_t smn_KvSavePosition(IPluginContext *pContext, const cell_t *params)
   932 {
   933 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   934 	HandleError herr;
   935 	HandleSecurity sec;
   936 	KeyValueStack *pStk;
   937 
   938 	sec.pOwner = NULL;
   939 	sec.pIdentity = g_pCoreIdent;
   940 
   941 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   942 		!= HandleError_None)
   943 	{
   944 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   945 	}
   946 
   947 	if (pStk->pCurRoot.size() < 2)
   948 	{
   949 		return 0;
   950 	}
   951 
   952 	KeyValues *pValues = pStk->pCurRoot.front();
   953 	pStk->pCurRoot.push(pValues);
   954 
   955 	return 1;
   956 }
   957 
   958 static cell_t smn_CopySubkeys(IPluginContext *pContext, const cell_t *params)
   959 {
   960 	Handle_t hndl_copied = static_cast<Handle_t>(params[1]);
   961 	Handle_t hndl_parent = static_cast<Handle_t>(params[2]);
   962 	HandleError herr;
   963 	HandleSecurity sec;
   964 	KeyValueStack *pStk_copied, *pStk_parent;
   965 
   966 	sec.pOwner = NULL;
   967 	sec.pIdentity = g_pCoreIdent;
   968 
   969 	if ((herr=g_HandleSys.ReadHandle(hndl_copied, g_KeyValueType, &sec, (void **)&pStk_copied))
   970 		!= HandleError_None)
   971 	{
   972 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl_copied, herr);
   973 	}
   974 	if ((herr=g_HandleSys.ReadHandle(hndl_parent, g_KeyValueType, &sec, (void **)&pStk_parent))
   975 		!= HandleError_None)
   976 	{
   977 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl_parent, herr);
   978 	}
   979 
   980 	pStk_copied->pCurRoot.front()->CopySubkeys(pStk_parent->pCurRoot.front());
   981 
   982 	return 1;
   983 }
   984 
   985 static cell_t smn_GetNameSymbol(IPluginContext *pContext, const cell_t *params)
   986 {
   987 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   988 	HandleError herr;
   989 	HandleSecurity sec;
   990 	KeyValueStack *pStk;
   991 	cell_t *val;
   992 	char *key;
   993 
   994 	sec.pOwner = NULL;
   995 	sec.pIdentity = g_pCoreIdent;
   996 
   997 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   998 		!= HandleError_None)
   999 	{
  1000 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
  1001 	}
  1002 
  1003 	if (pStk->pCurRoot.size() < 2)
  1004 	{
  1005 		return 0;
  1006 	}
  1007 
  1008 	pContext->LocalToString(params[2], &key);
  1009 
  1010 	KeyValues *pKv = pStk->pCurRoot.front()->FindKey(key);
  1011 	if (!pKv)
  1012 	{
  1013 		return 0;
  1014 	}
  1015 	pContext->LocalToPhysAddr(params[3], &val);
  1016 	*val = pKv->GetNameSymbol();
  1017 
  1018 	return 1;
  1019 }
  1020 
  1021 static cell_t smn_FindKeyById(IPluginContext *pContext, const cell_t *params)
  1022 {
  1023 	Handle_t hndl = static_cast<Handle_t>(params[1]);
  1024 	HandleError herr;
  1025 	HandleSecurity sec;
  1026 	KeyValueStack *pStk;
  1027 
  1028 	sec.pOwner = NULL;
  1029 	sec.pIdentity = g_pCoreIdent;
  1030 
  1031 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
  1032 		!= HandleError_None)
  1033 	{
  1034 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
  1035 	}
  1036 
  1037 	KeyValues *pKv = pStk->pCurRoot.front()->FindKey(params[2]);
  1038 	if (!pKv)
  1039 	{
  1040 		return 0;
  1041 	}
  1042 
  1043 	pContext->StringToLocalUTF8(params[3], params[4], pKv->GetName(), NULL);
  1044 
  1045 	return 1;
  1046 }
  1047 
  1048 static cell_t smn_KvGetSectionSymbol(IPluginContext *pCtx, const cell_t *params)
  1049 {
  1050 	Handle_t hndl = static_cast<Handle_t>(params[1]);
  1051 	HandleError herr;
  1052 	HandleSecurity sec;
  1053 	KeyValueStack *pStk;
  1054 	cell_t *val;
  1055 
  1056 	sec.pOwner = NULL;
  1057 	sec.pIdentity = g_pCoreIdent;
  1058 
  1059 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
  1060 		!= HandleError_None)
  1061 	{
  1062 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
  1063 	}
  1064 
  1065 	KeyValues *pSection = pStk->pCurRoot.front();
  1066 
  1067 	pCtx->LocalToPhysAddr(params[2], &val);
  1068 	*val = pSection->GetNameSymbol();
  1069 
  1070 	if (!*val)
  1071 	{
  1072 		return 0;
  1073 	}
  1074 
  1075 	return 1;
  1076 }
  1077 
  1078 static KeyValueNatives s_KeyValueNatives;
  1079 
  1080 REGISTER_NATIVES(keyvaluenatives)
  1081 {
  1082 	{"KvSetString",				smn_KvSetString},
  1083 	{"KvSetNum",				smn_KvSetNum},
  1084 	{"KvSetUInt64",				smn_KvSetUInt64},
  1085 	{"KvSetFloat",				smn_KvSetFloat},
  1086 	{"KvSetColor",				smn_KvSetColor},
  1087 	{"KvGetString",				smn_KvGetString},
  1088 	{"KvGetNum",				smn_KvGetNum},
  1089 	{"KvGetFloat",				smn_KvGetFloat},
  1090 	{"KvGetColor",				smn_KvGetColor},
  1091 	{"KvGetUInt64",				smn_KvGetUInt64},
  1092 	{"CreateKeyValues",			smn_CreateKeyValues},
  1093 	{"KvJumpToKey",				smn_KvJumpToKey},
  1094 	{"KvJumpToKeySymbol",		smn_KvJumpToKeySymbol},
  1095 	{"KvGotoNextKey",			smn_KvGotoNextKey},
  1096 	{"KvGotoFirstSubKey",		smn_KvGotoFirstSubKey},
  1097 	{"KvGoBack",				smn_KvGoBack},
  1098 	{"KvRewind",				smn_KvRewind},
  1099 	{"KvGetSectionName",		smn_KvGetSectionName},
  1100 	{"KvSetSectionName",		smn_KvSetSectionName},
  1101 	{"KvGetDataType",			smn_KvGetDataType},
  1102 	{"KeyValuesToFile",			smn_KeyValuesToFile},
  1103 	{"FileToKeyValues",			smn_FileToKeyValues},
  1104 	{"KvSetEscapeSequences",	smn_KvSetEscapeSequences},
  1105 	{"KvDeleteThis",			smn_KvDeleteThis},
  1106 	{"KvDeleteKey",				smn_KvDeleteKey},
  1107 	{"KvNodesInStack",			smn_KvNodesInStack},
  1108 	{"KvSavePosition",			smn_KvSavePosition},
  1109 	{"KvCopySubkeys",			smn_CopySubkeys},
  1110 	{"KvFindKeyById",			smn_FindKeyById},
  1111 	{"KvGetNameSymbol",			smn_GetNameSymbol},
  1112 	{"KvGetSectionSymbol",		smn_KvGetSectionSymbol},
  1113 	{"KvGetVector",				smn_KvGetVector},
  1114 	{"KvSetVector",				smn_KvSetVector},
  1115 	{NULL,						NULL}
  1116 };