core/logic/smn_adt_trie.cpp
author David Anderson <dvander@alliedmods.net>
Thu Aug 08 22:02:42 2013 -0700 (2013-08-08)
changeset 3980 dc7dfcd855dc
parent 2728 96022dad7e53
child 4096 1ed7fe4e8f7e
permissions -rw-r--r--
More Windows build fix.
dvander@1779
     1
/**
dvander@1779
     2
 * vim: set ts=4 :
dvander@1779
     3
 * =============================================================================
dvander@1779
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@1779
     6
 * =============================================================================
dvander@1779
     7
 *
dvander@1779
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@1779
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@1779
    10
 * Free Software Foundation.
dvander@1779
    11
 * 
dvander@1779
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@1779
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@1779
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@1779
    15
 * details.
dvander@1779
    16
 *
dvander@1779
    17
 * You should have received a copy of the GNU General Public License along with
dvander@1779
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1779
    19
 *
dvander@1779
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@1779
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@1779
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@1779
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@1779
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@1779
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@1779
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@1779
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@1779
    28
 *
dvander@1779
    29
 * Version: $Id$
dvander@1779
    30
 */
dvander@1779
    31
dvander@2471
    32
#include <stdlib.h>
dvander@2728
    33
#include "common_logic.h"
dvander@2728
    34
#include <sm_trie_tpl.h>
dvander@1779
    35
dvander@1779
    36
HandleType_t htCellTrie;
dvander@1779
    37
dvander@1779
    38
enum TrieNodeType
dvander@1779
    39
{
dvander@1779
    40
	TrieNode_Cell,
dvander@1779
    41
	TrieNode_CellArray,
dvander@1779
    42
	TrieNode_String,
dvander@1779
    43
};
dvander@1779
    44
dvander@1779
    45
struct SmartTrieNode
dvander@1779
    46
{
dvander@1779
    47
	SmartTrieNode()
dvander@1779
    48
	{
dvander@1779
    49
		ptr = NULL;
dvander@1779
    50
		type = TrieNode_Cell;
dvander@1779
    51
	}
dvander@1779
    52
	SmartTrieNode(const SmartTrieNode &obj)
dvander@1779
    53
	{
dvander@1779
    54
		type = obj.type;
dvander@1779
    55
		ptr = obj.ptr;
dvander@1779
    56
		data = obj.data;
dvander@1779
    57
		data_len = obj.data_len;
dvander@1779
    58
	}
dvander@1779
    59
	SmartTrieNode & operator =(const SmartTrieNode &src)
dvander@1779
    60
	{
dvander@1779
    61
		type = src.type;
dvander@1779
    62
		ptr = src.ptr;
dvander@1779
    63
		data = src.data;
dvander@1779
    64
		data_len = src.data_len;
dvander@1779
    65
		return *this;
dvander@1779
    66
	}
dvander@1779
    67
	TrieNodeType type;
dvander@1779
    68
	cell_t *ptr;
dvander@1779
    69
	cell_t data;
dvander@1779
    70
	cell_t data_len;
dvander@1779
    71
};
dvander@1779
    72
dvander@1779
    73
struct CellTrie
dvander@1779
    74
{
dvander@1779
    75
	KTrie<SmartTrieNode> trie;
dvander@1779
    76
	cell_t mem_usage;
dvander@1779
    77
};
dvander@1779
    78
dvander@1779
    79
class TrieHelpers : 
dvander@1779
    80
	public SMGlobalClass,
dvander@1779
    81
	public IHandleTypeDispatch
