scripts: Dropped tag/weight when returning rattrs
Now that these are contained in the Rattr class, including the tag/weight just clutters these APIs and makes things more confusing. To make this more convenient, I've adding __iter__ methods that allow unpacking both the Rattr and Ralt classes. These more-or-less represent tag+weight+data tuples anyways.
This commit is contained in:
+109
-116
@@ -398,17 +398,8 @@ class Rattr:
|
|||||||
def tagrepr(self):
|
def tagrepr(self):
|
||||||
return tagrepr(self.tag, self.weight, self.size)
|
return tagrepr(self.tag, self.weight, self.size)
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return bool(self.data)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.data)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
return self.data[key]
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.data)
|
return iter((self.tag, self.weight, self.data))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ((self.tag, self.weight, self.data)
|
return ((self.tag, self.weight, self.data)
|
||||||
@@ -421,7 +412,8 @@ class Rattr:
|
|||||||
return hash((self.tag, self.weight, self.data))
|
return hash((self.tag, self.weight, self.data))
|
||||||
|
|
||||||
class Ralt:
|
class Ralt:
|
||||||
def __init__(self, tag, weight, block, toff, off, jump, color=None):
|
def __init__(self, tag, weight, block, toff, off, jump,
|
||||||
|
color=None, followed=None):
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
self.weight = weight
|
self.weight = weight
|
||||||
self.block = block
|
self.block = block
|
||||||
@@ -433,6 +425,7 @@ class Ralt:
|
|||||||
self.color = color
|
self.color = color
|
||||||
else:
|
else:
|
||||||
self.color = 'r' if tag & TAG_R else 'b'
|
self.color = 'r' if tag & TAG_R else 'b'
|
||||||
|
self.followed = followed
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def joff(self):
|
def joff(self):
|
||||||
@@ -444,6 +437,9 @@ class Ralt:
|
|||||||
def tagrepr(self):
|
def tagrepr(self):
|
||||||
return tagrepr(self.tag, self.weight, self.jump, self.toff)
|
return tagrepr(self.tag, self.weight, self.jump, self.toff)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter((self.tag, self.weight, self.jump))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ((self.tag, self.weight, self.jump)
|
return ((self.tag, self.weight, self.jump)
|
||||||
== (other.tag, other.weight, other.jump))
|
== (other.tag, other.weight, other.jump))
|
||||||
@@ -650,7 +646,7 @@ class Rbyd:
|
|||||||
def lookupnext(self, rid=-1, tag=None, *,
|
def lookupnext(self, rid=-1, tag=None, *,
|
||||||
path=False):
|
path=False):
|
||||||
if not self:
|
if not self:
|
||||||
return None, None, None, None, *(([],) if path else ())
|
return None, None, *(([],) if path else ())
|
||||||
|
|
||||||
tag = max(tag or 0, 0x1)
|
tag = max(tag or 0, 0x1)
|
||||||
lower = 0
|
lower = 0
|
||||||
@@ -684,10 +680,10 @@ class Rbyd:
|
|||||||
else:
|
else:
|
||||||
color = 'b'
|
color = 'b'
|
||||||
|
|
||||||
path_.append((
|
path_.append(Ralt(
|
||||||
Ralt(alt, w, self.block, j+jump, j+jump+d,
|
alt, w, self.block, j+jump, j+jump+d, jump,
|
||||||
jump, color),
|
color=color,
|
||||||
True))
|
followed=True))
|
||||||
|
|
||||||
# stay on path
|
# stay on path
|
||||||
else:
|
else:
|
||||||
@@ -706,10 +702,10 @@ class Rbyd:
|
|||||||
else:
|
else:
|
||||||
color = 'b'
|
color = 'b'
|
||||||
|
|
||||||
path_.append((
|
path_.append(Ralt(
|
||||||
Ralt(alt, w, self.block, j-d, j,
|
alt, w, self.block, j-d, j, jump,
|
||||||
jump, color),
|
color=color,
|
||||||
False))
|
followed=False))
|
||||||
|
|
||||||
# found tag
|
# found tag
|
||||||
else:
|
else:
|
||||||
@@ -718,11 +714,9 @@ class Rbyd:
|
|||||||
w_ = upper-lower
|
w_ = upper-lower
|
||||||
|
|
||||||
if not tag_ or (rid_, tag_) < (rid, tag):
|
if not tag_ or (rid_, tag_) < (rid, tag):
|
||||||
return None, None, None, None, *(([],) if path else ())
|
return None, None, *(([],) if path else ())
|
||||||
|
|
||||||
return (rid_,
|
return (rid_,
|
||||||
tag_,
|
|
||||||
w_,
|
|
||||||
Rattr(tag_, w_, self.block, j, j+d,
|
Rattr(tag_, w_, self.block, j, j+d,
|
||||||
self.data[j+d:j+d+jump]),
|
self.data[j+d:j+d+jump]),
|
||||||
*((path_,) if path else ()))
|
*((path_,) if path else ()))
|
||||||
@@ -732,22 +726,17 @@ class Rbyd:
|
|||||||
if tag is None:
|
if tag is None:
|
||||||
tag, mask = 0, 0xffff
|
tag, mask = 0, 0xffff
|
||||||
|
|
||||||
rid_, tag_, w_, rattr_, *path_ = self.lookupnext(
|
rid_, rattr_, *path_ = self.lookupnext(rid, tag & ~(mask or 0),
|
||||||
rid, tag & ~(mask or 0),
|
|
||||||
path=path)
|
path=path)
|
||||||
if (rid_ is None
|
if (rid_ is None
|
||||||
or rid_ != rid
|
or rid_ != rid
|
||||||
or (tag_ & ~(mask or 0)) != (tag & ~(mask or 0))):
|
or (rattr_.tag & ~(mask or 0)) != (tag & ~(mask or 0))):
|
||||||
if mask is not None:
|
if path:
|
||||||
return None, None, *path_
|
|
||||||
elif path:
|
|
||||||
return None, *path_
|
return None, *path_
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if mask is not None:
|
if path:
|
||||||
return tag_, rattr_, *path_
|
|
||||||
elif path:
|
|
||||||
return rattr_, *path_
|
return rattr_, *path_
|
||||||
else:
|
else:
|
||||||
return rattr_
|
return rattr_
|
||||||
@@ -772,13 +761,13 @@ class Rbyd:
|
|||||||
path=False):
|
path=False):
|
||||||
rid = -1
|
rid = -1
|
||||||
while True:
|
while True:
|
||||||
rid, tag, w, rattr, *path_ = self.lookupnext(rid,
|
rid, rattr, *path_ = self.lookupnext(rid,
|
||||||
path=path)
|
path=path)
|
||||||
# found end of tree?
|
# found end of tree?
|
||||||
if rid is None:
|
if rid is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield rid, tag, w, rattr, *path_
|
yield rid, rattr, *path_
|
||||||
rid += 1
|
rid += 1
|
||||||
|
|
||||||
def rattrs(self, rid=None, *,
|
def rattrs(self, rid=None, *,
|
||||||
@@ -786,23 +775,28 @@ class Rbyd:
|
|||||||
if rid is None:
|
if rid is None:
|
||||||
rid, tag = -1, 0
|
rid, tag = -1, 0
|
||||||
while True:
|
while True:
|
||||||
rid, tag, w, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
rid, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
||||||
path=path)
|
path=path)
|
||||||
# found end of tree?
|
# found end of tree?
|
||||||
if rid is None:
|
if rid is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield rid, tag, w, rattr, *path_
|
yield rid, rattr, *path_
|
||||||
|
tag = rattr.tag
|
||||||
else:
|
else:
|
||||||
tag = 0
|
tag = 0
|
||||||
while True:
|
while True:
|
||||||
rid_, tag, w, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
rid_, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
||||||
path=path)
|
path=path)
|
||||||
# found end of tree?
|
# found end of tree?
|
||||||
if rid_ is None or rid_ != rid:
|
if rid_ is None or rid_ != rid:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield tag, rattr, *path_
|
if path:
|
||||||
|
yield rattr, *path_
|
||||||
|
else:
|
||||||
|
yield rattr
|
||||||
|
tag = rattr.tag
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self.rattrs()
|
return self.rattrs()
|
||||||
@@ -814,19 +808,18 @@ class Rbyd:
|
|||||||
lower = 0
|
lower = 0
|
||||||
upper = self.weight
|
upper = self.weight
|
||||||
while lower < upper:
|
while lower < upper:
|
||||||
rid, tag, w, rattr = self.lookupnext(
|
rid, rattr = self.lookupnext(lower + (upper-1-lower)//2)
|
||||||
lower + (upper-1-lower)//2)
|
|
||||||
if rid is None:
|
if rid is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
# treat vestigial names as a catch-all
|
# treat vestigial names as a catch-all
|
||||||
if ((tag == TAG_NAME and rid-(w-1) == 0)
|
if ((rattr.tag == TAG_NAME and rid-(rattr.weight-1) == 0)
|
||||||
or (tag & 0xff00) != TAG_NAME):
|
or (rattr.tag & 0xff00) != TAG_NAME):
|
||||||
did_ = 0
|
did_ = 0
|
||||||
name_ = b''
|
name_ = b''
|
||||||
else:
|
else:
|
||||||
did_, d = fromleb128(rattr[:])
|
did_, d = fromleb128(rattr.data)
|
||||||
name_ = rattr[d:]
|
name_ = rattr.data[d:]
|
||||||
|
|
||||||
# bisect search space
|
# bisect search space
|
||||||
if (did_, name_) > (did, name):
|
if (did_, name_) > (did, name):
|
||||||
@@ -834,10 +827,10 @@ class Rbyd:
|
|||||||
elif (did_, name_) < (did, name):
|
elif (did_, name_) < (did, name):
|
||||||
lower = rid + 1
|
lower = rid + 1
|
||||||
# keep track of best match
|
# keep track of best match
|
||||||
best = (False, rid, tag, w, rattr)
|
best = (False, rid, rattr)
|
||||||
else:
|
else:
|
||||||
# found a match
|
# found a match
|
||||||
return True, rid, tag, w, rattr
|
return True, rid, rattr
|
||||||
|
|
||||||
return best
|
return best
|
||||||
|
|
||||||
@@ -846,12 +839,12 @@ class Rbyd:
|
|||||||
trunks = co.defaultdict(lambda: (-1, 0))
|
trunks = co.defaultdict(lambda: (-1, 0))
|
||||||
alts = co.defaultdict(lambda: {})
|
alts = co.defaultdict(lambda: {})
|
||||||
|
|
||||||
for rid, tag, w, rattr, path in self.rattrs(path=True):
|
for rid, rattr, path in self.rattrs(path=True):
|
||||||
# keep track of trunks/alts
|
# keep track of trunks/alts
|
||||||
trunks[rattr.toff] = (rid, tag)
|
trunks[rattr.toff] = (rid, rattr.tag)
|
||||||
|
|
||||||
for ralt, followed in path:
|
for ralt in path:
|
||||||
if followed:
|
if ralt.followed:
|
||||||
alts[ralt.toff] |= {'f': ralt.joff, 'c': ralt.color}
|
alts[ralt.toff] |= {'f': ralt.joff, 'c': ralt.color}
|
||||||
else:
|
else:
|
||||||
alts[ralt.toff] |= {'nf': ralt.off, 'c': ralt.color}
|
alts[ralt.toff] |= {'nf': ralt.off, 'c': ralt.color}
|
||||||
@@ -1007,60 +1000,53 @@ class Btree:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
# first tag indicates the branch's weight
|
# first tag indicates the branch's weight
|
||||||
rid_, tag_, w_, rattr_ = rbyd.lookupnext(rid)
|
rid_, name_ = rbyd.lookupnext(rid)
|
||||||
# if we hit this the rbyd is probably corrupt
|
# if we hit this the rbyd is probably corrupt
|
||||||
if rid_ is None:
|
if rid_ is None:
|
||||||
# still keep track of best guess in path
|
# still keep track of best guess in path
|
||||||
if path:
|
if path:
|
||||||
path_.append((bid, rbyd, rid, None, None, None))
|
path_.append((bid, rbyd, rid, None))
|
||||||
return (None, None, None, None,
|
return (None, None, None, None,
|
||||||
*((path_,) if path else ()))
|
*((path_,) if path else ()))
|
||||||
|
|
||||||
# keep track of path
|
# keep track of path
|
||||||
if path:
|
if path:
|
||||||
path_.append((bid + (rid_-rid), rbyd, rid_, tag_, w_, rattr_))
|
path_.append((bid + (rid_-rid), rbyd, rid_, name_))
|
||||||
|
|
||||||
# find branch tag if there is one
|
# find branch tag if there is one
|
||||||
_, branch_ = rbyd.lookup(rid_, TAG_BRANCH, 0x3)
|
branch_ = rbyd.lookup(rid_, TAG_BRANCH, 0x3)
|
||||||
|
|
||||||
# descend down branch?
|
# descend down branch?
|
||||||
if branch_ is not None and (
|
if branch_ is not None and (
|
||||||
not depth or depth_ < depth):
|
not depth or depth_ < depth):
|
||||||
block, trunk, cksum = frombranch(branch_[:])
|
block, trunk, cksum = frombranch(branch_.data)
|
||||||
rbyd = Rbyd.fetch(self.bd, block, trunk, cksum)
|
rbyd = Rbyd.fetch(self.bd, block, trunk, cksum)
|
||||||
# keep track of expected trunk/weight if corrupted
|
# keep track of expected trunk/weight if corrupted
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
rbyd.trunk = trunk
|
rbyd.trunk = trunk
|
||||||
rbyd.weight = w_
|
rbyd.weight = name_.weight
|
||||||
|
|
||||||
rid -= (rid_-(w_-1))
|
rid -= (rid_-(name_.weight-1))
|
||||||
depth_ += 1
|
depth_ += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return (bid + (rid_-rid), rbyd, rid_, w_,
|
return (bid + (rid_-rid), rbyd, rid_, name_,
|
||||||
*((path_,) if path else ()))
|
*((path_,) if path else ()))
|
||||||
|
|
||||||
def lookup(self, bid, tag=None, mask=None, *,
|
def lookup(self, bid, tag=None, mask=None, *,
|
||||||
path=False,
|
path=False,
|
||||||
depth=None):
|
depth=None):
|
||||||
# lookup rbyd in btree
|
# lookup rbyd in btree
|
||||||
bid_, rbyd_, rid_, w_, *path_ = self.lookupleaf(bid,
|
bid_, rbyd_, rid_, name_, *path_ = self.lookupleaf(bid,
|
||||||
path=path,
|
path=path,
|
||||||
depth=depth)
|
depth=depth)
|
||||||
if bid_ is None:
|
if bid_ is None:
|
||||||
if mask is not None:
|
return None, None, None, None, None, *path_
|
||||||
return None, None, None, None, *path_
|
|
||||||
else:
|
|
||||||
return None, None, None, *path_
|
|
||||||
|
|
||||||
# lookup tag in rbyd
|
# lookup tag in rbyd
|
||||||
tag_, rattr_ = rbyd_.lookup(rid_, tag, mask or 0)
|
rattr_ = rbyd_.lookup(rid_, tag, mask or 0)
|
||||||
|
|
||||||
# note rbyd/rid is still accessible with either path or lookupleaf
|
return bid_, rbyd_, rid_, name_, rattr_, *path_
|
||||||
if mask is not None:
|
|
||||||
return bid_, w_, tag_, rattr_, *path_
|
|
||||||
else:
|
|
||||||
return bid_, w_, rattr_, *path_
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if not isinstance(key, tuple):
|
if not isinstance(key, tuple):
|
||||||
@@ -1085,7 +1071,7 @@ class Btree:
|
|||||||
|
|
||||||
bid = 0
|
bid = 0
|
||||||
while True:
|
while True:
|
||||||
bid, rbyd, rid, w, *path_ = self.lookupleaf(bid,
|
bid, rbyd, rid, name, *path_ = self.lookupleaf(bid,
|
||||||
path=path,
|
path=path,
|
||||||
depth=depth)
|
depth=depth)
|
||||||
if bid is None:
|
if bid is None:
|
||||||
@@ -1093,7 +1079,7 @@ class Btree:
|
|||||||
|
|
||||||
yield (bid-rid + (rbyd.weight-1), rbyd,
|
yield (bid-rid + (rbyd.weight-1), rbyd,
|
||||||
*((path_[0][:-1],) if path else ()))
|
*((path_[0][:-1],) if path else ()))
|
||||||
bid += (rbyd.weight - w) + 1
|
bid += (rbyd.weight - name.weight) + 1
|
||||||
|
|
||||||
def traverse(self, *,
|
def traverse(self, *,
|
||||||
path=False,
|
path=False,
|
||||||
@@ -1102,7 +1088,7 @@ class Btree:
|
|||||||
for bid, rbyd, path_ in self.leaves(
|
for bid, rbyd, path_ in self.leaves(
|
||||||
path=True,
|
path=True,
|
||||||
depth=depth):
|
depth=depth):
|
||||||
for d, (bid_, rbyd_, rid_, tag_, w_, rattr_) in pathdelta(
|
for d, (bid_, rbyd_, rid_, name_) in pathdelta(
|
||||||
path_, ppath_):
|
path_, ppath_):
|
||||||
yield (bid_-rid_ + (rbyd_.weight-1), rbyd_,
|
yield (bid_-rid_ + (rbyd_.weight-1), rbyd_,
|
||||||
*((path_[:d],) if path else ()))
|
*((path_[:d],) if path else ()))
|
||||||
@@ -1116,11 +1102,12 @@ class Btree:
|
|||||||
for bid, rbyd, *path_ in self.leaves(
|
for bid, rbyd, *path_ in self.leaves(
|
||||||
path=path,
|
path=path,
|
||||||
depth=depth):
|
depth=depth):
|
||||||
for rid, tag, w, rattr in rbyd.rids():
|
for rid, name in rbyd.rids():
|
||||||
yield (bid-(rbyd.weight-1) + rid, w, tag, rattr,
|
yield (bid-(rbyd.weight-1) + rid,
|
||||||
|
rbyd, rid, name,
|
||||||
*((path_[0]+[
|
*((path_[0]+[
|
||||||
(bid-(rbyd.weight-1) + rid,
|
(bid-(rbyd.weight-1) + rid,
|
||||||
rbyd, rid, tag, w, rattr)],)
|
rbyd, rid, name)],)
|
||||||
if path else ()))
|
if path else ()))
|
||||||
|
|
||||||
def rattrs(self, bid=None, *,
|
def rattrs(self, bid=None, *,
|
||||||
@@ -1130,19 +1117,23 @@ class Btree:
|
|||||||
for bid, rbyd, *path_ in self.leaves(
|
for bid, rbyd, *path_ in self.leaves(
|
||||||
path=path,
|
path=path,
|
||||||
depth=depth):
|
depth=depth):
|
||||||
for rid, tag, w, rattr in rbyd.rids():
|
for rid, name in rbyd.rids():
|
||||||
for tag, rattr in rbyd.rattrs(rid):
|
for rattr in rbyd.rattrs(rid):
|
||||||
yield (bid-(rbyd.weight-1) + rid, w, tag, rattr,
|
yield (bid-(rbyd.weight-1) + rid,
|
||||||
|
rbyd, rid, name, rattr,
|
||||||
*((path_[0]+[
|
*((path_[0]+[
|
||||||
(bid-(rbyd.weight-1) + rid,
|
(bid-(rbyd.weight-1) + rid,
|
||||||
rbyd, rid, tag, w, rattr)],)
|
rbyd, rid, name)],)
|
||||||
if path else ()))
|
if path else ()))
|
||||||
else:
|
else:
|
||||||
bid, rbyd, rid, w, *path_ = self.lookupleaf(bid,
|
bid, rbyd, rid, name, *path_ = self.lookupleaf(bid,
|
||||||
path=path,
|
path=path,
|
||||||
depth=depth)
|
depth=depth)
|
||||||
for tag, rattr in rbyd.rattrs(rid):
|
for rattr in rbyd.rattrs(rid):
|
||||||
yield tag, rattr, *path_
|
if path:
|
||||||
|
yield rattr, *path_
|
||||||
|
else:
|
||||||
|
yield rattr
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self.rattrs()
|
return self.rattrs()
|
||||||
@@ -1155,29 +1146,29 @@ class Btree:
|
|||||||
depth_ = 1
|
depth_ = 1
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
found_, rid_, tag_, w_, rattr_ = rbyd.namelookup(did, name)
|
found_, rid_, name_ = rbyd.namelookup(did, name)
|
||||||
|
|
||||||
# find branch tag if there is one
|
# find branch tag if there is one
|
||||||
_, branch_ = rbyd.lookup(rid_, TAG_BRANCH, 0x3)
|
branch_ = rbyd.lookup(rid_, TAG_BRANCH, 0x3)
|
||||||
|
|
||||||
# found another branch
|
# found another branch
|
||||||
if branch is not None and (
|
if branch_ is not None and (
|
||||||
not depth or depth_ < depth):
|
not depth or depth_ < depth):
|
||||||
# update our bid
|
# update our bid
|
||||||
bid += rid_ - (w_-1)
|
bid += rid_ - (name_.weight-1)
|
||||||
|
|
||||||
block, trunk, cksum = frombranch(branch[:])
|
block, trunk, cksum = frombranch(branch_.data)
|
||||||
rbyd = Rbyd.fetch(self.bd, block, trunk, cksum)
|
rbyd = Rbyd.fetch(self.bd, block, trunk, cksum)
|
||||||
# keep track of expected trunk/weight if corrupted
|
# keep track of expected trunk/weight if corrupted
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
rbyd.trunk = trunk
|
rbyd.trunk = trunk
|
||||||
rbyd.weight = w_
|
rbyd.weight = name_.weight
|
||||||
|
|
||||||
depth_ += 1
|
depth_ += 1
|
||||||
|
|
||||||
# found best match
|
# found best match
|
||||||
else:
|
else:
|
||||||
return found_, bid + rid_, tag_, w_, rattr_
|
return found_, bid + rid_, rbyd, rid_, name_
|
||||||
|
|
||||||
# btree rbyd-tree generation for debugging
|
# btree rbyd-tree generation for debugging
|
||||||
def _tree_rtree(self, *,
|
def _tree_rtree(self, *,
|
||||||
@@ -1217,8 +1208,8 @@ class Btree:
|
|||||||
# global order and make tree rendering quite a bit easier
|
# global order and make tree rendering quite a bit easier
|
||||||
a_rid, a_tag = t.a
|
a_rid, a_tag = t.a
|
||||||
b_rid, b_tag = t.b
|
b_rid, b_tag = t.b
|
||||||
_, _, a_w, _ = rbyd.lookupnext(a_rid)
|
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
||||||
_, _, b_w, _ = rbyd.lookupnext(b_rid)
|
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
||||||
tree.add(TreeBranch(
|
tree.add(TreeBranch(
|
||||||
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
||||||
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
||||||
@@ -1227,17 +1218,17 @@ class Btree:
|
|||||||
|
|
||||||
# connect rbyd branches to rbyd roots
|
# connect rbyd branches to rbyd roots
|
||||||
if path:
|
if path:
|
||||||
l_bid, l_rbyd, l_rid, l_tag, l_w, l_rattr = path[-1]
|
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
||||||
l_tag, l_rattr = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
||||||
|
|
||||||
if rtree:
|
if rtree:
|
||||||
r_rid, r_tag = min(rtree, key=lambda t: t.depth).a
|
r_rid, r_tag = min(rtree, key=lambda t: t.depth).a
|
||||||
_, _, r_w, _ = rbyd.lookupnext(r_rid)
|
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
||||||
else:
|
else:
|
||||||
r_rid, r_tag, r_w, _ = rbyd.lookupnext()
|
r_rid, (_, r_w, _) = rbyd.lookupnext()
|
||||||
|
|
||||||
tree.add(TreeBranch(
|
tree.add(TreeBranch(
|
||||||
(l_bid-(l_w-1), len(path)-1, l_tag),
|
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
||||||
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
||||||
d-1))
|
d-1))
|
||||||
|
|
||||||
@@ -1294,7 +1285,7 @@ class Btree:
|
|||||||
tree = set()
|
tree = set()
|
||||||
root = None
|
root = None
|
||||||
branches = {}
|
branches = {}
|
||||||
for bid, w, tag, rattr, path in self.bids(
|
for bid, rbyd, rid, name, path in self.bids(
|
||||||
path=True,
|
path=True,
|
||||||
depth=depth):
|
depth=depth):
|
||||||
# create branch for each jump in path
|
# create branch for each jump in path
|
||||||
@@ -1303,15 +1294,16 @@ class Btree:
|
|||||||
# global order and make tree rendering quite a bit easier
|
# global order and make tree rendering quite a bit easier
|
||||||
#
|
#
|
||||||
a = root
|
a = root
|
||||||
for d, (bid_, rbyd_, rid_, tag_, w_, rattr_) in enumerate(path):
|
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
||||||
b = (bid_-(w_-1), d, tag_)
|
b = (bid_-(name_.weight-1), d, name_.tag)
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner
|
# remap branches to leaves if we aren't showing inner
|
||||||
# branches
|
# branches
|
||||||
if not inner:
|
if not inner:
|
||||||
if b not in branches:
|
if b not in branches:
|
||||||
bid_, rbyd_, rid_, tag_, w_, rattr_ = path[-1]
|
bid_, rbyd_, rid_, name_ = path[-1]
|
||||||
branches[b] = (bid_-(w_-1), len(path)-1, tag_)
|
branches[b] = (
|
||||||
|
bid_-(name_.weight-1), len(path)-1, name_.tag)
|
||||||
b = branches[b]
|
b = branches[b]
|
||||||
|
|
||||||
# render the root path on first rid, this is arbitrary
|
# render the root path on first rid, this is arbitrary
|
||||||
@@ -1391,26 +1383,27 @@ def main(disk, roots=None, *,
|
|||||||
# prbyd here means the last rendered rbyd, we update
|
# prbyd here means the last rendered rbyd, we update
|
||||||
# in dbg_branch to always print interleaved addresses
|
# in dbg_branch to always print interleaved addresses
|
||||||
prbyd = None
|
prbyd = None
|
||||||
def dbg_branch(d, bid, rbyd, rid, w):
|
def dbg_branch(d, bid, rbyd, rid, name):
|
||||||
nonlocal prbyd
|
nonlocal prbyd
|
||||||
|
|
||||||
# show human-readable representation
|
# show human-readable representation
|
||||||
for i, (tag, rattr) in enumerate(rbyd.rattrs(rid)):
|
for rattr in rbyd.rattrs(rid):
|
||||||
print('%10s %s%*s %-*s %s' % (
|
print('%10s %s%*s %-*s %s' % (
|
||||||
'%04x.%04x:' % (rbyd.block, rbyd.trunk)
|
'%04x.%04x:' % (rbyd.block, rbyd.trunk)
|
||||||
if prbyd is None or rbyd != prbyd
|
if prbyd is None or rbyd != prbyd
|
||||||
else '',
|
else '',
|
||||||
treerepr(tree, (bid-(w-1), d, tag), t_depth, color)
|
treerepr(tree, (bid-(name.weight-1), d, rattr.tag),
|
||||||
|
t_depth, color)
|
||||||
if args.get('tree')
|
if args.get('tree')
|
||||||
or args.get('tree_rbyd')
|
or args.get('tree_rbyd')
|
||||||
or args.get('tree_btree')
|
or args.get('tree_btree')
|
||||||
else '',
|
else '',
|
||||||
2*w_width+1, '' if i != 0
|
2*w_width+1, '%d-%d' % (bid-(rattr.weight-1), bid)
|
||||||
else '%d-%d' % (bid-(w-1), bid) if w > 1
|
if rattr.weight > 1
|
||||||
else bid if w > 0
|
else bid if rattr.weight > 0
|
||||||
else '',
|
else '',
|
||||||
21+w_width, rattr.tagrepr(),
|
21+w_width, rattr.tagrepr(),
|
||||||
next(xxd(rattr[:], 8), '')
|
next(xxd(rattr.data, 8), '')
|
||||||
if not args.get('raw')
|
if not args.get('raw')
|
||||||
and not args.get('no_truncate')
|
and not args.get('no_truncate')
|
||||||
else ''))
|
else ''))
|
||||||
@@ -1421,12 +1414,12 @@ def main(disk, roots=None, *,
|
|||||||
for o, line in enumerate(xxd(
|
for o, line in enumerate(xxd(
|
||||||
rbyd.data[rattr.toff:rattr.off])):
|
rbyd.data[rattr.toff:rattr.off])):
|
||||||
print('%9s: %*s%*s %s' % (
|
print('%9s: %*s%*s %s' % (
|
||||||
'%04x' % (j + o*16),
|
'%04x' % (rattr.toff + o*16),
|
||||||
t_width, '',
|
t_width, '',
|
||||||
2*w_width+1, '',
|
2*w_width+1, '',
|
||||||
line))
|
line))
|
||||||
if args.get('raw') or args.get('no_truncate'):
|
if args.get('raw') or args.get('no_truncate'):
|
||||||
for o, line in enumerate(xxd(rattr[:])):
|
for o, line in enumerate(xxd(rattr.data)):
|
||||||
print('%9s: %*s%*s %s' % (
|
print('%9s: %*s%*s %s' % (
|
||||||
'%04x' % (rattr.off + o*16),
|
'%04x' % (rattr.off + o*16),
|
||||||
t_width, '',
|
t_width, '',
|
||||||
@@ -1452,17 +1445,17 @@ def main(disk, roots=None, *,
|
|||||||
corrupted = True
|
corrupted = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# print inner btree entries if requested
|
# print inner branches if requested
|
||||||
if args.get('inner'):
|
if args.get('inner'):
|
||||||
for d, (bid_, rbyd_, rid_, tag_, w_, rattr_) in pathdelta(
|
for d, (bid_, rbyd_, rid_, name_) in pathdelta(
|
||||||
path, ppath):
|
path, ppath):
|
||||||
dbg_branch(d, bid_, rbyd_, rid_, w_)
|
dbg_branch(d, bid_, rbyd_, rid_, name_)
|
||||||
ppath = path
|
ppath = path
|
||||||
|
|
||||||
for rid, tag, w, rattr in rbyd.rids():
|
for rid, name in rbyd.rids():
|
||||||
bid_ = bid-(rbyd.weight-1) + rid
|
bid_ = bid-(rbyd.weight-1) + rid
|
||||||
# show the branch
|
# show the leaf entry/branch
|
||||||
dbg_branch(len(path), bid_, rbyd, rid, w)
|
dbg_branch(len(path), bid_, rbyd, rid, name)
|
||||||
|
|
||||||
if args.get('error_on_corrupt') and corrupted:
|
if args.get('error_on_corrupt') and corrupted:
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|||||||
+52
-58
@@ -387,17 +387,8 @@ class Rattr:
|
|||||||
def tagrepr(self):
|
def tagrepr(self):
|
||||||
return tagrepr(self.tag, self.weight, self.size)
|
return tagrepr(self.tag, self.weight, self.size)
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return bool(self.data)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.data)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
return self.data[key]
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.data)
|
return iter((self.tag, self.weight, self.data))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ((self.tag, self.weight, self.data)
|
return ((self.tag, self.weight, self.data)
|
||||||
@@ -410,7 +401,8 @@ class Rattr:
|
|||||||
return hash((self.tag, self.weight, self.data))
|
return hash((self.tag, self.weight, self.data))
|
||||||
|
|
||||||
class Ralt:
|
class Ralt:
|
||||||
def __init__(self, tag, weight, block, toff, off, jump, color=None):
|
def __init__(self, tag, weight, block, toff, off, jump,
|
||||||
|
color=None, followed=None):
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
self.weight = weight
|
self.weight = weight
|
||||||
self.block = block
|
self.block = block
|
||||||
@@ -422,6 +414,7 @@ class Ralt:
|
|||||||
self.color = color
|
self.color = color
|
||||||
else:
|
else:
|
||||||
self.color = 'r' if tag & TAG_R else 'b'
|
self.color = 'r' if tag & TAG_R else 'b'
|
||||||
|
self.followed = followed
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def joff(self):
|
def joff(self):
|
||||||
@@ -433,6 +426,9 @@ class Ralt:
|
|||||||
def tagrepr(self):
|
def tagrepr(self):
|
||||||
return tagrepr(self.tag, self.weight, self.jump, self.toff)
|
return tagrepr(self.tag, self.weight, self.jump, self.toff)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter((self.tag, self.weight, self.jump))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ((self.tag, self.weight, self.jump)
|
return ((self.tag, self.weight, self.jump)
|
||||||
== (other.tag, other.weight, other.jump))
|
== (other.tag, other.weight, other.jump))
|
||||||
@@ -639,7 +635,7 @@ class Rbyd:
|
|||||||
def lookupnext(self, rid=-1, tag=None, *,
|
def lookupnext(self, rid=-1, tag=None, *,
|
||||||
path=False):
|
path=False):
|
||||||
if not self:
|
if not self:
|
||||||
return None, None, None, None, *(([],) if path else ())
|
return None, None, *(([],) if path else ())
|
||||||
|
|
||||||
tag = max(tag or 0, 0x1)
|
tag = max(tag or 0, 0x1)
|
||||||
lower = 0
|
lower = 0
|
||||||
@@ -673,10 +669,10 @@ class Rbyd:
|
|||||||
else:
|
else:
|
||||||
color = 'b'
|
color = 'b'
|
||||||
|
|
||||||
path_.append((
|
path_.append(Ralt(
|
||||||
Ralt(alt, w, self.block, j+jump, j+jump+d,
|
alt, w, self.block, j+jump, j+jump+d, jump,
|
||||||
jump, color),
|
color=color,
|
||||||
True))
|
followed=True))
|
||||||
|
|
||||||
# stay on path
|
# stay on path
|
||||||
else:
|
else:
|
||||||
@@ -695,10 +691,10 @@ class Rbyd:
|
|||||||
else:
|
else:
|
||||||
color = 'b'
|
color = 'b'
|
||||||
|
|
||||||
path_.append((
|
path_.append(Ralt(
|
||||||
Ralt(alt, w, self.block, j-d, j,
|
alt, w, self.block, j-d, j, jump,
|
||||||
jump, color),
|
color=color,
|
||||||
False))
|
followed=False))
|
||||||
|
|
||||||
# found tag
|
# found tag
|
||||||
else:
|
else:
|
||||||
@@ -707,11 +703,9 @@ class Rbyd:
|
|||||||
w_ = upper-lower
|
w_ = upper-lower
|
||||||
|
|
||||||
if not tag_ or (rid_, tag_) < (rid, tag):
|
if not tag_ or (rid_, tag_) < (rid, tag):
|
||||||
return None, None, None, None, *(([],) if path else ())
|
return None, None, *(([],) if path else ())
|
||||||
|
|
||||||
return (rid_,
|
return (rid_,
|
||||||
tag_,
|
|
||||||
w_,
|
|
||||||
Rattr(tag_, w_, self.block, j, j+d,
|
Rattr(tag_, w_, self.block, j, j+d,
|
||||||
self.data[j+d:j+d+jump]),
|
self.data[j+d:j+d+jump]),
|
||||||
*((path_,) if path else ()))
|
*((path_,) if path else ()))
|
||||||
@@ -721,22 +715,17 @@ class Rbyd:
|
|||||||
if tag is None:
|
if tag is None:
|
||||||
tag, mask = 0, 0xffff
|
tag, mask = 0, 0xffff
|
||||||
|
|
||||||
rid_, tag_, w_, rattr_, *path_ = self.lookupnext(
|
rid_, rattr_, *path_ = self.lookupnext(rid, tag & ~(mask or 0),
|
||||||
rid, tag & ~(mask or 0),
|
|
||||||
path=path)
|
path=path)
|
||||||
if (rid_ is None
|
if (rid_ is None
|
||||||
or rid_ != rid
|
or rid_ != rid
|
||||||
or (tag_ & ~(mask or 0)) != (tag & ~(mask or 0))):
|
or (rattr_.tag_ & ~(mask or 0)) != (tag & ~(mask or 0))):
|
||||||
if mask is not None:
|
if path:
|
||||||
return None, None, *path_
|
|
||||||
elif path:
|
|
||||||
return None, *path_
|
return None, *path_
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if mask is not None:
|
if path:
|
||||||
return tag_, rattr_, *path_
|
|
||||||
elif path:
|
|
||||||
return rattr_, *path_
|
return rattr_, *path_
|
||||||
else:
|
else:
|
||||||
return rattr_
|
return rattr_
|
||||||
@@ -761,13 +750,13 @@ class Rbyd:
|
|||||||
path=False):
|
path=False):
|
||||||
rid = -1
|
rid = -1
|
||||||
while True:
|
while True:
|
||||||
rid, tag, w, rattr, *path_ = self.lookupnext(rid,
|
rid, rattr, *path_ = self.lookupnext(rid,
|
||||||
path=path)
|
path=path)
|
||||||
# found end of tree?
|
# found end of tree?
|
||||||
if rid is None:
|
if rid is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield rid, tag, w, rattr, *path_
|
yield rid, rattr, *path_
|
||||||
rid += 1
|
rid += 1
|
||||||
|
|
||||||
def rattrs(self, rid=None, *,
|
def rattrs(self, rid=None, *,
|
||||||
@@ -775,23 +764,28 @@ class Rbyd:
|
|||||||
if rid is None:
|
if rid is None:
|
||||||
rid, tag = -1, 0
|
rid, tag = -1, 0
|
||||||
while True:
|
while True:
|
||||||
rid, tag, w, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
rid, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
||||||
path=path)
|
path=path)
|
||||||
# found end of tree?
|
# found end of tree?
|
||||||
if rid is None:
|
if rid is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield rid, tag, w, rattr, *path_
|
yield rid, rattr, *path_
|
||||||
|
tag = rattr.tag
|
||||||
else:
|
else:
|
||||||
tag = 0
|
tag = 0
|
||||||
while True:
|
while True:
|
||||||
rid_, tag, w, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
rid_, rattr, *path_ = self.lookupnext(rid, tag+0x1,
|
||||||
path=path)
|
path=path)
|
||||||
# found end of tree?
|
# found end of tree?
|
||||||
if rid_ is None or rid_ != rid:
|
if rid_ is None or rid_ != rid:
|
||||||
break
|
break
|
||||||
|
|
||||||
yield tag, rattr, *path_
|
if path:
|
||||||
|
yield rattr, *path_
|
||||||
|
else:
|
||||||
|
yield rattr
|
||||||
|
tag = rattr.tag
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self.rattrs()
|
return self.rattrs()
|
||||||
@@ -803,19 +797,18 @@ class Rbyd:
|
|||||||
lower = 0
|
lower = 0
|
||||||
upper = self.weight
|
upper = self.weight
|
||||||
while lower < upper:
|
while lower < upper:
|
||||||
rid, tag, w, rattr = self.lookupnext(
|
rid, rattr = self.lookupnext(lower + (upper-1-lower)//2)
|
||||||
lower + (upper-1-lower)//2)
|
|
||||||
if rid is None:
|
if rid is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
# treat vestigial names as a catch-all
|
# treat vestigial names as a catch-all
|
||||||
if ((tag == TAG_NAME and rid-(w-1) == 0)
|
if ((rattr.tag == TAG_NAME and rid-(rattr.weight-1) == 0)
|
||||||
or (tag & 0xff00) != TAG_NAME):
|
or (rattr.tag & 0xff00) != TAG_NAME):
|
||||||
did_ = 0
|
did_ = 0
|
||||||
name_ = b''
|
name_ = b''
|
||||||
else:
|
else:
|
||||||
did_, d = fromleb128(rattr[:])
|
did_, d = fromleb128(rattr.data)
|
||||||
name_ = rattr[d:]
|
name_ = rattr.data[d:]
|
||||||
|
|
||||||
# bisect search space
|
# bisect search space
|
||||||
if (did_, name_) > (did, name):
|
if (did_, name_) > (did, name):
|
||||||
@@ -823,10 +816,10 @@ class Rbyd:
|
|||||||
elif (did_, name_) < (did, name):
|
elif (did_, name_) < (did, name):
|
||||||
lower = rid + 1
|
lower = rid + 1
|
||||||
# keep track of best match
|
# keep track of best match
|
||||||
best = (False, rid, tag, w, rattr)
|
best = (False, rid, rattr)
|
||||||
else:
|
else:
|
||||||
# found a match
|
# found a match
|
||||||
return True, rid, tag, w, rattr
|
return True, rid, rattr
|
||||||
|
|
||||||
return best
|
return best
|
||||||
|
|
||||||
@@ -835,12 +828,12 @@ class Rbyd:
|
|||||||
trunks = co.defaultdict(lambda: (-1, 0))
|
trunks = co.defaultdict(lambda: (-1, 0))
|
||||||
alts = co.defaultdict(lambda: {})
|
alts = co.defaultdict(lambda: {})
|
||||||
|
|
||||||
for rid, tag, w, rattr, path in self.rattrs(path=True):
|
for rid, rattr, path in self.rattrs(path=True):
|
||||||
# keep track of trunks/alts
|
# keep track of trunks/alts
|
||||||
trunks[rattr.toff] = (rid, tag)
|
trunks[rattr.toff] = (rid, rattr.tag)
|
||||||
|
|
||||||
for ralt, followed in path:
|
for ralt in path:
|
||||||
if followed:
|
if ralt.followed:
|
||||||
alts[ralt.toff] |= {'f': ralt.joff, 'c': ralt.color}
|
alts[ralt.toff] |= {'f': ralt.joff, 'c': ralt.color}
|
||||||
else:
|
else:
|
||||||
alts[ralt.toff] |= {'nf': ralt.off, 'c': ralt.color}
|
alts[ralt.toff] |= {'nf': ralt.off, 'c': ralt.color}
|
||||||
@@ -1311,21 +1304,22 @@ def dbg_tree(rbyd, *,
|
|||||||
# dynamically size the id field
|
# dynamically size the id field
|
||||||
w_width = mt.ceil(mt.log10(max(1, rbyd.weight)+1))
|
w_width = mt.ceil(mt.log10(max(1, rbyd.weight)+1))
|
||||||
|
|
||||||
for i, (rid, tag, w, rattr) in enumerate(rbyd):
|
for i, (rid, rattr) in enumerate(rbyd):
|
||||||
# show human-readable tag representation
|
# show human-readable tag representation
|
||||||
print('%08x: %s%*s %-*s %s' % (
|
print('%08x: %s%*s %-*s %s' % (
|
||||||
rattr.toff,
|
rattr.toff,
|
||||||
treerepr(tree, (rid, tag), t_depth, color)
|
treerepr(tree, (rid, rattr.tag), t_depth, color)
|
||||||
if args.get('tree') or args.get('tree_rbyd')
|
if args.get('tree') or args.get('tree_rbyd')
|
||||||
else '',
|
else '',
|
||||||
2*w_width+1, '%d-%d' % (rid-(w-1), rid) if w > 1
|
2*w_width+1, '%d-%d' % (rid-(rattr.weight-1), rid)
|
||||||
else rid if w > 0 or i == 0
|
if rattr.weight > 1
|
||||||
|
else rid if rattr.weight > 0 or i == 0
|
||||||
else '',
|
else '',
|
||||||
21+w_width, rattr.tagrepr(),
|
21+w_width, rattr.tagrepr(),
|
||||||
next(xxd(rattr[:8], 8), '')
|
next(xxd(rattr.data[:8], 8), '')
|
||||||
if not args.get('raw')
|
if not args.get('raw')
|
||||||
and not args.get('no_truncate')
|
and not args.get('no_truncate')
|
||||||
and not tag & TAG_ALT
|
and not rattr.tag & TAG_ALT
|
||||||
else ''))
|
else ''))
|
||||||
|
|
||||||
# show on-disk encoding of tags
|
# show on-disk encoding of tags
|
||||||
@@ -1337,8 +1331,8 @@ def dbg_tree(rbyd, *,
|
|||||||
2*w_width+1, '',
|
2*w_width+1, '',
|
||||||
line))
|
line))
|
||||||
if args.get('raw') or args.get('no_truncate'):
|
if args.get('raw') or args.get('no_truncate'):
|
||||||
if not tag & TAG_ALT:
|
if not rattr.tag & TAG_ALT:
|
||||||
for o, line in enumerate(xxd(rattr[:])):
|
for o, line in enumerate(xxd(rattr.data)):
|
||||||
print('%8s: %*s%*s %s' % (
|
print('%8s: %*s%*s %s' % (
|
||||||
'%04x' % (rattr.off + o*16),
|
'%04x' % (rattr.off + o*16),
|
||||||
t_width, '',
|
t_width, '',
|
||||||
|
|||||||
Reference in New Issue
Block a user