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