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