- Adjusted some tests while debugging PrettyPrinters

- Adjusted RDTreePrinter to print more "tree-like"
 - Added SetPrinter and MapPrinter
 - Fixed Issues with CStringPrinter and StringPrinter
This commit is contained in:
2025-08-10 00:27:04 -04:00
parent d2be083a8f
commit 9f96155856
13 changed files with 188 additions and 43 deletions

View File

@@ -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

View File

@@ -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)
gdb.printing.register_pretty_printer(obj, containers.printer)
gdb.printing.register_pretty_printer(obj, strings.printer)
gdb.printing.register_pretty_printer(obj, memory.printer)

View File

@@ -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()

View File

@@ -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))
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()

View File

@@ -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))
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()

View File

@@ -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);
}

View File

@@ -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<size_t n>
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

View File

@@ -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);

View File

@@ -31,10 +31,8 @@ namespace fennec::test
const char string[] = "Hello World!";
array<char, sizeof(string)> arr1;
array<char, sizeof(string)> arr2;
std::array<char, sizeof(string)> 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);

View File

@@ -31,7 +31,7 @@ namespace fennec::test
dynarray<int> test1;
dynarray<int> test2;
int n = 10000;
int n = 50;
for (int i = 0; i < n; ++i) {
test1.push_back(i);
test2.push_back(n - i - 1);

View File

@@ -33,7 +33,7 @@ inline void fennec_test_containers_list() {
list<size_t> 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.");

View File

@@ -33,7 +33,7 @@ inline void fennec_test_containers_rdtree() {
rdtree<size_t> 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<size_t>::npos;

View File

@@ -31,18 +31,19 @@ namespace fennec::test
inline void fennec_test_containers_set() {
using type_t = decltype(rand());
std::unordered_set<type_t> ref;
list<type_t> ref;
set<type_t> 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;