diff --git a/.gdbinit b/.gdbinit index 4724c80..b850c4d 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,7 +1,7 @@ python import sys, os.path -print(os.path.abspath("./gdbpp")) -sys.path.insert(0, os.path.abspath("./gdbpp")) +print(os.path.abspath("./gdb")) +sys.path.insert(0, os.path.abspath("./gdb")) import fennec fennec.register_printers(gdb.current_objfile()) end \ No newline at end of file diff --git a/gdbpp/fennec/__init__.py b/gdb/fennec/__init__.py similarity index 86% rename from gdbpp/fennec/__init__.py rename to gdb/fennec/__init__.py index e11ab71..93a75de 100644 --- a/gdbpp/fennec/__init__.py +++ b/gdb/fennec/__init__.py @@ -20,7 +20,12 @@ # GDB CODE ============================================================================================================= import gdb -from .containers import * + +from . import containers +from . import strings +from . import memory def register_printers(obj): - gdb.printing.register_pretty_printer(obj, containers.printer) \ No newline at end of file + gdb.printing.register_pretty_printer(obj, containers.printer) + gdb.printing.register_pretty_printer(obj, strings.printer) + gdb.printing.register_pretty_printer(obj, memory.printer) \ No newline at end of file diff --git a/gdbpp/fennec/containers.py b/gdb/fennec/containers.py similarity index 60% rename from gdbpp/fennec/containers.py rename to gdb/fennec/containers.py index 4d97b68..c007edb 100644 --- a/gdbpp/fennec/containers.py +++ b/gdb/fennec/containers.py @@ -121,7 +121,7 @@ class ListPrinter: class RDTreePrinter: """Print a fennec::rdtree""" - class Iterator: # TODO: Revisit, this is the best I could manage as my first attempt + class Iterator: def __init__(self, tree, node, capacity): self.tree = tree self.capacity = capacity @@ -151,7 +151,7 @@ class RDTreePrinter: nprevc = self.tree[nprev]['child'] if nprev != 18446744073709551615 else 18446744073709551615 child = self.tree[node]['child'] - index = '⠀' * depth * 2 + index = '⠀' * depth * 2 # Uses Braille Space, otherwise it would get eaten as whitespace by parsers if nnext < self.capacity: self.visit.appendleft((nnext, i + 1, depth)) @@ -159,17 +159,20 @@ class RDTreePrinter: if child < self.capacity: self.visit.appendleft((child, 0, depth + 1)) - if child == 18446744073709551615: - if nprevc != 18446744073709551615: - index += '┌' - elif nnext != 18446744073709551615: - index += '├' - else: - index += '└' - elif nprevc != 18446744073709551615: - index += '─' - else: - index += '└' + if child == 18446744073709551615: # If the child is NULL + if nprevc != 18446744073709551615: # And there was a previous child + if nnext != 18446744073709551615: # And there is a next node + index += '┌' # Begin new branch + else: # Otherwise + index += '─' # Add single branch + elif nnext != 18446744073709551615: # Else if there is a next node + index += '├' # Continue Branch + else: # Otherwise + index += '└' # Terminate Branch + elif nprevc != 18446744073709551615: # Else if there is a previous child (this node has a child) + index += '─' # Add single branch + else: # Otherwise + index += '└' # Terminate Branch index += '─' index += '[{}]'.format(i) @@ -195,6 +198,104 @@ class RDTreePrinter: return self.Iterator(self.tree, 0, self.capacity) +# SET ================================================================================================================== + +class SetPrinter: + + class Iterator: + def __init__(self, table, capacity): + self.table = table + self.capacity = capacity + self.node = 0 + self.index = 0 + + def __iter__(self): + return self + + def __next__(self): + while self.node < self.capacity: + if self.table[self.node]['value']['_set']: + break + self.node = self.node + 1 + + if self.node >= self.capacity: + raise StopIteration + + i = self.index + value = self.table[self.node]['value']['_val'] + self.node = self.node + 1 + self.index = self.index + 1 + return '[{}]'.format(i), value + + def __init__(self, val): + self.table = val['_alloc']['_data'] + self.capacity = val['_alloc']['_capacity'] + self.size = val['_size'] + + def to_string(self): + if self.size == 0: + return "{ empty }" + return "{ size = " + str(self.size) + " }" + + def children(self): + return self.Iterator(self.table, self.capacity) + + +# MAP ================================================================================================================== + +class MapPrinter: + + class Iterator: + def __init__(self, table, capacity): + self.table = table + self.capacity = capacity + self.node = 0 + self.index = 0 + self.move = False + + def __iter__(self): + return self + + def __next__(self): + while self.node < self.capacity: + if self.table[self.node]['value']['_set']: + break + self.node = self.node + 1 + + if self.node >= self.capacity: + raise StopIteration + + i = self.index + pair = self.table[self.node]['value']['_val'] + key = pair['first'] + val = pair['second'] + + if not self.move: + self.move = True + return ('key' + str(i), key) + else: + self.move = False + self.index = self.index + 1 + self.node = self.node + 1 + return ('value' + str(i), val) + + def __init__(self, val): + self.table = val['_set']['_alloc']['_data'] + self.capacity = val['_set']['_alloc']['_capacity'] + self.size = val['_set']['_size'] + + def to_string(self): + if self.size == 0: + return "{ empty }" + return "{ size = " + str(self.size) + " }" + + def children(self): + return self.Iterator(self.table, self.capacity) + + def display_hint(self): + return 'map' + + # GDB Code ============================================================================================================= def register_printers(): @@ -206,6 +307,8 @@ def register_printers(): pp.add_printer('dynarray', '^fennec::dynarray<.*>$', DynArrayPrinter) pp.add_printer('list', '^fennec::list<.*>$', ListPrinter) pp.add_printer('rdtree', '^fennec::rdtree<.*>$', RDTreePrinter) + pp.add_printer('set', '^fennec::set<.*>$', SetPrinter) + pp.add_printer('map', '^fennec::map<.*>$', MapPrinter) return pp printer = register_printers() diff --git a/gdbpp/fennec/memory.py b/gdb/fennec/memory.py similarity index 75% rename from gdbpp/fennec/memory.py rename to gdb/fennec/memory.py index a66bddd..64b36e7 100644 --- a/gdbpp/fennec/memory.py +++ b/gdb/fennec/memory.py @@ -25,9 +25,20 @@ class AllocationPrinter: self.val = val def to_string(self): - return "fennec::allocation = " + str(self.val['_capacity']) + return "{ capacity = " + str(self.val['_capacity']) + " }" def children(self): size = int(self.val['_capacity']) start = self.val['_data'] - return (('[{}]'.format(i), start[i]) for i in range(size)) \ No newline at end of file + return (('[{}]'.format(i), start[i]) for i in range(size)) + + +# GDB Code ============================================================================================================= + +def register_printers(): + print("registering memory") + pp = gdb.printing.RegexpCollectionPrettyPrinter("fennec::memory") + pp.add_printer('allocation', '^fennec::allocation<.*>$', AllocationPrinter) + return pp + +printer = register_printers() \ No newline at end of file diff --git a/gdbpp/fennec/strings.py b/gdb/fennec/strings.py similarity index 58% rename from gdbpp/fennec/strings.py rename to gdb/fennec/strings.py index 5877ab6..6ebfcec 100644 --- a/gdbpp/fennec/strings.py +++ b/gdb/fennec/strings.py @@ -24,24 +24,39 @@ class CStringPrinter: def __init__(self, val): self.val = val - def to_string(self): - return str(self.val['_cstr']) + def display_hint(self): + return 'string' - def children(self): - size = int(self.val['_size']) - start = self.val['_cstr'] - return (('[{}]'.format(i), start[i]) for i in range(size)) + def to_string(self): + value = "\"" + self.val['_str'].string('', 'replace', self.val['_size'] - 1) + "\"" + return value + + def display_hint(self): + return 'string' # STRING =============================================================================================================== class StringPrinter: def __init__(self, val): - self.val = val + self.val = val['_str'] def to_string(self): - return str(self.val['_str']['_data']) + value = "\"" + self.val['_data'].string('', 'replace', self.val['_capacity'] - 1) + "\"" + return value - def children(self): - size = int(self.val['_str']['_capacity']) - start = self.val['_str']['_data'] - return (('[{}]'.format(i), start[i]) for i in range(size)) \ No newline at end of file + def display_hint(self): + return 'string' + + +# GDB Code ============================================================================================================= + +def register_printers(): + print("registering strings") + pp = gdb.printing.RegexpCollectionPrettyPrinter("fennec::strings") + pp.add_printer('cstring', '^fennec::cstring$', CStringPrinter) + pp.add_printer('wcstring', '^fennec::wcstring$', CStringPrinter) + pp.add_printer('string', '^fennec::_string<.*>$', StringPrinter) + pp.add_printer('wstring', '^fennec::_wstring<.*>$', StringPrinter) + return pp + +printer = register_printers() \ No newline at end of file diff --git a/include/fennec/containers/set.h b/include/fennec/containers/set.h index 548c69d..397fcfa 100644 --- a/include/fennec/containers/set.h +++ b/include/fennec/containers/set.h @@ -235,7 +235,7 @@ public: int p0 = psl - n, p1 = psl + n; bool c0 = false, c1 = false; - if ((c0 = (p0 > 0 && _alloc[i0].psl >= p0)) && _alloc[i0].value) { + if ((c0 = (p0 >= 0 && _alloc[i0].psl >= p0)) && _alloc[i0].value) { if (*_alloc[i0].value == val) { return iterator(this, i); } diff --git a/include/fennec/langproc/strings/string.h b/include/fennec/langproc/strings/string.h index 378279c..73eb71c 100644 --- a/include/fennec/langproc/strings/string.h +++ b/include/fennec/langproc/strings/string.h @@ -92,6 +92,16 @@ public: _str[n] = '\0'; } + /// + /// \brief Buffer Constructor, wraps the provided C-Style string + /// \param str the buffer to wrap + /// \tparam n the number of characters in the buffer plus the null terminator + template + constexpr _string(char(&str)[n]) + : _str(str, n) { + assert(_str[n - 1] == '\0', "Invalid NTBS."); + } + /// /// \brief Buffer Copy Constructor /// \param str the buffer to copy diff --git a/test/main.cpp b/test/main.cpp index a92ba2c..dc8b850 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -30,6 +30,8 @@ int main(int, char **) { + srand(0); + fennec_test_header("fennec-test, a program to execute unit tests for fennec"); fennec_test_spacer(2); diff --git a/test/tests/containers/test_array.h b/test/tests/containers/test_array.h index ab8061a..dad2557 100644 --- a/test/tests/containers/test_array.h +++ b/test/tests/containers/test_array.h @@ -31,10 +31,8 @@ namespace fennec::test const char string[] = "Hello World!"; array arr1; array arr2; - std::array stdarr; strcpy(&arr1[0], string); strcpy(&arr2[0], string); - strcpy(&stdarr[0], string); fennec_test_run(strcmp(&arr1[0], string), 0); fennec_test_run(strcmp(&arr2[0], string), 0); diff --git a/test/tests/containers/test_dynarray.h b/test/tests/containers/test_dynarray.h index 6884ca9..c845aa5 100644 --- a/test/tests/containers/test_dynarray.h +++ b/test/tests/containers/test_dynarray.h @@ -31,7 +31,7 @@ namespace fennec::test dynarray test1; dynarray test2; - int n = 10000; + int n = 50; for (int i = 0; i < n; ++i) { test1.push_back(i); test2.push_back(n - i - 1); diff --git a/test/tests/containers/test_list.h b/test/tests/containers/test_list.h index d0530cc..fe7631a 100644 --- a/test/tests/containers/test_list.h +++ b/test/tests/containers/test_list.h @@ -33,7 +33,7 @@ inline void fennec_test_containers_list() { list test; - const size_t n = 10000; + const size_t n = 50; for (size_t i = 0; i < n; ++i) { const size_t p = rand() % (i + 1); assertf(test.insert(p, i) == i, "List Construct Test Failed."); diff --git a/test/tests/containers/test_rdtree.h b/test/tests/containers/test_rdtree.h index 7305b9f..c2d9ed1 100644 --- a/test/tests/containers/test_rdtree.h +++ b/test/tests/containers/test_rdtree.h @@ -33,7 +33,7 @@ inline void fennec_test_containers_rdtree() { rdtree test; - const size_t n = 10000; + const size_t n = 50; for (size_t i = 0; i < n; ++i) { const size_t parent = rand() % (i + 1); const size_t child = rdtree::npos; diff --git a/test/tests/containers/test_set.h b/test/tests/containers/test_set.h index 4f543cf..03f0f13 100644 --- a/test/tests/containers/test_set.h +++ b/test/tests/containers/test_set.h @@ -31,18 +31,19 @@ namespace fennec::test inline void fennec_test_containers_set() { using type_t = decltype(rand()); - std::unordered_set ref; + list ref; set test; - srand(0); - for (int i = 0; i < 10000; ++i) { + int n = 50; + for (int i = 0; i < n; ++i) { type_t v = rand(); - ref.insert(v); test.insert(v); + ref.push_back(v); } - for (int i = 0; i < 10000; ++i) { - assertf(ref.contains(i) == test.contains(i), "set test failed"); + for (int i = 0; i < n; ++i) { + type_t v = ref[i]; + assertf(test.contains(v), "set test failed"); } std::cout << "passed" << std::endl;