dvander@1779
    82
{
dvander@1779
    83
public: //SMGlobalClass
dvander@1779
    84
	void OnSourceModAllInitialized()
dvander@1779
    85
	{
dvander@2728
    86
		htCellTrie = handlesys->CreateType("Trie", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@1779
    87
	}
dvander@1779
    88
	void OnSourceModShutdown()
dvander@1779
    89
	{
dvander@2728
    90
		handlesys->RemoveType(htCellTrie, g_pCoreIdent);
dvander@1779
    91
	}
dvander@1779
    92
public: //IHandleTypeDispatch
dvander@1779
    93
	static void DestroySmartTrieNode(SmartTrieNode *pNode)
dvander@1779
    94
	{
dvander@1779
    95
		free(pNode->ptr);
dvander@1779
    96
	}
dvander@1779
    97
	void OnHandleDestroy(HandleType_t type, void *object)
dvander@1779
    98
	{
dvander@1779
    99
		CellTrie *pTrie = (CellTrie *)object;
dvander@1779
   100
dvander@1779
   101
		pTrie->trie.run_destructor(DestroySmartTrieNode);
dvander@1779
   102
dvander@1779
   103
		delete pTrie;
dvander@1779
   104
	}
dvander@1779
   105
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@1779
   106
	{
dvander@1779
   107
		CellTrie *pArray = (CellTrie *)object;
dvander@1779
   108
		*pSize = sizeof(CellTrie) + pArray->mem_usage + pArray->trie.mem_usage();
dvander@1779
   109
		return true;
dvander@1779
   110
	}
dvander@1779
   111
} s_CellTrieHelpers;
dvander@1779
   112
dvander@1779
   113
static cell_t CreateTrie(IPluginContext *pContext, const cell_t *params)
dvander@1779
   114
{
dvander@1779
   115
	CellTrie *pTrie = new CellTrie;
dvander@1779
   116
	Handle_t hndl;
dvander@1779
   117
dvander@1779
   118
	pTrie->mem_usage = 0;
dvander@1779
   119
dvander@2728
   120
	if ((hndl = handlesys->CreateHandle(htCellTrie, pTrie, pContext->GetIdentity(), g_pCoreIdent, NULL))
dvander@1779
   121
		== BAD_HANDLE)
dvander@1779
   122
	{
dvander@1779
   123
		delete pTrie;
dvander@1779
   124
		return BAD_HANDLE;
dvander@1779
   125
	}
dvander@1779
   126
dvander@1779
   127
	return hndl;
dvander@1779
   128
}
dvander@1779
   129
dvander@1779
   130
static void UpdateNodeCells(CellTrie *pTrie, SmartTrieNode *pData, const cell_t *cells, cell_t num_cells)
dvander@1779
   131
{
dvander@1779
   132
	if (num_cells == 1)
dvander@1779
   133
	{
dvander@1779
   134
		pData->data = *cells;
dvander@1779
   135
		pData->type = TrieNode_Cell;
dvander@1779
   136
	}
dvander@1779
   137
	else
dvander@1779
   138
	{
dvander@1779
   139
		pData->type = TrieNode_CellArray;
dvander@1779
   140
		if (pData->ptr == NULL)
dvander@1779
   141
		{
dvander@1779
   142
			pData->ptr = (cell_t *)malloc(num_cells * sizeof(cell_t));
dvander@1779
   143
			pData->data_len = num_cells;
dvander@1779
   144
			pTrie->mem_usage += (pData->data_len * sizeof(cell_t));
dvander@1779
   145
		}
dvander@1779
   146
		else if (pData->data_len < num_cells)
dvander@1779
   147
		{
dvander@1779
   148
			pData->ptr = (cell_t *)realloc(pData->ptr, num_cells * sizeof(cell_t));
dvander@1779
   149
			pTrie->mem_usage += (num_cells - pData->data_len) * sizeof(cell_t);
dvander@1779
   150
			pData->data_len = num_cells;
dvander@1779
   151
		}
dvander@1779
   152
		if (num_cells != 0)
dvander@1779
   153
		{
dvander@1779
   154
			memcpy(pData->ptr, cells, sizeof(cell_t) * num_cells);
dvander@1779
   155
		}
dvander@1779
   156
		pData->data = num_cells;
dvander@1779
   157
	}
dvander@1779
   158
}
dvander@1779
   159
dvander@1779
   160
static void UpdateNodeString(CellTrie *pTrie, SmartTrieNode *pData, const char *str)
dvander@1779
   161
{
dvander@1779
   162
	size_t len = strlen(str);
dvander@1779
   163
	cell_t num_cells = (len + sizeof(cell_t)) / sizeof(cell_t);
dvander@1779
   164
dvander@1779
   165
	if (pData->ptr == NULL)
dvander@1779
   166
	{
dvander@1779
   167
		pData->ptr = (cell_t *)malloc(num_cells * sizeof(cell_t));
dvander@1779
   168
		pData->data_len = num_cells;
dvander@1779
   169
		pTrie->mem_usage += (pData->data_len * sizeof(cell_t));
dvander@1779
   170
	}
dvander@1779
   171
	else if (pData->data_len < num_cells)
dvander@1779
   172
	{
dvander@1779
   173
		pData->ptr = (cell_t *)realloc(pData->ptr, num_cells * sizeof(cell_t));
dvander@1779
   174
		pTrie->mem_usage += (num_cells - pData->data_len) * sizeof(cell_t);
dvander@1779
   175
		pData->data_len = num_cells;
dvander@1779
   176
	}
dvander@1779
   177
dvander@1779
   178
	strcpy((char *)pData->ptr, str);
dvander@1779
   179
	pData->data = len;
dvander@1779
   180
	pData->type = TrieNode_String;
dvander@1779
   181
}
dvander@1779
   182
dvander@1779
   183
static cell_t SetTrieValue(IPluginContext *pContext, const cell_t *params)
dvander@1779
   184
{
dvander@1779
   185
	Handle_t hndl;
dvander@1779
   186
	CellTrie *pTrie;
dvander@1779
   187
	HandleError err;
dvander@1779
   188
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   189
dvander@1779
   190
	hndl = params[1];
dvander@1779
   191
dvander@2728
   192
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   193
		!= HandleError_None)
dvander@1779
   194
	{
dvander@1779
   195
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   196
	}
dvander@1779
   197
dvander@1779
   198
	char *key;
dvander@1779
   199
	pContext->LocalToString(params[2], &key);
dvander@1779
   200
dvander@1779
   201
	SmartTrieNode *pNode;
dvander@1779
   202
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   203
	{
dvander@1779
   204
		SmartTrieNode node;
dvander@1779
   205
		UpdateNodeCells(pTrie, &node, &params[3], 1);
dvander@1779
   206
		return pTrie->trie.insert(key, node) ? 1 : 0;
dvander@1779
   207
	}
dvander@1779
   208
dvander@1779
   209
	if (!params[4])
dvander@1779
   210
	{
dvander@1779
   211
		return 0;
dvander@1779
   212
	}
dvander@1779
   213
dvander@1779
   214
	UpdateNodeCells(pTrie, pNode, &params[3], 1);
dvander@1779
   215
dvander@1779
   216
	return 1;
dvander@1779
   217
}
dvander@1779
   218
