Skip to content

Commit

Permalink
initial test passed
Browse files Browse the repository at this point in the history
  • Loading branch information
umegaya committed Jul 15, 2016
1 parent dc3fa00 commit 84641fa
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 37 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -DDEBUG")
endif()
if (OSXBUNDLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -bundle")
add_executable(shutup MACOSX_BUNDLE lib.cpp patricia.cpp)
Expand Down
5 changes: 4 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
test: testlib
make -C test run

debug:
lldb test/build/t

testlib:
- mkdir build.testlib
cd build.testlib && cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain/testlib.cmake .. && make
Expand All @@ -23,7 +26,7 @@ android:
cd build.android && cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain/android.cmake .. && make

clean:
rm -rf build build.android build.ios build.bundle
rm -rf build build.android build.ios build.bundle build.testlib

all: lib bundle android ios

35 changes: 27 additions & 8 deletions patricia.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include "patricia.h"

#if defined(DEBUG)
#include <cstdio>
#endif

namespace shutup {
//Patricia::Node
void Patricia::Node::destroy(allocator<Node*> &a) {
Expand All @@ -9,7 +13,6 @@ void Patricia::Node::destroy(allocator<Node*> &a) {
free(a);
}
void Patricia::Node::add_child(allocator<Node*> &a, const u8 *b, int l) {
imempool &m = a.pool();
int index = 0;
for (Node *child : children_) {
// == はないはず(あるならこのノードではなくその子供への追加になっているはず)
Expand All @@ -25,9 +28,9 @@ void Patricia::Node::add_child(allocator<Node*> &a, const u8 *b, int l) {
//TODO: 元データをshared_ptrとして扱って複数ノードで共有し、ofsとlenをviewとして各ノードに持たせることでmallocの回数をb[i + 1:]のための1回に減らせるだろう.
//ただし、ノードを削除する際にNodeをparentにさかのぼってunref的なことをする必要があるため削除のパフォーマンスは低下するかも
//いずれにせよ相当数のノードがないと効果は実感できないだろうと考えられるためTODOとしている.
Node *t = new(m.malloc(i)) Node(a, this, b, i); //childとb, lの共通部分.
Node *b1 = new(m.malloc(child->len_ - i)) Node(a, t, child->bytes_ + i, child->len_ - i);
Node *b2 = new(m.malloc(l - i)) Node(a, t, b + i, l - i);
Node *t = Node::new_node(a, this, b, i); //childとb, lの共通部分.
Node *b1 = Node::new_node(a, t, child->bytes_ + i, child->len_ - i);
Node *b2 = Node::new_node(a, t, b + i, l - i);
//このchildを取り除く.全てのリンクはまだ生きている.
children_.erase(children_.begin() + index);
//b1に今のchildのchild_を全部くっつける.
Expand All @@ -50,7 +53,7 @@ void Patricia::Node::add_child(allocator<Node*> &a, const u8 *b, int l) {
index++;
}
//全く一致するchildがなかったので新しく追加する.
children_.push_back(new (m.malloc(l)) Node(a, this, b, l));
children_.push_back(Node::new_node(a, this, b, l));
}
bool Patricia::Node::compare(const Node *left, const Node *right) {
int l = std::min(left->len_, right->len_);
Expand Down Expand Up @@ -104,11 +107,27 @@ bool Patricia::contains(const u8 *b, int l, int *ofs) {
Node *n = find_node(b, l, ofs);
return n->terminal();
}
bool Patricia::traverse(Node *cur, std::function<bool(Node*)> iter) {
if (!iter(cur)) { return false; }
bool Patricia::traverse(Node *cur, int depth, std::function<bool(Node*, int)> iter) {
if (!iter(cur, depth)) { return false; }
for (Node *n : cur->children_) {
if (!traverse(n, iter)) { return false; }
if (!traverse(n, depth + 1, iter)) { return false; }
}
return true;
}
#if defined(DEBUG)
void Patricia::dump() {
std::printf("dump patricia tree at %p\n", this);
std::printf("[*root*]\n");
traverse([] (shutup::Patricia::NodeData *n, int depth) -> bool {
char buffer[256];
std::memcpy(buffer, n->bytes(), n->len());
buffer[n->len()] = 0;
for (int i = 0; i < depth; i++) { std::putc('\t', stdout); }
std::printf("[%s]\n", buffer);
return true;
});
}
#else
void Patricia::dump() {}
#endif
} //namespace shutup
35 changes: 23 additions & 12 deletions patricia.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Patricia {
std::memcpy(bytes_, b, l);
len_ = l;
}
Node(allocator<Node*> &a) : parent_(nullptr), children_(a), len_(0) {} //for creating root node
~Node() {}
void destroy(allocator<Node*> &a);
void add_child(allocator<Node*> &a, const u8 *b, int l);
Expand All @@ -32,20 +33,25 @@ class Patricia {
operator delete(this, this);
a.pool().free(this);
}
inline bool terminal() {
return children_.size() == 0;
}
inline bool terminal() const { return children_.size() == 0; }
inline bool root() const { return parent_ == nullptr; }
static inline void *operator new(std::size_t, void *buf) { return buf; }
static inline void operator delete(void *p, void *buf) {}
static inline Node *new_node(allocator<Node*> &a, Node *parent, const u8 *b, int l) {
return new(a.pool().malloc(sizeof(Node) + l)) Node(a, parent, b, l);
}
static inline Node *new_root(allocator<Node*> &a) {
return new(a.pool().malloc(sizeof(Node))) Node(a);
}
};
public:
Node *root_;
imatcher *matcher_;
allocator<Node*> alloc_;
Patricia() : root_(nullptr), matcher_(new byte_matcher()), alloc_(new system_mempool()) {}
Patricia(imatcher *mch) : root_(nullptr), matcher_(mch), alloc_(new system_mempool()) {}
Patricia(imempool *m) : root_(nullptr), matcher_(new byte_matcher()), alloc_(m) {}
Patricia(imatcher *mch, imempool *m) : root_(nullptr), matcher_(mch), alloc_(m) {}
Node *root_;
inline Patricia() : matcher_(new byte_matcher()), alloc_(new system_mempool()), root_(Node::new_root(alloc_)) {}
inline Patricia(imatcher *mch) : matcher_(mch), alloc_(new system_mempool()), root_(Node::new_root(alloc_)) {}
inline Patricia(imempool *m) : matcher_(new byte_matcher()), alloc_(m), root_(Node::new_root(alloc_)) {}
inline Patricia(imatcher *mch, imempool *m) : matcher_(mch), alloc_(m), root_(Node::new_root(alloc_)) {}
~Patricia();
void add_slice(const u8 *b, int l);
void remove_slice(const u8 *b, int l) {}
Expand All @@ -54,19 +60,24 @@ class Patricia {
inline void add(const char *s) { add_slice(reinterpret_cast<const u8*>(s), std::strlen(s)); }
inline void remove(const char *s) { remove_slice(reinterpret_cast<const u8*>(s), std::strlen(s)); }
inline bool contains(const char *s, int *ofs) { return contains(reinterpret_cast<const u8*>(s), std::strlen(s), ofs); }
void dump();
protected:
Node *find_node(const u8 *b, int l, int *ofs);
bool traverse(Node *n, std::function<bool(Node*)> iter);
bool traverse(Node *n, int depth, std::function<bool(Node*, int)> iter);
#if defined(TEST)
public:
class ExportNode : public Node {
class NodeData : public Node {
public:
int len() const { return len_; }
const u8 *bytes() const { return bytes_; }
};
//test helpers
inline bool traverse(std::function<bool(ExportNode*)> iter) {
return traverse(root_, [&iter](Node *n) -> bool { return iter(reinterpret_cast<ExportNode*>(n)); });
inline bool traverse(std::function<bool(NodeData*, int)> iter) {
auto tmp = [&iter] (Node *n, int depth) -> bool { return iter(reinterpret_cast<NodeData*>(n), depth); };
for (Node *n : root_->children_) {
if (!traverse(n, 1, tmp)) { return false; }
}
return true;
}
#endif
};
Expand Down
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -Wall")
link_directories(../build.testlib)
include_directories(..)
add_definitions(-DTEST)
Expand Down
2 changes: 1 addition & 1 deletion test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ int main(int argc, char *argv[]) {
const char *name;
const char *(*proc)();
} tests[] = {
"patricia", patricia_test,
{"patricia", patricia_test},
};
for (int i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
if (argc <= 1 || std::strcmp(argv[1], tests[i].name) == 0) {
Expand Down
2 changes: 1 addition & 1 deletion test/makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
run:
-mkdir build
cd build && cmake .. && make && ./t
cd build && cmake .. && make clean all && lldb t
19 changes: 7 additions & 12 deletions test/patricia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,25 @@ struct traverse_testcase {
std::vector<const char *> inserts_;
std::vector<const char *> results_;
//test routine
void dump_tree(shutup::Patricia &p) {
p.traverse([] (shutup::Patricia::ExportNode *n) -> bool {
char buffer[256];
std::memcpy(buffer, n->bytes(), n->len());
buffer[n->len()] = 0;
std::printf("key:%s\n", buffer);
return true;
});
}
bool test() {
shutup::Patricia p;
for (auto i : inserts_) {
p.add(i);
}
auto results = results_;
int c = 0;
if (!p.traverse([&c, &results] (shutup::Patricia::ExportNode *n) -> bool {
if (!p.traverse([&c, &results] (shutup::Patricia::NodeData *n, int depth) -> bool {
auto s = results[c++];
return std::strlen(s) == n->len() && memcmp(s, n->bytes(), n->len()) == 0;
})) {
dump_tree(p);
p.dump();
return false;
};
dump_tree(p);
if (c != results.size()) {
p.dump();
return false;
}
p.dump();
return true;
}
};
Expand Down
2 changes: 1 addition & 1 deletion toolchain/testlib.cmake
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
add_definitions(-DTEST)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall")
set(DEBUG True)

0 comments on commit 84641fa

Please sign in to comment.