Module to handle spacemaps

Annotation For spacemap.py
anonymous

Annotation For spacemap.py

Lines of spacemap.py from check-in bfe3da6658 that are changed by the sequence of edits moving toward check-in 886158fbf4:

bfe3da6658 2010-10-14    1: class SpaceMap:
                         2: 	''' Here we have:
                         3: 	__bottom - minimum space address possible;
                         4: 	__top - maximum space address possible;
                         5: 	__pairs - internal list of ranges;
                         6: 	__walk_list - internal list of keys.'''
                         7: 
                         8: 	__slots__ = frozenset(('__bottom', '__pairs', '__top', '__walk_list'))
                         9: 
                        10: 	def __init__(self, source = None, bottom = 0, top = None):
                        11: 		''' This one can be bootstrapped by giving a dict in format {x:y, x:y}.'''
                        12: 		self.__pairs = {}
                        13: 		self.__walk_list = None
                        14: 		self.__bottom = bottom
                        15: 		self.__top = top
                        16: 		if type(source) == dict:
                        17: 			for key in source:
                        18: 				self.__set(key, source[key])
                        19: 			self.fold()
                        20: 
                        21: 	def __getitem__(self, name):
                        22: 		'''Returns last range address by first range address.'''
                        23: 		if name in self.__pairs:
                        24: 			return(self.__pairs[name])
                        25: 		else:
                        26: 			return(None)
                        27: 
                        28: 	def __set(self, name, value):
                        29: 		'''Internal function to add ranges without folding. Also checks for range correctness.'''
                        30: 		if type(name) != int or type(value) != int or name >= value:
                        31: 			return(False)
bfe3da6658 2010-10-14   32: 		if not self.__bottom == None:
                        33: 			if name < self.__bottom or value < self.__bottom:
                        34: 				return(False)
bfe3da6658 2010-10-14   35: 		if not self.__top == None:
                        36: 			if name >= self.__top or value >= self.__top:
                        37: 				return(False)
                        38: 		self.__pairs[name] = value
                        39: 		return True
                        40: 
                        41: 	def __setitem__(self, name, value):
                        42: 		'''Adds one more range and tries to fold a space map.'''
                        43: 		self.__set(name, value)
                        44: 		self.fold()
                        45: 
                        46: 	def fold(self):
                        47: 		'''Tries to normalize spacemap by joining coaligned or overlapping ranges.'''
                        48: 		self.rewind()
                        49: 		pairs = ()
                        50: 		while True:
                        51: 			pair = self.pop()
                        52: 			if pair[0] == None:
                        53: 				break
                        54: 			pairs += pair,
                        55: 		last_pair = self.__bottom
                        56: 		for pair in pairs:
                        57: 			if last_pair in self.__pairs and pair[0] <= self.__pairs[last_pair] and pair[1] > self.__pairs[last_pair]:
                        58: 				self.__pairs[last_pair] = pair[1]
                        59: 				del(self.__pairs[pair[0]])
                        60: 			else:
                        61: 				last_pair = pair[0]
                        62: 		self.clear()
                        63: 
                        64: 	def rewind(self):
                        65: 		'''Reinitialises internal ordered list of ranges.'''
                        66: 		self.__walk_list = list(self.__pairs.keys())
                        67: 		self.__walk_list.sort()
                        68: 
                        69: 	def clear(self):
                        70: 		'''Clears internal ordered list of ranges.'''
                        71: 		self.__walk_list = None
                        72: 
                        73: 	def pop(self):
                        74: 		'''Returns next range from ordered list of ranges.'''
                        75: 		if self.__walk_list != None:
                        76: 			if len(self.__walk_list) > 0:
                        77: 				next = self.__walk_list.pop(0)
                        78: 				return([next, self.__pairs[next]])
                        79: 		return([None, None])
                        80: 
                        81: 	def __repr__(self):
                        82: 		'''Returns the inner dict with ranges.'''
                        83: 		return(repr(self.__pairs))
                        84: 
                        85: 	def __and__(self, other):
                        86: 		'''Returns new space map with ranges that appears both in A and B.'''
