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
345c4778
Unverified
Commit
345c4778
authored
Sep 08, 2021
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
start structure-test unit test
added compare functions for Datablock and Category
parent
0ccb2f88
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1422 additions
and
946 deletions
+1422
-946
CMakeLists.txt
+1
-0
include/cif++/Cif++.hpp
+612
-498
include/cif++/Structure.hpp
+15
-0
src/Cif++.cpp
+632
-446
src/Structure.cpp
+38
-2
test/structure-test.cpp
+124
-0
test/unit-test.cpp
+0
-0
No files found.
CMakeLists.txt
View file @
345c4778
...
@@ -385,6 +385,7 @@ if(CIFPP_BUILD_TESTS)
...
@@ -385,6 +385,7 @@ if(CIFPP_BUILD_TESTS)
list
(
APPEND CIFPP_tests
list
(
APPEND CIFPP_tests
# pdb2cif
# pdb2cif
rename-compound
rename-compound
structure
unit
)
unit
)
foreach
(
CIFPP_TEST IN LISTS CIFPP_tests
)
foreach
(
CIFPP_TEST IN LISTS CIFPP_tests
)
...
...
include/cif++/Cif++.hpp
View file @
345c4778
...
@@ -28,14 +28,14 @@
...
@@ -28,14 +28,14 @@
#include <string>
#include <string>
#include <regex>
#include <array>
#include <functional>
#include <iostream>
#include <iostream>
#include <sstream>
#include <set>
#include <list>
#include <list>
#include <array>
#include <optional>
#include <optional>
#include <functional>
#include <regex>
#include <set>
#include <sstream>
#include "cif++/CifUtils.hpp"
#include "cif++/CifUtils.hpp"
...
@@ -141,17 +141,31 @@ class Item
...
@@ -141,17 +141,31 @@ class Item
public
:
public
:
Item
()
{}
Item
()
{}
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
Item
(
const
std
::
string
&
name
,
const
T
&
value
)
Item
(
const
std
::
string
&
name
,
const
T
&
value
)
:
mName
(
name
),
mValue
(
std
::
to_string
(
value
))
{}
:
mName
(
name
)
,
mValue
(
std
::
to_string
(
value
))
{
}
Item
(
const
std
::
string
&
name
,
const
std
::
string
&
value
)
Item
(
const
std
::
string
&
name
,
const
std
::
string
&
value
)
:
mName
(
name
),
mValue
(
value
)
{}
:
mName
(
name
)
,
mValue
(
value
)
{
}
Item
(
const
Item
&
rhs
)
:
mName
(
rhs
.
mName
),
mValue
(
rhs
.
mValue
)
{}
Item
(
const
Item
&
rhs
)
Item
(
Item
&&
rhs
)
noexcept
:
mName
(
std
::
move
(
rhs
.
mName
)),
mValue
(
std
::
move
(
rhs
.
mValue
))
{}
:
mName
(
rhs
.
mName
)
,
mValue
(
rhs
.
mValue
)
{
}
Item
(
Item
&&
rhs
)
noexcept
:
mName
(
std
::
move
(
rhs
.
mName
))
,
mValue
(
std
::
move
(
rhs
.
mValue
))
{
}
Item
&
operator
=
(
const
Item
&
rhs
)
Item
&
operator
=
(
const
Item
&
rhs
)
{
{
if
(
this
!=
&
rhs
)
if
(
this
!=
&
rhs
)
{
{
...
@@ -162,7 +176,7 @@ class Item
...
@@ -162,7 +176,7 @@ class Item
return
*
this
;
return
*
this
;
}
}
Item
&
operator
=
(
Item
&&
rhs
)
noexcept
Item
&
operator
=
(
Item
&&
rhs
)
noexcept
{
{
if
(
this
!=
&
rhs
)
if
(
this
!=
&
rhs
)
{
{
...
@@ -173,10 +187,10 @@ class Item
...
@@ -173,10 +187,10 @@ class Item
return
*
this
;
return
*
this
;
}
}
const
std
::
string
&
name
()
const
{
return
mName
;
}
const
std
::
string
&
name
()
const
{
return
mName
;
}
const
std
::
string
&
value
()
const
{
return
mValue
;
}
const
std
::
string
&
value
()
const
{
return
mValue
;
}
void
value
(
const
std
::
string
&
v
)
{
mValue
=
v
;
}
void
value
(
const
std
::
string
&
v
)
{
mValue
=
v
;
}
// empty means either null or unknown
// empty means either null or unknown
bool
empty
()
const
;
bool
empty
()
const
;
...
@@ -188,7 +202,7 @@ class Item
...
@@ -188,7 +202,7 @@ class Item
bool
is_unknown
()
const
;
bool
is_unknown
()
const
;
size_t
length
()
const
{
return
mValue
.
length
();
}
size_t
length
()
const
{
return
mValue
.
length
();
}
const
char
*
c_str
()
const
{
return
mValue
.
c_str
();
}
const
char
*
c_str
()
const
{
return
mValue
.
c_str
();
}
private
:
private
:
std
::
string
mName
;
std
::
string
mName
;
...
@@ -207,16 +221,16 @@ class Datablock
...
@@ -207,16 +221,16 @@ class Datablock
using
iterator
=
CategoryList
::
iterator
;
using
iterator
=
CategoryList
::
iterator
;
using
const_iterator
=
CategoryList
::
const_iterator
;
using
const_iterator
=
CategoryList
::
const_iterator
;
Datablock
(
const
std
::
string
&
name
);
Datablock
(
const
std
::
string
&
name
);
~
Datablock
();
~
Datablock
();
Datablock
(
const
Datablock
&
)
=
delete
;
Datablock
(
const
Datablock
&
)
=
delete
;
Datablock
&
operator
=
(
const
Datablock
&
)
=
delete
;
Datablock
&
operator
=
(
const
Datablock
&
)
=
delete
;
std
::
string
getName
()
const
{
return
mName
;
}
std
::
string
getName
()
const
{
return
mName
;
}
void
setName
(
const
std
::
string
&
n
)
{
mName
=
n
;
}
void
setName
(
const
std
::
string
&
n
)
{
mName
=
n
;
}
std
::
string
firstItem
(
const
std
::
string
&
tag
)
const
;
std
::
string
firstItem
(
const
std
::
string
&
tag
)
const
;
iterator
begin
()
{
return
mCategories
.
begin
();
}
iterator
begin
()
{
return
mCategories
.
begin
();
}
iterator
end
()
{
return
mCategories
.
end
();
}
iterator
end
()
{
return
mCategories
.
end
();
}
...
@@ -224,32 +238,36 @@ class Datablock
...
@@ -224,32 +238,36 @@ class Datablock
const_iterator
begin
()
const
{
return
mCategories
.
begin
();
}
const_iterator
begin
()
const
{
return
mCategories
.
begin
();
}
const_iterator
end
()
const
{
return
mCategories
.
end
();
}
const_iterator
end
()
const
{
return
mCategories
.
end
();
}
Category
&
operator
[](
const
std
::
string
&
name
);
Category
&
operator
[](
const
std
::
string
&
name
);
std
::
tuple
<
iterator
,
bool
>
emplace
(
const
std
::
string
&
name
);
std
::
tuple
<
iterator
,
bool
>
emplace
(
const
std
::
string
&
name
);
bool
isValid
();
bool
isValid
();
void
validateLinks
()
const
;
void
validateLinks
()
const
;
void
setValidator
(
Validator
*
v
);
void
setValidator
(
Validator
*
v
);
// this one only looks up a Category, returns nullptr if it does not exist
// this one only looks up a Category, returns nullptr if it does not exist
Category
*
get
(
const
std
::
string
&
name
);
const
Category
*
get
(
const
std
::
string
&
name
)
const
;
Category
*
get
(
const
std
::
string
&
name
);
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
order
);
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
);
void
write
(
std
::
ostream
&
os
);
void
write
(
std
::
ostream
&
os
);
// convenience function, add a line to the software category
// convenience function, add a line to the software category
void
add_software
(
const
std
::
string
&
name
,
const
std
::
string
&
classification
,
void
add_software
(
const
std
::
string
&
name
,
const
std
::
string
&
classification
,
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
);
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
);
private
:
friend
bool
operator
==
(
const
Datablock
&
lhs
,
const
Datablock
&
rhs
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Datablock
&
data
);
private
:
std
::
list
<
Category
>
mCategories
;
std
::
list
<
Category
>
mCategories
;
std
::
string
mName
;
std
::
string
mName
;
Validator
*
mValidator
;
Validator
*
mValidator
;
Datablock
*
mNext
;
Datablock
*
mNext
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -264,20 +282,19 @@ namespace detail
...
@@ -264,20 +282,19 @@ namespace detail
class
ItemReference
class
ItemReference
{
{
public
:
public
:
// conversion helper class
// conversion helper class
template
<
typename
T
,
typename
=
void
>
template
<
typename
T
,
typename
=
void
>
struct
item_value_as
;
struct
item_value_as
;
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
ItemReference
&
operator
=
(
const
T
&
value
)
ItemReference
&
operator
=
(
const
T
&
value
)
{
{
this
->
operator
=
(
std
::
to_string
(
value
));
this
->
operator
=
(
std
::
to_string
(
value
));
return
*
this
;
return
*
this
;
}
}
template
<
typename
T
>
template
<
typename
T
>
ItemReference
&
operator
=
(
const
std
::
optional
<
T
>&
value
)
ItemReference
&
operator
=
(
const
std
::
optional
<
T
>
&
value
)
{
{
if
(
value
)
if
(
value
)
this
->
operator
=
(
*
value
);
this
->
operator
=
(
*
value
);
...
@@ -286,27 +303,27 @@ namespace detail
...
@@ -286,27 +303,27 @@ namespace detail
return
*
this
;
return
*
this
;
}
}
ItemReference
&
operator
=
(
const
std
::
string
&
value
);
ItemReference
&
operator
=
(
const
std
::
string
&
value
);
template
<
typename
...
Ts
>
template
<
typename
...
Ts
>
void
os
(
const
Ts
&
...
v
)
void
os
(
const
Ts
&
...
v
)
{
{
std
::
ostringstream
ss
;
std
::
ostringstream
ss
;
((
ss
<<
v
),
...);
((
ss
<<
v
),
...);
this
->
operator
=
(
ss
.
str
());
this
->
operator
=
(
ss
.
str
());
}
}
void
swap
(
ItemReference
&
b
);
void
swap
(
ItemReference
&
b
);
template
<
typename
T
=
std
::
string
>
template
<
typename
T
=
std
::
string
>
auto
as
()
const
auto
as
()
const
{
{
using
value_type
=
std
::
remove_cv_t
<
std
::
remove_reference_t
<
T
>>
;
using
value_type
=
std
::
remove_cv_t
<
std
::
remove_reference_t
<
T
>>
;
return
item_value_as
<
value_type
>::
convert
(
*
this
);
return
item_value_as
<
value_type
>::
convert
(
*
this
);
}
}
template
<
typename
T
>
template
<
typename
T
>
int
compare
(
const
T
&
value
,
bool
icase
)
const
int
compare
(
const
T
&
value
,
bool
icase
)
const
{
{
return
item_value_as
<
T
>::
compare
(
*
this
,
value
,
icase
);
return
item_value_as
<
T
>::
compare
(
*
this
,
value
,
icase
);
}
}
...
@@ -321,36 +338,45 @@ namespace detail
...
@@ -321,36 +338,45 @@ namespace detail
// is_unknown means the field contains '?'
// is_unknown means the field contains '?'
bool
is_unknown
()
const
;
bool
is_unknown
()
const
;
const
char
*
c_str
()
const
;
const
char
*
c_str
()
const
;
// the following returns the defaultValue from either the parameter
// the following returns the defaultValue from either the parameter
// or, if specified, the value from _item_default.value in the dictionary
// or, if specified, the value from _item_default.value in the dictionary
const
char
*
c_str
(
const
char
*
defaultValue
)
const
;
const
char
*
c_str
(
const
char
*
defaultValue
)
const
;
bool
operator
!=
(
const
std
::
string
&
s
)
const
{
return
s
!=
c_str
();
}
bool
operator
!=
(
const
std
::
string
&
s
)
const
{
return
s
!=
c_str
();
}
bool
operator
==
(
const
std
::
string
&
s
)
const
{
return
s
==
c_str
();
}
bool
operator
==
(
const
std
::
string
&
s
)
const
{
return
s
==
c_str
();
}
private
:
private
:
friend
class
::
cif
::
Row
;
friend
class
::
cif
::
Row
;
ItemReference
(
const
char
*
name
,
size_t
column
,
Row
&
row
)
ItemReference
(
const
char
*
name
,
size_t
column
,
Row
&
row
)
:
mName
(
name
),
mColumn
(
column
),
mRow
(
row
)
{}
:
mName
(
name
)
,
mColumn
(
column
)
,
mRow
(
row
)
{
}
ItemReference
(
const
char
*
name
,
size_t
column
,
const
Row
&
row
)
ItemReference
(
const
char
*
name
,
size_t
column
,
const
Row
&
row
)
:
mName
(
name
),
mColumn
(
column
),
mRow
(
const_cast
<
Row
&>
(
row
)),
mConst
(
true
)
{}
:
mName
(
name
)
,
mColumn
(
column
)
,
mRow
(
const_cast
<
Row
&>
(
row
))
,
mConst
(
true
)
{
}
const
char
*
mName
;
const
char
*
mName
;
size_t
mColumn
;
size_t
mColumn
;
Row
&
mRow
;
Row
&
mRow
;
bool
mConst
=
false
;
bool
mConst
=
false
;
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
ItemReference
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_floating_point_v
<
T
>>>
struct
ItemReference
::
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
>>
;
using
value_type
=
std
::
remove_reference_t
<
std
::
remove_cv_t
<
T
>>
;
static
value_type
convert
(
const
ItemReference
&
ref
)
static
value_type
convert
(
const
ItemReference
&
ref
)
{
{
value_type
result
=
{};
value_type
result
=
{};
if
(
not
ref
.
empty
())
if
(
not
ref
.
empty
())
...
@@ -358,11 +384,11 @@ namespace detail
...
@@ -358,11 +384,11 @@ namespace detail
return
result
;
return
result
;
}
}
static
int
compare
(
const
ItemReference
&
ref
,
double
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
double
value
,
bool
icase
)
{
{
int
result
=
0
;
int
result
=
0
;
const
char
*
s
=
ref
.
c_str
();
const
char
*
s
=
ref
.
c_str
();
if
(
s
==
nullptr
or
*
s
==
0
)
if
(
s
==
nullptr
or
*
s
==
0
)
result
=
1
;
result
=
1
;
...
@@ -388,10 +414,10 @@ namespace detail
...
@@ -388,10 +414,10 @@ namespace detail
}
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
ItemReference
::
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
>>>
struct
ItemReference
::
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
ItemReference
&
ref
)
static
T
convert
(
const
ItemReference
&
ref
)
{
{
T
result
=
{};
T
result
=
{};
if
(
not
ref
.
empty
())
if
(
not
ref
.
empty
())
...
@@ -399,11 +425,11 @@ namespace detail
...
@@ -399,11 +425,11 @@ namespace detail
return
result
;
return
result
;
}
}
static
int
compare
(
const
ItemReference
&
ref
,
unsigned
long
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
unsigned
long
value
,
bool
icase
)
{
{
int
result
=
0
;
int
result
=
0
;
const
char
*
s
=
ref
.
c_str
();
const
char
*
s
=
ref
.
c_str
();
if
(
s
==
nullptr
or
*
s
==
0
)
if
(
s
==
nullptr
or
*
s
==
0
)
result
=
1
;
result
=
1
;
...
@@ -429,10 +455,10 @@ namespace detail
...
@@ -429,10 +455,10 @@ namespace detail
}
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
ItemReference
::
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
>>>
struct
ItemReference
::
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
ItemReference
&
ref
)
static
T
convert
(
const
ItemReference
&
ref
)
{
{
T
result
=
{};
T
result
=
{};
if
(
not
ref
.
empty
())
if
(
not
ref
.
empty
())
...
@@ -440,11 +466,11 @@ namespace detail
...
@@ -440,11 +466,11 @@ namespace detail
return
result
;
return
result
;
}
}
static
int
compare
(
const
ItemReference
&
ref
,
long
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
long
value
,
bool
icase
)
{
{
int
result
=
0
;
int
result
=
0
;
const
char
*
s
=
ref
.
c_str
();
const
char
*
s
=
ref
.
c_str
();
if
(
s
==
nullptr
or
*
s
==
0
)
if
(
s
==
nullptr
or
*
s
==
0
)
result
=
1
;
result
=
1
;
...
@@ -470,10 +496,10 @@ namespace detail
...
@@ -470,10 +496,10 @@ namespace detail
}
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
ItemReference
::
item_value_as
<
std
::
optional
<
T
>>
struct
ItemReference
::
item_value_as
<
std
::
optional
<
T
>>
{
{
static
std
::
optional
<
T
>
convert
(
const
ItemReference
&
ref
)
static
std
::
optional
<
T
>
convert
(
const
ItemReference
&
ref
)
{
{
std
::
optional
<
T
>
result
;
std
::
optional
<
T
>
result
;
if
(
ref
)
if
(
ref
)
...
@@ -481,7 +507,7 @@ namespace detail
...
@@ -481,7 +507,7 @@ namespace detail
return
result
;
return
result
;
}
}
static
int
compare
(
const
ItemReference
&
ref
,
std
::
optional
<
T
>
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
std
::
optional
<
T
>
value
,
bool
icase
)
{
{
if
(
ref
.
empty
()
and
not
value
)
if
(
ref
.
empty
()
and
not
value
)
return
0
;
return
0
;
...
@@ -495,10 +521,10 @@ namespace detail
...
@@ -495,10 +521,10 @@ namespace detail
}
}
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
ItemReference
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_same_v
<
T
,
bool
>>>
struct
ItemReference
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_same_v
<
T
,
bool
>>>
{
{
static
bool
convert
(
const
ItemReference
&
ref
)
static
bool
convert
(
const
ItemReference
&
ref
)
{
{
bool
result
=
false
;
bool
result
=
false
;
if
(
not
ref
.
empty
())
if
(
not
ref
.
empty
())
...
@@ -506,7 +532,7 @@ namespace detail
...
@@ -506,7 +532,7 @@ namespace detail
return
result
;
return
result
;
}
}
static
int
compare
(
const
ItemReference
&
ref
,
bool
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
bool
value
,
bool
icase
)
{
{
bool
rv
=
convert
(
ref
);
bool
rv
=
convert
(
ref
);
return
value
&&
rv
?
0
return
value
&&
rv
?
0
...
@@ -514,51 +540,52 @@ namespace detail
...
@@ -514,51 +540,52 @@ namespace detail
}
}
};
};
template
<
size_t
N
>
template
<
size_t
N
>
struct
ItemReference
::
item_value_as
<
char
[
N
]
>
struct
ItemReference
::
item_value_as
<
char
[
N
]
>
{
{
static
int
compare
(
const
ItemReference
&
ref
,
const
char
(
&
value
)[
N
],
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
const
char
(
&
value
)[
N
],
bool
icase
)
{
{
return
icase
?
cif
::
icompare
(
ref
.
c_str
(),
value
)
:
std
::
strcmp
(
ref
.
c_str
(),
value
);
return
icase
?
cif
::
icompare
(
ref
.
c_str
(),
value
)
:
std
::
strcmp
(
ref
.
c_str
(),
value
);
}
}
};
};
template
<>
template
<>
struct
ItemReference
::
item_value_as
<
const
char
*>
struct
ItemReference
::
item_value_as
<
const
char
*>
{
{
static
const
char
*
convert
(
const
ItemReference
&
ref
)
static
const
char
*
convert
(
const
ItemReference
&
ref
)
{
{
return
ref
.
c_str
();
return
ref
.
c_str
();
}
}
static
int
compare
(
const
ItemReference
&
ref
,
const
char
*
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
const
char
*
value
,
bool
icase
)
{
{
return
icase
?
cif
::
icompare
(
ref
.
c_str
(),
value
)
:
std
::
strcmp
(
ref
.
c_str
(),
value
);
return
icase
?
cif
::
icompare
(
ref
.
c_str
(),
value
)
:
std
::
strcmp
(
ref
.
c_str
(),
value
);
}
}
};
};
template
<>
template
<>
struct
ItemReference
::
item_value_as
<
std
::
string
>
struct
ItemReference
::
item_value_as
<
std
::
string
>
{
{
static
std
::
string
convert
(
const
ItemReference
&
ref
)
static
std
::
string
convert
(
const
ItemReference
&
ref
)
{
{
return
ref
.
c_str
();
return
ref
.
c_str
();
}
}
static
int
compare
(
const
ItemReference
&
ref
,
const
std
::
string
&
value
,
bool
icase
)
static
int
compare
(
const
ItemReference
&
ref
,
const
std
::
string
&
value
,
bool
icase
)
{
{
return
icase
?
cif
::
icompare
(
ref
.
c_str
(),
value
)
:
std
::
strcmp
(
ref
.
c_str
(),
value
.
c_str
());
return
icase
?
cif
::
icompare
(
ref
.
c_str
(),
value
)
:
std
::
strcmp
(
ref
.
c_str
(),
value
.
c_str
());
}
}
};
};
// some helper classes to help create tuple result types
// some helper classes to help create tuple result types
template
<
typename
...
C
>
template
<
typename
...
C
>
struct
getRowResult
struct
getRowResult
{
{
static
constexpr
size_t
N
=
sizeof
...(
C
);
static
constexpr
size_t
N
=
sizeof
...(
C
);
getRowResult
(
const
Row
&
r
,
std
::
array
<
size_t
,
N
>&&
columns
)
getRowResult
(
const
Row
&
r
,
std
::
array
<
size_t
,
N
>
&&
columns
)
:
mRow
(
r
),
mColumns
(
std
::
move
(
columns
))
:
mRow
(
r
)
,
mColumns
(
std
::
move
(
columns
))
{
{
}
}
...
@@ -567,30 +594,33 @@ namespace detail
...
@@ -567,30 +594,33 @@ namespace detail
return
mRow
[
mColumns
[
ix
]];
return
mRow
[
mColumns
[
ix
]];
}
}
template
<
typename
...
Ts
,
std
::
enable_if_t
<
N
==
sizeof
...(
Ts
),
int
>
=
0
>
template
<
typename
...
Ts
,
std
::
enable_if_t
<
N
==
sizeof
...(
Ts
),
int
>
=
0
>
operator
std
::
tuple
<
Ts
...
>
()
const
operator
std
::
tuple
<
Ts
...
>
()
const
{
{
return
get
<
Ts
...
>
(
std
::
index_sequence_for
<
Ts
...
>
{});
return
get
<
Ts
...
>
(
std
::
index_sequence_for
<
Ts
...
>
{});
}
}
template
<
typename
...
Ts
,
std
::
size_t
...
Is
>
template
<
typename
...
Ts
,
std
::
size_t
...
Is
>
std
::
tuple
<
Ts
...
>
get
(
std
::
index_sequence
<
Is
...
>
)
const
std
::
tuple
<
Ts
...
>
get
(
std
::
index_sequence
<
Is
...
>
)
const
{
{
return
std
::
tuple
<
Ts
...
>
{
mRow
[
mColumns
[
Is
]].
template
as
<
Ts
>
()...};
return
std
::
tuple
<
Ts
...
>
{
mRow
[
mColumns
[
Is
]].
template
as
<
Ts
>
()...};
}
}
const
Row
&
mRow
;
const
Row
&
mRow
;
std
::
array
<
size_t
,
N
>
mColumns
;
std
::
array
<
size_t
,
N
>
mColumns
;
};
};
// we want to be able to tie some variables to a RowResult, for this we use tiewraps
// we want to be able to tie some variables to a RowResult, for this we use tiewraps
template
<
typename
...
Ts
>
template
<
typename
...
Ts
>
struct
tieWrap
struct
tieWrap
{
{
tieWrap
(
Ts
...
args
)
:
mVal
(
args
...)
{}
tieWrap
(
Ts
...
args
)
:
mVal
(
args
...)
{
}
template
<
typename
RR
>
template
<
typename
RR
>
void
operator
=
(
const
RR
&&
rr
)
void
operator
=
(
const
RR
&&
rr
)
{
{
// getRowResult will do the conversion, but only if the types
// getRowResult will do the conversion, but only if the types
// are compatible. That means the number of parameters to the get()
// are compatible. That means the number of parameters to the get()
...
@@ -604,12 +634,12 @@ namespace detail
...
@@ -604,12 +634,12 @@ namespace detail
std
::
tuple
<
Ts
...
>
mVal
;
std
::
tuple
<
Ts
...
>
mVal
;
};
};
}
}
// namespace detail
template
<
typename
...
Ts
>
template
<
typename
...
Ts
>
auto
tie
(
Ts
&
...
v
)
auto
tie
(
Ts
&
...
v
)
{
{
return
detail
::
tieWrap
<
Ts
&
...
>
(
std
::
forward
<
Ts
&>
(
v
)...);
return
detail
::
tieWrap
<
Ts
&
...
>
(
std
::
forward
<
Ts
&>
(
v
)...);
}
}
class
Row
class
Row
...
@@ -622,19 +652,26 @@ class Row
...
@@ -622,19 +652,26 @@ class Row
friend
class
RowSet
;
friend
class
RowSet
;
Row
()
Row
()
:
mData
(
nullptr
)
{}
:
mData
(
nullptr
)
{
}
Row
(
ItemRow
*
data
)
Row
(
ItemRow
*
data
)
:
mData
(
data
)
{}
:
mData
(
data
)
{
}
Row
(
const
ItemRow
*
data
)
Row
(
const
ItemRow
*
data
)
:
mData
(
const_cast
<
ItemRow
*>
(
data
)),
mCascade
(
false
)
{}
:
mData
(
const_cast
<
ItemRow
*>
(
data
))
,
mCascade
(
false
)
{
}
Row
(
const
Row
&
rhs
);
Row
(
const
Row
&
rhs
);
Row
&
operator
=
(
const
Row
&
rhs
);
Row
&
operator
=
(
const
Row
&
rhs
);
Row
(
Row
&&
rhs
);
Row
(
Row
&&
rhs
);
Row
&
operator
=
(
Row
&&
rhs
);
Row
&
operator
=
(
Row
&&
rhs
);
~
Row
();
~
Row
();
...
@@ -650,26 +687,30 @@ class Row
...
@@ -650,26 +687,30 @@ class Row
using
iterator_category
=
std
::
forward_iterator_tag
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
value_type
=
const
Item
;
using
value_type
=
const
Item
;
using
difference_type
=
std
::
ptrdiff_t
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
using
reference
=
value_type
&
;
const_iterator
(
ItemRow
*
data
,
ItemValue
*
ptr
);
const_iterator
(
ItemRow
*
data
,
ItemValue
*
ptr
);
reference
operator
*
()
{
return
mCurrent
;
}
reference
operator
*
()
{
return
mCurrent
;
}
pointer
operator
->
()
{
return
&
mCurrent
;
}
pointer
operator
->
()
{
return
&
mCurrent
;
}
const_iterator
&
operator
++
();
const_iterator
&
operator
++
();
const_iterator
operator
++
(
int
)
{
const_iterator
result
(
*
this
);
this
->
operator
++
();
return
result
;
}
const_iterator
operator
++
(
int
)
{
const_iterator
result
(
*
this
);
this
->
operator
++
();
return
result
;
}
bool
operator
==
(
const
const_iterator
&
rhs
)
const
{
return
mPtr
==
rhs
.
mPtr
;
}
bool
operator
==
(
const
const_iterator
&
rhs
)
const
{
return
mPtr
==
rhs
.
mPtr
;
}
bool
operator
!=
(
const
const_iterator
&
rhs
)
const
{
return
mPtr
!=
rhs
.
mPtr
;
}
bool
operator
!=
(
const
const_iterator
&
rhs
)
const
{
return
mPtr
!=
rhs
.
mPtr
;
}
private
:
private
:
void
fetch
();
void
fetch
();
ItemRow
*
mData
;
ItemRow
*
mData
;
ItemValue
*
mPtr
;
ItemValue
*
mPtr
;
Item
mCurrent
;
Item
mCurrent
;
};
};
...
@@ -693,32 +734,32 @@ class Row
...
@@ -693,32 +734,32 @@ class Row
return
detail
::
ItemReference
(
"<anonymous column>"
,
column
,
*
this
);
return
detail
::
ItemReference
(
"<anonymous column>"
,
column
,
*
this
);
}
}
const
detail
::
ItemReference
operator
[](
const
char
*
itemTag
)
const
const
detail
::
ItemReference
operator
[](
const
char
*
itemTag
)
const
{
{
size_t
column
=
ColumnForItemTag
(
itemTag
);
size_t
column
=
ColumnForItemTag
(
itemTag
);
return
detail
::
ItemReference
(
itemTag
,
column
,
*
this
);
return
detail
::
ItemReference
(
itemTag
,
column
,
*
this
);
}
}
detail
::
ItemReference
operator
[](
const
char
*
itemTag
)
detail
::
ItemReference
operator
[](
const
char
*
itemTag
)
{
{
size_t
column
=
ColumnForItemTag
(
itemTag
);
size_t
column
=
ColumnForItemTag
(
itemTag
);
return
detail
::
ItemReference
(
itemTag
,
column
,
*
this
);
return
detail
::
ItemReference
(
itemTag
,
column
,
*
this
);
}
}
const
detail
::
ItemReference
operator
[](
const
std
::
string
&
itemTag
)
const
const
detail
::
ItemReference
operator
[](
const
std
::
string
&
itemTag
)
const
{
{
size_t
column
=
ColumnForItemTag
(
itemTag
.
c_str
());
size_t
column
=
ColumnForItemTag
(
itemTag
.
c_str
());
return
detail
::
ItemReference
(
itemTag
.
c_str
(),
column
,
*
this
);
return
detail
::
ItemReference
(
itemTag
.
c_str
(),
column
,
*
this
);
}
}
detail
::
ItemReference
operator
[](
const
std
::
string
&
itemTag
)
detail
::
ItemReference
operator
[](
const
std
::
string
&
itemTag
)
{
{
size_t
column
=
ColumnForItemTag
(
itemTag
.
c_str
());
size_t
column
=
ColumnForItemTag
(
itemTag
.
c_str
());
return
detail
::
ItemReference
(
itemTag
.
c_str
(),
column
,
*
this
);
return
detail
::
ItemReference
(
itemTag
.
c_str
(),
column
,
*
this
);
}
}
template
<
typename
...
Ts
,
size_t
N
>
template
<
typename
...
Ts
,
size_t
N
>
std
::
tuple
<
Ts
...
>
get
(
char
const
*
const
(
&
columns
)[
N
])
const
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"
);
static_assert
(
sizeof
...(
Ts
)
==
N
,
"Number of columns should be equal to number of types to return"
);
...
@@ -728,44 +769,43 @@ class Row
...
@@ -728,44 +769,43 @@ class Row
return
detail
::
getRowResult
<
Ts
...
>
(
*
this
,
std
::
move
(
cix
));
return
detail
::
getRowResult
<
Ts
...
>
(
*
this
,
std
::
move
(
cix
));
}
}
template
<
typename
...
C
>
template
<
typename
...
C
>
auto
get
(
C
...
columns
)
const
auto
get
(
C
...
columns
)
const
{
{
return
detail
::
getRowResult
<
C
...
>
(
*
this
,
{
ColumnForItemTag
(
columns
)...
});
return
detail
::
getRowResult
<
C
...
>
(
*
this
,
{
ColumnForItemTag
(
columns
)...
});
}
}
void
assign
(
const
std
::
vector
<
Item
>
&
values
);
void
assign
(
const
std
::
vector
<
Item
>
&
values
);
void
assign
(
const
std
::
string
&
name
,
const
std
::
string
&
value
,
bool
updateLinked
);
void
assign
(
const
std
::
string
&
name
,
const
std
::
string
&
value
,
bool
updateLinked
);
bool
operator
==
(
const
Row
&
rhs
)
const
bool
operator
==
(
const
Row
&
rhs
)
const
{
{
return
mData
==
rhs
.
mData
;
return
mData
==
rhs
.
mData
;
}
}
bool
operator
!=
(
const
Row
&
rhs
)
const
bool
operator
!=
(
const
Row
&
rhs
)
const
{
{
return
mData
!=
rhs
.
mData
;
return
mData
!=
rhs
.
mData
;
}
}
ItemRow
*
data
()
const
{
return
mData
;
}
ItemRow
*
data
()
const
{
return
mData
;
}
void
swap
(
Row
&
rhs
)
void
swap
(
Row
&
rhs
)
{
{
std
::
swap
(
mData
,
rhs
.
mData
);
std
::
swap
(
mData
,
rhs
.
mData
);
}
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Row
&
row
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Row
&
row
);
private
:
private
:
void
assign
(
size_t
column
,
const
std
::
string
&
value
,
bool
updateLinked
);
void
assign
(
const
Item
&
i
,
bool
updateLinked
);
void
assign
(
size_t
column
,
const
std
::
string
&
value
,
bool
updateLinked
);
static
void
swap
(
size_t
column
,
ItemRow
*
a
,
ItemRow
*
b
);
void
assign
(
const
Item
&
i
,
bool
updateLinked
);
s
tatic
void
swap
(
size_t
column
,
ItemRow
*
a
,
ItemRow
*
b
)
;
s
ize_t
ColumnForItemTag
(
const
char
*
itemTag
)
const
;
size_t
ColumnForItemTag
(
const
char
*
itemTag
)
const
;
ItemRow
*
mData
;
ItemRow
*
mData
;
uint32_t
mLineNr
=
0
;
uint32_t
mLineNr
=
0
;
bool
mCascade
=
true
;
bool
mCascade
=
true
;
};
};
...
@@ -776,45 +816,50 @@ class Row
...
@@ -776,45 +816,50 @@ class Row
namespace
detail
namespace
detail
{
{
struct
ConditionImpl
struct
ConditionImpl
{
{
virtual
~
ConditionImpl
()
{}
virtual
~
ConditionImpl
()
{}
virtual
void
prepare
(
const
Category
&
c
)
{}
virtual
void
prepare
(
const
Category
&
c
)
{}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
=
0
;
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
=
0
;
virtual
void
str
(
std
::
ostream
&
os
)
const
=
0
;
virtual
void
str
(
std
::
ostream
&
os
)
const
=
0
;
};
};
struct
AllConditionImpl
:
public
ConditionImpl
struct
AllConditionImpl
:
public
ConditionImpl
{
{
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
return
true
;
}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
return
true
;
}
virtual
void
str
(
std
::
ostream
&
os
)
const
{
os
<<
"*"
;
}
virtual
void
str
(
std
::
ostream
&
os
)
const
{
os
<<
"*"
;
}
};
};
struct
OrConditionImpl
;
struct
OrConditionImpl
;
struct
AndConditionImpl
;
struct
AndConditionImpl
;
struct
NotConditionImpl
;
struct
NotConditionImpl
;
}
}
// namespace detail
class
Condition
class
Condition
{
{
public
:
public
:
Condition
()
:
mImpl
(
nullptr
)
{
}
Condition
(
detail
::
ConditionImpl
*
impl
)
:
mImpl
(
impl
)
{
}
Condition
()
:
mImpl
(
nullptr
)
{}
Condition
(
const
Condition
&
)
=
delete
;
Condition
(
detail
::
ConditionImpl
*
impl
)
:
mImpl
(
impl
)
{}
Condition
(
const
Condition
&
)
=
delete
;
Condition
(
Condition
&&
rhs
)
noexcept
Condition
(
Condition
&&
rhs
)
noexcept
:
mImpl
(
nullptr
)
:
mImpl
(
nullptr
)
{
{
std
::
swap
(
mImpl
,
rhs
.
mImpl
);
std
::
swap
(
mImpl
,
rhs
.
mImpl
);
}
}
Condition
&
operator
=
(
const
Condition
&
)
=
delete
;
Condition
&
operator
=
(
const
Condition
&
)
=
delete
;
Condition
&
operator
=
(
Condition
&&
rhs
)
noexcept
Condition
&
operator
=
(
Condition
&&
rhs
)
noexcept
{
{
std
::
swap
(
mImpl
,
rhs
.
mImpl
);
std
::
swap
(
mImpl
,
rhs
.
mImpl
);
return
*
this
;
return
*
this
;
...
@@ -826,14 +871,14 @@ class Condition
...
@@ -826,14 +871,14 @@ class Condition
mImpl
=
nullptr
;
mImpl
=
nullptr
;
}
}
void
prepare
(
const
Category
&
c
)
void
prepare
(
const
Category
&
c
)
{
{
if
(
mImpl
)
if
(
mImpl
)
mImpl
->
prepare
(
c
);
mImpl
->
prepare
(
c
);
mPrepared
=
true
;
mPrepared
=
true
;
}
}
bool
operator
()(
const
Category
&
c
,
const
Row
&
r
)
const
bool
operator
()(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
assert
(
mImpl
);
assert
(
mImpl
);
assert
(
mPrepared
);
assert
(
mPrepared
);
...
@@ -842,27 +887,27 @@ class Condition
...
@@ -842,27 +887,27 @@ class Condition
bool
empty
()
const
{
return
mImpl
==
nullptr
;
}
bool
empty
()
const
{
return
mImpl
==
nullptr
;
}
friend
Condition
operator
||
(
Condition
&&
a
,
Condition
&&
b
);
friend
Condition
operator
||
(
Condition
&&
a
,
Condition
&&
b
);
friend
Condition
operator
&&
(
Condition
&&
a
,
Condition
&&
b
);
friend
Condition
operator
&&
(
Condition
&&
a
,
Condition
&&
b
);
friend
struct
detail
::
OrConditionImpl
;
friend
struct
detail
::
OrConditionImpl
;
friend
struct
detail
::
AndConditionImpl
;
friend
struct
detail
::
AndConditionImpl
;
friend
struct
detail
::
NotConditionImpl
;
friend
struct
detail
::
NotConditionImpl
;
void
swap
(
Condition
&
rhs
)
void
swap
(
Condition
&
rhs
)
{
{
std
::
swap
(
mImpl
,
rhs
.
mImpl
);
std
::
swap
(
mImpl
,
rhs
.
mImpl
);
std
::
swap
(
mPrepared
,
rhs
.
mPrepared
);
std
::
swap
(
mPrepared
,
rhs
.
mPrepared
);
}
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Condition
&
cond
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Condition
&
cond
);
private
:
private
:
detail
::
ConditionImpl
*
mImpl
;
detail
::
ConditionImpl
*
mImpl
;
bool
mPrepared
=
false
;
bool
mPrepared
=
false
;
};
};
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Condition
&
cond
)
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Condition
&
cond
)
{
{
if
(
cond
.
mImpl
)
if
(
cond
.
mImpl
)
cond
.
mImpl
->
str
(
os
);
cond
.
mImpl
->
str
(
os
);
...
@@ -872,41 +917,47 @@ inline std::ostream& operator<<(std::ostream& os, const Condition& cond)
...
@@ -872,41 +917,47 @@ inline std::ostream& operator<<(std::ostream& os, const Condition& cond)
namespace
detail
namespace
detail
{
{
struct
KeyIsEmptyConditionImpl
:
public
ConditionImpl
struct
KeyIsEmptyConditionImpl
:
public
ConditionImpl
{
{
KeyIsEmptyConditionImpl
(
const
std
::
string
&
ItemTag
)
KeyIsEmptyConditionImpl
(
const
std
::
string
&
ItemTag
)
:
mItemTag
(
ItemTag
)
{}
:
mItemTag
(
ItemTag
)
{
}
virtual
void
prepare
(
const
Category
&
c
);
virtual
void
prepare
(
const
Category
&
c
);
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
return
r
[
mItemIx
].
empty
();
return
r
[
mItemIx
].
empty
();
}
}
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
mItemTag
<<
" IS NULL"
;
os
<<
mItemTag
<<
" IS NULL"
;
}
}
std
::
string
mItemTag
;
std
::
string
mItemTag
;
size_t
mItemIx
=
0
;
size_t
mItemIx
=
0
;
};
};
struct
KeyCompareConditionImpl
:
public
ConditionImpl
struct
KeyCompareConditionImpl
:
public
ConditionImpl
{
{
template
<
typename
COMP
>
template
<
typename
COMP
>
KeyCompareConditionImpl
(
const
std
::
string
&
ItemTag
,
COMP
&&
comp
,
const
std
::
string
&
s
)
KeyCompareConditionImpl
(
const
std
::
string
&
ItemTag
,
COMP
&&
comp
,
const
std
::
string
&
s
)
:
mItemTag
(
ItemTag
),
mComp
(
std
::
move
(
comp
)),
mStr
(
s
)
{}
:
mItemTag
(
ItemTag
)
,
mComp
(
std
::
move
(
comp
))
,
mStr
(
s
)
{
}
virtual
void
prepare
(
const
Category
&
c
);
virtual
void
prepare
(
const
Category
&
c
);
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
return
mComp
(
c
,
r
,
mCaseInsensitive
);
return
mComp
(
c
,
r
,
mCaseInsensitive
);
}
}
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
mItemTag
<<
(
mCaseInsensitive
?
"^ "
:
" "
)
<<
mStr
;
os
<<
mItemTag
<<
(
mCaseInsensitive
?
"^ "
:
" "
)
<<
mStr
;
}
}
...
@@ -914,23 +965,27 @@ struct KeyCompareConditionImpl : public ConditionImpl
...
@@ -914,23 +965,27 @@ struct KeyCompareConditionImpl : public ConditionImpl
std
::
string
mItemTag
;
std
::
string
mItemTag
;
size_t
mItemIx
=
0
;
size_t
mItemIx
=
0
;
bool
mCaseInsensitive
=
false
;
bool
mCaseInsensitive
=
false
;
std
::
function
<
bool
(
const
Category
&
,
const
Row
&
,
bool
)
>
mComp
;
std
::
function
<
bool
(
const
Category
&
,
const
Row
&
,
bool
)
>
mComp
;
std
::
string
mStr
;
std
::
string
mStr
;
};
};
struct
KeyMatchesConditionImpl
:
public
ConditionImpl
struct
KeyMatchesConditionImpl
:
public
ConditionImpl
{
{
KeyMatchesConditionImpl
(
const
std
::
string
&
ItemTag
,
const
std
::
regex
&
rx
)
KeyMatchesConditionImpl
(
const
std
::
string
&
ItemTag
,
const
std
::
regex
&
rx
)
:
mItemTag
(
ItemTag
),
mItemIx
(
0
),
mRx
(
rx
)
{}
:
mItemTag
(
ItemTag
)
,
mItemIx
(
0
)
,
mRx
(
rx
)
{
}
virtual
void
prepare
(
const
Category
&
c
);
virtual
void
prepare
(
const
Category
&
c
);
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
return
std
::
regex_match
(
r
[
mItemIx
].
as
<
std
::
string
>
(),
mRx
);
return
std
::
regex_match
(
r
[
mItemIx
].
as
<
std
::
string
>
(),
mRx
);
}
}
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
mItemTag
<<
" =~ expression"
;
os
<<
mItemTag
<<
" =~ expression"
;
}
}
...
@@ -938,43 +993,48 @@ struct KeyMatchesConditionImpl : public ConditionImpl
...
@@ -938,43 +993,48 @@ struct KeyMatchesConditionImpl : public ConditionImpl
std
::
string
mItemTag
;
std
::
string
mItemTag
;
size_t
mItemIx
;
size_t
mItemIx
;
std
::
regex
mRx
;
std
::
regex
mRx
;
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
AnyIsConditionImpl
:
public
ConditionImpl
struct
AnyIsConditionImpl
:
public
ConditionImpl
{
{
typedef
T
valueType
;
typedef
T
valueType
;
AnyIsConditionImpl
(
const
valueType
&
value
)
AnyIsConditionImpl
(
const
valueType
&
value
)
:
mValue
(
value
)
{}
:
mValue
(
value
)
{
}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
;
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
;
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
"<any> == "
<<
mValue
;
os
<<
"<any> == "
<<
mValue
;
}
}
valueType
mValue
;
valueType
mValue
;
};
};
struct
AnyMatchesConditionImpl
:
public
ConditionImpl
struct
AnyMatchesConditionImpl
:
public
ConditionImpl
{
{
AnyMatchesConditionImpl
(
const
std
::
regex
&
rx
)
AnyMatchesConditionImpl
(
const
std
::
regex
&
rx
)
:
mRx
(
rx
)
{}
:
mRx
(
rx
)
{
}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
;
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
;
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
"<any> =~ expression"
;
os
<<
"<any> =~ expression"
;
}
}
std
::
regex
mRx
;
std
::
regex
mRx
;
};
};
struct
AndConditionImpl
:
public
ConditionImpl
struct
AndConditionImpl
:
public
ConditionImpl
{
{
AndConditionImpl
(
Condition
&&
a
,
Condition
&&
b
)
AndConditionImpl
(
Condition
&&
a
,
Condition
&&
b
)
:
mA
(
nullptr
),
mB
(
nullptr
)
:
mA
(
nullptr
)
,
mB
(
nullptr
)
{
{
std
::
swap
(
mA
,
a
.
mImpl
);
std
::
swap
(
mA
,
a
.
mImpl
);
std
::
swap
(
mB
,
b
.
mImpl
);
std
::
swap
(
mB
,
b
.
mImpl
);
...
@@ -986,18 +1046,18 @@ struct AndConditionImpl : public ConditionImpl
...
@@ -986,18 +1046,18 @@ struct AndConditionImpl : public ConditionImpl
delete
mB
;
delete
mB
;
}
}
virtual
void
prepare
(
const
Category
&
c
)
virtual
void
prepare
(
const
Category
&
c
)
{
{
mA
->
prepare
(
c
);
mA
->
prepare
(
c
);
mB
->
prepare
(
c
);
mB
->
prepare
(
c
);
}
}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
return
mA
->
test
(
c
,
r
)
and
mB
->
test
(
c
,
r
);
return
mA
->
test
(
c
,
r
)
and
mB
->
test
(
c
,
r
);
}
}
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
'('
;
os
<<
'('
;
mA
->
str
(
os
);
mA
->
str
(
os
);
...
@@ -1006,14 +1066,15 @@ struct AndConditionImpl : public ConditionImpl
...
@@ -1006,14 +1066,15 @@ struct AndConditionImpl : public ConditionImpl
os
<<
')'
;
os
<<
')'
;
}
}
ConditionImpl
*
mA
;
ConditionImpl
*
mA
;
ConditionImpl
*
mB
;
ConditionImpl
*
mB
;
};
};
struct
OrConditionImpl
:
public
ConditionImpl
struct
OrConditionImpl
:
public
ConditionImpl
{
{
OrConditionImpl
(
Condition
&&
a
,
Condition
&&
b
)
OrConditionImpl
(
Condition
&&
a
,
Condition
&&
b
)
:
mA
(
nullptr
),
mB
(
nullptr
)
:
mA
(
nullptr
)
,
mB
(
nullptr
)
{
{
std
::
swap
(
mA
,
a
.
mImpl
);
std
::
swap
(
mA
,
a
.
mImpl
);
std
::
swap
(
mB
,
b
.
mImpl
);
std
::
swap
(
mB
,
b
.
mImpl
);
...
@@ -1025,18 +1086,18 @@ struct OrConditionImpl : public ConditionImpl
...
@@ -1025,18 +1086,18 @@ struct OrConditionImpl : public ConditionImpl
delete
mB
;
delete
mB
;
}
}
virtual
void
prepare
(
const
Category
&
c
)
virtual
void
prepare
(
const
Category
&
c
)
{
{
mA
->
prepare
(
c
);
mA
->
prepare
(
c
);
mB
->
prepare
(
c
);
mB
->
prepare
(
c
);
}
}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
return
mA
->
test
(
c
,
r
)
or
mB
->
test
(
c
,
r
);
return
mA
->
test
(
c
,
r
)
or
mB
->
test
(
c
,
r
);
}
}
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
'('
;
os
<<
'('
;
mA
->
str
(
os
);
mA
->
str
(
os
);
...
@@ -1045,13 +1106,13 @@ struct OrConditionImpl : public ConditionImpl
...
@@ -1045,13 +1106,13 @@ struct OrConditionImpl : public ConditionImpl
os
<<
')'
;
os
<<
')'
;
}
}
ConditionImpl
*
mA
;
ConditionImpl
*
mA
;
ConditionImpl
*
mB
;
ConditionImpl
*
mB
;
};
};
struct
NotConditionImpl
:
public
ConditionImpl
struct
NotConditionImpl
:
public
ConditionImpl
{
{
NotConditionImpl
(
Condition
&&
a
)
NotConditionImpl
(
Condition
&&
a
)
:
mA
(
nullptr
)
:
mA
(
nullptr
)
{
{
std
::
swap
(
mA
,
a
.
mImpl
);
std
::
swap
(
mA
,
a
.
mImpl
);
...
@@ -1062,29 +1123,29 @@ struct NotConditionImpl : public ConditionImpl
...
@@ -1062,29 +1123,29 @@ struct NotConditionImpl : public ConditionImpl
delete
mA
;
delete
mA
;
}
}
virtual
void
prepare
(
const
Category
&
c
)
virtual
void
prepare
(
const
Category
&
c
)
{
{
mA
->
prepare
(
c
);
mA
->
prepare
(
c
);
}
}
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
virtual
bool
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
return
not
mA
->
test
(
c
,
r
);
return
not
mA
->
test
(
c
,
r
);
}
}
virtual
void
str
(
std
::
ostream
&
os
)
const
virtual
void
str
(
std
::
ostream
&
os
)
const
{
{
os
<<
"NOT ("
;
os
<<
"NOT ("
;
mA
->
str
(
os
);
mA
->
str
(
os
);
os
<<
')'
;
os
<<
')'
;
}
}
ConditionImpl
*
mA
;
ConditionImpl
*
mA
;
};
};
}
}
// namespace detail
inline
Condition
operator
&&
(
Condition
&&
a
,
Condition
&&
b
)
inline
Condition
operator
&&
(
Condition
&&
a
,
Condition
&&
b
)
{
{
if
(
a
.
mImpl
and
b
.
mImpl
)
if
(
a
.
mImpl
and
b
.
mImpl
)
return
Condition
(
new
detail
::
AndConditionImpl
(
std
::
move
(
a
),
std
::
move
(
b
)));
return
Condition
(
new
detail
::
AndConditionImpl
(
std
::
move
(
a
),
std
::
move
(
b
)));
...
@@ -1093,7 +1154,7 @@ inline Condition operator&&(Condition&& a, Condition&& b)
...
@@ -1093,7 +1154,7 @@ inline Condition operator&&(Condition&& a, Condition&& b)
return
Condition
(
std
::
move
(
b
));
return
Condition
(
std
::
move
(
b
));
}
}
inline
Condition
operator
||
(
Condition
&&
a
,
Condition
&&
b
)
inline
Condition
operator
||
(
Condition
&&
a
,
Condition
&&
b
)
{
{
if
(
a
.
mImpl
and
b
.
mImpl
)
if
(
a
.
mImpl
and
b
.
mImpl
)
return
Condition
(
new
detail
::
OrConditionImpl
(
std
::
move
(
a
),
std
::
move
(
b
)));
return
Condition
(
new
detail
::
OrConditionImpl
(
std
::
move
(
a
),
std
::
move
(
b
)));
...
@@ -1102,38 +1163,50 @@ inline Condition operator||(Condition&& a, Condition&& b)
...
@@ -1102,38 +1163,50 @@ inline Condition operator||(Condition&& a, Condition&& b)
return
Condition
(
std
::
move
(
b
));
return
Condition
(
std
::
move
(
b
));
}
}
struct
Empty
{};
struct
Empty
{
};
struct
Key
struct
Key
{
{
Key
(
const
std
::
string
&
itemTag
)
:
mItemTag
(
itemTag
)
{}
Key
(
const
std
::
string
&
itemTag
)
Key
(
const
char
*
itemTag
)
:
mItemTag
(
itemTag
)
{}
:
mItemTag
(
itemTag
)
{
}
Key
(
const
char
*
itemTag
)
:
mItemTag
(
itemTag
)
{
}
Key
(
const
Key
&
)
=
delete
;
Key
(
const
Key
&
)
=
delete
;
Key
&
operator
=
(
const
Key
&
)
=
delete
;
Key
&
operator
=
(
const
Key
&
)
=
delete
;
std
::
string
mItemTag
;
std
::
string
mItemTag
;
};
};
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
==
(
const
Key
&
key
,
const
T
&
v
)
Condition
operator
==
(
const
Key
&
key
,
const
T
&
v
)
{
{
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
" == "
<<
v
;
s
<<
" == "
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
==
0
;
},
s
.
str
()));
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
==
0
;
},
s
.
str
()));
}
}
inline
Condition
operator
==
(
const
Key
&
key
,
const
char
*
value
)
inline
Condition
operator
==
(
const
Key
&
key
,
const
char
*
value
)
{
{
if
(
value
!=
nullptr
and
*
value
!=
0
)
if
(
value
!=
nullptr
and
*
value
!=
0
)
{
{
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
" == "
<<
value
;
s
<<
" == "
<<
value
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
value
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
{
return
r
[
tag
].
compare
(
value
,
icase
)
==
0
;
},
s
.
str
()));
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
value
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
compare
(
value
,
icase
)
==
0
;
},
s
.
str
()));
}
}
else
else
return
Condition
(
new
detail
::
KeyIsEmptyConditionImpl
(
key
.
mItemTag
));
return
Condition
(
new
detail
::
KeyIsEmptyConditionImpl
(
key
.
mItemTag
));
...
@@ -1148,89 +1221,94 @@ inline Condition operator==(const Key& key, const char *value)
...
@@ -1148,89 +1221,94 @@ inline Condition operator==(const Key& key, const char *value)
// { return r[tag].template compare<(v, icase) == 0; }));
// { return r[tag].template compare<(v, icase) == 0; }));
// }
// }
inline
Condition
operator
==
(
const
Key
&
key
,
const
Empty
&
)
inline
Condition
operator
==
(
const
Key
&
key
,
const
Empty
&
)
{
{
return
Condition
(
new
detail
::
KeyIsEmptyConditionImpl
(
key
.
mItemTag
));
return
Condition
(
new
detail
::
KeyIsEmptyConditionImpl
(
key
.
mItemTag
));
}
}
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
!=
(
const
Key
&
key
,
const
T
&
v
)
Condition
operator
!=
(
const
Key
&
key
,
const
T
&
v
)
{
{
return
Condition
(
new
detail
::
NotConditionImpl
(
operator
==
(
key
,
v
)));
return
Condition
(
new
detail
::
NotConditionImpl
(
operator
==
(
key
,
v
)));
}
}
inline
Condition
operator
!=
(
const
Key
&
key
,
const
char
*
v
)
inline
Condition
operator
!=
(
const
Key
&
key
,
const
char
*
v
)
{
{
std
::
string
value
(
v
?
v
:
""
);
std
::
string
value
(
v
?
v
:
""
);
return
Condition
(
new
detail
::
NotConditionImpl
(
operator
==
(
key
,
value
)));
return
Condition
(
new
detail
::
NotConditionImpl
(
operator
==
(
key
,
value
)));
}
}
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
>
(
const
Key
&
key
,
const
T
&
v
)
Condition
operator
>
(
const
Key
&
key
,
const
T
&
v
)
{
{
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
" > "
<<
v
;
s
<<
" > "
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
>
0
;
},
s
.
str
()));
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
>
0
;
},
s
.
str
()));
}
}
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
>=
(
const
Key
&
key
,
const
T
&
v
)
Condition
operator
>=
(
const
Key
&
key
,
const
T
&
v
)
{
{
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
" >= "
<<
v
;
s
<<
" >= "
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
>=
0
;
},
s
.
str
()));
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
>=
0
;
},
s
.
str
()));
}
}
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
<
(
const
Key
&
key
,
const
T
&
v
)
Condition
operator
<
(
const
Key
&
key
,
const
T
&
v
)
{
{
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
" < "
<<
v
;
s
<<
" < "
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
<
0
;
},
s
.
str
()));
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
<
0
;
},
s
.
str
()));
}
}
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
<=
(
const
Key
&
key
,
const
T
&
v
)
Condition
operator
<=
(
const
Key
&
key
,
const
T
&
v
)
{
{
std
::
ostringstream
s
;
std
::
ostringstream
s
;
s
<<
" <= "
<<
v
;
s
<<
" <= "
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
<=
0
;
},
s
.
str
()));
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
<=
0
;
},
s
.
str
()));
}
}
template
<>
template
<>
inline
inline
Condition
operator
==
(
const
Key
&
key
,
const
std
::
regex
&
rx
)
Condition
operator
==
(
const
Key
&
key
,
const
std
::
regex
&
rx
)
{
{
return
Condition
(
new
detail
::
KeyMatchesConditionImpl
(
key
.
mItemTag
,
rx
));
return
Condition
(
new
detail
::
KeyMatchesConditionImpl
(
key
.
mItemTag
,
rx
));
}
}
template
<>
template
<>
inline
inline
Condition
operator
==
(
const
Key
&
key
,
const
Empty
&
)
Condition
operator
==
(
const
Key
&
key
,
const
Empty
&
)
{
{
return
Condition
(
new
detail
::
KeyIsEmptyConditionImpl
(
key
.
mItemTag
));
return
Condition
(
new
detail
::
KeyIsEmptyConditionImpl
(
key
.
mItemTag
));
}
}
struct
any
struct
any
{
{
template
<
typename
T
>
template
<
typename
T
>
Condition
operator
==
(
const
T
&
v
)
const
Condition
operator
==
(
const
T
&
v
)
const
{
{
return
Condition
(
new
detail
::
AnyIsConditionImpl
<
T
>
(
v
));
return
Condition
(
new
detail
::
AnyIsConditionImpl
<
T
>
(
v
));
}
}
};
};
template
<>
template
<>
inline
inline
Condition
any
::
operator
==
(
const
std
::
regex
&
rx
)
const
Condition
any
::
operator
==
(
const
std
::
regex
&
rx
)
const
{
{
return
Condition
(
new
detail
::
AnyMatchesConditionImpl
(
rx
));
return
Condition
(
new
detail
::
AnyMatchesConditionImpl
(
rx
));
}
}
...
@@ -1240,7 +1318,7 @@ inline Condition All()
...
@@ -1240,7 +1318,7 @@ inline Condition All()
return
Condition
(
new
detail
::
AllConditionImpl
());
return
Condition
(
new
detail
::
AllConditionImpl
());
}
}
inline
Condition
Not
(
Condition
&&
cond
)
inline
Condition
Not
(
Condition
&&
cond
)
{
{
return
Condition
(
new
detail
::
NotConditionImpl
(
std
::
move
(
cond
)));
return
Condition
(
new
detail
::
NotConditionImpl
(
std
::
move
(
cond
)));
}
}
...
@@ -1248,69 +1326,76 @@ inline Condition Not(Condition&& cond)
...
@@ -1248,69 +1326,76 @@ inline Condition Not(Condition&& cond)
namespace
literals
namespace
literals
{
{
inline
Key
operator
""
_key
(
const
char
*
text
,
size_t
length
)
inline
Key
operator
""
_key
(
const
char
*
text
,
size_t
length
)
{
{
return
Key
(
std
::
string
(
text
,
length
));
return
Key
(
std
::
string
(
text
,
length
));
}
}
inline
constexpr
Empty
Null
=
Empty
();
}
inline
constexpr
Empty
Null
=
Empty
();
}
// namespace literals
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// iterators
// iterators
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
class
iterator_impl
class
iterator_impl
{
{
public
:
public
:
template
<
typename
,
typename
...
>
friend
class
iterator_impl
;
template
<
typename
,
typename
...
>
friend
class
iterator_impl
;
static
constexpr
size_t
N
=
sizeof
...(
Ts
);
static
constexpr
size_t
N
=
sizeof
...(
Ts
);
using
iterator_category
=
std
::
forward_iterator_tag
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
value_type
=
std
::
conditional_t
<
N
==
0
,
RowType
,
std
::
tuple
<
Ts
...
>>
;
using
value_type
=
std
::
conditional_t
<
N
==
0
,
RowType
,
std
::
tuple
<
Ts
...
>>
;
using
difference_type
=
std
::
ptrdiff_t
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
using
reference
=
value_type
&
;
friend
class
Category
;
friend
class
Category
;
// default constructor, equal to end()
// default constructor, equal to end()
iterator_impl
()
{}
iterator_impl
()
{}
iterator_impl
(
const
iterator_impl
&
rhs
)
iterator_impl
(
const
iterator_impl
&
rhs
)
:
mCurrent
(
rhs
.
mCurrent
),
mValue
(
rhs
.
mValue
),
mCix
(
rhs
.
mCix
)
:
mCurrent
(
rhs
.
mCurrent
)
,
mValue
(
rhs
.
mValue
)
,
mCix
(
rhs
.
mCix
)
{
{
}
}
iterator_impl
(
ItemRow
*
data
)
iterator_impl
(
ItemRow
*
data
)
:
mCurrent
(
data
)
:
mCurrent
(
data
)
{
{
static_assert
(
N
==
0
,
"Only valid if this is a row iterator, not a row<xxx> iterator"
);
static_assert
(
N
==
0
,
"Only valid if this is a row iterator, not a row<xxx> iterator"
);
}
}
iterator_impl
(
ItemRow
*
data
,
const
std
::
array
<
size_t
,
N
>&
cix
)
iterator_impl
(
ItemRow
*
data
,
const
std
::
array
<
size_t
,
N
>
&
cix
)
:
mCurrent
(
data
),
mCix
(
cix
)
{}
:
mCurrent
(
data
)
,
mCix
(
cix
)
{
}
template
<
typename
IRowType
>
template
<
typename
IRowType
>
iterator_impl
(
iterator_impl
<
IRowType
,
Ts
...
>&
rhs
)
iterator_impl
(
iterator_impl
<
IRowType
,
Ts
...
>
&
rhs
)
:
mCurrent
(
rhs
.
mCurrent
),
mCix
(
rhs
.
mCix
)
:
mCurrent
(
rhs
.
mCurrent
)
,
mCix
(
rhs
.
mCix
)
{
{
if
constexpr
(
N
>
0
)
if
constexpr
(
N
>
0
)
mValue
=
get
(
mCurrent
,
std
::
make_index_sequence
<
N
>
());
mValue
=
get
(
mCurrent
,
std
::
make_index_sequence
<
N
>
());
}
}
template
<
typename
IRowType
>
template
<
typename
IRowType
>
iterator_impl
(
const
iterator_impl
<
IRowType
>&
rhs
,
const
std
::
array
<
size_t
,
N
>&
cix
)
iterator_impl
(
const
iterator_impl
<
IRowType
>
&
rhs
,
const
std
::
array
<
size_t
,
N
>
&
cix
)
:
mCurrent
(
rhs
.
mCurrent
),
mCix
(
cix
)
:
mCurrent
(
rhs
.
mCurrent
)
,
mCix
(
cix
)
{
{
if
constexpr
(
N
>
0
)
if
constexpr
(
N
>
0
)
mValue
=
get
(
mCurrent
,
std
::
make_index_sequence
<
N
>
());
mValue
=
get
(
mCurrent
,
std
::
make_index_sequence
<
N
>
());
}
}
iterator_impl
&
operator
=
(
const
iterator_impl
&
i
)
iterator_impl
&
operator
=
(
const
iterator_impl
&
i
)
{
{
mCurrent
=
i
.
mCurrent
;
mCurrent
=
i
.
mCurrent
;
if
constexpr
(
N
!=
0
)
if
constexpr
(
N
!=
0
)
...
@@ -1344,7 +1429,7 @@ class iterator_impl
...
@@ -1344,7 +1429,7 @@ class iterator_impl
return
mCurrent
;
return
mCurrent
;
}
}
iterator_impl
&
operator
++
()
iterator_impl
&
operator
++
()
{
{
mCurrent
.
next
();
mCurrent
.
next
();
...
@@ -1361,24 +1446,23 @@ class iterator_impl
...
@@ -1361,24 +1446,23 @@ class iterator_impl
return
result
;
return
result
;
}
}
bool
operator
==
(
const
iterator_impl
&
rhs
)
const
{
return
mCurrent
==
rhs
.
mCurrent
;
}
bool
operator
==
(
const
iterator_impl
&
rhs
)
const
{
return
mCurrent
==
rhs
.
mCurrent
;
}
bool
operator
!=
(
const
iterator_impl
&
rhs
)
const
{
return
mCurrent
!=
rhs
.
mCurrent
;
}
bool
operator
!=
(
const
iterator_impl
&
rhs
)
const
{
return
mCurrent
!=
rhs
.
mCurrent
;
}
template
<
typename
IRowType
,
typename
...
ITs
>
template
<
typename
IRowType
,
typename
...
ITs
>
bool
operator
==
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
bool
operator
==
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
{
{
return
mCurrent
==
rhs
.
mCurrent
;
return
mCurrent
==
rhs
.
mCurrent
;
}
}
template
<
typename
IRowType
,
typename
...
ITs
>
template
<
typename
IRowType
,
typename
...
ITs
>
bool
operator
!=
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
bool
operator
!=
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
{
{
return
mCurrent
!=
rhs
.
mCurrent
;
return
mCurrent
!=
rhs
.
mCurrent
;
}
}
private
:
private
:
template
<
std
::
size_t
...
Is
>
template
<
std
::
size_t
...
Is
>
std
::
tuple
<
Ts
...
>
get
(
Row
row
,
std
::
index_sequence
<
Is
...
>
)
const
std
::
tuple
<
Ts
...
>
get
(
Row
row
,
std
::
index_sequence
<
Is
...
>
)
const
{
{
if
(
row
)
if
(
row
)
...
@@ -1394,7 +1478,7 @@ class iterator_impl
...
@@ -1394,7 +1478,7 @@ class iterator_impl
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// iterator proxy
// iterator proxy
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
class
iterator_proxy
class
iterator_proxy
{
{
public
:
public
:
...
@@ -1403,14 +1487,14 @@ class iterator_proxy
...
@@ -1403,14 +1487,14 @@ class iterator_proxy
using
iterator
=
iterator_impl
<
RowType
,
Ts
...
>
;
using
iterator
=
iterator_impl
<
RowType
,
Ts
...
>
;
using
row_iterator
=
iterator_impl
<
RowType
>
;
using
row_iterator
=
iterator_impl
<
RowType
>
;
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
]);
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
]);
iterator_proxy
(
Category
&
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
);
iterator_proxy
(
const
iterator_proxy
&
)
=
delete
;
iterator_proxy
(
const
iterator_proxy
&
)
=
delete
;
iterator_proxy
&
operator
=
(
const
iterator_proxy
&
)
=
delete
;
iterator_proxy
&
operator
=
(
const
iterator_proxy
&
)
=
delete
;
iterator
begin
()
const
{
return
iterator
(
mCBegin
,
mCix
);
}
iterator
begin
()
const
{
return
iterator
(
mCBegin
,
mCix
);
}
iterator
end
()
const
{
return
iterator
(
mCEnd
,
mCix
);
}
iterator
end
()
const
{
return
iterator
(
mCEnd
,
mCix
);
}
...
@@ -1424,9 +1508,9 @@ class iterator_proxy
...
@@ -1424,9 +1508,9 @@ class iterator_proxy
RowType
front
()
{
return
*
begin
();
}
RowType
front
()
{
return
*
begin
();
}
RowType
back
()
{
return
*
(
std
::
prev
(
end
()));
}
RowType
back
()
{
return
*
(
std
::
prev
(
end
()));
}
Category
&
category
()
const
{
return
*
mCat
;
}
Category
&
category
()
const
{
return
*
mCat
;
}
void
swap
(
iterator_proxy
&
rhs
)
void
swap
(
iterator_proxy
&
rhs
)
{
{
std
::
swap
(
mCat
,
rhs
.
mCat
);
std
::
swap
(
mCat
,
rhs
.
mCat
);
std
::
swap
(
mCBegin
,
rhs
.
mCBegin
);
std
::
swap
(
mCBegin
,
rhs
.
mCBegin
);
...
@@ -1435,15 +1519,15 @@ class iterator_proxy
...
@@ -1435,15 +1519,15 @@ class iterator_proxy
}
}
private
:
private
:
Category
*
mCat
;
Category
*
mCat
;
row_iterator
mCBegin
,
mCEnd
;
row_iterator
mCBegin
,
mCEnd
;
std
::
array
<
size_t
,
N
>
mCix
;
std
::
array
<
size_t
,
N
>
mCix
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// conditional iterator proxy
// conditional iterator proxy
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
class
conditional_iterator_proxy
class
conditional_iterator_proxy
{
{
public
:
public
:
...
@@ -1461,12 +1545,12 @@ class conditional_iterator_proxy
...
@@ -1461,12 +1545,12 @@ class conditional_iterator_proxy
using
iterator_category
=
std
::
forward_iterator_tag
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
value_type
=
conditional_iterator_proxy
::
value_type
;
using
value_type
=
conditional_iterator_proxy
::
value_type
;
using
difference_type
=
std
::
ptrdiff_t
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
using
reference
=
value_type
&
;
conditional_iterator_impl
(
Category
&
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
;
virtual
~
conditional_iterator_impl
()
=
default
;
virtual
~
conditional_iterator_impl
()
=
default
;
...
@@ -1480,7 +1564,7 @@ class conditional_iterator_proxy
...
@@ -1480,7 +1564,7 @@ class conditional_iterator_proxy
return
&*
mBegin
;
return
&*
mBegin
;
}
}
conditional_iterator_impl
&
operator
++
()
conditional_iterator_impl
&
operator
++
()
{
{
while
(
mBegin
!=
mEnd
)
while
(
mBegin
!=
mEnd
)
{
{
...
@@ -1501,35 +1585,34 @@ class conditional_iterator_proxy
...
@@ -1501,35 +1585,34 @@ class conditional_iterator_proxy
return
result
;
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
;
}
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
>
template
<
typename
IRowType
,
typename
...
ITs
>
bool
operator
==
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
{
return
mBegin
==
rhs
;
}
bool
operator
==
(
const
iterator_impl
<
IRowType
,
ITs
...
>
&
rhs
)
const
{
return
mBegin
==
rhs
;
}
template
<
typename
IRowType
,
typename
...
ITs
>
template
<
typename
IRowType
,
typename
...
ITs
>
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
*
mCat
;
Category
*
mCat
;
base_iterator
mBegin
,
mEnd
;
base_iterator
mBegin
,
mEnd
;
const
Condition
*
mCondition
;
const
Condition
*
mCondition
;
};
};
using
iterator
=
conditional_iterator_impl
;
using
iterator
=
conditional_iterator_impl
;
using
reference
=
typename
iterator
::
reference
;
using
reference
=
typename
iterator
::
reference
;
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
);
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
);
template
<
std
::
size_t
TN
=
N
,
std
::
enable_if_t
<
TN
!=
0
,
bool
>
=
true
>
template
<
std
::
size_t
TN
=
N
,
std
::
enable_if_t
<
TN
!=
0
,
bool
>
=
true
>
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
char
const
*
const
columns
[
N
]);
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
char
const
*
const
columns
[
N
]);
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
);
conditional_iterator_proxy
(
const
conditional_iterator_proxy
&
)
=
delete
;
conditional_iterator_proxy
(
const
conditional_iterator_proxy
&
)
=
delete
;
conditional_iterator_proxy
&
operator
=
(
const
conditional_iterator_proxy
&
)
=
delete
;
conditional_iterator_proxy
&
operator
=
(
const
conditional_iterator_proxy
&
)
=
delete
;
iterator
begin
()
const
;
iterator
begin
()
const
;
iterator
end
()
const
;
iterator
end
()
const
;
...
@@ -1542,15 +1625,15 @@ class conditional_iterator_proxy
...
@@ -1542,15 +1625,15 @@ class conditional_iterator_proxy
RowType
front
()
{
return
*
begin
();
}
RowType
front
()
{
return
*
begin
();
}
Category
&
category
()
const
{
return
*
mCat
;
}
Category
&
category
()
const
{
return
*
mCat
;
}
void
swap
(
conditional_iterator_proxy
&
rhs
);
void
swap
(
conditional_iterator_proxy
&
rhs
);
private
:
private
:
Category
*
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
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -1732,9 +1815,9 @@ class Category
...
@@ -1732,9 +1815,9 @@ class Category
friend
class
Row
;
friend
class
Row
;
friend
class
detail
::
ItemReference
;
friend
class
detail
::
ItemReference
;
Category
(
Datablock
&
db
,
const
std
::
string
&
name
,
Validator
*
Validator
);
Category
(
Datablock
&
db
,
const
std
::
string
&
name
,
Validator
*
Validator
);
Category
(
const
Category
&
)
=
delete
;
Category
(
const
Category
&
)
=
delete
;
Category
&
operator
=
(
const
Category
&
)
=
delete
;
Category
&
operator
=
(
const
Category
&
)
=
delete
;
~
Category
();
~
Category
();
const
std
::
string
name
()
const
{
return
mName
;
}
const
std
::
string
name
()
const
{
return
mName
;
}
...
@@ -1759,55 +1842,55 @@ class Category
...
@@ -1759,55 +1842,55 @@ class Category
Row
front
()
{
return
Row
(
mHead
);
}
Row
front
()
{
return
Row
(
mHead
);
}
Row
back
()
{
return
Row
(
mTail
);
}
Row
back
()
{
return
Row
(
mTail
);
}
Row
operator
[](
Condition
&&
cond
);
Row
operator
[](
Condition
&&
cond
);
template
<
typename
...
Ts
,
size_t
N
>
template
<
typename
...
Ts
,
size_t
N
>
iterator_proxy
<
Row
,
Ts
...
>
rows
(
char
const
*
const
(
&
columns
)[
N
])
iterator_proxy
<
Row
,
Ts
...
>
rows
(
char
const
*
const
(
&
columns
)[
N
])
{
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
return
iterator_proxy
<
Row
,
Ts
...
>
(
*
this
,
begin
(),
columns
);
return
iterator_proxy
<
Row
,
Ts
...
>
(
*
this
,
begin
(),
columns
);
}
}
template
<
typename
...
Ts
,
typename
...
Ns
>
template
<
typename
...
Ts
,
typename
...
Ns
>
iterator_proxy
<
Row
,
Ts
...
>
rows
(
Ns
...
names
)
iterator_proxy
<
Row
,
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"
);
static_assert
(
sizeof
...(
Ts
)
==
sizeof
...(
Ns
),
"The number of column titles should be equal to the number of types to return"
);
return
iterator_proxy
<
Row
,
Ts
...
>
(
*
this
,
begin
(),
{
names
...
});
return
iterator_proxy
<
Row
,
Ts
...
>
(
*
this
,
begin
(),
{
names
...
});
}
}
conditional_iterator_proxy
<
Row
>
find
(
Condition
&&
cond
)
conditional_iterator_proxy
<
Row
>
find
(
Condition
&&
cond
)
{
{
return
find
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
));
return
find
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
));
}
}
conditional_iterator_proxy
<
Row
>
find
(
const_iterator
pos
,
Condition
&&
cond
)
conditional_iterator_proxy
<
Row
>
find
(
const_iterator
pos
,
Condition
&&
cond
)
{
{
return
{
*
this
,
pos
,
std
::
forward
<
Condition
>
(
cond
)
};
return
{
*
this
,
pos
,
std
::
forward
<
Condition
>
(
cond
)
};
}
}
template
<
typename
...
Ts
,
size_t
N
>
template
<
typename
...
Ts
,
size_t
N
>
conditional_iterator_proxy
<
Row
,
Ts
...
>
find
(
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
conditional_iterator_proxy
<
Row
,
Ts
...
>
find
(
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
{
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
return
find
<
Ts
...
>
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
char
const
*
const
[
N
]
>
(
columns
));
return
find
<
Ts
...
>
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
char
const
*
const
[
N
]
>
(
columns
));
}
}
template
<
typename
...
Ts
,
size_t
N
>
template
<
typename
...
Ts
,
size_t
N
>
conditional_iterator_proxy
<
Row
,
Ts
...
>
find
(
const_iterator
pos
,
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
conditional_iterator_proxy
<
Row
,
Ts
...
>
find
(
const_iterator
pos
,
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
{
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
return
{
*
this
,
pos
,
std
::
forward
<
Condition
>
(
cond
),
columns
};
return
{
*
this
,
pos
,
std
::
forward
<
Condition
>
(
cond
),
columns
};
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// if you only expect a single row
// if you only expect a single row
Row
find1
(
Condition
&&
cond
)
Row
find1
(
Condition
&&
cond
)
{
{
return
find1
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
));
return
find1
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
));
}
}
Row
find1
(
const_iterator
pos
,
Condition
&&
cond
)
Row
find1
(
const_iterator
pos
,
Condition
&&
cond
)
{
{
auto
h
=
find
(
pos
,
std
::
forward
<
Condition
>
(
cond
));
auto
h
=
find
(
pos
,
std
::
forward
<
Condition
>
(
cond
));
...
@@ -1820,19 +1903,19 @@ class Category
...
@@ -1820,19 +1903,19 @@ class Category
return
*
h
.
begin
();
return
*
h
.
begin
();
}
}
template
<
typename
...
Ts
,
size_t
N
>
template
<
typename
...
Ts
,
size_t
N
>
std
::
tuple
<
Ts
...
>
find1
(
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
std
::
tuple
<
Ts
...
>
find1
(
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
{
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
return
find1
<
Ts
...
>
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
char
const
*
const
[
N
]
>
(
columns
));
return
find1
<
Ts
...
>
(
cbegin
(),
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
char
const
*
const
[
N
]
>
(
columns
));
}
}
template
<
typename
...
Ts
,
size_t
N
>
template
<
typename
...
Ts
,
size_t
N
>
std
::
tuple
<
Ts
...
>
find1
(
const_iterator
pos
,
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
std
::
tuple
<
Ts
...
>
find1
(
const_iterator
pos
,
Condition
&&
cond
,
char
const
*
const
(
&
columns
)[
N
])
{
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
static_assert
(
sizeof
...(
Ts
)
==
N
,
"The number of column titles should be equal to the number of types to return"
);
auto
h
=
find
<
Ts
...
>
(
pos
,
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
char
const
*
const
[
N
]
>
(
columns
));
auto
h
=
find
<
Ts
...
>
(
pos
,
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
char
const
*
const
[
N
]
>
(
columns
));
if
(
h
.
empty
())
if
(
h
.
empty
())
throw
std
::
runtime_error
(
"No hits found"
);
throw
std
::
runtime_error
(
"No hits found"
);
...
@@ -1843,25 +1926,29 @@ class Category
...
@@ -1843,25 +1926,29 @@ class Category
return
*
h
.
begin
();
return
*
h
.
begin
();
}
}
bool
exists
(
Condition
&&
cond
)
const
;
bool
exists
(
Condition
&&
cond
)
const
;
RowSet
orderBy
(
const
std
::
string
&
Item
)
RowSet
orderBy
(
const
std
::
string
&
Item
)
{
return
orderBy
({
Item
});
}
{
return
orderBy
({
Item
});
}
RowSet
orderBy
(
std
::
initializer_list
<
std
::
string
>
Items
);
RowSet
orderBy
(
std
::
initializer_list
<
std
::
string
>
Items
);
std
::
tuple
<
Row
,
bool
>
emplace
(
Item
value
)
{
return
emplace
({
value
});
}
std
::
tuple
<
Row
,
bool
>
emplace
(
Item
value
)
{
return
emplace
({
value
});
}
std
::
tuple
<
Row
,
bool
>
emplace
(
std
::
initializer_list
<
Item
>
values
)
std
::
tuple
<
Row
,
bool
>
emplace
(
std
::
initializer_list
<
Item
>
values
)
{
return
emplace
(
values
.
begin
(),
values
.
end
());
}
{
return
emplace
(
values
.
begin
(),
values
.
end
());
}
std
::
tuple
<
Row
,
bool
>
emplace
(
Row
r
);
std
::
tuple
<
Row
,
bool
>
emplace
(
Row
r
);
template
<
class
Iter
>
template
<
class
Iter
>
std
::
tuple
<
Row
,
bool
>
emplace
(
Iter
b
,
Iter
e
);
std
::
tuple
<
Row
,
bool
>
emplace
(
Iter
b
,
Iter
e
);
size_t
erase
(
Condition
&&
cond
);
size_t
erase
(
Condition
&&
cond
);
size_t
erase
(
Condition
&&
cond
,
std
::
function
<
void
(
const
Row
&
)
>&&
visit
);
size_t
erase
(
Condition
&&
cond
,
std
::
function
<
void
(
const
Row
&
)
>
&&
visit
);
void
erase
(
Row
r
);
void
erase
(
Row
r
);
iterator
erase
(
iterator
ri
);
iterator
erase
(
iterator
ri
);
...
@@ -1872,48 +1959,48 @@ class Category
...
@@ -1872,48 +1959,48 @@ class Category
// erase without cascade, should only be used when speed is needed
// erase without cascade, should only be used when speed is needed
size_t
erase_nocascade
(
Condition
&&
cond
)
size_t
erase_nocascade
(
Condition
&&
cond
)
{
{
return
erase_nocascade
(
std
::
forward
<
Condition
>
(
cond
),
[](
auto
r
){});
return
erase_nocascade
(
std
::
forward
<
Condition
>
(
cond
),
[](
auto
r
)
{});
}
}
size_t
erase_nocascade
(
Condition
&&
cond
,
std
::
function
<
void
(
const
Row
&
)
>&&
visit
)
size_t
erase_nocascade
(
Condition
&&
cond
,
std
::
function
<
void
(
const
Row
&
)
>
&&
visit
)
{
{
auto
savedValidator
=
mValidator
;
auto
savedValidator
=
mValidator
;
mValidator
=
nullptr
;
mValidator
=
nullptr
;
auto
result
=
erase
(
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
std
::
function
<
void
(
const
Row
&
)
>>
(
visit
));
auto
result
=
erase
(
std
::
forward
<
Condition
>
(
cond
),
std
::
forward
<
std
::
function
<
void
(
const
Row
&
)
>>
(
visit
));
mValidator
=
savedValidator
;
mValidator
=
savedValidator
;
return
result
;
return
result
;
}
}
void
eraseOrphans
(
Condition
&&
cond
);
void
eraseOrphans
(
Condition
&&
cond
);
/// an orphan is a row that is the child side of one or more
/// an orphan is a row that is the child side of one or more
/// links and for which there is no single parent left.
/// links and for which there is no single parent left.
bool
isOrphan
(
Row
r
);
bool
isOrphan
(
Row
r
);
bool
hasParent
(
Row
r
,
const
Category
&
parentCat
,
const
ValidateLink
&
link
)
const
;
bool
hasParent
(
Row
r
,
const
Category
&
parentCat
,
const
ValidateLink
&
link
)
const
;
bool
hasChildren
(
Row
r
)
const
;
bool
hasChildren
(
Row
r
)
const
;
bool
hasParents
(
Row
r
)
const
;
bool
hasParents
(
Row
r
)
const
;
RowSet
getChildren
(
Row
r
,
Category
&
childCat
);
RowSet
getChildren
(
Row
r
,
Category
&
childCat
);
RowSet
getChildren
(
Row
r
,
const
char
*
childCat
);
RowSet
getChildren
(
Row
r
,
const
char
*
childCat
);
RowSet
getParents
(
Row
r
,
Category
&
parentCat
);
RowSet
getParents
(
Row
r
,
Category
&
parentCat
);
RowSet
getParents
(
Row
r
,
const
char
*
parentCat
);
RowSet
getParents
(
Row
r
,
const
char
*
parentCat
);
RowSet
getLinked
(
Row
r
,
Category
&
cat
);
RowSet
getLinked
(
Row
r
,
Category
&
cat
);
RowSet
getLinked
(
Row
r
,
const
char
*
cat
);
RowSet
getLinked
(
Row
r
,
const
char
*
cat
);
bool
isValid
();
bool
isValid
();
void
validateLinks
()
const
;
void
validateLinks
()
const
;
const
Validator
&
getValidator
()
const
;
const
Validator
&
getValidator
()
const
;
const
ValidateCategory
*
getCatValidator
()
const
{
return
mCatValidator
;
}
const
ValidateCategory
*
getCatValidator
()
const
{
return
mCatValidator
;
}
Datablock
&
db
()
{
return
mDb
;
}
Datablock
&
db
()
{
return
mDb
;
}
void
setValidator
(
Validator
*
v
);
void
setValidator
(
Validator
*
v
);
iset
fields
()
const
;
iset
fields
()
const
;
iset
mandatoryFields
()
const
;
iset
mandatoryFields
()
const
;
...
@@ -1921,18 +2008,18 @@ class Category
...
@@ -1921,18 +2008,18 @@ class Category
std
::
set
<
size_t
>
keyFieldsByIndex
()
const
;
std
::
set
<
size_t
>
keyFieldsByIndex
()
const
;
void
drop
(
const
std
::
string
&
field
);
void
drop
(
const
std
::
string
&
field
);
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
// return index for known column, or the next available column index
// return index for known column, or the next available column index
size_t
getColumnIndex
(
const
std
::
string
&
name
)
const
;
size_t
getColumnIndex
(
const
std
::
string
&
name
)
const
;
bool
hasColumn
(
const
std
::
string
&
name
)
const
;
bool
hasColumn
(
const
std
::
string
&
name
)
const
;
const
std
::
string
&
getColumnName
(
size_t
columnIndex
)
const
;
const
std
::
string
&
getColumnName
(
size_t
columnIndex
)
const
;
std
::
vector
<
std
::
string
>
getColumnNames
()
const
;
std
::
vector
<
std
::
string
>
getColumnNames
()
const
;
void
reorderByIndex
();
void
reorderByIndex
();
void
sort
(
std
::
function
<
int
(
const
Row
&
,
const
Row
&
)
>
comparator
);
void
sort
(
std
::
function
<
int
(
const
Row
&
,
const
Row
&
)
>
comparator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
/// Rename a single column in the rows that match \a cond to value \a value
/// Rename a single column in the rows that match \a cond to value \a value
...
@@ -1942,7 +2029,7 @@ class Category
...
@@ -1942,7 +2029,7 @@ class Category
void
update_value
(
Condition
&&
cond
,
const
std
::
string
&
tag
,
const
std
::
string
&
value
)
void
update_value
(
Condition
&&
cond
,
const
std
::
string
&
tag
,
const
std
::
string
&
value
)
{
{
update_value
(
RowSet
{
*
this
,
std
::
move
(
cond
)
},
tag
,
value
);
update_value
(
RowSet
{
*
this
,
std
::
move
(
cond
)
},
tag
,
value
);
}
}
void
update_value
(
RowSet
&&
rows
,
const
std
::
string
&
tag
,
const
std
::
string
&
value
);
void
update_value
(
RowSet
&&
rows
,
const
std
::
string
&
tag
,
const
std
::
string
&
value
);
...
@@ -1954,25 +2041,30 @@ class Category
...
@@ -1954,25 +2041,30 @@ class Category
std
::
string
getUniqueID
(
std
::
function
<
std
::
string
(
int
)
>
generator
=
cif
::
cifIdForNumber
);
std
::
string
getUniqueID
(
std
::
function
<
std
::
string
(
int
)
>
generator
=
cif
::
cifIdForNumber
);
std
::
string
getUniqueID
(
const
std
::
string
&
prefix
)
std
::
string
getUniqueID
(
const
std
::
string
&
prefix
)
{
{
return
getUniqueID
([
prefix
](
int
nr
)
{
return
prefix
+
std
::
to_string
(
nr
);
});
return
getUniqueID
([
prefix
](
int
nr
)
{
return
prefix
+
std
::
to_string
(
nr
);
});
}
}
private
:
// --------------------------------------------------------------------
// for debugging
friend
bool
operator
==
(
const
Category
&
lhs
,
const
Category
&
rhs
);
void
write
(
std
::
ostream
&
os
);
private
:
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
order
);
void
write
(
std
::
ostream
&
os
);
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
size_t
>&
order
,
bool
includeEmptyColumns
);
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
);
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
size_t
>
&
order
,
bool
includeEmptyColumns
);
size_t
addColumn
(
const
std
::
string
&
name
);
size_t
addColumn
(
const
std
::
string
&
name
);
Datablock
&
mDb
;
Datablock
&
mDb
;
std
::
string
mName
;
std
::
string
mName
;
Validator
*
mValidator
;
Validator
*
mValidator
;
const
ValidateCategory
*
mCatValidator
=
nullptr
;
const
ValidateCategory
*
mCatValidator
=
nullptr
;
std
::
vector
<
ItemColumn
>
mColumns
;
std
::
vector
<
ItemColumn
>
mColumns
;
ItemRow
*
mHead
;
ItemRow
*
mHead
;
ItemRow
*
mTail
;
ItemRow
*
mTail
;
class
CatIndex
*
mIndex
;
class
CatIndex
*
mIndex
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -1984,66 +2076,81 @@ class File
...
@@ -1984,66 +2076,81 @@ class File
friend
class
Validator
;
friend
class
Validator
;
File
();
File
();
File
(
std
::
istream
&
is
,
bool
validate
=
false
);
File
(
std
::
istream
&
is
,
bool
validate
=
false
);
File
(
const
std
::
string
&
path
,
bool
validate
=
false
);
File
(
const
std
::
string
&
path
,
bool
validate
=
false
);
File
(
File
&&
rhs
);
File
(
File
&&
rhs
);
File
(
const
File
&
rhs
)
=
delete
;
File
(
const
File
&
rhs
)
=
delete
;
File
&
operator
=
(
const
File
&
rhs
)
=
delete
;
File
&
operator
=
(
const
File
&
rhs
)
=
delete
;
~
File
();
~
File
();
void
load
(
const
std
::
string
&
p
);
void
load
(
const
std
::
string
&
p
);
void
save
(
const
std
::
string
&
p
);
void
save
(
const
std
::
string
&
p
);
void
load
(
std
::
istream
&
is
);
void
load
(
std
::
istream
&
is
);
void
save
(
std
::
ostream
&
os
);
void
save
(
std
::
ostream
&
os
);
/// \brief Load only the data block \a datablock from the mmCIF file
/// \brief Load only the data block \a datablock from the mmCIF file
void
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
);
void
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
);
void
save
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
order
)
{
write
(
os
,
order
);
}
void
save
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
)
{
write
(
os
,
order
);
}
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
order
);
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
);
void
loadDictionary
();
// load the default dictionary, that is mmcifDdl in this case
void
loadDictionary
();
// load the default dictionary, that is mmcifDdl in this case
void
loadDictionary
(
const
char
*
dict
);
// load one of the compiled in dictionaries
void
loadDictionary
(
const
char
*
dict
);
// load one of the compiled in dictionaries
void
loadDictionary
(
std
::
istream
&
is
);
// load dictionary from input stream
void
loadDictionary
(
std
::
istream
&
is
);
// load dictionary from input stream
bool
isValid
();
bool
isValid
();
void
validateLinks
()
const
;
void
validateLinks
()
const
;
Datablock
&
firstDatablock
()
const
Datablock
&
firstDatablock
()
const
{
if
(
mHead
==
nullptr
)
throw
std
::
runtime_error
(
"No datablocks in file"
);
return
*
mHead
;
}
Datablock
&
firstDatablock
()
{
{
if
(
mHead
==
nullptr
)
if
(
mHead
==
nullptr
)
throw
std
::
runtime_error
(
"No datablocks in file"
);
throw
std
::
runtime_error
(
"No datablocks in file"
);
return
*
mHead
;
return
*
mHead
;
}
}
void
append
(
Datablock
*
e
);
void
append
(
Datablock
*
e
);
Datablock
*
get
(
const
std
::
string
&
name
)
const
;
Datablock
*
get
(
const
std
::
string
&
name
)
const
;
Datablock
&
operator
[](
const
std
::
string
&
name
);
Datablock
&
operator
[](
const
std
::
string
&
name
);
struct
iterator
struct
iterator
{
{
using
iterator_category
=
std
::
forward_iterator_tag
;
using
iterator_category
=
std
::
forward_iterator_tag
;
using
value_type
=
Datablock
;
using
value_type
=
Datablock
;
using
difference_type
=
std
::
ptrdiff_t
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
using
reference
=
value_type
&
;
iterator
(
Datablock
*
db
)
:
mCurrent
(
db
)
{}
iterator
(
Datablock
*
db
)
:
mCurrent
(
db
)
{
}
reference
operator
*
()
{
return
*
mCurrent
;
}
reference
operator
*
()
{
return
*
mCurrent
;
}
pointer
operator
->
()
{
return
mCurrent
;
}
pointer
operator
->
()
{
return
mCurrent
;
}
iterator
&
operator
++
();
iterator
&
operator
++
();
iterator
operator
++
(
int
)
{
iterator
result
(
*
this
);
this
->
operator
++
();
return
result
;
}
iterator
operator
++
(
int
)
{
iterator
result
(
*
this
);
this
->
operator
++
();
return
result
;
}
bool
operator
==
(
const
iterator
&
rhs
)
const
{
return
mCurrent
==
rhs
.
mCurrent
;
}
bool
operator
==
(
const
iterator
&
rhs
)
const
{
return
mCurrent
==
rhs
.
mCurrent
;
}
bool
operator
!=
(
const
iterator
&
rhs
)
const
{
return
not
(
mCurrent
==
rhs
.
mCurrent
);
}
bool
operator
!=
(
const
iterator
&
rhs
)
const
{
return
not
(
mCurrent
==
rhs
.
mCurrent
);
}
private
:
private
:
Datablock
*
mCurrent
;
Datablock
*
mCurrent
;
};
};
iterator
begin
()
const
;
iterator
begin
()
const
;
...
@@ -2051,15 +2158,14 @@ class File
...
@@ -2051,15 +2158,14 @@ class File
bool
empty
()
const
{
return
mHead
==
nullptr
;
}
bool
empty
()
const
{
return
mHead
==
nullptr
;
}
const
Validator
&
getValidator
()
const
;
const
Validator
&
getValidator
()
const
;
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
private
:
private
:
void
setValidator
(
Validator
*
v
);
void
setValidator
(
Validator
*
v
);
Datablock
*
mHead
;
Validator
*
mValidator
;
Datablock
*
mHead
;
Validator
*
mValidator
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -2068,12 +2174,11 @@ class File
...
@@ -2068,12 +2174,11 @@ class File
namespace
detail
namespace
detail
{
{
template
<
typename
T
>
template
<
typename
T
>
inline
inline
bool
AnyIsConditionImpl
<
T
>::
test
(
const
Category
&
c
,
const
Row
&
r
)
const
bool
AnyIsConditionImpl
<
T
>::
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
bool
result
=
false
;
bool
result
=
false
;
for
(
auto
&
f
:
c
.
fields
())
for
(
auto
&
f
:
c
.
fields
())
{
{
try
try
{
{
...
@@ -2083,16 +2188,18 @@ bool AnyIsConditionImpl<T>::test(const Category& c, const Row& r) const
...
@@ -2083,16 +2188,18 @@ bool AnyIsConditionImpl<T>::test(const Category& c, const Row& r) const
break
;
break
;
}
}
}
}
catch
(...)
{}
catch
(...)
{
}
}
}
return
result
;
return
result
;
}
}
inline
bool
AnyMatchesConditionImpl
::
test
(
const
Category
&
c
,
const
Row
&
r
)
const
inline
bool
AnyMatchesConditionImpl
::
test
(
const
Category
&
c
,
const
Row
&
r
)
const
{
{
bool
result
=
false
;
bool
result
=
false
;
for
(
auto
&
f
:
c
.
fields
())
for
(
auto
&
f
:
c
.
fields
())
{
{
try
try
{
{
...
@@ -2102,30 +2209,32 @@ inline bool AnyMatchesConditionImpl::test(const Category& c, const Row& r) const
...
@@ -2102,30 +2209,32 @@ inline bool AnyMatchesConditionImpl::test(const Category& c, const Row& r) const
break
;
break
;
}
}
}
}
catch
(...)
{}
catch
(...)
{
}
}
}
return
result
;
return
result
;
}
}
}
}
// namespace detail
// these should be here, as I learned today
// these should be here, as I learned today
inline
void
swap
(
cif
::
Row
&
a
,
cif
::
Row
&
b
)
inline
void
swap
(
cif
::
Row
&
a
,
cif
::
Row
&
b
)
{
{
a
.
swap
(
b
);
a
.
swap
(
b
);
}
}
inline
void
swap
(
cif
::
detail
::
ItemReference
&
a
,
cif
::
detail
::
ItemReference
&
b
)
inline
void
swap
(
cif
::
detail
::
ItemReference
&
a
,
cif
::
detail
::
ItemReference
&
b
)
{
{
a
.
swap
(
b
);
a
.
swap
(
b
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
iterator_proxy
<
RowType
,
Ts
...
>::
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
char
const
*
const
columns
[
N
])
iterator_proxy
<
RowType
,
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
())
...
@@ -2134,8 +2243,8 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category& cat, row_iterator pos,
...
@@ -2134,8 +2243,8 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category& cat, row_iterator pos,
mCix
[
i
]
=
mCat
->
getColumnIndex
(
columns
[
i
]);
mCix
[
i
]
=
mCat
->
getColumnIndex
(
columns
[
i
]);
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
iterator_proxy
<
RowType
,
Ts
...
>::
iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
std
::
initializer_list
<
char
const
*>
columns
)
iterator_proxy
<
RowType
,
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
())
...
@@ -2143,30 +2252,36 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category& cat, row_iterator pos,
...
@@ -2143,30 +2252,36 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category& cat, row_iterator pos,
// static_assert(columns.size() == N, "The list of column names should be exactly the same as the list of requested columns");
// 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
;
std
::
size_t
i
=
0
;
for
(
auto
column
:
columns
)
for
(
auto
column
:
columns
)
mCix
[
i
++
]
=
mCat
->
getColumnIndex
(
column
);
mCix
[
i
++
]
=
mCat
->
getColumnIndex
(
column
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_impl
::
conditional_iterator_impl
(
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_impl
::
conditional_iterator_impl
(
Category
&
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
),
mBegin
(
pos
,
cix
),
mEnd
(
cat
.
end
(),
cix
),
mCondition
(
&
cond
)
:
mCat
(
&
cat
)
,
mBegin
(
pos
,
cix
)
,
mEnd
(
cat
.
end
(),
cix
)
,
mCondition
(
&
cond
)
{
{
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_proxy
(
conditional_iterator_proxy
&&
p
)
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_proxy
(
conditional_iterator_proxy
&&
p
)
:
mCat
(
nullptr
),
mCBegin
(
p
.
mCBegin
),
mCEnd
(
p
.
mCEnd
),
mCix
(
p
.
mCix
)
:
mCat
(
nullptr
)
,
mCBegin
(
p
.
mCBegin
)
,
mCEnd
(
p
.
mCEnd
)
,
mCix
(
p
.
mCix
)
{
{
std
::
swap
(
mCat
,
p
.
mCat
);
std
::
swap
(
mCat
,
p
.
mCat
);
std
::
swap
(
mCix
,
p
.
mCix
);
std
::
swap
(
mCix
,
p
.
mCix
);
mCondition
.
swap
(
p
.
mCondition
);
mCondition
.
swap
(
p
.
mCondition
);
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
)
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
)
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
,
mCondition
(
std
::
move
(
cond
))
,
mCondition
(
std
::
move
(
cond
))
,
mCBegin
(
pos
)
,
mCBegin
(
pos
)
...
@@ -2178,9 +2293,9 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category&
...
@@ -2178,9 +2293,9 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category&
++
mCBegin
;
++
mCBegin
;
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
template
<
std
::
size_t
TN
,
std
::
enable_if_t
<
TN
!=
0
,
bool
>>
template
<
std
::
size_t
TN
,
std
::
enable_if_t
<
TN
!=
0
,
bool
>>
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
const
char
*
const
columns
[
N
])
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
conditional_iterator_proxy
(
Category
&
cat
,
row_iterator
pos
,
Condition
&&
cond
,
const
char
*
const
columns
[
N
])
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
,
mCondition
(
std
::
move
(
cond
))
,
mCondition
(
std
::
move
(
cond
))
,
mCBegin
(
pos
)
,
mCBegin
(
pos
)
...
@@ -2195,33 +2310,33 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category&
...
@@ -2195,33 +2310,33 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category&
mCix
[
i
]
=
mCat
->
getColumnIndex
(
columns
[
i
]);
mCix
[
i
]
=
mCat
->
getColumnIndex
(
columns
[
i
]);
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
conditional_iterator_proxy
<
RowType
,
Ts
...
>
&
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
operator
=
(
conditional_iterator_proxy
&&
p
)
conditional_iterator_proxy
<
RowType
,
Ts
...
>
&
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
operator
=
(
conditional_iterator_proxy
&&
p
)
{
{
swap
(
p
);
swap
(
p
);
return
*
this
;
return
*
this
;
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
typename
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
begin
()
const
typename
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
begin
()
const
{
{
return
iterator
(
*
mCat
,
mCBegin
,
mCondition
,
mCix
);
return
iterator
(
*
mCat
,
mCBegin
,
mCondition
,
mCix
);
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
typename
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
end
()
const
typename
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
iterator
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
end
()
const
{
{
return
iterator
(
*
mCat
,
mCEnd
,
mCondition
,
mCix
);
return
iterator
(
*
mCat
,
mCEnd
,
mCondition
,
mCix
);
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
bool
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
empty
()
const
bool
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
empty
()
const
{
{
return
mCBegin
==
mCEnd
;
return
mCBegin
==
mCEnd
;
}
}
template
<
typename
RowType
,
typename
...
Ts
>
template
<
typename
RowType
,
typename
...
Ts
>
void
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
swap
(
conditional_iterator_proxy
&
rhs
)
void
conditional_iterator_proxy
<
RowType
,
Ts
...
>::
swap
(
conditional_iterator_proxy
&
rhs
)
{
{
std
::
swap
(
mCat
,
rhs
.
mCat
);
std
::
swap
(
mCat
,
rhs
.
mCat
);
mCondition
.
swap
(
rhs
.
mCondition
);
mCondition
.
swap
(
rhs
.
mCondition
);
...
@@ -2230,5 +2345,4 @@ void conditional_iterator_proxy<RowType, Ts...>::swap(conditional_iterator_proxy
...
@@ -2230,5 +2345,4 @@ void conditional_iterator_proxy<RowType, Ts...>::swap(conditional_iterator_proxy
std
::
swap
(
mCix
,
rhs
.
mCix
);
std
::
swap
(
mCix
,
rhs
.
mCix
);
}
}
}
}
// namespace cif
include/cif++/Structure.hpp
View file @
345c4778
...
@@ -397,6 +397,8 @@ class File : public std::enable_shared_from_this<File>
...
@@ -397,6 +397,8 @@ class File : public std::enable_shared_from_this<File>
File
(
const
File
&
)
=
delete
;
File
(
const
File
&
)
=
delete
;
File
&
operator
=
(
const
File
&
)
=
delete
;
File
&
operator
=
(
const
File
&
)
=
delete
;
cif
::
Datablock
&
createDatablock
(
const
std
::
string
&
name
);
void
load
(
const
std
::
string
&
path
);
void
load
(
const
std
::
string
&
path
);
void
save
(
const
std
::
string
&
path
);
void
save
(
const
std
::
string
&
path
);
...
@@ -482,6 +484,19 @@ class Structure
...
@@ -482,6 +484,19 @@ class Structure
void
changeResidue
(
const
Residue
&
res
,
const
std
::
string
&
newCompound
,
void
changeResidue
(
const
Residue
&
res
,
const
std
::
string
&
newCompound
,
const
std
::
vector
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
&
remappedAtoms
);
const
std
::
vector
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
&
remappedAtoms
);
/// \brief Create a new non-polymer entity, returns new ID
/// \param data The data to use to fill the entity
/// \param mon_id The mon_id for the new nonpoly
/// \param name The name of the nonpoly
/// \return The ID of the created entity
std
::
string
createEntityNonPoly
(
std
::
vector
<
cif
::
Item
>
data
,
const
std
::
string
&
mon_id
);
/// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atom_data, returns asym_id
/// \param entity_id The entity ID of the new nonpoly
/// \param atoms The array of atom data fields
/// \return The newly create asym ID
std
::
string
createNonpoly
(
const
std
::
string
&
entity_id
,
const
std
::
vector
<
cif
::
Item
>
&
atoms
);
/// To sort the atoms in order of model > asym-id > res-id > atom-id
/// To sort the atoms in order of model > asym-id > res-id > atom-id
/// Will asssign new atom_id's to all atoms. Be carefull
/// Will asssign new atom_id's to all atoms. Be carefull
void
sortAtoms
();
void
sortAtoms
();
...
...
src/Cif++.cpp
View file @
345c4778
...
@@ -26,26 +26,26 @@
...
@@ -26,26 +26,26 @@
#include <cassert>
#include <cassert>
#include <
stack
>
#include <
fstream
>
#include <
tuple
>
#include <
numeric
>
#include <regex>
#include <regex>
#include <set>
#include <set>
#include <stack>
#include <tuple>
#include <unordered_map>
#include <unordered_map>
#include <numeric>
#include <fstream>
#include <filesystem>
#include <filesystem>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/logic/tribool.hpp>
#include "cif++/Cif++.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/CifParser.hpp"
#include "cif++/CifParser.hpp"
#include "cif++/CifValidator.hpp"
#include "cif++/CifUtils.hpp"
#include "cif++/CifUtils.hpp"
#include "cif++/CifValidator.hpp"
namespace
ba
=
boost
::
algorithm
;
namespace
ba
=
boost
::
algorithm
;
namespace
io
=
boost
::
iostreams
;
namespace
io
=
boost
::
iostreams
;
...
@@ -56,7 +56,7 @@ namespace cif
...
@@ -56,7 +56,7 @@ namespace cif
CIFPP_EXPORT
int
VERBOSE
=
0
;
CIFPP_EXPORT
int
VERBOSE
=
0
;
static
const
char
*
kEmptyResult
=
""
;
static
const
char
*
kEmptyResult
=
""
;
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// most internal data structures are stored as linked lists
// most internal data structures are stored as linked lists
...
@@ -64,26 +64,27 @@ static const char* kEmptyResult = "";
...
@@ -64,26 +64,27 @@ static const char* kEmptyResult = "";
struct
ItemValue
struct
ItemValue
{
{
ItemValue
*
mNext
;
ItemValue
*
mNext
;
uint32_t
mColumnIndex
;
uint32_t
mColumnIndex
;
char
mText
[
4
];
char
mText
[
4
];
ItemValue
(
const
char
*
v
,
size_t
columnIndex
);
ItemValue
(
const
char
*
v
,
size_t
columnIndex
);
~
ItemValue
();
~
ItemValue
();
bool
empty
()
const
{
return
mText
[
0
]
==
0
or
((
mText
[
0
]
==
'.'
or
mText
[
0
]
==
'?'
)
and
mText
[
1
]
==
0
);
}
bool
empty
()
const
{
return
mText
[
0
]
==
0
or
((
mText
[
0
]
==
'.'
or
mText
[
0
]
==
'?'
)
and
mText
[
1
]
==
0
);
}
bool
null
()
const
{
return
mText
[
0
]
==
'.'
and
mText
[
1
]
==
0
;
}
bool
null
()
const
{
return
mText
[
0
]
==
'.'
and
mText
[
1
]
==
0
;
}
bool
unknown
()
const
{
return
mText
[
0
]
==
'?'
and
mText
[
1
]
==
0
;
}
bool
unknown
()
const
{
return
mText
[
0
]
==
'?'
and
mText
[
1
]
==
0
;
}
void
*
operator
new
(
size_t
size
,
size_t
dataSize
);
void
*
operator
new
(
size_t
size
,
size_t
dataSize
);
void
operator
delete
(
void
*
p
);
void
operator
delete
(
void
*
p
);
void
operator
delete
(
void
*
p
,
size_t
dataSize
);
void
operator
delete
(
void
*
p
,
size_t
dataSize
);
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
ItemValue
::
ItemValue
(
const
char
*
value
,
size_t
columnIndex
)
ItemValue
::
ItemValue
(
const
char
*
value
,
size_t
columnIndex
)
:
mNext
(
nullptr
),
mColumnIndex
(
uint32_t
(
columnIndex
))
:
mNext
(
nullptr
)
,
mColumnIndex
(
uint32_t
(
columnIndex
))
{
{
assert
(
columnIndex
<
std
::
numeric_limits
<
uint32_t
>::
max
());
assert
(
columnIndex
<
std
::
numeric_limits
<
uint32_t
>::
max
());
strcpy
(
mText
,
value
);
strcpy
(
mText
,
value
);
...
@@ -101,17 +102,17 @@ ItemValue::~ItemValue()
...
@@ -101,17 +102,17 @@ ItemValue::~ItemValue()
}
}
}
}
void
*
ItemValue
::
operator
new
(
size_t
size
,
size_t
dataSize
)
void
*
ItemValue
::
operator
new
(
size_t
size
,
size_t
dataSize
)
{
{
return
malloc
(
size
-
4
+
dataSize
+
1
);
return
malloc
(
size
-
4
+
dataSize
+
1
);
}
}
void
ItemValue
::
operator
delete
(
void
*
p
)
void
ItemValue
::
operator
delete
(
void
*
p
)
{
{
free
(
p
);
free
(
p
);
}
}
void
ItemValue
::
operator
delete
(
void
*
p
,
size_t
dataSize
)
void
ItemValue
::
operator
delete
(
void
*
p
,
size_t
dataSize
)
{
{
free
(
p
);
free
(
p
);
}
}
...
@@ -122,7 +123,7 @@ void ItemValue::operator delete(void* p, size_t dataSize)
...
@@ -122,7 +123,7 @@ void ItemValue::operator delete(void* p, size_t dataSize)
struct
ItemColumn
struct
ItemColumn
{
{
std
::
string
mName
;
// store lower-case, for optimization
std
::
string
mName
;
// store lower-case, for optimization
const
ValidateItem
*
mValidator
;
const
ValidateItem
*
mValidator
;
};
};
// itemRow contains the actual values for a Row in a Category
// itemRow contains the actual values for a Row in a Category
...
@@ -132,7 +133,7 @@ struct ItemRow
...
@@ -132,7 +133,7 @@ struct ItemRow
~
ItemRow
();
~
ItemRow
();
void
drop
(
size_t
columnIx
);
void
drop
(
size_t
columnIx
);
const
char
*
c_str
(
size_t
columnIx
)
const
;
const
char
*
c_str
(
size_t
columnIx
)
const
;
std
::
string
str
()
const
std
::
string
str
()
const
{
{
...
@@ -152,13 +153,13 @@ struct ItemRow
...
@@ -152,13 +153,13 @@ struct ItemRow
return
s
.
str
();
return
s
.
str
();
}
}
ItemRow
*
mNext
;
ItemRow
*
mNext
;
Category
*
mCategory
;
Category
*
mCategory
;
ItemValue
*
mValues
;
ItemValue
*
mValues
;
uint32_t
mLineNr
=
0
;
uint32_t
mLineNr
=
0
;
};
};
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
ItemRow
&
r
)
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
ItemRow
&
r
)
{
{
os
<<
r
.
mCategory
->
name
()
<<
'['
;
os
<<
r
.
mCategory
->
name
()
<<
'['
;
for
(
auto
iv
=
r
.
mValues
;
iv
!=
nullptr
;
iv
=
iv
->
mNext
)
for
(
auto
iv
=
r
.
mValues
;
iv
!=
nullptr
;
iv
=
iv
->
mNext
)
...
@@ -219,9 +220,9 @@ void ItemRow::drop(size_t columnIx)
...
@@ -219,9 +220,9 @@ void ItemRow::drop(size_t columnIx)
#endif
#endif
}
}
const
char
*
ItemRow
::
c_str
(
size_t
columnIx
)
const
const
char
*
ItemRow
::
c_str
(
size_t
columnIx
)
const
{
{
const
char
*
result
=
kEmptyResult
;
const
char
*
result
=
kEmptyResult
;
for
(
auto
v
=
mValues
;
v
!=
nullptr
;
v
=
v
->
mNext
)
for
(
auto
v
=
mValues
;
v
!=
nullptr
;
v
=
v
->
mNext
)
{
{
...
@@ -240,8 +241,8 @@ const char* ItemRow::c_str(size_t columnIx) const
...
@@ -240,8 +241,8 @@ const char* ItemRow::c_str(size_t columnIx) const
namespace
detail
namespace
detail
{
{
ItemReference
&
ItemReference
::
operator
=
(
const
std
::
string
&
value
)
ItemReference
&
ItemReference
::
operator
=
(
const
std
::
string
&
value
)
{
{
if
(
mConst
)
if
(
mConst
)
throw
std
::
logic_error
(
"Attempt to write to a constant row"
);
throw
std
::
logic_error
(
"Attempt to write to a constant row"
);
...
@@ -250,15 +251,15 @@ ItemReference& ItemReference::operator=(const std::string& value)
...
@@ -250,15 +251,15 @@ ItemReference& ItemReference::operator=(const std::string& value)
mRow
.
assign
(
mName
,
value
,
false
);
mRow
.
assign
(
mName
,
value
,
false
);
return
*
this
;
return
*
this
;
}
}
const
char
*
ItemReference
::
c_str
()
const
const
char
*
ItemReference
::
c_str
()
const
{
{
const
char
*
result
=
kEmptyResult
;
const
char
*
result
=
kEmptyResult
;
if
(
mRow
.
mData
!=
nullptr
/* and mRow.mData->mCategory != nullptr*/
)
if
(
mRow
.
mData
!=
nullptr
/* and mRow.mData->mCategory != nullptr*/
)
{
{
// assert(mRow.mData->mCategory);
// assert(mRow.mData->mCategory);
for
(
auto
iv
=
mRow
.
mData
->
mValues
;
iv
!=
nullptr
;
iv
=
iv
->
mNext
)
for
(
auto
iv
=
mRow
.
mData
->
mValues
;
iv
!=
nullptr
;
iv
=
iv
->
mNext
)
{
{
...
@@ -273,11 +274,11 @@ const char* ItemReference::c_str() const
...
@@ -273,11 +274,11 @@ const char* ItemReference::c_str() const
}
}
return
result
;
return
result
;
}
}
const
char
*
ItemReference
::
c_str
(
const
char
*
defaultValue
)
const
const
char
*
ItemReference
::
c_str
(
const
char
*
defaultValue
)
const
{
{
const
char
*
result
=
defaultValue
;
const
char
*
result
=
defaultValue
;
if
(
mRow
.
mData
!=
nullptr
and
mRow
.
mData
->
mCategory
!=
nullptr
)
if
(
mRow
.
mData
!=
nullptr
and
mRow
.
mData
->
mCategory
!=
nullptr
)
{
{
...
@@ -302,15 +303,15 @@ const char* ItemReference::c_str(const char* defaultValue) const
...
@@ -302,15 +303,15 @@ const char* ItemReference::c_str(const char* defaultValue) const
}
}
return
result
;
return
result
;
}
}
bool
ItemReference
::
empty
()
const
bool
ItemReference
::
empty
()
const
{
{
return
c_str
()
==
kEmptyResult
;
return
c_str
()
==
kEmptyResult
;
}
}
bool
ItemReference
::
is_null
()
const
bool
ItemReference
::
is_null
()
const
{
{
boost
::
tribool
result
;
boost
::
tribool
result
;
if
(
mRow
.
mData
!=
nullptr
and
mRow
.
mData
->
mCategory
!=
nullptr
)
if
(
mRow
.
mData
!=
nullptr
and
mRow
.
mData
->
mCategory
!=
nullptr
)
...
@@ -333,26 +334,28 @@ bool ItemReference::is_null() const
...
@@ -333,26 +334,28 @@ bool ItemReference::is_null() const
}
}
return
result
?
true
:
false
;
return
result
?
true
:
false
;
}
}
void
ItemReference
::
swap
(
ItemReference
&
b
)
void
ItemReference
::
swap
(
ItemReference
&
b
)
{
{
Row
::
swap
(
mColumn
,
mRow
.
mData
,
b
.
mRow
.
mData
);
Row
::
swap
(
mColumn
,
mRow
.
mData
,
b
.
mRow
.
mData
);
}
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
ItemReference
&
item
)
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
ItemReference
&
item
)
{
{
os
<<
item
.
c_str
();
os
<<
item
.
c_str
();
return
os
;
return
os
;
}
}
}
}
// namespace detail
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Datablock implementation
// Datablock implementation
Datablock
::
Datablock
(
const
std
::
string
&
name
)
Datablock
::
Datablock
(
const
std
::
string
&
name
)
:
mName
(
name
),
mValidator
(
nullptr
),
mNext
(
nullptr
)
:
mName
(
name
)
,
mValidator
(
nullptr
)
,
mNext
(
nullptr
)
{
{
}
}
...
@@ -361,18 +364,18 @@ Datablock::~Datablock()
...
@@ -361,18 +364,18 @@ Datablock::~Datablock()
delete
mNext
;
delete
mNext
;
}
}
std
::
string
Datablock
::
firstItem
(
const
std
::
string
&
tag
)
const
std
::
string
Datablock
::
firstItem
(
const
std
::
string
&
tag
)
const
{
{
std
::
string
result
;
std
::
string
result
;
std
::
string
catName
,
itemName
;
std
::
string
catName
,
itemName
;
std
::
tie
(
catName
,
itemName
)
=
splitTagName
(
tag
);
std
::
tie
(
catName
,
itemName
)
=
splitTagName
(
tag
);
for
(
auto
&
cat
:
mCategories
)
for
(
auto
&
cat
:
mCategories
)
{
{
if
(
iequals
(
cat
.
name
(),
catName
))
if
(
iequals
(
cat
.
name
(),
catName
))
{
{
for
(
auto
row
:
cat
)
for
(
auto
row
:
cat
)
{
{
result
=
row
[
itemName
].
as
<
std
::
string
>
();
result
=
row
[
itemName
].
as
<
std
::
string
>
();
break
;
break
;
...
@@ -385,10 +388,10 @@ std::string Datablock::firstItem(const std::string& tag) const
...
@@ -385,10 +388,10 @@ std::string Datablock::firstItem(const std::string& tag) const
return
result
;
return
result
;
}
}
auto
Datablock
::
emplace
(
const
std
::
string
&
name
)
->
std
::
tuple
<
iterator
,
bool
>
auto
Datablock
::
emplace
(
const
std
::
string
&
name
)
->
std
::
tuple
<
iterator
,
bool
>
{
{
bool
isNew
=
false
;
bool
isNew
=
false
;
iterator
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
iterator
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
{
return
iequals
(
cat
.
name
(),
name
);
});
{
return
iequals
(
cat
.
name
(),
name
);
});
if
(
i
==
end
())
if
(
i
==
end
())
...
@@ -400,16 +403,24 @@ auto Datablock::emplace(const std::string& name) -> std::tuple<iterator,bool>
...
@@ -400,16 +403,24 @@ auto Datablock::emplace(const std::string& name) -> std::tuple<iterator,bool>
return
std
::
make_tuple
(
i
,
isNew
);
return
std
::
make_tuple
(
i
,
isNew
);
}
}
Category
&
Datablock
::
operator
[](
const
std
::
string
&
name
)
Category
&
Datablock
::
operator
[](
const
std
::
string
&
name
)
{
{
iterator
i
;
iterator
i
;
std
::
tie
(
i
,
std
::
ignore
)
=
emplace
(
name
);
std
::
tie
(
i
,
std
::
ignore
)
=
emplace
(
name
);
return
*
i
;
return
*
i
;
}
}
Category
*
Datablock
::
get
(
const
std
::
string
&
name
)
Category
*
Datablock
::
get
(
const
std
::
string
&
name
)
{
auto
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
{
return
iequals
(
cat
.
name
(),
name
);
});
return
i
==
end
()
?
nullptr
:
&*
i
;
}
const
Category
*
Datablock
::
get
(
const
std
::
string
&
name
)
const
{
{
auto
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
auto
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
{
return
iequals
(
cat
.
name
(),
name
);
});
{
return
iequals
(
cat
.
name
(),
name
);
});
return
i
==
end
()
?
nullptr
:
&*
i
;
return
i
==
end
()
?
nullptr
:
&*
i
;
...
@@ -421,47 +432,45 @@ bool Datablock::isValid()
...
@@ -421,47 +432,45 @@ bool Datablock::isValid()
throw
std
::
runtime_error
(
"Validator not specified"
);
throw
std
::
runtime_error
(
"Validator not specified"
);
bool
result
=
true
;
bool
result
=
true
;
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
result
=
cat
.
isValid
()
and
result
;
result
=
cat
.
isValid
()
and
result
;
return
result
;
return
result
;
}
}
void
Datablock
::
validateLinks
()
const
void
Datablock
::
validateLinks
()
const
{
{
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
cat
.
validateLinks
();
cat
.
validateLinks
();
}
}
void
Datablock
::
setValidator
(
Validator
*
v
)
void
Datablock
::
setValidator
(
Validator
*
v
)
{
{
mValidator
=
v
;
mValidator
=
v
;
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
cat
.
setValidator
(
v
);
cat
.
setValidator
(
v
);
}
}
void
Datablock
::
add_software
(
const
std
::
string
&
name
,
const
std
::
string
&
classification
,
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
)
void
Datablock
::
add_software
(
const
std
::
string
&
name
,
const
std
::
string
&
classification
,
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
)
{
{
Category
&
cat
=
operator
[](
"software"
);
Category
&
cat
=
operator
[](
"software"
);
auto
ordNr
=
cat
.
size
()
+
1
;
auto
ordNr
=
cat
.
size
()
+
1
;
// TODO: should we check this ordinal number???
// TODO: should we check this ordinal number???
cat
.
emplace
({
cat
.
emplace
({{
"pdbx_ordinal"
,
ordNr
},
{
"pdbx_ordinal"
,
ordNr
},
{
"name"
,
name
},
{
"name"
,
name
},
{
"version"
,
versionNr
},
{
"version"
,
versionNr
},
{
"date"
,
versionDate
},
{
"date"
,
versionDate
},
{
"classification"
,
classification
}});
{
"classification"
,
classification
}
});
}
}
void
Datablock
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
void
Datablock
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
{
{
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
cat
.
getTagOrder
(
tags
);
cat
.
getTagOrder
(
tags
);
}
}
void
Datablock
::
write
(
std
::
ostream
&
os
)
void
Datablock
::
write
(
std
::
ostream
&
os
)
{
{
os
<<
"data_"
<<
mName
<<
std
::
endl
os
<<
"data_"
<<
mName
<<
std
::
endl
<<
"# "
<<
std
::
endl
;
<<
"# "
<<
std
::
endl
;
...
@@ -470,7 +479,7 @@ void Datablock::write(std::ostream& os)
...
@@ -470,7 +479,7 @@ void Datablock::write(std::ostream& os)
// and if it exists, _AND_ we have a Validator, write out the
// and if it exists, _AND_ we have a Validator, write out the
// audit_conform record.
// audit_conform record.
for
(
auto
&
cat
:
mCategories
)
for
(
auto
&
cat
:
mCategories
)
{
{
if
(
cat
.
name
()
==
"entry"
)
if
(
cat
.
name
()
==
"entry"
)
{
{
...
@@ -479,10 +488,8 @@ void Datablock::write(std::ostream& os)
...
@@ -479,10 +488,8 @@ void Datablock::write(std::ostream& os)
if
(
mValidator
!=
nullptr
)
if
(
mValidator
!=
nullptr
)
{
{
Category
auditConform
(
*
this
,
"audit_conform"
,
nullptr
);
Category
auditConform
(
*
this
,
"audit_conform"
,
nullptr
);
auditConform
.
emplace
({
auditConform
.
emplace
({{
"dict_name"
,
mValidator
->
dictName
()},
{
"dict_name"
,
mValidator
->
dictName
()
},
{
"dict_version"
,
mValidator
->
dictVersion
()}});
{
"dict_version"
,
mValidator
->
dictVersion
()
}
});
auditConform
.
write
(
os
);
auditConform
.
write
(
os
);
}
}
...
@@ -490,35 +497,36 @@ void Datablock::write(std::ostream& os)
...
@@ -490,35 +497,36 @@ void Datablock::write(std::ostream& os)
}
}
}
}
for
(
auto
&
cat
:
mCategories
)
for
(
auto
&
cat
:
mCategories
)
{
{
if
(
cat
.
name
()
!=
"entry"
and
cat
.
name
()
!=
"audit_conform"
)
if
(
cat
.
name
()
!=
"entry"
and
cat
.
name
()
!=
"audit_conform"
)
cat
.
write
(
os
);
cat
.
write
(
os
);
}
}
}
}
void
Datablock
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
order
)
void
Datablock
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
)
{
{
os
<<
"data_"
<<
mName
<<
std
::
endl
os
<<
"data_"
<<
mName
<<
std
::
endl
<<
"# "
<<
std
::
endl
;
<<
"# "
<<
std
::
endl
;
std
::
vector
<
std
::
string
>
catOrder
;
std
::
vector
<
std
::
string
>
catOrder
;
for
(
auto
&
o
:
order
)
for
(
auto
&
o
:
order
)
{
{
std
::
string
cat
,
Item
;
std
::
string
cat
,
Item
;
std
::
tie
(
cat
,
Item
)
=
splitTagName
(
o
);
std
::
tie
(
cat
,
Item
)
=
splitTagName
(
o
);
if
(
find_if
(
catOrder
.
rbegin
(),
catOrder
.
rend
(),
[
cat
](
const
std
::
string
&
s
)
->
bool
{
return
iequals
(
cat
,
s
);
})
==
catOrder
.
rend
())
if
(
find_if
(
catOrder
.
rbegin
(),
catOrder
.
rend
(),
[
cat
](
const
std
::
string
&
s
)
->
bool
{
return
iequals
(
cat
,
s
);
})
==
catOrder
.
rend
())
catOrder
.
push_back
(
cat
);
catOrder
.
push_back
(
cat
);
}
}
for
(
auto
&
c
:
catOrder
)
for
(
auto
&
c
:
catOrder
)
{
{
auto
cat
=
get
(
c
);
auto
cat
=
get
(
c
);
if
(
cat
==
nullptr
)
if
(
cat
==
nullptr
)
continue
;
continue
;
std
::
vector
<
std
::
string
>
items
;
std
::
vector
<
std
::
string
>
items
;
for
(
auto
&
o
:
order
)
for
(
auto
&
o
:
order
)
{
{
std
::
string
catName
,
Item
;
std
::
string
catName
,
Item
;
std
::
tie
(
catName
,
Item
)
=
splitTagName
(
o
);
std
::
tie
(
catName
,
Item
)
=
splitTagName
(
o
);
...
@@ -531,43 +539,115 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order)
...
@@ -531,43 +539,115 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order)
}
}
// for any Category we missed in the catOrder
// for any Category we missed in the catOrder
for
(
auto
&
cat
:
mCategories
)
for
(
auto
&
cat
:
mCategories
)
{
{
if
(
find_if
(
catOrder
.
begin
(),
catOrder
.
end
(),
[
&
](
const
std
::
string
&
s
)
->
bool
{
return
iequals
(
cat
.
name
(),
s
);
})
!=
catOrder
.
end
())
if
(
find_if
(
catOrder
.
begin
(),
catOrder
.
end
(),
[
&
](
const
std
::
string
&
s
)
->
bool
{
return
iequals
(
cat
.
name
(),
s
);
})
!=
catOrder
.
end
())
continue
;
continue
;
cat
.
write
(
os
);
cat
.
write
(
os
);
}
}
// // mmcif support, sort of. First write the 'entry' Category
// // mmcif support, sort of. First write the 'entry' Category
// // and if it exists, _AND_ we have a Validator, write out the
// // and if it exists, _AND_ we have a Validator, write out the
// // auditConform record.
// // auditConform record.
//
//
// for (auto& cat: mCategories)
// for (auto& cat: mCategories)
// {
// {
// if (cat.name() == "entry")
// if (cat.name() == "entry")
// {
// {
// cat.write(os);
// cat.write(os);
//
//
// if (mValidator != nullptr)
// if (mValidator != nullptr)
// {
// {
// Category auditConform(*this, "audit_conform", nullptr);
// Category auditConform(*this, "audit_conform", nullptr);
// auditConform.emplace({
// auditConform.emplace({
// { "dict_name", mValidator->dictName() },
// { "dict_name", mValidator->dictName() },
// { "dict_version", mValidator->dictVersion() }
// { "dict_version", mValidator->dictVersion() }
// });
// });
// auditConform.write(os);
// auditConform.write(os);
// }
// }
//
//
// break;
// break;
// }
// }
// }
// }
//
//
// for (auto& cat: mCategories)
// for (auto& cat: mCategories)
// {
// {
// if (cat.name() != "entry" and cat.name() != "audit_conform")
// if (cat.name() != "entry" and cat.name() != "audit_conform")
// cat.write(os);
// cat.write(os);
// }
// }
}
bool
operator
==
(
const
cif
::
Datablock
&
dbA
,
const
cif
::
Datablock
&
dbB
)
{
std
::
vector
<
std
::
string
>
catA
,
catB
;
for
(
auto
&
cat
:
dbA
)
{
if
(
not
cat
.
empty
())
catA
.
push_back
(
cat
.
name
());
}
sort
(
catA
.
begin
(),
catA
.
end
());
for
(
auto
&
cat
:
dbB
)
{
if
(
not
cat
.
empty
())
catB
.
push_back
(
cat
.
name
());
}
sort
(
catB
.
begin
(),
catB
.
end
());
// loop over categories twice, to group output
// First iteration is to list missing categories.
std
::
vector
<
std
::
string
>
missingA
,
missingB
;
auto
catA_i
=
catA
.
begin
(),
catB_i
=
catB
.
begin
();
while
(
catA_i
!=
catA
.
end
()
and
catB_i
!=
catB
.
end
())
{
if
(
not
iequals
(
*
catA_i
,
*
catB_i
))
return
false
;
++
catA_i
,
++
catB_i
;
}
if
(
catA_i
!=
catA
.
end
()
or
catB_i
!=
catB
.
end
())
return
false
;
// Second loop, now compare category values
catA_i
=
catA
.
begin
(),
catB_i
=
catB
.
begin
();
while
(
catA_i
!=
catA
.
end
()
and
catB_i
!=
catB
.
end
())
{
std
::
string
nA
=
*
catA_i
;
ba
::
to_lower
(
nA
);
std
::
string
nB
=
*
catB_i
;
ba
::
to_lower
(
nB
);
int
d
=
nA
.
compare
(
nB
);
if
(
d
>
0
)
++
catB_i
;
else
if
(
d
<
0
)
++
catA_i
;
else
{
if
(
not
(
*
dbA
.
get
(
*
catA_i
)
==
*
dbB
.
get
(
*
catB_i
)))
return
false
;
++
catA_i
;
++
catB_i
;
}
}
return
true
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Datablock
&
data
)
{
// whoohoo... this sucks!
const_cast
<
Datablock
&>
(
data
).
write
(
os
);
return
os
;
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -576,8 +656,8 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order)
...
@@ -576,8 +656,8 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order)
namespace
detail
namespace
detail
{
{
void
KeyCompareConditionImpl
::
prepare
(
const
Category
&
c
)
void
KeyCompareConditionImpl
::
prepare
(
const
Category
&
c
)
{
{
mItemIx
=
c
.
getColumnIndex
(
mItemTag
);
mItemIx
=
c
.
getColumnIndex
(
mItemTag
);
auto
cv
=
c
.
getCatValidator
();
auto
cv
=
c
.
getCatValidator
();
...
@@ -590,19 +670,19 @@ void KeyCompareConditionImpl::prepare(const Category& c)
...
@@ -590,19 +670,19 @@ void KeyCompareConditionImpl::prepare(const Category& c)
mCaseInsensitive
=
type
->
mPrimitiveType
==
DDL_PrimitiveType
::
UChar
;
mCaseInsensitive
=
type
->
mPrimitiveType
==
DDL_PrimitiveType
::
UChar
;
}
}
}
}
}
}
void
KeyIsEmptyConditionImpl
::
prepare
(
const
Category
&
c
)
void
KeyIsEmptyConditionImpl
::
prepare
(
const
Category
&
c
)
{
{
mItemIx
=
c
.
getColumnIndex
(
mItemTag
);
mItemIx
=
c
.
getColumnIndex
(
mItemTag
);
}
}
void
KeyMatchesConditionImpl
::
prepare
(
const
Category
&
c
)
void
KeyMatchesConditionImpl
::
prepare
(
const
Category
&
c
)
{
{
mItemIx
=
c
.
getColumnIndex
(
mItemTag
);
mItemIx
=
c
.
getColumnIndex
(
mItemTag
);
}
}
}
}
// namespace detail
// --------------------------------------------------------------------
// --------------------------------------------------------------------
//
//
...
@@ -611,32 +691,31 @@ void KeyMatchesConditionImpl::prepare(const Category& c)
...
@@ -611,32 +691,31 @@ void KeyMatchesConditionImpl::prepare(const Category& c)
class
RowComparator
class
RowComparator
{
{
public
:
public
:
RowComparator
(
Category
*
cat
)
RowComparator
(
Category
*
cat
)
:
RowComparator
(
cat
,
cat
->
getCatValidator
()
->
mKeys
.
begin
(),
cat
->
getCatValidator
()
->
mKeys
.
end
())
:
RowComparator
(
cat
,
cat
->
getCatValidator
()
->
mKeys
.
begin
(),
cat
->
getCatValidator
()
->
mKeys
.
end
())
{
{
}
}
template
<
typename
KeyIter
>
template
<
typename
KeyIter
>
RowComparator
(
Category
*
cat
,
KeyIter
b
,
KeyIter
e
);
RowComparator
(
Category
*
cat
,
KeyIter
b
,
KeyIter
e
);
int
operator
()(
const
ItemRow
*
a
,
const
ItemRow
*
b
)
const
;
int
operator
()(
const
ItemRow
*
a
,
const
ItemRow
*
b
)
const
;
int
operator
()(
const
Row
&
a
,
const
Row
&
b
)
const
int
operator
()(
const
Row
&
a
,
const
Row
&
b
)
const
{
{
return
operator
()(
a
.
mData
,
b
.
mData
);
return
operator
()(
a
.
mData
,
b
.
mData
);
}
}
private
:
private
:
typedef
std
::
function
<
int
(
const
char
*
,
const
char
*
)
>
compareFunc
;
typedef
std
::
function
<
int
(
const
char
*
,
const
char
*
)
>
compareFunc
;
typedef
std
::
tuple
<
size_t
,
compareFunc
>
keyComp
;
typedef
std
::
tuple
<
size_t
,
compareFunc
>
keyComp
;
std
::
vector
<
keyComp
>
mComp
;
std
::
vector
<
keyComp
>
mComp
;
};
};
template
<
typename
KeyIter
>
template
<
typename
KeyIter
>
RowComparator
::
RowComparator
(
Category
*
cat
,
KeyIter
b
,
KeyIter
e
)
RowComparator
::
RowComparator
(
Category
*
cat
,
KeyIter
b
,
KeyIter
e
)
{
{
auto
cv
=
cat
->
getCatValidator
();
auto
cv
=
cat
->
getCatValidator
();
...
@@ -660,21 +739,21 @@ RowComparator::RowComparator(Category* cat, KeyIter b, KeyIter e)
...
@@ -660,21 +739,21 @@ RowComparator::RowComparator(Category* cat, KeyIter b, KeyIter e)
}
}
}
}
int
RowComparator
::
operator
()(
const
ItemRow
*
a
,
const
ItemRow
*
b
)
const
int
RowComparator
::
operator
()(
const
ItemRow
*
a
,
const
ItemRow
*
b
)
const
{
{
assert
(
a
);
assert
(
a
);
assert
(
b
);
assert
(
b
);
int
d
=
0
;
int
d
=
0
;
for
(
auto
&
c
:
mComp
)
for
(
auto
&
c
:
mComp
)
{
{
size_t
k
;
size_t
k
;
compareFunc
f
;
compareFunc
f
;
std
::
tie
(
k
,
f
)
=
c
;
std
::
tie
(
k
,
f
)
=
c
;
const
char
*
ka
=
a
->
c_str
(
k
);
const
char
*
ka
=
a
->
c_str
(
k
);
const
char
*
kb
=
b
->
c_str
(
k
);
const
char
*
kb
=
b
->
c_str
(
k
);
d
=
f
(
ka
,
kb
);
d
=
f
(
ka
,
kb
);
...
@@ -693,26 +772,26 @@ int RowComparator::operator()(const ItemRow* a, const ItemRow* b) const
...
@@ -693,26 +772,26 @@ int RowComparator::operator()(const ItemRow* a, const ItemRow* b) const
class
CatIndex
class
CatIndex
{
{
public
:
public
:
CatIndex
(
Category
*
cat
);
CatIndex
(
Category
*
cat
);
~
CatIndex
();
~
CatIndex
();
ItemRow
*
find
(
ItemRow
*
k
)
const
;
ItemRow
*
find
(
ItemRow
*
k
)
const
;
void
insert
(
ItemRow
*
r
);
void
insert
(
ItemRow
*
r
);
void
erase
(
ItemRow
*
r
);
void
erase
(
ItemRow
*
r
);
// batch create
// batch create
void
reconstruct
();
void
reconstruct
();
// reorder the ItemRow's and returns new head and tail
// reorder the ItemRow's and returns new head and tail
std
::
tuple
<
ItemRow
*
,
ItemRow
*>
reorder
()
std
::
tuple
<
ItemRow
*
,
ItemRow
*>
reorder
()
{
{
std
::
tuple
<
ItemRow
*
,
ItemRow
*>
result
=
std
::
make_tuple
(
nullptr
,
nullptr
);
std
::
tuple
<
ItemRow
*
,
ItemRow
*>
result
=
std
::
make_tuple
(
nullptr
,
nullptr
);
if
(
mRoot
!=
nullptr
)
if
(
mRoot
!=
nullptr
)
{
{
entry
*
head
=
findMin
(
mRoot
);
entry
*
head
=
findMin
(
mRoot
);
entry
*
tail
=
reorder
(
mRoot
);
entry
*
tail
=
reorder
(
mRoot
);
tail
->
mRow
->
mNext
=
nullptr
;
tail
->
mRow
->
mNext
=
nullptr
;
...
@@ -723,14 +802,18 @@ class CatIndex
...
@@ -723,14 +802,18 @@ class CatIndex
}
}
size_t
size
()
const
;
size_t
size
()
const
;
// bool isValid() const;
// bool isValid() const;
private
:
private
:
struct
entry
struct
entry
{
{
entry
(
ItemRow
*
r
)
entry
(
ItemRow
*
r
)
:
mRow
(
r
),
mLeft
(
nullptr
),
mRight
(
nullptr
),
mRed
(
true
)
{}
:
mRow
(
r
)
,
mLeft
(
nullptr
)
,
mRight
(
nullptr
)
,
mRed
(
true
)
{
}
~
entry
()
~
entry
()
{
{
...
@@ -738,20 +821,20 @@ class CatIndex
...
@@ -738,20 +821,20 @@ class CatIndex
delete
mRight
;
delete
mRight
;
}
}
ItemRow
*
mRow
;
ItemRow
*
mRow
;
entry
*
mLeft
;
entry
*
mLeft
;
entry
*
mRight
;
entry
*
mRight
;
bool
mRed
;
bool
mRed
;
};
};
entry
*
insert
(
entry
*
h
,
ItemRow
*
v
);
entry
*
insert
(
entry
*
h
,
ItemRow
*
v
);
entry
*
erase
(
entry
*
h
,
ItemRow
*
k
);
entry
*
erase
(
entry
*
h
,
ItemRow
*
k
);
// void validate(entry* h, bool isParentRed, uint32_t blackDepth, uint32_t& minBlack, uint32_t& maxBlack) const;
// void validate(entry* h, bool isParentRed, uint32_t blackDepth, uint32_t& minBlack, uint32_t& maxBlack) const;
entry
*
rotateLeft
(
entry
*
h
)
entry
*
rotateLeft
(
entry
*
h
)
{
{
entry
*
x
=
h
->
mRight
;
entry
*
x
=
h
->
mRight
;
h
->
mRight
=
x
->
mLeft
;
h
->
mRight
=
x
->
mLeft
;
x
->
mLeft
=
h
;
x
->
mLeft
=
h
;
x
->
mRed
=
h
->
mRed
;
x
->
mRed
=
h
->
mRed
;
...
@@ -759,9 +842,9 @@ class CatIndex
...
@@ -759,9 +842,9 @@ class CatIndex
return
x
;
return
x
;
}
}
entry
*
rotateRight
(
entry
*
h
)
entry
*
rotateRight
(
entry
*
h
)
{
{
entry
*
x
=
h
->
mLeft
;
entry
*
x
=
h
->
mLeft
;
h
->
mLeft
=
x
->
mRight
;
h
->
mLeft
=
x
->
mRight
;
x
->
mRight
=
h
;
x
->
mRight
=
h
;
x
->
mRed
=
h
->
mRed
;
x
->
mRed
=
h
->
mRed
;
...
@@ -769,7 +852,7 @@ class CatIndex
...
@@ -769,7 +852,7 @@ class CatIndex
return
x
;
return
x
;
}
}
void
flipColour
(
entry
*
h
)
void
flipColour
(
entry
*
h
)
{
{
h
->
mRed
=
not
h
->
mRed
;
h
->
mRed
=
not
h
->
mRed
;
...
@@ -780,12 +863,12 @@ class CatIndex
...
@@ -780,12 +863,12 @@ class CatIndex
h
->
mRight
->
mRed
=
not
h
->
mRight
->
mRed
;
h
->
mRight
->
mRed
=
not
h
->
mRight
->
mRed
;
}
}
bool
isRed
(
entry
*
h
)
const
bool
isRed
(
entry
*
h
)
const
{
{
return
h
!=
nullptr
and
h
->
mRed
;
return
h
!=
nullptr
and
h
->
mRed
;
}
}
entry
*
moveRedLeft
(
entry
*
h
)
entry
*
moveRedLeft
(
entry
*
h
)
{
{
flipColour
(
h
);
flipColour
(
h
);
...
@@ -799,7 +882,7 @@ class CatIndex
...
@@ -799,7 +882,7 @@ class CatIndex
return
h
;
return
h
;
}
}
entry
*
moveRedRight
(
entry
*
h
)
entry
*
moveRedRight
(
entry
*
h
)
{
{
flipColour
(
h
);
flipColour
(
h
);
...
@@ -812,7 +895,7 @@ class CatIndex
...
@@ -812,7 +895,7 @@ class CatIndex
return
h
;
return
h
;
}
}
entry
*
fixUp
(
entry
*
h
)
entry
*
fixUp
(
entry
*
h
)
{
{
if
(
isRed
(
h
->
mRight
))
if
(
isRed
(
h
->
mRight
))
h
=
rotateLeft
(
h
);
h
=
rotateLeft
(
h
);
...
@@ -826,7 +909,7 @@ class CatIndex
...
@@ -826,7 +909,7 @@ class CatIndex
return
h
;
return
h
;
}
}
entry
*
findMin
(
entry
*
h
)
entry
*
findMin
(
entry
*
h
)
{
{
while
(
h
->
mLeft
!=
nullptr
)
while
(
h
->
mLeft
!=
nullptr
)
h
=
h
->
mLeft
;
h
=
h
->
mLeft
;
...
@@ -834,7 +917,7 @@ class CatIndex
...
@@ -834,7 +917,7 @@ class CatIndex
return
h
;
return
h
;
}
}
entry
*
eraseMin
(
entry
*
h
)
entry
*
eraseMin
(
entry
*
h
)
{
{
if
(
h
->
mLeft
==
nullptr
)
if
(
h
->
mLeft
==
nullptr
)
{
{
...
@@ -855,7 +938,7 @@ class CatIndex
...
@@ -855,7 +938,7 @@ class CatIndex
}
}
// Fix mNext fields for rows in order of this index
// Fix mNext fields for rows in order of this index
entry
*
reorder
(
entry
*
e
)
entry
*
reorder
(
entry
*
e
)
{
{
auto
result
=
e
;
auto
result
=
e
;
...
@@ -876,13 +959,15 @@ class CatIndex
...
@@ -876,13 +959,15 @@ class CatIndex
return
result
;
return
result
;
}
}
Category
&
mCat
;
Category
&
mCat
;
RowComparator
mComp
;
RowComparator
mComp
;
entry
*
mRoot
;
entry
*
mRoot
;
};
};
CatIndex
::
CatIndex
(
Category
*
cat
)
CatIndex
::
CatIndex
(
Category
*
cat
)
:
mCat
(
*
cat
),
mComp
(
cat
),
mRoot
(
nullptr
)
:
mCat
(
*
cat
)
,
mComp
(
cat
)
,
mRoot
(
nullptr
)
{
{
}
}
...
@@ -891,9 +976,9 @@ CatIndex::~CatIndex()
...
@@ -891,9 +976,9 @@ CatIndex::~CatIndex()
delete
mRoot
;
delete
mRoot
;
}
}
ItemRow
*
CatIndex
::
find
(
ItemRow
*
k
)
const
ItemRow
*
CatIndex
::
find
(
ItemRow
*
k
)
const
{
{
const
entry
*
r
=
mRoot
;
const
entry
*
r
=
mRoot
;
while
(
r
!=
nullptr
)
while
(
r
!=
nullptr
)
{
{
int
d
=
mComp
(
k
,
r
->
mRow
);
int
d
=
mComp
(
k
,
r
->
mRow
);
...
@@ -908,20 +993,22 @@ ItemRow* CatIndex::find(ItemRow* k) const
...
@@ -908,20 +993,22 @@ ItemRow* CatIndex::find(ItemRow* k) const
return
r
?
r
->
mRow
:
nullptr
;
return
r
?
r
->
mRow
:
nullptr
;
}
}
void
CatIndex
::
insert
(
ItemRow
*
k
)
void
CatIndex
::
insert
(
ItemRow
*
k
)
{
{
mRoot
=
insert
(
mRoot
,
k
);
mRoot
=
insert
(
mRoot
,
k
);
mRoot
->
mRed
=
false
;
mRoot
->
mRed
=
false
;
}
}
CatIndex
::
entry
*
CatIndex
::
insert
(
entry
*
h
,
ItemRow
*
v
)
CatIndex
::
entry
*
CatIndex
::
insert
(
entry
*
h
,
ItemRow
*
v
)
{
{
if
(
h
==
nullptr
)
if
(
h
==
nullptr
)
return
new
entry
(
v
);
return
new
entry
(
v
);
int
d
=
mComp
(
v
,
h
->
mRow
);
int
d
=
mComp
(
v
,
h
->
mRow
);
if
(
d
<
0
)
h
->
mLeft
=
insert
(
h
->
mLeft
,
v
);
if
(
d
<
0
)
else
if
(
d
>
0
)
h
->
mRight
=
insert
(
h
->
mRight
,
v
);
h
->
mLeft
=
insert
(
h
->
mLeft
,
v
);
else
if
(
d
>
0
)
h
->
mRight
=
insert
(
h
->
mRight
,
v
);
else
else
throw
std
::
runtime_error
(
"Duplicate Key violation, cat: "
+
mCat
.
name
()
+
" values: "
+
v
->
str
());
throw
std
::
runtime_error
(
"Duplicate Key violation, cat: "
+
mCat
.
name
()
+
" values: "
+
v
->
str
());
...
@@ -937,14 +1024,14 @@ CatIndex::entry* CatIndex::insert(entry* h, ItemRow* v)
...
@@ -937,14 +1024,14 @@ CatIndex::entry* CatIndex::insert(entry* h, ItemRow* v)
return
h
;
return
h
;
}
}
void
CatIndex
::
erase
(
ItemRow
*
k
)
void
CatIndex
::
erase
(
ItemRow
*
k
)
{
{
mRoot
=
erase
(
mRoot
,
k
);
mRoot
=
erase
(
mRoot
,
k
);
if
(
mRoot
!=
nullptr
)
if
(
mRoot
!=
nullptr
)
mRoot
->
mRed
=
false
;
mRoot
->
mRed
=
false
;
}
}
CatIndex
::
entry
*
CatIndex
::
erase
(
entry
*
h
,
ItemRow
*
k
)
CatIndex
::
entry
*
CatIndex
::
erase
(
entry
*
h
,
ItemRow
*
k
)
{
{
if
(
mComp
(
k
,
h
->
mRow
)
<
0
)
if
(
mComp
(
k
,
h
->
mRow
)
<
0
)
{
{
...
@@ -990,88 +1077,88 @@ void CatIndex::reconstruct()
...
@@ -990,88 +1077,88 @@ void CatIndex::reconstruct()
delete
mRoot
;
delete
mRoot
;
mRoot
=
nullptr
;
mRoot
=
nullptr
;
for
(
auto
r
:
mCat
)
for
(
auto
r
:
mCat
)
insert
(
r
.
mData
);
insert
(
r
.
mData
);
// maybe reconstruction can be done quicker by using the following commented code.
// maybe reconstruction can be done quicker by using the following commented code.
// however, I've not had the time to think of a way to std::set the red/black flag correctly in that case.
// however, I've not had the time to think of a way to std::set the red/black flag correctly in that case.
// std::vector<ItemRow*> rows;
// std::vector<ItemRow*> rows;
// transform(mCat.begin(), mCat.end(), backInserter(rows),
// transform(mCat.begin(), mCat.end(), backInserter(rows),
// [](Row r) -> ItemRow* { assert(r.mData); return r.mData; });
// [](Row r) -> ItemRow* { assert(r.mData); return r.mData; });
//
//
// assert(std::find(rows.begin(), rows.end(), nullptr) == rows.end());
// assert(std::find(rows.begin(), rows.end(), nullptr) == rows.end());
//
//
// // don't use sort here, it will run out of the stack of something.
// // don't use sort here, it will run out of the stack of something.
// // quicksort is notorious for using excessive recursion.
// // quicksort is notorious for using excessive recursion.
// // Besides, most of the time, the data is ordered already anyway.
// // Besides, most of the time, the data is ordered already anyway.
//
//
// stable_sort(rows.begin(), rows.end(), [this](ItemRow* a, ItemRow* b) -> bool { return this->mComp(a, b) < 0; });
// stable_sort(rows.begin(), rows.end(), [this](ItemRow* a, ItemRow* b) -> bool { return this->mComp(a, b) < 0; });
//
//
// for (size_t i = 0; i < rows.size() - 1; ++i)
// for (size_t i = 0; i < rows.size() - 1; ++i)
// assert(mComp(rows[i], rows[i + 1]) < 0);
// assert(mComp(rows[i], rows[i + 1]) < 0);
//
//
// deque<entry*> e;
// deque<entry*> e;
// transform(rows.begin(), rows.end(), back_inserter(e),
// transform(rows.begin(), rows.end(), back_inserter(e),
// [](ItemRow* r) -> entry* { return new entry(r); });
// [](ItemRow* r) -> entry* { return new entry(r); });
//
//
// while (e.size() > 1)
// while (e.size() > 1)
// {
// {
// deque<entry*> ne;
// deque<entry*> ne;
//
//
// while (not e.empty())
// while (not e.empty())
// {
// {
// entry* a = e.front();
// entry* a = e.front();
// e.pop_front();
// e.pop_front();
//
//
// if (e.empty())
// if (e.empty())
// ne.push_back(a);
// ne.push_back(a);
// else
// else
// {
// {
// entry* b = e.front();
// entry* b = e.front();
// b->mLeft = a;
// b->mLeft = a;
//
//
// assert(mComp(a->mRow, b->mRow) < 0);
// assert(mComp(a->mRow, b->mRow) < 0);
//
//
// e.pop_front();
// e.pop_front();
//
//
// if (not e.empty())
// if (not e.empty())
// {
// {
// entry* c = e.front();
// entry* c = e.front();
// e.pop_front();
// e.pop_front();
//
//
// assert(mComp(b->mRow, c->mRow) < 0);
// assert(mComp(b->mRow, c->mRow) < 0);
//
//
// b->mRight = c;
// b->mRight = c;
// }
// }
//
//
// ne.push_back(b);
// ne.push_back(b);
//
//
// if (not e.empty())
// if (not e.empty())
// {
// {
// ne.push_back(e.front());
// ne.push_back(e.front());
// e.pop_front();
// e.pop_front();
// }
// }
// }
// }
// }
// }
//
//
// swap (e, ne);
// swap (e, ne);
// }
// }
//
//
// assert(e.size() == 1);
// assert(e.size() == 1);
// mRoot = e.front();
// mRoot = e.front();
}
}
size_t
CatIndex
::
size
()
const
size_t
CatIndex
::
size
()
const
{
{
std
::
stack
<
entry
*>
s
;
std
::
stack
<
entry
*>
s
;
s
.
push
(
mRoot
);
s
.
push
(
mRoot
);
size_t
result
=
0
;
size_t
result
=
0
;
while
(
not
s
.
empty
())
while
(
not
s
.
empty
())
{
{
entry
*
e
=
s
.
top
();
entry
*
e
=
s
.
top
();
s
.
pop
();
s
.
pop
();
if
(
e
==
nullptr
)
if
(
e
==
nullptr
)
...
@@ -1153,36 +1240,36 @@ size_t CatIndex::size() const
...
@@ -1153,36 +1240,36 @@ size_t CatIndex::size() const
// --------------------------------------------------------------------
// --------------------------------------------------------------------
RowSet
::
RowSet
(
Category
&
cat
)
RowSet
::
RowSet
(
Category
&
cat
)
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
// , mCond(nullptr)
// , mCond(nullptr)
{
{
}
}
RowSet
::
RowSet
(
Category
&
cat
,
Condition
&&
cond
)
RowSet
::
RowSet
(
Category
&
cat
,
Condition
&&
cond
)
:
mCat
(
&
cat
)
:
mCat
(
&
cat
)
// , mCond(new Condition(std::forward<Condition>(cond)))
// , mCond(new Condition(std::forward<Condition>(cond)))
{
{
cond
.
prepare
(
cat
);
cond
.
prepare
(
cat
);
for
(
auto
r
:
cat
)
for
(
auto
r
:
cat
)
{
{
if
(
cond
(
cat
,
r
))
if
(
cond
(
cat
,
r
))
mItems
.
push_back
(
r
.
mData
);
mItems
.
push_back
(
r
.
mData
);
}
}
}
}
RowSet
::
RowSet
(
const
RowSet
&
rhs
)
RowSet
::
RowSet
(
const
RowSet
&
rhs
)
:
mCat
(
rhs
.
mCat
)
:
mCat
(
rhs
.
mCat
)
,
mItems
(
rhs
.
mItems
)
,
mItems
(
rhs
.
mItems
)
// , mCond(nullptr)
// , mCond(nullptr)
{
{
}
}
RowSet
::
RowSet
(
RowSet
&&
rhs
)
RowSet
::
RowSet
(
RowSet
&&
rhs
)
:
mCat
(
rhs
.
mCat
)
:
mCat
(
rhs
.
mCat
)
,
mItems
(
std
::
move
(
rhs
.
mItems
))
,
mItems
(
std
::
move
(
rhs
.
mItems
))
// , mCond(rhs.mCond)
// , mCond(rhs.mCond)
{
{
// rhs.mCond = nullptr;
// rhs.mCond = nullptr;
}
}
...
@@ -1192,7 +1279,7 @@ RowSet::~RowSet()
...
@@ -1192,7 +1279,7 @@ RowSet::~RowSet()
// delete mCond;
// delete mCond;
}
}
RowSet
&
RowSet
::
operator
=
(
const
RowSet
&
rhs
)
RowSet
&
RowSet
::
operator
=
(
const
RowSet
&
rhs
)
{
{
if
(
this
!=
&
rhs
)
if
(
this
!=
&
rhs
)
{
{
...
@@ -1203,7 +1290,7 @@ RowSet& RowSet::operator=(const RowSet& rhs)
...
@@ -1203,7 +1290,7 @@ RowSet& RowSet::operator=(const RowSet& rhs)
return
*
this
;
return
*
this
;
}
}
RowSet
&
RowSet
::
operator
=
(
RowSet
&&
rhs
)
RowSet
&
RowSet
::
operator
=
(
RowSet
&&
rhs
)
{
{
if
(
this
!=
&
rhs
)
if
(
this
!=
&
rhs
)
{
{
...
@@ -1214,7 +1301,7 @@ RowSet& RowSet::operator=(RowSet&& rhs)
...
@@ -1214,7 +1301,7 @@ RowSet& RowSet::operator=(RowSet&& rhs)
return
*
this
;
return
*
this
;
}
}
RowSet
&
RowSet
::
orderBy
(
std
::
initializer_list
<
std
::
string
>
items
)
RowSet
&
RowSet
::
orderBy
(
std
::
initializer_list
<
std
::
string
>
items
)
{
{
RowComparator
c
(
mCat
,
items
.
begin
(),
items
.
end
());
RowComparator
c
(
mCat
,
items
.
begin
(),
items
.
end
());
...
@@ -1225,9 +1312,13 @@ RowSet& RowSet::orderBy(std::initializer_list<std::string> items)
...
@@ -1225,9 +1312,13 @@ RowSet& RowSet::orderBy(std::initializer_list<std::string> items)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
Category
::
Category
(
Datablock
&
db
,
const
std
::
string
&
name
,
Validator
*
Validator
)
Category
::
Category
(
Datablock
&
db
,
const
std
::
string
&
name
,
Validator
*
Validator
)
:
mDb
(
db
),
mName
(
name
),
mValidator
(
Validator
)
:
mDb
(
db
)
,
mHead
(
nullptr
),
mTail
(
nullptr
),
mIndex
(
nullptr
)
,
mName
(
name
)
,
mValidator
(
Validator
)
,
mHead
(
nullptr
)
,
mTail
(
nullptr
)
,
mIndex
(
nullptr
)
{
{
if
(
mName
.
empty
())
if
(
mName
.
empty
())
throw
ValidationError
(
"invalid empty name for Category"
);
throw
ValidationError
(
"invalid empty name for Category"
);
...
@@ -1239,10 +1330,10 @@ Category::Category(Datablock& db, const std::string& name, Validator* Validator)
...
@@ -1239,10 +1330,10 @@ Category::Category(Datablock& db, const std::string& name, Validator* Validator)
{
{
// make sure all required columns are added
// make sure all required columns are added
for
(
auto
&
k
:
mCatValidator
->
mKeys
)
for
(
auto
&
k
:
mCatValidator
->
mKeys
)
addColumn
(
k
);
addColumn
(
k
);
for
(
auto
&
k
:
mCatValidator
->
mMandatoryFields
)
for
(
auto
&
k
:
mCatValidator
->
mMandatoryFields
)
addColumn
(
k
);
addColumn
(
k
);
mIndex
=
new
CatIndex
(
this
);
mIndex
=
new
CatIndex
(
this
);
...
@@ -1256,7 +1347,7 @@ Category::~Category()
...
@@ -1256,7 +1347,7 @@ Category::~Category()
delete
mIndex
;
delete
mIndex
;
}
}
void
Category
::
setValidator
(
Validator
*
v
)
void
Category
::
setValidator
(
Validator
*
v
)
{
{
mValidator
=
v
;
mValidator
=
v
;
...
@@ -1273,22 +1364,22 @@ void Category::setValidator(Validator* v)
...
@@ -1273,22 +1364,22 @@ void Category::setValidator(Validator* v)
{
{
mIndex
=
new
CatIndex
(
this
);
mIndex
=
new
CatIndex
(
this
);
mIndex
->
reconstruct
();
mIndex
->
reconstruct
();
//#if DEBUG
//#if DEBUG
// assert(mIndex->size() == size());
// assert(mIndex->size() == size());
// mIndex->validate();
// mIndex->validate();
//#endif
//#endif
}
}
}
}
else
else
mCatValidator
=
nullptr
;
mCatValidator
=
nullptr
;
}
}
bool
Category
::
hasColumn
(
const
std
::
string
&
name
)
const
bool
Category
::
hasColumn
(
const
std
::
string
&
name
)
const
{
{
return
getColumnIndex
(
name
)
<
mColumns
.
size
();
return
getColumnIndex
(
name
)
<
mColumns
.
size
();
}
}
size_t
Category
::
getColumnIndex
(
const
std
::
string
&
name
)
const
size_t
Category
::
getColumnIndex
(
const
std
::
string
&
name
)
const
{
{
size_t
result
;
size_t
result
;
...
@@ -1308,7 +1399,7 @@ size_t Category::getColumnIndex(const std::string& name) const
...
@@ -1308,7 +1399,7 @@ size_t Category::getColumnIndex(const std::string& name) const
return
result
;
return
result
;
}
}
const
std
::
string
&
Category
::
getColumnName
(
size_t
columnIx
)
const
const
std
::
string
&
Category
::
getColumnName
(
size_t
columnIx
)
const
{
{
return
mColumns
.
at
(
columnIx
).
mName
;
return
mColumns
.
at
(
columnIx
).
mName
;
}
}
...
@@ -1316,18 +1407,18 @@ const std::string& Category::getColumnName(size_t columnIx) const
...
@@ -1316,18 +1407,18 @@ const std::string& Category::getColumnName(size_t columnIx) const
std
::
vector
<
std
::
string
>
Category
::
getColumnNames
()
const
std
::
vector
<
std
::
string
>
Category
::
getColumnNames
()
const
{
{
std
::
vector
<
std
::
string
>
result
;
std
::
vector
<
std
::
string
>
result
;
for
(
auto
&
c
:
mColumns
)
for
(
auto
&
c
:
mColumns
)
result
.
push_back
(
c
.
mName
);
result
.
push_back
(
c
.
mName
);
return
result
;
return
result
;
}
}
size_t
Category
::
addColumn
(
const
std
::
string
&
name
)
size_t
Category
::
addColumn
(
const
std
::
string
&
name
)
{
{
size_t
result
=
getColumnIndex
(
name
);
size_t
result
=
getColumnIndex
(
name
);
if
(
result
==
mColumns
.
size
())
if
(
result
==
mColumns
.
size
())
{
{
const
ValidateItem
*
itemValidator
=
nullptr
;
const
ValidateItem
*
itemValidator
=
nullptr
;
if
(
mCatValidator
!=
nullptr
)
if
(
mCatValidator
!=
nullptr
)
{
{
...
@@ -1363,17 +1454,17 @@ void Category::reorderByIndex()
...
@@ -1363,17 +1454,17 @@ void Category::reorderByIndex()
std
::
tie
(
mHead
,
mTail
)
=
mIndex
->
reorder
();
std
::
tie
(
mHead
,
mTail
)
=
mIndex
->
reorder
();
}
}
void
Category
::
sort
(
std
::
function
<
int
(
const
Row
&
,
const
Row
&
)
>
comparator
)
void
Category
::
sort
(
std
::
function
<
int
(
const
Row
&
,
const
Row
&
)
>
comparator
)
{
{
if
(
mHead
==
nullptr
)
if
(
mHead
==
nullptr
)
return
;
return
;
std
::
vector
<
ItemRow
*>
rows
;
std
::
vector
<
ItemRow
*>
rows
;
for
(
auto
itemRow
=
mHead
;
itemRow
!=
nullptr
;
itemRow
=
itemRow
->
mNext
)
for
(
auto
itemRow
=
mHead
;
itemRow
!=
nullptr
;
itemRow
=
itemRow
->
mNext
)
rows
.
push_back
(
itemRow
);
rows
.
push_back
(
itemRow
);
std
::
stable_sort
(
rows
.
begin
(),
rows
.
end
(),
std
::
stable_sort
(
rows
.
begin
(),
rows
.
end
(),
[
&
comparator
](
ItemRow
*
ia
,
ItemRow
*
ib
)
[
&
comparator
](
ItemRow
*
ia
,
ItemRow
*
ib
)
{
{
Row
ra
(
ia
);
Row
ra
(
ia
);
Row
rb
(
ib
);
Row
rb
(
ib
);
...
@@ -1428,11 +1519,12 @@ bool Category::empty() const
...
@@ -1428,11 +1519,12 @@ bool Category::empty() const
return
mHead
==
nullptr
or
mHead
->
mValues
==
nullptr
;
return
mHead
==
nullptr
or
mHead
->
mValues
==
nullptr
;
}
}
void
Category
::
drop
(
const
std
::
string
&
field
)
void
Category
::
drop
(
const
std
::
string
&
field
)
{
{
using
namespace
std
::
placeholders
;
using
namespace
std
::
placeholders
;
auto
ci
=
find_if
(
mColumns
.
begin
(),
mColumns
.
end
(),
auto
ci
=
find_if
(
mColumns
.
begin
(),
mColumns
.
end
(),
[
field
](
ItemColumn
&
c
)
->
bool
{
return
iequals
(
c
.
mName
,
field
);
});
[
field
](
ItemColumn
&
c
)
->
bool
{
return
iequals
(
c
.
mName
,
field
);
});
if
(
ci
!=
mColumns
.
end
())
if
(
ci
!=
mColumns
.
end
())
{
{
...
@@ -1445,13 +1537,13 @@ void Category::drop(const std::string& field)
...
@@ -1445,13 +1537,13 @@ void Category::drop(const std::string& field)
}
}
}
}
Row
Category
::
operator
[](
Condition
&&
cond
)
Row
Category
::
operator
[](
Condition
&&
cond
)
{
{
Row
result
;
Row
result
;
cond
.
prepare
(
*
this
);
cond
.
prepare
(
*
this
);
for
(
auto
r
:
*
this
)
for
(
auto
r
:
*
this
)
{
{
if
(
cond
(
*
this
,
r
))
if
(
cond
(
*
this
,
r
))
{
{
...
@@ -1478,13 +1570,13 @@ Row Category::operator[](Condition&& cond)
...
@@ -1478,13 +1570,13 @@ Row Category::operator[](Condition&& cond)
// return result;
// return result;
// }
// }
bool
Category
::
exists
(
Condition
&&
cond
)
const
bool
Category
::
exists
(
Condition
&&
cond
)
const
{
{
bool
result
=
false
;
bool
result
=
false
;
cond
.
prepare
(
*
this
);
cond
.
prepare
(
*
this
);
for
(
auto
r
:
*
this
)
for
(
auto
r
:
*
this
)
{
{
if
(
cond
(
*
this
,
r
))
if
(
cond
(
*
this
,
r
))
{
{
...
@@ -1516,8 +1608,8 @@ void Category::clear()
...
@@ -1516,8 +1608,8 @@ void Category::clear()
}
}
}
}
template
<
class
Iter
>
template
<
class
Iter
>
std
::
tuple
<
Row
,
bool
>
Category
::
emplace
(
Iter
b
,
Iter
e
)
std
::
tuple
<
Row
,
bool
>
Category
::
emplace
(
Iter
b
,
Iter
e
)
{
{
// First, make sure all mandatory fields are supplied
// First, make sure all mandatory fields are supplied
Row
result
;
Row
result
;
...
@@ -1525,7 +1617,7 @@ std::tuple<Row,bool> Category::emplace(Iter b, Iter e)
...
@@ -1525,7 +1617,7 @@ std::tuple<Row,bool> Category::emplace(Iter b, Iter e)
if
(
mCatValidator
!=
nullptr
and
b
!=
e
)
if
(
mCatValidator
!=
nullptr
and
b
!=
e
)
{
{
for
(
auto
&
col
:
mColumns
)
for
(
auto
&
col
:
mColumns
)
{
{
auto
iv
=
mCatValidator
->
getValidatorForItem
(
col
.
mName
);
auto
iv
=
mCatValidator
->
getValidatorForItem
(
col
.
mName
);
...
@@ -1601,15 +1693,15 @@ std::tuple<Row,bool> Category::emplace(Iter b, Iter e)
...
@@ -1601,15 +1693,15 @@ std::tuple<Row,bool> Category::emplace(Iter b, Iter e)
mIndex
->
insert
(
nr
);
mIndex
->
insert
(
nr
);
}
}
return
{
result
,
isNew
};
return
{
result
,
isNew
};
}
}
std
::
tuple
<
Row
,
bool
>
Category
::
emplace
(
Row
r
)
std
::
tuple
<
Row
,
bool
>
Category
::
emplace
(
Row
r
)
{
{
return
emplace
(
r
.
begin
(),
r
.
end
());
return
emplace
(
r
.
begin
(),
r
.
end
());
}
}
size_t
Category
::
erase
(
Condition
&&
cond
)
size_t
Category
::
erase
(
Condition
&&
cond
)
{
{
size_t
result
=
0
;
size_t
result
=
0
;
...
@@ -1630,7 +1722,7 @@ size_t Category::erase(Condition&& cond)
...
@@ -1630,7 +1722,7 @@ size_t Category::erase(Condition&& cond)
return
result
;
return
result
;
}
}
size_t
Category
::
erase
(
Condition
&&
cond
,
std
::
function
<
void
(
const
Row
&
)
>&&
verbose
)
size_t
Category
::
erase
(
Condition
&&
cond
,
std
::
function
<
void
(
const
Row
&
)
>
&&
verbose
)
{
{
size_t
result
=
0
;
size_t
result
=
0
;
...
@@ -1652,13 +1744,13 @@ size_t Category::erase(Condition&& cond, std::function<void(const Row&)>&& verbo
...
@@ -1652,13 +1744,13 @@ size_t Category::erase(Condition&& cond, std::function<void(const Row&)>&& verbo
return
result
;
return
result
;
}
}
void
Category
::
eraseOrphans
(
Condition
&&
cond
)
void
Category
::
eraseOrphans
(
Condition
&&
cond
)
{
{
std
::
vector
<
ItemRow
*>
remove
;
std
::
vector
<
ItemRow
*>
remove
;
cond
.
prepare
(
*
this
);
cond
.
prepare
(
*
this
);
for
(
auto
r
:
*
this
)
for
(
auto
r
:
*
this
)
{
{
if
(
cond
(
*
this
,
r
)
and
isOrphan
(
r
))
if
(
cond
(
*
this
,
r
)
and
isOrphan
(
r
))
{
{
...
@@ -1671,7 +1763,7 @@ void Category::eraseOrphans(Condition&& cond)
...
@@ -1671,7 +1763,7 @@ void Category::eraseOrphans(Condition&& cond)
}
}
}
}
for
(
auto
r
:
remove
)
for
(
auto
r
:
remove
)
erase
(
iterator
(
r
));
erase
(
iterator
(
r
));
}
}
...
@@ -1723,7 +1815,7 @@ auto Category::erase(iterator pos) -> iterator
...
@@ -1723,7 +1815,7 @@ auto Category::erase(iterator pos) -> iterator
if
(
mValidator
!=
nullptr
)
if
(
mValidator
!=
nullptr
)
{
{
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
))
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
))
{
{
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
if
(
childCat
==
nullptr
)
if
(
childCat
==
nullptr
)
...
@@ -1733,7 +1825,7 @@ auto Category::erase(iterator pos) -> iterator
...
@@ -1733,7 +1825,7 @@ auto Category::erase(iterator pos) -> iterator
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
{
{
const
char
*
value
=
r
[
link
->
mParentKeys
[
ix
]].
c_str
();
const
char
*
value
=
r
[
link
->
mParentKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mChildKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mChildKeys
[
ix
])
==
value
);
}
}
...
@@ -1780,15 +1872,15 @@ Row Category::copyRow(const Row &row)
...
@@ -1780,15 +1872,15 @@ Row Category::copyRow(const Row &row)
}
}
}
}
auto
&&
[
result
,
inserted
]
=
emplace
(
items
.
begin
(),
items
.
end
());
auto
&&
[
result
,
inserted
]
=
emplace
(
items
.
begin
(),
items
.
end
());
// assert(inserted);
// assert(inserted);
return
result
;
return
result
;
}
}
void
Category
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
void
Category
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
{
{
for
(
auto
&
c
:
mColumns
)
for
(
auto
&
c
:
mColumns
)
tags
.
push_back
(
"_"
+
mName
+
"."
+
c
.
mName
);
tags
.
push_back
(
"_"
+
mName
+
"."
+
c
.
mName
);
}
}
...
@@ -1822,7 +1914,7 @@ Category::const_iterator Category::end() const
...
@@ -1822,7 +1914,7 @@ Category::const_iterator Category::end() const
return
const_iterator
();
return
const_iterator
();
}
}
bool
Category
::
hasParent
(
Row
r
,
const
Category
&
parentCat
,
const
ValidateLink
&
link
)
const
bool
Category
::
hasParent
(
Row
r
,
const
Category
&
parentCat
,
const
ValidateLink
&
link
)
const
{
{
assert
(
mValidator
!=
nullptr
);
assert
(
mValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
...
@@ -1832,7 +1924,7 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l
...
@@ -1832,7 +1924,7 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l
Condition
cond
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
.
mChildKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
.
mChildKeys
.
size
();
++
ix
)
{
{
auto
&
name
=
link
.
mChildKeys
[
ix
];
auto
&
name
=
link
.
mChildKeys
[
ix
];
auto
field
=
r
[
name
];
auto
field
=
r
[
name
];
if
(
field
.
empty
())
if
(
field
.
empty
())
{
{
...
@@ -1841,7 +1933,7 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l
...
@@ -1841,7 +1933,7 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l
}
}
else
else
{
{
const
char
*
value
=
field
.
c_str
();
const
char
*
value
=
field
.
c_str
();
cond
=
std
::
move
(
cond
)
and
(
Key
(
link
.
mParentKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
and
(
Key
(
link
.
mParentKeys
[
ix
])
==
value
);
}
}
}
}
...
@@ -1866,7 +1958,7 @@ bool Category::isOrphan(Row r)
...
@@ -1866,7 +1958,7 @@ bool Category::isOrphan(Row r)
return
false
;
return
false
;
bool
isOrphan
=
true
;
bool
isOrphan
=
true
;
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
{
{
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
if
(
parentCat
==
nullptr
)
if
(
parentCat
==
nullptr
)
...
@@ -1875,7 +1967,7 @@ bool Category::isOrphan(Row r)
...
@@ -1875,7 +1967,7 @@ bool Category::isOrphan(Row r)
Condition
cond
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
{
{
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
}
}
...
@@ -1902,7 +1994,7 @@ bool Category::hasChildren(Row r) const
...
@@ -1902,7 +1994,7 @@ bool Category::hasChildren(Row r) const
bool
result
=
false
;
bool
result
=
false
;
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
))
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
))
{
{
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
if
(
childCat
==
nullptr
)
if
(
childCat
==
nullptr
)
...
@@ -1912,7 +2004,7 @@ bool Category::hasChildren(Row r) const
...
@@ -1912,7 +2004,7 @@ bool Category::hasChildren(Row r) const
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
{
{
const
char
*
value
=
r
[
link
->
mParentKeys
[
ix
]].
c_str
();
const
char
*
value
=
r
[
link
->
mParentKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mChildKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mChildKeys
[
ix
])
==
value
);
}
}
...
@@ -1933,7 +2025,7 @@ bool Category::hasParents(Row r) const
...
@@ -1933,7 +2025,7 @@ bool Category::hasParents(Row r) const
bool
result
=
false
;
bool
result
=
false
;
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
{
{
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
if
(
parentCat
==
nullptr
)
if
(
parentCat
==
nullptr
)
...
@@ -1943,7 +2035,7 @@ bool Category::hasParents(Row r) const
...
@@ -1943,7 +2035,7 @@ bool Category::hasParents(Row r) const
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
{
{
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
}
}
...
@@ -1957,19 +2049,19 @@ bool Category::hasParents(Row r) const
...
@@ -1957,19 +2049,19 @@ bool Category::hasParents(Row r) const
return
result
;
return
result
;
}
}
RowSet
Category
::
getChildren
(
Row
r
,
const
char
*
childCat
)
RowSet
Category
::
getChildren
(
Row
r
,
const
char
*
childCat
)
{
{
return
getChildren
(
r
,
mDb
[
childCat
]);
return
getChildren
(
r
,
mDb
[
childCat
]);
}
}
RowSet
Category
::
getChildren
(
Row
r
,
Category
&
childCat
)
RowSet
Category
::
getChildren
(
Row
r
,
Category
&
childCat
)
{
{
assert
(
mValidator
!=
nullptr
);
assert
(
mValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
RowSet
result
(
childCat
);
RowSet
result
(
childCat
);
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
))
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
))
{
{
if
(
link
->
mChildCategory
!=
childCat
.
mName
)
if
(
link
->
mChildCategory
!=
childCat
.
mName
)
continue
;
continue
;
...
@@ -1978,7 +2070,7 @@ RowSet Category::getChildren(Row r, Category& childCat)
...
@@ -1978,7 +2070,7 @@ RowSet Category::getChildren(Row r, Category& childCat)
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
{
{
const
char
*
value
=
r
[
link
->
mParentKeys
[
ix
]].
c_str
();
const
char
*
value
=
r
[
link
->
mParentKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mChildKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mChildKeys
[
ix
])
==
value
);
}
}
...
@@ -1993,19 +2085,19 @@ RowSet Category::getChildren(Row r, Category& childCat)
...
@@ -1993,19 +2085,19 @@ RowSet Category::getChildren(Row r, Category& childCat)
return
result
;
return
result
;
}
}
RowSet
Category
::
getParents
(
Row
r
,
const
char
*
parentCat
)
RowSet
Category
::
getParents
(
Row
r
,
const
char
*
parentCat
)
{
{
return
getParents
(
r
,
mDb
[
parentCat
]);
return
getParents
(
r
,
mDb
[
parentCat
]);
}
}
RowSet
Category
::
getParents
(
Row
r
,
Category
&
parentCat
)
RowSet
Category
::
getParents
(
Row
r
,
Category
&
parentCat
)
{
{
assert
(
mValidator
!=
nullptr
);
assert
(
mValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
RowSet
result
(
parentCat
);
RowSet
result
(
parentCat
);
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
{
{
if
(
link
->
mParentCategory
!=
parentCat
.
mName
)
if
(
link
->
mParentCategory
!=
parentCat
.
mName
)
continue
;
continue
;
...
@@ -2014,7 +2106,7 @@ RowSet Category::getParents(Row r, Category& parentCat)
...
@@ -2014,7 +2106,7 @@ RowSet Category::getParents(Row r, Category& parentCat)
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
{
{
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
}
}
...
@@ -2029,12 +2121,12 @@ RowSet Category::getParents(Row r, Category& parentCat)
...
@@ -2029,12 +2121,12 @@ RowSet Category::getParents(Row r, Category& parentCat)
return
result
;
return
result
;
}
}
RowSet
Category
::
getLinked
(
Row
r
,
const
char
*
cat
)
RowSet
Category
::
getLinked
(
Row
r
,
const
char
*
cat
)
{
{
return
getLinked
(
r
,
mDb
[
cat
]);
return
getLinked
(
r
,
mDb
[
cat
]);
}
}
RowSet
Category
::
getLinked
(
Row
r
,
Category
&
cat
)
RowSet
Category
::
getLinked
(
Row
r
,
Category
&
cat
)
{
{
RowSet
result
=
getChildren
(
r
,
cat
);
RowSet
result
=
getChildren
(
r
,
cat
);
if
(
result
.
empty
())
if
(
result
.
empty
())
...
@@ -2064,7 +2156,7 @@ bool Category::isValid()
...
@@ -2064,7 +2156,7 @@ bool Category::isValid()
auto
mandatory
=
mCatValidator
->
mMandatoryFields
;
auto
mandatory
=
mCatValidator
->
mMandatoryFields
;
for
(
auto
&
col
:
mColumns
)
for
(
auto
&
col
:
mColumns
)
{
{
auto
iv
=
mCatValidator
->
getValidatorForItem
(
col
.
mName
);
auto
iv
=
mCatValidator
->
getValidatorForItem
(
col
.
mName
);
if
(
iv
==
nullptr
)
if
(
iv
==
nullptr
)
...
@@ -2084,18 +2176,18 @@ bool Category::isValid()
...
@@ -2084,18 +2176,18 @@ bool Category::isValid()
result
=
false
;
result
=
false
;
}
}
//#if not defined(NDEBUG)
//#if not defined(NDEBUG)
// // check index?
// // check index?
// if (mIndex)
// if (mIndex)
// {
// {
// mIndex->validate();
// mIndex->validate();
// for (auto r: *this)
// for (auto r: *this)
// {
// {
// if (mIndex->find(r.mData) != r.mData)
// if (mIndex->find(r.mData) != r.mData)
// mValidator->reportError("Key not found in index for Category " + mName);
// mValidator->reportError("Key not found in index for Category " + mName);
// }
// }
// }
// }
//#endif
//#endif
// validate all values
// validate all values
mandatory
=
mCatValidator
->
mMandatoryFields
;
mandatory
=
mCatValidator
->
mMandatoryFields
;
...
@@ -2123,7 +2215,7 @@ bool Category::isValid()
...
@@ -2123,7 +2215,7 @@ bool Category::isValid()
{
{
(
*
iv
)(
vi
->
mText
);
(
*
iv
)(
vi
->
mText
);
}
}
catch
(
const
std
::
exception
&
e
)
catch
(
const
std
::
exception
&
e
)
{
{
mValidator
->
reportError
(
"Error validating "
+
mColumns
[
cix
].
mName
+
": "
+
e
.
what
(),
false
);
mValidator
->
reportError
(
"Error validating "
+
mColumns
[
cix
].
mName
+
": "
+
e
.
what
(),
false
);
continue
;
continue
;
...
@@ -2147,16 +2239,16 @@ bool Category::isValid()
...
@@ -2147,16 +2239,16 @@ bool Category::isValid()
void
Category
::
validateLinks
()
const
void
Category
::
validateLinks
()
const
{
{
auto
&
validator
=
getValidator
();
auto
&
validator
=
getValidator
();
for
(
auto
linkValidator
:
validator
.
getLinksForChild
(
mName
))
for
(
auto
linkValidator
:
validator
.
getLinksForChild
(
mName
))
{
{
auto
parent
=
mDb
.
get
(
linkValidator
->
mParentCategory
);
auto
parent
=
mDb
.
get
(
linkValidator
->
mParentCategory
);
if
(
parent
==
nullptr
)
if
(
parent
==
nullptr
)
continue
;
continue
;
size_t
missing
=
0
;
size_t
missing
=
0
;
for
(
auto
r
:
*
this
)
for
(
auto
r
:
*
this
)
if
(
not
hasParent
(
r
,
*
parent
,
*
linkValidator
))
if
(
not
hasParent
(
r
,
*
parent
,
*
linkValidator
))
++
missing
;
++
missing
;
...
@@ -2168,7 +2260,7 @@ void Category::validateLinks() const
...
@@ -2168,7 +2260,7 @@ void Category::validateLinks() const
}
}
}
}
const
Validator
&
Category
::
getValidator
()
const
const
Validator
&
Category
::
getValidator
()
const
{
{
if
(
mValidator
==
nullptr
)
if
(
mValidator
==
nullptr
)
throw
std
::
runtime_error
(
"no Validator defined yet"
);
throw
std
::
runtime_error
(
"no Validator defined yet"
);
...
@@ -2184,7 +2276,7 @@ iset Category::fields() const
...
@@ -2184,7 +2276,7 @@ iset Category::fields() const
mValidator
->
reportError
(
"undefined Category"
,
true
);
mValidator
->
reportError
(
"undefined Category"
,
true
);
iset
result
;
iset
result
;
for
(
auto
&
iv
:
mCatValidator
->
mItemValidators
)
for
(
auto
&
iv
:
mCatValidator
->
mItemValidators
)
result
.
insert
(
iv
.
mTag
);
result
.
insert
(
iv
.
mTag
);
return
result
;
return
result
;
}
}
...
@@ -2208,7 +2300,7 @@ iset Category::keyFields() const
...
@@ -2208,7 +2300,7 @@ iset Category::keyFields() const
if
(
mCatValidator
==
nullptr
)
if
(
mCatValidator
==
nullptr
)
mValidator
->
reportError
(
"undefined Category"
,
true
);
mValidator
->
reportError
(
"undefined Category"
,
true
);
return
iset
{
mCatValidator
->
mKeys
.
begin
(),
mCatValidator
->
mKeys
.
end
()
};
return
iset
{
mCatValidator
->
mKeys
.
begin
(),
mCatValidator
->
mKeys
.
end
()
};
}
}
std
::
set
<
size_t
>
Category
::
keyFieldsByIndex
()
const
std
::
set
<
size_t
>
Category
::
keyFieldsByIndex
()
const
...
@@ -2220,12 +2312,105 @@ std::set<size_t> Category::keyFieldsByIndex() const
...
@@ -2220,12 +2312,105 @@ std::set<size_t> Category::keyFieldsByIndex() const
mValidator
->
reportError
(
"undefined Category"
,
true
);
mValidator
->
reportError
(
"undefined Category"
,
true
);
std
::
set
<
size_t
>
result
;
std
::
set
<
size_t
>
result
;
for
(
auto
&
k
:
mCatValidator
->
mKeys
)
for
(
auto
&
k
:
mCatValidator
->
mKeys
)
result
.
insert
(
getColumnIndex
(
k
));
result
.
insert
(
getColumnIndex
(
k
));
return
result
;
return
result
;
}
}
bool
operator
==
(
const
Category
&
a
,
const
Category
&
b
)
{
using
namespace
std
::
placeholders
;
// set<std::string> tagsA(a.fields()), tagsB(b.fields());
//
// if (tagsA != tagsB)
// std::cout << "Unequal number of fields" << std::endl;
auto
&
validator
=
a
.
getValidator
();
auto
catValidator
=
validator
.
getValidatorForCategory
(
a
.
name
());
if
(
catValidator
==
nullptr
)
throw
std
::
runtime_error
(
"missing cat validator"
);
typedef
std
::
function
<
int
(
const
char
*
,
const
char
*
)
>
compType
;
std
::
vector
<
std
::
tuple
<
std
::
string
,
compType
>>
tags
;
auto
keys
=
catValidator
->
mKeys
;
std
::
vector
<
size_t
>
keyIx
;
for
(
auto
&
tag
:
a
.
fields
())
{
auto
iv
=
catValidator
->
getValidatorForItem
(
tag
);
if
(
iv
==
nullptr
)
throw
std
::
runtime_error
(
"missing item validator"
);
auto
tv
=
iv
->
mType
;
if
(
tv
==
nullptr
)
throw
std
::
runtime_error
(
"missing type validator"
);
tags
.
push_back
(
std
::
make_tuple
(
tag
,
std
::
bind
(
&
cif
::
ValidateType
::
compare
,
tv
,
std
::
placeholders
::
_1
,
std
::
placeholders
::
_2
)));
auto
pred
=
[
tag
](
const
std
::
string
&
s
)
->
bool
{
return
cif
::
iequals
(
tag
,
s
)
==
0
;
};
if
(
find_if
(
keys
.
begin
(),
keys
.
end
(),
pred
)
==
keys
.
end
())
keyIx
.
push_back
(
tags
.
size
()
-
1
);
}
// a.reorderByIndex();
// b.reorderByIndex();
auto
rowEqual
=
[
&
](
const
cif
::
Row
&
a
,
const
cif
::
Row
&
b
)
{
int
d
=
0
;
for
(
auto
kix
:
keyIx
)
{
std
::
string
tag
;
compType
compare
;
std
::
tie
(
tag
,
compare
)
=
tags
[
kix
];
d
=
compare
(
a
[
tag
].
c_str
(),
b
[
tag
].
c_str
());
if
(
d
!=
0
)
break
;
}
return
d
==
0
;
};
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
while
(
ai
!=
a
.
end
()
or
bi
!=
b
.
end
())
{
if
(
ai
==
a
.
end
()
or
bi
==
b
.
end
())
return
false
;
cif
::
Row
ra
=
*
ai
,
rb
=
*
bi
;
if
(
not
rowEqual
(
ra
,
rb
))
return
false
;
std
::
vector
<
std
::
string
>
missingA
,
missingB
,
different
;
for
(
auto
&
tt
:
tags
)
{
std
::
string
tag
;
compType
compare
;
std
::
tie
(
tag
,
compare
)
=
tt
;
// make it an option to compare unapplicable to empty or something
const
char
*
ta
=
ra
[
tag
].
c_str
();
if
(
strcmp
(
ta
,
"."
)
==
0
)
ta
=
""
;
const
char
*
tb
=
rb
[
tag
].
c_str
();
if
(
strcmp
(
tb
,
"."
)
==
0
)
tb
=
""
;
if
(
compare
(
ta
,
tb
)
!=
0
)
return
false
;
}
++
ai
;
++
bi
;
}
return
true
;
}
// auto Category::iterator::operator++() -> iterator&
// auto Category::iterator::operator++() -> iterator&
// {
// {
// mCurrent = Row(mCurrent.data()->mNext);
// mCurrent = Row(mCurrent.data()->mNext);
...
@@ -2241,8 +2426,8 @@ std::set<size_t> Category::keyFieldsByIndex() const
...
@@ -2241,8 +2426,8 @@ std::set<size_t> Category::keyFieldsByIndex() const
namespace
detail
namespace
detail
{
{
size_t
writeValue
(
std
::
ostream
&
os
,
std
::
string
value
,
size_t
offset
,
size_t
width
)
size_t
writeValue
(
std
::
ostream
&
os
,
std
::
string
value
,
size_t
offset
,
size_t
width
)
{
{
if
(
value
.
find
(
'\n'
)
!=
std
::
string
::
npos
or
width
==
0
or
value
.
length
()
>=
132
)
// write as text field
if
(
value
.
find
(
'\n'
)
!=
std
::
string
::
npos
or
width
==
0
or
value
.
length
()
>=
132
)
// write as text field
{
{
ba
::
replace_all
(
value
,
"
\n
;"
,
"
\n\\
;"
);
ba
::
replace_all
(
value
,
"
\n
;"
,
"
\n\\
;"
);
...
@@ -2273,7 +2458,7 @@ size_t writeValue(std::ostream& os, std::string value, size_t offset, size_t wid
...
@@ -2273,7 +2458,7 @@ size_t writeValue(std::ostream& os, std::string value, size_t offset, size_t wid
else
else
{
{
bool
done
=
false
;
bool
done
=
false
;
for
(
char
q
:
{
'\''
,
'"'
})
for
(
char
q
:
{
'\''
,
'"'
})
{
{
auto
p
=
value
.
find
(
q
);
// see if we can use the quote character
auto
p
=
value
.
find
(
q
);
// see if we can use the quote character
while
(
p
!=
std
::
string
::
npos
and
isNonBlank
(
value
[
p
+
1
])
and
value
[
p
+
1
]
!=
q
)
while
(
p
!=
std
::
string
::
npos
and
isNonBlank
(
value
[
p
+
1
])
and
value
[
p
+
1
]
!=
q
)
...
@@ -2310,11 +2495,11 @@ size_t writeValue(std::ostream& os, std::string value, size_t offset, size_t wid
...
@@ -2310,11 +2495,11 @@ size_t writeValue(std::ostream& os, std::string value, size_t offset, size_t wid
}
}
return
offset
;
return
offset
;
}
}
}
}
// namespace detail
void
Category
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
size_t
>&
order
,
bool
includeEmptyColumns
)
void
Category
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
size_t
>
&
order
,
bool
includeEmptyColumns
)
{
{
if
(
empty
())
if
(
empty
())
return
;
return
;
...
@@ -2328,9 +2513,9 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
...
@@ -2328,9 +2513,9 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
std
::
vector
<
size_t
>
columnWidths
;
std
::
vector
<
size_t
>
columnWidths
;
for
(
auto
cix
:
order
)
for
(
auto
cix
:
order
)
{
{
auto
&
col
=
mColumns
[
cix
];
auto
&
col
=
mColumns
[
cix
];
os
<<
'_'
<<
mName
<<
'.'
<<
col
.
mName
<<
' '
<<
std
::
endl
;
os
<<
'_'
<<
mName
<<
'.'
<<
col
.
mName
<<
' '
<<
std
::
endl
;
columnWidths
.
push_back
(
2
);
columnWidths
.
push_back
(
2
);
}
}
...
@@ -2359,7 +2544,7 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
...
@@ -2359,7 +2544,7 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
{
{
size_t
offset
=
0
;
size_t
offset
=
0
;
for
(
size_t
cix
:
order
)
for
(
size_t
cix
:
order
)
{
{
size_t
w
=
columnWidths
[
cix
];
size_t
w
=
columnWidths
[
cix
];
...
@@ -2406,7 +2591,7 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
...
@@ -2406,7 +2591,7 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
// first find the indent level
// first find the indent level
size_t
l
=
0
;
size_t
l
=
0
;
for
(
auto
&
col
:
mColumns
)
for
(
auto
&
col
:
mColumns
)
{
{
std
::
string
tag
=
'_'
+
mName
+
'.'
+
col
.
mName
;
std
::
string
tag
=
'_'
+
mName
+
'.'
+
col
.
mName
;
...
@@ -2416,9 +2601,9 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
...
@@ -2416,9 +2601,9 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
l
+=
3
;
l
+=
3
;
for
(
size_t
cix
:
order
)
for
(
size_t
cix
:
order
)
{
{
auto
&
col
=
mColumns
[
cix
];
auto
&
col
=
mColumns
[
cix
];
os
<<
'_'
<<
mName
<<
'.'
<<
col
.
mName
<<
std
::
string
(
l
-
col
.
mName
.
length
()
-
mName
.
length
()
-
2
,
' '
);
os
<<
'_'
<<
mName
<<
'.'
<<
col
.
mName
<<
std
::
string
(
l
-
col
.
mName
.
length
()
-
mName
.
length
()
-
2
,
' '
);
...
@@ -2450,23 +2635,23 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
...
@@ -2450,23 +2635,23 @@ void Category::write(std::ostream& os, const std::vector<size_t>& order, bool in
os
<<
"# "
<<
std
::
endl
;
os
<<
"# "
<<
std
::
endl
;
}
}
void
Category
::
write
(
std
::
ostream
&
os
)
void
Category
::
write
(
std
::
ostream
&
os
)
{
{
std
::
vector
<
size_t
>
order
(
mColumns
.
size
());
std
::
vector
<
size_t
>
order
(
mColumns
.
size
());
iota
(
order
.
begin
(),
order
.
end
(),
0
);
iota
(
order
.
begin
(),
order
.
end
(),
0
);
write
(
os
,
order
,
false
);
write
(
os
,
order
,
false
);
}
}
void
Category
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
columns
)
void
Category
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
columns
)
{
{
// make sure all columns are present
// make sure all columns are present
for
(
auto
&
c
:
columns
)
for
(
auto
&
c
:
columns
)
addColumn
(
c
);
addColumn
(
c
);
std
::
vector
<
size_t
>
order
;
std
::
vector
<
size_t
>
order
;
order
.
reserve
(
mColumns
.
size
());
order
.
reserve
(
mColumns
.
size
());
for
(
auto
&
c
:
columns
)
for
(
auto
&
c
:
columns
)
order
.
push_back
(
getColumnIndex
(
c
));
order
.
push_back
(
getColumnIndex
(
c
));
for
(
size_t
i
=
0
;
i
<
mColumns
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
mColumns
.
size
();
++
i
)
...
@@ -2489,7 +2674,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2489,7 +2674,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
if
(
colIx
>=
mColumns
.
size
())
if
(
colIx
>=
mColumns
.
size
())
throw
std
::
runtime_error
(
"Invalid column "
+
value
+
" for "
+
mName
);
throw
std
::
runtime_error
(
"Invalid column "
+
value
+
" for "
+
mName
);
auto
&
col
=
mColumns
[
colIx
];
auto
&
col
=
mColumns
[
colIx
];
// check the value
// check the value
if
(
col
.
mValidator
)
if
(
col
.
mValidator
)
...
@@ -2497,7 +2682,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2497,7 +2682,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
// first some sanity checks, what was the old value and is it the same for all rows?
// first some sanity checks, what was the old value and is it the same for all rows?
std
::
string
oldValue
=
rows
.
front
()[
tag
].
c_str
();
std
::
string
oldValue
=
rows
.
front
()[
tag
].
c_str
();
for
(
auto
&
row
:
rows
)
for
(
auto
&
row
:
rows
)
{
{
if
(
oldValue
!=
row
[
tag
].
c_str
())
if
(
oldValue
!=
row
[
tag
].
c_str
())
throw
std
::
runtime_error
(
"Inconsistent old values in update_value"
);
throw
std
::
runtime_error
(
"Inconsistent old values in update_value"
);
...
@@ -2507,16 +2692,16 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2507,16 +2692,16 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
return
;
return
;
// update rows, but do not cascade
// update rows, but do not cascade
for
(
auto
&
row
:
rows
)
for
(
auto
&
row
:
rows
)
row
.
assign
(
colIx
,
value
,
true
);
row
.
assign
(
colIx
,
value
,
true
);
// see if we need to update any child categories that depend on this value
// see if we need to update any child categories that depend on this value
auto
&
validator
=
getValidator
();
auto
&
validator
=
getValidator
();
auto
&
db
=
mDb
;
auto
&
db
=
mDb
;
for
(
auto
parent
:
rows
)
for
(
auto
parent
:
rows
)
{
{
for
(
auto
linked
:
validator
.
getLinksForParent
(
mName
))
for
(
auto
linked
:
validator
.
getLinksForParent
(
mName
))
{
{
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
if
(
childCat
==
nullptr
)
if
(
childCat
==
nullptr
)
...
@@ -2544,7 +2729,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2544,7 +2729,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
cond
=
std
::
move
(
cond
)
&&
Key
(
ck
)
==
parent
[
pk
].
c_str
();
cond
=
std
::
move
(
cond
)
&&
Key
(
ck
)
==
parent
[
pk
].
c_str
();
}
}
auto
children
=
RowSet
{
*
childCat
,
std
::
move
(
cond
)
};
auto
children
=
RowSet
{
*
childCat
,
std
::
move
(
cond
)
};
if
(
children
.
empty
())
if
(
children
.
empty
())
continue
;
continue
;
...
@@ -2554,7 +2739,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2554,7 +2739,7 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
RowSet
process
(
*
childCat
);
RowSet
process
(
*
childCat
);
for
(
auto
child
:
children
)
for
(
auto
child
:
children
)
{
{
Condition
cond_c
;
Condition
cond_c
;
...
@@ -2619,13 +2804,13 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2619,13 +2804,13 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
// --------------------------------------------------------------------
// --------------------------------------------------------------------
Row
::
Row
(
const
Row
&
rhs
)
Row
::
Row
(
const
Row
&
rhs
)
:
mData
(
rhs
.
mData
)
:
mData
(
rhs
.
mData
)
,
mCascade
(
rhs
.
mCascade
)
,
mCascade
(
rhs
.
mCascade
)
{
{
}
}
Row
::
Row
(
Row
&&
rhs
)
Row
::
Row
(
Row
&&
rhs
)
:
mData
(
rhs
.
mData
)
:
mData
(
rhs
.
mData
)
,
mCascade
(
rhs
.
mCascade
)
,
mCascade
(
rhs
.
mCascade
)
{
{
...
@@ -2634,7 +2819,6 @@ Row::Row(Row&& rhs)
...
@@ -2634,7 +2819,6 @@ Row::Row(Row&& rhs)
Row
::~
Row
()
Row
::~
Row
()
{
{
}
}
void
Row
::
next
()
void
Row
::
next
()
...
@@ -2643,30 +2827,31 @@ void Row::next()
...
@@ -2643,30 +2827,31 @@ void Row::next()
mData
=
mData
->
mNext
;
mData
=
mData
->
mNext
;
}
}
Row
&
Row
::
operator
=
(
Row
&&
rhs
)
Row
&
Row
::
operator
=
(
Row
&&
rhs
)
{
{
mData
=
rhs
.
mData
;
rhs
.
mData
=
nullptr
;
mData
=
rhs
.
mData
;
rhs
.
mData
=
nullptr
;
mCascade
=
rhs
.
mCascade
;
mCascade
=
rhs
.
mCascade
;
return
*
this
;
return
*
this
;
}
}
Row
&
Row
::
operator
=
(
const
Row
&
rhs
)
Row
&
Row
::
operator
=
(
const
Row
&
rhs
)
{
{
mData
=
rhs
.
mData
;
mData
=
rhs
.
mData
;
mCascade
=
rhs
.
mCascade
;
mCascade
=
rhs
.
mCascade
;
return
*
this
;
return
*
this
;
}
}
void
Row
::
assign
(
const
std
::
vector
<
Item
>
&
values
)
void
Row
::
assign
(
const
std
::
vector
<
Item
>
&
values
)
{
{
auto
cat
=
mData
->
mCategory
;
auto
cat
=
mData
->
mCategory
;
std
::
map
<
std
::
string
,
std
::
tuple
<
size_t
,
std
::
string
,
std
::
string
>>
changed
;
std
::
map
<
std
::
string
,
std
::
tuple
<
size_t
,
std
::
string
,
std
::
string
>>
changed
;
for
(
auto
&
value
:
values
)
for
(
auto
&
value
:
values
)
{
{
auto
columnIx
=
cat
->
addColumn
(
value
.
name
());
auto
columnIx
=
cat
->
addColumn
(
value
.
name
());
auto
&
col
=
cat
->
mColumns
[
columnIx
];
auto
&
col
=
cat
->
mColumns
[
columnIx
];
std
::
string
tag
=
col
.
mValidator
?
col
.
mValidator
->
mTag
:
std
::
to_string
(
columnIx
);
std
::
string
tag
=
col
.
mValidator
?
col
.
mValidator
->
mTag
:
std
::
to_string
(
columnIx
);
changed
[
tag
]
=
std
::
make_tuple
(
columnIx
,
operator
[](
columnIx
).
c_str
(),
value
.
value
());
changed
[
tag
]
=
std
::
make_tuple
(
columnIx
,
operator
[](
columnIx
).
c_str
(),
value
.
value
());
...
@@ -2678,10 +2863,10 @@ void Row::assign(const std::vector<Item>& values)
...
@@ -2678,10 +2863,10 @@ void Row::assign(const std::vector<Item>& values)
// auto iv = col.mValidator;
// auto iv = col.mValidator;
if
(
mCascade
)
if
(
mCascade
)
{
{
auto
&
validator
=
cat
->
getValidator
();
auto
&
validator
=
cat
->
getValidator
();
auto
&
db
=
cat
->
db
();
auto
&
db
=
cat
->
db
();
for
(
auto
linked
:
validator
.
getLinksForParent
(
cat
->
mName
))
for
(
auto
linked
:
validator
.
getLinksForParent
(
cat
->
mName
))
{
{
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
if
(
childCat
==
nullptr
)
if
(
childCat
==
nullptr
)
...
@@ -2708,46 +2893,46 @@ void Row::assign(const std::vector<Item>& values)
...
@@ -2708,46 +2893,46 @@ void Row::assign(const std::vector<Item>& values)
}
}
else
else
{
{
const
char
*
value
=
(
*
this
)[
pk
].
c_str
();
const
char
*
value
=
(
*
this
)[
pk
].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
ck
)
==
value
);
cond
=
std
::
move
(
cond
)
&&
(
Key
(
ck
)
==
value
);
}
}
}
}
auto
rows
=
childCat
->
find
(
std
::
move
(
cond
));
auto
rows
=
childCat
->
find
(
std
::
move
(
cond
));
for
(
auto
&
cr
:
rows
)
for
(
auto
&
cr
:
rows
)
cr
.
assign
(
newValues
);
cr
.
assign
(
newValues
);
}
}
}
}
}
}
void
Row
::
assign
(
const
Item
&
value
,
bool
skipUpdateLinked
)
void
Row
::
assign
(
const
Item
&
value
,
bool
skipUpdateLinked
)
{
{
assign
(
value
.
name
(),
value
.
value
(),
skipUpdateLinked
);
assign
(
value
.
name
(),
value
.
value
(),
skipUpdateLinked
);
}
}
void
Row
::
assign
(
const
std
::
string
&
name
,
const
std
::
string
&
value
,
bool
skipUpdateLinked
)
void
Row
::
assign
(
const
std
::
string
&
name
,
const
std
::
string
&
value
,
bool
skipUpdateLinked
)
{
{
try
try
{
{
auto
cat
=
mData
->
mCategory
;
auto
cat
=
mData
->
mCategory
;
assign
(
cat
->
addColumn
(
name
),
value
,
skipUpdateLinked
);
assign
(
cat
->
addColumn
(
name
),
value
,
skipUpdateLinked
);
}
}
catch
(
const
std
::
exception
&
ex
)
catch
(
const
std
::
exception
&
ex
)
{
{
std
::
cerr
<<
"Could not assign value '"
<<
value
<<
"' to column _"
<<
mData
->
mCategory
->
name
()
<<
'.'
<<
name
<<
std
::
endl
;
std
::
cerr
<<
"Could not assign value '"
<<
value
<<
"' to column _"
<<
mData
->
mCategory
->
name
()
<<
'.'
<<
name
<<
std
::
endl
;
throw
;
throw
;
}
}
}
}
void
Row
::
assign
(
size_t
column
,
const
std
::
string
&
value
,
bool
skipUpdateLinked
)
void
Row
::
assign
(
size_t
column
,
const
std
::
string
&
value
,
bool
skipUpdateLinked
)
{
{
if
(
mData
==
nullptr
)
if
(
mData
==
nullptr
)
throw
std
::
logic_error
(
"invalid Row, no data assigning value '"
+
value
+
"' to column with index "
+
std
::
to_string
(
column
));
throw
std
::
logic_error
(
"invalid Row, no data assigning value '"
+
value
+
"' to column with index "
+
std
::
to_string
(
column
));
auto
cat
=
mData
->
mCategory
;
auto
cat
=
mData
->
mCategory
;
auto
&
col
=
cat
->
mColumns
[
column
];
auto
&
col
=
cat
->
mColumns
[
column
];
const
char
*
oldValue
=
nullptr
;
const
char
*
oldValue
=
nullptr
;
for
(
auto
iv
=
mData
->
mValues
;
iv
!=
nullptr
;
iv
=
iv
->
mNext
)
for
(
auto
iv
=
mData
->
mValues
;
iv
!=
nullptr
;
iv
=
iv
->
mNext
)
{
{
assert
(
iv
!=
iv
->
mNext
and
(
iv
->
mNext
==
nullptr
or
iv
!=
iv
->
mNext
->
mNext
));
assert
(
iv
!=
iv
->
mNext
and
(
iv
->
mNext
==
nullptr
or
iv
!=
iv
->
mNext
->
mNext
));
...
@@ -2810,7 +2995,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
...
@@ -2810,7 +2995,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
if
(
not
value
.
empty
())
if
(
not
value
.
empty
())
{
{
auto
nv
=
new
(
value
.
length
())
ItemValue
(
value
.
c_str
(),
column
);
auto
nv
=
new
(
value
.
length
())
ItemValue
(
value
.
c_str
(),
column
);
if
(
mData
->
mValues
==
nullptr
)
if
(
mData
->
mValues
==
nullptr
)
mData
->
mValues
=
nv
;
mData
->
mValues
=
nv
;
...
@@ -2830,10 +3015,10 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
...
@@ -2830,10 +3015,10 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
auto
iv
=
col
.
mValidator
;
auto
iv
=
col
.
mValidator
;
if
(
not
skipUpdateLinked
and
iv
!=
nullptr
and
mCascade
)
if
(
not
skipUpdateLinked
and
iv
!=
nullptr
and
mCascade
)
{
{
auto
&
validator
=
cat
->
getValidator
();
auto
&
validator
=
cat
->
getValidator
();
auto
&
db
=
cat
->
db
();
auto
&
db
=
cat
->
db
();
for
(
auto
linked
:
validator
.
getLinksForParent
(
cat
->
mName
))
for
(
auto
linked
:
validator
.
getLinksForParent
(
cat
->
mName
))
{
{
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
if
(
childCat
==
nullptr
)
if
(
childCat
==
nullptr
)
...
@@ -2859,7 +3044,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
...
@@ -2859,7 +3044,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
}
}
else
else
{
{
const
char
*
pk_value
=
(
*
this
)[
pk
].
c_str
();
const
char
*
pk_value
=
(
*
this
)[
pk
].
c_str
();
if
(
*
pk_value
==
0
)
if
(
*
pk_value
==
0
)
cond
=
std
::
move
(
cond
)
&&
Key
(
ck
)
==
Empty
();
cond
=
std
::
move
(
cond
)
&&
Key
(
ck
)
==
Empty
();
else
else
...
@@ -2893,7 +3078,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
...
@@ -2893,7 +3078,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
cond_n
=
std
::
move
(
cond_n
)
&&
Key
(
ck
)
==
value
;
cond_n
=
std
::
move
(
cond_n
)
&&
Key
(
ck
)
==
value
;
else
else
{
{
const
char
*
pk_value
=
(
*
this
)[
pk
].
c_str
();
const
char
*
pk_value
=
(
*
this
)[
pk
].
c_str
();
if
(
*
pk_value
==
0
)
if
(
*
pk_value
==
0
)
cond_n
=
std
::
move
(
cond_n
)
&&
Key
(
ck
)
==
Empty
();
cond_n
=
std
::
move
(
cond_n
)
&&
Key
(
ck
)
==
Empty
();
else
else
...
@@ -2910,13 +3095,13 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
...
@@ -2910,13 +3095,13 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
continue
;
continue
;
}
}
for
(
auto
&
cr
:
rows
)
for
(
auto
&
cr
:
rows
)
cr
.
assign
(
childTag
,
value
,
false
);
cr
.
assign
(
childTag
,
value
,
false
);
}
}
}
}
}
}
void
Row
::
swap
(
size_t
cix
,
ItemRow
*
a
,
ItemRow
*
b
)
void
Row
::
swap
(
size_t
cix
,
ItemRow
*
a
,
ItemRow
*
b
)
{
{
if
(
a
==
nullptr
or
b
==
nullptr
)
if
(
a
==
nullptr
or
b
==
nullptr
)
throw
std
::
logic_error
(
"invalid Rows in swap"
);
throw
std
::
logic_error
(
"invalid Rows in swap"
);
...
@@ -2939,10 +3124,10 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
...
@@ -2939,10 +3124,10 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
cat
->
mIndex
->
erase
(
b
);
cat
->
mIndex
->
erase
(
b
);
}
}
ItemValue
*
ap
=
nullptr
;
// parent of ai
ItemValue
*
ap
=
nullptr
;
// parent of ai
ItemValue
*
ai
=
nullptr
;
ItemValue
*
ai
=
nullptr
;
ItemValue
*
bp
=
nullptr
;
// parent of bi
ItemValue
*
bp
=
nullptr
;
// parent of bi
ItemValue
*
bi
=
nullptr
;
ItemValue
*
bi
=
nullptr
;
if
(
a
->
mValues
==
nullptr
)
if
(
a
->
mValues
==
nullptr
)
;
;
...
@@ -2964,7 +3149,6 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
...
@@ -2964,7 +3149,6 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
}
}
}
}
if
(
b
->
mValues
==
nullptr
)
if
(
b
->
mValues
==
nullptr
)
;
;
else
if
(
b
->
mValues
->
mColumnIndex
==
cix
)
else
if
(
b
->
mValues
->
mColumnIndex
==
cix
)
...
@@ -3018,10 +3202,10 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
...
@@ -3018,10 +3202,10 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
auto
parentColName
=
cat
->
getColumnName
(
cix
);
auto
parentColName
=
cat
->
getColumnName
(
cix
);
// see if we need to update any child categories that depend on these values
// see if we need to update any child categories that depend on these values
auto
&
validator
=
cat
->
getValidator
();
auto
&
validator
=
cat
->
getValidator
();
auto
parentCatValidator
=
cat
->
getCatValidator
();
auto
parentCatValidator
=
cat
->
getCatValidator
();
for
(
auto
&
link
:
validator
.
getLinksForParent
(
cat
->
mName
))
for
(
auto
&
link
:
validator
.
getLinksForParent
(
cat
->
mName
))
{
{
if
(
find
(
link
->
mParentKeys
.
begin
(),
link
->
mParentKeys
.
end
(),
parentColName
)
==
link
->
mParentKeys
.
end
())
if
(
find
(
link
->
mParentKeys
.
begin
(),
link
->
mParentKeys
.
end
(),
parentColName
)
==
link
->
mParentKeys
.
end
())
continue
;
continue
;
...
@@ -3057,13 +3241,13 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
...
@@ -3057,13 +3241,13 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
if
(
pcix
==
cix
)
if
(
pcix
==
cix
)
{
{
linkChildColName
=
childColName
;
linkChildColName
=
childColName
;
if
(
not
(
i
==
nullptr
or
strcmp
(
i
->
mText
,
"."
)
==
0
or
strcmp
(
i
->
mText
,
"?"
)
==
0
))
if
(
not
(
i
==
nullptr
or
strcmp
(
i
->
mText
,
"."
)
==
0
or
strcmp
(
i
->
mText
,
"?"
)
==
0
))
childValue
=
i
->
mText
;
childValue
=
i
->
mText
;
}
}
else
else
{
{
std
::
string
ps
=
r
->
c_str
(
pcix
);
std
::
string
ps
=
r
->
c_str
(
pcix
);
if
(
not
(
ps
.
empty
()
or
ps
==
"."
or
ps
==
"?"
))
if
(
not
(
ps
.
empty
()
or
ps
==
"."
or
ps
==
"?"
))
childValue
=
ps
;
childValue
=
ps
;
}
}
...
@@ -3098,14 +3282,14 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
...
@@ -3098,14 +3282,14 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
{
{
auto
i
=
ab
==
0
?
bi
:
ai
;
auto
i
=
ab
==
0
?
bi
:
ai
;
for
(
auto
r
:
rs
[
ab
])
for
(
auto
r
:
rs
[
ab
])
{
{
// now due to the way links are defined, we might have found a row
// now due to the way links are defined, we might have found a row
// that contains an empty value for all child columns...
// that contains an empty value for all child columns...
// Now, that's not a real hit, is it?
// Now, that's not a real hit, is it?
size_t
n
=
0
;
size_t
n
=
0
;
for
(
auto
c
:
link
->
mChildKeys
)
for
(
auto
c
:
link
->
mChildKeys
)
if
(
r
[
c
].
empty
())
if
(
r
[
c
].
empty
())
++
n
;
++
n
;
...
@@ -3126,7 +3310,7 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
...
@@ -3126,7 +3310,7 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
}
}
}
}
size_t
Row
::
ColumnForItemTag
(
const
char
*
itemTag
)
const
size_t
Row
::
ColumnForItemTag
(
const
char
*
itemTag
)
const
{
{
size_t
result
=
0
;
size_t
result
=
0
;
if
(
mData
!=
nullptr
)
if
(
mData
!=
nullptr
)
...
@@ -3163,14 +3347,15 @@ void Row::lineNr(uint32_t l)
...
@@ -3163,14 +3347,15 @@ void Row::lineNr(uint32_t l)
mData
->
mLineNr
=
l
;
mData
->
mLineNr
=
l
;
}
}
Row
::
const_iterator
::
const_iterator
(
ItemRow
*
data
,
ItemValue
*
ptr
)
Row
::
const_iterator
::
const_iterator
(
ItemRow
*
data
,
ItemValue
*
ptr
)
:
mData
(
data
),
mPtr
(
ptr
)
:
mData
(
data
)
,
mPtr
(
ptr
)
{
{
if
(
mPtr
!=
nullptr
)
if
(
mPtr
!=
nullptr
)
fetch
();
fetch
();
}
}
Row
::
const_iterator
&
Row
::
const_iterator
::
operator
++
()
Row
::
const_iterator
&
Row
::
const_iterator
::
operator
++
()
{
{
if
(
mPtr
!=
nullptr
)
if
(
mPtr
!=
nullptr
)
mPtr
=
mPtr
->
mNext
;
mPtr
=
mPtr
->
mNext
;
...
@@ -3188,7 +3373,7 @@ void Row::const_iterator::fetch()
...
@@ -3188,7 +3373,7 @@ void Row::const_iterator::fetch()
mPtr
->
mText
);
mPtr
->
mText
);
}
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Row
&
row
)
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Row
&
row
)
{
{
auto
category
=
row
.
mData
->
mCategory
;
auto
category
=
row
.
mData
->
mCategory
;
std
::
string
catName
=
category
->
name
();
std
::
string
catName
=
category
->
name
();
...
@@ -3209,28 +3394,29 @@ File::File()
...
@@ -3209,28 +3394,29 @@ File::File()
{
{
}
}
File
::
File
(
std
::
istream
&
is
,
bool
validate
)
File
::
File
(
std
::
istream
&
is
,
bool
validate
)
:
File
()
:
File
()
{
{
load
(
is
);
load
(
is
);
}
}
File
::
File
(
const
std
::
string
&
path
,
bool
validate
)
File
::
File
(
const
std
::
string
&
path
,
bool
validate
)
:
File
()
:
File
()
{
{
try
try
{
{
load
(
path
);
load
(
path
);
}
}
catch
(
const
std
::
exception
&
ex
)
catch
(
const
std
::
exception
&
ex
)
{
{
std
::
cerr
<<
"Error while loading file "
<<
path
<<
std
::
endl
;
std
::
cerr
<<
"Error while loading file "
<<
path
<<
std
::
endl
;
throw
;
throw
;
}
}
}
}
File
::
File
(
File
&&
rhs
)
File
::
File
(
File
&&
rhs
)
:
mHead
(
nullptr
),
mValidator
(
nullptr
)
:
mHead
(
nullptr
)
,
mValidator
(
nullptr
)
{
{
std
::
swap
(
mHead
,
rhs
.
mHead
);
std
::
swap
(
mHead
,
rhs
.
mHead
);
std
::
swap
(
mValidator
,
rhs
.
mValidator
);
std
::
swap
(
mValidator
,
rhs
.
mValidator
);
...
@@ -3242,7 +3428,7 @@ File::~File()
...
@@ -3242,7 +3428,7 @@ File::~File()
delete
mValidator
;
delete
mValidator
;
}
}
void
File
::
append
(
Datablock
*
e
)
void
File
::
append
(
Datablock
*
e
)
{
{
e
->
setValidator
(
mValidator
);
e
->
setValidator
(
mValidator
);
...
@@ -3267,7 +3453,7 @@ void File::append(Datablock* e)
...
@@ -3267,7 +3453,7 @@ void File::append(Datablock* e)
}
}
}
}
void
File
::
load
(
const
std
::
string
&
p
)
void
File
::
load
(
const
std
::
string
&
p
)
{
{
fs
::
path
path
(
p
);
fs
::
path
path
(
p
);
...
@@ -3295,14 +3481,14 @@ void File::load(const std::string& p)
...
@@ -3295,14 +3481,14 @@ void File::load(const std::string& p)
{
{
load
(
in
);
load
(
in
);
}
}
catch
(
const
std
::
exception
&
ex
)
catch
(
const
std
::
exception
&
ex
)
{
{
std
::
cerr
<<
"Error loading file "
<<
path
<<
std
::
endl
;
std
::
cerr
<<
"Error loading file "
<<
path
<<
std
::
endl
;
throw
;
throw
;
}
}
}
}
void
File
::
save
(
const
std
::
string
&
p
)
void
File
::
save
(
const
std
::
string
&
p
)
{
{
fs
::
path
path
(
p
);
fs
::
path
path
(
p
);
...
@@ -3324,9 +3510,9 @@ void File::save(const std::string& p)
...
@@ -3324,9 +3510,9 @@ void File::save(const std::string& p)
save
(
out
);
save
(
out
);
}
}
void
File
::
load
(
std
::
istream
&
is
)
void
File
::
load
(
std
::
istream
&
is
)
{
{
Validator
*
saved
=
mValidator
;
Validator
*
saved
=
mValidator
;
setValidator
(
nullptr
);
setValidator
(
nullptr
);
Parser
p
(
is
,
*
this
);
Parser
p
(
is
,
*
this
);
...
@@ -3339,9 +3525,9 @@ void File::load(std::istream& is)
...
@@ -3339,9 +3525,9 @@ void File::load(std::istream& is)
}
}
}
}
void
File
::
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
)
void
File
::
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
)
{
{
Validator
*
saved
=
mValidator
;
Validator
*
saved
=
mValidator
;
setValidator
(
nullptr
);
setValidator
(
nullptr
);
Parser
p
(
is
,
*
this
);
Parser
p
(
is
,
*
this
);
...
@@ -3354,9 +3540,9 @@ void File::load(std::istream& is, const std::string& datablock)
...
@@ -3354,9 +3540,9 @@ void File::load(std::istream& is, const std::string& datablock)
}
}
}
}
void
File
::
save
(
std
::
ostream
&
os
)
void
File
::
save
(
std
::
ostream
&
os
)
{
{
Datablock
*
e
=
mHead
;
Datablock
*
e
=
mHead
;
while
(
e
!=
nullptr
)
while
(
e
!=
nullptr
)
{
{
e
->
write
(
os
);
e
->
write
(
os
);
...
@@ -3364,9 +3550,9 @@ void File::save(std::ostream& os)
...
@@ -3364,9 +3550,9 @@ void File::save(std::ostream& os)
}
}
}
}
void
File
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>&
order
)
void
File
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
)
{
{
Datablock
*
e
=
mHead
;
Datablock
*
e
=
mHead
;
while
(
e
!=
nullptr
)
while
(
e
!=
nullptr
)
{
{
e
->
write
(
os
,
order
);
e
->
write
(
os
,
order
);
...
@@ -3374,17 +3560,17 @@ void File::write(std::ostream& os, const std::vector<std::string>& order)
...
@@ -3374,17 +3560,17 @@ void File::write(std::ostream& os, const std::vector<std::string>& order)
}
}
}
}
Datablock
*
File
::
get
(
const
std
::
string
&
name
)
const
Datablock
*
File
::
get
(
const
std
::
string
&
name
)
const
{
{
const
Datablock
*
result
=
mHead
;
const
Datablock
*
result
=
mHead
;
while
(
result
!=
nullptr
and
not
iequals
(
result
->
mName
,
name
))
while
(
result
!=
nullptr
and
not
iequals
(
result
->
mName
,
name
))
result
=
result
->
mNext
;
result
=
result
->
mNext
;
return
const_cast
<
Datablock
*>
(
result
);
return
const_cast
<
Datablock
*>
(
result
);
}
}
Datablock
&
File
::
operator
[](
const
std
::
string
&
name
)
Datablock
&
File
::
operator
[](
const
std
::
string
&
name
)
{
{
Datablock
*
result
=
mHead
;
Datablock
*
result
=
mHead
;
while
(
result
!=
nullptr
and
not
iequals
(
result
->
mName
,
name
))
while
(
result
!=
nullptr
and
not
iequals
(
result
->
mName
,
name
))
result
=
result
->
mNext
;
result
=
result
->
mNext
;
if
(
result
==
nullptr
)
if
(
result
==
nullptr
)
...
@@ -3414,7 +3600,7 @@ void File::validateLinks() const
...
@@ -3414,7 +3600,7 @@ void File::validateLinks() const
d
->
validateLinks
();
d
->
validateLinks
();
}
}
const
Validator
&
File
::
getValidator
()
const
const
Validator
&
File
::
getValidator
()
const
{
{
if
(
mValidator
==
nullptr
)
if
(
mValidator
==
nullptr
)
throw
std
::
runtime_error
(
"no Validator defined yet"
);
throw
std
::
runtime_error
(
"no Validator defined yet"
);
...
@@ -3426,7 +3612,7 @@ void File::loadDictionary()
...
@@ -3426,7 +3612,7 @@ void File::loadDictionary()
loadDictionary
(
"mmcif_ddl"
);
loadDictionary
(
"mmcif_ddl"
);
}
}
void
File
::
loadDictionary
(
const
char
*
dict
)
void
File
::
loadDictionary
(
const
char
*
dict
)
{
{
fs
::
path
dict_name
(
dict
);
fs
::
path
dict_name
(
dict
);
...
@@ -3449,7 +3635,7 @@ void File::loadDictionary(const char* dict)
...
@@ -3449,7 +3635,7 @@ void File::loadDictionary(const char* dict)
#if defined(CACHE_DIR) and defined(DATA_DIR)
#if defined(CACHE_DIR) and defined(DATA_DIR)
if
(
not
fs
::
exists
(
p
))
if
(
not
fs
::
exists
(
p
))
{
{
for
(
const
char
*
dir
:
{
CACHE_DIR
,
DATA_DIR
})
for
(
const
char
*
dir
:
{
CACHE_DIR
,
DATA_DIR
})
{
{
auto
p2
=
fs
::
path
(
dir
)
/
p
;
auto
p2
=
fs
::
path
(
dir
)
/
p
;
if
(
fs
::
exists
(
p2
))
if
(
fs
::
exists
(
p2
))
...
@@ -3478,7 +3664,7 @@ void File::loadDictionary(const char* dict)
...
@@ -3478,7 +3664,7 @@ void File::loadDictionary(const char* dict)
}
}
}
}
void
File
::
loadDictionary
(
std
::
istream
&
is
)
void
File
::
loadDictionary
(
std
::
istream
&
is
)
{
{
std
::
unique_ptr
<
Validator
>
v
(
new
Validator
());
std
::
unique_ptr
<
Validator
>
v
(
new
Validator
());
...
@@ -3488,7 +3674,7 @@ void File::loadDictionary(std::istream& is)
...
@@ -3488,7 +3674,7 @@ void File::loadDictionary(std::istream& is)
setValidator
(
v
.
release
());
setValidator
(
v
.
release
());
}
}
void
File
::
setValidator
(
Validator
*
v
)
void
File
::
setValidator
(
Validator
*
v
)
{
{
mValidator
=
v
;
mValidator
=
v
;
...
@@ -3496,13 +3682,13 @@ void File::setValidator(Validator* v)
...
@@ -3496,13 +3682,13 @@ void File::setValidator(Validator* v)
d
->
setValidator
(
mValidator
);
d
->
setValidator
(
mValidator
);
}
}
void
File
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
void
File
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
{
{
for
(
auto
d
=
mHead
;
d
!=
nullptr
;
d
=
d
->
mNext
)
for
(
auto
d
=
mHead
;
d
!=
nullptr
;
d
=
d
->
mNext
)
d
->
getTagOrder
(
tags
);
d
->
getTagOrder
(
tags
);
}
}
auto
File
::
iterator
::
operator
++
()
->
iterator
&
auto
File
::
iterator
::
operator
++
()
->
iterator
&
{
{
mCurrent
=
mCurrent
->
mNext
;
mCurrent
=
mCurrent
->
mNext
;
return
*
this
;
return
*
this
;
...
@@ -3518,4 +3704,4 @@ auto File::end() const -> iterator
...
@@ -3518,4 +3704,4 @@ auto File::end() const -> iterator
return
iterator
(
nullptr
);
return
iterator
(
nullptr
);
}
}
}
}
// namespace cif
src/Structure.cpp
View file @
345c4778
...
@@ -1740,6 +1740,14 @@ File::~File()
...
@@ -1740,6 +1740,14 @@ File::~File()
delete
mImpl
;
delete
mImpl
;
}
}
cif
::
Datablock
&
File
::
createDatablock
(
const
std
::
string
&
name
)
{
auto
db
=
new
cif
::
Datablock
(
name
);
mImpl
->
mData
.
append
(
db
);
mImpl
->
mDb
=
db
;
}
void
File
::
load
(
const
std
::
string
&
p
)
void
File
::
load
(
const
std
::
string
&
p
)
{
{
mImpl
->
load
(
p
);
mImpl
->
load
(
p
);
...
@@ -1778,8 +1786,11 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
...
@@ -1778,8 +1786,11 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
:
mFile
(
f
)
:
mFile
(
f
)
,
mModelNr
(
modelNr
)
,
mModelNr
(
modelNr
)
{
{
auto
&
db
=
*
mFile
.
impl
().
mDb
;
auto
db
=
mFile
.
impl
().
mDb
;
auto
&
atomCat
=
db
[
"atom_site"
];
if
(
db
==
nullptr
)
throw
std
::
logic_error
(
"Empty file!"
);
auto
&
atomCat
=
(
*
db
)[
"atom_site"
];
for
(
auto
&
a
:
atomCat
)
for
(
auto
&
a
:
atomCat
)
{
{
...
@@ -2400,6 +2411,31 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
...
@@ -2400,6 +2411,31 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
}
}
}
}
std
::
string
Structure
::
createEntityNonPoly
(
std
::
vector
<
cif
::
Item
>
data
,
const
std
::
string
&
mon_id
)
{
auto
&
db
=
mFile
.
data
();
auto
&
entity
=
db
[
"entity"
];
std
::
string
entity_id
=
entity
.
getUniqueID
(
""
);
// remove any ID fields
data
.
erase
(
std
::
remove_if
(
data
.
begin
(),
data
.
end
(),
[](
cif
::
Item
&
item
)
{
return
item
.
name
()
==
"id"
;
}),
data
.
end
());
// add our new ID
data
.
emplace_back
(
"id"
,
entity_id
);
data
.
emplace_back
(
"type"
,
"non-polymer"
);
entity
.
emplace
(
data
.
begin
(),
data
.
end
());
return
entity_id
;
}
std
::
string
Structure
::
createNonpoly
(
const
std
::
string
&
entity_id
,
const
std
::
vector
<
cif
::
Item
>
&
atoms
)
{
return
{};
}
void
Structure
::
cleanupEmptyCategories
()
void
Structure
::
cleanupEmptyCategories
()
{
{
using
namespace
cif
::
literals
;
using
namespace
cif
::
literals
;
...
...
test/structure-test.cpp
0 → 100644
View file @
345c4778
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2021 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define BOOST_TEST_MODULE Structure_Test
#include <boost/test/included/unit_test.hpp>
#include <stdexcept>
#include "cif++/Cif++.hpp"
#include "cif++/Structure.hpp"
// --------------------------------------------------------------------
cif
::
File
operator
""
_cf
(
const
char
*
text
,
size_t
length
)
{
struct
membuf
:
public
std
::
streambuf
{
membuf
(
char
*
text
,
size_t
length
)
{
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
text
),
length
);
std
::
istream
is
(
&
buffer
);
return
cif
::
File
(
is
);
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
create_nonpoly_1
)
{
cif
::
VERBOSE
=
1
;
// do this now, avoids the need for installing
cif
::
addFileResource
(
"mmcif_pdbx_v50.dic"
,
"../rsrc/mmcif_pdbx_v50.dic"
);
auto
expected
=
R"(
data_TEST
loop_
_entity.id
_entity.type
_entity.src_method
_entity.pdbx_description
_entity.formula_weight
1 non-polymer syn 'PROTOPORPHYRIN IX CONTAINING FE' 616.487
)"
_cf
;
expected
.
loadDictionary
(
"mmcif_pdbx_v50.dic"
);
mmcif
::
File
file
;
file
.
file
().
loadDictionary
(
"mmcif_pdbx_v50.dic"
);
file
.
createDatablock
(
"TEST"
);
// create a datablock
mmcif
::
Structure
structure
(
file
);
structure
.
createEntityNonPoly
({
{
"src_method"
,
"syn"
},
{
"pdbx_description"
,
"PROTOPORPHYRIN IX CONTAINING FE"
},
{
"formula_weight"
,
616.487
}
},
"HEM"
);
BOOST_TEST
(
expected
.
firstDatablock
()
==
structure
.
getFile
().
data
());
std
::
cout
<<
expected
.
firstDatablock
()
<<
std
::
endl
<<
std
::
endl
<<
structure
.
getFile
().
data
()
<<
std
::
endl
;
// // using namespace mmcif;
// auto f = R"(data_TEST
// #
// loop_
// _test.id
// _test.name
// 1 aap
// 2 noot
// 3 mies
// )"_cf;
// auto& db = f.firstDatablock();
// BOOST_CHECK(db.getName() == "TEST");
// auto& test = db["test"];
// BOOST_CHECK(test.size() == 3);
// // wrong! the next lines will crash. And that's OK, don't do that
// // for (auto r: test)
// // test.erase(r);
// // BOOST_CHECK(test.empty());
// // test.purge();
// auto n = test.erase(cif::Key("id") == 1, [](const cif::Row& r) {
// BOOST_CHECK_EQUAL(r["id"].as<int>(), 1);
// BOOST_CHECK_EQUAL(r["name"].as<std::string>(), "aap");
// });
// BOOST_CHECK_EQUAL(n, 1);
}
test/unit-test.cpp
View file @
345c4778
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