diff --git a/.gdbinit b/.gdbinit
index 3a76adc..4724c80 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -1 +1,7 @@
-source ./gdb/printers.py
\ No newline at end of file
+python
+import sys, os.path
+print(os.path.abspath("./gdbpp"))
+sys.path.insert(0, os.path.abspath("./gdbpp"))
+import fennec
+fennec.register_printers(gdb.current_objfile())
+end
\ No newline at end of file
diff --git a/gdb/printers.py b/gdb/printers.py
deleted file mode 100644
index 6b12ed3..0000000
--- a/gdb/printers.py
+++ /dev/null
@@ -1,120 +0,0 @@
-import gdb
-import sys
-
-
-# CSTRING ==============================================================================================================
-class CStringPrinter:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return self.val['_cstr']
-
- def children(self):
- size = int(self.val['_size'])
- start = self.val['_cstr']
- return (('[{}]'.format(i), start[i]) for i in range(size))
-
-
-# ALLOCATION ===========================================================================================================
-class StringPrinter:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return str("fennec::allocation = {value}").format(value = self.val['_str']['_data'])
-
- def children(self):
- size = int(self.val['_str']['_capacity'])
- start = self.val['_str']['_data']
- return (('[{}]'.format(i), start[i]) for i in range(size))
-
-# OPTIONAL =================================================================================================================
-class OptionalPrinter:
- """Print a fennec::optional"""
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- is_initialized = self.val['_set']
- if is_initialized:
- return "Value = {}".format(self.val['_val'])
- else:
- return "empty"
-
-
-# ALLOCATION ===========================================================================================================
-class AllocationPrinter:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return "fennec::allocation"
-
- def children(self):
- size = int(self.val['_capacity'])
- start = self.val['_data']
- return (('[{}]'.format(i), start[i]) for i in range(size))
-
-
-# LIST =================================================================================================================
-class ListPrinter:
- """Print a fennec::list"""
-
- class Iterator:
- def __init__(self, val):
- self.list = val
- self.node = self.list['_root']
- #self.index = 0
-
- def __iter__(self):
- return self
-
- def __next__(self):
- if self.node == 18446744073709551615:
- raise StopIteration
-
-
- value = self.list['_table']['_data'][self.node]['value']['_val']
- self.node = self.list['_table']['_data'][self.node]['next']
- return value
- #index = self.index
- #self.index = self.index + 1
- #value = self.list['_table']['_data'][self.node]['value']['_val']
- #self.node = self.list['_table']['_data'][self.node]['next']
- #return str("value[{index}] = {value}").format(index = index, value = value)
-
-
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return "fennec::list"
-
- def children(self):
- return enumerate(self.Iterator(self.val))
-
-
-# GDB CODE =============================================================================================================
-
-
-def lookup_function(val):
- type = str(val.type)
- if type.startswith('const '):
- type = type[6:]
- if type.startswith('fennec::cstring') or type.startswith('fennec::wcstring'):
- return CStringPrinter(val)
- if type.startswith('fennec::string') or type.startswith('fennec::wstring'):
- return StringPrinter(val)
- if type.startswith('fennec::optional'):
- return OptionalPrinter(val)
- if type.startswith('fennec::list'):
- return ListPrinter(val)
- if type.startswith('fennec::allocation'):
- return AllocationPrinter(val)
- return None
-
-
-gdb.pretty_printers.append(lookup_function)
\ No newline at end of file
diff --git a/gdbpp/fennec/__init__.py b/gdbpp/fennec/__init__.py
new file mode 100644
index 0000000..e11ab71
--- /dev/null
+++ b/gdbpp/fennec/__init__.py
@@ -0,0 +1,26 @@
+# ======================================================================================================================
+# fennec, a free and open source game engine
+# Copyright © 2025 Medusa Slockbower
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+# ======================================================================================================================
+
+
+# GDB CODE =============================================================================================================
+
+import gdb
+from .containers import *
+
+def register_printers(obj):
+ gdb.printing.register_pretty_printer(obj, containers.printer)
\ No newline at end of file
diff --git a/gdbpp/fennec/containers.py b/gdbpp/fennec/containers.py
new file mode 100644
index 0000000..4d97b68
--- /dev/null
+++ b/gdbpp/fennec/containers.py
@@ -0,0 +1,211 @@
+# ======================================================================================================================
+# fennec, a free and open source game engine
+# Copyright © 2025 Medusa Slockbower
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+# ======================================================================================================================
+
+import gdb
+import re
+from collections import deque
+
+# OPTIONAL =============================================================================================================
+class OptionalPrinter:
+ """Print a fennec::optional"""
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ is_initialized = self.val['_set']
+ if is_initialized:
+ return "{{ value = {} }}".format(self.val['_val'])
+ else:
+ return "{ empty }"
+
+# OPTIONAL =============================================================================================================
+class PairPrinter:
+ """Print a fennec::optional"""
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "{ first = " + str(self.val['first']) + ", second = " + str(self.val['second']) + " }"
+
+ def children(self):
+ return ("first", self.val['first']), ("second", self.val['second'])
+
+
+# ARRAY ================================================================================================================
+class ArrayPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "{ length = " + str(self.val['elements'].type.range()[1] + 1) + " }"
+
+ def display_hint(self):
+ return 'array'
+
+ def children(self):
+ start = self.val['elements']
+ return (('[{}]'.format(i), start[i]) for i in range(0, self.val['elements'].type.range()[1] + 1))
+
+
+# DYNARRAY =============================================================================================================
+class DynArrayPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "{ length " + str(self.val['_size']) + ", capacity " + str(self.val['_alloc']['_capacity']) + " }"
+
+ def children(self):
+ size = int(self.val['_size'])
+ start = self.val['_alloc']['_data']
+ return (('[{}]'.format(i), start[i]) for i in range(size))
+
+
+# LIST =================================================================================================================
+class ListPrinter:
+ """Print a fennec::list"""
+
+ class Iterator:
+ def __init__(self, val):
+ self.list = val
+ self.node = self.list['_root']
+ self.index = 0
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ if self.node == 18446744073709551615:
+ raise StopIteration
+
+ i = self.index
+ self.index = self.index + 1
+ value = self.list['_table']['_data'][self.node]['value']['_val']
+ self.node = self.list['_table']['_data'][self.node]['next']
+ return '[{}]'.format(i), value
+
+
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "{ length " + str(self.val['_size']) + ", capacity " + str(self.val['_table']['_capacity']) + " }"
+
+ def children(self):
+ return self.Iterator(self.val)
+
+ def display_hint(self):
+ return 'array'
+
+
+# RDTREE ===============================================================================================================
+
+class RDTreePrinter:
+ """Print a fennec::rdtree"""
+
+ class Iterator: # TODO: Revisit, this is the best I could manage as my first attempt
+ def __init__(self, tree, node, capacity):
+ self.tree = tree
+ self.capacity = capacity
+ self.visit = deque()
+
+ self.visit.append((node, 0, 0))
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ if len(self.visit) == 0:
+ raise StopIteration
+
+ node = self.visit[0][0]
+ i = self.visit[0][1]
+ depth = self.visit[0][2]
+ self.visit.popleft()
+
+ opt = self.tree[node]['value']
+ value = None
+ if opt['_set']:
+ value = opt['_val']
+
+ nnext = self.tree[node]['next']
+ nprev = self.tree[node]['prev']
+ nprevc = self.tree[nprev]['child'] if nprev != 18446744073709551615 else 18446744073709551615
+ child = self.tree[node]['child']
+
+ index = '⠀' * depth * 2
+
+ if nnext < self.capacity:
+ self.visit.appendleft((nnext, i + 1, depth))
+
+ 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 += '└'
+
+ index += '─'
+ index += '[{}]'.format(i)
+ print(index)
+ if value is None:
+ return index, '{ empty }'
+ return index, value
+
+
+ def __init__(self, val):
+ self.tree = val['_table']['_data']
+ self.size = val['_size']
+ self.capacity = val['_table']['_capacity']
+
+ def to_string(self):
+ if self.size == 0:
+ return "{ empty }"
+ return "{ size = " + str(self.size) + " }"
+
+ def children(self):
+ if self.size == 0:
+ return None
+ return self.Iterator(self.tree, 0, self.capacity)
+
+
+# GDB Code =============================================================================================================
+
+def register_printers():
+ print("registering containers")
+ pp = gdb.printing.RegexpCollectionPrettyPrinter("fennec::containers")
+ pp.add_printer('optional', '^fennec::optional<.*>$', OptionalPrinter)
+ pp.add_printer('pair', '^fennec::pair<.*>$', PairPrinter)
+ pp.add_printer('array', '^fennec::array<.*>$', ArrayPrinter)
+ pp.add_printer('dynarray', '^fennec::dynarray<.*>$', DynArrayPrinter)
+ pp.add_printer('list', '^fennec::list<.*>$', ListPrinter)
+ pp.add_printer('rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
+ return pp
+
+printer = register_printers()
diff --git a/gdbpp/fennec/memory.py b/gdbpp/fennec/memory.py
new file mode 100644
index 0000000..a66bddd
--- /dev/null
+++ b/gdbpp/fennec/memory.py
@@ -0,0 +1,33 @@
+# ======================================================================================================================
+# fennec, a free and open source game engine
+# Copyright © 2025 Medusa Slockbower
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+# ======================================================================================================================
+
+import gdb
+import re
+
+# ALLOCATION ===========================================================================================================
+class AllocationPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "fennec::allocation = " + 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
diff --git a/gdbpp/fennec/strings.py b/gdbpp/fennec/strings.py
new file mode 100644
index 0000000..5877ab6
--- /dev/null
+++ b/gdbpp/fennec/strings.py
@@ -0,0 +1,47 @@
+# ======================================================================================================================
+# fennec, a free and open source game engine
+# Copyright © 2025 Medusa Slockbower
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+# ======================================================================================================================
+
+import gdb
+import re
+
+# CSTRING ==============================================================================================================
+class CStringPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return str(self.val['_cstr'])
+
+ def children(self):
+ size = int(self.val['_size'])
+ start = self.val['_cstr']
+ return (('[{}]'.format(i), start[i]) for i in range(size))
+
+
+# STRING ===============================================================================================================
+class StringPrinter:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return str(self.val['_str']['_data'])
+
+ 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
diff --git a/test/tests/containers/test_array.h b/test/tests/containers/test_array.h
index dad2557..ab8061a 100644
--- a/test/tests/containers/test_array.h
+++ b/test/tests/containers/test_array.h
@@ -31,8 +31,10 @@ 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);