dvander@1779
   219
static cell_t SetTrieArray(IPluginContext *pContext, const cell_t *params)
dvander@1779
   220
{
dvander@1779
   221
	Handle_t hndl;
dvander@1779
   222
	CellTrie *pTrie;
dvander@1779
   223
	HandleError err;
dvander@1779
   224
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   225
dvander@1779
   226
	hndl = params[1];
dvander@1779
   227
dvander@2728
   228
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   229
		!= HandleError_None)
dvander@1779
   230
	{
dvander@1779
   231
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   232
	}
dvander@1779
   233
dvander@1779
   234
	if (params[4] < 0)
dvander@1779
   235
	{
dvander@1779
   236
		return pContext->ThrowNativeError("Invalid array size: %d", params[4]);
dvander@1779
   237
	}
dvander@1779
   238
dvander@1779
   239
	char *key;
dvander@1779
   240
	cell_t *array;
dvander@1779
   241
	pContext->LocalToString(params[2], &key);
dvander@1779
   242
	pContext->LocalToPhysAddr(params[3], &array);
dvander@1779
   243
dvander@1779
   244
	SmartTrieNode *pNode;
dvander@1779
   245
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   246
	{
dvander@1779
   247
		SmartTrieNode node;
dvander@1779
   248
		UpdateNodeCells(pTrie, &node, array, params[4]);
dvander@1779
   249
		if (!pTrie->trie.insert(key, node))
dvander@1779
   250
		{
dvander@1779
   251
			free(node.ptr);
dvander@1779
   252
			return 0;
dvander@1779
   253
		}
dvander@1779
   254
		return 1;
dvander@1779
   255
	}