bfe3da6658 2010-10-14   87: 		if not type(other) == SpaceMap:
                        88: 			return(False)
                        89: 		new = {}
                        90: 		self.rewind()
                        91: 		other.rewind()
                        92: 		my_pair = self.pop()
                        93: 		other_pair = other.pop()
                        94: 		# if there are no pairs in B - we have nothing to do
                        95: 		if other_pair[0] == None or my_pair[0] == None:
                        96: 			all_parts_found = True
                        97: 		else:
                        98: 			all_parts_found = False
                        99: 		while not all_parts_found:
                       100: 			if my_pair[0] > other_pair[0]:
                       101: 				# when my pair starts after other pair starts
                       102: 				#  m---
                       103: 				# o---
                       104: 				if my_pair[0] > other_pair[1]:
                       105: 					# when my pair starts after other pair ends
                       106: 					#       m---
                       107: 					# o---o
                       108: 					other_pair = other.pop()
                       109: 					# tossing out other pair
                       110: 					if other_pair[0] == None:
                       111: 						all_parts_found = True
                       112: 				else:
                       113: 					# when my pair starts before other pair ends
                       114: 					#    m--- |     m---
                       115: 					# o---o   | o---o
                       116: 					if my_pair[1] > other_pair[1]:
                       117: 						# when my pair ends after other pair ends
                       118: 						#    m---m |     m---m
                       119: 						# o---o    | o---o
                       120: 						other_pair[0] = my_pair[0]
                       121: 						# trimming other pair by my pair start
                       122: 						#   m---m
                       123: 						# o.o-o
                       124: 					else:
                       125: 						# when my pair ends before other pair ends
                       126: 						#  m---m
                       127: 						# o-----o
                       128: 						new[my_pair[0]] = my_pair[1]
                       129: 						# my pair is covered and should be added to result
                       130: 						my_pair = self.pop()
                       131: 						# tossing out my pair
                       132: 						if my_pair[0] == None:
                       133: 							all_parts_found = True
                       134: 			elif my_pair[0] < other_pair[0]:
                       135: 				# when my pair starts before other one
                       136: 				# m---
                       137: 				#  o---
                       138: 				if my_pair[1] < other_pair[0]:
                       139: 					# when my pair ends before other pair starts
                       140: 					# m---m
                       141: 					#       o---
                       142: 					my_pair = self.pop()
                       143: 					# tossing out my pair
                       144: 					if my_pair[0] == None:
                       145: 						all_parts_found = True
                       146: 				else:
                       147: 					# when my pair ends before other pair starts
                       148: 					# m---m
                       149: 					#   o---
                       150: 					my_pair[0] = other_pair[0]
                       151: 					# trimming my pair by other pair start
                       152: 					# m.m-m
                       153: 					#   o---
                       154: 			else:
                       155: 				# when both pairs starts simultaneously
                       156: 				# m---
                       157: 				# o---
                       158: 				if my_pair[1] < other_pair[1]:
                       159: 					# when my pair ends before other pair
                       160: 					# m---m
                       161: 					# o-----o
                       162: 					new[my_pair[0]] = my_pair[1]
                       163: 					# my pair is covered and should be added to result
                       164: 					my_pair = self.pop()
                       165: 					# tossing out my pair
                       166: 					if my_pair[0] == None:
                       167: 						all_parts_found = True
                       168: 				else:
                       169: 					# when my pair ends after other pair
                       170: 					# m-----m
                       171: 					# o---o
                       172: 					new[my_pair[0]] = other_pair[1]
                       173: 					# part of my pair is covered and should be added to result
                       174: 					other_pair = other.pop()
                       175: 					# tossing out other pair
                       176: 					if other_pair[0] == None:
                       177: 						all_parts_found = True
                       178: 		self.clear()
                       179: 		other.clear()
                       180: 		return(SpaceMap(new, self.__bottom, self.__top))
                       181: 
                       182: 	def __sub__(self, other):
                       183: 		'''Returns new space map with ranges in A not covered by B.'''
