diff --git a/src/libuast.hpp b/src/libuast.hpp index 3f5037a..4344d1c 100644 --- a/src/libuast.hpp +++ b/src/libuast.hpp @@ -58,6 +58,11 @@ namespace uast { virtual T node() = 0; }; + // NodeHash is a hash of a node subtree. + struct NodeHash { + uint8_t data[UAST_HASH_SIZE]; + }; + // Context is a common interface implemented by all UAST contexts. template class Context { public: @@ -75,6 +80,7 @@ namespace uast { virtual Iterator* Filter(T root, std::string query) = 0; virtual Iterator* Iterate(T root, TreeOrder order) = 0; + virtual NodeHash Hash(T root, HashFlags flags) = 0; }; // NodeCreator is an interface that creates new UAST nodes. @@ -351,6 +357,11 @@ namespace uast { CheckError(); return new RawIterator(it); } + NodeHash Hash(NodeHandle root, HashFlags flags) { + NodeHash h; + UastHash(ctx, root, (void*)&h, flags); + return h; + } }; // PtrIterator is an iterator that casts NodeHandle directly to pointer type T. @@ -414,6 +425,9 @@ namespace uast { auto it = new PtrIterator(raw, true); return it; } + NodeHash Hash(T root, HashFlags flags) { + return ctx->Hash(ToHandle(root), flags); + } void CheckError(){ ctx->CheckError(); } diff --git a/src/uast.h b/src/uast.h index 37578ed..0896d77 100644 --- a/src/uast.h +++ b/src/uast.h @@ -91,6 +91,7 @@ typedef struct UastIterator { typedef enum { UAST_BINARY = 0, UAST_YAML = 1 } UastFormat; typedef enum { + HASH_ALL = 0x0, HASH_NO_POS = 0x1, } HashFlags; diff --git a/tests/main.cc b/tests/main.cc index 71f5528..0ed6c4d 100644 --- a/tests/main.cc +++ b/tests/main.cc @@ -28,6 +28,7 @@ int main() { // add the tests to the suite ADD_TEST(suite, "test of RoleNameForId()", TestRoleNameForId); + ADD_TEST(suite, "test node hash", TestNodeHash); ADD_TEST(suite, "test of UastFilter() pointers", TestUastFilterPointers); ADD_TEST(suite, "test iteration (preorder)", TestUastIteratorPreOrder); ADD_TEST(suite, "test of UastFilter() counting", TestUastFilterCount); diff --git a/tests/nodes_test.h b/tests/nodes_test.h index 82de303..e5cca8e 100644 --- a/tests/nodes_test.h +++ b/tests/nodes_test.h @@ -642,6 +642,24 @@ void TestNodeFindError() { UastFree(ctx); } +void TestNodeHash() { + Uast *ctx = NewUastMock(); + Node* module = newObject("Module"); + Node* child = newObject("Child"); + module->SetChild("field", child); + + unsigned char hash[UAST_HASH_SIZE]; + unsigned char exp[UAST_HASH_SIZE] = { + 0xe6, 0xd2, 0x53, 0xe1, 0x26, 0xa, 0xaa, 0xa9, + 0x37, 0xcc, 0xfc, 0x42, 0xf, 0x52, 0x65, 0x48, + 0x1d, 0x59, 0x18, 0xce, 0x1, 0xad, 0xda, 0xa2, + 0x82, 0x4c, 0x74, 0x77, 0xae, 0xa1, 0x26, 0xb5}; + UastHash(ctx, NodeHandle(module), (void*)hash, HASH_ALL); + CU_ASSERT_FATAL(memcmp(hash, exp, UAST_HASH_SIZE) == 0); + + UastFree(ctx); +} + void TestEmptyResult() { Uast *ctx = NewUastMock(); Node* module = newObject("Module");