dvander@1779
   256
dvander@1779
   257
	if (!params[4])
dvander@1779
   258
	{
dvander@1779
   259
		return 0;
dvander@1779
   260
	}
dvander@1779
   261
dvander@1779
   262
	UpdateNodeCells(pTrie, pNode, array, params[4]);
dvander@1779
   263
dvander@1779
   264
	return 1;
dvander@1779
   265
}
dvander@1779
   266
dvander@1779
   267
static cell_t SetTrieString(IPluginContext *pContext, const cell_t *params)
dvander@1779
   268
{
dvander@1779
   269
	Handle_t hndl;
dvander@1779
   270
	CellTrie *pTrie;
dvander@1779
   271
	HandleError err;
dvander@1779
   272
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   273
dvander@1779
   274
	hndl = params[1];
dvander@1779
   275
dvander@2728
   276
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   277
		!= HandleError_None)
dvander@1779
   278
	{
dvander@1779
   279
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   280
	}
dvander@1779
   281
dvander@1779
   282
	char *key, *val;
dvander@1779
   283
	pContext->LocalToString(params[2], &key);
dvander@1779
   284
	pContext->LocalToString(params[3], &val);
dvander@1779
   285
dvander@1779
   286
	SmartTrieNode *pNode;
dvander@1779
   287
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   288
	{
dvander@1779
   289
		SmartTrieNode node;
dvander@1779
   290
		UpdateNodeString(pTrie, &node, val);
dvander@1779
   291
		if (!pTrie->trie.insert(key, node))
dvander@1779
   292
		{
dvander@1779
   293
			free(node.ptr);
dvander@1779
   294
			return 0;
dvander@1779
   295
		}
dvander@1779
   296
		return 1;
dvander@1779
   297
	}
dvander@1779
   298
dvander@1779
   299
	if (!params[4])
dvander@1779
   300
	{
dvander@1779
   301
		return 0;
dvander@1779
   302
	}
dvander@1779
   303
dvander@1779
   304
	UpdateNodeString(pTrie, pNode, val);
dvander@1779
   305
dvander@1779
   306
	return 1;
dvander@1779
   307
}
dvander@1779
   308
dvander@1779
   309
static cell_t RemoveFromTrie(IPluginContext *pContext, const cell_t *params)
dvander@1779
   310
{
dvander@1779
   311
	Handle_t hndl;
dvander@1779
   312
	CellTrie *pTrie;
dvander@1779
   313
	HandleError err;
dvander@1779
   314
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   315
dvander@1779
   316
	hndl = params[1];
dvander@1779
   317
dvander@2728
   318
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   319
		!= HandleError_None)
dvander@1779
   320
	{
dvander@1779
   321
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   322
	}
dvander@1779
   323
dvander@1779
   324
	char *key;
dvander@1779
   325
	pContext->LocalToString(params[2], &key);
dvander@1779
   326
dvander@1779
   327
	SmartTrieNode *pNode;
dvander@1779
   328
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   329
	{
dvander@1779
   330
		return 0;
dvander@1779
   331
	}
dvander@1779
   332
dvander@1779
   333
	free(pNode->ptr);
dvander@1779
   334
	pNode->ptr = NULL;
dvander@1779
   335
dvander@1779
   336
	return pTrie->trie.remove(key) ? 1 : 0;
dvander@1779
   337
}
dvander@1779
   338
dvander@1779
   339
static cell_t ClearTrie(IPluginContext *pContext, const cell_t *params)
dvander@1779
   340
{
dvander@1779
   341
	Handle_t hndl;
dvander@1779
   342
	CellTrie *pTrie;
dvander@1779
   343
	HandleError err;
dvander@1779
   344
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   345
dvander@1779
   346
	hndl = params[1];
dvander@1779
   347
dvander@2728
   348
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   349
		!= HandleError_None)
dvander@1779
   350
	{
dvander@1779
   351
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   352
	}
