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