Merge.
3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sourcemod.h"
33 #include "sourcemm_api.h"
34 #include "sm_stringutil.h"
35 #include "HandleSys.h"
36 #include "HalfLife2.h"
37 #include <KeyValues.h>
38 #include "utlbuffer.h"
40 HandleType_t g_KeyValueType;
45 CStack<KeyValues *> pCurRoot;
48 class KeyValueNatives :
50 public IHandleTypeDispatch
53 void OnSourceModAllInitialized()
55 g_KeyValueType = g_HandleSys.CreateType("KeyValues", this, 0, NULL, NULL, g_pCoreIdent, NULL);
57 void OnSourceModShutdown()
59 g_HandleSys.RemoveType(g_KeyValueType, g_pCoreIdent);
62 void OnHandleDestroy(HandleType_t type, void *object)
64 KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
65 pStk->pBase->deleteThis();
68 int CalcKVSizeR(KeyValues *pv)
73 pv->RecursiveSaveToFile(buf, 0);
74 size = buf.TellMaxPut();
80 bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
82 KeyValueStack *pStk = (KeyValueStack *)object;
83 unsigned int size = sizeof(KeyValueStack) + (pStk->pCurRoot.size() * sizeof(KeyValues *));
85 /* Check how much memory the actual thing takes up */
86 size += CalcKVSizeR(pStk->pBase);
94 /* From MM:S - metamod_util.cpp */
95 inline bool pathchar_isalpha(char a)
97 return (((a & 1<<7) == 0) && isalpha(a));
100 inline bool pathchar_sep(char a)
103 return (a == '/' || a == '\\');
104 #elif defined __linux__
109 inline bool pathstr_isabsolute(const char *str)
112 return (pathchar_isalpha(str[0])
114 && pathchar_sep(str[2]));
115 #elif defined __linux__
116 return (str[0] == '/');
120 inline bool pathchar_cmp(char a, char b)
122 #if defined PLATFORM_WINDOWS
123 if (pathchar_isalpha(a) && pathchar_isalpha(b))
125 return (tolower(a) == tolower(b));
127 /* Either path separator is acceptable */
130 return pathchar_sep(b);
136 bool UTIL_Relatize(char buffer[],
141 /* We don't allow relative paths in here, force
142 * the user to resolve these himself!
144 if (!pathstr_isabsolute(relTo)
145 || !pathstr_isabsolute(relFrom))
150 #if defined PLATFORM_WINDOWS
151 /* Relative paths across drives are not possible */
152 if (!pathchar_cmp(relTo[0], relFrom[0]))
156 /* Get rid of the drive and semicolon part */
158 relFrom = &relFrom[2];
161 /* Eliminate the common root between the paths */
162 const char *rootTo = NULL;
163 const char *rootFrom = NULL;
164 while (*relTo != '\0' && *relFrom != '\0')
166 /* If we get to a new path sequence, start over */
167 if (pathchar_sep(*relTo)
168 && pathchar_sep(*relFrom))
172 /* If the paths don't compare, stop looking for a common root */
173 } else if (!pathchar_cmp(*relTo, *relFrom)) {
180 /* NULLs shouldn't happen! */
187 size_t numLevels = 0;
189 /* The root case is special!
190 * Don't count anything from it.
192 if (*(rootTo + 1) != '\0')
194 /* Search for how many levels we need to go up.
195 * Since the root pointer points to a '/', we increment
196 * the initial pointer by one.
198 while (*rootTo != '\0')
200 if (pathchar_sep(*rootTo))
202 /* Check for an improper trailing slash,
203 * just to be nice even though the user
204 * should NOT have done this!
206 if (*(rootTo + 1) == '\0')
216 /* Now build the new relative path. */
217 size_t len, total = 0;
220 len = _snprintf(&buffer[total], maxlength - total, ".." PLATFORM_SEP_STR);
221 if (len >= maxlength - total)
223 /* Not enough space in the buffer */
229 /* Add the absolute path. */
230 len = _snprintf(&buffer[total], maxlength - total, "%s", &rootFrom[1]);
231 if (len >= maxlength - total)
239 KeyValues *SourceModBase::ReadKeyValuesHandle(Handle_t hndl, HandleError *err, bool root)
246 sec.pIdentity = g_pCoreIdent;
248 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
260 *err = HandleError_None;
263 return (root) ? pStk->pBase : pStk->pCurRoot.front();
266 static cell_t smn_KvSetString(IPluginContext *pCtx, const cell_t *params)
268 Handle_t hndl = static_cast<Handle_t>(params[1]);
274 sec.pIdentity = g_pCoreIdent;
276 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
279 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
283 pCtx->LocalToStringNULL(params[2], &key);
284 pCtx->LocalToString(params[3], &value);
286 pStk->pCurRoot.front()->SetString(key, value);
291 static cell_t smn_KvSetNum(IPluginContext *pCtx, const cell_t *params)
293 Handle_t hndl = static_cast<Handle_t>(params[1]);
299 sec.pIdentity = g_pCoreIdent;
301 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
304 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
308 pCtx->LocalToStringNULL(params[2], &key);
310 pStk->pCurRoot.front()->SetInt(key, params[3]);
315 static cell_t smn_KvSetUInt64(IPluginContext *pCtx, const cell_t *params)
317 Handle_t hndl = static_cast<Handle_t>(params[1]);
323 sec.pIdentity = g_pCoreIdent;
325 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
328 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
334 pCtx->LocalToStringNULL(params[2], &key);
335 pCtx->LocalToPhysAddr(params[3], &addr);
337 value = static_cast<uint64>(*addr);
338 pStk->pCurRoot.front()->SetUint64(key, value);
343 static cell_t smn_KvSetFloat(IPluginContext *pCtx, const cell_t *params)
345 Handle_t hndl = static_cast<Handle_t>(params[1]);
351 sec.pIdentity = g_pCoreIdent;
353 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
356 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
360 pCtx->LocalToStringNULL(params[2], &key);
362 pStk->pCurRoot.front()->SetFloat(key, sp_ctof(params[3]));
367 static cell_t smn_KvSetColor(IPluginContext *pCtx, const cell_t *params)
369 Handle_t hndl = static_cast<Handle_t>(params[1]);
375 sec.pIdentity = g_pCoreIdent;
377 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
380 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
384 pCtx->LocalToStringNULL(params[2], &key);
386 Color color(params[3], params[4], params[5], params[6]);
387 pStk->pCurRoot.front()->SetColor(key, color);
392 static cell_t smn_KvSetVector(IPluginContext *pCtx, const cell_t *params)
394 Handle_t hndl = static_cast<Handle_t>(params[1]);
400 sec.pIdentity = g_pCoreIdent;
402 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
405 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
411 pCtx->LocalToStringNULL(params[2], &key);
412 pCtx->LocalToPhysAddr(params[3], &vector);
414 UTIL_Format(buffer, sizeof(buffer), "%f %f %f", sp_ctof(vector[0]), sp_ctof(vector[1]), sp_ctof(vector[2]));
416 pStk->pCurRoot.front()->SetString(key, buffer);
421 static cell_t smn_KvGetString(IPluginContext *pCtx, const cell_t *params)
423 Handle_t hndl = static_cast<Handle_t>(params[1]);
429 sec.pIdentity = g_pCoreIdent;
431 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
434 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
438 char *key, *defvalue;
439 pCtx->LocalToStringNULL(params[2], &key);
440 pCtx->LocalToString(params[5], &defvalue);
442 value = pStk->pCurRoot.front()->GetString(key, defvalue);
443 pCtx->StringToLocalUTF8(params[3], params[4], value, NULL);
448 static cell_t smn_KvGetNum(IPluginContext *pCtx, const cell_t *params)
450 Handle_t hndl = static_cast<Handle_t>(params[1]);
456 sec.pIdentity = g_pCoreIdent;
458 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
461 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
466 pCtx->LocalToStringNULL(params[2], &key);
468 value = pStk->pCurRoot.front()->GetInt(key, params[3]);
473 static cell_t smn_KvGetFloat(IPluginContext *pCtx, const cell_t *params)
475 Handle_t hndl = static_cast<Handle_t>(params[1]);
481 sec.pIdentity = g_pCoreIdent;
483 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
486 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
491 pCtx->LocalToStringNULL(params[2], &key);
493 value = pStk->pCurRoot.front()->GetFloat(key, sp_ctof(params[3]));
495 return sp_ftoc(value);
498 static cell_t smn_KvGetColor(IPluginContext *pCtx, const cell_t *params)
500 Handle_t hndl = static_cast<Handle_t>(params[1]);
506 sec.pIdentity = g_pCoreIdent;
508 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
511 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
516 cell_t *r, *g, *b, *a;
517 pCtx->LocalToStringNULL(params[2], &key);
518 pCtx->LocalToPhysAddr(params[3], &r);
519 pCtx->LocalToPhysAddr(params[4], &g);
520 pCtx->LocalToPhysAddr(params[5], &b);
521 pCtx->LocalToPhysAddr(params[6], &a);
523 color = pStk->pCurRoot.front()->GetColor(key);
532 static cell_t smn_KvGetUInt64(IPluginContext *pCtx, const cell_t *params)
534 Handle_t hndl = static_cast<Handle_t>(params[1]);
540 sec.pIdentity = g_pCoreIdent;
542 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
545 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
549 cell_t *addr, *defvalue;
551 pCtx->LocalToStringNULL(params[2], &key);
552 pCtx->LocalToPhysAddr(params[3], &addr);
553 pCtx->LocalToPhysAddr(params[4], &defvalue);
555 value = pStk->pCurRoot.front()->GetUint64(key, static_cast<uint64>(*defvalue));
556 *reinterpret_cast<uint64 *>(addr) = value;
561 static cell_t smn_KvGetVector(IPluginContext *pCtx, const cell_t *params)
563 Handle_t hndl = static_cast<Handle_t>(params[1]);
569 sec.pIdentity = g_pCoreIdent;
571 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
574 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
579 cell_t *defvector, *outvector;
581 pCtx->LocalToStringNULL(params[2], &key);
582 pCtx->LocalToPhysAddr(params[3], &outvector);
583 pCtx->LocalToPhysAddr(params[4], &defvector);
585 UTIL_Format(buffer, sizeof(buffer), "%f %f %f", sp_ctof(defvector[0]), sp_ctof(defvector[1]), sp_ctof(defvector[2]));
587 value = pStk->pCurRoot.front()->GetString(key, buffer);
591 while (*value && components < 3)
593 while ((*value) && (*value == ' '))
610 for (; *value && isdigit(*value); ++value)
620 for (; *value && isdigit(*value); ++value)
622 out += (*value - '0') * factor;
627 out = (isnegative) ? -out : out;
628 outvector[components++] = sp_ftoc(out);
634 static cell_t smn_CreateKeyValues(IPluginContext *pCtx, const cell_t *params)
637 char *name, *firstkey, *firstvalue;
640 pCtx->LocalToString(params[1], &name);
641 pCtx->LocalToString(params[2], &firstkey);
642 pCtx->LocalToString(params[3], &firstvalue);
644 is_empty = (firstkey[0] == '\0');
645 pStk = new KeyValueStack;
646 pStk->pBase = new KeyValues(name, is_empty ? NULL : firstkey, (is_empty||(firstvalue[0]=='\0')) ? NULL : firstvalue);
647 pStk->pCurRoot.push(pStk->pBase);
649 return g_HandleSys.CreateHandle(g_KeyValueType, pStk, pCtx->GetIdentity(), g_pCoreIdent, NULL);
652 static cell_t smn_KvJumpToKey(IPluginContext *pCtx, const cell_t *params)
654 Handle_t hndl = static_cast<Handle_t>(params[1]);
661 sec.pIdentity = g_pCoreIdent;
663 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
666 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
669 pCtx->LocalToString(params[2], &name);
671 KeyValues *pSubKey = pStk->pCurRoot.front();
672 pSubKey = pSubKey->FindKey(name, (params[3]) ? true : false);
677 pStk->pCurRoot.push(pSubKey);
682 static cell_t smn_KvJumpToKeySymbol(IPluginContext *pCtx, const cell_t *params)
684 Handle_t hndl = static_cast<Handle_t>(params[1]);
690 sec.pIdentity = g_pCoreIdent;
692 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
695 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
698 KeyValues *pSubKey = pStk->pCurRoot.front();
699 pSubKey = pSubKey->FindKey(params[2]);
704 pStk->pCurRoot.push(pSubKey);
709 static cell_t smn_KvGotoFirstSubKey(IPluginContext *pCtx, const cell_t *params)
711 Handle_t hndl = static_cast<Handle_t>(params[1]);
717 sec.pIdentity = g_pCoreIdent;
719 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
722 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
725 KeyValues *pSubKey = pStk->pCurRoot.front();
726 KeyValues *pFirstSubKey;
729 pFirstSubKey = pSubKey->GetFirstTrueSubKey();
731 pFirstSubKey = pSubKey->GetFirstSubKey();
738 pStk->pCurRoot.push(pFirstSubKey);
743 static cell_t smn_KvGotoNextKey(IPluginContext *pCtx, const cell_t *params)
745 Handle_t hndl = static_cast<Handle_t>(params[1]);
751 sec.pIdentity = g_pCoreIdent;
753 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
756 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
759 KeyValues *pSubKey = pStk->pCurRoot.front();
762 pSubKey = pSubKey->GetNextTrueSubKey();
764 pSubKey = pSubKey->GetNextKey();
770 pStk->pCurRoot.pop();
771 pStk->pCurRoot.push(pSubKey);
776 static cell_t smn_KvGoBack(IPluginContext *pCtx, const cell_t *params)
778 Handle_t hndl = static_cast<Handle_t>(params[1]);
784 sec.pIdentity = g_pCoreIdent;
786 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
789 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
792 if (pStk->pCurRoot.size() == 1)
796 pStk->pCurRoot.pop();
801 static cell_t smn_KvRewind(IPluginContext *pCtx, const cell_t *params)
803 Handle_t hndl = static_cast<Handle_t>(params[1]);
809 sec.pIdentity = g_pCoreIdent;
811 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
814 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
817 while (pStk->pCurRoot.size() > 1)
819 pStk->pCurRoot.pop();
825 static cell_t smn_KvGetSectionName(IPluginContext *pCtx, const cell_t *params)
827 Handle_t hndl = static_cast<Handle_t>(params[1]);
833 sec.pIdentity = g_pCoreIdent;
835 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
838 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
841 KeyValues *pSection = pStk->pCurRoot.front();
842 const char *name = pSection->GetName();
847 pCtx->StringToLocalUTF8(params[2], params[3], name, NULL);
852 static cell_t smn_KvSetSectionName(IPluginContext *pCtx, const cell_t *params)
854 Handle_t hndl = static_cast<Handle_t>(params[1]);
861 sec.pIdentity = g_pCoreIdent;
863 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
866 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
869 pCtx->LocalToString(params[2], &name);
871 KeyValues *pSection = pStk->pCurRoot.front();
872 pSection->SetName(name);
877 static cell_t smn_KvGetDataType(IPluginContext *pCtx, const cell_t *params)
879 Handle_t hndl = static_cast<Handle_t>(params[1]);
886 sec.pIdentity = g_pCoreIdent;
888 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
891 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
894 pCtx->LocalToString(params[2], &name);
896 return pStk->pCurRoot.front()->GetDataType(name);
899 static cell_t smn_KeyValuesToFile(IPluginContext *pCtx, const cell_t *params)
901 Handle_t hndl = static_cast<Handle_t>(params[1]);
908 sec.pIdentity = g_pCoreIdent;
910 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
913 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
916 pCtx->LocalToString(params[2], &path);
918 char realpath[PLATFORM_MAX_PATH];
919 char relpath[PLATFORM_MAX_PATH * 2];
920 g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
921 UTIL_Relatize(relpath, sizeof(relpath), g_SourceMod.GetGamePath(), realpath);
923 return pStk->pCurRoot.front()->SaveToFile(basefilesystem, relpath);
926 static cell_t smn_FileToKeyValues(IPluginContext *pCtx, const cell_t *params)
928 Handle_t hndl = static_cast<Handle_t>(params[1]);
936 sec.pIdentity = g_pCoreIdent;
938 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
941 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
944 pCtx->LocalToString(params[2], &path);
946 char realpath[PLATFORM_MAX_PATH];
947 char relpath[PLATFORM_MAX_PATH * 2];
948 g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
949 UTIL_Relatize(relpath, sizeof(relpath), g_SourceMod.GetGamePath(), realpath);
951 kv = pStk->pCurRoot.front();
952 return g_HL2.KVLoadFromFile(kv, basefilesystem, relpath);
955 static cell_t smn_KvSetEscapeSequences(IPluginContext *pCtx, const cell_t *params)
957 Handle_t hndl = static_cast<Handle_t>(params[1]);
963 sec.pIdentity = g_pCoreIdent;
965 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
968 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
971 pStk->pCurRoot.front()->UsesEscapeSequences(params[2] ? true : false);
976 static cell_t smn_KvNodesInStack(IPluginContext *pCtx, const cell_t *params)
978 Handle_t hndl = static_cast<Handle_t>(params[1]);
984 sec.pIdentity = g_pCoreIdent;
986 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
989 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
992 return pStk->pCurRoot.size() - 1;
995 static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params)
997 Handle_t hndl = static_cast<Handle_t>(params[1]);
1000 KeyValueStack *pStk;
1003 sec.pIdentity = g_pCoreIdent;
1005 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
1006 != HandleError_None)
1008 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1011 if (pStk->pCurRoot.size() < 2)
1016 KeyValues *pValues = pStk->pCurRoot.front();
1017 pStk->pCurRoot.pop();
1018 KeyValues *pRoot = pStk->pCurRoot.front();
1020 /* We have to manually verify this since Valve sucks
1021 * :TODO: make our own KeyValues.h file and make
1022 * the sub stuff private so we can do this ourselves!
1024 KeyValues *sub = pRoot->GetFirstSubKey();
1029 KeyValues *pNext = pValues->GetNextKey();
1030 pRoot->RemoveSubKey(pValues);
1031 pValues->deleteThis();
1034 pStk->pCurRoot.push(pNext);
1040 sub = sub->GetNextKey();
1043 /* Push this back on :( */
1044 pStk->pCurRoot.push(pValues);
1049 static cell_t smn_KvDeleteKey(IPluginContext *pContext, const cell_t *params)
1051 Handle_t hndl = static_cast<Handle_t>(params[1]);
1054 KeyValueStack *pStk;
1057 sec.pIdentity = g_pCoreIdent;
1059 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
1060 != HandleError_None)
1062 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1065 if (pStk->pCurRoot.size() < 2)
1071 pContext->LocalToString(params[2], &keyName);
1073 KeyValues *pRoot = pStk->pCurRoot.front();
1074 KeyValues *pValues = pRoot->FindKey(keyName);
1080 pRoot->RemoveSubKey(pValues);
1081 pValues->deleteThis();
1086 static cell_t smn_KvSavePosition(IPluginContext *pContext, const cell_t *params)
1088 Handle_t hndl = static_cast<Handle_t>(params[1]);
1091 KeyValueStack *pStk;
1094 sec.pIdentity = g_pCoreIdent;
1096 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
1097 != HandleError_None)
1099 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1102 if (pStk->pCurRoot.size() < 2)
1107 KeyValues *pValues = pStk->pCurRoot.front();
1108 pStk->pCurRoot.push(pValues);
1113 static cell_t smn_CopySubkeys(IPluginContext *pContext, const cell_t *params)
1115 Handle_t hndl_copied = static_cast<Handle_t>(params[1]);
1116 Handle_t hndl_parent = static_cast<Handle_t>(params[2]);
1119 KeyValueStack *pStk_copied, *pStk_parent;
1122 sec.pIdentity = g_pCoreIdent;
1124 if ((herr=g_HandleSys.ReadHandle(hndl_copied, g_KeyValueType, &sec, (void **)&pStk_copied))
1125 != HandleError_None)
1127 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl_copied, herr);
1129 if ((herr=g_HandleSys.ReadHandle(hndl_parent, g_KeyValueType, &sec, (void **)&pStk_parent))
1130 != HandleError_None)
1132 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl_parent, herr);
1135 pStk_copied->pCurRoot.front()->CopySubkeys(pStk_parent->pCurRoot.front());
1140 static cell_t smn_GetNameSymbol(IPluginContext *pContext, const cell_t *params)
1142 Handle_t hndl = static_cast<Handle_t>(params[1]);
1145 KeyValueStack *pStk;
1150 sec.pIdentity = g_pCoreIdent;
1152 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
1153 != HandleError_None)
1155 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1158 if (pStk->pCurRoot.size() < 2)
1163 pContext->LocalToString(params[2], &key);
1165 KeyValues *pKv = pStk->pCurRoot.front()->FindKey(key);
1170 pContext->LocalToPhysAddr(params[3], &val);
1171 *val = pKv->GetNameSymbol();
1176 static cell_t smn_FindKeyById(IPluginContext *pContext, const cell_t *params)
1178 Handle_t hndl = static_cast<Handle_t>(params[1]);
1181 KeyValueStack *pStk;
1184 sec.pIdentity = g_pCoreIdent;
1186 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
1187 != HandleError_None)
1189 return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1192 KeyValues *pKv = pStk->pCurRoot.front()->FindKey(params[2]);
1198 pContext->StringToLocalUTF8(params[3], params[4], pKv->GetName(), NULL);
1203 static cell_t smn_KvGetSectionSymbol(IPluginContext *pCtx, const cell_t *params)
1205 Handle_t hndl = static_cast<Handle_t>(params[1]);
1208 KeyValueStack *pStk;
1212 sec.pIdentity = g_pCoreIdent;
1214 if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
1215 != HandleError_None)
1217 return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1220 KeyValues *pSection = pStk->pCurRoot.front();
1222 pCtx->LocalToPhysAddr(params[2], &val);
1223 *val = pSection->GetNameSymbol();
1233 static KeyValueNatives s_KeyValueNatives;
1235 REGISTER_NATIVES(keyvaluenatives)
1237 {"KvSetString", smn_KvSetString},
1238 {"KvSetNum", smn_KvSetNum},
1239 {"KvSetUInt64", smn_KvSetUInt64},
1240 {"KvSetFloat", smn_KvSetFloat},
1241 {"KvSetColor", smn_KvSetColor},
1242 {"KvGetString", smn_KvGetString},
1243 {"KvGetNum", smn_KvGetNum},
1244 {"KvGetFloat", smn_KvGetFloat},
1245 {"KvGetColor", smn_KvGetColor},
1246 {"KvGetUInt64", smn_KvGetUInt64},
1247 {"CreateKeyValues", smn_CreateKeyValues},
1248 {"KvJumpToKey", smn_KvJumpToKey},
1249 {"KvJumpToKeySymbol", smn_KvJumpToKeySymbol},
1250 {"KvGotoNextKey", smn_KvGotoNextKey},
1251 {"KvGotoFirstSubKey", smn_KvGotoFirstSubKey},
1252 {"KvGoBack", smn_KvGoBack},
1253 {"KvRewind", smn_KvRewind},
1254 {"KvGetSectionName", smn_KvGetSectionName},
1255 {"KvSetSectionName", smn_KvSetSectionName},
1256 {"KvGetDataType", smn_KvGetDataType},
1257 {"KeyValuesToFile", smn_KeyValuesToFile},
1258 {"FileToKeyValues", smn_FileToKeyValues},
1259 {"KvSetEscapeSequences", smn_KvSetEscapeSequences},
1260 {"KvDeleteThis", smn_KvDeleteThis},
1261 {"KvDeleteKey", smn_KvDeleteKey},
1262 {"KvNodesInStack", smn_KvNodesInStack},
1263 {"KvSavePosition", smn_KvSavePosition},
1264 {"KvCopySubkeys", smn_CopySubkeys},
1265 {"KvFindKeyById", smn_FindKeyById},
1266 {"KvGetNameSymbol", smn_GetNameSymbol},
1267 {"KvGetSectionSymbol", smn_KvGetSectionSymbol},
1268 {"KvGetVector", smn_KvGetVector},
1269 {"KvSetVector", smn_KvSetVector},