dvander@1779
   353
dvander@1779
   354
	pTrie->trie.run_destructor(TrieHelpers::DestroySmartTrieNode);
dvander@1779
   355
	pTrie->trie.clear();
dvander@1779
   356
dvander@1779
   357
	return 1;
dvander@1779
   358
}
dvander@1779
   359
dvander@1779
   360
static cell_t GetTrieValue(IPluginContext *pContext, const cell_t *params)
dvander@1779
   361
{
dvander@1779
   362
	Handle_t hndl;
dvander@1779
   363
	CellTrie *pTrie;
dvander@1779
   364
	HandleError err;
dvander@1779
   365
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   366
dvander@1779
   367
	hndl = params[1];
dvander@1779
   368
dvander@2728
   369
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   370
		!= HandleError_None)
dvander@1779
   371
	{
dvander@1779
   372
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   373
	}
dvander@1779
   374
dvander@1779
   375
	char *key;
dvander@1779
   376
	cell_t *pValue;
dvander@1779
   377
	pContext->LocalToString(params[2], &key);
dvander@1779
   378
	pContext->LocalToPhysAddr(params[3], &pValue);
dvander@1779
   379
dvander@1779
   380
	SmartTrieNode *pNode;
dvander@1779
   381
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   382
	{
dvander@1779
   383
		return 0;
dvander@1779
   384
	}
dvander@1779
   385
dvander@1779
   386
	if (pNode->type == TrieNode_Cell)
dvander@1779
   387
	{
dvander@1779
   388
		*pValue = pNode->data;
dvander@1779
   389
		return 1;
dvander@1779
   390
	}
dvander@1779
   391
	
dvander@1779
   392
	return 0;
dvander@1779
   393
}
dvander@1779
   394
dvander@1779
   395
static cell_t GetTrieArray(IPluginContext *pContext, const cell_t *params)
dvander@1779
   396
{
dvander@1779
   397
	Handle_t hndl;
dvander@1779
   398
	CellTrie *pTrie;
dvander@1779
   399
	HandleError err;
dvander@1779
   400
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   401
dvander@1779
   402
	hndl = params[1];
dvander@1779
   403
dvander@2728
   404
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   405
		!= HandleError_None)
dvander@1779
   406
	{
dvander@1779
   407
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   408
	}
dvander@1779
   409
dvander@1779
   410
	if (params[4] < 0)
dvander@1779
   411
	{
dvander@1779
   412
		return pContext->ThrowNativeError("Invalid array size: %d", params[4]);
dvander@1779
   413
	}
dvander@1779
   414
dvander@1779
   415
	char *key;
dvander@1779
   416
	cell_t *pValue, *pSize;
dvander@1779
   417
	pContext->LocalToString(params[2], &key);
dvander@1779
   418
	pContext->LocalToPhysAddr(params[3], &pValue);
dvander@1779
   419
	pContext->LocalToPhysAddr(params[5], &pSize);
dvander@1779
   420
dvander@1779
   421
	SmartTrieNode *pNode;
dvander@1779
   422
	if ((pNode = pTrie->trie.retrieve(key)) == NULL
dvander@1779
   423
		|| pNode->type != TrieNode_CellArray)
dvander@1779
   424
	{
dvander@1779
   425
		return 0;
dvander@1779
   426
	}
dvander@1779
   427
dvander@1779
   428
	if (pNode->ptr == NULL)
dvander@1779
   429
	{
dvander@1779
   430
		*pSize = 0;
dvander@1779
   431
		return 1;
dvander@1779
   432
	}
dvander@1779
   433
dvander@1779
   434
	if (pNode->data > params[4])
dvander@1779
   435
	{
dvander@1779
   436
		*pSize = params[4];
dvander@1779
   437
	}
dvander@1779
   438
	else if (params[4] != 0)
dvander@1779
   439
	{
dvander@1779
   440
		*pSize = pNode->data;
dvander@1779
   441
	}
dvander@1779
   442
	else
dvander@1779
   443
	{
dvander@1779
   444
		return 1;
dvander@1779
   445
	}
