Prechádzať zdrojové kódy

Added new map types, TIntMap and TPtrMap.

woollybah 10 rokov pred
rodič
commit
d026f6ae9e
4 zmenil súbory, kde vykonal 582 pridanie a 0 odobranie
  1. 166 0
      map.mod/intmap.bmx
  2. 5 0
      map.mod/map.bmx
  3. 244 0
      map.mod/map.c
  4. 167 0
      map.mod/ptrmap.bmx

+ 166 - 0
map.mod/intmap.bmx

@@ -0,0 +1,166 @@
+Strict
+
+
+Extern
+	Function bmx_map_intmap_clear(root:Byte Ptr Ptr)
+	Function bmx_map_intmap_isempty:Int(root:Byte Ptr Ptr)
+	Function bmx_map_intmap_insert(key:Int, value:Object, root:Byte Ptr Ptr)
+	Function bmx_map_intmap_contains:Int(key:Int, root:Byte Ptr Ptr)
+	Function bmx_map_intmap_valueforkey:Object(key:Int, root:Byte Ptr Ptr)
+	Function bmx_map_intmap_remove:Int(key:Int, root:Byte Ptr Ptr)
+	Function bmx_map_intmap_firstnode:Byte Ptr(root:Byte Ptr)
+	Function bmx_map_intmap_nextnode:Byte Ptr(node:Byte Ptr)
+	Function bmx_map_intmap_key:Int(node:Byte Ptr)
+	Function bmx_map_intmap_value:Object(node:Byte Ptr)
+	Function bmx_map_intmap_hasnext:Int(node:Byte Ptr, root:Byte Ptr)
+	Function bmx_map_intmap_copy(dst:Byte Ptr Ptr, _root:Byte Ptr)
+End Extern
+
+Type TIntMap
+
+	Method Delete()
+		Clear
+	End Method
+
+	Method Clear()
+		bmx_map_intmap_clear(Varptr _root)
+	End Method
+	
+	Method IsEmpty()
+		Return bmx_map_intmap_isempty(Varptr _root)
+	End Method
+	
+	Method Insert( key:Int,value:Object )
+		bmx_map_intmap_insert(key, value, Varptr _root)
+	End Method
+
+	Method Contains:Int( key:Int )
+		Return bmx_map_intmap_contains(key, Varptr _root)
+	End Method
+	
+	Method ValueForKey:Object( key:Int )
+		Return bmx_map_intmap_valueforkey(key, Varptr _root)
+	End Method
+	
+	Method Remove( key:Int )
+		Return bmx_map_intmap_remove(key, Varptr _root)
+	End Method
+
+	Method _FirstNode:TIntNode()
+		If Not IsEmpty() Then
+			Local node:TIntNode= New TIntNode
+			node._root = _root
+			Return node
+		Else
+			Return Null
+		End If
+	End Method
+	
+	Method Keys:TIntMapEnumerator()
+		Local nodeenum:TIntNodeEnumerator=New TIntKeyEnumerator
+		nodeenum._node=_FirstNode()
+		Local mapenum:TIntMapEnumerator=New TIntMapEnumerator
+		mapenum._enumerator=nodeenum
+		Return mapenum
+	End Method
+	
+	Method Values:TIntMapEnumerator()
+		Local nodeenum:TIntNodeEnumerator=New TIntValueEnumerator
+		nodeenum._node=_FirstNode()
+		Local mapenum:TIntMapEnumerator=New TIntMapEnumerator
+		mapenum._enumerator=nodeenum
+		Return mapenum
+	End Method
+	
+	Method Copy:TIntMap()
+		Local map:TIntMap=New TIntMap
+		bmx_map_intmap_copy(Varptr map._root, _root)
+		Return map
+	End Method
+	
+	Method ObjectEnumerator:TIntNodeEnumerator()
+		Local nodeenum:TIntNodeEnumerator=New TIntNodeEnumerator
+		nodeenum._node=_FirstNode()
+		Return nodeenum
+	End Method
+
+	Field _root:Byte Ptr
+	
+End Type
+
+Type TIntNode
+	Field _root:Byte Ptr
+	Field _nodePtr:Byte Ptr
+	
+	Method Key:Int()
+		Return bmx_map_intmap_key(_nodePtr)
+	End Method
+	
+	Method Value:Object()
+		Return bmx_map_intmap_value(_nodePtr)
+	End Method
+
+	Method HasNext()
+		Return bmx_map_intmap_hasnext(_nodePtr, _root)
+	End Method
+	
+	Method NextNode:TIntNode()
+		If Not _nodePtr Then
+			_nodePtr = bmx_map_intmap_firstnode(_root)
+		Else
+			_nodePtr = bmx_map_intmap_nextnode(_nodePtr)
+		End If
+
+		Return Self
+	End Method
+	
+End Type
+
+Rem
+bbdoc: Int holder for key returned by TIntMap.Keys() enumerator.
+End Rem
+Type TIntKey
+	Field value:Int
+End Type
+
+Type TIntNodeEnumerator
+	Method HasNext()
+		Return _node.HasNext()
+	End Method
+	
+	Method NextObject:Object()
+		Local node:TIntNode=_node
+		_node=_node.NextNode()
+		Return node
+	End Method
+
+	'***** PRIVATE *****
+		
+	Field _node:TIntNode	
+End Type
+
+Type TIntKeyEnumerator Extends TIntNodeEnumerator
+	Field _key:TIntKey = New TIntKey
+	Method NextObject:Object()
+		Local node:TIntNode=_node
+		_node=_node.NextNode()
+		_key.value = node.Key()
+		Return _key
+	End Method
+End Type
+
+Type TIntValueEnumerator Extends TIntNodeEnumerator
+	Method NextObject:Object()
+		Local node:TIntNode=_node
+		_node=_node.NextNode()
+		Return node.Value()
+	End Method
+End Type
+
+Type TIntMapEnumerator
+	Method ObjectEnumerator:TIntNodeEnumerator()
+		Return _enumerator
+	End Method
+	Field _enumerator:TIntNodeEnumerator
+End Type
+

