added stix_deletedic() and Dictionary>>removeKey: and its derivatives
This commit is contained in:
		@ -259,6 +259,16 @@ class Apex(nil)
 | 
			
		||||
		^false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method notError
 | 
			
		||||
	{
 | 
			
		||||
		^true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method(#class) notError
 | 
			
		||||
	{
 | 
			
		||||
		^true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	## -------------------------------------------------------
 | 
			
		||||
	## -------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -320,32 +330,37 @@ class Apex(nil)
 | 
			
		||||
	 * ------------------------------------------------------------------ *)
 | 
			
		||||
	method primitiveFailed
 | 
			
		||||
	{
 | 
			
		||||
		self class primitiveFailed.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method doesNotUnderstand: messageSymbol
 | 
			
		||||
	{
 | 
			
		||||
		self class doesNotUnderstand: messageSymbol
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method index: index outOfRange: ubound
 | 
			
		||||
	{
 | 
			
		||||
		self class index: index outOfRange: ubound.
 | 
			
		||||
		^self class primitiveFailed.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method cannotInstantiate
 | 
			
		||||
	{
 | 
			
		||||
		self class cannotInstantiate
 | 
			
		||||
		^self class cannotInstantiate
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method subclassResponsibility: message_name
 | 
			
		||||
	method doesNotUnderstand: messageSymbol
 | 
			
		||||
	{
 | 
			
		||||
		self class subclassResponsibility: message_name
 | 
			
		||||
		^self class doesNotUnderstand: messageSymbol
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method index: index outOfRange: ubound
 | 
			
		||||
	{
 | 
			
		||||
		^self class index: index outOfRange: ubound.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method subclassResponsibility: method_name
 | 
			
		||||
	{
 | 
			
		||||
		^self class subclassResponsibility: method_name
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method notImplemented: method_name
 | 
			
		||||
	{
 | 
			
		||||
		^self class notImplemented: method_name
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method cannotExceptionizeError
 | 
			
		||||
	{
 | 
			
		||||
		self class cannotExceptionizeError
 | 
			
		||||
		^self class cannotExceptionizeError
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method(#class) error: msgText
 | 
			
		||||
@ -413,6 +428,11 @@ class Error(Apex)
 | 
			
		||||
		^true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method notError
 | 
			
		||||
	{
 | 
			
		||||
		^false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method asInteger
 | 
			
		||||
	{
 | 
			
		||||
		<primitive: #_error_as_integer>
 | 
			
		||||
 | 
			
		||||
@ -145,7 +145,7 @@ class Set(Collection)
 | 
			
		||||
 | 
			
		||||
		[(ass := self.bucket at: index) notNil] 
 | 
			
		||||
			whileTrue: [
 | 
			
		||||
				[key == ass key] ifTrue: [ (* TODO: change it to equality??? *)
 | 
			
		||||
				(key = ass key) ifTrue: [
 | 
			
		||||
					(* found *)
 | 
			
		||||
					upsert ifTrue: [ass value: value].
 | 
			
		||||
					^ass
 | 
			
		||||
@ -153,7 +153,7 @@ class Set(Collection)
 | 
			
		||||
				index := (index + 1) rem: bs.
 | 
			
		||||
			].
 | 
			
		||||
 | 
			
		||||
		upsert ifFalse: [^nil].
 | 
			
		||||
		upsert ifFalse: [^ErrorCode.NOENT].
 | 
			
		||||
 | 
			
		||||
		ntally := self.tally + 1.
 | 
			
		||||
		(ntally >= bs) ifTrue: [
 | 
			
		||||
@ -187,29 +187,42 @@ class Set(Collection)
 | 
			
		||||
	{
 | 
			
		||||
		| ass |
 | 
			
		||||
		ass := self __find: key or_upsert: false with: nil.
 | 
			
		||||
		(ass notNil) ifTrue: [^ass value].
 | 
			
		||||
		^ErrorCode.NOENT
 | 
			
		||||
		(ass isError) ifTrue: [^ass].
 | 
			
		||||
		^ass value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method at: key ifAbsent: error_block
 | 
			
		||||
	{
 | 
			
		||||
		| ass |
 | 
			
		||||
		ass := self __find: key or_upsert: false with: nil.
 | 
			
		||||
		(ass notNil) ifTrue: [^ass value].
 | 
			
		||||
		^error_block value.
 | 
			
		||||
		(ass isError) ifTrue: [^error_block value].
 | 
			
		||||
		^ass value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method associationAt: key
 | 
			
		||||
	{
 | 
			
		||||
		^self __find: key or_upsert: false with: nil.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method associationAt: key ifAbsent: error_block
 | 
			
		||||
	{
 | 
			
		||||
		| ass |
 | 
			
		||||
		ass := self __find: key or_upsert: false with: nil.
 | 
			
		||||
		(ass isError) ifTrue: [^error_block value].
 | 
			
		||||
		^ass
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method at: key put: value
 | 
			
		||||
	{
 | 
			
		||||
		self __find: key or_upsert: true with: value.
 | 
			
		||||
		^value
 | 
			
		||||
		(* returns the affected/inserted association *)
 | 
			
		||||
		^self __find: key or_upsert: true with: value.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method includesKey: key
 | 
			
		||||
	{
 | 
			
		||||
		| ass |
 | 
			
		||||
		ass := self __find: key or_upsert: false with: nil.
 | 
			
		||||
		^ass notNil
 | 
			
		||||
		^ass notError
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method includesAssociation: assoc
 | 
			
		||||
@ -226,18 +239,98 @@ class Set(Collection)
 | 
			
		||||
		^ass key = key and: [ass value = value]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method __find_index: key
 | 
			
		||||
	{
 | 
			
		||||
		| bs ass index |
 | 
			
		||||
		
 | 
			
		||||
		bs := self.bucket size.
 | 
			
		||||
		index := (key hash) rem: bs.
 | 
			
		||||
		
 | 
			
		||||
		[(ass := self.bucket at: index) notNil] 
 | 
			
		||||
			whileTrue: [ 
 | 
			
		||||
				(key = ass key) ifTrue: [^index].
 | 
			
		||||
				index := (index + 1) rem: bs.
 | 
			
		||||
			].
 | 
			
		||||
 | 
			
		||||
		^ErrorCode.NOENT.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method __remove_at: index
 | 
			
		||||
	{
 | 
			
		||||
		| bs x y i v |
 | 
			
		||||
 | 
			
		||||
		bs := self.bucket size.
 | 
			
		||||
		v := self.bucket basicAt: index.
 | 
			
		||||
 | 
			
		||||
		x := index.
 | 
			
		||||
		y := index.
 | 
			
		||||
		i := 0.
 | 
			
		||||
		[i < self.tally] whileTrue: [
 | 
			
		||||
			| ass z |
 | 
			
		||||
 | 
			
		||||
			y := (y + 1) rem: bs.
 | 
			
		||||
 | 
			
		||||
			ass := self.bucket at: i.
 | 
			
		||||
			(ass isNil)
 | 
			
		||||
				ifTrue: [ 
 | 
			
		||||
					(* done. the slot at the current index is nil *)
 | 
			
		||||
					i := self.tally 
 | 
			
		||||
				]
 | 
			
		||||
				ifFalse: [
 | 
			
		||||
					(* get the natural hash index *)
 | 
			
		||||
					z := (ass key hash) rem: bs.
 | 
			
		||||
 | 
			
		||||
					(* move an element if necessary *)
 | 
			
		||||
					((y > x and: [(z <= x) or: [z > y]]) or: 
 | 
			
		||||
					[(y < x) and: [(z <= x) and: [z > y]]]) ifTrue: [
 | 
			
		||||
						self.bucket at: x put: (self.bucket at: y).
 | 
			
		||||
						x := y.
 | 
			
		||||
					].
 | 
			
		||||
 | 
			
		||||
					i := i + 1
 | 
			
		||||
				].
 | 
			
		||||
		].
 | 
			
		||||
		
 | 
			
		||||
		self.bucket at: x put: nil.
 | 
			
		||||
		self.tally := self.tally - 1.
 | 
			
		||||
		
 | 
			
		||||
		(* return the affected association *)
 | 
			
		||||
		^v
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method removeKey: key
 | 
			
		||||
	{
 | 
			
		||||
(* TODO: *)
 | 
			
		||||
self subclassResponsbility: #removeKey
 | 
			
		||||
		| index |
 | 
			
		||||
		index := self __find_index: key.
 | 
			
		||||
		(index isError) ifTrue: [ ^index ].
 | 
			
		||||
		^self __remove_at: index.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method removeKey: key ifAbsent: error_block
 | 
			
		||||
	{
 | 
			
		||||
(* TODO: *)
 | 
			
		||||
self subclassResponsbility: #removeKey
 | 
			
		||||
		| index |
 | 
			
		||||
		index := self __find_index: key.
 | 
			
		||||
		(index isError) ifTrue: [ ^error_block value ].
 | 
			
		||||
		^self __remove_at: index.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	method removeAllKeys
 | 
			
		||||
	{
 | 
			
		||||
		(* remove all items from a dictionary *)
 | 
			
		||||
		| bs |
 | 
			
		||||
		bs := self.bucket size.
 | 
			
		||||
		0 priorTo: bs do: [:i | self.bucket at: i put: nil ].
 | 
			
		||||
		self.tally := 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
(* TODO: ... keys is an array of keys.
 | 
			
		||||
	method removeAllKeys: keys
 | 
			
		||||
	{
 | 
			
		||||
		self notImplemented: #removeAllKeys:
 | 
			
		||||
	}
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
	method remove: assoc
 | 
			
		||||
	{
 | 
			
		||||
		^self removeKey: (assoc key)
 | 
			
		||||
@ -248,6 +341,7 @@ self subclassResponsbility: #removeKey
 | 
			
		||||
		^self removeKey: (assoc key) ifAbsent: error_block
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	method do: block
 | 
			
		||||
	{
 | 
			
		||||
		| bs |
 | 
			
		||||
 | 
			
		||||
@ -351,6 +351,10 @@ thisContext isExceptionContext dump.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##============================================================================
 | 
			
		||||
class PrimitiveFailureException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class InstantiationFailureException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@ -359,10 +363,6 @@ class NoSuchMessageException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class PrimitiveFailureException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class IndexOutOfRangeException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@ -371,7 +371,7 @@ class SubclassResponsibilityException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class InvalidArgumentException(Exception)
 | 
			
		||||
class NotImplementedException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -379,6 +379,10 @@ class ErrorExceptionizationFailureException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class InvalidArgumentException(Exception)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extend Apex
 | 
			
		||||
{
 | 
			
		||||
	method(#class) primitiveFailed
 | 
			
		||||
@ -414,9 +418,14 @@ ctx := thisContext.
 | 
			
		||||
		IndexOutOfRangeException signal: 'Out of range'.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method(#class) subclassResponsibility: message_name
 | 
			
		||||
	method(#class) subclassResponsibility: method_name
 | 
			
		||||
	{
 | 
			
		||||
		SubclassResponsibilityException signal: ('Subclass must implment ' & message_name).
 | 
			
		||||
		SubclassResponsibilityException signal: ('Subclass must implement ' & method_name).
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method(#class) notImplemented: method_name
 | 
			
		||||
	{
 | 
			
		||||
		NotImplementedException signal: (method_name & ' not implemented by ' & (self name)).
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	method(#class) cannotExceptionizeError
 | 
			
		||||
 | 
			
		||||
@ -261,6 +261,72 @@ stix_oop_association_t stix_lookupdic (stix_t* stix, stix_oop_set_t dic, const s
 | 
			
		||||
	return lookup (stix, dic, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stix_deletedic (stix_t* stix, stix_oop_set_t dic, const stix_oocs_t* name)
 | 
			
		||||
{
 | 
			
		||||
	stix_ooi_t tally;
 | 
			
		||||
	stix_oow_t hv, index, bs, i, x, y, z;
 | 
			
		||||
	stix_oop_association_t ass;
 | 
			
		||||
 | 
			
		||||
	STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->tally) == stix->_small_integer);
 | 
			
		||||
	STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->bucket) == stix->_array);
 | 
			
		||||
 | 
			
		||||
	tally = STIX_OOP_TO_SMOOI(dic->tally);
 | 
			
		||||
 | 
			
		||||
	bs = STIX_OBJ_GET_SIZE(dic->bucket);
 | 
			
		||||
	hv = stix_hashoochars(name->ptr, name->len) % bs;
 | 
			
		||||
	index = hv % bs;
 | 
			
		||||
 | 
			
		||||
	/* find */
 | 
			
		||||
	while (dic->bucket->slot[index] != stix->_nil) 
 | 
			
		||||
	{
 | 
			
		||||
		ass = (stix_oop_association_t)dic->bucket->slot[index];
 | 
			
		||||
 | 
			
		||||
		STIX_ASSERT (stix, STIX_CLASSOF(stix,ass) == stix->_association);
 | 
			
		||||
		STIX_ASSERT (stix, STIX_CLASSOF(stix,ass->key) == stix->_symbol);
 | 
			
		||||
 | 
			
		||||
		if (name->len == STIX_OBJ_GET_SIZE(ass->key) &&
 | 
			
		||||
		    stix_equaloochars(name->ptr, ((stix_oop_char_t)ass->key)->slot, name->len)) 
 | 
			
		||||
		{
 | 
			
		||||
			goto found;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		index = (index + 1) % bs;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stix->errnum = STIX_ENOENT;
 | 
			
		||||
	return -1;
 | 
			
		||||
 | 
			
		||||
found:
 | 
			
		||||
	/* compact the cluster */
 | 
			
		||||
	for (i = 0, x = index, y = index; i < tally; i++)
 | 
			
		||||
	{
 | 
			
		||||
		y = (y + 1) % bs;
 | 
			
		||||
 | 
			
		||||
		/* done if the slot at the current index is empty */
 | 
			
		||||
		if (dic->bucket->slot[y] == stix->_nil) break;
 | 
			
		||||
 | 
			
		||||
		/* get the natural hash index for the data in the slot at
 | 
			
		||||
		 * the current hash index */
 | 
			
		||||
		ass = (stix_oop_association_t)dic->bucket->slot[y];
 | 
			
		||||
		z = stix_hashoochars(((stix_oop_char_t)ass->key)->slot, STIX_OBJ_GET_SIZE(ass->key)) % bs;
 | 
			
		||||
 | 
			
		||||
		/* move an element if necesary */
 | 
			
		||||
		if ((y > x && (z <= x || z > y)) ||
 | 
			
		||||
		    (y < x && (z <= x && z > y)))
 | 
			
		||||
		{
 | 
			
		||||
			dic->bucket->slot[x] = dic->bucket->slot[y];
 | 
			
		||||
			x = y;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dic->bucket->slot[x] = stix->_nil;
 | 
			
		||||
 | 
			
		||||
	tally--;
 | 
			
		||||
	dic->tally = STIX_SMOOI_TO_OOP(tally);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stix_oop_set_t stix_makedic (stix_t* stix, stix_oop_t cls, stix_oow_t size)
 | 
			
		||||
{
 | 
			
		||||
	stix_oop_set_t dic;
 | 
			
		||||
 | 
			
		||||
@ -985,6 +985,12 @@ stix_oop_association_t stix_lookupdic (
 | 
			
		||||
	const stix_oocs_t* name
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int stix_deletedic (
 | 
			
		||||
	stix_t*            stix,
 | 
			
		||||
	stix_oop_set_t     dic,
 | 
			
		||||
	const stix_oocs_t* name
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
stix_oop_set_t stix_makedic (
 | 
			
		||||
	stix_t*    stix,
 | 
			
		||||
	stix_oop_t cls,
 | 
			
		||||
@ -1000,7 +1006,7 @@ stix_oop_process_t stix_makeproc (
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
/* bigint.c                                                                    */
 | 
			
		||||
/* bigint.c                                                                  */
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
int stix_isint (
 | 
			
		||||
	stix_t*    stix,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user