Skip to content

Commit

Permalink
trie: implement clone() method (#852)
Browse files Browse the repository at this point in the history
* Add Clone() for StringMap

* Fix for std::string addition

* trie: broken return key.

* clonetrie: correct handle leakage.

Co-authored-by: Kyle Sanderson <kyle.leet@gmail.com>
  • Loading branch information
Headline and KyleSanderson committed Jul 15, 2020
1 parent b8ae4e6 commit 5fa25e7
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
51 changes: 51 additions & 0 deletions core/logic/smn_adt_trie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,56 @@ static cell_t GetTrieSnapshotKey(IPluginContext *pContext, const cell_t *params)
return written;
}

static cell_t CloneTrie(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);

CellTrie *pOldTrie;
if ((err = handlesys->ReadHandle(params[1], htCellTrie, &sec, (void **)&pOldTrie))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
}

CellTrie *pNewTrie = new CellTrie;
Handle_t hndl = handlesys->CreateHandle(htCellTrie, pNewTrie, pContext->GetIdentity(), g_pCoreIdent, NULL);
if (!hndl)
{
delete pNewTrie;
return hndl;
}

for (StringHashMap<Entry>::iterator it = pOldTrie->map.iter(); !it.empty(); it.next())
{
const char *key = it->key.c_str();
StringHashMap<Entry>::Insert insert = pNewTrie->map.findForAdd(key);
if (pNewTrie->map.add(insert, key))
{
StringHashMap<Entry>::Result result = pOldTrie->map.find(key);
if (result->value.isCell())
{
insert->value.setCell(result->value.cell());
}
else if (result->value.isString())
{
insert->value.setString(result->value.c_str());
}
else if (result->value.isArray())
{
insert->value.setArray(result->value.array(), result->value.arrayLength());
}
else
{
handlesys->FreeHandle(hndl, NULL);
return pContext->ThrowNativeError("Unhandled data type encountered, file a bug and reference pr #852");
}
}
}

return hndl;
}

REGISTER_NATIVES(trieNatives)
{
{"ClearTrie", ClearTrie},
Expand Down Expand Up @@ -666,6 +716,7 @@ REGISTER_NATIVES(trieNatives)
{"StringMap.SetValue", SetTrieValue},
{"StringMap.Size.get", GetTrieSize},
{"StringMap.Snapshot", CreateTrieSnapshot},
{"StringMap.Clone", CloneTrie},

{"StringMapSnapshot.Length.get", TrieSnapshotLength},
{"StringMapSnapshot.KeyBufferSize", TrieSnapshotKeyBufferSize},
Expand Down
8 changes: 8 additions & 0 deletions plugins/include/adt_trie.inc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ methodmap StringMap < Handle
// The StringMap must be freed via delete or CloseHandle().
public native StringMap();

// Clones a string map, returning a new handle with the same size and data.
// This should NOT be confused with CloneHandle. This is a completely new
// handle with the same data but no relation to the original. It should be
// closed when no longer needed with delete or CloseHandle().
//
// @return New handle to the cloned string map
public native StringMap Clone();

// Sets a value in a hash map, either inserting a new entry or replacing an old one.
//
// @param key Key string.
Expand Down
2 changes: 1 addition & 1 deletion public/sm_trie_tpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ enum NodeType
* @brief DEPRECATED. This class scales extremely poorly; insertion scales
* quadratic (O(n^2)) with respect to the number of elements in the table.
* Only use this class if you have less than 200 elements or so. Otherwise,
* use StringHashMap in sm_hashtable.h which scales linearly and has comparable
* use StringHashMap in sm_stringhashmap.h which scales linearly and has comparable
* retrievable performance.
*
* See bug 5878 for more detail.
Expand Down

0 comments on commit 5fa25e7

Please sign in to comment.