Bladeren bron

Fixed TStringMap issues.
Added generic TObjectMap.

woollybah 10 jaren geleden
bovenliggende
commit
976ee92667
3 gewijzigde bestanden met toevoegingen van 353 en 5 verwijderingen
  1. 1 0
      map.mod/map.bmx
  2. 132 5
      map.mod/map.c
  3. 220 0
      map.mod/objectmap.bmx

+ 1 - 0
map.mod/map.bmx

@@ -32,6 +32,7 @@ ModuleInfo "History: Fixed TMap.Remove:TNode not returning node"
 Import "intmap.bmx"
 Import "ptrmap.bmx"
 Import "stringmap.bmx"
+Import "objectmap.bmx"
 Import "map.c"
 
 Private

+ 132 - 5
map.mod/map.c

@@ -288,7 +288,7 @@ void bmx_map_stringmap_insert( BBString * key, BBObject *value, struct tree_root
 	node->value = value;
 	BBRETAIN(value);
 	
-	struct stringmap_node * old_node = (struct stringmap_node *)tree_map(&node->link, compare_intmap_nodes, root);
+	struct stringmap_node * old_node = (struct stringmap_node *)tree_map(&node->link, compare_stringmap_nodes, root);
 
 	if (&node->link != &old_node->link) {
 		BBRELEASE(old_node->key);
@@ -304,7 +304,7 @@ int bmx_map_stringmap_contains(BBString * key, struct tree_root ** root) {
 	struct stringmap_node node;
 	node.key = key;
 	
-	struct stringmap_node * found = (struct stringmap_node *)tree_search(&node, compare_intmap_nodes, *root);
+	struct stringmap_node * found = (struct stringmap_node *)tree_search(&node, compare_stringmap_nodes, *root);
 	if (found) {
 		return 1;
 	} else {
@@ -312,11 +312,11 @@ int bmx_map_stringmap_contains(BBString * key, struct tree_root ** root) {
 	}
 }
 
-BBObject * bmx_map_stringmap_valueforkey(int key, struct tree_root ** root) {
+BBObject * bmx_map_stringmap_valueforkey(BBString * key, struct tree_root ** root) {
 	struct stringmap_node node;
 	node.key = key;
 	
-	struct stringmap_node * found = (struct stringmap_node *)tree_search(&node, compare_intmap_nodes, *root);
+	struct stringmap_node * found = (struct stringmap_node *)tree_search(&node, compare_stringmap_nodes, *root);
 	
 	if (found) {
 		return found->value;
@@ -329,7 +329,7 @@ int bmx_map_stringmap_remove(int key, struct tree_root ** root) {
 	struct stringmap_node node;
 	node.key = key;
 	
-	struct stringmap_node * found = (struct stringmap_node *)tree_search(&node, compare_intmap_nodes, *root);
+	struct stringmap_node * found = (struct stringmap_node *)tree_search(&node, compare_stringmap_nodes, *root);
 	
 	if (found) {
 		BBRELEASE(found->key);
@@ -377,3 +377,130 @@ void bmx_map_stringmap_copy(struct tree_root ** dst_root, struct tree_root * src
 		bmx_map_stringmap_insert(src_node->key, src_node->value, dst_root);
 	}
 }
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+struct objectmap_node {
+	struct tree_root link;
+	BBOBJECT key;
+	BBOBJECT value;
+};
+
+static int compare_objectmap_nodes(const void *x, const void *y) {
+        struct objectmap_node * node_x = (struct objectmap_node *)x;
+        struct objectmap_node * node_y = (struct objectmap_node *)y;
+
+        return node_x->key->clas->Compare(node_x->key, node_y->key);
+}
+
+void bmx_map_objectmap_clear(struct tree_root ** root) {
+	struct objectmap_node *node;
+	struct objectmap_node *tmp;
+	tree_for_each_entry_safe(node, tmp, *root, link) {
+		BBRELEASE(node->key);
+		BBRELEASE(node->value);
+		tree_del(&node->link, root);
+		free(node);
+	}
+}
+
+int bmx_map_objectmap_isempty(struct tree_root ** root) {
+	return *root == 0;
+}
+
+void bmx_map_objectmap_insert( BBObject * key, BBObject *value, struct tree_root ** root) {
+	struct objectmap_node * node = (struct objectmap_node *)malloc(sizeof(struct objectmap_node));
+	node->key = key;
+	BBRETAIN(key);
+	node->value = value;
+	BBRETAIN(value);
+	
+	struct objectmap_node * old_node = (struct objectmap_node *)tree_map(&node->link, compare_objectmap_nodes, root);
+
+	if (&node->link != &old_node->link) {
+		BBRELEASE(node->key);
+		BBRELEASE(node->value);
+		// key already exists. Store the value in this node.
+		old_node->value = value;
+		// delete the new node, since we don't need it
+		free(node);
+	}
+}
+
+int bmx_map_objectmap_contains(BBObject * key, struct tree_root ** root) {
+	struct objectmap_node node;
+	node.key = key;
+	
+	struct objectmap_node * found = (struct objectmap_node *)tree_search(&node, compare_objectmap_nodes, *root);
+	if (found) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+BBObject * bmx_map_objectmap_valueforkey(BBObject * key, struct tree_root ** root) {
+	struct objectmap_node node;
+	node.key = key;
+	
+	struct objectmap_node * found = (struct objectmap_node *)tree_search(&node, compare_objectmap_nodes, *root);
+	
+	if (found) {
+		return found->value;
+	}
+	
+	return &bbNullObject;
+}
+
+int bmx_map_objectmap_remove(int key, struct tree_root ** root) {
+	struct objectmap_node node;
+	node.key = key;
+	
+	struct objectmap_node * found = (struct objectmap_node *)tree_search(&node, compare_objectmap_nodes, *root);
+	
+	if (found) {
+		BBRELEASE(found->key);
+		BBRELEASE(found->value);
+		tree_del(&found->link, root);
+		free(found);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+struct objectmap_node * bmx_map_objectmap_nextnode(struct objectmap_node * node) {
+	return tree_successor(node);
+}
+
+struct objectmap_node * bmx_map_objectmap_firstnode(struct tree_root * root) {
+	return tree_min(root);
+}
+
+BBObject * bmx_map_objectmap_key(struct objectmap_node * node) {
+	return node->key;
+}
+
+BBObject * bmx_map_objectmap_value(struct objectmap_node * node) {
+	return node->value;
+}
+
+int bmx_map_objectmap_hasnext(struct objectmap_node * node, struct tree_root * root) {
+	if (!root) {
+		return 0;
+	}
+	
+	if (!node) {
+		return 1;
+	}
+	
+	return (tree_successor(node) != 0) ? 1 : 0;
+}
+
+void bmx_map_objectmap_copy(struct tree_root ** dst_root, struct tree_root * src_root) {
+	struct objectmap_node *src_node;
+	struct objectmap_node *tmp;
+	tree_for_each_entry_safe(src_node, tmp, src_root, link) {
+		bmx_map_objectmap_insert(src_node->key, src_node->value, dst_root);
+	}
+}

+ 220 - 0
map.mod/objectmap.bmx

@@ -0,0 +1,220 @@
+Strict
+
+
+Extern
+	Function bmx_map_objectmap_clear(root:Byte Ptr Ptr)
+	Function bmx_map_objectmap_isempty:Int(root:Byte Ptr Ptr)
+	Function bmx_map_objectmap_insert(key:Object, value:Object, root:Byte Ptr Ptr)
+	Function bmx_map_objectmap_contains:Int(key:Object, root:Byte Ptr Ptr)
+	Function bmx_map_objectmap_valueforkey:Object(key:Object, root:Byte Ptr Ptr)
+	Function bmx_map_objectmap_remove:Int(key:Object, root:Byte Ptr Ptr)
+	Function bmx_map_objectmap_firstnode:Byte Ptr(root:Byte Ptr)
+	Function bmx_map_objectmap_nextnode:Byte Ptr(node:Byte Ptr)
+	Function bmx_map_objectmap_key:Object(node:Byte Ptr)
+	Function bmx_map_objectmap_value:Object(node:Byte Ptr)
+	Function bmx_map_objectmap_hasnext:Int(node:Byte Ptr, root:Byte Ptr)
+	Function bmx_map_objectmap_copy(dst:Byte Ptr Ptr, _root:Byte Ptr)
+End Extern
+
+Type TObjectMap
+
+	Method Delete()
+		Clear
+	End Method
+
+	Method Clear()
+?ngcmod
+		If Not IsEmpty() Then
+			_modCount :+ 1
+		End If
+?
+		bmx_map_objectmap_clear(Varptr _root)
+	End Method
+	
+	Method IsEmpty()
+		Return bmx_map_objectmap_isempty(Varptr _root)
+	End Method
+	
+	Method Insert( key:Object,value:Object )
+		bmx_map_objectmap_insert(key, value, Varptr _root)
+?ngcmod
+		_modCount :+ 1
+?
+	End Method
+
+	Method Contains:Int( key:Object )
+		Return bmx_map_objectmap_contains(key, Varptr _root)
+	End Method
+	
+	Method ValueForKey:Object( key:Object )
+		Return bmx_map_objectmap_valueforkey(key, Varptr _root)
+	End Method
+	
+	Method Remove( key:Object )
+?ngcmod
+		_modCount :+ 1
+?
+		Return bmx_map_objectmap_remove(key, Varptr _root)
+	End Method
+
+	Method _FirstNode:TObjectNode()
+		If Not IsEmpty() Then
+			Local node:TObjectNode= New TObjectNode
+			node._root = _root
+			Return node
+		Else
+			Return Null
+		End If
+	End Method
+	
+	Method Keys:TObjectMapEnumerator()
+		Local nodeenum:TObjectNodeEnumerator
+		If Not isEmpty() Then
+			nodeenum=New TObjectKeyEnumerator
+			nodeenum._node=_FirstNode()
+		Else
+			nodeenum=New TObjectEmptyEnumerator
+		End If
+		Local mapenum:TObjectMapEnumerator=New TObjectMapEnumerator
+		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+?ngcmod
+		nodeenum._expectedModCount = _modCount
+?
+		Return mapenum
+	End Method
+	
+	Method Values:TObjectMapEnumerator()
+		Local nodeenum:TObjectNodeEnumerator
+		If Not isEmpty() Then
+			nodeenum=New TObjectValueEnumerator
+			nodeenum._node=_FirstNode()
+		Else
+			nodeenum=New TObjectEmptyEnumerator
+		End If
+		Local mapenum:TObjectMapEnumerator=New TObjectMapEnumerator
+		mapenum._enumerator=nodeenum
+		nodeenum._map = Self
+?ngcmod
+		nodeenum._expectedModCount = _modCount
+?
+		Return mapenum
+	End Method
+	
+	Method Copy:TObjectMap()
+		Local map:TObjectMap=New TObjectMap
+		bmx_map_objectmap_copy(Varptr map._root, _root)
+		Return map
+	End Method
+	
+	Method ObjectEnumerator:TObjectNodeEnumerator()
+		Local nodeenum:TObjectNodeEnumerator=New TObjectNodeEnumerator
+		nodeenum._node=_FirstNode()
+		nodeenum._map = Self
+?ngcmod
+		nodeenum._expectedModCount = _modCount
+?
+		Return nodeenum
+	End Method
+
+	Field _root:Byte Ptr
+
+?ngcmod
+	Field _modCount:Int
+?
+
+End Type
+
+Type TObjectNode
+	Field _root:Byte Ptr
+	Field _nodePtr:Byte Ptr
+	
+	Method Key:Object()
+		Return bmx_map_objectmap_key(_nodePtr)
+	End Method
+	
+	Method Value:Object()
+		Return bmx_map_objectmap_value(_nodePtr)
+	End Method
+
+	Method HasNext()
+		Return bmx_map_objectmap_hasnext(_nodePtr, _root)
+	End Method
+	
+	Method NextNode:TObjectNode()
+		If Not _nodePtr Then
+			_nodePtr = bmx_map_objectmap_firstnode(_root)
+		Else
+			_nodePtr = bmx_map_objectmap_nextnode(_nodePtr)
+		End If
+
+		Return Self
+	End Method
+	
+End Type
+
+Type TObjectNodeEnumerator
+	Method HasNext()
+		Local has:Int = _node.HasNext()
+		If Not has Then
+			_map = Null
+		End If
+		Return has
+	End Method
+	
+	Method NextObject:Object()
+?ngcmod
+		Assert _expectedModCount = _map._modCount, "TObjectMap Concurrent Modification"
+?
+		Local node:TObjectNode=_node
+		_node=_node.NextNode()
+		Return node
+	End Method
+
+	'***** PRIVATE *****
+		
+	Field _node:TObjectNode	
+
+	Field _map:TObjectMap
+?ngcmod
+	Field _expectedModCount:Int
+?
+End Type
+
+Type TObjectKeyEnumerator Extends TObjectNodeEnumerator
+	Method NextObject:Object()
+?ngcmod
+		Assert _expectedModCount = _map._modCount, "TObjectMap Concurrent Modification"
+?
+		Local node:TObjectNode=_node
+		_node=_node.NextNode()
+		Return node.Key()
+	End Method
+End Type
+
+Type TObjectValueEnumerator Extends TObjectNodeEnumerator
+	Method NextObject:Object()
+?ngcmod
+		Assert _expectedModCount = _map._modCount, "TObjectMap Concurrent Modification"
+?
+		Local node:TObjectNode=_node
+		_node=_node.NextNode()
+		Return node.Value()
+	End Method
+End Type
+
+Type TObjectMapEnumerator
+	Method ObjectEnumerator:TObjectNodeEnumerator()
+		Return _enumerator
+	End Method
+	Field _enumerator:TObjectNodeEnumerator
+End Type
+
+Type TObjectEmptyEnumerator Extends TObjectNodeEnumerator
+	Method HasNext()
+		_map = Null
+		Return False
+	End Method
+End Type
+
+