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