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
d268cd3b
Commit
d268cd3b
authored
Jul 21, 2009
by
Joey Adams
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
stringmap: Flipped bit order to match sorted string order and added traversal test
parent
f26355f2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
138 additions
and
31 deletions
+138
-31
ccan/stringmap/stringmap.c
ccan/stringmap/stringmap.c
+3
-3
ccan/stringmap/test/run.c
ccan/stringmap/test/run.c
+135
-28
No files found.
ccan/stringmap/stringmap.c
View file @
d268cd3b
...
...
@@ -39,7 +39,7 @@
#define assert(...) do {} while(0)
#endif
#define PEEK_BIT(key, bit) ((key[bit >> 3] >> (bit & 7)) & 1)
#define PEEK_BIT(key, bit) ((key[bit >> 3] >> (
~
bit & 7)) & 1)
struct
stringmap_node
{
uint32_t
left_is_leaf
:
1
,
right_is_leaf
:
1
,
bitno
:
30
;
...
...
@@ -155,8 +155,8 @@ void *stringmap_lookup_real(struct stringmap *t, const char *key, size_t len, in
//advance cix to the first differing bit
ix
=
*
m
^
*
k
;
while
((
ix
&
1
)
==
0
)
ix
>>
=
1
,
cix
++
;
while
((
ix
&
1
28
)
==
0
)
ix
<<
=
1
,
cix
++
;
//choose left/right based on the differing bit
bit
=
PEEK_BIT
(
key
,
cix
);
...
...
ccan/stringmap/test/run.c
View file @
d268cd3b
...
...
@@ -88,13 +88,21 @@ struct test_entry {
this key has been entered already. */
};
static
int
tecmp
(
const
struct
test_entry
*
a
,
const
struct
test_entry
*
b
)
{
if
(
a
->
len
<
b
->
len
)
return
-
1
;
else
if
(
a
->
len
>
b
->
len
)
return
1
;
else
return
memcmp
(
a
->
str
,
b
->
str
,
a
->
len
);
static
int
tecmp
(
const
struct
test_entry
*
ap
,
const
struct
test_entry
*
bp
)
{
const
unsigned
char
*
a
=
(
unsigned
char
*
)
ap
->
str
,
*
ae
=
a
+
ap
->
len
;
const
unsigned
char
*
b
=
(
unsigned
char
*
)
bp
->
str
,
*
be
=
b
+
bp
->
len
;
for
(;;
a
++
,
b
++
)
{
if
(
a
>=
ae
)
{
if
(
b
>=
be
)
return
0
;
//strings are the same
return
-
1
;
//a is shorter than b
}
if
(
b
>=
be
)
return
1
;
//b is shorter than a
if
(
*
a
!=
*
b
)
//there is a differing character
return
(
unsigned
int
)
*
a
-
(
unsigned
int
)
*
b
;
}
}
static
int
by_str
(
const
void
*
a
,
const
void
*
b
)
{
...
...
@@ -126,26 +134,116 @@ static void cull_duplicates(struct test_entry *entries, size_t *count) {
*
count
=
o
-
entries
;
}
#define print(tag, fmt, ...) do { \
if (out) \
fprintf(out, tag fmt "\n", ##__VA_ARGS__); \
} while(0)
#define err(...) do { \
print("error: ", __VA_ARGS__); \
goto fail; \
} while(0)
//#define debug(...) print("debug: ", __VA_ARGS__)
#define debug(...) do {} while(0)
#define msg(...) print("info: ", __VA_ARGS__)
static
int
test_traverse
(
struct
stringmap
*
map
,
struct
test_entry
*
strings
,
size_t
size
,
FILE
*
out
)
{
size_t
sp
=
0
;
size_t
stack_alloc
=
16
;
struct
stringmap_node
**
stack
=
NULL
;
struct
stringmap_node
*
n
;
void
*
leaf
;
#define check(lri) do { \
leaf = n->lr[lri]; \
if (!size--) \
err("Fewer items in tree than counted"); \
if (tecmp(leaf, strings++)) \
err("%s leaf has incorrect string", lri ? "Left" : "Right"); \
} while(0)
#define check_left() check(0)
#define check_right() check(1)
if
(
map
->
count
!=
size
)
err
(
"map->count != size"
);
if
(
map
->
count
==
0
)
return
1
;
if
(
map
->
count
==
1
)
{
leaf
=
(
struct
test_entry
*
)
map
->
root
;
if
(
!
tecmp
(
leaf
,
&
strings
[
0
]))
return
1
;
else
err
(
"Only leaf in tree has incorrect value"
);
}
stack
=
malloc
(
sizeof
(
*
stack
)
*
stack_alloc
);
n
=
map
->
root
;
for
(;;)
{
//descend left
while
(
!
n
->
left_is_leaf
)
{
stack
[
sp
++
]
=
n
;
n
=
n
->
lr
[
0
];
if
(
sp
>=
stack_alloc
)
{
stack_alloc
+=
stack_alloc
;
stack
=
realloc
(
stack
,
sizeof
(
*
stack
)
*
stack_alloc
);
}
}
check_left
();
ascend_right:
while
(
n
->
right_is_leaf
)
{
check_right
();
if
(
!
sp
)
goto
done
;
//we finished up the last entry
n
=
stack
[
--
sp
];
}
//descend right
n
=
n
->
lr
[
1
];
while
(
n
->
left_is_leaf
)
{
check_left
();
if
(
n
->
right_is_leaf
)
{
check_right
();
if
(
!
sp
)
goto
done
;
n
=
stack
[
--
sp
];
goto
ascend_right
;
//sorry
}
n
=
n
->
lr
[
1
];
}
}
done:
if
(
size
!=
0
)
err
(
"More items in tree than counted"
);
free
(
stack
);
return
1
;
fail:
if
(
stack
)
free
(
stack
);
return
0
;
#undef check
#undef check_left
#undef check_right
}
static
int
test_stringmap
(
size_t
count
,
FILE
*
out
)
{
stringmap
(
char
*
)
map
=
stringmap_new
(
NULL
);
#define print(tag, fmt, ...) do { \
if (out) \
fprintf(out, tag fmt "\n", ##__VA_ARGS__); \
} while(0)
#define err(...) do { \
print("error: ", __VA_ARGS__); \
goto fail; \
} while(0)
//#define debug(...) print("debug: ", __VA_ARGS__)
#define debug(...) do {} while(0)
#define msg(...) print("info: ", __VA_ARGS__)
struct
block_pool
*
bp
=
block_pool_new
(
NULL
);
struct
test_entry
*
entries
=
block_pool_alloc
(
bp
,
sizeof
(
*
entries
)
*
count
);
struct
test_entry
*
i
,
*
e
=
entries
+
count
;
struct
test_entry
*
i
,
*
e
=
entries
+
count
,
*
o
;
char
*
value_base
=
block_pool_alloc
(
bp
,
count
),
*
value
=
value_base
;
size_t
unique_count
=
0
;
size_t
unique_count
;
//we use value to track whether an entry has been added or not
memset
(
value
,
0
,
count
);
...
...
@@ -170,7 +268,7 @@ static int test_stringmap(size_t count, FILE *out) {
msg
(
"Inserting/looking up %zu entries..."
,
count
);
for
(
i
=
entries
;
i
<
e
;
i
++
)
{
for
(
i
=
entries
,
o
=
entries
;
i
<
e
;
i
++
)
{
char
**
node
;
debug
(
"Looking up %s"
,
i
->
str
);
...
...
@@ -191,7 +289,8 @@ static int test_stringmap(size_t count, FILE *out) {
*
node
=
i
->
value
;
*
i
->
value
=
1
;
//mark that the entry is entered
unique_count
++
;
//write this unique entry to the entry list to traverse later
*
o
++
=
*
i
;
}
else
{
if
(
tecmp
(
i
,
(
void
*
)
map
.
last
))
err
(
"lookup returned incorrect string"
);
...
...
@@ -204,9 +303,17 @@ static int test_stringmap(size_t count, FILE *out) {
}
}
unique_count
=
o
-
entries
;
if
(
map
.
t
.
count
!=
unique_count
)
err
(
"Map has incorrect count"
);
qsort
(
entries
,
unique_count
,
sizeof
(
*
entries
),
by_str
);
msg
(
"Traversing forward through %zu items"
,
unique_count
);
if
(
!
test_traverse
(
&
map
.
t
,
entries
,
unique_count
,
out
))
err
(
"Traversal does not produce the strings in order"
);
printf
(
"stringmap test passed after %zu inserts, %zu lookups (%zu total operations)
\n
"
,
unique_count
,
(
i
-
entries
)
-
unique_count
,
i
-
entries
);
...
...
@@ -221,13 +328,13 @@ fail:
block_pool_free
(
bp
);
stringmap_free
(
map
);
return
0
;
#undef print
#undef err
#undef debug
#undef msg
}
#undef print
#undef err
#undef debug
#undef msg
int
main
(
void
)
{
plan_tests
(
14
);
...
...
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