core/smn_keyvalues.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 06 22:31:54 2007 +0000 (2007-06-06)
changeset 896 e30eef2642ba
parent 816 f5551f32680b
child 1000 aefbd36eaf91
permissions -rw-r--r--
added config options for chat triggers
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include "sourcemod.h"
    16 #include "sourcemm_api.h"
    17 #include "sm_stringutil.h"
    18 #include "HandleSys.h"
    19 #include <KeyValues.h>
    20 
    21 HandleType_t g_KeyValueType;
    22 
    23 struct KeyValueStack 
    24 {
    25 	KeyValues *pBase;
    26 	CStack<KeyValues *> pCurRoot;
    27 };
    28 
    29 class KeyValueNatives : 
    30 	public SMGlobalClass,
    31 	public IHandleTypeDispatch
    32 {
    33 public:
    34 	void OnSourceModAllInitialized()
    35 	{
    36 		g_KeyValueType = g_HandleSys.CreateType("KeyValues", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    37 	}
    38 	void OnSourceModShutdown()
    39 	{
    40 		g_HandleSys.RemoveType(g_KeyValueType, g_pCoreIdent);
    41 		g_KeyValueType = 0;
    42 	}
    43 	void OnHandleDestroy(HandleType_t type, void *object)
    44 	{
    45 		KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
    46 		pStk->pBase->deleteThis();
    47 		delete pStk;
    48 	}
    49 };
    50 
    51 KeyValues *SourceModBase::ReadKeyValuesHandle(Handle_t hndl, HandleError *err, bool root)
    52 {
    53 	HandleError herr;
    54 	HandleSecurity sec;
    55 	KeyValueStack *pStk;
    56 
    57 	sec.pOwner = NULL;
    58 	sec.pIdentity = g_pCoreIdent;
    59 
    60 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
    61 		!= HandleError_None)
    62 	{
    63 		if (err)
    64 		{
    65 			*err = herr;
    66 		}
    67 		return NULL;
    68 	}
    69 
    70 	if (err)
    71 	{
    72 		*err = HandleError_None;
    73 	}
    74 
    75 	return (root) ? pStk->pBase : pStk->pCurRoot.front();
    76 }
    77 
    78 static cell_t smn_KvSetString(IPluginContext *pCtx, const cell_t *params)
    79 {
    80 	Handle_t hndl = static_cast<Handle_t>(params[1]);
    81 	HandleError herr;
    82 	HandleSecurity sec;
    83 	KeyValueStack *pStk;
    84 
    85 	sec.pOwner = NULL;
    86 	sec.pIdentity = g_pCoreIdent;
    87 
    88 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
    89 		!= HandleError_None)
    90 	{
    91 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
    92 	}
    93 
    94 	char *key, *value;
    95 	pCtx->LocalToString(params[2], &key);
    96 	pCtx->LocalToString(params[3], &value);
    97 
    98 	pStk->pCurRoot.front()->SetString(key, value);
    99 
   100 	return 1;
   101 }
   102 
   103 static cell_t smn_KvSetNum(IPluginContext *pCtx, const cell_t *params)
   104 {
   105 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   106 	HandleError herr;
   107 	HandleSecurity sec;
   108 	KeyValueStack *pStk;
   109 
   110 	sec.pOwner = NULL;
   111 	sec.pIdentity = g_pCoreIdent;
   112 
   113 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   114 		!= HandleError_None)
   115 	{
   116 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   117 	}
   118 
   119 	char *key;
   120 	pCtx->LocalToString(params[2], &key);
   121 
   122 	pStk->pCurRoot.front()->SetInt(key, params[3]);
   123 
   124 	return 1;
   125 }
   126 
   127 static cell_t smn_KvSetUInt64(IPluginContext *pCtx, const cell_t *params)
   128 {
   129 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   130 	HandleError herr;
   131 	HandleSecurity sec;
   132 	KeyValueStack *pStk;
   133 
   134 	sec.pOwner = NULL;
   135 	sec.pIdentity = g_pCoreIdent;
   136 
   137 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   138 		!= HandleError_None)
   139 	{
   140 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   141 	}
   142 
   143 	char *key;
   144 	cell_t *addr;
   145 	uint64 value;
   146 	pCtx->LocalToString(params[2], &key);
   147 	pCtx->LocalToPhysAddr(params[3], &addr);
   148 
   149 	value = static_cast<uint64>(*addr);
   150 	pStk->pCurRoot.front()->SetUint64(key, value);
   151 
   152 	return 1;
   153 }
   154 
   155 static cell_t smn_KvSetFloat(IPluginContext *pCtx, const cell_t *params)
   156 {
   157 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   158 	HandleError herr;
   159 	HandleSecurity sec;
   160 	KeyValueStack *pStk;
   161 
   162 	sec.pOwner = NULL;
   163 	sec.pIdentity = g_pCoreIdent;
   164 
   165 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   166 		!= HandleError_None)
   167 	{
   168 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   169 	}
   170 
   171 	char *key;
   172 	pCtx->LocalToString(params[2], &key);
   173 
   174 	pStk->pCurRoot.front()->SetFloat(key, sp_ctof(params[3]));
   175 
   176 	return 1;
   177 }
   178 
   179 static cell_t smn_KvSetColor(IPluginContext *pCtx, const cell_t *params)
   180 {
   181 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   182 	HandleError herr;
   183 	HandleSecurity sec;
   184 	KeyValueStack *pStk;
   185 
   186 	sec.pOwner = NULL;
   187 	sec.pIdentity = g_pCoreIdent;
   188 
   189 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   190 		!= HandleError_None)
   191 	{
   192 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   193 	}
   194 
   195 	char *key;
   196 	pCtx->LocalToString(params[2], &key);
   197 
   198 	Color color(params[3], params[4], params[5], params[6]);
   199 	pStk->pCurRoot.front()->SetColor(key, color);
   200 
   201 	return 1;
   202 }
   203 
   204 static cell_t smn_KvGetString(IPluginContext *pCtx, const cell_t *params)
   205 {
   206 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   207 	HandleError herr;
   208 	HandleSecurity sec;
   209 	KeyValueStack *pStk;
   210 
   211 	sec.pOwner = NULL;
   212 	sec.pIdentity = g_pCoreIdent;
   213 
   214 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   215 		!= HandleError_None)
   216 	{
   217 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   218 	}
   219 
   220 	const char *value;
   221 	char *key, *defvalue;
   222 	pCtx->LocalToString(params[2], &key);
   223 	pCtx->LocalToString(params[5], &defvalue);
   224 
   225 	value = pStk->pCurRoot.front()->GetString(key, defvalue);
   226 	pCtx->StringToLocalUTF8(params[3], params[4], value, NULL);
   227 
   228 	return 1;
   229 }
   230 
   231 static cell_t smn_KvGetNum(IPluginContext *pCtx, const cell_t *params)
   232 {
   233 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   234 	HandleError herr;
   235 	HandleSecurity sec;
   236 	KeyValueStack *pStk;
   237 
   238 	sec.pOwner = NULL;
   239 	sec.pIdentity = g_pCoreIdent;
   240 
   241 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   242 		!= HandleError_None)
   243 	{
   244 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   245 	}
   246 
   247 	int value;
   248 	char *key;
   249 	pCtx->LocalToString(params[2], &key);
   250 
   251 	value = pStk->pCurRoot.front()->GetInt(key, params[3]);
   252 
   253 	return value;
   254 }
   255 
   256 static cell_t smn_KvGetFloat(IPluginContext *pCtx, const cell_t *params)
   257 {
   258 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   259 	HandleError herr;
   260 	HandleSecurity sec;
   261 	KeyValueStack *pStk;
   262 
   263 	sec.pOwner = NULL;
   264 	sec.pIdentity = g_pCoreIdent;
   265 
   266 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   267 		!= HandleError_None)
   268 	{
   269 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   270 	}
   271 
   272 	float value;
   273 	char *key;
   274 	pCtx->LocalToString(params[2], &key);
   275 
   276 	value = pStk->pCurRoot.front()->GetFloat(key, sp_ctof(params[3]));
   277 
   278 	return sp_ftoc(value);
   279 }
   280 
   281 static cell_t smn_KvGetColor(IPluginContext *pCtx, const cell_t *params)
   282 {
   283 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   284 	HandleError herr;
   285 	HandleSecurity sec;
   286 	KeyValueStack *pStk;
   287 
   288 	sec.pOwner = NULL;
   289 	sec.pIdentity = g_pCoreIdent;
   290 
   291 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   292 		!= HandleError_None)
   293 	{
   294 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   295 	}
   296 
   297 	Color color;
   298 	char *key;
   299 	cell_t *r, *g, *b, *a;
   300 	pCtx->LocalToString(params[2], &key);
   301 	pCtx->LocalToPhysAddr(params[3], &r);
   302 	pCtx->LocalToPhysAddr(params[4], &g);
   303 	pCtx->LocalToPhysAddr(params[5], &b);
   304 	pCtx->LocalToPhysAddr(params[6], &a);
   305 
   306 	color = pStk->pCurRoot.front()->GetColor(key);
   307 	*r = color.r();
   308 	*g = color.g();
   309 	*b = color.b();
   310 	*a = color.a();
   311 
   312 	return 1;
   313 }
   314 
   315 static cell_t smn_KvGetUInt64(IPluginContext *pCtx, const cell_t *params)
   316 {
   317 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   318 	HandleError herr;
   319 	HandleSecurity sec;
   320 	KeyValueStack *pStk;
   321 
   322 	sec.pOwner = NULL;
   323 	sec.pIdentity = g_pCoreIdent;
   324 
   325 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   326 		!= HandleError_None)
   327 	{
   328 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   329 	}
   330 
   331 	char *key;
   332 	cell_t *addr, *defvalue;
   333 	uint64 value;
   334 	pCtx->LocalToString(params[2], &key);
   335 	pCtx->LocalToPhysAddr(params[3], &addr);
   336 	pCtx->LocalToPhysAddr(params[4], &defvalue);
   337 
   338 	value = pStk->pCurRoot.front()->GetUint64(key, static_cast<uint64>(*defvalue));
   339 	*reinterpret_cast<uint64 *>(addr) = value;
   340 
   341 	return 1;
   342 }
   343 
   344 static cell_t smn_CreateKeyValues(IPluginContext *pCtx, const cell_t *params)
   345 {
   346 	KeyValueStack *pStk;
   347 	char *name, *firstkey, *firstvalue;
   348 	bool is_empty;
   349 
   350 	pCtx->LocalToString(params[1], &name);
   351 	pCtx->LocalToString(params[2], &firstkey);
   352 	pCtx->LocalToString(params[3], &firstvalue);
   353 
   354 	is_empty = (firstkey[0] == '\0');
   355 	pStk = new KeyValueStack;
   356 	pStk->pBase = new KeyValues(name, is_empty ? NULL : firstkey, (is_empty||(firstvalue[0]=='\0')) ? NULL : firstvalue);
   357 	pStk->pCurRoot.push(pStk->pBase);
   358 
   359 	return g_HandleSys.CreateHandle(g_KeyValueType, pStk, pCtx->GetIdentity(), g_pCoreIdent, NULL);
   360 }
   361 
   362 static cell_t smn_KvJumpToKey(IPluginContext *pCtx, const cell_t *params)
   363 {
   364 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   365 	HandleError herr;
   366 	HandleSecurity sec;
   367 	char *name;	
   368 	KeyValueStack *pStk;
   369 
   370 	sec.pOwner = NULL;
   371 	sec.pIdentity = g_pCoreIdent;
   372 
   373 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   374 		!= HandleError_None)
   375 	{
   376 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   377 	}
   378 
   379 	pCtx->LocalToString(params[2], &name);
   380 
   381 	KeyValues *pSubKey = pStk->pCurRoot.front();
   382 	pSubKey = pSubKey->FindKey(name, (params[3]) ? true : false);
   383 	if (!pSubKey)
   384 	{
   385 		return 0;
   386 	}
   387 	pStk->pCurRoot.push(pSubKey);
   388 
   389 	return 1;
   390 }
   391 
   392 static cell_t smn_KvGotoFirstSubKey(IPluginContext *pCtx, const cell_t *params)
   393 {
   394 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   395 	HandleError herr;
   396 	HandleSecurity sec;
   397 	KeyValueStack *pStk;
   398 
   399 	sec.pOwner = NULL;
   400 	sec.pIdentity = g_pCoreIdent;
   401 
   402 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   403 		!= HandleError_None)
   404 	{
   405 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   406 	}
   407 
   408 	KeyValues *pSubKey = pStk->pCurRoot.front();
   409 	KeyValues *pFirstSubKey;
   410 	if (params[2])
   411 	{
   412 		pFirstSubKey = pSubKey->GetFirstTrueSubKey();
   413 	} else {
   414 		pFirstSubKey = pSubKey->GetFirstSubKey();
   415 	}
   416 
   417 	if (!pFirstSubKey)
   418 	{
   419 		return 0;
   420 	}
   421 	pStk->pCurRoot.push(pFirstSubKey);
   422 
   423 	return 1;
   424 }
   425 
   426 static cell_t smn_KvGotoNextKey(IPluginContext *pCtx, const cell_t *params)
   427 {
   428 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   429 	HandleError herr;
   430 	HandleSecurity sec;
   431 	KeyValueStack *pStk;
   432 
   433 	sec.pOwner = NULL;
   434 	sec.pIdentity = g_pCoreIdent;
   435 
   436 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   437 		!= HandleError_None)
   438 	{
   439 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   440 	}
   441 
   442 	KeyValues *pSubKey = pStk->pCurRoot.front();
   443 	if (params[2])
   444 	{
   445 		pSubKey = pSubKey->GetNextKey();
   446 	} else {
   447 		pSubKey = pSubKey->GetNextTrueSubKey();
   448 	}
   449 	if (!pSubKey)
   450 	{
   451 		return 0;
   452 	}
   453 	pStk->pCurRoot.pop();
   454 	pStk->pCurRoot.push(pSubKey);
   455 
   456 	return 1;	
   457 }
   458 
   459 static cell_t smn_KvJumpNextSubKey(IPluginContext *pCtx, const cell_t *params)
   460 {
   461 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   462 	HandleError herr;
   463 	HandleSecurity sec;
   464 	KeyValueStack *pStk;
   465 
   466 	sec.pOwner = NULL;
   467 	sec.pIdentity = g_pCoreIdent;
   468 
   469 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   470 		!= HandleError_None)
   471 	{
   472 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   473 	}
   474 
   475 	KeyValues *pSubKey = pStk->pCurRoot.front();
   476 	KeyValues *pNextKey = pSubKey->GetNextKey();
   477 	if (!pNextKey)
   478 	{
   479 		return 0;
   480 	}
   481 	pStk->pCurRoot.push(pNextKey);
   482 
   483 	return 1;	
   484 }
   485 
   486 static cell_t smn_KvGoBack(IPluginContext *pCtx, const cell_t *params)
   487 {
   488 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   489 	HandleError herr;
   490 	HandleSecurity sec;
   491 	KeyValueStack *pStk;
   492 
   493 	sec.pOwner = NULL;
   494 	sec.pIdentity = g_pCoreIdent;
   495 
   496 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   497 		!= HandleError_None)
   498 	{
   499 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   500 	}
   501 
   502 	if (pStk->pCurRoot.size() == 1)
   503 	{
   504 		return 0;
   505 	}
   506 	pStk->pCurRoot.pop();
   507 
   508 	return 1;
   509 }
   510 
   511 static cell_t smn_KvRewind(IPluginContext *pCtx, const cell_t *params)
   512 {
   513 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   514 	HandleError herr;
   515 	HandleSecurity sec;
   516 	KeyValueStack *pStk;
   517 
   518 	sec.pOwner = NULL;
   519 	sec.pIdentity = g_pCoreIdent;
   520 
   521 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   522 		!= HandleError_None)
   523 	{
   524 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   525 	}
   526 
   527 	while (pStk->pCurRoot.size() > 1)
   528 	{
   529 		pStk->pCurRoot.pop();
   530 	}
   531 
   532 	return 1;
   533 }
   534 
   535 static cell_t smn_KvGetSectionName(IPluginContext *pCtx, const cell_t *params)
   536 {
   537 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   538 	HandleError herr;
   539 	HandleSecurity sec;
   540 	KeyValueStack *pStk;
   541 
   542 	sec.pOwner = NULL;
   543 	sec.pIdentity = g_pCoreIdent;
   544 
   545 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   546 		!= HandleError_None)
   547 	{
   548 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   549 	}
   550 
   551 	KeyValues *pSection = pStk->pCurRoot.front();
   552 	const char *name = pSection->GetName();
   553 	if (!name)
   554 	{
   555 		return 0;
   556 	}
   557 	pCtx->StringToLocalUTF8(params[2], params[3], name, NULL);
   558 
   559 	return 1;
   560 }
   561 
   562 static cell_t smn_KvSetSectionName(IPluginContext *pCtx, const cell_t *params)
   563 {
   564 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   565 	HandleError herr;
   566 	HandleSecurity sec;
   567 	char *name;
   568 	KeyValueStack *pStk;
   569 
   570 	sec.pOwner = NULL;
   571 	sec.pIdentity = g_pCoreIdent;
   572 
   573 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   574 		!= HandleError_None)
   575 	{
   576 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   577 	}
   578 
   579 	pCtx->LocalToString(params[2], &name);
   580 
   581 	KeyValues *pSection = pStk->pCurRoot.front();
   582 	pSection->SetName(name);
   583 
   584 	return 1;
   585 }
   586 
   587 static cell_t smn_KvGetDataType(IPluginContext *pCtx, const cell_t *params)
   588 {
   589 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   590 	HandleError herr;
   591 	HandleSecurity sec;
   592 	char *name;
   593 	KeyValueStack *pStk;
   594 
   595 	sec.pOwner = NULL;
   596 	sec.pIdentity = g_pCoreIdent;
   597 
   598 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   599 		!= HandleError_None)
   600 	{
   601 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   602 	}
   603 
   604 	pCtx->LocalToString(params[2], &name);
   605 
   606 	return pStk->pCurRoot.front()->GetDataType(name);
   607 }
   608 
   609 static cell_t smn_KeyValuesToFile(IPluginContext *pCtx, const cell_t *params)
   610 {
   611 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   612 	HandleError herr;
   613 	HandleSecurity sec;
   614 	char *path;
   615 	KeyValueStack *pStk;
   616 
   617 	sec.pOwner = NULL;
   618 	sec.pIdentity = g_pCoreIdent;
   619 
   620 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   621 		!= HandleError_None)
   622 	{
   623 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   624 	}
   625 
   626 	pCtx->LocalToString(params[2], &path);
   627 
   628 	char realpath[PLATFORM_MAX_PATH];
   629 	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
   630 
   631 	return pStk->pCurRoot.front()->SaveToFile(basefilesystem, realpath);
   632 }
   633 
   634 static cell_t smn_FileToKeyValues(IPluginContext *pCtx, const cell_t *params)
   635 {
   636 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   637 	HandleError herr;
   638 	HandleSecurity sec;
   639 	char *path;
   640 	KeyValueStack *pStk;
   641 
   642 	sec.pOwner = NULL;
   643 	sec.pIdentity = g_pCoreIdent;
   644 
   645 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   646 		!= HandleError_None)
   647 	{
   648 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   649 	}
   650 
   651 	pCtx->LocalToString(params[2], &path);
   652 
   653 	char realpath[PLATFORM_MAX_PATH];
   654 	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
   655 
   656 	return pStk->pCurRoot.front()->LoadFromFile(basefilesystem, realpath);
   657 }
   658 
   659 static cell_t smn_KvSetEscapeSequences(IPluginContext *pCtx, const cell_t *params)
   660 {
   661 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   662 	HandleError herr;
   663 	HandleSecurity sec;
   664 	KeyValueStack *pStk;
   665 
   666 	sec.pOwner = NULL;
   667 	sec.pIdentity = g_pCoreIdent;
   668 
   669 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   670 		!= HandleError_None)
   671 	{
   672 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   673 	}
   674 
   675 	pStk->pCurRoot.front()->UsesEscapeSequences(params[2] ? true : false);
   676 
   677 	return 1;
   678 }
   679 
   680 static cell_t smn_KvNodesInStack(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 	return pStk->pCurRoot.size() - 1;
   697 }
   698 
   699 static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params)
   700 {
   701 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   702 	HandleError herr;
   703 	HandleSecurity sec;
   704 	KeyValueStack *pStk;
   705 
   706 	sec.pOwner = NULL;
   707 	sec.pIdentity = g_pCoreIdent;
   708 
   709 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   710 		!= HandleError_None)
   711 	{
   712 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   713 	}
   714 
   715 	if (pStk->pCurRoot.size() < 2)
   716 	{
   717 		return 0;
   718 	}
   719 
   720 	KeyValues *pValues = pStk->pCurRoot.front();
   721 	pStk->pCurRoot.pop();
   722 	KeyValues *pRoot = pStk->pCurRoot.front();
   723 
   724 	/* We have to manually verify this since Valve sucks
   725 	 * :TODO: make our own KeyValues.h file and make
   726 	 * the sub stuff private so we can do this ourselves!
   727  	 */
   728 	KeyValues *sub = pRoot->GetFirstSubKey();
   729 	while (sub)
   730 	{
   731 		if (sub == pValues)
   732 		{
   733 			KeyValues *pNext = pValues->GetNextKey();
   734 			pRoot->RemoveSubKey(pValues);
   735 			pValues->deleteThis();
   736 			if (pNext)
   737 			{
   738 				pStk->pCurRoot.push(pNext);
   739 				return 1;
   740 			} else {
   741 				return -1;
   742 			}
   743 		}
   744 		sub = sub->GetNextKey();
   745 	}
   746 
   747 	/* Push this back on :( */
   748 	pStk->pCurRoot.push(pValues);
   749 
   750 	return 0;
   751 }
   752 
   753 static cell_t smn_KvDeleteKey(IPluginContext *pContext, const cell_t *params)
   754 {
   755 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   756 	HandleError herr;
   757 	HandleSecurity sec;
   758 	KeyValueStack *pStk;
   759 
   760 	sec.pOwner = NULL;
   761 	sec.pIdentity = g_pCoreIdent;
   762 
   763 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   764 		!= HandleError_None)
   765 	{
   766 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   767 	}
   768 
   769 	if (pStk->pCurRoot.size() < 2)
   770 	{
   771 		return 0;
   772 	}
   773 
   774 	char *keyName;
   775 	pContext->LocalToString(params[2], &keyName);
   776 
   777 	KeyValues *pRoot = pStk->pCurRoot.front();
   778 	KeyValues *pValues = pRoot->FindKey(keyName);
   779 	if (!pValues)
   780 	{
   781 		return 0;
   782 	}
   783 
   784 	pRoot->RemoveSubKey(pValues);
   785 	pValues->deleteThis();
   786 
   787 	return 1;
   788 }
   789 
   790 static cell_t smn_KvSavePosition(IPluginContext *pContext, const cell_t *params)
   791 {
   792 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   793 	HandleError herr;
   794 	HandleSecurity sec;
   795 	KeyValueStack *pStk;
   796 
   797 	sec.pOwner = NULL;
   798 	sec.pIdentity = g_pCoreIdent;
   799 
   800 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   801 		!= HandleError_None)
   802 	{
   803 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   804 	}
   805 
   806 	if (pStk->pCurRoot.size() < 2)
   807 	{
   808 		return 0;
   809 	}
   810 
   811 	KeyValues *pValues = pStk->pCurRoot.front();
   812 	pStk->pCurRoot.push(pValues);
   813 
   814 	return 1;
   815 }
   816 
   817 static KeyValueNatives s_KeyValueNatives;
   818 
   819 REGISTER_NATIVES(keyvaluenatives)
   820 {
   821 	{"KvSetString",				smn_KvSetString},
   822 	{"KvSetNum",				smn_KvSetNum},
   823 	{"KvSetUInt64",				smn_KvSetUInt64},
   824 	{"KvSetFloat",				smn_KvSetFloat},
   825 	{"KvSetColor",				smn_KvSetColor},
   826 	{"KvGetString",				smn_KvGetString},
   827 	{"KvGetNum",				smn_KvGetNum},
   828 	{"KvGetFloat",				smn_KvGetFloat},
   829 	{"KvGetColor",				smn_KvGetColor},
   830 	{"KvGetUInt64",				smn_KvGetUInt64},
   831 	{"CreateKeyValues",			smn_CreateKeyValues},
   832 	{"KvJumpToKey",				smn_KvJumpToKey},
   833 	{"KvGotoNextKey",			smn_KvGotoNextKey},
   834 	{"KvJumpFirstSubKey",		smn_KvGotoFirstSubKey},		/* BACKWARDS COMPAT SHIM */
   835 	{"KvGotoFirstSubKey",		smn_KvGotoFirstSubKey},
   836 	{"KvJumpNextSubKey",		smn_KvJumpNextSubKey},		/* BACKWARDS COMPAT SHIM */
   837 	{"KvGoBack",				smn_KvGoBack},
   838 	{"KvRewind",				smn_KvRewind},
   839 	{"KvGetSectionName",		smn_KvGetSectionName},
   840 	{"KvSetSectionName",		smn_KvSetSectionName},
   841 	{"KvGetDataType",			smn_KvGetDataType},
   842 	{"KeyValuesToFile",			smn_KeyValuesToFile},
   843 	{"FileToKeyValues",			smn_FileToKeyValues},
   844 	{"KvSetEscapeSequences",	smn_KvSetEscapeSequences},
   845 	{"KvDeleteThis",			smn_KvDeleteThis},
   846 	{"KvDeleteKey",				smn_KvDeleteKey},
   847 	{"KvNodesInStack",			smn_KvNodesInStack},
   848 	{"KvSavePosition",			smn_KvSavePosition},
   849 	{NULL,						NULL}
   850 };