bfe3da6658 2010-10-14  184: 		if not type(other) == SpaceMap:
                       185: 			return(False)
                       186: 		new = {}
                       187: 		self.rewind()
                       188: 		other.rewind()
                       189: 		my_pair = self.pop()
                       190: 		other_pair = other.pop()
                       191: 		# if there are no pairs in B - copy this one to new SpaceMap
                       192: 		if other_pair[0] == None:
                       193: 			new[my_pair[0]] = my_pair[1]
                       194: 			all_parts_found = True
                       195: 		elif my_pair[0] == None:
                       196: 			all_parts_found = True
                       197: 		else:
                       198: 			all_parts_found = False
                       199: 		while not all_parts_found:
                       200: 			if my_pair[0] > other_pair[0]:
                       201: 				# when my pair starts after other pair starts
                       202: 				#  m---
                       203: 				# o---
                       204: 				if my_pair[0] > other_pair[1]:
                       205: 					# when my pair starts after other pair ends
                       206: 					#       m---
                       207: 					# o---o
                       208: 					other_pair = other.pop()
                       209: 					# tossing out other pair
                       210: 					if other_pair[0] == None:
                       211: 						# this was last one - my pair goes to result
                       212: 						new[my_pair[0]] = my_pair[1]
                       213: 						all_parts_found = True
                       214: 				else:
                       215: 					# when my pair starts before other pair ends
                       216: 					#    m--- |     m---
                       217: 					# o---o   | o---o
                       218: 					if my_pair[1] > other_pair[1]:
                       219: 						# when my pair ends after other pair ends
                       220: 						#    m---m |     m---m
                       221: 						# o---o    | o---o
                       222: 						my_pair[0] = other_pair[1]
                       223: 						# trimming my pair by other pair end
                       224: 						#   m.m-m
                       225: 						# o---o
                       226: 						other_pair = other.pop()
                       227: 						# tossing out other pair
                       228: 						if other_pair[0] == None:
                       229: 						# this was last one - my pair goes to result
                       230: 							new[my_pair[0]] = my_pair[1]
                       231: 							all_parts_found = True
                       232: 					else:
                       233: 						# when my pair ends before other pair ends
                       234: 						#  m---m
                       235: 						# o-----o
                       236: 						my_pair = self.pop()
                       237: 						# tossing out my pair
                       238: 						if my_pair[0] == None:
                       239: 							all_parts_found = True
                       240: 			elif my_pair[0] < other_pair[0]:
                       241: 				# when my pair starts before other one
                       242: 				# m---
                       243: 				#  o---
                       244: 				if my_pair[1] < other_pair[0]:
                       245: 					# when my pair ends before other pair starts
                       246: 					# m---m
                       247: 					#       o---
                       248: 					new[my_pair[0]] = my_pair[1]
                       249: 					# my pair is not covered and should be added to result
                       250: 					my_pair = self.pop()
                       251: 					# tossing out my pair
                       252: 					if my_pair[0] == None:
                       253: 						all_parts_found = True
                       254: 				else:
                       255: 					# when my pair ends before other pair starts
                       256: 					# m---m
                       257: 					#   o---
                       258: 					new[my_pair[0]] = other_pair[0]
                       259: 					# start of my pair is not covered and should be added to result
                       260: 					my_pair[0] = other_pair[0]
                       261: 					# trimming my pair by other pair start
                       262: 					# m.m-m
                       263: 					#   o---
                       264: 			else:
                       265: 				# when both pairs starts simultaneously
                       266: 				# m---
                       267: 				# o---
                       268: 				if my_pair[1] < other_pair[1]:
                       269: 					# when my pair ends before other pair
                       270: 					# m---m
                       271: 					# o-----o
                       272: 					my_pair = self.pop()
                       273: 					# tossing out my pair
                       274: 					if my_pair[0] == None:
                       275: 						all_parts_found = True
                       276: 				else:
                       277: 					# when my pair ends after other pair
                       278: 					# m-----m
                       279: 					# o---o
                       280: 					my_pair[0] = other_pair[1]
                       281: 					# trimming my pair by other pair end
                       282: 					# m...m-m
                       283: 					# o---o
                       284: 					other_pair = other.pop()
                       285: 					# tossing out other pair
                       286: 					if other_pair[0] == None:
                       287: 						# this was last one - my pair goes to result
                       288: 						new[my_pair[0]] = my_pair[1]
                       289: 						all_parts_found = True
                       290: 		while True:
                       291: 			# copy any leftover in A to new SpaceMap
                       292: 			my_pair = self.pop()
                       293: 			if my_pair[0] == None:
                       294: 				break
                       295: 			else:
                       296: 				new[my_pair[0]] = my_pair[1]
                       297: 		self.clear()
                       298: 		other.clear()
                       299: 		return(SpaceMap(new, self.__bottom, self.__top))
                       300: 
                       301: 	def __eq__(self, other):
                       302: 		'''Compares two space maps.'''
                       303: 		if type(other) != SpaceMap:
                       304: 			return(False)
                       305: 		self.rewind()
                       306: 		other.rewind()
                       307: 		result = None
                       308: 		while True:
                       309: 			this = self.pop()
                       310: 			that = other.pop()
                       311: 			if this != that:
                       312: 				result = False
                       313: 				break
                       314: 			if this == [None, None] and that == [None, None]:
                       315: 				result = True
                       316: 				break
                       317: 		self.clear()
                       318: 		other.clear()
                       319: 		return(result)
                       320: 
                       321: 	def end(self):
                       322: 		'''Returns last known point.'''
                       323: 		end = None
                       324: 		self.rewind()
                       325: 		while True:
                       326: 			this = self.pop()
                       327: 			if this == [None, None]:
                       328: 				break
                       329: 			elif end == None or this[1] > end:
                       330: 				end = this[1]
                       331: 		self.clear()
                       332: 		return(end)
                       333: 
                       334: 	def __len__(self):
                       335: 		return(len(self.__pairs))