dvander@1779
   446
dvander@1779
   447
	memcpy(pValue, pNode->ptr, sizeof(cell_t) * pSize[0]);
dvander@1779
   448
dvander@1779
   449
	return 1;
dvander@1779
   450
}
dvander@1779
   451
dvander@1779
   452
static cell_t GetTrieString(IPluginContext *pContext, const cell_t *params)
dvander@1779
   453
{
dvander@1779
   454
	Handle_t hndl;
dvander@1779
   455
	CellTrie *pTrie;
dvander@1779
   456
	HandleError err;
dvander@1779
   457
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   458
dvander@1779
   459
	hndl = params[1];
dvander@1779
   460
dvander@2728
   461
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   462
		!= HandleError_None)
dvander@1779
   463
	{
dvander@1779
   464
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   465
	}
dvander@1779
   466
dvander@1779
   467
	if (params[4] < 0)
dvander@1779
   468
	{
dvander@1779
   469
		return pContext->ThrowNativeError("Invalid buffer size: %d", params[4]);
dvander@1779
   470
	}
dvander@1779
   471
dvander@1779
   472
	char *key;
dvander@1779
   473
	cell_t *pSize;
dvander@1779
   474
	pContext->LocalToString(params[2], &key);
dvander@1779
   475
	pContext->LocalToPhysAddr(params[5], &pSize);
dvander@1779
   476
dvander@1779
   477
	SmartTrieNode *pNode;
dvander@1779
   478
	if ((pNode = pTrie->trie.retrieve(key)) == NULL
dvander@1779
   479
		|| pNode->type != TrieNode_String)
dvander@1779
   480
	{
dvander@1779
   481
		return 0;
dvander@1779
   482
	}
dvander@1779
   483
dvander@1779
   484
	if (pNode->ptr == NULL)
dvander@1779
   485
	{
dvander@1779
   486
		*pSize = 0;
dvander@1779
   487
		pContext->StringToLocal(params[3], params[4], "");
dvander@1779
   488
		return 1;
dvander@1779
   489
	}
dvander@1779
   490
dvander@1779
   491
	size_t written;
dvander@1779
   492
	pContext->StringToLocalUTF8(params[3], params[4], (char *)pNode->ptr, &written);
dvander@1779
   493
dvander@1779
   494
	*pSize = (cell_t)written;
dvander@1779
   495
dvander@1779
   496
	return 1;
dvander@1779
   497
}
dvander@1779
   498
dvander@1829
   499
static cell_t GetTrieSize(IPluginContext *pContext, const cell_t *params)
dvander@1829
   500
{
dvander@1829
   501
	Handle_t hndl;
dvander@1829
   502
	CellTrie *pTrie;
dvander@1829
   503
	HandleError err;
dvander@1829
   504
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1829
   505
dvander@1829
   506
	hndl = params[1];
dvander@1829
   507
dvander@2728
   508
	if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1829
   509
		!= HandleError_None)
dvander@1829
   510
	{
dvander@1829
   511
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1829
   512
	}
dvander@1829
   513
dvander@1829
   514
	return pTrie->trie.size();
dvander@1829
   515
}
dvander@1829
   516
dvander@1779
   517
REGISTER_NATIVES(trieNatives)
dvander@1779
   518
{
dvander@1779
   519
	{"ClearTrie",				ClearTrie},
dvander@1779
   520
	{"CreateTrie",				CreateTrie},
dvander@1779
   521
	{"GetTrieArray",			GetTrieArray},
dvander@1779
   522
	{"GetTrieString",			GetTrieString},
dvander@1779
   523
	{"GetTrieValue",			GetTrieValue},
dvander@1779
   524
	{"RemoveFromTrie",			RemoveFromTrie},
dvander@1779
   525
	{"SetTrieArray",			SetTrieArray},
dvander@1779
   526
	{"SetTrieString",			SetTrieString},
dvander@1779
   527
	{"SetTrieValue",			SetTrieValue},
dvander@1829
   528
	{"GetTrieSize",				GetTrieSize},
dvander@1779
   529
	{NULL,						NULL},
dvander@1779
   530
};