Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
ccan
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mirror
ccan
Commits
7aac849a
Commit
7aac849a
authored
Oct 10, 2019
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
intmap: implement intmap_before()
Signed-off-by:
Rusty Russell
<
rusty@rustcorp.com.au
>
parent
f7ead5da
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
139 additions
and
1 deletion
+139
-1
ccan/intmap/intmap.c
ccan/intmap/intmap.c
+57
-0
ccan/intmap/intmap.h
ccan/intmap/intmap.h
+35
-0
ccan/intmap/test/run-order-smallsize.c
ccan/intmap/test/run-order-smallsize.c
+22
-1
ccan/intmap/test/run-order.c
ccan/intmap/test/run-order.c
+25
-0
No files found.
ccan/intmap/intmap.c
View file @
7aac849a
...
...
@@ -231,6 +231,63 @@ none_left:
return
NULL
;
}
void
*
intmap_before_
(
const
struct
intmap
*
map
,
intmap_index_t
*
indexp
)
{
const
struct
intmap
*
n
,
*
prev
=
NULL
;
intmap_index_t
index
=
(
*
indexp
)
-
1
;
/* Special case of overflow */
if
(
index
==
(
intmap_index_t
)
-
1ULL
)
goto
none_left
;
/* Special case of empty map */
if
(
intmap_empty_
(
map
))
goto
none_left
;
/* Follow down, until prefix differs. */
n
=
map
;
while
(
!
n
->
v
)
{
int
crit
=
critbit
(
n
);
u8
direction
;
intmap_index_t
prefix
,
idx
;
idx
=
(
index
>>
crit
);
direction
=
idx
&
1
;
/* Leave critbit in place: we can't shift by 64 anyway */
idx
|=
1
;
prefix
=
n
->
u
.
n
->
prefix_and_critbit
>>
crit
;
/* If this entire tree is less than index, take last */
if
(
idx
>
prefix
)
return
intmap_last_
(
n
,
indexp
);
/* If this entire tree is greater than index, we're past it. */
else
if
(
idx
<
prefix
)
goto
try_lesser_tree
;
/* Remember lesser tree for backtracking */
if
(
direction
)
prev
=
n
;
n
=
&
n
->
u
.
n
->
child
[
direction
];
}
/* Found a predecessor? */
if
(
n
->
u
.
i
<=
index
)
{
errno
=
0
;
*
indexp
=
n
->
u
.
i
;
return
n
->
v
;
}
try_lesser_tree:
/* If we ever took a lesser branch, go back to lesser branch */
if
(
prev
)
return
intmap_last_
(
&
prev
->
u
.
n
->
child
[
0
],
indexp
);
none_left:
errno
=
ENOENT
;
return
NULL
;
}
void
*
intmap_last_
(
const
struct
intmap
*
map
,
intmap_index_t
*
indexp
)
{
const
struct
intmap
*
n
;
...
...
ccan/intmap/intmap.h
View file @
7aac849a
...
...
@@ -309,6 +309,32 @@ void *intmap_after_(const struct intmap *map, intmap_index_t *indexp);
tcon_cast((smap), sintmap_canary, \
sintmap_after_(sintmap_unwrap_(smap), (indexp)))
/**
* uintmap_before - get the closest preceding index in an unsigned intmap
* @umap: the typed intmap to iterate through.
* @indexp: the succeeding index (may not exist)
*
* Returns NULL if the there is no entry < @indexp, otherwise
* populates *@indexp and returns the highest entry < @indexp.
*/
#define uintmap_before(umap, indexp) \
tcon_cast((umap), uintmap_canary, \
intmap_before_(uintmap_unwrap_(umap), (indexp)))
void
*
intmap_before_
(
const
struct
intmap
*
map
,
intmap_index_t
*
indexp
);
/**
* sintmap_before - get the closest preceding index in a signed intmap
* @smap: the typed intmap to iterate through.
* @indexp: the succeeding index (may not exist)
*
* Returns NULL if the there is no entry < @indexp, otherwise
* populates *@indexp and returns the highest entry < @indexp.
*/
#define sintmap_before(smap, indexp) \
tcon_cast((smap), sintmap_canary, \
sintmap_before_(sintmap_unwrap_(smap), (indexp)))
/**
* uintmap_last - get last value in an unsigned intmap
* @umap: the typed intmap to iterate through.
...
...
@@ -455,6 +481,15 @@ static inline void *sintmap_after_(const struct intmap *map,
return
ret
;
}
static
inline
void
*
sintmap_before_
(
const
struct
intmap
*
map
,
sintmap_index_t
*
indexp
)
{
intmap_index_t
i
=
SINTMAP_OFF
(
*
indexp
);
void
*
ret
=
intmap_before_
(
map
,
&
i
);
*
indexp
=
SINTMAP_UNOFF
(
i
);
return
ret
;
}
static
inline
void
*
sintmap_last_
(
const
struct
intmap
*
map
,
sintmap_index_t
*
indexp
)
{
...
...
ccan/intmap/test/run-order-smallsize.c
View file @
7aac849a
...
...
@@ -19,6 +19,15 @@ static bool check_umap(const umap *map)
bool
last
=
true
;
/* Must be in order, must contain value. */
prev
=
256
;
for
(
v
=
uintmap_last
(
map
,
&
i
);
v
;
v
=
uintmap_before
(
map
,
&
i
))
{
if
(
i
>=
prev
)
return
false
;
if
(
*
v
!=
i
)
return
false
;
prev
=
i
;
}
prev
=
-
1
;
for
(
v
=
uintmap_first
(
map
,
&
i
);
v
;
v
=
uintmap_after
(
map
,
&
i
))
{
if
(
i
<=
prev
)
...
...
@@ -40,6 +49,15 @@ static bool check_smap(const smap *map)
bool
last
=
true
;
/* Must be in order, must contain value. */
prev
=
0x80000000ULL
;
for
(
v
=
sintmap_last
(
map
,
&
i
);
v
;
v
=
sintmap_before
(
map
,
&
i
))
{
if
(
i
>=
prev
)
return
false
;
if
(
*
v
!=
i
)
return
false
;
prev
=
i
;
}
prev
=
-
0x80000001ULL
;
for
(
v
=
sintmap_first
(
map
,
&
i
);
v
;
v
=
sintmap_after
(
map
,
&
i
))
{
if
(
i
<=
prev
)
...
...
@@ -52,7 +70,7 @@ static bool check_smap(const smap *map)
return
last
;
}
int
main
(
void
)
int
main
(
int
argc
,
char
*
argv
[]
)
{
umap
umap
;
smap
smap
;
...
...
@@ -64,6 +82,9 @@ int main(void)
uintmap_init
(
&
umap
);
sintmap_init
(
&
smap
);
if
(
argc
>
1
)
srandom
(
atoi
(
argv
[
1
]));
for
(
i
=
0
;
i
<
NUM
;
i
++
)
{
urandoms
[
i
]
=
random
();
srandoms
[
i
]
=
random
();
...
...
ccan/intmap/test/run-order.c
View file @
7aac849a
...
...
@@ -36,6 +36,19 @@ static bool check_umap(const umap *map)
last
=
(
uintmap_last
(
map
,
&
last_idx
)
==
v
);
}
if
(
!
last
)
return
false
;
prev
=
INT_MAX
;
for
(
v
=
uintmap_last
(
map
,
&
i
);
v
;
v
=
uintmap_before
(
map
,
&
i
))
{
if
((
int64_t
)
i
>=
prev
)
return
false
;
if
(
*
v
!=
i
)
return
false
;
prev
=
i
;
last
=
(
uintmap_first
(
map
,
&
last_idx
)
==
v
);
}
if
(
!
last
)
return
false
;
...
...
@@ -71,6 +84,18 @@ static bool check_smap(const smap *map)
prev
=
i
;
}
if
(
!
last
)
return
false
;
prev
=
0x80000001ULL
;
for
(
v
=
sintmap_last
(
map
,
&
i
);
v
;
v
=
sintmap_before
(
map
,
&
i
))
{
if
(
i
>=
prev
)
return
false
;
if
(
*
v
!=
i
)
return
false
;
prev
=
i
;
last
=
(
sintmap_first
(
map
,
&
last_idx
)
==
v
);
}
if
(
!
last
)
return
false
;
...
...
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