scripts: maps: Cleaned up comments and junk
This took a bit of a messy route, but these scripts should be good to go now.
This commit is contained in:
@@ -3851,8 +3851,6 @@ def punescape(s, attrs=None):
|
||||
return re.sub(pattern, unescape, s)
|
||||
|
||||
|
||||
# TODO sync these
|
||||
|
||||
# naive space filling curve (the default)
|
||||
def naive_curve(width, height):
|
||||
for y in range(height):
|
||||
@@ -4065,580 +4063,6 @@ class BmapBlock:
|
||||
}
|
||||
|
||||
|
||||
# a mergable range set type
|
||||
class RangeSet:
|
||||
def __init__(self, ranges=None):
|
||||
self._ranges = []
|
||||
|
||||
if ranges is not None:
|
||||
# using add here makes sure all ranges are merged/sorted
|
||||
# correctly
|
||||
for r in ranges:
|
||||
self.add(r)
|
||||
|
||||
def __repr__(self):
|
||||
return 'RangeSet(%r)' % self._ranges
|
||||
|
||||
def __contains__(self, k):
|
||||
i = bisect.bisect(self._ranges, k,
|
||||
key=lambda r: r.start) - 1
|
||||
if i > -1:
|
||||
return k in self._ranges[i]
|
||||
else:
|
||||
return False
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self._ranges)
|
||||
|
||||
def ranges(self):
|
||||
yield from self._ranges
|
||||
|
||||
def __iter__(self):
|
||||
for r in self._ranges:
|
||||
yield from r
|
||||
|
||||
def add(self, r):
|
||||
assert isinstance(r, range)
|
||||
# trivial range?
|
||||
if not r:
|
||||
return
|
||||
|
||||
# find earliest possible merge point
|
||||
ranges = self._ranges
|
||||
i = bisect.bisect_left(ranges, r.start,
|
||||
key=lambda r: r.stop)
|
||||
|
||||
# copy ranges < merge
|
||||
merged = ranges[:i]
|
||||
|
||||
# merge ranges and append
|
||||
while i < len(ranges) and ranges[i].start <= r.stop:
|
||||
r = range(
|
||||
min(ranges[i].start, r.start),
|
||||
max(ranges[i].stop, r.stop))
|
||||
i += 1
|
||||
merged.append(r)
|
||||
|
||||
# copy ranges > merge
|
||||
merged.extend(ranges[i:])
|
||||
|
||||
self._ranges = merged
|
||||
|
||||
def remove(self, r):
|
||||
assert isinstance(r, range)
|
||||
# trivial range?
|
||||
if not r:
|
||||
return
|
||||
|
||||
# find earliest possible carve point
|
||||
ranges = self._ranges
|
||||
i = bisect.bisect_left(ranges, r.start,
|
||||
key=lambda r: r.stop)
|
||||
|
||||
# copy ranges < carve
|
||||
carved = ranges[:i]
|
||||
|
||||
# carve overlapping ranges, note this can split ranges
|
||||
while i < len(ranges) and ranges[i].start <= r.stop:
|
||||
if ranges[i].start < r.start:
|
||||
carved.append(range(ranges[i].start, r.start))
|
||||
if ranges[i].stop > r.stop:
|
||||
carved.append(range(r.stop, ranges[i].stop))
|
||||
i += 1
|
||||
|
||||
# copy ranges > carve
|
||||
carved.extend(ranges[i:])
|
||||
|
||||
self._ranges = carved
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
if not self._ranges:
|
||||
return 0
|
||||
else:
|
||||
return self._ranges[0].start
|
||||
|
||||
@property
|
||||
def stop(self):
|
||||
if not self._ranges:
|
||||
return 0
|
||||
else:
|
||||
return self._ranges[-1].stop
|
||||
|
||||
def __len__(self):
|
||||
return self.stop
|
||||
|
||||
def copy(self):
|
||||
# create a shallow copy
|
||||
ranges = RangeSet()
|
||||
ranges._ranges = self._ranges.copy()
|
||||
return ranges
|
||||
|
||||
def __getitem__(self, slice_):
|
||||
assert isinstance(slice_, slice)
|
||||
|
||||
# create a copy
|
||||
ranges = self.copy()
|
||||
|
||||
# just use remove to do the carving, it's good enough probably
|
||||
if slice_.stop is not None:
|
||||
ranges.remove(range(slice_.stop, len(self)))
|
||||
if slice_.start is not None:
|
||||
ranges.remove(range(0, slice_.start))
|
||||
ranges._ranges = [range(
|
||||
r.start - slice_.start,
|
||||
r.stop - slice_.start)
|
||||
for r in ranges._ranges]
|
||||
|
||||
return ranges
|
||||
|
||||
def __ior__(self, other):
|
||||
for r in other.ranges():
|
||||
self.add(r)
|
||||
return self
|
||||
|
||||
def __or__(self, other):
|
||||
ranges = self.copy()
|
||||
ranges |= other
|
||||
return ranges
|
||||
|
||||
# a mergable range dict type
|
||||
class RangeDict:
|
||||
def __init__(self, ranges=None):
|
||||
self._ranges = []
|
||||
|
||||
if ranges is not None:
|
||||
# using __setitem__ here makes sure all ranges are
|
||||
# merged/sorted correctly
|
||||
for r, v in ranges:
|
||||
self[r] = v
|
||||
|
||||
def __repr__(self):
|
||||
return 'RangeDict(%r)' % self._ranges
|
||||
|
||||
def _get(self, k):
|
||||
i = bisect.bisect(self._ranges, k,
|
||||
key=lambda rv: rv[0].start) - 1
|
||||
if i > -1:
|
||||
return self._ranges[i][1]
|
||||
else:
|
||||
raise KeyError(k)
|
||||
|
||||
def get(self, k, d=None):
|
||||
try:
|
||||
return self._get(k)
|
||||
except KeyError:
|
||||
return d
|
||||
|
||||
def __getitem__(self, k):
|
||||
# special case for slicing
|
||||
if isinstance(k, slice):
|
||||
return self._slice(k)
|
||||
else:
|
||||
return self._get(k)
|
||||
|
||||
def __contains__(self, k):
|
||||
try:
|
||||
self._get(k)
|
||||
return True
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self._ranges)
|
||||
|
||||
def ranges(self):
|
||||
yield from self._ranges
|
||||
|
||||
def __iter__(self):
|
||||
for r, v in self._ranges:
|
||||
for k in r:
|
||||
yield k, v
|
||||
|
||||
# apply a function to a range
|
||||
def map(self, r, f):
|
||||
assert isinstance(r, range)
|
||||
# trivial range?
|
||||
if not r:
|
||||
return
|
||||
|
||||
# find earliest possible merge point
|
||||
ranges = self._ranges
|
||||
i = bisect.bisect_left(ranges, r.start,
|
||||
key=lambda rv: rv[0].stop)
|
||||
|
||||
# copy ranges < merge
|
||||
merged = ranges[:i]
|
||||
|
||||
# map, merge/carve ranges
|
||||
while i < len(ranges) and ranges[i][0].start <= r.stop:
|
||||
# carve prefix
|
||||
if ranges[i][0].start < r.start:
|
||||
merged.append((
|
||||
range(ranges[i][0].start, r.start),
|
||||
ranges[i][1]))
|
||||
|
||||
# need fill?
|
||||
if ranges[i][0].start > r.start:
|
||||
v = f(None)
|
||||
# merge?
|
||||
if (merged
|
||||
and merged[-1][0].stop >= r.start
|
||||
and merged[-1][1] == v):
|
||||
merged[-1] = (
|
||||
range(
|
||||
merged[-1][0].start,
|
||||
ranges[i][0].start),
|
||||
merged[-1][1])
|
||||
else:
|
||||
merged.append((
|
||||
range(r.start, ranges[i][0].start),
|
||||
f(None)))
|
||||
|
||||
# apply f
|
||||
v = f(ranges[i][1])
|
||||
|
||||
# merge?
|
||||
if (merged
|
||||
and merged[-1][0].stop >= r.start
|
||||
and merged[-1][1] == v):
|
||||
merged[-1] = (
|
||||
range(
|
||||
merged[-1][0].start,
|
||||
min(ranges[i][0].stop, r.stop)),
|
||||
merged[-1][1])
|
||||
else:
|
||||
merged.append((
|
||||
range(
|
||||
r.start,
|
||||
min(ranges[i][0].stop, r.stop)),
|
||||
v))
|
||||
r = range(
|
||||
min(ranges[i][0].stop, r.stop),
|
||||
r.stop)
|
||||
|
||||
# carve suffix
|
||||
if ranges[i][0].stop > r.stop:
|
||||
# merge?
|
||||
if ranges[i][1] == v:
|
||||
merged[-1] = (
|
||||
range(
|
||||
merged[-1][0].start,
|
||||
ranges[i][0].stop),
|
||||
merged[-1][1])
|
||||
else:
|
||||
merged.append((
|
||||
range(r.stop, ranges[i][0].stop),
|
||||
ranges[i][1]))
|
||||
|
||||
i += 1
|
||||
|
||||
# need fill?
|
||||
if not merged or merged[-1][0].stop < r.stop:
|
||||
v = f(None)
|
||||
# merge?
|
||||
if (merged
|
||||
and merged[-1][0].stop >= r.start
|
||||
and merged[-1][1] == v):
|
||||
merged[-1] = (
|
||||
range(merged[-1][0].start, r.stop),
|
||||
merged[-1][1])
|
||||
else:
|
||||
merged.append((r, v))
|
||||
|
||||
# copy ranges > merge
|
||||
merged.extend(ranges[i:])
|
||||
|
||||
self._ranges = merged
|
||||
|
||||
def __setitem__(self, r, v):
|
||||
# we can define __setitem__ using map
|
||||
assert isinstance(r, range)
|
||||
self.map(r, lambda _: v)
|
||||
|
||||
def __delitem__(self, r):
|
||||
# __delitem__ is a bit more complicated
|
||||
assert isinstance(r, range)
|
||||
# trivial range?
|
||||
if not r:
|
||||
return
|
||||
|
||||
# find earliest possible carve point
|
||||
ranges = self._ranges
|
||||
i = bisect.bisect_left(ranges, r.start,
|
||||
key=lambda rv: rv[0].stop)
|
||||
|
||||
# copy ranges < carve
|
||||
carved = ranges[:i]
|
||||
|
||||
# carve overlapping ranges, note this can split ranges
|
||||
while i < len(ranges) and ranges[i][0].start <= r.stop:
|
||||
if ranges[i][0].start < r.start:
|
||||
carved.append((
|
||||
range(ranges[i][0].start, r.start),
|
||||
ranges[i][1]))
|
||||
if ranges[i][0].stop > r.stop:
|
||||
carved.append((
|
||||
range(r.stop, ranges[i][0].stop),
|
||||
ranges[i][1]))
|
||||
i += 1
|
||||
|
||||
# copy ranges > carve
|
||||
carved.extend(ranges[i:])
|
||||
|
||||
self._ranges = carved
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
if not self._ranges:
|
||||
return 0
|
||||
else:
|
||||
return self._ranges[0][0].start
|
||||
|
||||
@property
|
||||
def stop(self):
|
||||
if not self._ranges:
|
||||
return 0
|
||||
else:
|
||||
return self._ranges[-1][0].stop
|
||||
|
||||
def __len__(self):
|
||||
return self.stop
|
||||
|
||||
def copy(self):
|
||||
# create a shallow copy
|
||||
ranges = RangeDict()
|
||||
ranges._ranges = self._ranges.copy()
|
||||
return ranges
|
||||
|
||||
def _slice(self, slice_):
|
||||
assert isinstance(slice_, slice)
|
||||
|
||||
# create a copy
|
||||
ranges = RangeDict()
|
||||
ranges._ranges = self._ranges
|
||||
|
||||
# just use __delitem__ to do the carving, it's good enough probably
|
||||
if slice_.stop is not None:
|
||||
del ranges[range(slice_.stop, len(self))]
|
||||
if slice_.start is not None:
|
||||
del ranges[range(0, slice_.start)]
|
||||
ranges._ranges = [(
|
||||
range(
|
||||
r.start - slice_.start,
|
||||
r.stop - slice_.start),
|
||||
v)
|
||||
for r, v in ranges._ranges]
|
||||
|
||||
return ranges
|
||||
|
||||
def __ior__(self, other):
|
||||
for r, v in other.ranges():
|
||||
self[r] = v
|
||||
return self
|
||||
|
||||
def __or__(self, other):
|
||||
ranges = self.copy()
|
||||
ranges |= other
|
||||
return ranges
|
||||
|
||||
|
||||
## a representation of a range of blocks/offs to show
|
||||
#class BmapSlice:
|
||||
# def __init__(self, blocks=None, off=None, size=None):
|
||||
# self.orig_blocks = blocks
|
||||
# self.orig_off = off
|
||||
# self.orig_size = size
|
||||
#
|
||||
# # flatten blocks, default to all blocks
|
||||
# blocks = ([blocks] if isinstance(blocks, slice)
|
||||
# else list(it.chain.from_iterable(
|
||||
# [blocks_] if isinstance(blocks_, slice) else blocks_
|
||||
# for blocks_ in blocks))
|
||||
# if blocks is not None
|
||||
# else [slice(None)])
|
||||
#
|
||||
# # blocks may also encode offsets
|
||||
# blocks, offs, size = (
|
||||
# [block[0] if isinstance(block, tuple)
|
||||
# else block
|
||||
# for block in blocks],
|
||||
# [off.start if isinstance(off, slice)
|
||||
# else off if off is not None
|
||||
# else size.start if isinstance(size, slice)
|
||||
# else block[1] if isinstance(block, tuple)
|
||||
# else None
|
||||
# for block in blocks],
|
||||
# (size.stop - (size.start or 0)
|
||||
# if size.stop is not None
|
||||
# else None) if isinstance(size, slice)
|
||||
# else size if size is not None
|
||||
# else ((off.stop - (off.start or 0))
|
||||
# if off.stop is not None
|
||||
# else None) if isinstance(off, slice)
|
||||
# else None)
|
||||
#
|
||||
# self.blocks = blocks
|
||||
# self.offs = offs
|
||||
# self.size = size
|
||||
#
|
||||
# @property
|
||||
# def off(self):
|
||||
# if not self.offs:
|
||||
# return None
|
||||
# else:
|
||||
# return self.offs[-1]
|
||||
#
|
||||
# def __repr__(self):
|
||||
# return 'BmapSlice(%r, %r, %r)' % (
|
||||
# self.orig_blocks,
|
||||
# self.orig_off,
|
||||
# self.orig_size)
|
||||
#
|
||||
# def slices(self, block_size, block_count):
|
||||
# for block, off in zip(self.blocks, self.offs):
|
||||
# # figure out off range, bound to block_size
|
||||
# off = off if off is not None else 0
|
||||
# size = self.size if self.size is not None else block_size - off
|
||||
# if off >= block_size:
|
||||
# continue
|
||||
# size = min(off + size, block_size) - off
|
||||
#
|
||||
# # flatten/filter blocks
|
||||
# if isinstance(block, slice):
|
||||
# start = block.start if block.start is not None else 0
|
||||
# stop = block.stop if block.stop is not None else block_count
|
||||
# for block_ in range(start, min(stop, block_count)):
|
||||
# yield block_, off, size
|
||||
# else:
|
||||
# block = block if block is not None else 0
|
||||
# if block < block_count:
|
||||
# yield block, off, size
|
||||
#
|
||||
# def blocks(self, block_count):
|
||||
# for block in self.blocks:
|
||||
# # flatten/filter blocks
|
||||
# if isinstance(block, slice):
|
||||
# start = block.start if block.start is not None else 0
|
||||
# stop = block.stop if block.stop is not None else block_count
|
||||
# for block_ in range(start, min(stop, block_count)):
|
||||
# yield block_
|
||||
# else:
|
||||
# block = block if block is not None else 0
|
||||
# if block < block_count:
|
||||
# yield block
|
||||
#
|
||||
# def sorted_slices(self, block_size, block_count):
|
||||
# # merge block ranges
|
||||
# blocks = RangeDict()
|
||||
# for block in self.blocks:
|
||||
# # figure out off range, bound to block_size
|
||||
# off = off if off is not None else 0
|
||||
# size = self.size if self.size is not None else block_size - off
|
||||
# if off >= block_size:
|
||||
# continue
|
||||
# size = min(off + size, block_size) - off
|
||||
#
|
||||
# # flatten/filter blocks
|
||||
# if isinstance(block, slice):
|
||||
# start = block.start if block.start is not None else 0
|
||||
# stop = block.stop if block.stop is not None else block_count
|
||||
# blocks.map(range(start, min(stop, block_count)),
|
||||
# lambda r: (r if r is not None else RangeSet())
|
||||
# | RangeSet([range(off, off+size)]))
|
||||
# else:
|
||||
# block = block if block is not None else 0
|
||||
# if block < block_count:
|
||||
# blocks.map(range(block, block+1),
|
||||
# lambda r: (r if r is not None else RangeSet())
|
||||
# | RangeSet([range(off, off+size)]))
|
||||
#
|
||||
# for block, r in blocks:
|
||||
# for off, stop in r:
|
||||
# yield off, stop-off
|
||||
#
|
||||
# def sorted_blocks(self, block_count):
|
||||
# # merge block ranges
|
||||
# blocks = RangeSet()
|
||||
# for block in self.blocks:
|
||||
# # flatten/filter blocks
|
||||
# if isinstance(block, slice):
|
||||
# start = block.start if block.start is not None else 0
|
||||
# stop = block.stop if block.stop is not None else block_count
|
||||
# blocks.add(range(start, min(stop, block_count)))
|
||||
# else:
|
||||
# block = block if block is not None else 0
|
||||
# if block < block_count:
|
||||
# blocks.add(range(block, block+1))
|
||||
#
|
||||
# yield from blocks
|
||||
#
|
||||
#
|
||||
#
|
||||
## # merge block ranges
|
||||
## merged = []
|
||||
## for blocks, offs in zip(self.blocks, self.offs):
|
||||
## # simplify blocks first
|
||||
## if not isinstance(blocks, slice):
|
||||
## blocks = slice(blocks, blocks+1)
|
||||
## blocks = slice(
|
||||
## blocks.start if blocks.start is not None else 0,
|
||||
## blocks.start if blocks.start is not None else block_count)
|
||||
##
|
||||
## # copy ranges before merge
|
||||
## i = 0
|
||||
## merged_ = []
|
||||
## blocks_ = blocks
|
||||
## while i < len(merged) and merged[i].stop < blocks_.start:
|
||||
## merged_.append(merged[i])
|
||||
##
|
||||
## # merge ranges and append
|
||||
## while i < len(merged) and merged[i].start <= blocks_.stop:
|
||||
## blocks_ = slice(
|
||||
## min(merged[i].start, blocks_.start),
|
||||
## max(merged[i].stop, blocks_.stop))
|
||||
## merged_.append(blocks_)
|
||||
##
|
||||
## # and copy the rest
|
||||
## merged_.extend(merged[i:])
|
||||
##
|
||||
##
|
||||
##
|
||||
##
|
||||
##
|
||||
## for blocks_ in merged:
|
||||
## # merge ranges?
|
||||
## if blocks_
|
||||
## else
|
||||
#
|
||||
#
|
||||
# def __contains__(self, block):
|
||||
# if isinstance(block, tuple):
|
||||
# block, off = block
|
||||
# else:
|
||||
# block, off = block, None
|
||||
#
|
||||
# for block_, off_ in zip(self.blocks, self.offs):
|
||||
# # in off range?
|
||||
# if off is not None:
|
||||
# off_ = off_ if off_ is not None else 0
|
||||
# size_ = self.size
|
||||
# if not (off >= off_
|
||||
# and (size_ is None or off < off_ + size_)):
|
||||
# continue
|
||||
#
|
||||
# # in block range?
|
||||
# if isinstance(block_, slice):
|
||||
# if ((block_.start is None or block >= block_.start)
|
||||
# and (block_.stop is None or block < block_.stop)):
|
||||
# return True
|
||||
# else:
|
||||
# if block_ is None or block == block_:
|
||||
# return True
|
||||
#
|
||||
# return False
|
||||
|
||||
|
||||
|
||||
def main(disk, output, mroots=None, *,
|
||||
trunk=None,
|
||||
@@ -5799,47 +5223,6 @@ if __name__ == "__main__":
|
||||
'--block-count',
|
||||
type=lambda x: int(x, 0),
|
||||
help="Block count in blocks.")
|
||||
|
||||
# # subparser for block arguments
|
||||
# blocks_parser = argparse.ArgumentParser(
|
||||
# prog="%s -@/--blocks" % parser.prog,
|
||||
# allow_abbrev=False)
|
||||
# blocks_parser.add_argument(
|
||||
# 'blocks',
|
||||
# nargs='*',
|
||||
# type=lambda x: (
|
||||
# slice(*(int(x, 0) if x.strip() else None
|
||||
# for x in x.split(',', 1)))
|
||||
# if ',' in x and '{' not in x
|
||||
# else rbydaddr(x)),
|
||||
# help="Block addresses, may be a range.")
|
||||
# blocks_parser.add_argument(
|
||||
# '--off',
|
||||
# type=lambda x: (
|
||||
# slice(*(int(x, 0) if x.strip() else None
|
||||
# for x in x.split(',', 1)))
|
||||
# if ',' in x
|
||||
# else int(x, 0)),
|
||||
# help="Show a specific offset, may be a range.")
|
||||
# blocks_parser.add_argument(
|
||||
# '-n', '--size',
|
||||
# type=lambda x: (
|
||||
# slice(*(int(x, 0) if x.strip() else None
|
||||
# for x in x.split(',', 1)))
|
||||
# if ',' in x
|
||||
# else int(x, 0)),
|
||||
# help="Show this many bytes, may be a range.")
|
||||
#
|
||||
# parser.add_argument(
|
||||
# '-@', '--blocks',
|
||||
# type=lambda blocks: BmapSlice(**{k: v
|
||||
# for k, v in vars(blocks_parser.parse_intermixed_args(
|
||||
# shlex.split(blocks))).items()
|
||||
# if v is not None}),
|
||||
# help="Optional blocks to show, may be a range. Can also include "
|
||||
# "--off and -n/--size flags to indicate a range inside the "
|
||||
# "block, both which may also be ranges.")
|
||||
|
||||
parser.add_argument(
|
||||
'-@', '--blocks',
|
||||
type=lambda x: (
|
||||
|
||||
Reference in New Issue
Block a user