Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
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
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
10442d50
Unverified
Commit
10442d50
authored
Aug 01, 2022
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
structured binding, start
parent
573a695c
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
575 additions
and
290 deletions
+575
-290
include/cif++/Cif++.hpp
+36
-38
include/cif++/v2/category.hpp
+99
-82
include/cif++/v2/item.hpp
+34
-146
include/cif++/v2/iterator.hpp
+283
-20
include/cif++/v2/row.hpp
+95
-3
test/unit-v2-test.cpp
+28
-1
No files found.
include/cif++/Cif++.hpp
View file @
10442d50
...
@@ -1368,7 +1368,7 @@ namespace literals
...
@@ -1368,7 +1368,7 @@ namespace literals
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// iterators
// iterators
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
class
iterator_impl
class
iterator_impl
{
{
public
:
public
:
...
@@ -1377,7 +1377,7 @@ class iterator_impl
...
@@ -1377,7 +1377,7 @@ class iterator_impl
static
constexpr
size_t
N
=
sizeof
...(
Ts
);
static
constexpr
size_t
N
=
sizeof
...(
Ts
);
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
Category
Type
>
,
const
Row
,
Row
>
;
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
Category
>
,
const
Row
,
Row
>
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
value_type
=
std
::
conditional_t
<
N
==
0
,
row_type
,
std
::
tuple
<
Ts
...
>>
;
using
value_type
=
std
::
conditional_t
<
N
==
0
,
row_type
,
std
::
tuple
<
Ts
...
>>
;
...
@@ -1385,8 +1385,6 @@ class iterator_impl
...
@@ -1385,8 +1385,6 @@ class iterator_impl
using
pointer
=
value_type
*
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
using
reference
=
value_type
&
;
friend
class
Category
;
// default constructor, equal to end()
// default constructor, equal to end()
iterator_impl
()
{}
iterator_impl
()
{}
...
@@ -1510,19 +1508,19 @@ class iterator_impl
...
@@ -1510,19 +1508,19 @@ class iterator_impl
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// iterator proxy
// iterator proxy
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
class
iterator_proxy
class
iterator_proxy
{
{
public
:
public
:
static
constexpr
const
size_t
N
=
sizeof
...(
Ts
);
static
constexpr
const
size_t
N
=
sizeof
...(
Ts
);
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
Category
Type
>
,
const
Row
,
Row
>
;
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
Category
>
,
const
Row
,
Row
>
;
using
iterator
=
iterator_impl
<
row_type
,
Ts
...
>
;
using
iterator
=
iterator_impl
<
row_type
,
Ts
...
>
;
using
row_iterator
=
iterator_impl
<
row_type
>
;
using
row_iterator
=
iterator_impl
<
row_type
>
;
iterator_proxy
(
Category
Type
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
]);
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
]);
iterator_proxy
(
Category
Type
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
);
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
);
iterator_proxy
(
iterator_proxy
&&
p
);
iterator_proxy
(
iterator_proxy
&&
p
);
iterator_proxy
&
operator
=
(
iterator_proxy
&&
p
);
iterator_proxy
&
operator
=
(
iterator_proxy
&&
p
);
...
@@ -1542,7 +1540,7 @@ class iterator_proxy
...
@@ -1542,7 +1540,7 @@ class iterator_proxy
row_type
front
()
{
return
*
begin
();
}
row_type
front
()
{
return
*
begin
();
}
row_type
back
()
{
return
*
(
std
::
prev
(
end
()));
}
row_type
back
()
{
return
*
(
std
::
prev
(
end
()));
}
Category
Type
&
category
()
const
{
return
*
mCat
;
}
Category
&
category
()
const
{
return
*
mCat
;
}
void
swap
(
iterator_proxy
&
rhs
)
void
swap
(
iterator_proxy
&
rhs
)
{
{
...
@@ -1553,7 +1551,7 @@ class iterator_proxy
...
@@ -1553,7 +1551,7 @@ class iterator_proxy
}
}
private
:
private
:
Category
Type
*
mCat
;
Category
*
mCat
;
row_iterator
mCBegin
,
mCEnd
;
row_iterator
mCBegin
,
mCEnd
;
std
::
array
<
size_t
,
N
>
mCix
;
std
::
array
<
size_t
,
N
>
mCix
;
};
};
...
@@ -1561,13 +1559,13 @@ class iterator_proxy
...
@@ -1561,13 +1559,13 @@ class iterator_proxy
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// conditional iterator proxy
// conditional iterator proxy
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
class
conditional_iterator_proxy
class
conditional_iterator_proxy
{
{
public
:
public
:
static
constexpr
const
size_t
N
=
sizeof
...(
Ts
);
static
constexpr
const
size_t
N
=
sizeof
...(
Ts
);
using
base_iterator
=
iterator_impl
<
Category
Type
,
Ts
...
>
;
using
base_iterator
=
iterator_impl
<
Category
,
Ts
...
>
;
using
value_type
=
typename
base_iterator
::
value_type
;
using
value_type
=
typename
base_iterator
::
value_type
;
using
row_type
=
typename
base_iterator
::
row_type
;
using
row_type
=
typename
base_iterator
::
row_type
;
using
row_iterator
=
iterator_impl
<
row_type
>
;
using
row_iterator
=
iterator_impl
<
row_type
>
;
...
@@ -1581,7 +1579,7 @@ class conditional_iterator_proxy
...
@@ -1581,7 +1579,7 @@ class conditional_iterator_proxy
using
pointer
=
value_type
*
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
using
reference
=
value_type
&
;
conditional_iterator_impl
(
Category
Type
&
cat
,
row_iterator
pos
,
const
Condition
&
cond
,
const
std
::
array
<
size_t
,
N
>
&
cix
);
conditional_iterator_impl
(
Category
&
cat
,
row_iterator
pos
,
const
Condition
&
cond
,
const
std
::
array
<
size_t
,
N
>
&
cix
);
conditional_iterator_impl
(
const
conditional_iterator_impl
&
i
)
=
default
;
conditional_iterator_impl
(
const
conditional_iterator_impl
&
i
)
=
default
;
conditional_iterator_impl
&
operator
=
(
const
conditional_iterator_impl
&
i
)
=
default
;
conditional_iterator_impl
&
operator
=
(
const
conditional_iterator_impl
&
i
)
=
default
;
...
@@ -1628,7 +1626,7 @@ class conditional_iterator_proxy
...
@@ -1628,7 +1626,7 @@ class conditional_iterator_proxy
bool
operator
!=
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
{
return
mBegin
!=
rhs
;
}
bool
operator
!=
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
{
return
mBegin
!=
rhs
;
}
private
:
private
:
Category
Type
*
mCat
;
Category
*
mCat
;
base_iterator
mBegin
,
mEnd
;
base_iterator
mBegin
,
mEnd
;
const
Condition
*
mCondition
;
const
Condition
*
mCondition
;
};
};
...
@@ -1637,7 +1635,7 @@ class conditional_iterator_proxy
...
@@ -1637,7 +1635,7 @@ class conditional_iterator_proxy
using
reference
=
typename
iterator
::
reference
;
using
reference
=
typename
iterator
::
reference
;
template
<
typename
...
Ns
>
template
<
typename
...
Ns
>
conditional_iterator_proxy
(
Category
Type
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
Ns
...
names
);
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
Ns
...
names
);
conditional_iterator_proxy
(
conditional_iterator_proxy
&&
p
);
conditional_iterator_proxy
(
conditional_iterator_proxy
&&
p
);
conditional_iterator_proxy
&
operator
=
(
conditional_iterator_proxy
&&
p
);
conditional_iterator_proxy
&
operator
=
(
conditional_iterator_proxy
&&
p
);
...
@@ -1656,12 +1654,12 @@ class conditional_iterator_proxy
...
@@ -1656,12 +1654,12 @@ class conditional_iterator_proxy
row_type
front
()
{
return
*
begin
();
}
row_type
front
()
{
return
*
begin
();
}
Category
Type
&
category
()
const
{
return
*
mCat
;
}
Category
&
category
()
const
{
return
*
mCat
;
}
void
swap
(
conditional_iterator_proxy
&
rhs
);
void
swap
(
conditional_iterator_proxy
&
rhs
);
private
:
private
:
Category
Type
*
mCat
;
Category
*
mCat
;
Condition
mCondition
;
Condition
mCondition
;
row_iterator
mCBegin
,
mCEnd
;
row_iterator
mCBegin
,
mCEnd
;
std
::
array
<
size_t
,
N
>
mCix
;
std
::
array
<
size_t
,
N
>
mCix
;
...
@@ -2353,8 +2351,8 @@ inline void swap(cif::detail::ItemReference &a, cif::detail::ItemReference &b)
...
@@ -2353,8 +2351,8 @@ inline void swap(cif::detail::ItemReference &a, cif::detail::ItemReference &b)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
iterator_proxy
<
Category
Type
,
Ts
...
>::
iterator_proxy
(
CategoryType
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
])
iterator_proxy
<
Category
,
Ts
...
>::
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
])
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
,
mCBegin
(
pos
)
,
mCBegin
(
pos
)
,
mCEnd
(
cat
.
end
())
,
mCEnd
(
cat
.
end
())
...
@@ -2363,8 +2361,8 @@ iterator_proxy<CategoryType, Ts...>::iterator_proxy(CategoryType &cat, row_itera
...
@@ -2363,8 +2361,8 @@ iterator_proxy<CategoryType, Ts...>::iterator_proxy(CategoryType &cat, row_itera
mCix
[
i
]
=
mCat
->
getColumnIndex
(
columns
[
i
]);
mCix
[
i
]
=
mCat
->
getColumnIndex
(
columns
[
i
]);
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
iterator_proxy
<
Category
Type
,
Ts
...
>::
iterator_proxy
(
CategoryType
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
)
iterator_proxy
<
Category
,
Ts
...
>::
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
)
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
,
mCBegin
(
pos
)
,
mCBegin
(
pos
)
,
mCEnd
(
cat
.
end
())
,
mCEnd
(
cat
.
end
())
...
@@ -2378,9 +2376,9 @@ iterator_proxy<CategoryType, Ts...>::iterator_proxy(CategoryType &cat, row_itera
...
@@ -2378,9 +2376,9 @@ iterator_proxy<CategoryType, Ts...>::iterator_proxy(CategoryType &cat, row_itera
// --------------------------------------------------------------------
// --------------------------------------------------------------------
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
conditional_iterator_impl
::
conditional_iterator_impl
(
conditional_iterator_proxy
<
Category
,
Ts
...
>::
conditional_iterator_impl
::
conditional_iterator_impl
(
Category
Type
&
cat
,
row_iterator
pos
,
const
Condition
&
cond
,
const
std
::
array
<
size_t
,
N
>
&
cix
)
Category
&
cat
,
row_iterator
pos
,
const
Condition
&
cond
,
const
std
::
array
<
size_t
,
N
>
&
cix
)
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
,
mBegin
(
pos
,
cix
)
,
mBegin
(
pos
,
cix
)
,
mEnd
(
cat
.
end
(),
cix
)
,
mEnd
(
cat
.
end
(),
cix
)
...
@@ -2388,8 +2386,8 @@ conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_impl::cond
...
@@ -2388,8 +2386,8 @@ conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_impl::cond
{
{
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
conditional_iterator_proxy
(
conditional_iterator_proxy
&&
p
)
conditional_iterator_proxy
<
Category
,
Ts
...
>::
conditional_iterator_proxy
(
conditional_iterator_proxy
&&
p
)
:
mCat
(
nullptr
)
:
mCat
(
nullptr
)
,
mCBegin
(
p
.
mCBegin
)
,
mCBegin
(
p
.
mCBegin
)
,
mCEnd
(
p
.
mCEnd
)
,
mCEnd
(
p
.
mCEnd
)
...
@@ -2400,9 +2398,9 @@ conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_proxy(cond
...
@@ -2400,9 +2398,9 @@ conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_proxy(cond
mCondition
.
swap
(
p
.
mCondition
);
mCondition
.
swap
(
p
.
mCondition
);
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
template
<
typename
...
Ns
>
template
<
typename
...
Ns
>
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
conditional_iterator_proxy
(
CategoryType
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
Ns
...
names
)
conditional_iterator_proxy
<
Category
,
Ts
...
>::
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
Ns
...
names
)
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
,
mCondition
(
std
::
move
(
cond
))
,
mCondition
(
std
::
move
(
cond
))
,
mCBegin
(
pos
)
,
mCBegin
(
pos
)
...
@@ -2419,33 +2417,33 @@ conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_proxy(Cate
...
@@ -2419,33 +2417,33 @@ conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_proxy(Cate
((
mCix
[
i
++
]
=
mCat
->
getColumnIndex
(
names
)),
...);
((
mCix
[
i
++
]
=
mCat
->
getColumnIndex
(
names
)),
...);
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>
&
conditional_iterator_proxy
<
CategoryType
,
Ts
...
>::
operator
=
(
conditional_iterator_proxy
&&
p
)
conditional_iterator_proxy
<
Category
,
Ts
...
>
&
conditional_iterator_proxy
<
Category
,
Ts
...
>::
operator
=
(
conditional_iterator_proxy
&&
p
)
{
{
swap
(
p
);
swap
(
p
);
return
*
this
;
return
*
this
;
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
typename
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
CategoryType
,
Ts
...
>::
begin
()
const
typename
conditional_iterator_proxy
<
Category
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
Category
,
Ts
...
>::
begin
()
const
{
{
return
iterator
(
*
mCat
,
mCBegin
,
mCondition
,
mCix
);
return
iterator
(
*
mCat
,
mCBegin
,
mCondition
,
mCix
);
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
typename
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
CategoryType
,
Ts
...
>::
end
()
const
typename
conditional_iterator_proxy
<
Category
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
Category
,
Ts
...
>::
end
()
const
{
{
return
iterator
(
*
mCat
,
mCEnd
,
mCondition
,
mCix
);
return
iterator
(
*
mCat
,
mCEnd
,
mCondition
,
mCix
);
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
bool
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
empty
()
const
bool
conditional_iterator_proxy
<
Category
,
Ts
...
>::
empty
()
const
{
{
return
mCBegin
==
mCEnd
;
return
mCBegin
==
mCEnd
;
}
}
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
void
conditional_iterator_proxy
<
Category
Type
,
Ts
...
>::
swap
(
conditional_iterator_proxy
&
rhs
)
void
conditional_iterator_proxy
<
Category
,
Ts
...
>::
swap
(
conditional_iterator_proxy
&
rhs
)
{
{
std
::
swap
(
mCat
,
rhs
.
mCat
);
std
::
swap
(
mCat
,
rhs
.
mCat
);
mCondition
.
swap
(
rhs
.
mCondition
);
mCondition
.
swap
(
rhs
.
mCondition
);
...
...
include/cif++/v2/category.hpp
View file @
10442d50
...
@@ -39,6 +39,50 @@ template <
...
@@ -39,6 +39,50 @@ template <
typename
Alloc
=
std
::
allocator
<
std
::
byte
>>
typename
Alloc
=
std
::
allocator
<
std
::
byte
>>
class
category_t
class
category_t
{
{
private
:
// --------------------------------------------------------------------
// Internal storage, strictly forward linked list with minimal space
// requirements. Strings of size 7 or shorter are stored internally.
// Typically, more than 99% of the strings in an mmCIF file are less
// than 8 bytes in length.
struct
item_value
{
item_value
(
uint16_t
column_ix
,
uint16_t
length
)
:
m_next
(
nullptr
)
,
m_column_ix
(
column_ix
)
,
m_length
(
length
)
{
}
item_value
()
=
delete
;
item_value
(
const
item_value
&
)
=
delete
;
item_value
&
operator
=
(
const
item_value
&
)
=
delete
;
item_value
*
m_next
;
uint16_t
m_column_ix
;
uint16_t
m_length
;
union
{
char
m_local_data
[
8
];
char
*
m_data
;
};
static
constexpr
size_t
kBufferSize
=
sizeof
(
m_local_data
);
std
::
string_view
text
()
const
{
return
{
m_length
>=
kBufferSize
?
m_data
:
m_local_data
,
m_length
};
}
const
char
*
c_str
()
const
{
return
m_length
>=
kBufferSize
?
m_data
:
m_local_data
;
}
};
static_assert
(
sizeof
(
item_value
)
==
24
,
"sizeof(item_value) should be 24 bytes"
);
public
:
public
:
using
allocator_type
=
Alloc
;
using
allocator_type
=
Alloc
;
...
@@ -59,6 +103,42 @@ class category_t
...
@@ -59,6 +103,42 @@ class category_t
using
iterator
=
iterator_impl
<
category_t
>
;
using
iterator
=
iterator_impl
<
category_t
>
;
using
const_iterator
=
iterator_impl
<
const
category_t
>
;
using
const_iterator
=
iterator_impl
<
const
category_t
>
;
class
row
{
public
:
row
()
:
m_next
(
nullptr
)
,
m_head
(
nullptr
)
,
m_tail
(
nullptr
)
{
}
row
(
row
*
next
,
item_value
*
data
)
:
m_next
(
next
)
,
m_head
(
data
)
,
m_tail
(
data
)
{
auto
n
=
m_tail
?
m_tail
->
m_next
:
nullptr
;
while
(
n
!=
nullptr
)
{
m_tail
=
n
;
n
=
n
->
m_next
;
}
}
private
:
template
<
typename
>
friend
class
item_handle
;
template
<
typename
,
typename
...
>
friend
class
iterator_impl
;
friend
class
category_t
;
row
*
m_next
=
nullptr
;
item_value
*
m_head
=
nullptr
,
*
m_tail
=
nullptr
;
};
category_t
()
=
default
;
category_t
()
=
default
;
category_t
(
std
::
string_view
name
,
const
allocator_type
&
alloc
=
allocator_type
())
category_t
(
std
::
string_view
name
,
const
allocator_type
&
alloc
=
allocator_type
())
...
@@ -161,6 +241,24 @@ class category_t
...
@@ -161,6 +241,24 @@ class category_t
return
{
*
this
,
nullptr
};
return
{
*
this
,
nullptr
};
}
}
// --------------------------------------------------------------------
template
<
typename
...
Ts
,
typename
...
Ns
>
iterator_proxy
<
const
category_t
,
Ts
...
>
rows
(
Ns
...
names
)
const
{
static_assert
(
sizeof
...(
Ts
)
==
sizeof
...(
Ns
),
"The number of column titles should be equal to the number of types to return"
);
return
iterator_proxy
<
const
category_t
,
Ts
...
>
(
*
this
,
begin
(),
{
names
...});
}
template
<
typename
...
Ts
,
typename
...
Ns
>
iterator_proxy
<
category_t
,
Ts
...
>
rows
(
Ns
...
names
)
{
static_assert
(
sizeof
...(
Ts
)
==
sizeof
...(
Ns
),
"The number of column titles should be equal to the number of types to return"
);
return
iterator_proxy
<
category_t
,
Ts
...
>
(
*
this
,
begin
(),
{
names
...});
}
// --------------------------------------------------------------------
iterator
emplace
(
std
::
initializer_list
<
item
>
items
)
iterator
emplace
(
std
::
initializer_list
<
item
>
items
)
{
{
return
this
->
emplace
(
items
.
begin
(),
items
.
end
());
return
this
->
emplace
(
items
.
begin
(),
items
.
end
());
...
@@ -243,7 +341,7 @@ class category_t
...
@@ -243,7 +341,7 @@ class category_t
else
else
m_tail
=
m_tail
->
m_next
=
r
;
m_tail
=
m_tail
->
m_next
=
r
;
return
{
*
this
,
r
};
return
{
*
this
,
r
};
// result = r;
// result = r;
...
@@ -298,49 +396,6 @@ class category_t
...
@@ -298,49 +396,6 @@ class category_t
}
}
private
:
private
:
// --------------------------------------------------------------------
// Internal storage, strictly forward linked list with minimal space
// requirements. Strings of size 7 or shorter are stored internally.
// Typically, more than 99% of the strings in an mmCIF file are less
// than 8 bytes in length.
struct
item_value
{
item_value
(
uint16_t
column_ix
,
uint16_t
length
)
:
m_next
(
nullptr
)
,
m_column_ix
(
column_ix
)
,
m_length
(
length
)
{
}
item_value
()
=
delete
;
item_value
(
const
item_value
&
)
=
delete
;
item_value
&
operator
=
(
const
item_value
&
)
=
delete
;
item_value
*
m_next
;
uint16_t
m_column_ix
;
uint16_t
m_length
;
union
{
char
m_local_data
[
8
];
char
*
m_data
;
};
static
constexpr
size_t
kBufferSize
=
sizeof
(
m_local_data
);
std
::
string_view
text
()
const
{
return
{
m_length
>=
kBufferSize
?
m_data
:
m_local_data
,
m_length
};
}
const
char
*
c_str
()
const
{
return
m_length
>=
kBufferSize
?
m_data
:
m_local_data
;
}
};
static_assert
(
sizeof
(
item_value
)
==
24
,
"sizeof(item_value) should be 24 bytes"
);
using
char_allocator_type
=
typename
std
::
allocator_traits
<
Alloc
>::
template
rebind_alloc
<
char
>
;
using
char_allocator_type
=
typename
std
::
allocator_traits
<
Alloc
>::
template
rebind_alloc
<
char
>
;
using
char_allocator_traits
=
std
::
allocator_traits
<
char_allocator_type
>
;
using
char_allocator_traits
=
std
::
allocator_traits
<
char_allocator_type
>
;
...
@@ -397,44 +452,6 @@ class category_t
...
@@ -397,44 +452,6 @@ class category_t
item_allocator_traits
::
deallocate
(
ia
,
iv
,
1
);
item_allocator_traits
::
deallocate
(
ia
,
iv
,
1
);
}
}
struct
row
{
// row() = default;
// row(const row &) = default;
// row(row &&) = default;
// row &operator=(const row &) = default;
// row &operator=(row &&) = default;
template
<
typename
R
>
friend
class
item_handle
;
row
()
:
m_next
(
nullptr
)
,
m_head
(
nullptr
)
,
m_tail
(
nullptr
)
{
}
row
(
row
*
next
,
item_value
*
data
)
:
m_next
(
next
)
,
m_head
(
data
)
,
m_tail
(
data
)
{
auto
n
=
m_tail
?
m_tail
->
m_next
:
nullptr
;
while
(
n
!=
nullptr
)
{
m_tail
=
n
;
n
=
n
->
m_next
;
}
}
row
*
m_next
=
nullptr
;
item_value
*
m_head
=
nullptr
,
*
m_tail
=
nullptr
;
};
using
row_allocator_type
=
typename
std
::
allocator_traits
<
allocator_type
>::
template
rebind_alloc
<
row
>
;
using
row_allocator_type
=
typename
std
::
allocator_traits
<
allocator_type
>::
template
rebind_alloc
<
row
>
;
using
row_allocator_traits
=
std
::
allocator_traits
<
row_allocator_type
>
;
using
row_allocator_traits
=
std
::
allocator_traits
<
row_allocator_type
>
;
...
...
include/cif++/v2/item.hpp
View file @
10442d50
...
@@ -33,6 +33,12 @@
...
@@ -33,6 +33,12 @@
#include <optional>
#include <optional>
#include <limits>
#include <limits>
namespace
cif
{
extern
int
VERBOSE
;
}
namespace
cif
::
v2
namespace
cif
::
v2
{
{
...
@@ -238,7 +244,7 @@ struct item_handle
...
@@ -238,7 +244,7 @@ struct item_handle
template
<
typename
Row
>
template
<
typename
Row
>
template
<
typename
T
>
template
<
typename
T
>
struct
item_handle
<
Row
>::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_
integral
_v
<
T
>>>
struct
item_handle
<
Row
>::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_
arithmetic
_v
<
T
>>>
{
{
using
value_type
=
std
::
remove_reference_t
<
std
::
remove_cv_t
<
T
>>
;
using
value_type
=
std
::
remove_reference_t
<
std
::
remove_cv_t
<
T
>>
;
...
@@ -247,25 +253,30 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_integral_v<T>
...
@@ -247,25 +253,30 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_integral_v<T>
auto
txt
=
ref
.
text
();
auto
txt
=
ref
.
text
();
value_type
result
=
{};
value_type
result
=
{};
auto
[
ptr
,
ec
]
{
std
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
)
};
if
(
ec
==
std
::
errc
::
invalid_argument
)
std
::
from_chars_result
r
;
if
constexpr
(
std
::
is_floating_point_v
<
T
>
)
r
=
cif
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
);
else
r
=
std
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
);
if
(
r
.
ec
!=
std
::
errc
())
{
{
// if (cif::VERBOSE)
// std::cerr << "Attempt to convert " << std::quoted(txt) << " into a number" << std::endl;
result
=
{};
result
=
{};
}
if
(
cif
::
VERBOSE
)
else
if
(
ec
==
std
::
errc
::
result_out_of_range
)
{
{
// if (cif::VERBOSE)
if
(
r
.
ec
==
std
::
errc
::
invalid_argument
)
// std::cerr << "Conversion of " << std::quoted(txt) << " into a type that is too small" << std::endl;
std
::
cerr
<<
"Attempt to convert "
<<
std
::
quoted
(
txt
)
<<
" into a number"
<<
std
::
endl
;
result
=
{};
else
if
(
r
.
ec
==
std
::
errc
::
result_out_of_range
)
std
::
cerr
<<
"Conversion of "
<<
std
::
quoted
(
txt
)
<<
" into a type that is too small"
<<
std
::
endl
;
}
}
}
return
result
;
return
result
;
}
}
static
int
compare
(
const
item_handle
&
ref
,
double
value
,
bool
icase
)
static
int
compare
(
const
item_handle
&
ref
,
const
T
&
value
,
bool
icase
)
{
{
int
result
=
0
;
int
result
=
0
;
...
@@ -276,64 +287,25 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_integral_v<T>
...
@@ -276,64 +287,25 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_integral_v<T>
else
else
{
{
value_type
v
=
{};
value_type
v
=
{};
auto
[
ptr
,
ec
]
{
std
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
)
};
if
(
ec
!=
std
::
errc
())
result
=
1
;
else
if
(
v
<
value
)
result
=
-
1
;
else
if
(
v
>
value
)
result
=
1
;
}
return
result
;
}
};
template
<
typename
Row
>
template
<
typename
T
>
struct
item_handle
<
Row
>::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_floating_point_v
<
T
>>>
{
using
value_type
=
std
::
remove_reference_t
<
std
::
remove_cv_t
<
T
>>
;
static
value_type
convert
(
const
item_handle
&
ref
)
std
::
from_chars_result
r
;
{
auto
txt
=
ref
.
text
();
value_type
result
=
{};
if
constexpr
(
std
::
is_floating_point_v
<
T
>
)
auto
[
ptr
,
ec
]
{
cif
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
)
};
r
=
cif
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
);
else
r
=
std
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
);
if
(
ec
==
std
::
errc
::
invalid_argument
)
if
(
r
.
ec
!=
std
::
errc
()
)
{
{
// if (cif::VERBOSE)
if
(
cif
::
VERBOSE
)
// std::cerr << "Attempt to convert " << std::quoted(txt) << " into a number" << std::endl;
result
=
{};
}
else
if
(
ec
==
std
::
errc
::
result_out_of_range
)
{
{
// if (cif::VERBOSE)
if
(
r
.
ec
==
std
::
errc
::
invalid_argument
)
// std::cerr << "Conversion of " << std::quoted(txt) << " into a type that is too small" << std::endl;
std
::
cerr
<<
"Attempt to convert "
<<
std
::
quoted
(
txt
)
<<
" into a number"
<<
std
::
endl
;
result
=
{};
else
if
(
r
.
ec
==
std
::
errc
::
result_out_of_range
)
}
std
::
cerr
<<
"Conversion of "
<<
std
::
quoted
(
txt
)
<<
" into a type that is too small"
<<
std
::
endl
;
return
result
;
}
}
static
int
compare
(
const
item_handle
&
ref
,
double
value
,
bool
icase
)
{
int
result
=
0
;
auto
txt
=
ref
.
text
();
if
(
txt
.
empty
())
result
=
1
;
else
{
value_type
v
=
{};
auto
[
ptr
,
ec
]
{
cif
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
)
};
if
(
ec
!=
std
::
errc
())
result
=
1
;
result
=
1
;
}
else
if
(
v
<
value
)
else
if
(
v
<
value
)
result
=
-
1
;
result
=
-
1
;
else
if
(
v
>
value
)
else
if
(
v
>
value
)
...
@@ -344,90 +316,6 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_floating_poin
...
@@ -344,90 +316,6 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_floating_poin
}
}
};
};
// template <typename Row>
// template <typename T>
// struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_integral_v<T> and std::is_unsigned_v<T> and not std::is_same_v<T, bool>>>
// {
// static T convert(const item_handle &ref)
// {
// T result = {};
// if (not ref.empty())
// result = static_cast<T>(std::stoul(ref.c_str()));
// return result;
// }
// static int compare(const item_handle &ref, unsigned long value, bool icase)
// {
// int result = 0;
// auto txt = ref.text();
// if (txt.empty())
// result = 1;
// else
// {
// try
// {
// auto v = std::stol(txt);
// if (v < value)
// result = -1;
// else if (v > value)
// result = 1;
// }
// catch (...)
// {
// // if (VERBOSE)
// // std::cerr << "conversion error in compare for '" << ref.c_str() << '\'' << std::endl;
// result = 1;
// }
// }
// return result;
// }
// };
// template <typename Row>
// template <typename T>
// struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_integral_v<T> and std::is_signed_v<T> and not std::is_same_v<T, bool>>>
// {
// static T convert(const item_handle &ref)
// {
// T result = {};
// if (not ref.empty())
// result = static_cast<T>(std::stol(ref.text()));
// return result;
// }
// static int compare(const item_handle &ref, long value, bool icase)
// {
// int result = 0;
// auto txt = ref.text();
// if (txt.empty())
// result = 1;
// else
// {
// try
// {
// auto v = std::stol(txt);
// if (v < value)
// result = -1;
// else if (v > value)
// result = 1;
// }
// catch (...)
// {
// // if (VERBOSE)
// // std::cerr << "conversion error in compare for '" << ref.c_str() << '\'' << std::endl;
// result = 1;
// }
// }
// return result;
// }
// };
template
<
typename
Row
>
template
<
typename
Row
>
template
<
typename
T
>
template
<
typename
T
>
struct
item_handle
<
Row
>::
item_value_as
<
std
::
optional
<
T
>>
struct
item_handle
<
Row
>::
item_value_as
<
std
::
optional
<
T
>>
...
...
include/cif++/v2/iterator.hpp
View file @
10442d50
...
@@ -33,7 +33,7 @@ namespace cif::v2
...
@@ -33,7 +33,7 @@ namespace cif::v2
// --------------------------------------------------------------------
// --------------------------------------------------------------------
template
<
typename
Category
Type
,
typename
...
Ts
>
template
<
typename
Category
,
typename
...
Ts
>
class
iterator_impl
class
iterator_impl
{
{
public
:
public
:
...
@@ -42,22 +42,15 @@ class iterator_impl
...
@@ -42,22 +42,15 @@ class iterator_impl
static
constexpr
size_t
N
=
sizeof
...(
Ts
);
static
constexpr
size_t
N
=
sizeof
...(
Ts
);
using
category_type
=
CategoryType
;
using
category_type
=
Category
;
using
row_type
=
typename
category_type
::
row
;
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
category_type
>
,
const
typename
category_type
::
row
,
typename
category_type
::
row
>
;
using
row_handle_type
=
std
::
conditional_t
<
std
::
is_const_v
<
category_type
>
,
const
row_handle
<
category_type
>
,
row_handle
<
category_type
>>
;
// using row_type = std::conditional_t<std::is_const_v<category_type>, const category_type::row, category_type::row>;
// using row_impl_type = std::conditional_t<std::is_const_v<category_type>, typename const category_type::row, typename category_type::row>;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
value_type
=
std
::
conditional_t
<
N
==
0
,
row_handle
<
category_type
>
,
std
::
tuple
<
Ts
...
>>
;
using
value_type
=
std
::
conditional_t
<
N
==
0
,
row_handle
_type
,
std
::
tuple
<
Ts
...
>>
;
using
difference_type
=
std
::
ptrdiff_t
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
pointer
=
std
::
conditional_t
<
N
==
0
,
row_handle_type
,
value_type
*>
;
using
reference
=
std
::
conditional_t
<
N
==
0
,
row_handle
<
category_type
>
,
value_type
>
;
using
reference
=
std
::
conditional_t
<
N
==
0
,
row_handle_type
,
value_type
&>
;
friend
class
Category
;
// // default constructor, equal to end()
// iterator_impl() {}
iterator_impl
(
const
iterator_impl
&
rhs
)
iterator_impl
(
const
iterator_impl
&
rhs
)
:
m_category
(
rhs
.
m_category
)
:
m_category
(
rhs
.
m_category
)
...
@@ -91,6 +84,7 @@ class iterator_impl
...
@@ -91,6 +84,7 @@ class iterator_impl
iterator_impl
(
iterator_impl
<
IRowType
,
Ts
...
>
&
rhs
)
iterator_impl
(
iterator_impl
<
IRowType
,
Ts
...
>
&
rhs
)
:
m_category
(
rhs
.
m_category
)
:
m_category
(
rhs
.
m_category
)
,
m_current
(
rhs
.
m_current
)
,
m_current
(
rhs
.
m_current
)
,
m_value
(
rhs
.
m_value
)
,
m_column_ix
(
rhs
.
m_column_ix
)
,
m_column_ix
(
rhs
.
m_column_ix
)
{
{
if
constexpr
(
N
>
0
)
if
constexpr
(
N
>
0
)
...
@@ -104,7 +98,7 @@ class iterator_impl
...
@@ -104,7 +98,7 @@ class iterator_impl
,
m_column_ix
(
cix
)
,
m_column_ix
(
cix
)
{
{
if
constexpr
(
N
>
0
)
if
constexpr
(
N
>
0
)
m_value
=
get
(
m_current
,
std
::
make_index_sequence
<
N
>
());
m_value
=
get
(
std
::
make_index_sequence
<
N
>
());
}
}
iterator_impl
&
operator
=
(
const
iterator_impl
&
i
)
iterator_impl
&
operator
=
(
const
iterator_impl
&
i
)
...
@@ -124,7 +118,7 @@ class iterator_impl
...
@@ -124,7 +118,7 @@ class iterator_impl
reference
operator
*
()
reference
operator
*
()
{
{
if
constexpr
(
N
==
0
)
if
constexpr
(
N
==
0
)
return
{
*
m_category
,
*
m_current
};
return
{
*
m_category
,
*
m_current
};
else
else
return
m_value
;
return
m_value
;
}
}
...
@@ -148,7 +142,7 @@ class iterator_impl
...
@@ -148,7 +142,7 @@ class iterator_impl
m_current
=
m_current
->
m_next
;
m_current
=
m_current
->
m_next
;
if
constexpr
(
N
!=
0
)
if
constexpr
(
N
!=
0
)
m_value
=
get
(
m_current
,
std
::
make_index_sequence
<
N
>
());
m_value
=
get
(
std
::
make_index_sequence
<
N
>
());
return
*
this
;
return
*
this
;
}
}
...
@@ -177,10 +171,14 @@ class iterator_impl
...
@@ -177,10 +171,14 @@ class iterator_impl
private
:
private
:
template
<
std
::
size_t
...
Is
>
template
<
std
::
size_t
...
Is
>
std
::
tuple
<
Ts
...
>
get
(
row_type
row
,
std
::
index_sequence
<
Is
...
>
)
const
std
::
tuple
<
Ts
...
>
get
(
std
::
index_sequence
<
Is
...
>
)
const
{
if
(
m_current
!=
nullptr
)
{
{
if
(
row
)
row_handle_type
rh
{
*
m_category
,
*
m_current
};
return
std
::
tuple
<
Ts
...
>
{
row
[
m_column_ix
[
Is
]].
template
as
<
Ts
>
()...};
return
std
::
tuple
<
Ts
...
>
{
rh
[
m_column_ix
[
Is
]].
template
as
<
Ts
>
()...};
}
return
{};
return
{};
}
}
...
@@ -190,5 +188,269 @@ class iterator_impl
...
@@ -190,5 +188,269 @@ class iterator_impl
std
::
array
<
size_t
,
N
>
m_column_ix
;
std
::
array
<
size_t
,
N
>
m_column_ix
;
};
};
// --------------------------------------------------------------------
// iterator proxy
template
<
typename
Category
,
typename
...
Ts
>
class
iterator_proxy
{
public
:
static
constexpr
const
size_t
N
=
sizeof
...(
Ts
);
using
category_type
=
Category
;
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
category_type
>
,
const
typename
category_type
::
row
,
typename
category_type
::
row
>
;
using
row_handle_type
=
std
::
conditional_t
<
std
::
is_const_v
<
category_type
>
,
const
row_handle
<
category_type
>
,
row_handle
<
category_type
>>
;
using
iterator
=
iterator_impl
<
category_type
,
Ts
...
>
;
using
row_iterator
=
iterator_impl
<
category_type
>
;
iterator_proxy
(
category_type
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
]);
iterator_proxy
(
category_type
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
);
iterator_proxy
(
iterator_proxy
&&
p
);
iterator_proxy
&
operator
=
(
iterator_proxy
&&
p
);
iterator_proxy
(
const
iterator_proxy
&
)
=
delete
;
iterator_proxy
&
operator
=
(
const
iterator_proxy
&
)
=
delete
;
iterator
begin
()
const
{
return
iterator
(
m_begin
,
m_column_ix
);
}
iterator
end
()
const
{
return
iterator
(
m_end
,
m_column_ix
);
}
bool
empty
()
const
{
return
m_begin
==
m_end
;
}
explicit
operator
bool
()
const
{
return
not
empty
();
}
size_t
size
()
const
{
return
std
::
distance
(
begin
(),
end
());
}
row_type
front
()
{
return
*
begin
();
}
row_type
back
()
{
return
*
(
std
::
prev
(
end
()));
}
category_type
&
category
()
const
{
return
*
m_category
;
}
void
swap
(
iterator_proxy
&
rhs
)
{
std
::
swap
(
m_category
,
rhs
.
m_category
);
std
::
swap
(
m_begin
,
rhs
.
m_begin
);
std
::
swap
(
m_end
,
rhs
.
m_end
);
std
::
swap
(
m_column_ix
,
rhs
.
m_column_ix
);
}
private
:
category_type
*
m_category
;
row_iterator
m_begin
,
m_end
;
std
::
array
<
size_t
,
N
>
m_column_ix
;
};
// // --------------------------------------------------------------------
// // conditional iterator proxy
// template <typename CategoryType, typename... Ts>
// class conditional_iterator_proxy
// {
// public:
// static constexpr const size_t N = sizeof...(Ts);
// using base_iterator = iterator_impl<CategoryType, Ts...>;
// using value_type = typename base_iterator::value_type;
// using row_type = typename base_iterator::row_type;
// using row_iterator = iterator_impl<row_type>;
// class conditional_iterator_impl
// {
// public:
// using iterator_category = std::forward_iterator_tag;
// using value_type = conditional_iterator_proxy::value_type;
// using difference_type = std::ptrdiff_t;
// using pointer = value_type *;
// using reference = value_type &;
// conditional_iterator_impl(CategoryType &cat, row_iterator pos, const Condition &cond, const std::array<size_t, N> &cix);
// conditional_iterator_impl(const conditional_iterator_impl &i) = default;
// conditional_iterator_impl &operator=(const conditional_iterator_impl &i) = default;
// virtual ~conditional_iterator_impl() = default;
// reference operator*()
// {
// return *mBegin;
// }
// pointer operator->()
// {
// return &*mBegin;
// }
// conditional_iterator_impl &operator++()
// {
// while (mBegin != mEnd)
// {
// if (++mBegin == mEnd)
// break;
// if ((*mCondition)(*mCat, mBegin.row()))
// break;
// }
// return *this;
// }
// conditional_iterator_impl operator++(int)
// {
// conditional_iterator_impl result(*this);
// this->operator++();
// return result;
// }
// bool operator==(const conditional_iterator_impl &rhs) const { return mBegin == rhs.mBegin; }
// bool operator!=(const conditional_iterator_impl &rhs) const { return mBegin != rhs.mBegin; }
// template <typename IRowType, typename... ITs>
// bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin == rhs; }
// template <typename IRowType, typename... ITs>
// bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin != rhs; }
// private:
// CategoryType *mCat;
// base_iterator mBegin, mEnd;
// const Condition *mCondition;
// };
// using iterator = conditional_iterator_impl;
// using reference = typename iterator::reference;
// template <typename... Ns>
// conditional_iterator_proxy(CategoryType &cat, row_iterator pos, Condition &&cond, Ns... names);
// conditional_iterator_proxy(conditional_iterator_proxy &&p);
// conditional_iterator_proxy &operator=(conditional_iterator_proxy &&p);
// conditional_iterator_proxy(const conditional_iterator_proxy &) = delete;
// conditional_iterator_proxy &operator=(const conditional_iterator_proxy &) = delete;
// iterator begin() const;
// iterator end() const;
// bool empty() const;
// explicit operator bool() const { return not empty(); }
// size_t size() const { return std::distance(begin(), end()); }
// row_type front() { return *begin(); }
// CategoryType &category() const { return *mCat; }
// void swap(conditional_iterator_proxy &rhs);
// private:
// CategoryType *mCat;
// Condition mCondition;
// row_iterator mCBegin, mCEnd;
// std::array<size_t, N> mCix;
// };
// --------------------------------------------------------------------
template
<
typename
Category
,
typename
...
Ts
>
iterator_proxy
<
Category
,
Ts
...
>::
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
])
:
m_category
(
&
cat
)
,
m_begin
(
pos
)
,
m_end
(
cat
.
end
())
{
for
(
size_t
i
=
0
;
i
<
N
;
++
i
)
m_column_ix
[
i
]
=
m_category
->
get_column_ix
(
columns
[
i
]);
}
template
<
typename
Category
,
typename
...
Ts
>
iterator_proxy
<
Category
,
Ts
...
>::
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
)
:
m_category
(
&
cat
)
,
m_begin
(
pos
)
,
m_end
(
cat
.
end
())
{
// static_assert(columns.size() == N, "The list of column names should be exactly the same as the list of requested columns");
std
::
size_t
i
=
0
;
for
(
auto
column
:
columns
)
m_column_ix
[
i
++
]
=
m_category
->
get_column_ix
(
column
);
}
// --------------------------------------------------------------------
// template <typename Category, typename... Ts>
// conditional_iterator_proxy<Category, Ts...>::conditional_iterator_impl::conditional_iterator_impl(
// Category &cat, row_iterator pos, const Condition &cond, const std::array<size_t, N> &cix)
// : mCat(&cat)
// , mBegin(pos, cix)
// , mEnd(cat.end(), cix)
// , mCondition(&cond)
// {
// }
// template <typename Category, typename... Ts>
// conditional_iterator_proxy<Category, Ts...>::conditional_iterator_proxy(conditional_iterator_proxy &&p)
// : mCat(nullptr)
// , mCBegin(p.mCBegin)
// , mCEnd(p.mCEnd)
// , mCix(p.mCix)
// {
// std::swap(mCat, p.mCat);
// std::swap(mCix, p.mCix);
// mCondition.swap(p.mCondition);
// }
// template <typename Category, typename... Ts>
// template <typename... Ns>
// conditional_iterator_proxy<Category, Ts...>::conditional_iterator_proxy(Category &cat, row_iterator pos, Condition &&cond, Ns... names)
// : mCat(&cat)
// , mCondition(std::move(cond))
// , mCBegin(pos)
// , mCEnd(cat.end())
// {
// static_assert(sizeof...(Ts) == sizeof...(Ns), "Number of column names should be equal to number of requested value types");
// mCondition.prepare(cat);
// while (mCBegin != mCEnd and not mCondition(*mCat, mCBegin.row()))
// ++mCBegin;
// size_t i = 0;
// ((mCix[i++] = mCat->getColumnIndex(names)), ...);
// }
// template <typename Category, typename... Ts>
// conditional_iterator_proxy<Category, Ts...> &conditional_iterator_proxy<Category, Ts...>::operator=(conditional_iterator_proxy &&p)
// {
// swap(p);
// return *this;
// }
// template <typename Category, typename... Ts>
// typename conditional_iterator_proxy<Category, Ts...>::iterator conditional_iterator_proxy<Category, Ts...>::begin() const
// {
// return iterator(*mCat, mCBegin, mCondition, mCix);
// }
// template <typename Category, typename... Ts>
// typename conditional_iterator_proxy<Category, Ts...>::iterator conditional_iterator_proxy<Category, Ts...>::end() const
// {
// return iterator(*mCat, mCEnd, mCondition, mCix);
// }
// template <typename Category, typename... Ts>
// bool conditional_iterator_proxy<Category, Ts...>::empty() const
// {
// return mCBegin == mCEnd;
// }
// template <typename Category, typename... Ts>
// void conditional_iterator_proxy<Category, Ts...>::swap(conditional_iterator_proxy &rhs)
// {
// std::swap(mCat, rhs.mCat);
// mCondition.swap(rhs.mCondition);
// std::swap(mCBegin, rhs.mCBegin);
// std::swap(mCEnd, rhs.mCEnd);
// std::swap(mCix, rhs.mCix);
// }
}
//
namespace
cif
::
v2
}
//
namespace
cif
::
v2
\ No newline at end of file
include/cif++/v2/row.hpp
View file @
10442d50
...
@@ -31,6 +31,85 @@
...
@@ -31,6 +31,85 @@
namespace
cif
::
v2
namespace
cif
::
v2
{
{
template
<
typename
>
class
row_handle
;
namespace
detail
{
// some helper classes to help create tuple result types
template
<
typename
Category
,
typename
...
C
>
struct
get_row_result
{
using
category_type
=
Category
;
using
row_type
=
category_type
::
row
;
using
row_handle_type
=
row_handle
<
category_type
>
;
using
item_handle_type
=
item_handle
<
row_type
>
;
static
constexpr
size_t
N
=
sizeof
...(
C
);
get_row_result
(
const
row_handle_type
&
r
,
std
::
array
<
size_t
,
N
>
&&
columns
)
:
m_row
(
r
)
,
m_columns
(
std
::
move
(
columns
))
{
}
const
item_handle_type
operator
[](
size_t
ix
)
const
{
return
m_row
[
m_columns
[
ix
]];
}
template
<
typename
...
Ts
,
std
::
enable_if_t
<
N
==
sizeof
...(
Ts
),
int
>
=
0
>
operator
std
::
tuple
<
Ts
...
>
()
const
{
return
get
<
Ts
...
>
(
std
::
index_sequence_for
<
Ts
...
>
{});
}
template
<
typename
...
Ts
,
std
::
size_t
...
Is
>
std
::
tuple
<
Ts
...
>
get
(
std
::
index_sequence
<
Is
...
>
)
const
{
return
std
::
tuple
<
Ts
...
>
{
m_row
[
m_columns
[
Is
]].
template
as
<
Ts
>
()...};
}
const
row_handle_type
&
m_row
;
std
::
array
<
size_t
,
N
>
m_columns
;
};
// we want to be able to tie some variables to a get_row_result, for this we use tiewraps
template
<
typename
...
Ts
>
struct
tie_wrap
{
tie_wrap
(
Ts
...
args
)
:
m_value
(
args
...)
{
}
template
<
typename
RR
>
void
operator
=
(
const
RR
&&
rr
)
{
// get_row_result will do the conversion, but only if the types
// are compatible. That means the number of parameters to the get()
// of the row should be equal to the number of items in the tuple
// you are trying to tie.
using
RType
=
std
::
tuple
<
typename
std
::
remove_reference
<
Ts
>::
type
...
>
;
m_value
=
static_cast
<
RType
>
(
rr
);
}
std
::
tuple
<
Ts
...
>
m_value
;
};
}
template
<
typename
...
Ts
>
auto
tie
(
Ts
&
...
v
)
{
return
detail
::
tie_wrap
<
Ts
&
...
>
(
std
::
forward
<
Ts
&>
(
v
)...);
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
/// \brief row_handle is the way to access data in rows
/// \brief row_handle is the way to access data in rows
...
@@ -40,7 +119,7 @@ class row_handle
...
@@ -40,7 +119,7 @@ class row_handle
public
:
public
:
using
category_type
=
Category
;
using
category_type
=
Category
;
using
row_type
=
category_type
::
row
;
using
row_type
=
std
::
conditional_t
<
std
::
is_const_v
<
category_type
>
,
const
typename
category_type
::
row
,
typename
category_type
::
row
>
;
row_handle
(
category_type
&
cat
,
row_type
&
row
)
row_handle
(
category_type
&
cat
,
row_type
&
row
)
:
m_cat
(
cat
)
:
m_cat
(
cat
)
...
@@ -66,7 +145,22 @@ class row_handle
...
@@ -66,7 +145,22 @@ class row_handle
return
item_handle
<
const
row_type
>
(
get_column_ix
(
column_name
),
m_row
);
return
item_handle
<
const
row_type
>
(
get_column_ix
(
column_name
),
m_row
);
}
}
template
<
typename
...
Ts
,
size_t
N
>
std
::
tuple
<
Ts
...
>
get
(
char
const
*
const
(
&
columns
)[
N
])
const
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"Number of columns should be equal to number of types to return"
);
std
::
array
<
size_t
,
N
>
cix
;
for
(
size_t
i
=
0
;
i
<
N
;
++
i
)
cix
[
i
]
=
get_column_ix
(
columns
[
i
]);
return
detail
::
get_row_result
<
category_type
,
Ts
...
>
(
*
this
,
std
::
move
(
cix
));
}
template
<
typename
...
C
>
auto
get
(
C
...
columns
)
const
{
return
detail
::
get_row_result
<
category_type
,
C
...
>
(
*
this
,
{
get_column_ix
(
columns
)...});
}
private
:
private
:
...
@@ -75,8 +169,6 @@ class row_handle
...
@@ -75,8 +169,6 @@ class row_handle
return
m_cat
.
get_column_ix
(
name
);
return
m_cat
.
get_column_ix
(
name
);
}
}
category_type
&
m_cat
;
category_type
&
m_cat
;
row_type
&
m_row
;
row_type
&
m_row
;
};
};
...
...
test/unit-v2-test.cpp
View file @
10442d50
...
@@ -91,6 +91,11 @@ BOOST_AUTO_TEST_CASE(cc_1)
...
@@ -91,6 +91,11 @@ BOOST_AUTO_TEST_CASE(cc_1)
{
"-.2e11 "
,
-
.2e11
,
' '
},
{
"-.2e11 "
,
-
.2e11
,
' '
},
{
"1.3e-10 "
,
1.3e-10
,
' '
},
{
"1.3e-10 "
,
1.3e-10
,
' '
},
{
"3.0"
,
3.0
,
0
},
{
"3.0 "
,
3.0
,
' '
},
{
"3.000000"
,
3.0
,
0
},
{
"3.000000 "
,
3.0
,
' '
},
};
};
for
(
const
auto
&
[
txt
,
val
,
ch
]
:
tests
)
for
(
const
auto
&
[
txt
,
val
,
ch
]
:
tests
)
...
@@ -123,7 +128,6 @@ BOOST_AUTO_TEST_CASE(r_1)
...
@@ -123,7 +128,6 @@ BOOST_AUTO_TEST_CASE(r_1)
BOOST_CHECK_EQUAL
(
row
[
"f-3"
].
compare
(
3.0
),
0
);
BOOST_CHECK_EQUAL
(
row
[
"f-3"
].
compare
(
3.0
),
0
);
}
}
BOOST_AUTO_TEST_CASE
(
r_2
)
BOOST_AUTO_TEST_CASE
(
r_2
)
{
{
cif
::
v2
::
category
c
(
"foo"
);
cif
::
v2
::
category
c
(
"foo"
);
...
@@ -156,6 +160,29 @@ BOOST_AUTO_TEST_CASE(c_1)
...
@@ -156,6 +160,29 @@ BOOST_AUTO_TEST_CASE(c_1)
BOOST_CHECK_EQUAL
(
r
[
"s"
].
compare
(
ts
[
n
-
1
]),
0
);
BOOST_CHECK_EQUAL
(
r
[
"s"
].
compare
(
ts
[
n
-
1
]),
0
);
++
n
;
++
n
;
}
}
n
=
1
;
for
(
auto
r
:
c
)
{
int
i
;
std
::
string
s
;
cif
::
v2
::
tie
(
i
,
s
)
=
r
.
get
(
"id"
,
"s"
);
BOOST_CHECK_EQUAL
(
i
,
n
);
BOOST_CHECK_EQUAL
(
s
.
compare
(
ts
[
n
-
1
]),
0
);
++
n
;
}
n
=
1
;
for
(
const
auto
&
[
i
,
s
]
:
c
.
rows
<
int
,
std
::
string
>
(
"id"
,
"s"
))
{
BOOST_CHECK_EQUAL
(
i
,
n
);
BOOST_CHECK_EQUAL
(
s
.
compare
(
ts
[
n
-
1
]),
0
);
++
n
;
}
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
...
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