+ 5 - 0
map.mod/map.bmx

@@ -26,6 +26,10 @@ ModuleInfo "History: Added procedural interface"
 ModuleInfo "History: 1.02 Release"
 ModuleInfo "History: 1.02 Release"
 ModuleInfo "History: Fixed TMap.Remove:TNode not returning node"
 ModuleInfo "History: Fixed TMap.Remove:TNode not returning node"
 
 
+Import "intmap.bmx"
+Import "ptrmap.bmx"
+Import "map.c"
+
 Private
 Private
 
 
 Global nil:TNode=New TNode
 Global nil:TNode=New TNode
@@ -564,3 +568,4 @@ End Rem
 Function CopyMap:TMap( map:TMap )
 Function CopyMap:TMap( map:TMap )
 	Return map.Copy()
 	Return map.Copy()
 End Function
 End Function
+

+ 244 - 0
map.mod/map.c

@@ -0,0 +1,244 @@
+#include "brl.mod/blitz.mod/blitz.h"
+#include "brl.mod/blitz.mod/tree/tree.h"
+
+#define generic_compare(x, y) (((x) > (y)) - ((x) < (y)))
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+struct intmap_node {
+	struct tree_root link;
+	int key;
+	BBOBJECT value;
+};
+
+static int compare_intmap_nodes(const void *x, const void *y) {
+
+        struct intmap_node * node_x = (struct intmap_node *)x;
+        struct intmap_node * node_y = (struct intmap_node *)y;
+
+        return generic_compare(node_x->key, node_y->key);
+}
+
+void bmx_map_intmap_clear(struct tree_root ** root) {
+	struct intmap_node *node;
+	struct intmap_node *tmp;
+	tree_for_each_entry_safe(node, tmp, *root, link) {
+		tree_del(&node->link, root);
+		GC_FREE(node);
+	}
+}
+
+int bmx_map_intmap_isempty(struct tree_root ** root) {
+	return *root == 0;
+}
+
+void bmx_map_intmap_insert( int key, BBObject *value, struct tree_root ** root ) {
+	struct intmap_node * node = (struct intmap_node *)GC_MALLOC(sizeof(struct intmap_node));
+	node->key = key;
+	node->value = value;
+	
+	struct intmap_node * old_node = (struct intmap_node *)tree_map(&node->link, compare_intmap_nodes, root);
+
+	if (&node->link != &old_node->link) {
+		// key already exists. Store the value in this node.
+		old_node->value = value;
+		// delete the new node, since we don't need it
+		GC_FREE(node);
+	}
+}
+
+int bmx_map_intmap_contains(int key, struct tree_root ** root) {
+	struct intmap_node node;
+	node.key = key;
+	
+	struct intmap_node * found = (struct intmap_node *)tree_search(&node, compare_intmap_nodes, *root);
+	if (found) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+BBObject * bmx_map_intmap_valueforkey(int key, struct tree_root ** root) {
+	struct intmap_node node;
+	node.key = key;
+	
+	struct intmap_node * found = (struct intmap_node *)tree_map(&node.link, compare_intmap_nodes, root);
+	
+	if (found) {
+		return found->value;
+	}
+	
+	return &bbNullObject;
+}
+
+int bmx_map_intmap_remove(int key, struct tree_root ** root) {
+	struct intmap_node node;
+	node.key = key;
+	
+	struct intmap_node * found = (struct intmap_node *)tree_search(&node, compare_intmap_nodes, *root);
+	
+	if (found) {
+		tree_del(&found->link, root);
+		GC_FREE(found);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+struct intmap_node * bmx_map_intmap_nextnode(struct intmap_node * node) {
+	return tree_successor(node);
+}
+
+struct intmap_node * bmx_map_intmap_firstnode(struct tree_root * root) {
+	return tree_min(root);
+}
+
+int bmx_map_intmap_key(struct intmap_node * node) {
+	return node->key;
+}
+
+BBObject * bmx_map_intmap_value(struct intmap_node * node) {
+	return node->value;
+}
+
+int bmx_map_intmap_hasnext(struct intmap_node * node, struct tree_root * root) {
+	if (!root) {
+		return 0;
+	}
+	
+	if (!node) {
+		return 1;
+	}
+	
+	return (tree_successor(node) != 0) ? 1 : 0;
+}
+
+void bmx_map_intmap_copy(struct tree_root ** dst_root, struct tree_root * src_root) {
+	struct intmap_node *src_node;
+	struct intmap_node *tmp;
+	tree_for_each_entry_safe(src_node, tmp, src_root, link) {
+		bmx_map_intmap_insert(src_node->key, src_node->value, dst_root);
+	}
+}
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+struct ptrmap_node {
+	struct tree_root link;
+	void * key;
+	BBOBJECT value;
+};
+
+static int compare_ptrmap_nodes(const void *x, const void *y) {
+
+        struct ptrmap_node * node_x = (struct ptrmap_node *)x;
+        struct ptrmap_node * node_y = (struct ptrmap_node *)y;
+
+        return generic_compare(node_x->key, node_y->key);
+}
+
+void bmx_map_ptrmap_clear(struct tree_root ** root) {
+	struct ptrmap_node *node;
+	struct ptrmap_node *tmp;
+	tree_for_each_entry_safe(node, tmp, *root, link) {
+		tree_del(&node->link, root);
+		GC_FREE(node);
+	}
+}
+
+int bmx_map_ptrmap_isempty(struct tree_root ** root) {
+	return *root == 0;
+}
+
+void bmx_map_ptrmap_insert( void * key, BBObject *value, struct tree_root ** root ) {
+	struct ptrmap_node * node = (struct ptrmap_node *)GC_MALLOC(sizeof(struct ptrmap_node));
+	node->key = key;
+	node->value = value;
+	
+	struct ptrmap_node * old_node = (struct ptrmap_node *)tree_map(&node->link, compare_ptrmap_nodes, root);
+
+	if (&node->link != &old_node->link) {
+		// key already exists. Store the value in this node.
+		old_node->value = value;
+		// delete the new node, since we don't need it
+		GC_FREE(node);
+	}
+}
+
+int bmx_map_ptrmap_contains(void * key, struct tree_root ** root) {
+	struct ptrmap_node node;
+	node.key = key;
+	
+	struct ptrmap_node * found = (struct ptrmap_node *)tree_search(&node, compare_ptrmap_nodes, *root);
+	if (found) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+BBObject * bmx_map_ptrmap_valueforkey(void * key, struct tree_root ** root) {
+	struct ptrmap_node node;
+	node.key = key;
+	
+	struct ptrmap_node * found = (struct ptrmap_node *)tree_map(&node.link, compare_ptrmap_nodes, root);
+	
+	if (found) {
+		return found->value;
+	}
+	
+	return &bbNullObject;
+}
+
+int bmx_map_ptrmap_remove(void * key, struct tree_root ** root) {
+	struct ptrmap_node node;
+	node.key = key;
+	
+	struct ptrmap_node * found = (struct ptrmap_node *)tree_search(&node, compare_ptrmap_nodes, *root);
+	
+	if (found) {
+		tree_del(&found->link, root);
+		GC_FREE(found);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+struct ptrmap_node * bmx_map_ptrmap_nextnode(struct ptrmap_node * node) {
+	return tree_successor(node);
+}
+
+struct ptrmap_node * bmx_map_ptrmap_firstnode(struct tree_root * root) {
+	return tree_min(root);
+}
+
+void * bmx_map_ptrmap_key(struct ptrmap_node * node) {
+	return node->key;
+}
+
+BBObject * bmx_map_ptrmap_value(struct ptrmap_node * node) {
+	return node->value;
+}
+
+int bmx_map_ptrmap_hasnext(struct ptrmap_node * node, struct tree_root * root) {
+	if (!root) {
+		return 0;
+	}
+	
+	if (!node) {
+		return 1;
+	}
+	
+	return (tree_successor(node) != 0) ? 1 : 0;
+}
+
+void bmx_map_ptrmap_copy(struct tree_root ** dst_root, struct tree_root * src_root) {
+	struct ptrmap_node *src_node;
+	struct ptrmap_node *tmp;
+	tree_for_each_entry_safe(src_node, tmp, src_root, link) {
+		bmx_map_ptrmap_insert(src_node->key, src_node->value, dst_root);
+	}
+}

+ 167 - 0
map.mod/ptrmap.bmx

@@ -0,0 +1,167 @@
+Strict
+
+
+Extern
+	Function bmx_map_ptrmap_clear(root:Byte Ptr Ptr)
+	Function bmx_map_ptrmap_isempty:Int(root:Byte Ptr Ptr)
+	Function bmx_map_ptrmap_insert(key:Byte Ptr, value:Object, root:Byte Ptr Ptr)
+	Function bmx_map_ptrmap_contains:Int(key:Byte Ptr, root:Byte Ptr Ptr)
+	Function bmx_map_ptrmap_valueforkey:Object(key:Byte Ptr, root:Byte Ptr Ptr)
+	Function bmx_map_ptrmap_remove:Int(key:Byte Ptr, root:Byte Ptr Ptr)
+	Function bmx_map_ptrmap_firstnode:Byte Ptr(root:Byte Ptr)
+	Function bmx_map_ptrmap_nextnode:Byte Ptr(node:Byte Ptr)
+	Function bmx_map_ptrmap_key:Byte Ptr(node:Byte Ptr)
+	Function bmx_map_ptrmap_value:Object(node:Byte Ptr)
+	Function bmx_map_ptrmap_hasnext:Int(node:Byte Ptr, root:Byte Ptr)
+	Function bmx_map_ptrmap_copy(dst:Byte Ptr Ptr, _root:Byte Ptr)
+End Extern
+
+Type TPtrMap
+
+	Method Delete()
+		Clear
+	End Method
+
+	Method Clear()
+		bmx_map_ptrmap_clear(Varptr _root)
+	End Method
+	
+	Method IsEmpty()
+		Return bmx_map_ptrmap_isempty(Varptr _root)
+	End Method
+	
+	Method Insert( key:Int,value:Object )
+		bmx_map_ptrmap_insert(key, value, Varptr _root)
+	End Method
+
+	Method Contains:Int( key:Byte Ptr )
+		Return bmx_map_ptrmap_contains(key, Varptr _root)
+	End Method
+	
+	Method ValueForKey:Object( key:Byte Ptr )
+		Return bmx_map_ptrmap_valueforkey(key, Varptr _root)
+	End Method
+	
+	Method Remove( key:Byte Ptr )
+		Return bmx_map_ptrmap_remove(key, Varptr _root)
+	End Method
+
+	Method _FirstNode:TPtrNode()
+		If Not IsEmpty() Then
+			Local node:TPtrNode= New TPtrNode
+			node._root = _root
+			Return node
+		Else
+			Return Null
+		End If
+	End Method
+	
+	Method Keys:TPtrMapEnumerator()
+		Local nodeenum:TPtrNodeEnumerator=New TPtrKeyEnumerator
+		nodeenum._node=_FirstNode()
+		Local mapenum:TPtrMapEnumerator=New TPtrMapEnumerator
+		mapenum._enumerator=nodeenum
+		Return mapenum
+	End Method
+	
+	Method Values:TPtrMapEnumerator()
+		Local nodeenum:TPtrNodeEnumerator=New TPtrValueEnumerator
+		nodeenum._node=_FirstNode()
+		Local mapenum:TPtrMapEnumerator=New TPtrMapEnumerator
+		mapenum._enumerator=nodeenum
+		Return mapenum
+	End Method
+	
+	Method Copy:TPtrMap()
+		Local map:TPtrMap=New TPtrMap
+		bmx_map_ptrmap_copy(Varptr map._root, _root)
+		Return map
+	End Method
+	
+	Method ObjectEnumerator:TPtrNodeEnumerator()
+		Local nodeenum:TPtrNodeEnumerator=New TPtrNodeEnumerator
+		nodeenum._node=_FirstNode()
+		Return nodeenum
+	End Method
+
+	Field _root:Byte Ptr
+	
+End Type
+
+Type TPtrNode
+	Field _root:Byte Ptr
+	Field _nodePtr:Byte Ptr
+	
+	Method Key:Byte Ptr()
+		Return bmx_map_ptrmap_key(_nodePtr)
+	End Method
+	
+	Method Value:Object()
+		Return bmx_map_ptrmap_value(_nodePtr)
+	End Method
+
+	Method HasNext()
+		Return bmx_map_ptrmap_hasnext(_nodePtr, _root)
+	End Method
+	
+	Method NextNode:TPtrNode()
+		If Not _nodePtr Then
+			_nodePtr = bmx_map_ptrmap_firstnode(_root)
+		Else
+			_nodePtr = bmx_map_ptrmap_nextnode(_nodePtr)
+		End If
+
+		Return Self
+	End Method
+	
+End Type
+
+Rem
+bbdoc: Byte Ptr holder for key returned by TIntMap.Keys() enumerator.
+End Rem
+Type TPtrKey
+	Field value:Byte Ptr
+End Type
+
+Type TPtrNodeEnumerator
+	Method HasNext()
+		Return _node.HasNext()
+	End Method
+	
+	Method NextObject:Object()
+		Local node:TPtrNode=_node
+		_node=_node.NextNode()
+		Return node
+	End Method
+
+	'***** PRIVATE *****
+		
+	Field _node:TPtrNode	
+End Type
+
+Type TPtrKeyEnumerator Extends TPtrNodeEnumerator
+	Field _key:TPtrKey = New TPtrKey
+	Method NextObject:Object()
+		Local node:TPtrNode=_node
+		_node=_node.NextNode()
+		_key.value = node.Key()
+		Return _key
+	End Method
+End Type
+
+Type TPtrValueEnumerator Extends TPtrNodeEnumerator
+	Method NextObject:Object()
+		Local node:TPtrNode=_node
+		_node=_node.NextNode()
+		Return node.Value()
+	End Method
+End Type
+
+Type TPtrMapEnumerator
+	Method ObjectEnumerator:TPtrNodeEnumerator()
+		Return _enumerator
+	End Method
+	Field _enumerator:TPtrNodeEnumerator
+End Type
+
+