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
04b7828a
Unverified
Commit
04b7828a
authored
Aug 04, 2022
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
validator work
parent
9c621eca
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1138 additions
and
621 deletions
+1138
-621
include/cif++/v2/category.hpp
+95
-68
include/cif++/v2/datablock.hpp
+39
-0
include/cif++/v2/dictionary_parser.hpp
+1
-1
include/cif++/v2/file.hpp
+69
-8
include/cif++/v2/item.hpp
+17
-1
include/cif++/v2/row.hpp
+6
-0
include/cif++/v2/validate.hpp
+78
-83
src/v2/category.cpp
+450
-87
src/v2/condition.cpp
+4
-4
src/v2/dictionary_parser.cpp
+51
-51
src/v2/item.cpp
+11
-3
src/v2/validate.cpp
+86
-86
test/unit-v2-test.cpp
+231
-229
No files found.
include/cif++/v2/category.hpp
View file @
04b7828a
...
...
@@ -32,6 +32,7 @@
#include <cif++/v2/iterator.hpp>
#include <cif++/v2/row.hpp>
#include <cif++/v2/validate.hpp>
namespace
cif
::
v2
{
...
...
@@ -127,17 +128,22 @@ class category
throw
std
::
runtime_error
(
"No Validator specified"
);
if
(
m_cat_validator
==
nullptr
)
m_validator
->
report
E
rror
(
"undefined Category"
,
true
);
m_validator
->
report
_e
rror
(
"undefined Category"
,
true
);
iset
result
;
for
(
auto
&
iv
:
m_cat_validator
->
m
ItemV
alidators
)
result
.
insert
(
iv
.
m
T
ag
);
for
(
auto
&
iv
:
m_cat_validator
->
m
_item_v
alidators
)
result
.
insert
(
iv
.
m
_t
ag
);
return
result
;
}
const
Validator
*
get_validator
()
const
{
return
m_validator
;
}
const
ValidateCategory
*
get_cat_validator
()
const
{
return
m_cat_validator
;
}
void
set_validator
(
const
validator
*
v
,
datablock
&
db
);
void
update_links
(
datablock
&
db
);
const
validator
*
get_validator
()
const
{
return
m_validator
;
}
const
category_validator
*
get_cat_validator
()
const
{
return
m_cat_validator
;
}
bool
is_valid
()
const
;
// --------------------------------------------------------------------
...
...
@@ -379,6 +385,10 @@ class category
// insert_impl(pos, std::move(row));
// }
iterator
erase
(
iterator
pos
);
size_t
erase
(
condition
&&
cond
);
size_t
erase
(
condition
&&
cond
,
std
::
function
<
void
(
row_handle
)
>
&&
visit
);
iterator
emplace
(
std
::
initializer_list
<
item
>
items
)
{
return
this
->
emplace
(
items
.
begin
(),
items
.
end
());
...
...
@@ -388,52 +398,52 @@ class category
iterator
emplace
(
ItemIter
b
,
ItemIter
e
)
{
// First, make sure all mandatory fields are supplied
// if (mCatV
alidator != nullptr and b != e)
//
{
// for (auto &col
: m_columns)
//
{
// auto iv = mCatValidator->getValidatorForItem(col.mName);
// if (iv == nullptr)
// continu
e;
// bool seen = false;
// for (auto v = b; v != e; ++v
)
//
{
// if (iequals(v->name(), col.mName))
// {
//
seen = true;
//
break;
//
}
//
}
// if (not seen and iv->mM
andatory)
// throw std::runtime_error("missing mandatory field " + col.mName + " for category " + mN
ame);
//
}
//
if (mIndex != nullptr)
//
{
//
std::unique_ptr<ItemRow> nr(new ItemRow{nullptr, this, nullptr});
//
Row r(nr.get());
//
auto keys = keyFields();
//
for (auto v = b; v != e; ++v)
//
{
//
if (keys.count(v->name()))
//
r.assign(v->name(), v->value(), true);
//
}
//
auto test = mIndex->find(nr.get());
//
if (test != nullptr)
//
{
//
if (VERBOSE > 1)
//
std::cerr << "Not inserting new record in " << mName << " (duplicate Key)" << std::endl;
//
result = test;
//
isNew = false;
//
}
//
}
//
}
if
(
m_cat_v
alidator
!=
nullptr
and
b
!=
e
)
{
for
(
const
auto
&
[
column
,
iv
]
:
m_columns
)
{
if
(
iv
==
nullptr
)
continue
;
bool
seen
=
fals
e
;
for
(
auto
v
=
b
;
v
!=
e
;
++
v
)
{
if
(
iequals
(
v
->
name
(),
column
)
)
{
iv
->
operator
()(
v
->
value
());
seen
=
true
;
break
;
}
}
if
(
not
seen
and
iv
->
m_m
andatory
)
throw
std
::
runtime_error
(
"missing mandatory field "
+
column
+
" for category "
+
m_n
ame
);
}
//
if (mIndex != nullptr)
//
{
//
std::unique_ptr<ItemRow> nr(new ItemRow{nullptr, this, nullptr});
//
Row r(nr.get());
//
auto keys = keyFields();
//
for (auto v = b; v != e; ++v)
//
{
//
if (keys.count(v->name()))
//
r.assign(v->name(), v->value(), true);
//
}
//
auto test = mIndex->find(nr.get());
//
if (test != nullptr)
//
{
//
if (VERBOSE > 1)
//
std::cerr << "Not inserting new record in " << mName << " (duplicate Key)" << std::endl;
//
result = test;
//
isNew = false;
//
}
//
}
}
row
*
r
=
this
->
create_row
();
...
...
@@ -486,12 +496,12 @@ class category
break
;
}
// if (VERBOSE > 0 and result == m_columns.size() and mCatV
alidator != nullptr) // validate the name, if it is known at all (since it was not found)
//
{
// auto iv = mCatValidator->getValidatorForItem(
name);
//
if (iv == nullptr)
// std::cerr << "Invalid name used '" << name << "' is not a known column in " + mN
ame << std::endl;
//
}
if
(
VERBOSE
>
0
and
result
==
m_columns
.
size
()
and
m_cat_v
alidator
!=
nullptr
)
// validate the name, if it is known at all (since it was not found)
{
auto
iv
=
m_cat_validator
->
get_validator_for_item
(
column_
name
);
if
(
iv
==
nullptr
)
std
::
cerr
<<
"Invalid name used '"
<<
name
<<
"' is not a known column in "
+
m_n
ame
<<
std
::
endl
;
}
return
result
;
}
...
...
@@ -504,14 +514,14 @@ class category
if
(
result
==
m_columns
.
size
())
{
const
ValidateItem
*
item_validator
=
nullptr
;
const
item_validator
*
item_validator
=
nullptr
;
// if (mCatV
alidator != nullptr)
//
{
// item_validator = mCatValidator->getValidatorForI
tem(column_name);
//
if (item_validator == nullptr)
// m_validator->reportError("tag " + std::string(column_name) + " not allowed in category " + mN
ame, false);
//
}
if
(
m_cat_v
alidator
!=
nullptr
)
{
item_validator
=
m_cat_validator
->
get_validator_for_i
tem
(
column_name
);
if
(
item_validator
==
nullptr
)
m_validator
->
report_error
(
"tag "
+
std
::
string
(
column_name
)
+
" not allowed in category "
+
m_n
ame
,
false
);
}
m_columns
.
emplace_back
(
column_name
,
item_validator
);
}
...
...
@@ -523,6 +533,9 @@ class category
void
update_value
(
row
*
row
,
size_t
column
,
std
::
string_view
value
,
bool
updateLinked
,
bool
validate
=
true
);
private
:
bool
is_orphan
(
row_handle
r
)
const
;
void
erase_orphans
(
condition
&&
cond
);
using
allocator_type
=
std
::
allocator
<
void
>
;
constexpr
allocator_type
get_allocator
()
const
...
...
@@ -645,15 +658,27 @@ class category
struct
item_column
{
std
::
string
m_name
;
const
ValidateItem
*
m_validator
;
const
item_validator
*
m_validator
;
item_column
(
std
::
string_view
name
,
const
ValidateItem
*
validator
)
item_column
(
std
::
string_view
name
,
const
item_validator
*
validator
)
:
m_name
(
name
)
,
m_validator
(
validator
)
{
}
};
struct
link
{
link
(
category
*
linked
,
const
link_validator
*
v
)
:
linked
(
linked
)
,
v
(
v
)
{
}
category
*
linked
;
const
link_validator
*
v
;
};
// proxy methods for every insertion
iterator
insert_impl
(
const_iterator
pos
,
row
*
n
);
...
...
@@ -661,8 +686,10 @@ class category
std
::
string
m_name
;
std
::
vector
<
item_column
>
m_columns
;
const
Validator
*
m_validator
=
nullptr
;
const
ValidateCategory
*
m_cat_validator
=
nullptr
;
const
validator
*
m_validator
=
nullptr
;
const
category_validator
*
m_cat_validator
=
nullptr
;
std
::
vector
<
link
>
m_parent_links
,
m_child_links
;
bool
m_cascade
=
true
;
row
*
m_head
=
nullptr
,
*
m_tail
=
nullptr
;
};
...
...
include/cif++/v2/datablock.hpp
View file @
04b7828a
...
...
@@ -63,6 +63,31 @@ class datablock
const
std
::
string
&
name
()
const
{
return
m_name
;
}
void
set_validator
(
const
validator
*
v
)
{
m_validator
=
v
;
for
(
auto
&
cat
:
*
this
)
cat
.
set_validator
(
v
,
*
this
);
}
const
validator
*
get_validator
()
const
{
return
m_validator
;
}
bool
is_valid
()
const
{
if
(
m_validator
==
nullptr
)
throw
std
::
runtime_error
(
"Validator not specified"
);
bool
result
=
true
;
for
(
auto
&
cat
:
*
this
)
result
=
cat
.
is_valid
()
and
result
;
return
result
;
}
// --------------------------------------------------------------------
bool
empty
()
const
{
return
m_categories
.
empty
();
}
...
...
@@ -102,6 +127,18 @@ class datablock
return
i
==
m_categories
.
end
()
?
s_empty
:
*
i
;
}
category
*
get
(
std
::
string_view
name
)
{
auto
i
=
std
::
find_if
(
m_categories
.
begin
(),
m_categories
.
end
(),
[
name
](
const
category
&
c
)
{
return
iequals
(
c
.
name
(),
name
);
});
return
i
==
m_categories
.
end
()
?
nullptr
:
&*
i
;
}
const
category
*
get
(
std
::
string_view
name
)
const
{
return
const_cast
<
datablock
*>
(
this
)
->
get
(
name
);
}
std
::
tuple
<
iterator
,
bool
>
emplace
(
std
::
string_view
name
)
{
bool
is_new
=
true
;
...
...
@@ -182,6 +219,7 @@ class datablock
private
:
category_list
m_categories
;
std
::
string
m_name
;
const
validator
*
m_validator
=
nullptr
;
};
}
//
namespace
cif
::
v2
\ No newline at end of file
include/cif++/v2/dictionary_parser.hpp
View file @
04b7828a
...
...
@@ -31,6 +31,6 @@
namespace
cif
::
v2
{
V
alidator
parse_dictionary
(
std
::
string_view
name
,
std
::
istream
&
is
);
v
alidator
parse_dictionary
(
std
::
string_view
name
,
std
::
istream
&
is
);
}
// namespace cif::v2
include/cif++/v2/file.hpp
View file @
04b7828a
...
...
@@ -60,6 +60,57 @@ class file
file
&
operator
=
(
const
file
&
)
=
default
;
file
&
operator
=
(
file
&&
)
=
default
;
void
set_validator
(
const
validator
*
v
)
{
m_validator
=
v
;
for
(
auto
&
db
:
*
this
)
db
.
set_validator
(
v
);
}
const
validator
*
get_validator
()
const
{
return
m_validator
;
}
bool
is_valid
()
const
{
if
(
m_validator
==
nullptr
)
std
::
runtime_error
(
"No validator loaded explicitly, cannot continue"
);
bool
result
=
true
;
for
(
auto
&
d
:
*
this
)
result
=
d
.
is_valid
()
and
result
;
return
result
;
}
bool
is_valid
()
{
if
(
m_validator
==
nullptr
)
{
if
(
VERBOSE
>
0
)
std
::
cerr
<<
"No dictionary loaded explicitly, loading default"
<<
std
::
endl
;
load_dictionary
();
}
bool
result
=
true
;
for
(
auto
&
d
:
*
this
)
result
=
d
.
is_valid
()
and
result
;
return
result
;
}
void
load_dictionary
()
{
load_dictionary
(
"mmcif_ddl"
);
}
void
load_dictionary
(
std
::
string_view
name
)
{
set_validator
(
&
validator_factory
::
instance
()[
name
]);
}
datablock
&
operator
[](
std
::
string_view
name
)
{
auto
i
=
std
::
find_if
(
m_datablocks
.
begin
(),
m_datablocks
.
end
(),
[
name
](
const
datablock
&
c
)
...
...
@@ -112,27 +163,36 @@ class file
bool
empty
()
const
{
return
m_datablocks
.
empty
();
}
size_t
size
()
const
{
return
m_datablocks
.
size
();
}
iterator
begin
()
{
return
m_datablocks
.
begin
();
}
iterator
end
()
{
return
m_datablocks
.
end
();
}
const_iterator
cbegin
()
{
return
m_datablocks
.
begin
();
}
const_iterator
cend
()
{
return
m_datablocks
.
end
();
}
const_iterator
begin
()
const
{
return
m_datablocks
.
begin
();
}
const_iterator
end
()
const
{
return
m_datablocks
.
end
();
}
reference
front
()
{
return
m_datablocks
.
front
();
}
reference
back
()
{
return
m_datablocks
.
back
();
}
void
load
(
std
::
istream
&
is
)
{
// auto saved = mV
alidator;
// setV
alidator(nullptr);
auto
saved
=
m_v
alidator
;
set_v
alidator
(
nullptr
);
parser
p
(
is
,
*
this
);
p
.
parse_file
();
//
if (saved != nullptr)
//
{
// setV
alidator(saved);
// (void)isV
alid();
//
}
if
(
saved
!=
nullptr
)
{
set_v
alidator
(
saved
);
(
void
)
is_v
alid
();
}
}
private
:
datablock_list
m_datablocks
;
std
::
unique_ptr
<
Validator
>
m_validato
r
;
const
validator
*
m_validator
=
nullpt
r
;
};
}
\ No newline at end of file
include/cif++/v2/item.hpp
View file @
04b7828a
...
...
@@ -199,7 +199,7 @@ struct item_handle
item_handle
&
operator
=
(
const
T
&
value
)
{
item
v
{
""
,
value
};
m_row_handle
.
assign
(
m_column
,
v
.
value
(),
false
);
assign_value
(
v
);
return
*
this
;
}
...
...
@@ -281,6 +281,8 @@ struct item_handle
uint16_t
m_column
;
row_handle
&
m_row_handle
;
void
assign_value
(
const
item
&
value
);
static
constexpr
const
char
*
s_empty_result
=
""
;
};
...
...
@@ -432,6 +434,20 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, const ch
};
template
<
typename
T
>
struct
item_handle
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_same_v
<
T
,
std
::
string_view
>>>
{
// static std::string_view convert(const item_handle &ref)
// {
// return ref.text();
// }
static
int
compare
(
const
item_handle
&
ref
,
const
std
::
string_view
&
value
,
bool
icase
)
{
return
icase
?
cif
::
icompare
(
ref
.
text
(),
value
)
:
ref
.
text
().
compare
(
value
);
}
};
template
<
typename
T
>
struct
item_handle
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_same_v
<
T
,
std
::
string
>>>
{
static
std
::
string
convert
(
const
item_handle
&
ref
)
...
...
include/cif++/v2/row.hpp
View file @
04b7828a
...
...
@@ -135,6 +135,7 @@ class row_handle
{
public
:
friend
class
item_handle
;
friend
class
category
;
row_handle
()
=
default
;
...
...
@@ -262,6 +263,11 @@ class row_handle
uint16_t
add_column
(
std
::
string_view
name
);
operator
row
*
()
{
return
m_row
;
}
void
assign
(
const
item
&
i
,
bool
updateLinked
)
{
assign
(
i
.
name
(),
i
.
value
(),
updateLinked
);
...
...
include/cif++/v2/validate.hpp
View file @
04b7828a
...
...
@@ -27,6 +27,7 @@
#pragma once
#include <filesystem>
#include <mutex>
// duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
// #include <regex>
...
...
@@ -43,19 +44,19 @@ namespace io = boost::iostreams;
namespace
cif
::
v2
{
struct
ValidateCategory
;
class
ValidatorF
actory
;
struct
category_validator
;
class
validator_f
actory
;
// --------------------------------------------------------------------
class
ValidationE
rror
:
public
std
::
exception
class
validation_e
rror
:
public
std
::
exception
{
public
:
ValidationE
rror
(
const
std
::
string
&
msg
);
ValidationE
rror
(
const
std
::
string
&
cat
,
const
std
::
string
&
item
,
validation_e
rror
(
const
std
::
string
&
msg
);
validation_e
rror
(
const
std
::
string
&
cat
,
const
std
::
string
&
item
,
const
std
::
string
&
msg
);
const
char
*
what
()
const
noexcept
{
return
m
M
sg
.
c_str
();
}
std
::
string
m
M
sg
;
const
char
*
what
()
const
noexcept
{
return
m
_m
sg
.
c_str
();
}
std
::
string
m
_m
sg
;
};
// --------------------------------------------------------------------
...
...
@@ -67,126 +68,120 @@ enum class DDL_PrimitiveType
Numb
};
DDL_PrimitiveType
map
ToPrimitiveT
ype
(
std
::
string_view
s
);
DDL_PrimitiveType
map
_to_primitive_t
ype
(
std
::
string_view
s
);
struct
ValidateType
struct
type_validator
{
std
::
string
m
N
ame
;
DDL_PrimitiveType
m
PrimitiveT
ype
;
std
::
string
m
_n
ame
;
DDL_PrimitiveType
m
_primitive_t
ype
;
// std::regex mRx;
boost
::
regex
m
R
x
;
boost
::
regex
m
_r
x
;
bool
operator
<
(
const
ValidateType
&
rhs
)
const
bool
operator
<
(
const
type_validator
&
rhs
)
const
{
return
icompare
(
m
Name
,
rhs
.
mN
ame
)
<
0
;
return
icompare
(
m
_name
,
rhs
.
m_n
ame
)
<
0
;
}
// compare values based on type
// int compare(const std::string& a, const std::string& b) const
// {
// return compare(a.c_str(), b.c_str());
// }
int
compare
(
const
char
*
a
,
const
char
*
b
)
const
;
};
struct
ValidateItem
struct
item_validator
{
std
::
string
m
T
ag
;
bool
m
M
andatory
;
const
ValidateType
*
mT
ype
;
cif
::
iset
m
E
nums
;
std
::
string
m
D
efault
;
bool
m
DefaultIsN
ull
;
ValidateCategory
*
mC
ategory
=
nullptr
;
std
::
string
m
_t
ag
;
bool
m
_m
andatory
;
const
type_validator
*
m_t
ype
;
cif
::
iset
m
_e
nums
;
std
::
string
m
_d
efault
;
bool
m
_default_is_n
ull
;
category_validator
*
m_c
ategory
=
nullptr
;
// ItemLinked is used for non-key links
struct
ItemLinked
struct
item_link
{
ValidateItem
*
mP
arent
;
std
::
string
m
ParentI
tem
;
std
::
string
m
ChildI
tem
;
item_validator
*
m_p
arent
;
std
::
string
m
_parent_i
tem
;
std
::
string
m
_child_i
tem
;
};
std
::
vector
<
ItemLinked
>
mLinked
;
std
::
vector
<
item_link
>
mLinked
;
bool
operator
<
(
const
ValidateItem
&
rhs
)
const
bool
operator
<
(
const
item_validator
&
rhs
)
const
{
return
icompare
(
m
Tag
,
rhs
.
mT
ag
)
<
0
;
return
icompare
(
m
_tag
,
rhs
.
m_t
ag
)
<
0
;
}
bool
operator
==
(
const
ValidateItem
&
rhs
)
const
bool
operator
==
(
const
item_validator
&
rhs
)
const
{
return
iequals
(
m
Tag
,
rhs
.
mT
ag
);
return
iequals
(
m
_tag
,
rhs
.
m_t
ag
);
}
void
operator
()(
std
::
string
value
)
const
;
void
operator
()(
std
::
string
_view
value
)
const
;
};
struct
ValidateCategory
struct
category_validator
{
std
::
string
m
N
ame
;
std
::
vector
<
std
::
string
>
m
K
eys
;
cif
::
iset
m
G
roups
;
cif
::
iset
m
MandatoryF
ields
;
std
::
set
<
ValidateItem
>
mItemV
alidators
;
std
::
string
m
_n
ame
;
std
::
vector
<
std
::
string
>
m
_k
eys
;
cif
::
iset
m
_g
roups
;
cif
::
iset
m
_mandatory_f
ields
;
std
::
set
<
item_validator
>
m_item_v
alidators
;
bool
operator
<
(
const
ValidateCategory
&
rhs
)
const
bool
operator
<
(
const
category_validator
&
rhs
)
const
{
return
icompare
(
m
Name
,
rhs
.
mN
ame
)
<
0
;
return
icompare
(
m
_name
,
rhs
.
m_n
ame
)
<
0
;
}
void
addItemValidator
(
ValidateItem
&&
v
);
void
addItemValidator
(
item_validator
&&
v
);
const
ValidateItem
*
getValidatorForI
tem
(
std
::
string_view
tag
)
const
;
const
item_validator
*
get_validator_for_i
tem
(
std
::
string_view
tag
)
const
;
const
std
::
set
<
ValidateItem
>
&
itemV
alidators
()
const
const
std
::
set
<
item_validator
>
&
item_v
alidators
()
const
{
return
m
ItemV
alidators
;
return
m
_item_v
alidators
;
}
};
struct
ValidateLink
struct
link_validator
{
int
m
LinkGroupID
;
std
::
string
m
ParentC
ategory
;
std
::
vector
<
std
::
string
>
m
ParentK
eys
;
std
::
string
m
ChildC
ategory
;
std
::
vector
<
std
::
string
>
m
ChildK
eys
;
std
::
string
m
LinkGroupL
abel
;
int
m
_link_group_id
;
std
::
string
m
_parent_c
ategory
;
std
::
vector
<
std
::
string
>
m
_parent_k
eys
;
std
::
string
m
_child_c
ategory
;
std
::
vector
<
std
::
string
>
m
_child_k
eys
;
std
::
string
m
_link_group_l
abel
;
};
// --------------------------------------------------------------------
class
V
alidator
class
v
alidator
{
public
:
V
alidator
(
std
::
string_view
name
)
v
alidator
(
std
::
string_view
name
)
:
m_name
(
name
)
{
}
~
V
alidator
()
=
default
;
~
v
alidator
()
=
default
;
Validator
(
const
V
alidator
&
rhs
)
=
delete
;
Validator
&
operator
=
(
const
V
alidator
&
rhs
)
=
delete
;
validator
(
const
v
alidator
&
rhs
)
=
delete
;
validator
&
operator
=
(
const
v
alidator
&
rhs
)
=
delete
;
Validator
(
V
alidator
&&
rhs
)
=
default
;
Validator
&
operator
=
(
V
alidator
&&
rhs
)
=
default
;
validator
(
v
alidator
&&
rhs
)
=
default
;
validator
&
operator
=
(
v
alidator
&&
rhs
)
=
default
;
friend
class
dictionary_parser
;
void
add
TypeValidator
(
ValidateType
&&
v
);
const
ValidateType
*
getValidatorForType
(
std
::
string_view
typeC
ode
)
const
;
void
add
_type_validator
(
type_validator
&&
v
);
const
type_validator
*
get_validator_for_type
(
std
::
string_view
type_c
ode
)
const
;
void
add
CategoryValidator
(
ValidateCategory
&&
v
);
const
ValidateCategory
*
getValidatorForC
ategory
(
std
::
string_view
category
)
const
;
void
add
_category_validator
(
category_validator
&&
v
);
const
category_validator
*
get_validator_for_c
ategory
(
std
::
string_view
category
)
const
;
void
add
LinkValidator
(
ValidateLink
&&
v
);
std
::
vector
<
const
ValidateLink
*>
getLinksForP
arent
(
std
::
string_view
category
)
const
;
std
::
vector
<
const
ValidateLink
*>
getLinksForC
hild
(
std
::
string_view
category
)
const
;
void
add
_link_validator
(
link_validator
&&
v
);
std
::
vector
<
const
link_validator
*>
get_links_for_p
arent
(
std
::
string_view
category
)
const
;
std
::
vector
<
const
link_validator
*>
get_links_for_c
hild
(
std
::
string_view
category
)
const
;
void
report
E
rror
(
const
std
::
string
&
msg
,
bool
fatal
)
const
;
void
report
_e
rror
(
const
std
::
string
&
msg
,
bool
fatal
)
const
;
const
std
::
string
&
name
()
const
{
return
m_name
;
}
void
set_name
(
const
std
::
string
&
name
)
{
m_name
=
name
;
}
...
...
@@ -196,37 +191,37 @@ class Validator
private
:
// name is fully qualified here:
ValidateItem
*
getValidatorForI
tem
(
std
::
string_view
name
)
const
;
item_validator
*
get_validator_for_i
tem
(
std
::
string_view
name
)
const
;
std
::
string
m_name
;
std
::
string
m_version
;
bool
m_strict
=
false
;
std
::
set
<
ValidateType
>
mTypeV
alidators
;
std
::
set
<
ValidateCategory
>
mCategoryV
alidators
;
std
::
vector
<
ValidateLink
>
mLinkV
alidators
;
std
::
set
<
type_validator
>
m_type_v
alidators
;
std
::
set
<
category_validator
>
m_category_v
alidators
;
std
::
vector
<
link_validator
>
m_link_v
alidators
;
};
// --------------------------------------------------------------------
class
ValidatorF
actory
class
validator_f
actory
{
public
:
static
ValidatorF
actory
&
instance
()
static
validator_f
actory
&
instance
()
{
static
ValidatorF
actory
s_instance
;
static
validator_f
actory
s_instance
;
return
s_instance
;
}
const
V
alidator
&
operator
[](
std
::
string_view
dictionary_name
);
const
v
alidator
&
operator
[](
std
::
string_view
dictionary_name
);
private
:
void
construct_validator
(
std
::
string_view
name
,
std
::
istream
&
is
);
// --------------------------------------------------------------------
ValidatorF
actory
()
=
default
;
validator_f
actory
()
=
default
;
std
::
mutex
m
M
utex
;
std
::
list
<
Validator
>
mV
alidators
;
std
::
mutex
m
_m
utex
;
std
::
list
<
validator
>
m_v
alidators
;
};
}
// namespace cif::v2
src/v2/category.cpp
View file @
04b7828a
...
...
@@ -25,10 +25,371 @@
*/
#include <cif++/v2/category.hpp>
#include <cif++/v2/datablock.hpp>
namespace
cif
::
v2
{
template
<
typename
V
>
std
::
string
join
(
const
V
&
arr
,
std
::
string_view
sep
)
{
std
::
ostringstream
s
;
if
(
not
arr
.
empty
())
{
auto
ai
=
arr
.
begin
();
auto
ni
=
std
::
next
(
ai
);
for
(;;)
{
s
<<
*
ai
;
ai
=
ni
;
ni
=
std
::
next
(
ai
);
if
(
ni
==
arr
.
end
())
break
;
s
<<
sep
;
}
}
return
s
.
str
();
}
void
category
::
set_validator
(
const
validator
*
v
,
datablock
&
db
)
{
m_validator
=
v
;
// if (m_index != nullptr)
// {
// delete m_index;
// m_index = nullptr;
// }
if
(
m_validator
!=
nullptr
)
{
m_cat_validator
=
m_validator
->
get_validator_for_category
(
m_name
);
// if (m_cat_validator != nullptr)
// {
// m_index = new CatIndex(this);
// m_index->reconstruct();
// //#if DEBUG
// // assert(m_index->size() == size());
// // m_index->validate();
// //#endif
// }
}
else
m_cat_validator
=
nullptr
;
for
(
auto
&&
[
column
,
cv
]
:
m_columns
)
cv
=
m_cat_validator
?
m_cat_validator
->
get_validator_for_item
(
column
)
:
nullptr
;
update_links
(
db
);
}
void
category
::
update_links
(
datablock
&
db
)
{
m_child_links
.
clear
();
m_parent_links
.
clear
();
if
(
m_validator
!=
nullptr
)
{
for
(
auto
link
:
m_validator
->
get_links_for_parent
(
m_name
))
{
auto
childCat
=
db
.
get
(
link
->
m_child_category
);
if
(
childCat
==
nullptr
)
continue
;
m_child_links
.
emplace_back
(
childCat
,
link
);
}
for
(
auto
link
:
m_validator
->
get_links_for_child
(
m_name
))
{
auto
parentCat
=
db
.
get
(
link
->
m_parent_category
);
if
(
parentCat
==
nullptr
)
continue
;
m_parent_links
.
emplace_back
(
parentCat
,
link
);
}
}
}
bool
category
::
is_valid
()
const
{
bool
result
=
true
;
if
(
m_validator
==
nullptr
)
throw
std
::
runtime_error
(
"no Validator specified"
);
if
(
empty
())
{
if
(
VERBOSE
>
2
)
std
::
cerr
<<
"Skipping validation of empty Category "
<<
m_name
<<
std
::
endl
;
return
true
;
}
if
(
m_cat_validator
==
nullptr
)
{
m_validator
->
report_error
(
"undefined Category "
+
m_name
,
false
);
return
false
;
}
auto
mandatory
=
m_cat_validator
->
m_mandatory_fields
;
for
(
auto
&
col
:
m_columns
)
{
auto
iv
=
m_cat_validator
->
get_validator_for_item
(
col
.
m_name
);
if
(
iv
==
nullptr
)
{
m_validator
->
report_error
(
"Field "
+
col
.
m_name
+
" is not valid in Category "
+
m_name
,
false
);
result
=
false
;
}
// col.m_validator = iv;
if
(
col
.
m_validator
!=
iv
)
m_validator
->
report_error
(
"Column validator is not specified correctly"
,
true
);
mandatory
.
erase
(
col
.
m_name
);
}
if
(
not
mandatory
.
empty
())
{
m_validator
->
report_error
(
"In Category "
+
m_name
+
" the following mandatory fields are missing: "
+
join
(
mandatory
,
", "
),
false
);
result
=
false
;
}
//#if not defined(NDEBUG)
// // check index?
// if (m_index)
// {
// m_index->validate();
// for (auto r: *this)
// {
// if (m_index->find(r.mData) != r.mData)
// m_validator->report_error("Key not found in index for Category " + m_name);
// }
// }
//#endif
// validate all values
mandatory
=
m_cat_validator
->
m_mandatory_fields
;
for
(
auto
ri
=
m_head
;
ri
!=
nullptr
;
ri
=
ri
->
m_next
)
{
for
(
size_t
cix
=
0
;
cix
<
m_columns
.
size
();
++
cix
)
{
bool
seen
=
false
;
auto
iv
=
m_columns
[
cix
].
m_validator
;
if
(
iv
==
nullptr
)
{
m_validator
->
report_error
(
"invalid field "
+
m_columns
[
cix
].
m_name
+
" for Category "
+
m_name
,
false
);
result
=
false
;
continue
;
}
for
(
auto
vi
=
ri
->
m_head
;
vi
!=
nullptr
;
vi
=
vi
->
m_next
)
{
if
(
vi
->
m_column_ix
==
cix
)
{
seen
=
true
;
try
{
(
*
iv
)(
vi
->
text
());
}
catch
(
const
std
::
exception
&
e
)
{
m_validator
->
report_error
(
"Error validating "
+
m_columns
[
cix
].
m_name
+
": "
+
e
.
what
(),
false
);
continue
;
}
}
}
if
(
seen
or
ri
!=
m_head
)
continue
;
if
(
iv
!=
nullptr
and
iv
->
m_mandatory
)
{
m_validator
->
report_error
(
"missing mandatory field "
+
m_columns
[
cix
].
m_name
+
" for Category "
+
m_name
,
false
);
result
=
false
;
}
}
}
return
result
;
}
category
::
iterator
category
::
erase
(
iterator
pos
)
{
row_handle
rh
=
*
pos
;
row
*
r
=
rh
;
iterator
result
=
++
pos
;
iset
keys
;
if
(
m_cat_validator
)
keys
=
iset
(
m_cat_validator
->
m_keys
.
begin
(),
m_cat_validator
->
m_keys
.
end
());
if
(
m_head
==
nullptr
)
throw
std
::
runtime_error
(
"erase"
);
// if (mIndex != nullptr)
// mIndex->erase(r.mData);
if
(
r
==
m_head
)
{
m_head
=
m_head
->
m_next
;
r
->
m_next
=
nullptr
;
}
else
{
for
(
auto
pi
=
m_head
;
pi
!=
nullptr
;
pi
=
pi
->
m_next
)
{
if
(
pi
->
m_next
==
r
)
{
pi
->
m_next
=
r
->
m_next
;
r
->
m_next
=
nullptr
;
break
;
}
}
}
// links are created based on the _pdbx_item_linked_group_list entries
// in mmcif_pdbx_v50.dic dictionary.
//
// For each link group in _pdbx_item_linked_group_list
// a std::set of keys from one category is mapped to another.
// If all values in a child are the same as the specified parent ones
// the child is removed as well, recursively of course.
if
(
m_validator
!=
nullptr
)
{
for
(
auto
&&
[
childCat
,
link
]
:
m_child_links
)
{
condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
m_parent_keys
.
size
();
++
ix
)
{
std
::
string_view
value
=
rh
[
link
->
m_parent_keys
[
ix
]].
text
();
cond
=
std
::
move
(
cond
)
and
(
key
(
link
->
m_child_keys
[
ix
])
==
value
);
}
childCat
->
erase_orphans
(
std
::
move
(
cond
));
}
}
delete_row
(
r
);
// reset mTail, if needed
if
(
r
==
m_tail
)
{
m_tail
=
m_head
;
if
(
m_tail
!=
nullptr
)
while
(
m_tail
->
m_next
!=
nullptr
)
m_tail
=
m_tail
->
m_next
;
}
return
result
;
}
size_t
category
::
erase
(
condition
&&
cond
)
{
size_t
result
=
0
;
cond
.
prepare
(
*
this
);
auto
ri
=
begin
();
while
(
ri
!=
end
())
{
if
(
cond
(
*
ri
))
{
ri
=
erase
(
ri
);
++
result
;
}
else
++
ri
;
}
return
result
;
}
size_t
category
::
erase
(
condition
&&
cond
,
std
::
function
<
void
(
row_handle
)
>
&&
visit
)
{
size_t
result
=
0
;
cond
.
prepare
(
*
this
);
auto
ri
=
begin
();
while
(
ri
!=
end
())
{
if
(
cond
(
*
ri
))
{
visit
(
*
ri
);
ri
=
erase
(
ri
);
++
result
;
}
else
++
ri
;
}
return
result
;
}
bool
category
::
is_orphan
(
row_handle
r
)
const
{
// be safe
if
(
m_cat_validator
==
nullptr
)
return
false
;
bool
isOrphan
=
true
;
for
(
auto
&&
[
parentCat
,
link
]
:
m_parent_links
)
{
condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
m_child_keys
.
size
();
++
ix
)
{
std
::
string_view
value
=
r
[
link
->
m_child_keys
[
ix
]].
text
();
cond
=
std
::
move
(
cond
)
and
(
key
(
link
->
m_parent_keys
[
ix
])
==
value
);
}
// if (VERBOSE > 2)
// std::cerr << "Check condition '" << cond << "' in parent category " << link->mParentCategory << " for child cat " << mName << std::endl;
if
(
parentCat
->
exists
(
std
::
move
(
cond
)))
{
if
(
VERBOSE
>
2
)
std
::
cerr
<<
"Not removing because row has a parent in category "
<<
link
->
m_parent_category
<<
std
::
endl
;
isOrphan
=
false
;
break
;
}
}
return
isOrphan
;
}
void
category
::
erase_orphans
(
condition
&&
cond
)
{
std
::
vector
<
row
*>
remove
;
cond
.
prepare
(
*
this
);
for
(
auto
r
:
*
this
)
{
if
(
cond
(
r
)
and
is_orphan
(
r
))
{
if
(
VERBOSE
>
1
)
std
::
cerr
<<
"Removing orphaned record: "
<<
std
::
endl
<<
r
<<
std
::
endl
<<
std
::
endl
;
remove
.
push_back
(
r
);
}
}
for
(
auto
r
:
remove
)
erase
(
iterator
(
*
this
,
r
));
}
void
category
::
update_value
(
row
*
row
,
size_t
column
,
std
::
string_view
value
,
bool
updateLinked
,
bool
validate
)
{
auto
&
col
=
m_columns
[
column
];
...
...
@@ -50,9 +411,9 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
std
::
string
oldStrValue
=
oldValue
?
oldValue
:
""
;
//
//
check the value
//
if (col.m_validator and validate)
// (*col.m_validator
)(value);
// check the value
if
(
col
.
m_validator
and
validate
)
col
.
m_validator
->
operator
(
)(
value
);
// If the field is part of the Key for this Category, remove it from the index
// before updating
...
...
@@ -60,11 +421,11 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
bool
reinsert
=
false
;
// if (updateLinked and // an update of an Item's value
// cat->m
I
ndex != nullptr and cat->keyFieldsByIndex().count(column))
// cat->m
_i
ndex != nullptr and cat->keyFieldsByIndex().count(column))
// {
// reinsert = cat->m
I
ndex->find(mData);
// reinsert = cat->m
_i
ndex->find(mData);
// if (reinsert)
// cat->m
I
ndex->erase(mData);
// cat->m
_i
ndex->erase(mData);
// }
// first remove old value with cix
...
...
@@ -112,87 +473,89 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
// if (reinsert)
// cat->mIndex->insert(mData);
// // see if we need to update any child categories that depend on this value
// auto iv = col.m_validator;
// if (not skipUpdateLinked and iv != nullptr and mCascade)
// {
// for (auto &&[childCat, linked] : cat->mChildLinks)
// {
// if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end())
// continue;
// Condition cond;
// std::string childTag;
// for (size_t ix = 0; ix < linked->mParentKeys.size(); ++ix)
// {
// std::string pk = linked->mParentKeys[ix];
// std::string ck = linked->mChildKeys[ix];
// // TODO add code to *NOT* test mandatory fields for Empty
// if (pk == iv->mTag)
// {
// childTag = ck;
// cond = std::move(cond) && Key(ck) == oldStrValue;
// }
// else
// {
// const char *pk_value = (*this)[pk].c_str();
// if (*pk_value == 0)
// cond = std::move(cond) && Key(ck) == Empty();
// else
// cond = std::move(cond) && ((Key(ck) == pk_value) or Key(ck) == Empty());
// }
// }
// auto rows = childCat->find(std::move(cond));
// if (rows.empty())
// continue;
// // if (cif::VERBOSE > 2)
// // {
// // std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl
// // << cond << std::endl;
// // }
// // Now, suppose there are already rows in child that conform to the new value,
// // we then skip this renam
// Condition cond_n;
// for (size_t ix = 0; ix < linked->mParentKeys.size(); ++ix)
// {
// std::string pk = linked->mParentKeys[ix];
// std::string ck = linked->mChildKeys[ix];
// // TODO add code to *NOT* test mandatory fields for Empty
// if (pk == iv->mTag)
// cond_n = std::move(cond_n) && Key(ck) == value;
// else
// {
// const char *pk_value = (*this)[pk].c_str();
// if (*pk_value == 0)
// cond_n = std::move(cond_n) && Key(ck) == Empty();
// else
// cond_n = std::move(cond_n) && ((Key(ck) == pk_value) or Key(ck) == Empty());
// }
// }
// auto rows_n = childCat->find(std::move(cond_n));
// if (not rows_n.empty())
// {
// if (cif::VERBOSE > 0)
// std::cerr << "Will not rename in child category since there are already rows that link to the parent" << std::endl;
// continue;
// }
// for (auto &cr : rows)
// cr.assign(childTag, value, false);
// }
// }
// see if we need to update any child categories that depend on this value
auto
iv
=
col
.
m_validator
;
if
(
updateLinked
and
iv
!=
nullptr
/*and m_cascade*/
)
{
row_handle
rh
(
*
this
,
*
row
);
for
(
auto
&&
[
childCat
,
linked
]
:
m_child_links
)
{
if
(
std
::
find
(
linked
->
m_parent_keys
.
begin
(),
linked
->
m_parent_keys
.
end
(),
iv
->
m_tag
)
==
linked
->
m_parent_keys
.
end
())
continue
;
condition
cond
;
std
::
string
childTag
;
for
(
size_t
ix
=
0
;
ix
<
linked
->
m_parent_keys
.
size
();
++
ix
)
{
std
::
string
pk
=
linked
->
m_parent_keys
[
ix
];
std
::
string
ck
=
linked
->
m_child_keys
[
ix
];
// TODO add code to *NOT* test mandatory fields for Empty
if
(
pk
==
iv
->
m_tag
)
{
childTag
=
ck
;
cond
=
std
::
move
(
cond
)
and
key
(
ck
)
==
oldStrValue
;
}
else
{
std
::
string_view
pk_value
=
rh
[
pk
].
text
();
if
(
pk_value
.
empty
())
cond
=
std
::
move
(
cond
)
and
key
(
ck
)
==
null
;
else
cond
=
std
::
move
(
cond
)
and
((
key
(
ck
)
==
pk_value
)
or
key
(
ck
)
==
null
);
}
}
auto
rows
=
childCat
->
find
(
std
::
move
(
cond
));
if
(
rows
.
empty
())
continue
;
// if (cif::VERBOSE > 2)
// {
// std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl
// << cond << std::endl;
// }
// Now, suppose there are already rows in child that conform to the new value,
// we then skip this renam
condition
cond_n
;
for
(
size_t
ix
=
0
;
ix
<
linked
->
m_parent_keys
.
size
();
++
ix
)
{
std
::
string
pk
=
linked
->
m_parent_keys
[
ix
];
std
::
string
ck
=
linked
->
m_child_keys
[
ix
];
// TODO add code to *NOT* test mandatory fields for Empty
if
(
pk
==
iv
->
m_tag
)
cond_n
=
std
::
move
(
cond_n
)
and
key
(
ck
)
==
value
;
else
{
std
::
string_view
pk_value
=
rh
[
pk
].
text
();
if
(
pk_value
.
empty
())
cond_n
=
std
::
move
(
cond_n
)
and
key
(
ck
)
==
null
;
else
cond_n
=
std
::
move
(
cond_n
)
and
((
key
(
ck
)
==
pk_value
)
or
key
(
ck
)
==
null
);
}
}
auto
rows_n
=
childCat
->
find
(
std
::
move
(
cond_n
));
if
(
not
rows_n
.
empty
())
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"Will not rename in child category since there are already rows that link to the parent"
<<
std
::
endl
;
continue
;
}
for
(
auto
cr
:
rows
)
cr
.
assign
(
childTag
,
value
,
false
);
}
}
}
// proxy methods for every insertion
...
...
src/v2/condition.cpp
View file @
04b7828a
...
...
@@ -47,11 +47,11 @@ bool is_column_type_uchar(const category &cat, std::string_view col)
auto
cv
=
cat
.
get_cat_validator
();
if
(
cv
)
{
auto
iv
=
cv
->
get
ValidatorForI
tem
(
col
);
if
(
iv
!=
nullptr
and
iv
->
m
T
ype
!=
nullptr
)
auto
iv
=
cv
->
get
_validator_for_i
tem
(
col
);
if
(
iv
!=
nullptr
and
iv
->
m
_t
ype
!=
nullptr
)
{
auto
type
=
iv
->
m
T
ype
;
result
=
type
->
m
PrimitiveT
ype
==
DDL_PrimitiveType
::
UChar
;
auto
type
=
iv
->
m
_t
ype
;
result
=
type
->
m
_primitive_t
ype
==
DDL_PrimitiveType
::
UChar
;
}
}
...
...
src/v2/dictionary_parser.cpp
View file @
04b7828a
...
...
@@ -43,7 +43,7 @@ inline void replace_all(std::string &s, std::string_view pat, std::string_view r
class
dictionary_parser
:
public
parser
{
public
:
dictionary_parser
(
V
alidator
&
validator
,
std
::
istream
&
is
,
file
&
f
)
dictionary_parser
(
v
alidator
&
validator
,
std
::
istream
&
is
,
file
&
f
)
:
parser
(
is
,
f
)
,
m_validator
(
validator
)
{
...
...
@@ -83,17 +83,17 @@ class dictionary_parser : public parser
// store all validators
for
(
auto
&
ic
:
mCategoryValidators
)
m_validator
.
add
CategoryV
alidator
(
std
::
move
(
ic
));
m_validator
.
add
_category_v
alidator
(
std
::
move
(
ic
));
mCategoryValidators
.
clear
();
for
(
auto
&
iv
:
mItemValidators
)
{
auto
cv
=
m_validator
.
get
ValidatorForC
ategory
(
iv
.
first
);
auto
cv
=
m_validator
.
get
_validator_for_c
ategory
(
iv
.
first
);
if
(
cv
==
nullptr
)
error
(
"Undefined category '"
+
iv
.
first
);
for
(
auto
&
v
:
iv
.
second
)
const_cast
<
ValidateCategory
*>
(
cv
)
->
addItemValidator
(
std
::
move
(
v
));
const_cast
<
category_validator
*>
(
cv
)
->
addItemValidator
(
std
::
move
(
v
));
}
// check all item validators for having a typeValidator
...
...
@@ -145,15 +145,15 @@ class dictionary_parser : public parser
std
::
vector
<
std
::
string
>
tags
;
while
(
m_lookahead
==
CIFToken
::
Tag
)
{
std
::
string
catName
,
item
N
ame
;
std
::
tie
(
catName
,
item
N
ame
)
=
splitTagName
(
m_token_value
);
std
::
string
catName
,
item
_n
ame
;
std
::
tie
(
catName
,
item
_n
ame
)
=
splitTagName
(
m_token_value
);
if
(
cat
==
dict
.
end
())
std
::
tie
(
cat
,
std
::
ignore
)
=
dict
.
emplace
(
catName
);
else
if
(
not
iequals
(
cat
->
name
(),
catName
))
error
(
"inconsistent categories in loop_"
);
tags
.
push_back
(
item
N
ame
);
tags
.
push_back
(
item
_n
ame
);
match
(
CIFToken
::
Tag
);
}
...
...
@@ -173,8 +173,8 @@ class dictionary_parser : public parser
}
else
{
std
::
string
catName
,
item
N
ame
;
std
::
tie
(
catName
,
item
N
ame
)
=
splitTagName
(
m_token_value
);
std
::
string
catName
,
item
_n
ame
;
std
::
tie
(
catName
,
item
_n
ame
)
=
splitTagName
(
m_token_value
);
if
(
cat
==
dict
.
end
()
or
not
iequals
(
cat
->
name
(),
catName
))
std
::
tie
(
cat
,
std
::
ignore
)
=
dict
.
emplace
(
catName
);
...
...
@@ -183,7 +183,7 @@ class dictionary_parser : public parser
if
(
cat
->
empty
())
cat
->
emplace
({});
cat
->
back
()[
item
N
ame
]
=
m_token_value
;
cat
->
back
()[
item
_n
ame
]
=
m_token_value
;
match
(
CIFToken
::
Value
);
}
...
...
@@ -204,7 +204,7 @@ class dictionary_parser : public parser
for
(
auto
g
:
dict
[
"category_group"
])
groups
.
insert
(
g
[
"id"
].
as
<
std
::
string
>
());
mCategoryValidators
.
push_back
(
ValidateCategory
{
category
,
keys
,
groups
});
mCategoryValidators
.
push_back
(
category_validator
{
category
,
keys
,
groups
});
}
else
{
...
...
@@ -212,9 +212,9 @@ class dictionary_parser : public parser
std
::
string
typeCode
;
cif
::
v2
::
tie
(
typeCode
)
=
dict
[
"item_type"
].
front
().
get
(
"code"
);
const
ValidateType
*
tv
=
nullptr
;
const
type_validator
*
tv
=
nullptr
;
if
(
not
(
typeCode
.
empty
()
or
typeCode
==
"?"
))
tv
=
m_validator
.
get
ValidatorForT
ype
(
typeCode
);
tv
=
m_validator
.
get
_validator_for_t
ype
(
typeCode
);
iset
ess
;
for
(
auto
e
:
dict
[
"item_enumeration"
])
...
...
@@ -240,10 +240,10 @@ class dictionary_parser : public parser
cif
::
v2
::
tie
(
tagName
,
category
,
mandatory
)
=
i
.
get
(
"name"
,
"category_id"
,
"mandatory_code"
);
std
::
string
catName
,
item
N
ame
;
std
::
tie
(
catName
,
item
N
ame
)
=
splitTagName
(
tagName
);
std
::
string
catName
,
item
_n
ame
;
std
::
tie
(
catName
,
item
_n
ame
)
=
splitTagName
(
tagName
);
if
(
catName
.
empty
()
or
item
N
ame
.
empty
())
if
(
catName
.
empty
()
or
item
_n
ame
.
empty
())
error
(
"Invalid tag name in _item.name "
+
tagName
);
if
(
not
iequals
(
category
,
catName
)
and
not
(
category
.
empty
()
or
category
==
"?"
))
...
...
@@ -253,13 +253,13 @@ class dictionary_parser : public parser
auto
&
ivs
=
mItemValidators
[
category
];
auto
vi
=
find
(
ivs
.
begin
(),
ivs
.
end
(),
ValidateItem
{
itemN
ame
});
auto
vi
=
find
(
ivs
.
begin
(),
ivs
.
end
(),
item_validator
{
item_n
ame
});
if
(
vi
==
ivs
.
end
())
ivs
.
push_back
(
ValidateItem
{
itemN
ame
,
iequals
(
mandatory
,
"yes"
),
tv
,
ess
,
defaultValue
,
defaultIsNull
});
ivs
.
push_back
(
item_validator
{
item_n
ame
,
iequals
(
mandatory
,
"yes"
),
tv
,
ess
,
defaultValue
,
defaultIsNull
});
else
{
// need to update the itemValidator?
if
(
vi
->
m
M
andatory
!=
(
iequals
(
mandatory
,
"yes"
)))
if
(
vi
->
m
_m
andatory
!=
(
iequals
(
mandatory
,
"yes"
)))
{
if
(
VERBOSE
>
2
)
{
...
...
@@ -268,24 +268,24 @@ class dictionary_parser : public parser
if
(
iequals
(
tagName
,
saveFrameName
))
std
::
cerr
<<
"choosing "
<<
mandatory
<<
std
::
endl
;
else
std
::
cerr
<<
"choosing "
<<
(
vi
->
m
M
andatory
?
"Y"
:
"N"
)
<<
std
::
endl
;
std
::
cerr
<<
"choosing "
<<
(
vi
->
m
_m
andatory
?
"Y"
:
"N"
)
<<
std
::
endl
;
}
if
(
iequals
(
tagName
,
saveFrameName
))
vi
->
m
M
andatory
=
(
iequals
(
mandatory
,
"yes"
));
vi
->
m
_m
andatory
=
(
iequals
(
mandatory
,
"yes"
));
}
if
(
vi
->
m
Type
!=
nullptr
and
tv
!=
nullptr
and
vi
->
mT
ype
!=
tv
)
if
(
vi
->
m
_type
!=
nullptr
and
tv
!=
nullptr
and
vi
->
m_t
ype
!=
tv
)
{
if
(
VERBOSE
>
1
)
std
::
cerr
<<
"inconsistent type for "
<<
tagName
<<
" in dictionary"
<<
std
::
endl
;
}
// vi->mMandatory = (iequals(mandatory, "yes"));
if
(
vi
->
m
T
ype
==
nullptr
)
vi
->
m
T
ype
=
tv
;
if
(
vi
->
m
_t
ype
==
nullptr
)
vi
->
m
_t
ype
=
tv
;
vi
->
m
E
nums
.
insert
(
ess
.
begin
(),
ess
.
end
());
vi
->
m
_e
nums
.
insert
(
ess
.
begin
(),
ess
.
end
());
// anything else yet?
// ...
...
...
@@ -349,15 +349,15 @@ class dictionary_parser : public parser
int
link_group_id
;
cif
::
v2
::
tie
(
child
,
parent
,
link_group_id
)
=
gl
.
get
(
"child_name"
,
"parent_name"
,
"link_group_id"
);
auto
civ
=
m_validator
.
get
ValidatorForI
tem
(
child
);
auto
civ
=
m_validator
.
get
_validator_for_i
tem
(
child
);
if
(
civ
==
nullptr
)
error
(
"in pdbx_item_linked_group_list, item '"
+
child
+
"' is not specified"
);
auto
piv
=
m_validator
.
get
ValidatorForI
tem
(
parent
);
auto
piv
=
m_validator
.
get
_validator_for_i
tem
(
parent
);
if
(
piv
==
nullptr
)
error
(
"in pdbx_item_linked_group_list, item '"
+
parent
+
"' is not specified"
);
key_type
key
{
piv
->
m
Category
->
mName
,
civ
->
mCategory
->
mN
ame
,
link_group_id
};
key_type
key
{
piv
->
m
_category
->
m_name
,
civ
->
m_category
->
m_n
ame
,
link_group_id
};
if
(
not
linkIndex
.
count
(
key
))
{
linkIndex
[
key
]
=
linkKeys
.
size
();
...
...
@@ -365,7 +365,7 @@ class dictionary_parser : public parser
}
size_t
ix
=
linkIndex
.
at
(
key
);
addLink
(
ix
,
piv
->
m
Tag
,
civ
->
mT
ag
);
addLink
(
ix
,
piv
->
m
_tag
,
civ
->
m_t
ag
);
}
// Only process inline linked items if the linked group list is absent
...
...
@@ -377,15 +377,15 @@ class dictionary_parser : public parser
std
::
string
child
,
parent
;
std
::
tie
(
child
,
parent
)
=
li
;
auto
civ
=
m_validator
.
get
ValidatorForI
tem
(
child
);
auto
civ
=
m_validator
.
get
_validator_for_i
tem
(
child
);
if
(
civ
==
nullptr
)
error
(
"in pdbx_item_linked_group_list, item '"
+
child
+
"' is not specified"
);
auto
piv
=
m_validator
.
get
ValidatorForI
tem
(
parent
);
auto
piv
=
m_validator
.
get
_validator_for_i
tem
(
parent
);
if
(
piv
==
nullptr
)
error
(
"in pdbx_item_linked_group_list, item '"
+
parent
+
"' is not specified"
);
key_type
key
{
piv
->
m
Category
->
mName
,
civ
->
mCategory
->
mN
ame
,
0
};
key_type
key
{
piv
->
m
_category
->
m_name
,
civ
->
m_category
->
m_n
ame
,
0
};
if
(
not
linkIndex
.
count
(
key
))
{
linkIndex
[
key
]
=
linkKeys
.
size
();
...
...
@@ -393,7 +393,7 @@ class dictionary_parser : public parser
}
size_t
ix
=
linkIndex
.
at
(
key
);
addLink
(
ix
,
piv
->
m
Tag
,
civ
->
mT
ag
);
addLink
(
ix
,
piv
->
m
_tag
,
civ
->
m_t
ag
);
}
}
...
...
@@ -402,29 +402,29 @@ class dictionary_parser : public parser
// now store the links in the validator
for
(
auto
&
kv
:
linkIndex
)
{
ValidateLink
link
=
{};
std
::
tie
(
link
.
m
ParentCategory
,
link
.
mChildCategory
,
link
.
mLinkGroupID
)
=
kv
.
first
;
link_validator
link
=
{};
std
::
tie
(
link
.
m
_parent_category
,
link
.
m_child_category
,
link
.
m_link_group_id
)
=
kv
.
first
;
std
::
tie
(
link
.
m
ParentKeys
,
link
.
mChildK
eys
)
=
linkKeys
[
kv
.
second
];
std
::
tie
(
link
.
m
_parent_keys
,
link
.
m_child_k
eys
)
=
linkKeys
[
kv
.
second
];
// look up the label
for
(
auto
r
:
linkedGroup
.
find
(
"category_id"
_key
==
link
.
m
ChildCategory
and
"link_group_id"
_key
==
link
.
mLinkGroupID
))
for
(
auto
r
:
linkedGroup
.
find
(
"category_id"
_key
==
link
.
m
_child_category
and
"link_group_id"
_key
==
link
.
m_link_group_id
))
{
link
.
m
LinkGroupL
abel
=
r
[
"label"
].
as
<
std
::
string
>
();
link
.
m
_link_group_l
abel
=
r
[
"label"
].
as
<
std
::
string
>
();
break
;
}
m_validator
.
add
LinkV
alidator
(
std
::
move
(
link
));
m_validator
.
add
_link_v
alidator
(
std
::
move
(
link
));
}
// now make sure the itemType is specified for all itemValidators
for
(
auto
&
cv
:
m_validator
.
m
CategoryV
alidators
)
for
(
auto
&
cv
:
m_validator
.
m
_category_v
alidators
)
{
for
(
auto
&
iv
:
cv
.
m
ItemV
alidators
)
for
(
auto
&
iv
:
cv
.
m
_item_v
alidators
)
{
if
(
iv
.
m
T
ype
==
nullptr
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Missing item_type for "
<<
iv
.
m
T
ag
<<
std
::
endl
;
if
(
iv
.
m
_t
ype
==
nullptr
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Missing item_type for "
<<
iv
.
m
_t
ag
<<
std
::
endl
;
}
}
}
...
...
@@ -449,10 +449,10 @@ class dictionary_parser : public parser
try
{
ValidateType
v
=
{
code
,
map
ToPrimitiveT
ype
(
primitiveCode
),
boost
::
regex
(
construct
,
boost
::
regex
::
extended
|
boost
::
regex
::
optimize
)};
type_validator
v
=
{
code
,
map
_to_primitive_t
ype
(
primitiveCode
),
boost
::
regex
(
construct
,
boost
::
regex
::
extended
|
boost
::
regex
::
optimize
)};
m_validator
.
add
TypeV
alidator
(
std
::
move
(
v
));
m_validator
.
add
_type_v
alidator
(
std
::
move
(
v
));
}
catch
(
const
std
::
exception
&
)
{
...
...
@@ -473,19 +473,19 @@ class dictionary_parser : public parser
return
result
;
}
V
alidator
&
m_validator
;
v
alidator
&
m_validator
;
bool
m_collected_item_types
=
false
;
std
::
vector
<
ValidateCategory
>
mCategoryValidators
;
std
::
map
<
std
::
string
,
std
::
vector
<
ValidateItem
>>
mItemValidators
;
std
::
vector
<
category_validator
>
mCategoryValidators
;
std
::
map
<
std
::
string
,
std
::
vector
<
item_validator
>>
mItemValidators
;
std
::
set
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
mLinkedItems
;
};
// --------------------------------------------------------------------
V
alidator
parse_dictionary
(
std
::
string_view
name
,
std
::
istream
&
is
)
v
alidator
parse_dictionary
(
std
::
string_view
name
,
std
::
istream
&
is
)
{
V
alidator
result
(
name
);
v
alidator
result
(
name
);
file
f
;
dictionary_parser
p
(
result
,
is
,
f
);
...
...
src/v2/item.cpp
View file @
04b7828a
...
...
@@ -31,13 +31,21 @@ namespace cif::v2
std
::
string_view
item_handle
::
text
()
const
{
for
(
auto
iv
=
m_row_handle
.
m_row
->
m_head
;
iv
!=
nullptr
;
iv
=
iv
->
m_next
)
if
(
m_row_handle
.
m_row
!=
nullptr
)
{
if
(
iv
->
m_column_ix
==
m_column
)
return
iv
->
text
();
for
(
auto
iv
=
m_row_handle
.
m_row
->
m_head
;
iv
!=
nullptr
;
iv
=
iv
->
m_next
)
{
if
(
iv
->
m_column_ix
==
m_column
)
return
iv
->
text
();
}
}
return
{};
}
void
item_handle
::
assign_value
(
const
item
&
v
)
{
m_row_handle
.
assign
(
m_column
,
v
.
value
(),
false
);
}
}
src/v2/validate.cpp
View file @
04b7828a
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 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
...
...
@@ -28,8 +28,8 @@
#include <fstream>
#include <iostream>
#include <cif++/v2/validate.hpp>
#include <cif++/v2/dictionary_parser.hpp>
#include <cif++/v2/validate.hpp>
namespace
cif
{
...
...
@@ -41,19 +41,19 @@ namespace cif::v2
using
cif
::
VERBOSE
;
ValidationError
::
ValidationE
rror
(
const
std
::
string
&
msg
)
:
m
M
sg
(
msg
)
validation_error
::
validation_e
rror
(
const
std
::
string
&
msg
)
:
m
_m
sg
(
msg
)
{
}
ValidationError
::
ValidationE
rror
(
const
std
::
string
&
cat
,
const
std
::
string
&
item
,
const
std
::
string
&
msg
)
:
m
M
sg
(
"When validating _"
+
cat
+
'.'
+
item
+
": "
+
msg
)
validation_error
::
validation_e
rror
(
const
std
::
string
&
cat
,
const
std
::
string
&
item
,
const
std
::
string
&
msg
)
:
m
_m
sg
(
"When validating _"
+
cat
+
'.'
+
item
+
": "
+
msg
)
{
}
// --------------------------------------------------------------------
DDL_PrimitiveType
map
ToPrimitiveT
ype
(
std
::
string_view
s
)
DDL_PrimitiveType
map
_to_primitive_t
ype
(
std
::
string_view
s
)
{
DDL_PrimitiveType
result
;
if
(
iequals
(
s
,
"char"
))
...
...
@@ -63,13 +63,13 @@ DDL_PrimitiveType mapToPrimitiveType(std::string_view s)
else
if
(
iequals
(
s
,
"numb"
))
result
=
DDL_PrimitiveType
::
Numb
;
else
throw
ValidationE
rror
(
"Not a known primitive type"
);
throw
validation_e
rror
(
"Not a known primitive type"
);
return
result
;
}
// --------------------------------------------------------------------
int
ValidateType
::
compare
(
const
char
*
a
,
const
char
*
b
)
const
int
type_validator
::
compare
(
const
char
*
a
,
const
char
*
b
)
const
{
int
result
=
0
;
...
...
@@ -81,7 +81,7 @@ int ValidateType::compare(const char *a, const char *b) const
{
try
{
switch
(
m
PrimitiveT
ype
)
switch
(
m
_primitive_t
ype
)
{
case
DDL_PrimitiveType
:
:
Numb
:
{
...
...
@@ -123,7 +123,7 @@ int ValidateType::compare(const char *a, const char *b) const
char
ca
=
*
ai
;
char
cb
=
*
bi
;
if
(
m
PrimitiveT
ype
==
DDL_PrimitiveType
::
UChar
)
if
(
m
_primitive_t
ype
==
DDL_PrimitiveType
::
UChar
)
{
ca
=
tolower
(
ca
);
cb
=
tolower
(
cb
);
...
...
@@ -161,10 +161,10 @@ int ValidateType::compare(const char *a, const char *b) const
// --------------------------------------------------------------------
//void ValidateItem::addLinked(ValidateItem* parent, const std::string& parentItem, const std::string& childItem)
//
void ValidateItem::addLinked(ValidateItem* parent, const std::string& parentItem, const std::string& childItem)
//{
//// if (mParent != nullptr and VERBOSE)
//// cerr << "replacing parent in " << mCategory->m
Name << " from " << mParent->mCategory->mName << " to " << parent->mCategory->mN
ame << endl;
//// cerr << "replacing parent in " << mCategory->m
_name << " from " << mParent->mCategory->m_name << " to " << parent->mCategory->m_n
ame << endl;
//// mParent = parent;
//
// if (mType == nullptr and parent != nullptr)
...
...
@@ -181,40 +181,40 @@ int ValidateType::compare(const char *a, const char *b) const
// }
//}
void
ValidateItem
::
operator
()(
std
::
string
value
)
const
void
item_validator
::
operator
()(
std
::
string_view
value
)
const
{
if
(
not
value
.
empty
()
and
value
!=
"?"
and
value
!=
"."
)
{
if
(
m
Type
!=
nullptr
and
not
regex_match
(
value
,
mType
->
mR
x
))
throw
ValidationError
(
mCategory
->
mName
,
mTag
,
"Value '"
+
value
+
"' does not match type expression for type "
+
mType
->
mN
ame
);
if
(
m
_type
!=
nullptr
and
not
regex_match
(
value
.
begin
(),
value
.
end
(),
m_type
->
m_r
x
))
throw
validation_error
(
m_category
->
m_name
,
m_tag
,
"Value '"
+
std
::
string
{
value
}
+
"' does not match type expression for type "
+
m_type
->
m_n
ame
);
if
(
not
m
E
nums
.
empty
())
if
(
not
m
_e
nums
.
empty
())
{
if
(
m
Enums
.
count
(
value
)
==
0
)
throw
ValidationError
(
mCategory
->
mName
,
mTag
,
"Value '"
+
value
+
"' is not in the list of allowed values"
);
if
(
m
_enums
.
count
(
std
::
string
{
value
}
)
==
0
)
throw
validation_error
(
m_category
->
m_name
,
m_tag
,
"Value '"
+
std
::
string
{
value
}
+
"' is not in the list of allowed values"
);
}
}
}
// --------------------------------------------------------------------
void
ValidateCategory
::
addItemValidator
(
ValidateItem
&&
v
)
void
category_validator
::
addItemValidator
(
item_validator
&&
v
)
{
if
(
v
.
m
M
andatory
)
m
MandatoryFields
.
insert
(
v
.
mT
ag
);
if
(
v
.
m
_m
andatory
)
m
_mandatory_fields
.
insert
(
v
.
m_t
ag
);
v
.
m
C
ategory
=
this
;
v
.
m
_c
ategory
=
this
;
auto
r
=
m
ItemV
alidators
.
insert
(
std
::
move
(
v
));
auto
r
=
m
_item_v
alidators
.
insert
(
std
::
move
(
v
));
if
(
not
r
.
second
and
VERBOSE
>=
4
)
std
::
cout
<<
"Could not add validator for item "
<<
v
.
m
Tag
<<
" to category "
<<
mN
ame
<<
std
::
endl
;
std
::
cout
<<
"Could not add validator for item "
<<
v
.
m
_tag
<<
" to category "
<<
m_n
ame
<<
std
::
endl
;
}
const
ValidateItem
*
ValidateCategory
::
getValidatorForI
tem
(
std
::
string_view
tag
)
const
const
item_validator
*
category_validator
::
get_validator_for_i
tem
(
std
::
string_view
tag
)
const
{
const
ValidateItem
*
result
=
nullptr
;
auto
i
=
m
ItemValidators
.
find
(
ValidateItem
{
std
::
string
(
tag
)});
if
(
i
!=
m
ItemV
alidators
.
end
())
const
item_validator
*
result
=
nullptr
;
auto
i
=
m
_item_validators
.
find
(
item_validator
{
std
::
string
(
tag
)});
if
(
i
!=
m
_item_v
alidators
.
end
())
result
=
&*
i
;
else
if
(
VERBOSE
>
4
)
std
::
cout
<<
"No validator for tag "
<<
tag
<<
std
::
endl
;
...
...
@@ -223,53 +223,53 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
// --------------------------------------------------------------------
void
Validator
::
addTypeValidator
(
ValidateType
&&
v
)
void
validator
::
add_type_validator
(
type_validator
&&
v
)
{
auto
r
=
m
TypeV
alidators
.
insert
(
std
::
move
(
v
));
auto
r
=
m
_type_v
alidators
.
insert
(
std
::
move
(
v
));
if
(
not
r
.
second
and
VERBOSE
>
4
)
std
::
cout
<<
"Could not add validator for type "
<<
v
.
m
N
ame
<<
std
::
endl
;
std
::
cout
<<
"Could not add validator for type "
<<
v
.
m
_n
ame
<<
std
::
endl
;
}
const
ValidateType
*
Validator
::
getValidatorForT
ype
(
std
::
string_view
typeCode
)
const
const
type_validator
*
validator
::
get_validator_for_t
ype
(
std
::
string_view
typeCode
)
const
{
const
ValidateType
*
result
=
nullptr
;
const
type_validator
*
result
=
nullptr
;
auto
i
=
m
TypeValidators
.
find
(
ValidateType
{
std
::
string
(
typeCode
),
DDL_PrimitiveType
::
Char
,
boost
::
regex
()});
if
(
i
!=
m
TypeV
alidators
.
end
())
auto
i
=
m
_type_validators
.
find
(
type_validator
{
std
::
string
(
typeCode
),
DDL_PrimitiveType
::
Char
,
boost
::
regex
()});
if
(
i
!=
m
_type_v
alidators
.
end
())
result
=
&*
i
;
else
if
(
VERBOSE
>
4
)
std
::
cout
<<
"No validator for type "
<<
typeCode
<<
std
::
endl
;
return
result
;
}
void
Validator
::
addCategoryValidator
(
ValidateCategory
&&
v
)
void
validator
::
add_category_validator
(
category_validator
&&
v
)
{
auto
r
=
m
CategoryV
alidators
.
insert
(
std
::
move
(
v
));
auto
r
=
m
_category_v
alidators
.
insert
(
std
::
move
(
v
));
if
(
not
r
.
second
and
VERBOSE
>
4
)
std
::
cout
<<
"Could not add validator for category "
<<
v
.
m
N
ame
<<
std
::
endl
;
std
::
cout
<<
"Could not add validator for category "
<<
v
.
m
_n
ame
<<
std
::
endl
;
}
const
ValidateCategory
*
Validator
::
getValidatorForC
ategory
(
std
::
string_view
category
)
const
const
category_validator
*
validator
::
get_validator_for_c
ategory
(
std
::
string_view
category
)
const
{
const
ValidateCategory
*
result
=
nullptr
;
auto
i
=
m
CategoryValidators
.
find
(
ValidateCategory
{
std
::
string
(
category
)});
if
(
i
!=
m
CategoryV
alidators
.
end
())
const
category_validator
*
result
=
nullptr
;
auto
i
=
m
_category_validators
.
find
(
category_validator
{
std
::
string
(
category
)});
if
(
i
!=
m
_category_v
alidators
.
end
())
result
=
&*
i
;
else
if
(
VERBOSE
>
4
)
std
::
cout
<<
"No validator for category "
<<
category
<<
std
::
endl
;
return
result
;
}
ValidateItem
*
Validator
::
getValidatorForI
tem
(
std
::
string_view
tag
)
const
item_validator
*
validator
::
get_validator_for_i
tem
(
std
::
string_view
tag
)
const
{
ValidateItem
*
result
=
nullptr
;
item_validator
*
result
=
nullptr
;
std
::
string
cat
,
item
;
std
::
tie
(
cat
,
item
)
=
splitTagName
(
tag
);
auto
*
cv
=
get
ValidatorForC
ategory
(
cat
);
auto
*
cv
=
get
_validator_for_c
ategory
(
cat
);
if
(
cv
!=
nullptr
)
result
=
const_cast
<
ValidateItem
*>
(
cv
->
getValidatorForI
tem
(
item
));
result
=
const_cast
<
item_validator
*>
(
cv
->
get_validator_for_i
tem
(
item
));
if
(
result
==
nullptr
and
VERBOSE
>
4
)
std
::
cout
<<
"No validator for item "
<<
tag
<<
std
::
endl
;
...
...
@@ -277,80 +277,80 @@ ValidateItem *Validator::getValidatorForItem(std::string_view tag) const
return
result
;
}
void
Validator
::
addLinkValidator
(
ValidateLink
&&
v
)
void
validator
::
add_link_validator
(
link_validator
&&
v
)
{
assert
(
v
.
m
ParentKeys
.
size
()
==
v
.
mChildK
eys
.
size
());
if
(
v
.
m
ParentKeys
.
size
()
!=
v
.
mChildK
eys
.
size
())
assert
(
v
.
m
_parent_keys
.
size
()
==
v
.
m_child_k
eys
.
size
());
if
(
v
.
m
_parent_keys
.
size
()
!=
v
.
m_child_k
eys
.
size
())
throw
std
::
runtime_error
(
"unequal number of keys for parent and child in link"
);
auto
pcv
=
get
ValidatorForCategory
(
v
.
mParentC
ategory
);
auto
ccv
=
get
ValidatorForCategory
(
v
.
mChildC
ategory
);
auto
pcv
=
get
_validator_for_category
(
v
.
m_parent_c
ategory
);
auto
ccv
=
get
_validator_for_category
(
v
.
m_child_c
ategory
);
if
(
pcv
==
nullptr
)
throw
std
::
runtime_error
(
"unknown parent category "
+
v
.
m
ParentC
ategory
);
throw
std
::
runtime_error
(
"unknown parent category "
+
v
.
m
_parent_c
ategory
);
if
(
ccv
==
nullptr
)
throw
std
::
runtime_error
(
"unknown child category "
+
v
.
m
ChildC
ategory
);
throw
std
::
runtime_error
(
"unknown child category "
+
v
.
m
_child_c
ategory
);
for
(
size_t
i
=
0
;
i
<
v
.
m
ParentK
eys
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
v
.
m
_parent_k
eys
.
size
();
++
i
)
{
auto
piv
=
pcv
->
get
ValidatorForItem
(
v
.
mParentK
eys
[
i
]);
auto
piv
=
pcv
->
get
_validator_for_item
(
v
.
m_parent_k
eys
[
i
]);
if
(
piv
==
nullptr
)
throw
std
::
runtime_error
(
"unknown parent tag _"
+
v
.
m
ParentCategory
+
'.'
+
v
.
mParentK
eys
[
i
]);
throw
std
::
runtime_error
(
"unknown parent tag _"
+
v
.
m
_parent_category
+
'.'
+
v
.
m_parent_k
eys
[
i
]);
auto
civ
=
ccv
->
get
ValidatorForItem
(
v
.
mChildK
eys
[
i
]);
auto
civ
=
ccv
->
get
_validator_for_item
(
v
.
m_child_k
eys
[
i
]);
if
(
civ
==
nullptr
)
throw
std
::
runtime_error
(
"unknown child tag _"
+
v
.
m
ChildCategory
+
'.'
+
v
.
mChildK
eys
[
i
]);
throw
std
::
runtime_error
(
"unknown child tag _"
+
v
.
m
_child_category
+
'.'
+
v
.
m_child_k
eys
[
i
]);
if
(
civ
->
m
Type
==
nullptr
and
piv
->
mT
ype
!=
nullptr
)
const_cast
<
ValidateItem
*>
(
civ
)
->
mType
=
piv
->
mT
ype
;
if
(
civ
->
m
_type
==
nullptr
and
piv
->
m_t
ype
!=
nullptr
)
const_cast
<
item_validator
*>
(
civ
)
->
m_type
=
piv
->
m_t
ype
;
}
m
LinkV
alidators
.
emplace_back
(
std
::
move
(
v
));
m
_link_v
alidators
.
emplace_back
(
std
::
move
(
v
));
}
std
::
vector
<
const
ValidateLink
*>
Validator
::
getLinksForP
arent
(
std
::
string_view
category
)
const
std
::
vector
<
const
link_validator
*>
validator
::
get_links_for_p
arent
(
std
::
string_view
category
)
const
{
std
::
vector
<
const
ValidateLink
*>
result
;
std
::
vector
<
const
link_validator
*>
result
;
for
(
auto
&
l
:
m
LinkV
alidators
)
for
(
auto
&
l
:
m
_link_v
alidators
)
{
if
(
l
.
m
ParentC
ategory
==
category
)
if
(
l
.
m
_parent_c
ategory
==
category
)
result
.
push_back
(
&
l
);
}
return
result
;
}
std
::
vector
<
const
ValidateLink
*>
Validator
::
getLinksForC
hild
(
std
::
string_view
category
)
const
std
::
vector
<
const
link_validator
*>
validator
::
get_links_for_c
hild
(
std
::
string_view
category
)
const
{
std
::
vector
<
const
ValidateLink
*>
result
;
std
::
vector
<
const
link_validator
*>
result
;
for
(
auto
&
l
:
m
LinkV
alidators
)
for
(
auto
&
l
:
m
_link_v
alidators
)
{
if
(
l
.
m
ChildC
ategory
==
category
)
if
(
l
.
m
_child_c
ategory
==
category
)
result
.
push_back
(
&
l
);
}
return
result
;
}
void
Validator
::
reportE
rror
(
const
std
::
string
&
msg
,
bool
fatal
)
const
void
validator
::
report_e
rror
(
const
std
::
string
&
msg
,
bool
fatal
)
const
{
if
(
m_strict
or
fatal
)
throw
ValidationE
rror
(
msg
);
throw
validation_e
rror
(
msg
);
else
if
(
VERBOSE
>
0
)
std
::
cerr
<<
msg
<<
std
::
endl
;
}
// --------------------------------------------------------------------
const
Validator
&
ValidatorF
actory
::
operator
[](
std
::
string_view
dictionary_name
)
const
validator
&
validator_f
actory
::
operator
[](
std
::
string_view
dictionary_name
)
{
std
::
lock_guard
lock
(
m
M
utex
);
std
::
lock_guard
lock
(
m
_m
utex
);
for
(
auto
&
validator
:
m
V
alidators
)
for
(
auto
&
validator
:
m
_v
alidators
)
{
if
(
iequals
(
validator
.
name
(),
dictionary_name
))
return
validator
;
...
...
@@ -384,12 +384,12 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name)
{
for
(
const
char
*
dir
:
{
#if defined(CACHE_DIR)
CACHE_DIR
,
CACHE_DIR
,
#endif
#if defined(DATA_DIR)
DATA_DIR
DATA_DIR
#endif
})
})
{
auto
p2
=
std
::
filesystem
::
path
(
dir
)
/
p
;
if
(
std
::
filesystem
::
exists
(
p2
,
ec
)
and
not
ec
)
...
...
@@ -417,14 +417,14 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name)
throw
std
::
runtime_error
(
"Dictionary not found or defined ("
+
dictionary
.
string
()
+
")"
);
}
assert
(
iequals
(
m
V
alidators
.
back
().
name
(),
dictionary_name
));
assert
(
iequals
(
m
_v
alidators
.
back
().
name
(),
dictionary_name
));
return
m
V
alidators
.
back
();
return
m
_v
alidators
.
back
();
}
void
ValidatorF
actory
::
construct_validator
(
std
::
string_view
name
,
std
::
istream
&
is
)
void
validator_f
actory
::
construct_validator
(
std
::
string_view
name
,
std
::
istream
&
is
)
{
mValidators
.
emplace_back
(
parse_dictionary
(
name
,
is
)
);
parse_dictionary
(
name
,
is
);
}
}
// namespace cif
}
// namespace cif
::v2
test/unit-v2-test.cpp
View file @
04b7828a
...
...
@@ -36,6 +36,7 @@
// #include <cif++/CifParser.hpp>
#include <cif++/v2/parser.hpp>
#include <cif++/v2/dictionary_parser.hpp>
namespace
tt
=
boost
::
test_tools
;
...
...
@@ -307,7 +308,7 @@ _test.name
// test.clear();
// auto n = test.erase(cif::
K
ey("id") == 1, [](const cif::Row &r)
// auto n = test.erase(cif::
v2::k
ey("id") == 1, [](const cif::Row &r)
// {
// BOOST_CHECK_EQUAL(r["id"].as<int>(), 1);
// BOOST_CHECK_EQUAL(r["name"].as<std::string>(), "aap"); });
...
...
@@ -385,171 +386,172 @@ _test.value
BOOST_CHECK
(
test
.
find
(
"value"
_key
==
cif
::
v2
::
null
).
size
()
==
2
);
}
// // --------------------------------------------------------------------
// BOOST_AUTO_TEST_CASE(d1)
// {
// const char dict[] = R"(
// data_test_dict.dic
// _datablock.id test_dict.dic
// _datablock.description
// ;
// A test dictionary
// ;
// _dictionary.title test_dict.dic
// _dictionary.datablock_id test_dict.dic
// _dictionary.version 1.0
// loop_
// _item_type_list.code
// _item_type_list.primitive_code
// _item_type_list.construct
// _item_type_list.detail
// code char
// '[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
// ; code item types/single words ...
// ;
// text char
// '[][ \n\t()_,.;:"&<>/\{}'`~!@#$%?+=*A-Za-z0-9|^-]*'
// ; text item types / multi-line text ...
// ;
// int numb
// '[+-]?[0-9]+'
// ; int item types are the subset of numbers that are the negative
// or positive integers.
// ;
// save_cat_1
// _category.description 'A simple test category'
// _category.id cat_1
// _category.mandatory_code no
// _category_key.name '_cat_1.id'
// save_
// save__cat_1.id
// _item.name '_cat_1.id'
// _item.category_id cat_1
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_linked.child_name '_cat_2.parent_id'
// _item_linked.parent_name '_cat_1.id'
// _item_type.code code
// save_
// save__cat_1.name
// _item.name '_cat_1.name'
// _item.category_id cat_1
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code text
// save_
// save_cat_2
// _category.description 'A second simple test category'
// _category.id cat_2
// _category.mandatory_code no
// _category_key.name '_cat_2.id'
// save_
// save__cat_2.id
// _item.name '_cat_2.id'
// _item.category_id cat_2
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code int
// save_
// save__cat_2.parent_id
// _item.name '_cat_2.parent_id'
// _item.category_id cat_2
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code code
// save_
// save__cat_2.desc
// _item.name '_cat_2.desc'
// _item.category_id cat_2
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code text
// save_
// )";
// --------------------------------------------------------------------
// struct membuf : public std::streambuf
// {
// membuf(char *text, size_t length)
// {
// this->setg(text, text, text + length);
// }
// } buffer(const_cast<char *>(dict), sizeof(dict) - 1);
BOOST_AUTO_TEST_CASE
(
d1
)
{
const
char
dict
[]
=
R"(
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.description
;
A test dictionary
;
_dictionary.title test_dict.dic
_dictionary.datablock_id test_dict.dic
_dictionary.version 1.0
loop_
_item_type_list.code
_item_type_list.primitive_code
_item_type_list.construct
_item_type_list.detail
code char
'[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
; code item types/single words ...
;
text char
'[][ \n\t()_,.;:"&<>/\{}'`~!@#$%?+=*A-Za-z0-9|^-]*'
; text item types / multi-line text ...
;
int numb
'[+-]?[0-9]+'
; int item types are the subset of numbers that are the negative
or positive integers.
;
save_cat_1
_category.description 'A simple test category'
_category.id cat_1
_category.mandatory_code no
_category_key.name '_cat_1.id'
save_
save__cat_1.id
_item.name '_cat_1.id'
_item.category_id cat_1
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_linked.child_name '_cat_2.parent_id'
_item_linked.parent_name '_cat_1.id'
_item_type.code code
save_
save__cat_1.name
_item.name '_cat_1.name'
_item.category_id cat_1
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code text
save_
save_cat_2
_category.description 'A second simple test category'
_category.id cat_2
_category.mandatory_code no
_category_key.name '_cat_2.id'
save_
save__cat_2.id
_item.name '_cat_2.id'
_item.category_id cat_2
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code int
save_
save__cat_2.parent_id
_item.name '_cat_2.parent_id'
_item.category_id cat_2
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code code
save_
save__cat_2.desc
_item.name '_cat_2.desc'
_item.category_id cat_2
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code text
save_
)"
;
// std::istream is_dict(&buffer);
struct
membuf
:
public
std
::
streambuf
{
membuf
(
char
*
text
,
size_t
length
)
{
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
// cif::Validator validator("test", is_dict
);
std
::
istream
is_dict
(
&
buffer
);
// cif::File f;
// f.setValidator(&validator);
auto
validator
=
cif
::
v2
::
parse_dictionary
(
"test"
,
is_dict
);
// // --------------------------------------------------------------------
cif
::
v2
::
file
f
;
f
.
set_validator
(
&
validator
);
// const char data[] = R"(
// data_test
// loop_
// _cat_1.id
// _cat_1.name
// 1 Aap
// 2 Noot
// 3 Mies
// --------------------------------------------------------------------
// loop_
// _cat_2.id
// _cat_2.parent_id
// _cat_2.desc
// 1 1 'Een dier'
// 2 1 'Een andere aap'
// 3 2 'walnoot bijvoorbeeld'
// )";
const
char
data
[]
=
R"(
data_test
loop_
_cat_1.id
_cat_1.name
1 Aap
2 Noot
3 Mies
// struct data_membuf : public std::streambuf
// {
// data_membuf(char *text, size_t length)
// {
// this->setg(text, text, text + length);
// }
// } data_buffer(const_cast<char *>(data), sizeof(data) - 1);
loop_
_cat_2.id
_cat_2.parent_id
_cat_2.desc
1 1 'Een dier'
2 1 'Een andere aap'
3 2 'walnoot bijvoorbeeld'
)"
;
struct
data_membuf
:
public
std
::
streambuf
{
data_membuf
(
char
*
text
,
size_t
length
)
{
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
//
std::istream is_data(&data_buffer);
//
f.load(is_data);
std
::
istream
is_data
(
&
data_buffer
);
f
.
load
(
is_data
);
//
auto &cat1 = f.front()["cat_1"];
//
auto &cat2 = f.front()["cat_2"];
auto
&
cat1
=
f
.
front
()[
"cat_1"
];
auto
&
cat2
=
f
.
front
()[
"cat_2"
];
//
BOOST_CHECK(cat1.size() == 3);
//
BOOST_CHECK(cat2.size() == 3);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
3
);
// cat1.erase(cif::K
ey("id") == 1);
cat1
.
erase
(
cif
::
v2
::
k
ey
(
"id"
)
==
1
);
//
BOOST_CHECK(cat1.size() == 2);
//
BOOST_CHECK(cat2.size() == 1);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
BOOST_CHECK
(
cat2
.
size
()
==
1
);
//
// BOOST_CHECK_THROW(cat2.emplace({
//
// { "id", 4 },
//
// { "parent_id", 4 },
//
// { "desc", "moet fout gaan" }
//
// }), std::exception);
// BOOST_CHECK_THROW(cat2.emplace({
// { "id", 4 },
// { "parent_id", 4 },
// { "desc", "moet fout gaan" }
// }), std::exception);
// BOOST_CHECK_THROW(cat2.emplace({{"id", "vijf"}, // <- invalid value
// {"parent_id", 2},
// {"desc", "moet fout gaan"}}),
// std::exception);
// }
BOOST_CHECK_THROW
(
cat2
.
emplace
({
{
"id"
,
"vijf"
},
// <- invalid value
{
"parent_id"
,
2
},
{
"desc"
,
"moet fout gaan"
}}),
std
::
exception
);
}
// // --------------------------------------------------------------------
...
...
@@ -621,7 +623,7 @@ _test.value
// std::istream is_dict(&buffer);
// cif::
V
alidator validator("test", is_dict);
// cif::
v2::v
alidator validator("test", is_dict);
// cif::File f;
// f.setValidator(&validator);
...
...
@@ -653,11 +655,11 @@ _test.value
// BOOST_CHECK(cat1.size() == 3);
// cat1.erase(cif::
K
ey("id") == "AAP");
// cat1.erase(cif::
v2::k
ey("id") == "AAP");
// BOOST_CHECK(cat1.size() == 3);
// cat1.erase(cif::
K
ey("id") == "noot");
// cat1.erase(cif::
v2::k
ey("id") == "noot");
// BOOST_CHECK(cat1.size() == 2);
// }
...
...
@@ -769,7 +771,7 @@ _test.value
// std::istream is_dict(&buffer);
// cif::
V
alidator validator("test", is_dict);
// cif::
v2::v
alidator validator("test", is_dict);
// cif::File f;
// f.setValidator(&validator);
...
...
@@ -813,7 +815,7 @@ _test.value
// // check a rename in parent and child
// for (auto r : cat1.find(cif::
K
ey("id") == 1))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 1))
// {
// r["id"] = 10;
// break;
...
...
@@ -822,15 +824,15 @@ _test.value
// BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 4);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 10).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 10).size() == 2);
// // check a rename in parent and child, this time only one child should be renamed
// for (auto r : cat1.find(cif::
K
ey("id") == 2))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 2))
// {
// r["id"] = 20;
// break;
...
...
@@ -839,25 +841,25 @@ _test.value
// BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 4);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 20).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 2).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 2).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::
Key("parent_id") == 2 and cif::K
ey("name2") == "noot").size() == 0);
// BOOST_CHECK(cat2.find(cif::
Key("parent_id") == 2 and cif::K
ey("name2") == "n2").size() == 1);
// BOOST_CHECK(cat2.find(cif::
Key("parent_id") == 20 and cif::K
ey("name2") == "noot").size() == 1);
// BOOST_CHECK(cat2.find(cif::
Key("parent_id") == 20 and cif::K
ey("name2") == "n2").size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::key("parent_id") == 2 and cif::v2::k
ey("name2") == "noot").size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::key("parent_id") == 2 and cif::v2::k
ey("name2") == "n2").size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::key("parent_id") == 20 and cif::v2::k
ey("name2") == "noot").size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::key("parent_id") == 20 and cif::v2::k
ey("name2") == "n2").size() == 0);
// // // --------------------------------------------------------------------
// // cat1.erase(cif::
K
ey("id") == 10);
// // cat1.erase(cif::
v2::k
ey("id") == 10);
// // BOOST_CHECK(cat1.size() == 2);
// // BOOST_CHECK(cat2.size() == 2);
// // cat1.erase(cif::
K
ey("id") == 20);
// // cat1.erase(cif::
v2::k
ey("id") == 20);
// // BOOST_CHECK(cat1.size() == 1);
// // BOOST_CHECK(cat2.size() == 1);
...
...
@@ -972,7 +974,7 @@ _test.value
// std::istream is_dict(&buffer);
// cif::
V
alidator validator("test", is_dict);
// cif::
v2::v
alidator validator("test", is_dict);
// cif::File f;
// f.setValidator(&validator);
...
...
@@ -1026,7 +1028,7 @@ _test.value
// // check a rename in parent and child
// for (auto r : cat1.find(cif::
K
ey("id") == 1))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 1))
// {
// r["id"] = 10;
// break;
...
...
@@ -1035,13 +1037,13 @@ _test.value
// BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 1).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 10).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 1).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 10).size() == 2);
// for (auto r : cat1.find(cif::
K
ey("id") == 2))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 2))
// {
// r["id"] = 20;
// break;
...
...
@@ -1050,13 +1052,13 @@ _test.value
// BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 20).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 2).size() == 2);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 2).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 20).size() == 2);
// for (auto r : cat1.find(cif::
K
ey("id") == 3))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 3))
// {
// r["id"] = 30;
// break;
...
...
@@ -1065,13 +1067,13 @@ _test.value
// BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 3).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 30).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 3).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 3).size() == 2);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 3).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 30).size() == 1);
// for (auto r : cat1.find(cif::
K
ey("id") == 4))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 4))
// {
// r["id"] = 40;
// break;
...
...
@@ -1080,11 +1082,11 @@ _test.value
// BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 4).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 4).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 4).size() == 3);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 40).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 4).size() == 3);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 40).size() == 0);
// }
// // --------------------------------------------------------------------
...
...
@@ -1193,7 +1195,7 @@ _test.value
// std::istream is_dict(&buffer);
// cif::
V
alidator validator("test", is_dict);
// cif::
v2::v
alidator validator("test", is_dict);
// cif::File f;
// f.setValidator(&validator);
...
...
@@ -1241,7 +1243,7 @@ _test.value
// // --------------------------------------------------------------------
// // check iterate children
// auto PR2set = cat1.find(cif::
K
ey("id") == 2);
// auto PR2set = cat1.find(cif::
v2::k
ey("id") == 2);
// BOOST_ASSERT(PR2set.size() == 1);
// auto PR2 = PR2set.front();
// BOOST_CHECK(PR2["id"].as<int>() == 2);
...
...
@@ -1257,7 +1259,7 @@ _test.value
// // check a rename in parent and child
// for (auto r : cat1.find(cif::
K
ey("id") == 1))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 1))
// {
// r["id"] = 10;
// break;
...
...
@@ -1266,17 +1268,17 @@ _test.value
// BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 7);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id2") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id3") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id2") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id3") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id2") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id3") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id2") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id3") == 10).size() == 1);
// for (auto r : cat1.find(cif::
K
ey("id") == 2))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 2))
// {
// r["id"] = 20;
// break;
...
...
@@ -1285,17 +1287,17 @@ _test.value
// BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 7);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 20).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id2") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id3") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id2") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id3") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id2") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id3") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id2") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id3") == 20).size() == 2);
// for (auto r : cat1.find(cif::
K
ey("id") == 3))
// for (auto r : cat1.find(cif::
v2::k
ey("id") == 3))
// {
// r["id"] = 30;
// break;
...
...
@@ -1304,27 +1306,27 @@ _test.value
// BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 7);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 3).size() == 0);
// BOOST_CHECK(cat1.find(cif::
K
ey("id") == 30).size() == 1);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 3).size() == 0);
// BOOST_CHECK(cat1.find(cif::
v2::k
ey("id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id2") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id3") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id2") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
K
ey("parent_id3") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id2") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id3") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id2") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::
v2::k
ey("parent_id3") == 30).size() == 1);
// // test delete
// cat1.erase(cif::
K
ey("id") == 10);
// cat1.erase(cif::
v2::k
ey("id") == 10);
// BOOST_CHECK(cat1.size() == 2);
// BOOST_CHECK(cat2.size() == 4);
// cat1.erase(cif::
K
ey("id") == 20);
// cat1.erase(cif::
v2::k
ey("id") == 20);
// BOOST_CHECK(cat1.size() == 1);
// BOOST_CHECK(cat2.size() == 1);
// cat1.erase(cif::
K
ey("id") == 30);
// cat1.erase(cif::
v2::k
ey("id") == 30);
// BOOST_CHECK(cat1.size() == 0);
// BOOST_CHECK(cat2.size() == 0);
// }
...
...
@@ -1349,21 +1351,21 @@ _test.value
// auto &db = f.front();
// for (auto r : db["test"].find(cif::
K
ey("id") == 1))
// for (auto r : db["test"].find(cif::
v2::k
ey("id") == 1))
// {
// const auto &[id, name] = r.get<int, std::string>({"id", "name"});
// BOOST_CHECK(id == 1);
// BOOST_CHECK(name == "aap");
// }
// for (auto r : db["test"].find(cif::
K
ey("id") == 4))
// for (auto r : db["test"].find(cif::
v2::k
ey("id") == 4))
// {
// const auto &[id, name] = r.get<int, std::string>({"id", "name"});
// BOOST_CHECK(id == 4);
// BOOST_CHECK(name.empty());
// }
// for (auto r : db["test"].find(cif::
K
ey("id") == 5))
// for (auto r : db["test"].find(cif::
v2::k
ey("id") == 5))
// {
// const auto &[id, name] = r.get<int, std::string>({"id", "name"});
// BOOST_CHECK(id == 5);
...
...
@@ -1456,7 +1458,7 @@ _test.value
// }
// }
// const auto &[id, name] = db["test"].find1<int, std::string>(cif::
K
ey("id") == 1, "id", "name");
// const auto &[id, name] = db["test"].find1<int, std::string>(cif::
v2::k
ey("id") == 1, "id", "name");
// BOOST_CHECK(id == 1);
// BOOST_CHECK(name == "aap");
...
...
@@ -1621,7 +1623,7 @@ _test.value
// } buffer(const_cast<char *>(dict), sizeof(dict) - 1);
// std::istream is_dict(&buffer);
// cif::
V
alidator validator("test", is_dict);
// cif::
v2::v
alidator validator("test", is_dict);
// cif::File f;
// f.setValidator(&validator);
...
...
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