core/smn_adt_trie.cpp
author Scott Ehlert <ds@alliedmods.net>
Fri Mar 21 04:26:53 2008 +0000 (2008-03-21)
changeset 1944 17984feecafd
parent 1829 97cd42e800e8
child 1947 e73a1e51833b
permissions -rw-r--r--
Merged crash fix (amb1539) from 1.0.1 branch
dvander@1779
     1
/**
dvander@1779
     2
 * vim: set ts=4 :
dvander@1779
     3
 * =============================================================================
dvander@1779
     4
 * SourceMod
dvander@1779
     5
 * Copyright (C) 2004-2007 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@1779
    32
#include <malloc.h>
dvander@1779
    33
#include "sm_globals.h"
dvander@1779
    34
#include "sm_stringutil.h"
dvander@1779
    35
#include "HandleSys.h"
dvander@1779
    36
#include "sm_trie_tpl.h"
dvander@1779
    37
dvander@1779
    38
HandleType_t htCellTrie;
dvander@1779
    39
dvander@1779
    40
enum TrieNodeType
dvander@1779
    41
{
dvander@1779
    42
	TrieNode_Cell,
dvander@1779
    43
	TrieNode_CellArray,
dvander@1779
    44
	TrieNode_String,
dvander@1779
    45
};
dvander@1779
    46
dvander@1779
    47
struct SmartTrieNode
dvander@1779
    48
{
dvander@1779
    49
	SmartTrieNode()
dvander@1779
    50
	{
dvander@1779
    51
		ptr = NULL;
dvander@1779
    52
		type = TrieNode_Cell;
dvander@1779
    53
	}
dvander@1779
    54
	SmartTrieNode(const SmartTrieNode &obj)
dvander@1779
    55
	{
dvander@1779
    56
		type = obj.type;
dvander@1779
    57
		ptr = obj.ptr;
dvander@1779
    58
		data = obj.data;
dvander@1779
    59
		data_len = obj.data_len;
dvander@1779
    60
	}
dvander@1779
    61
	SmartTrieNode & operator =(const SmartTrieNode &src)
dvander@1779
    62
	{
dvander@1779
    63
		type = src.type;
dvander@1779
    64
		ptr = src.ptr;
dvander@1779
    65
		data = src.data;
dvander@1779
    66
		data_len = src.data_len;
dvander@1779
    67
		return *this;
dvander@1779
    68
	}
dvander@1779
    69
	TrieNodeType type;
dvander@1779
    70
	cell_t *ptr;
dvander@1779
    71
	cell_t data;
dvander@1779
    72
	cell_t data_len;
dvander@1779
    73
};
dvander@1779
    74
dvander@1779
    75
struct CellTrie
dvander@1779
    76
{
dvander@1779
    77
	KTrie<SmartTrieNode> trie;
dvander@1779
    78
	cell_t mem_usage;
dvander@1779
    79
};
dvander@1779
    80
dvander@1779
    81
class TrieHelpers : 
dvander@1779
    82
	public SMGlobalClass,
dvander@1779
    83
	public IHandleTypeDispatch
dvander@1779
    84
{
dvander@1779
    85
public: //SMGlobalClass
dvander@1779
    86
	void OnSourceModAllInitialized()
dvander@1779
    87
	{
dvander@1779
    88
		htCellTrie = g_HandleSys.CreateType("Trie", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@1779
    89
	}
dvander@1779
    90
	void OnSourceModShutdown()
dvander@1779
    91
	{
dvander@1779
    92
		g_HandleSys.RemoveType(htCellTrie, g_pCoreIdent);
dvander@1779
    93
	}
dvander@1779
    94
public: //IHandleTypeDispatch
dvander@1779
    95
	static void DestroySmartTrieNode(SmartTrieNode *pNode)
dvander@1779
    96
	{
dvander@1779
    97
		free(pNode->ptr);
dvander@1779
    98
	}
dvander@1779
    99
	void OnHandleDestroy(HandleType_t type, void *object)
dvander@1779
   100
	{
dvander@1779
   101
		CellTrie *pTrie = (CellTrie *)object;
dvander@1779
   102
dvander@1779
   103
		pTrie->trie.run_destructor(DestroySmartTrieNode);
dvander@1779
   104
dvander@1779
   105
		delete pTrie;
dvander@1779
   106
	}
dvander@1779
   107
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
dvander@1779
   108
	{
dvander@1779
   109
		CellTrie *pArray = (CellTrie *)object;
dvander@1779
   110
		*pSize = sizeof(CellTrie) + pArray->mem_usage + pArray->trie.mem_usage();
dvander@1779
   111
		return true;
dvander@1779
   112
	}
dvander@1779
   113
} s_CellTrieHelpers;
dvander@1779
   114
dvander@1779
   115
static cell_t CreateTrie(IPluginContext *pContext, const cell_t *params)
dvander@1779
   116
{
dvander@1779
   117
	CellTrie *pTrie = new CellTrie;
dvander@1779
   118
	Handle_t hndl;
dvander@1779
   119
dvander@1779
   120
	pTrie->mem_usage = 0;
dvander@1779
   121
dvander@1779
   122
	if ((hndl = g_HandleSys.CreateHandle(htCellTrie, pTrie, pContext->GetIdentity(), g_pCoreIdent, NULL))
dvander@1779
   123
		== BAD_HANDLE)
dvander@1779
   124
	{
dvander@1779
   125
		delete pTrie;
dvander@1779
   126
		return BAD_HANDLE;
dvander@1779
   127
	}
dvander@1779
   128
dvander@1779
   129
	return hndl;
dvander@1779
   130
}
dvander@1779
   131
dvander@1779
   132
static void UpdateNodeCells(CellTrie *pTrie, SmartTrieNode *pData, const cell_t *cells, cell_t num_cells)
dvander@1779
   133
{
dvander@1779
   134
	if (num_cells == 1)
dvander@1779
   135
	{
dvander@1779
   136
		pData->data = *cells;
dvander@1779
   137
		pData->type = TrieNode_Cell;
dvander@1779
   138
	}
dvander@1779
   139
	else
dvander@1779
   140
	{
dvander@1779
   141
		pData->type = TrieNode_CellArray;
dvander@1779
   142
		if (pData->ptr == NULL)
dvander@1779
   143
		{
dvander@1779
   144
			pData->ptr = (cell_t *)malloc(num_cells * sizeof(cell_t));
dvander@1779
   145
			pData->data_len = num_cells;
dvander@1779
   146
			pTrie->mem_usage += (pData->data_len * sizeof(cell_t));
dvander@1779
   147
		}
dvander@1779
   148
		else if (pData->data_len < num_cells)
dvander@1779
   149
		{
dvander@1779
   150
			pData->ptr = (cell_t *)realloc(pData->ptr, num_cells * sizeof(cell_t));
dvander@1779
   151
			pTrie->mem_usage += (num_cells - pData->data_len) * sizeof(cell_t);
dvander@1779
   152
			pData->data_len = num_cells;
dvander@1779
   153
		}
dvander@1779
   154
		if (num_cells != 0)
dvander@1779
   155
		{
dvander@1779
   156
			memcpy(pData->ptr, cells, sizeof(cell_t) * num_cells);
dvander@1779
   157
		}
dvander@1779
   158
		pData->data = num_cells;
dvander@1779
   159
	}
dvander@1779
   160
}
dvander@1779
   161
dvander@1779
   162
static void UpdateNodeString(CellTrie *pTrie, SmartTrieNode *pData, const char *str)
dvander@1779
   163
{
dvander@1779
   164
	size_t len = strlen(str);
dvander@1779
   165
	cell_t num_cells = (len + sizeof(cell_t)) / sizeof(cell_t);
dvander@1779
   166
dvander@1779
   167
	if (pData->ptr == NULL)
dvander@1779
   168
	{
dvander@1779
   169
		pData->ptr = (cell_t *)malloc(num_cells * sizeof(cell_t));
dvander@1779
   170
		pData->data_len = num_cells;
dvander@1779
   171
		pTrie->mem_usage += (pData->data_len * sizeof(cell_t));
dvander@1779
   172
	}
dvander@1779
   173
	else if (pData->data_len < num_cells)
dvander@1779
   174
	{
dvander@1779
   175
		pData->ptr = (cell_t *)realloc(pData->ptr, num_cells * sizeof(cell_t));
dvander@1779
   176
		pTrie->mem_usage += (num_cells - pData->data_len) * sizeof(cell_t);
dvander@1779
   177
		pData->data_len = num_cells;
dvander@1779
   178
	}
dvander@1779
   179
dvander@1779
   180
	strcpy((char *)pData->ptr, str);
dvander@1779
   181
	pData->data = len;
dvander@1779
   182
	pData->type = TrieNode_String;
dvander@1779
   183
}
dvander@1779
   184
dvander@1779
   185
static cell_t SetTrieValue(IPluginContext *pContext, const cell_t *params)
dvander@1779
   186
{
dvander@1779
   187
	Handle_t hndl;
dvander@1779
   188
	CellTrie *pTrie;
dvander@1779
   189
	HandleError err;
dvander@1779
   190
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   191
dvander@1779
   192
	hndl = params[1];
dvander@1779
   193
dvander@1779
   194
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   195
		!= HandleError_None)
dvander@1779
   196
	{
dvander@1779
   197
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   198
	}
dvander@1779
   199
dvander@1779
   200
	char *key;
dvander@1779
   201
	pContext->LocalToString(params[2], &key);
dvander@1779
   202
dvander@1779
   203
	SmartTrieNode *pNode;
dvander@1779
   204
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   205
	{
dvander@1779
   206
		SmartTrieNode node;
dvander@1779
   207
		UpdateNodeCells(pTrie, &node, &params[3], 1);
dvander@1779
   208
		return pTrie->trie.insert(key, node) ? 1 : 0;
dvander@1779
   209
	}
dvander@1779
   210
dvander@1779
   211
	if (!params[4])
dvander@1779
   212
	{
dvander@1779
   213
		return 0;
dvander@1779
   214
	}
dvander@1779
   215
dvander@1779
   216
	UpdateNodeCells(pTrie, pNode, &params[3], 1);
dvander@1779
   217
dvander@1779
   218
	return 1;
dvander@1779
   219
}
dvander@1779
   220
dvander@1779
   221
static cell_t SetTrieArray(IPluginContext *pContext, const cell_t *params)
dvander@1779
   222
{
dvander@1779
   223
	Handle_t hndl;
dvander@1779
   224
	CellTrie *pTrie;
dvander@1779
   225
	HandleError err;
dvander@1779
   226
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   227
dvander@1779
   228
	hndl = params[1];
dvander@1779
   229
dvander@1779
   230
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   231
		!= HandleError_None)
dvander@1779
   232
	{
dvander@1779
   233
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   234
	}
dvander@1779
   235
dvander@1779
   236
	if (params[4] < 0)
dvander@1779
   237
	{
dvander@1779
   238
		return pContext->ThrowNativeError("Invalid array size: %d", params[4]);
dvander@1779
   239
	}
dvander@1779
   240
dvander@1779
   241
	char *key;
dvander@1779
   242
	cell_t *array;
dvander@1779
   243
	pContext->LocalToString(params[2], &key);
dvander@1779
   244
	pContext->LocalToPhysAddr(params[3], &array);
dvander@1779
   245
dvander@1779
   246
	SmartTrieNode *pNode;
dvander@1779
   247
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   248
	{
dvander@1779
   249
		SmartTrieNode node;
dvander@1779
   250
		UpdateNodeCells(pTrie, &node, array, params[4]);
dvander@1779
   251
		if (!pTrie->trie.insert(key, node))
dvander@1779
   252
		{
dvander@1779
   253
			free(node.ptr);
dvander@1779
   254
			return 0;
dvander@1779
   255
		}
dvander@1779
   256
		return 1;
dvander@1779
   257
	}
dvander@1779
   258
dvander@1779
   259
	if (!params[4])
dvander@1779
   260
	{
dvander@1779
   261
		return 0;
dvander@1779
   262
	}
dvander@1779
   263
dvander@1779
   264
	UpdateNodeCells(pTrie, pNode, array, params[4]);
dvander@1779
   265
dvander@1779
   266
	return 1;
dvander@1779
   267
}
dvander@1779
   268
dvander@1779
   269
static cell_t SetTrieString(IPluginContext *pContext, const cell_t *params)
dvander@1779
   270
{
dvander@1779
   271
	Handle_t hndl;
dvander@1779
   272
	CellTrie *pTrie;
dvander@1779
   273
	HandleError err;
dvander@1779
   274
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   275
dvander@1779
   276
	hndl = params[1];
dvander@1779
   277
dvander@1779
   278
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   279
		!= HandleError_None)
dvander@1779
   280
	{
dvander@1779
   281
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   282
	}
dvander@1779
   283
dvander@1779
   284
	char *key, *val;
dvander@1779
   285
	pContext->LocalToString(params[2], &key);
dvander@1779
   286
	pContext->LocalToString(params[3], &val);
dvander@1779
   287
dvander@1779
   288
	SmartTrieNode *pNode;
dvander@1779
   289
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   290
	{
dvander@1779
   291
		SmartTrieNode node;
dvander@1779
   292
		UpdateNodeString(pTrie, &node, val);
dvander@1779
   293
		if (!pTrie->trie.insert(key, node))
dvander@1779
   294
		{
dvander@1779
   295
			free(node.ptr);
dvander@1779
   296
			return 0;
dvander@1779
   297
		}
dvander@1779
   298
		return 1;
dvander@1779
   299
	}
dvander@1779
   300
dvander@1779
   301
	if (!params[4])
dvander@1779
   302
	{
dvander@1779
   303
		return 0;
dvander@1779
   304
	}
dvander@1779
   305
dvander@1779
   306
	UpdateNodeString(pTrie, pNode, val);
dvander@1779
   307
dvander@1779
   308
	return 1;
dvander@1779
   309
}
dvander@1779
   310
dvander@1779
   311
static cell_t RemoveFromTrie(IPluginContext *pContext, const cell_t *params)
dvander@1779
   312
{
dvander@1779
   313
	Handle_t hndl;
dvander@1779
   314
	CellTrie *pTrie;
dvander@1779
   315
	HandleError err;
dvander@1779
   316
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   317
dvander@1779
   318
	hndl = params[1];
dvander@1779
   319
dvander@1779
   320
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   321
		!= HandleError_None)
dvander@1779
   322
	{
dvander@1779
   323
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   324
	}
dvander@1779
   325
dvander@1779
   326
	char *key;
dvander@1779
   327
	pContext->LocalToString(params[2], &key);
dvander@1779
   328
dvander@1779
   329
	SmartTrieNode *pNode;
dvander@1779
   330
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   331
	{
dvander@1779
   332
		return 0;
dvander@1779
   333
	}
dvander@1779
   334
dvander@1779
   335
	free(pNode->ptr);
dvander@1779
   336
	pNode->ptr = NULL;
dvander@1779
   337
dvander@1779
   338
	return pTrie->trie.remove(key) ? 1 : 0;
dvander@1779
   339
}
dvander@1779
   340
dvander@1779
   341
static cell_t ClearTrie(IPluginContext *pContext, const cell_t *params)
dvander@1779
   342
{
dvander@1779
   343
	Handle_t hndl;
dvander@1779
   344
	CellTrie *pTrie;
dvander@1779
   345
	HandleError err;
dvander@1779
   346
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   347
dvander@1779
   348
	hndl = params[1];
dvander@1779
   349
dvander@1779
   350
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   351
		!= HandleError_None)
dvander@1779
   352
	{
dvander@1779
   353
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   354
	}
dvander@1779
   355
dvander@1779
   356
	pTrie->trie.run_destructor(TrieHelpers::DestroySmartTrieNode);
dvander@1779
   357
	pTrie->trie.clear();
dvander@1779
   358
dvander@1779
   359
	return 1;
dvander@1779
   360
}
dvander@1779
   361
dvander@1779
   362
static cell_t GetTrieValue(IPluginContext *pContext, const cell_t *params)
dvander@1779
   363
{
dvander@1779
   364
	Handle_t hndl;
dvander@1779
   365
	CellTrie *pTrie;
dvander@1779
   366
	HandleError err;
dvander@1779
   367
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   368
dvander@1779
   369
	hndl = params[1];
dvander@1779
   370
dvander@1779
   371
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   372
		!= HandleError_None)
dvander@1779
   373
	{
dvander@1779
   374
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   375
	}
dvander@1779
   376
dvander@1779
   377
	char *key;
dvander@1779
   378
	cell_t *pValue;
dvander@1779
   379
	pContext->LocalToString(params[2], &key);
dvander@1779
   380
	pContext->LocalToPhysAddr(params[3], &pValue);
dvander@1779
   381
dvander@1779
   382
	SmartTrieNode *pNode;
dvander@1779
   383
	if ((pNode = pTrie->trie.retrieve(key)) == NULL)
dvander@1779
   384
	{
dvander@1779
   385
		return 0;
dvander@1779
   386
	}
dvander@1779
   387
dvander@1779
   388
	if (pNode->type == TrieNode_Cell)
dvander@1779
   389
	{
dvander@1779
   390
		*pValue = pNode->data;
dvander@1779
   391
		return 1;
dvander@1779
   392
	}
dvander@1779
   393
	
dvander@1779
   394
	return 0;
dvander@1779
   395
}
dvander@1779
   396
dvander@1779
   397
static cell_t GetTrieArray(IPluginContext *pContext, const cell_t *params)
dvander@1779
   398
{
dvander@1779
   399
	Handle_t hndl;
dvander@1779
   400
	CellTrie *pTrie;
dvander@1779
   401
	HandleError err;
dvander@1779
   402
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   403
dvander@1779
   404
	hndl = params[1];
dvander@1779
   405
dvander@1779
   406
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   407
		!= HandleError_None)
dvander@1779
   408
	{
dvander@1779
   409
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   410
	}
dvander@1779
   411
dvander@1779
   412
	if (params[4] < 0)
dvander@1779
   413
	{
dvander@1779
   414
		return pContext->ThrowNativeError("Invalid array size: %d", params[4]);
dvander@1779
   415
	}
dvander@1779
   416
dvander@1779
   417
	char *key;
dvander@1779
   418
	cell_t *pValue, *pSize;
dvander@1779
   419
	pContext->LocalToString(params[2], &key);
dvander@1779
   420
	pContext->LocalToPhysAddr(params[3], &pValue);
dvander@1779
   421
	pContext->LocalToPhysAddr(params[5], &pSize);
dvander@1779
   422
dvander@1779
   423
	SmartTrieNode *pNode;
dvander@1779
   424
	if ((pNode = pTrie->trie.retrieve(key)) == NULL
dvander@1779
   425
		|| pNode->type != TrieNode_CellArray)
dvander@1779
   426
	{
dvander@1779
   427
		return 0;
dvander@1779
   428
	}
dvander@1779
   429
dvander@1779
   430
	if (pNode->ptr == NULL)
dvander@1779
   431
	{
dvander@1779
   432
		*pSize = 0;
dvander@1779
   433
		return 1;
dvander@1779
   434
	}
dvander@1779
   435
dvander@1779
   436
	if (pNode->data > params[4])
dvander@1779
   437
	{
dvander@1779
   438
		*pSize = params[4];
dvander@1779
   439
	}
dvander@1779
   440
	else if (params[4] != 0)
dvander@1779
   441
	{
dvander@1779
   442
		*pSize = pNode->data;
dvander@1779
   443
	}
dvander@1779
   444
	else
dvander@1779
   445
	{
dvander@1779
   446
		return 1;
dvander@1779
   447
	}
dvander@1779
   448
dvander@1779
   449
	memcpy(pValue, pNode->ptr, sizeof(cell_t) * pSize[0]);
dvander@1779
   450
dvander@1779
   451
	return 1;
dvander@1779
   452
}
dvander@1779
   453
dvander@1779
   454
static cell_t GetTrieString(IPluginContext *pContext, const cell_t *params)
dvander@1779
   455
{
dvander@1779
   456
	Handle_t hndl;
dvander@1779
   457
	CellTrie *pTrie;
dvander@1779
   458
	HandleError err;
dvander@1779
   459
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1779
   460
dvander@1779
   461
	hndl = params[1];
dvander@1779
   462
dvander@1779
   463
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1779
   464
		!= HandleError_None)
dvander@1779
   465
	{
dvander@1779
   466
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1779
   467
	}
dvander@1779
   468
dvander@1779
   469
	if (params[4] < 0)
dvander@1779
   470
	{
dvander@1779
   471
		return pContext->ThrowNativeError("Invalid buffer size: %d", params[4]);
dvander@1779
   472
	}
dvander@1779
   473
dvander@1779
   474
	char *key;
dvander@1779
   475
	cell_t *pSize;
dvander@1779
   476
	pContext->LocalToString(params[2], &key);
dvander@1779
   477
	pContext->LocalToPhysAddr(params[5], &pSize);
dvander@1779
   478
dvander@1779
   479
	SmartTrieNode *pNode;
dvander@1779
   480
	if ((pNode = pTrie->trie.retrieve(key)) == NULL
dvander@1779
   481
		|| pNode->type != TrieNode_String)
dvander@1779
   482
	{
dvander@1779
   483
		return 0;
dvander@1779
   484
	}
dvander@1779
   485
dvander@1779
   486
	if (pNode->ptr == NULL)
dvander@1779
   487
	{
dvander@1779
   488
		*pSize = 0;
dvander@1779
   489
		pContext->StringToLocal(params[3], params[4], "");
dvander@1779
   490
		return 1;
dvander@1779
   491
	}
dvander@1779
   492
dvander@1779
   493
	size_t written;
dvander@1779
   494
	pContext->StringToLocalUTF8(params[3], params[4], (char *)pNode->ptr, &written);
dvander@1779
   495
dvander@1779
   496
	*pSize = (cell_t)written;
dvander@1779
   497
dvander@1779
   498
	return 1;
dvander@1779
   499
}
dvander@1779
   500
dvander@1829
   501
static cell_t GetTrieSize(IPluginContext *pContext, const cell_t *params)
dvander@1829
   502
{
dvander@1829
   503
	Handle_t hndl;
dvander@1829
   504
	CellTrie *pTrie;
dvander@1829
   505
	HandleError err;
dvander@1829
   506
	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
dvander@1829
   507
dvander@1829
   508
	hndl = params[1];
dvander@1829
   509
dvander@1829
   510
	if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
dvander@1829
   511
		!= HandleError_None)
dvander@1829
   512
	{
dvander@1829
   513
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
dvander@1829
   514
	}
dvander@1829
   515
dvander@1829
   516
	return pTrie->trie.size();
dvander@1829
   517
}
dvander@1829
   518
dvander@1779
   519
REGISTER_NATIVES(trieNatives)
dvander@1779
   520
{
dvander@1779
   521
	{"ClearTrie",				ClearTrie},
dvander@1779
   522
	{"CreateTrie",				CreateTrie},
dvander@1779
   523
	{"GetTrieArray",			GetTrieArray},
dvander@1779
   524
	{"GetTrieString",			GetTrieString},
dvander@1779
   525
	{"GetTrieValue",			GetTrieValue},
dvander@1779
   526
	{"RemoveFromTrie",			RemoveFromTrie},
dvander@1779
   527
	{"SetTrieArray",			SetTrieArray},
dvander@1779
   528
	{"SetTrieString",			SetTrieString},
dvander@1779
   529
	{"SetTrieValue",			SetTrieValue},
dvander@1829
   530
	{"GetTrieSize",				GetTrieSize},
dvander@1779
   531
	{NULL,						NULL},
dvander@1779
   532
};