Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
4a330282
Commit
4a330282
authored
Jun 10, 2018
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add IntertionOrderIndex.
parent
b0868e34
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
281 additions
and
0 deletions
+281
-0
table-test.c++
c++/src/kj/table-test.c++
+104
-0
table.c++
c++/src/kj/table.c++
+86
-0
table.h
c++/src/kj/table.h
+91
-0
No files found.
c++/src/kj/table-test.c++
View file @
4a330282
...
...
@@ -893,5 +893,109 @@ KJ_TEST("benchmark: std::set<StringPtr>") {
}
}
// =======================================================================================
KJ_TEST
(
"insertion order index"
)
{
Table
<
uint
,
InsertionOrderIndex
>
table
;
{
auto
range
=
table
.
ordered
();
KJ_EXPECT
(
range
.
begin
()
==
range
.
end
());
}
table
.
insert
(
12
);
table
.
insert
(
34
);
table
.
insert
(
56
);
table
.
insert
(
78
);
{
auto
range
=
table
.
ordered
();
auto
iter
=
range
.
begin
();
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
12
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
34
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
56
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
78
);
KJ_EXPECT
(
iter
==
range
.
end
());
KJ_EXPECT
(
*--
iter
==
78
);
KJ_EXPECT
(
*--
iter
==
56
);
KJ_EXPECT
(
*--
iter
==
34
);
KJ_EXPECT
(
*--
iter
==
12
);
KJ_EXPECT
(
iter
==
range
.
begin
());
}
table
.
erase
(
table
.
begin
()[
1
]);
{
auto
range
=
table
.
ordered
();
auto
iter
=
range
.
begin
();
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
12
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
56
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
78
);
KJ_EXPECT
(
iter
==
range
.
end
());
KJ_EXPECT
(
*--
iter
==
78
);
KJ_EXPECT
(
*--
iter
==
56
);
KJ_EXPECT
(
*--
iter
==
12
);
KJ_EXPECT
(
iter
==
range
.
begin
());
}
// Allocate enough more elements to cause a resize.
table
.
insert
(
111
);
table
.
insert
(
222
);
table
.
insert
(
333
);
table
.
insert
(
444
);
table
.
insert
(
555
);
table
.
insert
(
666
);
table
.
insert
(
777
);
table
.
insert
(
888
);
table
.
insert
(
999
);
{
auto
range
=
table
.
ordered
();
auto
iter
=
range
.
begin
();
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
12
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
56
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
78
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
111
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
222
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
333
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
444
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
555
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
666
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
777
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
888
);
KJ_ASSERT
(
iter
!=
range
.
end
());
KJ_EXPECT
(
*
iter
++
==
999
);
KJ_EXPECT
(
iter
==
range
.
end
());
}
// Remove everything.
while
(
table
.
size
()
>
0
)
{
table
.
erase
(
*
table
.
begin
());
}
{
auto
range
=
table
.
ordered
();
KJ_EXPECT
(
range
.
begin
()
==
range
.
end
());
}
}
}
// namespace kj
}
// namespace _
c++/src/kj/table.c++
View file @
4a330282
...
...
@@ -721,4 +721,90 @@ void BTreeImpl::Parent::eraseAfter(uint i) {
}
}
// namespace _
// =======================================================================================
// Insertion order
const
InsertionOrderIndex
::
Link
InsertionOrderIndex
::
EMPTY_LINK
=
{
0
,
0
};
InsertionOrderIndex
::
InsertionOrderIndex
()
:
capacity
(
0
),
links
(
const_cast
<
Link
*>
(
&
EMPTY_LINK
))
{}
InsertionOrderIndex
::~
InsertionOrderIndex
()
noexcept
(
false
)
{
if
(
links
!=
&
EMPTY_LINK
)
delete
links
;
}
void
InsertionOrderIndex
::
reserve
(
size_t
size
)
{
KJ_ASSERT
(
size
<
(
1u
<<
31
),
"Table too big for InsertionOrderIndex"
);
if
(
size
>
capacity
)
{
// Need to grow.
// Note that `size` and `capacity` do not include the special link[0].
// Round up to the next power of 2.
size_t
allocation
=
1u
<<
(
_
::
lg
(
size
)
+
1
);
KJ_DASSERT
(
allocation
>
size
);
KJ_DASSERT
(
allocation
<=
size
*
2
);
// Round first allocation up to 8.
allocation
=
kj
::
max
(
allocation
,
8
);
Link
*
newLinks
=
new
Link
[
allocation
];
#ifdef KJ_DEBUG
// To catch bugs, fill unused links with 0xff.
memset
(
newLinks
,
0xff
,
allocation
*
sizeof
(
Link
));
#endif
_
::
acopy
(
newLinks
,
links
,
capacity
+
1
);
if
(
links
!=
&
EMPTY_LINK
)
delete
[]
links
;
links
=
newLinks
;
capacity
=
allocation
-
1
;
}
}
void
InsertionOrderIndex
::
clear
()
{
links
[
0
]
=
Link
{
0
,
0
};
#ifdef KJ_DEBUG
// To catch bugs, fill unused links with 0xff.
memset
(
links
+
1
,
0xff
,
capacity
*
sizeof
(
Link
));
#endif
}
kj
::
Maybe
<
size_t
>
InsertionOrderIndex
::
insertImpl
(
size_t
pos
)
{
if
(
pos
>=
capacity
)
{
reserve
(
pos
+
1
);
}
links
[
pos
+
1
].
prev
=
links
[
0
].
prev
;
links
[
pos
+
1
].
next
=
0
;
links
[
links
[
0
].
prev
].
next
=
pos
+
1
;
links
[
0
].
prev
=
pos
+
1
;
return
nullptr
;
}
void
InsertionOrderIndex
::
eraseImpl
(
size_t
pos
)
{
Link
&
link
=
links
[
pos
+
1
];
links
[
link
.
next
].
prev
=
link
.
prev
;
links
[
link
.
prev
].
next
=
link
.
next
;
#ifdef KJ_DEBUG
memset
(
&
link
,
0xff
,
sizeof
(
Link
));
#endif
}
void
InsertionOrderIndex
::
moveImpl
(
size_t
oldPos
,
size_t
newPos
)
{
Link
&
link
=
links
[
oldPos
+
1
];
Link
&
newLink
=
links
[
newPos
+
1
];
newLink
=
link
;
KJ_DASSERT
(
links
[
link
.
next
].
prev
==
oldPos
+
1
);
KJ_DASSERT
(
links
[
link
.
prev
].
next
==
oldPos
+
1
);
links
[
link
.
next
].
prev
=
newPos
+
1
;
links
[
link
.
prev
].
next
=
newPos
+
1
;
#ifdef KJ_DEBUG
memset
(
&
link
,
0xff
,
sizeof
(
Link
));
#endif
}
}
// namespace kj
c++/src/kj/table.h
View file @
4a330282
...
...
@@ -1388,4 +1388,95 @@ private:
}
};
// -----------------------------------------------------------------------------
// Insertion order index
class
InsertionOrderIndex
{
// Table index which allows iterating over elements in order of insertion. This index cannot
// be used for Table::find(), but can be used for Table::ordered().
struct
Link
;
public
:
InsertionOrderIndex
();
~
InsertionOrderIndex
()
noexcept
(
false
);
class
Iterator
{
public
:
Iterator
(
const
Link
*
links
,
uint
pos
)
:
links
(
links
),
pos
(
pos
)
{}
inline
size_t
operator
*
()
const
{
KJ_IREQUIRE
(
pos
!=
0
,
"can't derefrence end() iterator"
);
return
pos
-
1
;
};
inline
Iterator
&
operator
++
()
{
pos
=
links
[
pos
].
next
;
return
*
this
;
}
inline
Iterator
operator
++
(
int
)
{
Iterator
result
=
*
this
;
++*
this
;
return
result
;
}
inline
Iterator
&
operator
--
()
{
pos
=
links
[
pos
].
prev
;
return
*
this
;
}
inline
Iterator
operator
--
(
int
)
{
Iterator
result
=
*
this
;
--*
this
;
return
result
;
}
inline
bool
operator
==
(
const
Iterator
&
other
)
const
{
return
pos
==
other
.
pos
;
}
inline
bool
operator
!=
(
const
Iterator
&
other
)
const
{
return
pos
!=
other
.
pos
;
}
private
:
const
Link
*
links
;
uint
pos
;
};
void
reserve
(
size_t
size
);
void
clear
();
inline
Iterator
begin
()
const
{
return
Iterator
(
links
,
links
[
0
].
next
);
}
inline
Iterator
end
()
const
{
return
Iterator
(
links
,
0
);
}
template
<
typename
Row
>
kj
::
Maybe
<
size_t
>
insert
(
kj
::
ArrayPtr
<
Row
>
table
,
size_t
pos
)
{
return
insertImpl
(
pos
);
}
template
<
typename
Row
>
void
erase
(
kj
::
ArrayPtr
<
Row
>
table
,
size_t
pos
)
{
eraseImpl
(
pos
);
}
template
<
typename
Row
>
void
move
(
kj
::
ArrayPtr
<
Row
>
table
,
size_t
oldPos
,
size_t
newPos
)
{
return
moveImpl
(
oldPos
,
newPos
);
}
private
:
struct
Link
{
uint
next
;
uint
prev
;
};
uint
capacity
;
Link
*
links
;
// links[0] is special: links[0].next points to the first link, links[0].prev points to the last.
// links[n+1] corresponds no row n.
kj
::
Maybe
<
size_t
>
insertImpl
(
size_t
pos
);
void
eraseImpl
(
size_t
pos
);
void
moveImpl
(
size_t
oldPos
,
size_t
newPos
);
static
const
Link
EMPTY_LINK
;
};
}
// namespace kj
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