Source code for vsc.model.rangelist_model

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from typing import List




# Created on Aug 4, 2019
#
# @author: ballance


[docs]class RangelistModel(object): def __init__(self, rl : List[List[int]]=None): self.range_l = [] if rl is not None: for r in rl: if isinstance(r, (list,tuple)): if len(r) == 2: self.range_l.append([r[0], r[1]]) else: raise Exception("Each range element must have 2 elements") else: self.range_l.append([int(r), int(r)])
[docs] def add_value(self, v): self.range_l.append([v,v])
[docs] def add_range(self, low, high): self.range_l.append([low, high])
# Merge any overlapping ranges
[docs] def compact(self): self.range_l.sort(key=lambda e : e[0]) i=0 while i < len(self.range_l)-1: if self.range_l[i][0] >= self.range_l[i+1][0]: # Entire range subsumed self.range_l.pop(i) elif self.range_l[i][1] >= self.range_l[i+1][1]: # Upper just overlaps self.range_l[i][1] = self.range_l[i+1][0] self.range_l.pop(i+1) else: i += 1 pass
[docs] def intersect(self, other): """ Intersects another list or ranges with this one, trimming values that overlap """ if len(self.range_l) == 0 or len(other.range_l) == 0: return rng_i=0 while rng_i < len(self.range_l): for r in other.range_l: rng_i = self._intersect( self.range_l, rng_i, self.range_l[rng_i], r) rng_i += 1
def _intersect(self, ranges, rng_i, target_rng, trim_rng) -> int: if target_rng[0] >= trim_rng[0] and target_rng[1] <= trim_rng[1]: # The target range is entirely inside the trim range ranges.pop(rng_i) rng_i -= 1 elif trim_rng[0] > target_rng[0] and trim_rng[1] < target_rng[1]: # Trim range is entirely inside the target range # Need to split the range into two new_rng = [trim_rng[1]+1, target_rng[1]] target_rng[1] = trim_rng[0]-1 ranges.insert(rng_i+1, new_rng) elif trim_rng[0] > target_rng[0] and trim_rng[0] <= target_rng[1]: # Lower edge of the trim bin inside the target range, but # doesn't eclipse the entire range target_rng[1] = trim_rng[0]-1 elif trim_rng[1] >= target_rng[0] and trim_rng[1] < target_rng[1]: # Upper edge of the trim bin is inside the target range, but # doesn't eclipse it target_rng[0] = trim_rng[1]+1 return rng_i def __contains__(self, val): for r in self.range_l: if val >= r[0] and val <= r[1]: return True return False
[docs] def equals(self, oth)->bool: eq = isinstance(oth, RangelistModel) if len(self.range_l) == len(oth.range_l): for i in range(len(self.range_l)): eq &= self.range_l[i][0] == oth.range_l[i][0] eq &= self.range_l[i][1] == oth.range_l[i][1] else: eq = False return eq
[docs] def toString(self): ret = "[" for i,r in enumerate(self.range_l): if i > 0: ret += "," ret += str(r[0]) + ".." + str(r[1]) ret += "]" return ret
[docs] def clone(self): ret = RangelistModel(None) for r in self.range_l: ret.range_l.append([r[0], r[1]]) return ret
[docs] def accept(self, v): v.visit_rangelist(self);