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