Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Kirill Smelkov
wendelin.core
Commits
db2d48ae
Commit
db2d48ae
authored
Sep 27, 2021
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
5a23e03b
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
951 additions
and
354 deletions
+951
-354
wcfs/internal/xbtree/blib/gen-rangemap
wcfs/internal/xbtree/blib/gen-rangemap
+48
-0
wcfs/internal/xbtree/blib/keyrange.go
wcfs/internal/xbtree/blib/keyrange.go
+49
-0
wcfs/internal/xbtree/blib/rangemap.go.in
wcfs/internal/xbtree/blib/rangemap.go.in
+426
-0
wcfs/internal/xbtree/blib/rangeset.go
wcfs/internal/xbtree/blib/rangeset.go
+2
-354
wcfs/internal/xbtree/blib/rangeset.go.orig
wcfs/internal/xbtree/blib/rangeset.go.orig
+426
-0
No files found.
wcfs/internal/xbtree/blib/gen-rangemap
0 → 100755
View file @
db2d48ae
#!/bin/bash -e
# rangemap.go.in -> specialized with concrete types
# gen-rangemap KIND VALUE out
# Copyright (C) 2018-2021 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
KIND
=
$1
VALUE
=
$2
out
=
$3
kind
=
${
KIND
,,
}
# IO -> io
Value
=
${
VALUE
^
}
input
=
$(
dirname
$0
)
/rangemap.go.in
echo
"// Code generated by gen-rangemap; DO NOT EDIT."
>
$out
echo
>>
$out
sed
\
-e
"s/<kind>/
$kind
/g"
\
-e
"s/<KIND>/
$KIND
/g"
\
-e
"s/VALUE/
$VALUE
/g"
\
-e
"s/<Value>/
$Value
/g"
\
-e
"s/
\b
Node
\b
/
${
KIND
}
Node/g"
\
-e
"s/
\b
BTree
\b
/
${
KIND
}
BTree/g"
\
-e
"s/
\b
Entry
\b
/
${
KIND
}
Entry/g"
\
-e
"s/
\b
Bucket
\b
/
${
KIND
}
Bucket/g"
\
-e
"s/
\b
BucketEntry
\b
/
${
KIND
}
BucketEntry/g"
\
-e
"s/
\b
btreeState
\b
/
${
kind
}
btreeState/g"
\
-e
"s/
\b
bucketState
\b
/
${
kind
}
bucketState/g"
\
$input
>>
$out
wcfs/internal/xbtree/blib/
rangemap
.go
→
wcfs/internal/xbtree/blib/
keyrange
.go
View file @
db2d48ae
...
...
@@ -18,99 +18,32 @@
// See https://www.nexedi.com/licensing for rationale and options.
package
blib
//
map [lo,hi) Key ranges to value
s.
//
range of key
s.
import
(
"fmt"
)
const
traceRangeMap
=
true
const
debugRangeMap
=
true
type
VALUE
=
interface
{}
// RangedMap is Key->VALUE map with adjacent keys mapped to the same value coalesced into Ranges.
//
// Zero value represents empty map.
type
RangedMap
struct
{
// XXX -> BTree
entryv
[]
mapEntry
// lo↑
}
type
mapEntry
struct
{
keycov
KeyRange
value
VALUE
}
// Set changes m to map key k to value v.
func
(
m
*
RangedMap
)
Set
(
k
Key
,
v
VALUE
)
{
m
.
SetRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
},
v
)
}
// Del removes key k.
func
(
m
*
RangedMap
)
Del
(
k
Key
)
{
m
.
DelRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
// Has returns whether key k is present in the map.
func
(
m
*
RangedMap
)
Has
(
k
Key
)
bool
{
_
,
ok
:=
m
.
Get_
(
k
)
return
ok
}
// Get returns value associated with key k.
func
(
m
*
RangedMap
)
Get
(
k
Key
)
VALUE
{
v
,
_
:=
m
.
Get_
(
k
)
return
v
// KeyRange represents [lo,hi) Key range.
type
KeyRange
struct
{
Lo
Key
Hi_
Key
// NOTE _not_ hi) to avoid overflow at ∞; hi = hi_ + 1
}
// Get_ is comma-ok version of Get.
func
(
m
*
RangedMap
)
Get_
(
k
Key
)
(
VALUE
,
bool
)
{
panic
(
"TODO"
)
// XXX
}
// SetRange changes m to map key range r to value v.
func
(
m
*
RangedMap
)
SetRange
(
r
KeyRange
,
v
VALUE
)
{
panic
(
"TODO"
)
// XXX
}
//
DelRange removes range r from the map
.
func
(
m
*
RangedMap
)
DelRange
(
r
KeyRange
)
{
panic
(
"TODO"
)
// XXX
//
Has returns whether key k belongs to the range
.
func
(
r
*
KeyRange
)
Has
(
k
Key
)
bool
{
return
(
r
.
Lo
<=
k
&&
k
<=
r
.
Hi_
)
}
// XXX HasRange ?
// --------
// verify checks RangedMap for internal consistency:
// - XXX
func
(
m
*
RangedMap
)
verify
()
{
// XXX
}
// Empty returns whether the map is empty.
func
(
m
*
RangedMap
)
Empty
()
bool
{
return
len
(
m
.
entryv
)
==
0
}
// XXX Equal ?
// XXX Clear ?
// XXX AllEntries ?
func
(
m
*
RangedMap
)
String
()
string
{
s
:=
"{"
for
i
,
e
:=
range
m
.
entryv
{
if
i
>
0
{
s
+=
" "
}
s
+=
fmt
.
Sprintf
(
"%s:%v"
,
e
.
keycov
,
e
.
value
)
func
(
r
KeyRange
)
String
()
string
{
var
shi
string
if
r
.
Hi_
==
KeyMax
{
shi
=
KStr
(
r
.
Hi_
)
// ∞
}
else
{
shi
=
fmt
.
Sprintf
(
"%d"
,
r
.
Hi_
+
1
)
}
s
+=
"}"
return
s
return
fmt
.
Sprintf
(
"[%s,%s)"
,
KStr
(
r
.
Lo
),
shi
)
}
wcfs/internal/xbtree/blib/rangemap.go.in
0 → 100644
View file @
db2d48ae
//
Copyright
(
C
)
2021
Nexedi
SA
and
Contributors
.
//
Kirill
Smelkov
<
kirr
@
nexedi
.
com
>
//
//
This
program
is
free
software
:
you
can
Use
,
Study
,
Modify
and
Redistribute
//
it
under
the
terms
of
the
GNU
General
Public
License
version
3
,
or
(
at
your
//
option
)
any
later
version
,
as
published
by
the
Free
Software
Foundation
.
//
//
You
can
also
Link
and
Combine
this
program
with
other
software
covered
by
//
the
terms
of
any
of
the
Free
Software
licenses
or
any
of
the
Open
Source
//
Initiative
approved
licenses
and
Convey
the
resulting
work
.
Corresponding
//
source
of
such
a
combination
shall
include
the
source
code
for
all
other
//
software
used
.
//
//
This
program
is
distributed
WITHOUT
ANY
WARRANTY
;
without
even
the
implied
//
warranty
of
MERCHANTABILITY
or
FITNESS
FOR
A
PARTICULAR
PURPOSE
.
//
//
See
COPYING
file
for
full
licensing
terms
.
//
See
https
://
www
.
nexedi
.
com
/
licensing
for
rationale
and
options
.
package
blib
//
map
[
lo
,
hi
)
Key
ranges
to
values
.
import
(
"fmt"
"sort"
)
const
traceRangeMap
=
true
const
debugRangeMap
=
true
//
RangedMap
is
Key
->
VALUE
map
with
adjacent
keys
mapped
to
the
same
value
coalesced
into
Ranges
.
//
//
Zero
value
represents
empty
map
.
type
RangedMap
struct
{
//
TODO
rework
to
use
BTree
lo
->
hi_
instead
if
in
practice
in
treediff
,
//
and
other
usage
places
,
N
(
ranges
)
turns
out
to
be
not
small
//
(
i
.
e
.
performance
turns
out
to
be
not
acceptable
)
entryv
[]
mapEntry
//
lo
↑
}
//
mapEntry
represents
one
entry
in
RangedMap
.
type
mapEntry
struct
{
keycov
KeyRange
value
VALUE
}
//
Set
changes
M
to
map
key
k
to
value
v
.
func
(
M
*
RangedMap
)
Set
(
k
Key
,
v
VALUE
)
{
M
.
SetRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
},
v
)
}
//
Del
removes
key
k
.
func
(
M
*
RangedMap
)
Del
(
k
Key
)
{
M
.
DelRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
//
Has
returns
whether
key
k
is
present
in
the
map
.
func
(
M
*
RangedMap
)
Has
(
k
Key
)
bool
{
_
,
ok
:=
M
.
Get_
(
k
)
return
ok
}
//
Get
returns
value
associated
with
key
k
.
func
(
M
*
RangedMap
)
Get
(
k
Key
)
VALUE
{
v
,
_
:=
M
.
Get_
(
k
)
return
v
}
//
Get_
is
comma
-
ok
version
of
Get
.
func
(
M
*
RangedMap
)
Get_
(
k
Key
)
(
VALUE
,
bool
)
{
panic
(
"TODO"
)
//
XXX
}
//
SetRange
changes
M
to
map
key
range
r
to
value
v
.
func
(
M
*
RangedMap
)
SetRange
(
r
KeyRange
,
v
VALUE
)
{
panic
(
"TODO"
)
//
XXX
}
//
DelRange
removes
range
r
from
the
map
.
func
(
M
*
RangedMap
)
DelRange
(
r
KeyRange
)
{
panic
(
"TODO"
)
//
XXX
}
//
HasRange
returns
whether
all
keys
from
range
r
belong
to
the
map
.
func
(
M
*
RangedMap
)
HasRange
(
r
KeyRange
)
bool
{
panic
(
"TODO"
)
//
XXX
}
//
--------
//
XXX
Equal
?
//
XXX
AllEntries
?
//
AddRange
adds
range
r
to
the
set
.
func
(
S
*
RangedKeySet
)
AddRange
(
r
KeyRange
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
AddRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
fmt
.
Printf
(
"->u: %s
\n
"
,
S
)
}
S
.
verify
()
defer
S
.
verify
()
//
find
first
ilo
:
r
.
Lo
<
[
ilo
].
hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
].
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
//
not
found
S
.
rangev
=
append
(
S
.
rangev
,
r
)
l
++
debugfRSet
(
"
\t
append %s
\t
-> %s
\n
"
,
r
,
S
)
}
//
find
last
jhi
:
[
jhi
].
Lo
<
r
.
hi
jhi
:=
ilo
for
;;
jhi
++
{
if
jhi
==
l
{
break
}
if
S
.
rangev
[
jhi
].
Lo
<=
r
.
Hi_
{
continue
}
break
}
debugfRSet
(
"
\t
jhi: %d
\n
"
,
jhi
)
//
entries
in
[
ilo
:
jhi
)
∈
[
r
.
Lo
,
r
.
hi
)
and
should
be
merged
into
one
if
(
jhi
-
ilo
)
>
1
{
lo
:=
S
.
rangev
[
ilo
].
Lo
hi_
:=
S
.
rangev
[
jhi
-
1
].
Hi_
vReplaceSlice
(&
S
.
rangev
,
ilo
,
jhi
,
KeyRange
{
lo
,
hi_
})
debugfRSet
(
"
\t
merge S[%d:%d]
\t
-> %s
\n
"
,
ilo
,
jhi
,
S
)
}
jhi
=
-
1
//
no
longer
valid
//
if
[
r
.
lo
,
r
.
hi
)
was
outside
of
any
entry
-
create
new
entry
if
r
.
Hi_
<
S
.
rangev
[
ilo
].
Lo
{
vInsert
(&
S
.
rangev
,
ilo
,
r
)
debugfRSet
(
"
\t
insert %s
\t
-> %s
\n
"
,
r
,
S
)
}
//
now
we
have
covered
entries
merged
as
needed
into
[
ilo
]
//
extend
this
entry
if
r
coverage
is
wider
if
r
.
Lo
<
S
.
rangev
[
ilo
].
Lo
{
S
.
rangev
[
ilo
].
Lo
=
r
.
Lo
debugfRSet
(
"
\t
extend left
\t
-> %s
\n
"
,
S
)
}
if
r
.
Hi_
>
S
.
rangev
[
ilo
].
Hi_
{
S
.
rangev
[
ilo
].
Hi_
=
r
.
Hi_
debugfRSet
(
"
\t
extend right
\t
-> %s
\n
"
,
S
)
}
//
and
check
if
we
should
merge
it
with
right
/
left
neighbours
if
ilo
+
1
<
len
(
S
.
rangev
)
{
//
right
if
S
.
rangev
[
ilo
].
Hi_
+
1
==
S
.
rangev
[
ilo
+
1
].
Lo
{
vReplaceSlice
(&
S
.
rangev
,
ilo
,
ilo
+
2
,
KeyRange
{
S
.
rangev
[
ilo
].
Lo
,
S
.
rangev
[
ilo
+
1
].
Hi_
})
debugfRSet
(
"
\t
merge right
\t
-> %s
\n
"
,
S
)
}
}
if
ilo
>
0
{
//
left
if
S
.
rangev
[
ilo
-
1
].
Hi_
+
1
==
S
.
rangev
[
ilo
].
Lo
{
vReplaceSlice
(&
S
.
rangev
,
ilo
-
1
,
ilo
+
1
,
KeyRange
{
S
.
rangev
[
ilo
-
1
].
Lo
,
S
.
rangev
[
ilo
].
Hi_
})
debugfRSet
(
"
\t
merge left
\t
-> %s
\n
"
,
S
)
}
}
//
done
}
//
DelRange
removes
range
r
from
the
set
.
func
(
S
*
RangedKeySet
)
DelRange
(
r
KeyRange
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
DelRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
fmt
.
Printf
(
"->d: %s
\n
"
,
S
)
}
S
.
verify
()
defer
S
.
verify
()
//
find
first
ilo
:
r
.
Lo
<
[
ilo
].
hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
].
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
//
not
found
debugfRSet
(
"
\t
non-overlap right
\n
"
)
return
}
//
find
last
jhi
:
[
jhi
].
Lo
<
r
.
hi
jhi
:=
ilo
for
;;
jhi
++
{
if
jhi
==
l
{
break
}
if
S
.
rangev
[
jhi
].
Lo
<=
r
.
Hi_
{
continue
}
break
}
debugfRSet
(
"
\t
jhi: %d
\n
"
,
jhi
)
if
jhi
==
0
{
debugfRSet
(
"
\t
non-overlap left
\n
"
)
return
}
//
[
ilo
+
1
:
jhi
-
1
]
should
be
deleted
//
[
ilo
]
and
[
jhi
-
1
]
overlap
with
[
r
.
lo
,
r
.
hi
)
-
they
should
be
deleted
,
or
shrinked
,
//
or
split
+
shrinked
if
ilo
==
jhi
-
1
and
r
is
inside
[
ilo
]
if
jhi
-
ilo
==
1
&&
S
.
rangev
[
ilo
].
Lo
<
r
.
Lo
&&
r
.
Hi_
<
S
.
rangev
[
ilo
].
Hi_
{
x
:=
S
.
rangev
[
ilo
]
vInsert
(&
S
.
rangev
,
ilo
,
x
)
jhi
++
debugfRSet
(
"
\t
presplit copy %s
\t
-> %s
\n
"
,
x
,
S
)
}
if
S
.
rangev
[
ilo
].
Lo
<
r
.
Lo
{
//
shrink
left
S
.
rangev
[
ilo
]
=
KeyRange
{
S
.
rangev
[
ilo
].
Lo
,
r
.
Lo
-
1
}
ilo
++
debugfRSet
(
"
\t
shrink [%d] left
\t
-> %s
\n
"
,
ilo
,
S
)
}
if
r
.
Hi_
<
S
.
rangev
[
jhi
-
1
].
Hi_
{
//
shrink
right
S
.
rangev
[
jhi
-
1
]
=
KeyRange
{
r
.
Hi_
+
1
,
S
.
rangev
[
jhi
-
1
].
Hi_
}
jhi
--
debugfRSet
(
"
\t
shrink [%d] right
\t
-> %s
\n
"
,
jhi
-
1
,
S
)
}
if
(
jhi
-
ilo
)
>
0
{
vDeleteSlice
(&
S
.
rangev
,
ilo
,
jhi
)
debugfRSet
(
"
\t
delete S[%d:%d]
\t
-> %s
\n
"
,
ilo
,
jhi
,
S
)
}
//
done
}
//
HasRange
returns
whether
all
keys
from
range
r
belong
to
the
set
.
func
(
S
*
RangedKeySet
)
HasRange
(
r
KeyRange
)
(
yes
bool
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
HasRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
func
()
{
fmt
.
Printf
(
"->·: %v
\n
"
,
yes
)
}()
}
S
.
verify
()
//
find
first
ilo
:
r
.
lo
<
[
ilo
].
hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
].
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
//
not
found
return
false
}
//
all
keys
from
r
are
in
S
if
r
∈
[
ilo
]
return
(
S
.
rangev
[
ilo
].
Lo
<=
r
.
Lo
&&
r
.
Hi_
<=
S
.
rangev
[
ilo
].
Hi_
)
}
//
--------
//
verify
checks
RangedMap
for
internal
consistency
:
//
-
ranges
must
be
not
overlapping
and
↑
//
-
adjacent
ranges
must
map
to
different
values
func
(
M
*
RangedMap
)
verify
()
{
//
TODO
!debug -> return
var
badv
[]
string
badf
:=
func
(
format
string
,
argv
...
interface
{})
{
badv
=
append
(
badv
,
fmt
.
Sprintf
(
format
,
argv
...))
}
defer
func
()
{
if
badv
!= nil {
emsg
:=
"M.verify: fail:
\n\n
"
for
_
,
bad
:=
range
badv
{
emsg
+=
fmt
.
Sprintf
(
"- %s
\n
"
,
bad
)
}
emsg
+=
fmt
.
Sprintf
(
"
\n
S: %s
\n
"
,
M
)
panic
(
emsg
)
}
}()
hi_Prev
:=
KeyMin
var
v_Prev
VALUE
for
i
,
e
:=
range
M
.
entryv
{
hiPrev
:=
hi_Prev
+
1
if
i
>
0
{
if
(
e
.
value
==
v_Prev
)
{
if
!(hiPrev < e.Lo) { // NOTE not ≤ - adjacent ranges must be merged
badf
(
"[%d]: same value: !(hiPrev < e.lo)"
,
i
)
}
}
else
{
if
!(hi_Prev <= e.Lo) {
badf
(
"[%d]: different value: !(hiPrev ≤ e.lo)"
,
i
)
}
}
}
if
!(e.Lo <= e.Hi_) {
badf
(
"[%d]: !(e.lo <= e.hi_)"
,
i
)
}
hi_Prev
=
e
.
Hi_
v_Prev
=
e
.
value
}
}
//
Clone
returns
copy
of
the
set
.
func
(
orig
*
RangedKeySet
)
Clone
()
*
RangedKeySet
{
klon
:=
&
RangedKeySet
{}
klon
.
rangev
=
append
(
klon
.
rangev
,
orig
.
rangev
...)
return
klon
}
//
Empty
returns
whether
the
map
is
empty
.
func
(
M
*
RangedMap
)
Empty
()
bool
{
return
len
(
M
.
entryv
)
==
0
}
//
Equal
returns
whether
A
==
B
.
func
(
A
*
RangedKeySet
)
Equal
(
B
*
RangedKeySet
)
bool
{
if
len
(
A
.
rangev
)
!= len(B.rangev) {
return
false
}
for
i
,
ra
:=
range
A
.
rangev
{
rb
:=
B
.
rangev
[
i
]
if
ra
!= rb {
return
false
}
}
return
true
}
//
Clear
removes
all
elements
from
the
map
.
func
(
M
*
RangedMap
)
Clear
()
{
M
.
entryv
=
nil
}
//
AllRanges
returns
slice
of
all
key
ranges
in
the
set
.
//
//
TODO
->
iter
?
func
(
S
*
RangedKeySet
)
AllRanges
()
/*
readonly
*/[]
KeyRange
{
return
S
.
rangev
}
//
XXX
->
ptr
?
func
(
M
RangedMap
)
String
()
string
{
s
:=
"{"
for
i
,
e
:=
range
M
.
entryv
{
if
i
>
0
{
s
+=
" "
}
s
+=
fmt
.
Sprintf
(
"%s:%v"
,
e
.
keycov
,
e
.
value
)
}
s
+=
"}"
return
s
}
func
debugfRSet
(
format
string
,
argv
...
interface
{})
{
if
!debugRangeSet {
return
}
fmt
.
Printf
(
format
,
argv
...)
}
//
----
slice
ops
----
//
vInsert
inserts
r
into
*
pv
[
i
].
func
vInsert
(
pv
*[]
KeyRange
,
i
int
,
r
KeyRange
)
{
v
:=
*
pv
v
=
append
(
v
,
KeyRange
{})
copy
(
v
[
i
+
1
:],
v
[
i
:])
v
[
i
]
=
r
*
pv
=
v
}
//
vDeleteSlice
deletes
*
pv
[
lo
:
hi
].
func
vDeleteSlice
(
pv
*[]
KeyRange
,
lo
,
hi
int
)
{
v
:=
*
pv
n
:=
copy
(
v
[
lo
:],
v
[
hi
:])
v
=
v
[:
lo
+
n
]
*
pv
=
v
}
//
vReplaceSlice
replaces
*
pv
[
lo
:
hi
]
with
r
.
func
vReplaceSlice
(
pv
*[]
KeyRange
,
lo
,
hi
int
,
r
KeyRange
)
{
v
:=
*
pv
n
:=
copy
(
v
[
lo
+
1
:],
v
[
hi
:])
v
[
lo
]
=
r
v
=
v
[:
lo
+
1
+
n
]
*
pv
=
v
}
wcfs/internal/xbtree/blib/rangeset.go
View file @
db2d48ae
...
...
@@ -20,234 +20,16 @@
package
blib
// set of [lo,hi) Key ranges.
import
(
"fmt"
"sort"
)
const
traceRangeSet
=
false
const
debugRangeSet
=
false
// KeyRange represents [lo,hi) Key range.
type
KeyRange
struct
{
Lo
Key
Hi_
Key
// NOTE _not_ hi) to avoid overflow at ∞; hi = hi_ + 1
}
//go:generate gen-rangemap void struct{} zrangemap_void.go
// RangedKeySet is set of Keys with adjacent keys coalesced into Ranges.
//
// Zero value represents empty set.
type
RangedKeySet
struct
{
// TODO rework to use BTree lo->hi_ instead if in practice in treediff,
// and other usage places, N(ranges) turns out to be not small
// (i.e. performance turns out to be not acceptable)
rangev
[]
KeyRange
// lo↑
}
// Has returns whether key k belongs to the range.
func
(
r
*
KeyRange
)
Has
(
k
Key
)
bool
{
return
(
r
.
Lo
<=
k
&&
k
<=
r
.
Hi_
)
}
// Add adds key k to the set.
func
(
S
*
RangedKeySet
)
Add
(
k
Key
)
{
S
.
AddRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
// Del removes key k from the set.
func
(
S
*
RangedKeySet
)
Del
(
k
Key
)
{
S
.
DelRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
// Has returns whether key k belongs to the set.
func
(
S
*
RangedKeySet
)
Has
(
k
Key
)
bool
{
return
S
.
HasRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
// AddRange adds range r to the set.
func
(
S
*
RangedKeySet
)
AddRange
(
r
KeyRange
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
AddRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
fmt
.
Printf
(
"->u: %s
\n
"
,
S
)
}
S
.
verify
()
defer
S
.
verify
()
// find first ilo: r.Lo < [ilo].hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
]
.
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
// not found
S
.
rangev
=
append
(
S
.
rangev
,
r
)
l
++
debugfRSet
(
"
\t
append %s
\t
-> %s
\n
"
,
r
,
S
)
}
// find last jhi: [jhi].Lo < r.hi
jhi
:=
ilo
for
;;
jhi
++
{
if
jhi
==
l
{
break
}
if
S
.
rangev
[
jhi
]
.
Lo
<=
r
.
Hi_
{
continue
}
break
}
debugfRSet
(
"
\t
jhi: %d
\n
"
,
jhi
)
// entries in [ilo:jhi) ∈ [r.Lo,r.hi) and should be merged into one
if
(
jhi
-
ilo
)
>
1
{
lo
:=
S
.
rangev
[
ilo
]
.
Lo
hi_
:=
S
.
rangev
[
jhi
-
1
]
.
Hi_
vReplaceSlice
(
&
S
.
rangev
,
ilo
,
jhi
,
KeyRange
{
lo
,
hi_
})
debugfRSet
(
"
\t
merge S[%d:%d]
\t
-> %s
\n
"
,
ilo
,
jhi
,
S
)
}
jhi
=
-
1
// no longer valid
// if [r.lo,r.hi) was outside of any entry - create new entry
if
r
.
Hi_
<
S
.
rangev
[
ilo
]
.
Lo
{
vInsert
(
&
S
.
rangev
,
ilo
,
r
)
debugfRSet
(
"
\t
insert %s
\t
-> %s
\n
"
,
r
,
S
)
}
// now we have covered entries merged as needed into [ilo]
// extend this entry if r coverage is wider
if
r
.
Lo
<
S
.
rangev
[
ilo
]
.
Lo
{
S
.
rangev
[
ilo
]
.
Lo
=
r
.
Lo
debugfRSet
(
"
\t
extend left
\t
-> %s
\n
"
,
S
)
}
if
r
.
Hi_
>
S
.
rangev
[
ilo
]
.
Hi_
{
S
.
rangev
[
ilo
]
.
Hi_
=
r
.
Hi_
debugfRSet
(
"
\t
extend right
\t
-> %s
\n
"
,
S
)
}
// and check if we should merge it with right/left neighbours
if
ilo
+
1
<
len
(
S
.
rangev
)
{
// right
if
S
.
rangev
[
ilo
]
.
Hi_
+
1
==
S
.
rangev
[
ilo
+
1
]
.
Lo
{
vReplaceSlice
(
&
S
.
rangev
,
ilo
,
ilo
+
2
,
KeyRange
{
S
.
rangev
[
ilo
]
.
Lo
,
S
.
rangev
[
ilo
+
1
]
.
Hi_
})
debugfRSet
(
"
\t
merge right
\t
-> %s
\n
"
,
S
)
}
}
if
ilo
>
0
{
// left
if
S
.
rangev
[
ilo
-
1
]
.
Hi_
+
1
==
S
.
rangev
[
ilo
]
.
Lo
{
vReplaceSlice
(
&
S
.
rangev
,
ilo
-
1
,
ilo
+
1
,
KeyRange
{
S
.
rangev
[
ilo
-
1
]
.
Lo
,
S
.
rangev
[
ilo
]
.
Hi_
})
debugfRSet
(
"
\t
merge left
\t
-> %s
\n
"
,
S
)
}
}
// done
m
_RangedKeyMap_void
// XXX naming
}
// DelRange removes range r from the set.
func
(
S
*
RangedKeySet
)
DelRange
(
r
KeyRange
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
DelRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
fmt
.
Printf
(
"->d: %s
\n
"
,
S
)
}
S
.
verify
()
defer
S
.
verify
()
// find first ilo: r.Lo < [ilo].hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
]
.
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
// not found
debugfRSet
(
"
\t
non-overlap right
\n
"
)
return
}
// find last jhi: [jhi].Lo < r.hi
jhi
:=
ilo
for
;;
jhi
++
{
if
jhi
==
l
{
break
}
if
S
.
rangev
[
jhi
]
.
Lo
<=
r
.
Hi_
{
continue
}
break
}
debugfRSet
(
"
\t
jhi: %d
\n
"
,
jhi
)
if
jhi
==
0
{
debugfRSet
(
"
\t
non-overlap left
\n
"
)
return
}
// [ilo+1:jhi-1] should be deleted
// [ilo] and [jhi-1] overlap with [r.lo,r.hi) - they should be deleted, or shrinked,
// or split+shrinked if ilo==jhi-1 and r is inside [ilo]
if
jhi
-
ilo
==
1
&&
S
.
rangev
[
ilo
]
.
Lo
<
r
.
Lo
&&
r
.
Hi_
<
S
.
rangev
[
ilo
]
.
Hi_
{
x
:=
S
.
rangev
[
ilo
]
vInsert
(
&
S
.
rangev
,
ilo
,
x
)
jhi
++
debugfRSet
(
"
\t
presplit copy %s
\t
-> %s
\n
"
,
x
,
S
)
}
if
S
.
rangev
[
ilo
]
.
Lo
<
r
.
Lo
{
// shrink left
S
.
rangev
[
ilo
]
=
KeyRange
{
S
.
rangev
[
ilo
]
.
Lo
,
r
.
Lo
-
1
}
ilo
++
debugfRSet
(
"
\t
shrink [%d] left
\t
-> %s
\n
"
,
ilo
,
S
)
}
if
r
.
Hi_
<
S
.
rangev
[
jhi
-
1
]
.
Hi_
{
// shrink right
S
.
rangev
[
jhi
-
1
]
=
KeyRange
{
r
.
Hi_
+
1
,
S
.
rangev
[
jhi
-
1
]
.
Hi_
}
jhi
--
debugfRSet
(
"
\t
shrink [%d] right
\t
-> %s
\n
"
,
jhi
-
1
,
S
)
}
if
(
jhi
-
ilo
)
>
0
{
vDeleteSlice
(
&
S
.
rangev
,
ilo
,
jhi
)
debugfRSet
(
"
\t
delete S[%d:%d]
\t
-> %s
\n
"
,
ilo
,
jhi
,
S
)
}
// done
}
// HasRange returns whether all keys from range r belong to the set.
func
(
S
*
RangedKeySet
)
HasRange
(
r
KeyRange
)
(
yes
bool
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
HasRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
func
()
{
fmt
.
Printf
(
"->·: %v
\n
"
,
yes
)
}()
}
S
.
verify
()
// find first ilo: r.lo < [ilo].hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
]
.
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
// not found
return
false
}
// all keys from r are in S if r ∈ [ilo]
return
(
S
.
rangev
[
ilo
]
.
Lo
<=
r
.
Lo
&&
r
.
Hi_
<=
S
.
rangev
[
ilo
]
.
Hi_
)
}
// Union returns RangedKeySet(A.keys | B.keys).
...
...
@@ -290,137 +72,3 @@ func (A *RangedKeySet) DifferenceInplace(B *RangedKeySet) {
A
.
DelRange
(
r
)
}
}
// --------
// verify checks RangedKeySet for internal consistency:
// - ranges must be not overlapping nor adjacent and ↑
func
(
S
*
RangedKeySet
)
verify
()
{
// TODO !debug -> return
var
badv
[]
string
badf
:=
func
(
format
string
,
argv
...
interface
{})
{
badv
=
append
(
badv
,
fmt
.
Sprintf
(
format
,
argv
...
))
}
defer
func
()
{
if
badv
!=
nil
{
emsg
:=
"S.verify: fail:
\n\n
"
for
_
,
bad
:=
range
badv
{
emsg
+=
fmt
.
Sprintf
(
"- %s
\n
"
,
bad
)
}
emsg
+=
fmt
.
Sprintf
(
"
\n
S: %s
\n
"
,
S
)
panic
(
emsg
)
}
}()
hi_Prev
:=
KeyMin
for
i
,
r
:=
range
S
.
rangev
{
hiPrev
:=
hi_Prev
+
1
if
i
>
0
&&
!
(
hiPrev
<
r
.
Lo
)
{
// NOTE not ≤ - adjacent ranges must be merged
badf
(
"[%d]: !(hiPrev < r.lo)"
,
i
)
}
if
!
(
r
.
Lo
<=
r
.
Hi_
)
{
badf
(
"[%d]: !(r.lo <= r.hi_)"
,
i
)
}
hi_Prev
=
r
.
Hi_
}
}
// Clone returns copy of the set.
func
(
orig
*
RangedKeySet
)
Clone
()
*
RangedKeySet
{
klon
:=
&
RangedKeySet
{}
klon
.
rangev
=
append
(
klon
.
rangev
,
orig
.
rangev
...
)
return
klon
}
// Empty returns whether the set is empty.
func
(
S
*
RangedKeySet
)
Empty
()
bool
{
return
len
(
S
.
rangev
)
==
0
}
// Equal returns whether A == B.
func
(
A
*
RangedKeySet
)
Equal
(
B
*
RangedKeySet
)
bool
{
if
len
(
A
.
rangev
)
!=
len
(
B
.
rangev
)
{
return
false
}
for
i
,
ra
:=
range
A
.
rangev
{
rb
:=
B
.
rangev
[
i
]
if
ra
!=
rb
{
return
false
}
}
return
true
}
// Clear removes all elements from the set.
func
(
S
*
RangedKeySet
)
Clear
()
{
S
.
rangev
=
nil
}
// AllRanges returns slice of all key ranges in the set.
//
// TODO -> iter?
func
(
S
*
RangedKeySet
)
AllRanges
()
/*readonly*/
[]
KeyRange
{
return
S
.
rangev
}
// XXX -> ptr?
func
(
S
RangedKeySet
)
String
()
string
{
s
:=
"{"
for
i
,
r
:=
range
S
.
rangev
{
if
i
>
0
{
s
+=
" "
}
s
+=
r
.
String
()
}
s
+=
"}"
return
s
}
func
(
r
KeyRange
)
String
()
string
{
var
shi
string
if
r
.
Hi_
==
KeyMax
{
shi
=
KStr
(
r
.
Hi_
)
// ∞
}
else
{
shi
=
fmt
.
Sprintf
(
"%d"
,
r
.
Hi_
+
1
)
}
return
fmt
.
Sprintf
(
"[%s,%s)"
,
KStr
(
r
.
Lo
),
shi
)
}
func
debugfRSet
(
format
string
,
argv
...
interface
{})
{
if
!
debugRangeSet
{
return
}
fmt
.
Printf
(
format
,
argv
...
)
}
// ---- slice ops ----
// vInsert inserts r into *pv[i].
func
vInsert
(
pv
*
[]
KeyRange
,
i
int
,
r
KeyRange
)
{
v
:=
*
pv
v
=
append
(
v
,
KeyRange
{})
copy
(
v
[
i
+
1
:
],
v
[
i
:
])
v
[
i
]
=
r
*
pv
=
v
}
// vDeleteSlice deletes *pv[lo:hi].
func
vDeleteSlice
(
pv
*
[]
KeyRange
,
lo
,
hi
int
)
{
v
:=
*
pv
n
:=
copy
(
v
[
lo
:
],
v
[
hi
:
])
v
=
v
[
:
lo
+
n
]
*
pv
=
v
}
// vReplaceSlice replaces *pv[lo:hi] with r.
func
vReplaceSlice
(
pv
*
[]
KeyRange
,
lo
,
hi
int
,
r
KeyRange
)
{
v
:=
*
pv
n
:=
copy
(
v
[
lo
+
1
:
],
v
[
hi
:
])
v
[
lo
]
=
r
v
=
v
[
:
lo
+
1
+
n
]
*
pv
=
v
}
wcfs/internal/xbtree/blib/rangeset.go.orig
0 → 100644
View file @
db2d48ae
//
Copyright
(
C
)
2021
Nexedi
SA
and
Contributors
.
//
Kirill
Smelkov
<
kirr
@
nexedi
.
com
>
//
//
This
program
is
free
software
:
you
can
Use
,
Study
,
Modify
and
Redistribute
//
it
under
the
terms
of
the
GNU
General
Public
License
version
3
,
or
(
at
your
//
option
)
any
later
version
,
as
published
by
the
Free
Software
Foundation
.
//
//
You
can
also
Link
and
Combine
this
program
with
other
software
covered
by
//
the
terms
of
any
of
the
Free
Software
licenses
or
any
of
the
Open
Source
//
Initiative
approved
licenses
and
Convey
the
resulting
work
.
Corresponding
//
source
of
such
a
combination
shall
include
the
source
code
for
all
other
//
software
used
.
//
//
This
program
is
distributed
WITHOUT
ANY
WARRANTY
;
without
even
the
implied
//
warranty
of
MERCHANTABILITY
or
FITNESS
FOR
A
PARTICULAR
PURPOSE
.
//
//
See
COPYING
file
for
full
licensing
terms
.
//
See
https
://
www
.
nexedi
.
com
/
licensing
for
rationale
and
options
.
package
blib
//
set
of
[
lo
,
hi
)
Key
ranges
.
import
(
"fmt"
"sort"
)
const
traceRangeSet
=
false
const
debugRangeSet
=
false
//
KeyRange
represents
[
lo
,
hi
)
Key
range
.
type
KeyRange
struct
{
Lo
Key
Hi_
Key
//
NOTE
_not_
hi
)
to
avoid
overflow
at
∞
;
hi
=
hi_
+
1
}
//
RangedKeySet
is
set
of
Keys
with
adjacent
keys
coalesced
into
Ranges
.
//
//
Zero
value
represents
empty
set
.
type
RangedKeySet
struct
{
//
TODO
rework
to
use
BTree
lo
->
hi_
instead
if
in
practice
in
treediff
,
//
and
other
usage
places
,
N
(
ranges
)
turns
out
to
be
not
small
//
(
i
.
e
.
performance
turns
out
to
be
not
acceptable
)
rangev
[]
KeyRange
//
lo
↑
}
//
Has
returns
whether
key
k
belongs
to
the
range
.
func
(
r
*
KeyRange
)
Has
(
k
Key
)
bool
{
return
(
r
.
Lo
<=
k
&&
k
<=
r
.
Hi_
)
}
//
Add
adds
key
k
to
the
set
.
func
(
S
*
RangedKeySet
)
Add
(
k
Key
)
{
S
.
AddRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
//
Del
removes
key
k
from
the
set
.
func
(
S
*
RangedKeySet
)
Del
(
k
Key
)
{
S
.
DelRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
//
Has
returns
whether
key
k
belongs
to
the
set
.
func
(
S
*
RangedKeySet
)
Has
(
k
Key
)
bool
{
return
S
.
HasRange
(
KeyRange
{
Lo
:
k
,
Hi_
:
k
})
}
//
AddRange
adds
range
r
to
the
set
.
func
(
S
*
RangedKeySet
)
AddRange
(
r
KeyRange
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
AddRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
fmt
.
Printf
(
"->u: %s
\n
"
,
S
)
}
S
.
verify
()
defer
S
.
verify
()
//
find
first
ilo
:
r
.
Lo
<
[
ilo
].
hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
].
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
//
not
found
S
.
rangev
=
append
(
S
.
rangev
,
r
)
l
++
debugfRSet
(
"
\t
append %s
\t
-> %s
\n
"
,
r
,
S
)
}
//
find
last
jhi
:
[
jhi
].
Lo
<
r
.
hi
jhi
:=
ilo
for
;;
jhi
++
{
if
jhi
==
l
{
break
}
if
S
.
rangev
[
jhi
].
Lo
<=
r
.
Hi_
{
continue
}
break
}
debugfRSet
(
"
\t
jhi: %d
\n
"
,
jhi
)
//
entries
in
[
ilo
:
jhi
)
∈
[
r
.
Lo
,
r
.
hi
)
and
should
be
merged
into
one
if
(
jhi
-
ilo
)
>
1
{
lo
:=
S
.
rangev
[
ilo
].
Lo
hi_
:=
S
.
rangev
[
jhi
-
1
].
Hi_
vReplaceSlice
(&
S
.
rangev
,
ilo
,
jhi
,
KeyRange
{
lo
,
hi_
})
debugfRSet
(
"
\t
merge S[%d:%d]
\t
-> %s
\n
"
,
ilo
,
jhi
,
S
)
}
jhi
=
-
1
//
no
longer
valid
//
if
[
r
.
lo
,
r
.
hi
)
was
outside
of
any
entry
-
create
new
entry
if
r
.
Hi_
<
S
.
rangev
[
ilo
].
Lo
{
vInsert
(&
S
.
rangev
,
ilo
,
r
)
debugfRSet
(
"
\t
insert %s
\t
-> %s
\n
"
,
r
,
S
)
}
//
now
we
have
covered
entries
merged
as
needed
into
[
ilo
]
//
extend
this
entry
if
r
coverage
is
wider
if
r
.
Lo
<
S
.
rangev
[
ilo
].
Lo
{
S
.
rangev
[
ilo
].
Lo
=
r
.
Lo
debugfRSet
(
"
\t
extend left
\t
-> %s
\n
"
,
S
)
}
if
r
.
Hi_
>
S
.
rangev
[
ilo
].
Hi_
{
S
.
rangev
[
ilo
].
Hi_
=
r
.
Hi_
debugfRSet
(
"
\t
extend right
\t
-> %s
\n
"
,
S
)
}
//
and
check
if
we
should
merge
it
with
right
/
left
neighbours
if
ilo
+
1
<
len
(
S
.
rangev
)
{
//
right
if
S
.
rangev
[
ilo
].
Hi_
+
1
==
S
.
rangev
[
ilo
+
1
].
Lo
{
vReplaceSlice
(&
S
.
rangev
,
ilo
,
ilo
+
2
,
KeyRange
{
S
.
rangev
[
ilo
].
Lo
,
S
.
rangev
[
ilo
+
1
].
Hi_
})
debugfRSet
(
"
\t
merge right
\t
-> %s
\n
"
,
S
)
}
}
if
ilo
>
0
{
//
left
if
S
.
rangev
[
ilo
-
1
].
Hi_
+
1
==
S
.
rangev
[
ilo
].
Lo
{
vReplaceSlice
(&
S
.
rangev
,
ilo
-
1
,
ilo
+
1
,
KeyRange
{
S
.
rangev
[
ilo
-
1
].
Lo
,
S
.
rangev
[
ilo
].
Hi_
})
debugfRSet
(
"
\t
merge left
\t
-> %s
\n
"
,
S
)
}
}
//
done
}
//
DelRange
removes
range
r
from
the
set
.
func
(
S
*
RangedKeySet
)
DelRange
(
r
KeyRange
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
DelRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
fmt
.
Printf
(
"->d: %s
\n
"
,
S
)
}
S
.
verify
()
defer
S
.
verify
()
//
find
first
ilo
:
r
.
Lo
<
[
ilo
].
hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
].
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
//
not
found
debugfRSet
(
"
\t
non-overlap right
\n
"
)
return
}
//
find
last
jhi
:
[
jhi
].
Lo
<
r
.
hi
jhi
:=
ilo
for
;;
jhi
++
{
if
jhi
==
l
{
break
}
if
S
.
rangev
[
jhi
].
Lo
<=
r
.
Hi_
{
continue
}
break
}
debugfRSet
(
"
\t
jhi: %d
\n
"
,
jhi
)
if
jhi
==
0
{
debugfRSet
(
"
\t
non-overlap left
\n
"
)
return
}
//
[
ilo
+
1
:
jhi
-
1
]
should
be
deleted
//
[
ilo
]
and
[
jhi
-
1
]
overlap
with
[
r
.
lo
,
r
.
hi
)
-
they
should
be
deleted
,
or
shrinked
,
//
or
split
+
shrinked
if
ilo
==
jhi
-
1
and
r
is
inside
[
ilo
]
if
jhi
-
ilo
==
1
&&
S
.
rangev
[
ilo
].
Lo
<
r
.
Lo
&&
r
.
Hi_
<
S
.
rangev
[
ilo
].
Hi_
{
x
:=
S
.
rangev
[
ilo
]
vInsert
(&
S
.
rangev
,
ilo
,
x
)
jhi
++
debugfRSet
(
"
\t
presplit copy %s
\t
-> %s
\n
"
,
x
,
S
)
}
if
S
.
rangev
[
ilo
].
Lo
<
r
.
Lo
{
//
shrink
left
S
.
rangev
[
ilo
]
=
KeyRange
{
S
.
rangev
[
ilo
].
Lo
,
r
.
Lo
-
1
}
ilo
++
debugfRSet
(
"
\t
shrink [%d] left
\t
-> %s
\n
"
,
ilo
,
S
)
}
if
r
.
Hi_
<
S
.
rangev
[
jhi
-
1
].
Hi_
{
//
shrink
right
S
.
rangev
[
jhi
-
1
]
=
KeyRange
{
r
.
Hi_
+
1
,
S
.
rangev
[
jhi
-
1
].
Hi_
}
jhi
--
debugfRSet
(
"
\t
shrink [%d] right
\t
-> %s
\n
"
,
jhi
-
1
,
S
)
}
if
(
jhi
-
ilo
)
>
0
{
vDeleteSlice
(&
S
.
rangev
,
ilo
,
jhi
)
debugfRSet
(
"
\t
delete S[%d:%d]
\t
-> %s
\n
"
,
ilo
,
jhi
,
S
)
}
//
done
}
//
HasRange
returns
whether
all
keys
from
range
r
belong
to
the
set
.
func
(
S
*
RangedKeySet
)
HasRange
(
r
KeyRange
)
(
yes
bool
)
{
if
traceRangeSet
{
fmt
.
Printf
(
"
\n\n
HasRange:
\n
"
)
fmt
.
Printf
(
" S: %s
\n
"
,
S
)
fmt
.
Printf
(
" r: %s
\n
"
,
r
)
defer
func
()
{
fmt
.
Printf
(
"->·: %v
\n
"
,
yes
)
}()
}
S
.
verify
()
//
find
first
ilo
:
r
.
lo
<
[
ilo
].
hi
l
:=
len
(
S
.
rangev
)
ilo
:=
sort
.
Search
(
l
,
func
(
i
int
)
bool
{
return
r
.
Lo
<=
S
.
rangev
[
i
].
Hi_
})
debugfRSet
(
"
\t
ilo: %d
\n
"
,
ilo
)
if
ilo
==
l
{
//
not
found
return
false
}
//
all
keys
from
r
are
in
S
if
r
∈
[
ilo
]
return
(
S
.
rangev
[
ilo
].
Lo
<=
r
.
Lo
&&
r
.
Hi_
<=
S
.
rangev
[
ilo
].
Hi_
)
}
//
Union
returns
RangedKeySet
(
A
.
keys
|
B
.
keys
).
func
(
A
*
RangedKeySet
)
Union
(
B
*
RangedKeySet
)
*
RangedKeySet
{
U
:=
A
.
Clone
()
U
.
UnionInplace
(
B
)
return
U
}
//
Difference
returns
RangedKeySet
(
A
.
keys
\
B
.
keys
).
func
(
A
*
RangedKeySet
)
Difference
(
B
*
RangedKeySet
)
*
RangedKeySet
{
D
:=
A
.
Clone
()
D
.
DifferenceInplace
(
B
)
return
D
}
//
XXX
Intersection
func
(
A
*
RangedKeySet
)
UnionInplace
(
B
*
RangedKeySet
)
{
A
.
verify
()
B
.
verify
()
defer
A
.
verify
()
//
XXX
dumb
for
_
,
r
:=
range
B
.
rangev
{
A
.
AddRange
(
r
)
}
}
func
(
A
*
RangedKeySet
)
DifferenceInplace
(
B
*
RangedKeySet
)
{
A
.
verify
()
B
.
verify
()
defer
A
.
verify
()
//
XXX
dumb
for
_
,
r
:=
range
B
.
rangev
{
if
len
(
A
.
rangev
)
==
0
{
break
}
A
.
DelRange
(
r
)
}
}
//
--------
//
verify
checks
RangedKeySet
for
internal
consistency
:
//
-
ranges
must
be
not
overlapping
nor
adjacent
and
↑
func
(
S
*
RangedKeySet
)
verify
()
{
//
TODO
!debug -> return
var
badv
[]
string
badf
:=
func
(
format
string
,
argv
...
interface
{})
{
badv
=
append
(
badv
,
fmt
.
Sprintf
(
format
,
argv
...))
}
defer
func
()
{
if
badv
!= nil {
emsg
:=
"S.verify: fail:
\n\n
"
for
_
,
bad
:=
range
badv
{
emsg
+=
fmt
.
Sprintf
(
"- %s
\n
"
,
bad
)
}
emsg
+=
fmt
.
Sprintf
(
"
\n
S: %s
\n
"
,
S
)
panic
(
emsg
)
}
}()
hi_Prev
:=
KeyMin
for
i
,
r
:=
range
S
.
rangev
{
hiPrev
:=
hi_Prev
+
1
if
i
>
0
&&
!(hiPrev < r.Lo) { // NOTE not ≤ - adjacent ranges must be merged
badf
(
"[%d]: !(hiPrev < r.lo)"
,
i
)
}
if
!(r.Lo <= r.Hi_) {
badf
(
"[%d]: !(r.lo <= r.hi_)"
,
i
)
}
hi_Prev
=
r
.
Hi_
}
}
//
Clone
returns
copy
of
the
set
.
func
(
orig
*
RangedKeySet
)
Clone
()
*
RangedKeySet
{
klon
:=
&
RangedKeySet
{}
klon
.
rangev
=
append
(
klon
.
rangev
,
orig
.
rangev
...)
return
klon
}
//
Empty
returns
whether
the
set
is
empty
.
func
(
S
*
RangedKeySet
)
Empty
()
bool
{
return
len
(
S
.
rangev
)
==
0
}
//
Equal
returns
whether
A
==
B
.
func
(
A
*
RangedKeySet
)
Equal
(
B
*
RangedKeySet
)
bool
{
if
len
(
A
.
rangev
)
!= len(B.rangev) {
return
false
}
for
i
,
ra
:=
range
A
.
rangev
{
rb
:=
B
.
rangev
[
i
]
if
ra
!= rb {
return
false
}
}
return
true
}
//
Clear
removes
all
elements
from
the
set
.
func
(
S
*
RangedKeySet
)
Clear
()
{
S
.
rangev
=
nil
}
//
AllRanges
returns
slice
of
all
key
ranges
in
the
set
.
//
//
TODO
->
iter
?
func
(
S
*
RangedKeySet
)
AllRanges
()
/*
readonly
*/[]
KeyRange
{
return
S
.
rangev
}
//
XXX
->
ptr
?
func
(
S
RangedKeySet
)
String
()
string
{
s
:=
"{"
for
i
,
r
:=
range
S
.
rangev
{
if
i
>
0
{
s
+=
" "
}
s
+=
r
.
String
()
}
s
+=
"}"
return
s
}
func
(
r
KeyRange
)
String
()
string
{
var
shi
string
if
r
.
Hi_
==
KeyMax
{
shi
=
KStr
(
r
.
Hi_
)
//
∞
}
else
{
shi
=
fmt
.
Sprintf
(
"%d"
,
r
.
Hi_
+
1
)
}
return
fmt
.
Sprintf
(
"[%s,%s)"
,
KStr
(
r
.
Lo
),
shi
)
}
func
debugfRSet
(
format
string
,
argv
...
interface
{})
{
if
!debugRangeSet {
return
}
fmt
.
Printf
(
format
,
argv
...)
}
//
----
slice
ops
----
//
vInsert
inserts
r
into
*
pv
[
i
].
func
vInsert
(
pv
*[]
KeyRange
,
i
int
,
r
KeyRange
)
{
v
:=
*
pv
v
=
append
(
v
,
KeyRange
{})
copy
(
v
[
i
+
1
:],
v
[
i
:])
v
[
i
]
=
r
*
pv
=
v
}
//
vDeleteSlice
deletes
*
pv
[
lo
:
hi
].
func
vDeleteSlice
(
pv
*[]
KeyRange
,
lo
,
hi
int
)
{
v
:=
*
pv
n
:=
copy
(
v
[
lo
:],
v
[
hi
:])
v
=
v
[:
lo
+
n
]
*
pv
=
v
}
//
vReplaceSlice
replaces
*
pv
[
lo
:
hi
]
with
r
.
func
vReplaceSlice
(
pv
*[]
KeyRange
,
lo
,
hi
int
,
r
KeyRange
)
{
v
:=
*
pv
n
:=
copy
(
v
[
lo
+
1
:],
v
[
hi
:])
v
[
lo
]
=
r
v
=
v
[:
lo
+
1
+
n
]
*
pv
=
v
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment