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, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user