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
19210df6
Unverified
Commit
19210df6
authored
Feb 08, 2022
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix parsing mmCIF files with an unquoted string ??
parent
15c57307
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
651 additions
and
657 deletions
+651
-657
CMakeLists.txt
+1
-1
changelog
+7
-0
include/cif++/CifParser.hpp
+8
-8
src/CifParser.cpp
+73
-109
test/unit-test.cpp
+562
-539
No files found.
CMakeLists.txt
View file @
19210df6
...
@@ -25,7 +25,7 @@
...
@@ -25,7 +25,7 @@
cmake_minimum_required
(
VERSION 3.16
)
cmake_minimum_required
(
VERSION 3.16
)
# set the project name
# set the project name
project
(
cifpp VERSION 3.0.
2
LANGUAGES CXX
)
project
(
cifpp VERSION 3.0.
4
LANGUAGES CXX
)
list
(
PREPEND CMAKE_MODULE_PATH
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/cmake"
)
list
(
PREPEND CMAKE_MODULE_PATH
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/cmake"
)
...
...
changelog
View file @
19210df6
Version
3.0.4
-
Fix
in
mmCIF
parser
,
now
correctly
handles
the
unquoted
string
??
Version
3.0.3
Version
3.0.3
-
Better
configuration
checks
,
for
atomic
e
.
g
.
-
Better
configuration
checks
,
for
atomic
e
.
g
.
-
Fixed
a
problem
introduced
in
refactoring
mmcif
::
Atom
-
Fixed
a
problem
introduced
in
refactoring
mmcif
::
Atom
...
@@ -17,6 +21,9 @@ Version 3.0.0
...
@@ -17,6 +21,9 @@ Version 3.0.0
-
Upgraded
mmcif
::
Structure
-
Upgraded
mmcif
::
Structure
-
various
other
small
fixes
-
various
other
small
fixes
Version
2.0.5
-
Backporting
updated
CMakeLists
.
txt
file
Version
2.0.4
Version
2.0.4
-
Reverted
a
too
strict
test
when
reading
cif
files
.
-
Reverted
a
too
strict
test
when
reading
cif
files
.
...
...
include/cif++/CifParser.hpp
View file @
19210df6
/*-
/*-
* SPDX-License-Identifier: BSD-2-Clause
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* 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
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
@@ -139,7 +139,7 @@ class SacParser
...
@@ -139,7 +139,7 @@ class SacParser
int
getNextChar
();
int
getNextChar
();
void
retract
();
void
retract
();
void
restart
(
);
int
restart
(
int
start
);
CIFToken
getNextToken
();
CIFToken
getNextToken
();
void
match
(
CIFToken
token
);
void
match
(
CIFToken
token
);
...
@@ -181,8 +181,9 @@ class SacParser
...
@@ -181,8 +181,9 @@ class SacParser
eStateTextField
,
eStateTextField
,
eStateFloat
=
100
,
eStateFloat
=
100
,
eStateInt
=
110
,
eStateInt
=
110
,
// eStateNumericSuffix = 200,
eStateValue
=
300
,
eStateValue
=
300
eStateDATA
,
eStateSAVE
};
};
std
::
istream
&
mData
;
std
::
istream
&
mData
;
...
@@ -191,7 +192,6 @@ class SacParser
...
@@ -191,7 +192,6 @@ class SacParser
bool
mValidate
;
bool
mValidate
;
uint32_t
mLineNr
;
uint32_t
mLineNr
;
bool
mBol
;
bool
mBol
;
int
mState
,
mStart
;
CIFToken
mLookahead
;
CIFToken
mLookahead
;
std
::
string
mTokenValue
;
std
::
string
mTokenValue
;
CIFValueType
mTokenType
;
CIFValueType
mTokenType
;
...
...
src/CifParser.cpp
View file @
19210df6
/*-
/*-
* SPDX-License-Identifier: BSD-2-Clause
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* 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
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
@@ -42,7 +42,7 @@ namespace cif
...
@@ -42,7 +42,7 @@ namespace cif
const
uint32_t
kMaxLineLength
=
132
;
const
uint32_t
kMaxLineLength
=
132
;
const
uint8_t
kCharTraitsTable
[
128
]
=
{
const
uint8_t
kCharTraitsTable
[
128
]
=
{
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
14
,
15
,
14
,
14
,
14
,
15
,
15
,
14
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
// 2
14
,
15
,
14
,
14
,
14
,
15
,
15
,
14
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
// 2
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
10
,
15
,
15
,
15
,
15
,
// 3
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
10
,
15
,
15
,
15
,
15
,
// 3
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
// 4
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
15
,
// 4
...
@@ -151,23 +151,26 @@ void SacParser::retract()
...
@@ -151,23 +151,26 @@ void SacParser::retract()
mTokenValue
.
pop_back
();
mTokenValue
.
pop_back
();
}
}
void
SacParser
::
restart
()
int
SacParser
::
restart
(
int
start
)
{
{
int
result
=
0
;
while
(
not
mTokenValue
.
empty
())
while
(
not
mTokenValue
.
empty
())
retract
();
retract
();
switch
(
mS
tart
)
switch
(
s
tart
)
{
{
case
eStateStart
:
case
eStateStart
:
mState
=
mStar
t
=
eStateFloat
;
resul
t
=
eStateFloat
;
break
;
break
;
case
eStateFloat
:
case
eStateFloat
:
mState
=
mStar
t
=
eStateInt
;
resul
t
=
eStateInt
;
break
;
break
;
case
eStateInt
:
case
eStateInt
:
mState
=
mStar
t
=
eStateValue
;
resul
t
=
eStateValue
;
break
;
break
;
default
:
default
:
...
@@ -175,6 +178,8 @@ void SacParser::restart()
...
@@ -175,6 +178,8 @@ void SacParser::restart()
}
}
mBol
=
false
;
mBol
=
false
;
return
result
;
}
}
void
SacParser
::
match
(
SacParser
::
CIFToken
t
)
void
SacParser
::
match
(
SacParser
::
CIFToken
t
)
...
@@ -191,7 +196,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -191,7 +196,7 @@ SacParser::CIFToken SacParser::getNextToken()
CIFToken
result
=
eCIFTokenUnknown
;
CIFToken
result
=
eCIFTokenUnknown
;
int
quoteChar
=
0
;
int
quoteChar
=
0
;
mState
=
mS
tart
=
eStateStart
;
int
state
=
eStateStart
,
s
tart
=
eStateStart
;
mBol
=
false
;
mBol
=
false
;
mTokenValue
.
clear
();
mTokenValue
.
clear
();
...
@@ -201,7 +206,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -201,7 +206,7 @@ SacParser::CIFToken SacParser::getNextToken()
{
{
auto
ch
=
getNextChar
();
auto
ch
=
getNextChar
();
switch
(
mS
tate
)
switch
(
s
tate
)
{
{
case
eStateStart
:
case
eStateStart
:
if
(
ch
==
kEOF
)
if
(
ch
==
kEOF
)
...
@@ -209,27 +214,23 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -209,27 +214,23 @@ SacParser::CIFToken SacParser::getNextToken()
else
if
(
ch
==
'\n'
)
else
if
(
ch
==
'\n'
)
{
{
mBol
=
true
;
mBol
=
true
;
mS
tate
=
eStateWhite
;
s
tate
=
eStateWhite
;
}
}
else
if
(
ch
==
' '
or
ch
==
'\t'
)
else
if
(
ch
==
' '
or
ch
==
'\t'
)
mS
tate
=
eStateWhite
;
s
tate
=
eStateWhite
;
else
if
(
ch
==
'#'
)
else
if
(
ch
==
'#'
)
mState
=
eStateComment
;
state
=
eStateComment
;
else
if
(
ch
==
'.'
)
mState
=
eStateDot
;
else
if
(
ch
==
'_'
)
else
if
(
ch
==
'_'
)
mS
tate
=
eStateTag
;
s
tate
=
eStateTag
;
else
if
(
ch
==
';'
and
mBol
)
else
if
(
ch
==
';'
and
mBol
)
mS
tate
=
eStateTextField
;
s
tate
=
eStateTextField
;
else
if
(
ch
==
'\''
or
ch
==
'"'
)
else
if
(
ch
==
'\''
or
ch
==
'"'
)
{
{
quoteChar
=
ch
;
quoteChar
=
ch
;
mS
tate
=
eStateQuotedString
;
s
tate
=
eStateQuotedString
;
}
}
else
if
(
ch
==
'?'
)
mState
=
eStateQuestionMark
;
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
case
eStateWhite
:
case
eStateWhite
:
...
@@ -237,7 +238,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -237,7 +238,7 @@ SacParser::CIFToken SacParser::getNextToken()
result
=
eCIFTokenEOF
;
result
=
eCIFTokenEOF
;
else
if
(
not
isspace
(
ch
))
else
if
(
not
isspace
(
ch
))
{
{
mS
tate
=
eStateStart
;
s
tate
=
eStateStart
;
retract
();
retract
();
mTokenValue
.
clear
();
mTokenValue
.
clear
();
}
}
...
@@ -248,7 +249,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -248,7 +249,7 @@ SacParser::CIFToken SacParser::getNextToken()
case
eStateComment
:
case
eStateComment
:
if
(
ch
==
'\n'
)
if
(
ch
==
'\n'
)
{
{
mS
tate
=
eStateStart
;
s
tate
=
eStateStart
;
mBol
=
true
;
mBol
=
true
;
mTokenValue
.
clear
();
mTokenValue
.
clear
();
}
}
...
@@ -258,44 +259,19 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -258,44 +259,19 @@ SacParser::CIFToken SacParser::getNextToken()
error
(
"invalid character in comment"
);
error
(
"invalid character in comment"
);
break
;
break
;
case
eStateQuestionMark
:
if
(
isNonBlank
(
ch
))
mState
=
eStateValue
;
else
{
retract
();
result
=
eCIFTokenValue
;
mTokenValue
.
clear
();
mTokenType
=
eCIFValueUnknown
;
}
break
;
case
eStateDot
:
if
(
isdigit
(
ch
))
mState
=
eStateFloat
+
2
;
else
if
(
isspace
(
ch
))
{
retract
();
result
=
eCIFTokenValue
;
mTokenType
=
eCIFValueInapplicable
;
}
else
mState
=
eStateValue
;
break
;
case
eStateTextField
:
case
eStateTextField
:
if
(
ch
==
'\n'
)
if
(
ch
==
'\n'
)
mS
tate
=
eStateTextField
+
1
;
s
tate
=
eStateTextField
+
1
;
else
if
(
ch
==
kEOF
)
else
if
(
ch
==
kEOF
)
error
(
"unterminated textfield"
);
error
(
"unterminated textfield"
);
else
if
(
not
isAnyPrint
(
ch
)
and
cif
::
VERBOSE
>=
0
)
else
if
(
not
isAnyPrint
(
ch
))
// error("invalid character in text field '" + string({ static_cast<char>(ch) }) + "' (" + to_string((int)ch) + ")");
// error("invalid character in text field '" + string({ static_cast<char>(ch) }) + "' (" + to_string((int)ch) + ")");
std
::
cerr
<<
"invalid character in text field '"
<<
std
::
string
({
static_cast
<
char
>
(
ch
)})
<<
"' ("
<<
ch
<<
") line: "
<<
mLineNr
<<
std
::
endl
;
std
::
cerr
<<
"invalid character in text field '"
<<
std
::
string
({
static_cast
<
char
>
(
ch
)})
<<
"' ("
<<
ch
<<
") line: "
<<
mLineNr
<<
std
::
endl
;
break
;
break
;
case
eStateTextField
+
1
:
case
eStateTextField
+
1
:
if
(
isTextLead
(
ch
)
or
ch
==
' '
or
ch
==
'\t'
)
if
(
isTextLead
(
ch
)
or
ch
==
' '
or
ch
==
'\t'
)
mS
tate
=
eStateTextField
;
s
tate
=
eStateTextField
;
else
if
(
ch
==
';'
)
else
if
(
ch
==
';'
)
{
{
assert
(
mTokenValue
.
length
()
>=
2
);
assert
(
mTokenValue
.
length
()
>=
2
);
...
@@ -313,7 +289,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -313,7 +289,7 @@ SacParser::CIFToken SacParser::getNextToken()
if
(
ch
==
kEOF
)
if
(
ch
==
kEOF
)
error
(
"unterminated quoted string"
);
error
(
"unterminated quoted string"
);
else
if
(
ch
==
quoteChar
)
else
if
(
ch
==
quoteChar
)
mS
tate
=
eStateQuotedStringQuote
;
s
tate
=
eStateQuotedStringQuote
;
else
if
(
not
isAnyPrint
(
ch
))
else
if
(
not
isAnyPrint
(
ch
))
error
(
"invalid character in quoted string"
);
error
(
"invalid character in quoted string"
);
break
;
break
;
...
@@ -331,7 +307,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -331,7 +307,7 @@ SacParser::CIFToken SacParser::getNextToken()
else
if
(
ch
==
quoteChar
)
else
if
(
ch
==
quoteChar
)
;
;
else
if
(
isAnyPrint
(
ch
))
else
if
(
isAnyPrint
(
ch
))
mS
tate
=
eStateQuotedString
;
s
tate
=
eStateQuotedString
;
else
if
(
ch
==
kEOF
)
else
if
(
ch
==
kEOF
)
error
(
"unterminated quoted string"
);
error
(
"unterminated quoted string"
);
else
else
...
@@ -349,12 +325,12 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -349,12 +325,12 @@ SacParser::CIFToken SacParser::getNextToken()
case
eStateFloat
:
case
eStateFloat
:
if
(
ch
==
'+'
or
ch
==
'-'
)
if
(
ch
==
'+'
or
ch
==
'-'
)
{
{
mS
tate
=
eStateFloat
+
1
;
s
tate
=
eStateFloat
+
1
;
}
}
else
if
(
isdigit
(
ch
))
else
if
(
isdigit
(
ch
))
mS
tate
=
eStateFloat
+
1
;
s
tate
=
eStateFloat
+
1
;
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
case
eStateFloat
+
1
:
case
eStateFloat
+
1
:
...
@@ -362,9 +338,9 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -362,9 +338,9 @@ SacParser::CIFToken SacParser::getNextToken()
// mState = eStateNumericSuffix;
// mState = eStateNumericSuffix;
// else
// else
if
(
ch
==
'.'
)
if
(
ch
==
'.'
)
mS
tate
=
eStateFloat
+
2
;
s
tate
=
eStateFloat
+
2
;
else
if
(
tolower
(
ch
)
==
'e'
)
else
if
(
tolower
(
ch
)
==
'e'
)
mS
tate
=
eStateFloat
+
3
;
s
tate
=
eStateFloat
+
3
;
else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
{
{
retract
();
retract
();
...
@@ -372,16 +348,13 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -372,16 +348,13 @@ SacParser::CIFToken SacParser::getNextToken()
mTokenType
=
eCIFValueInt
;
mTokenType
=
eCIFValueInt
;
}
}
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
// parsed '.'
// parsed '.'
case
eStateFloat
+
2
:
case
eStateFloat
+
2
:
// if (ch == '(') // numeric???
// mState = eStateNumericSuffix;
// else
if
(
tolower
(
ch
)
==
'e'
)
if
(
tolower
(
ch
)
==
'e'
)
mS
tate
=
eStateFloat
+
3
;
s
tate
=
eStateFloat
+
3
;
else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
{
{
retract
();
retract
();
...
@@ -389,30 +362,27 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -389,30 +362,27 @@ SacParser::CIFToken SacParser::getNextToken()
mTokenType
=
eCIFValueFloat
;
mTokenType
=
eCIFValueFloat
;
}
}
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
// parsed 'e'
// parsed 'e'
case
eStateFloat
+
3
:
case
eStateFloat
+
3
:
if
(
ch
==
'-'
or
ch
==
'+'
)
if
(
ch
==
'-'
or
ch
==
'+'
)
mS
tate
=
eStateFloat
+
4
;
s
tate
=
eStateFloat
+
4
;
else
if
(
isdigit
(
ch
))
else
if
(
isdigit
(
ch
))
mS
tate
=
eStateFloat
+
5
;
s
tate
=
eStateFloat
+
5
;
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
case
eStateFloat
+
4
:
case
eStateFloat
+
4
:
if
(
isdigit
(
ch
))
if
(
isdigit
(
ch
))
mS
tate
=
eStateFloat
+
5
;
s
tate
=
eStateFloat
+
5
;
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
case
eStateFloat
+
5
:
case
eStateFloat
+
5
:
// if (ch == '(')
// mState = eStateNumericSuffix;
// else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
{
{
retract
();
retract
();
...
@@ -420,14 +390,14 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -420,14 +390,14 @@ SacParser::CIFToken SacParser::getNextToken()
mTokenType
=
eCIFValueFloat
;
mTokenType
=
eCIFValueFloat
;
}
}
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
case
eStateInt
:
case
eStateInt
:
if
(
isdigit
(
ch
)
or
ch
==
'+'
or
ch
==
'-'
)
if
(
isdigit
(
ch
)
or
ch
==
'+'
or
ch
==
'-'
)
mS
tate
=
eStateInt
+
1
;
s
tate
=
eStateInt
+
1
;
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
case
eStateInt
+
1
:
case
eStateInt
+
1
:
...
@@ -438,35 +408,11 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -438,35 +408,11 @@ SacParser::CIFToken SacParser::getNextToken()
mTokenType
=
eCIFValueInt
;
mTokenType
=
eCIFValueInt
;
}
}
else
else
restart
(
);
state
=
start
=
restart
(
start
);
break
;
break
;
// case eStateNumericSuffix:
// if (isdigit(ch))
// mState = eStateNumericSuffix + 1;
// else
// restart();
// break;
//
// case eStateNumericSuffix + 1:
// if (ch == ')')
// {
// result = eCIFTokenValue;
// mTokenType = eCIFValueNumeric;
// }
// else if (not isdigit(ch))
// restart();
// break;
case
eStateValue
:
case
eStateValue
:
if
(
isNonBlank
(
ch
))
if
(
ch
==
'_'
)
mState
=
eStateValue
+
1
;
else
error
(
"invalid character at this position"
);
break
;
case
eStateValue
+
1
:
if
(
ch
==
'_'
)
// first _, check for keywords
{
{
std
::
string
s
=
toLowerCopy
(
mTokenValue
);
std
::
string
s
=
toLowerCopy
(
mTokenValue
);
...
@@ -476,23 +422,40 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -476,23 +422,40 @@ SacParser::CIFToken SacParser::getNextToken()
result
=
eCIFTokenSTOP
;
result
=
eCIFTokenSTOP
;
else
if
(
s
==
"loop_"
)
else
if
(
s
==
"loop_"
)
result
=
eCIFTokenLOOP
;
result
=
eCIFTokenLOOP
;
else
if
(
s
==
"data_"
or
s
==
"save_"
)
else
if
(
s
==
"data_"
)
mState
=
eStateValue
+
2
;
{
state
=
eStateDATA
;
continue
;
}
else
if
(
s
==
"save_"
)
{
state
=
eStateSAVE
;
continue
;
}
}
}
else
if
(
not
isNonBlank
(
ch
))
if
(
result
==
eCIFTokenUnknown
and
not
isNonBlank
(
ch
))
{
{
retract
();
retract
();
result
=
eCIFTokenValue
;
result
=
eCIFTokenValue
;
mTokenType
=
eCIFValueString
;
if
(
mTokenValue
==
"."
)
mTokenType
=
eCIFValueInapplicable
;
else
if
(
mTokenValue
==
"?"
)
{
mTokenType
=
eCIFValueUnknown
;
mTokenValue
.
clear
();
}
}
}
break
;
break
;
case
eStateValue
+
2
:
case
eStateDATA
:
case
eStateSAVE
:
if
(
not
isNonBlank
(
ch
))
if
(
not
isNonBlank
(
ch
))
{
{
retract
();
retract
();
if
(
tolower
(
mTokenValue
[
0
])
==
'd'
)
if
(
state
==
eStateDATA
)
result
=
eCIFTokenDATA
;
result
=
eCIFTokenDATA
;
else
else
result
=
eCIFTokenSAVE
;
result
=
eCIFTokenSAVE
;
...
@@ -521,6 +484,7 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -521,6 +484,7 @@ SacParser::CIFToken SacParser::getNextToken()
return
result
;
return
result
;
}
}
DatablockIndex
SacParser
::
indexDatablocks
()
DatablockIndex
SacParser
::
indexDatablocks
()
{
{
DatablockIndex
index
;
DatablockIndex
index
;
...
...
test/unit-test.cpp
View file @
19210df6
/*-
/*-
* SPDX-License-Identifier: BSD-2-Clause
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* 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
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
@@ -31,36 +31,35 @@
...
@@ -31,36 +31,35 @@
#include <stdexcept>
#include <stdexcept>
// #include "cif++/DistanceMap.hpp"
// #include "cif++/DistanceMap.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/BondMap.hpp"
#include "cif++/BondMap.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/CifValidator.hpp"
#include "cif++/CifValidator.hpp"
namespace
tt
=
boost
::
test_tools
;
namespace
tt
=
boost
::
test_tools
;
std
::
filesystem
::
path
gTestDir
=
std
::
filesystem
::
current_path
();
// filled in first test
std
::
filesystem
::
path
gTestDir
=
std
::
filesystem
::
current_path
();
// filled in first test
// --------------------------------------------------------------------
// --------------------------------------------------------------------
cif
::
File
operator
""
_cf
(
const
char
*
text
,
size_t
length
)
cif
::
File
operator
""
_cf
(
const
char
*
text
,
size_t
length
)
{
{
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
text
),
length
);
}
buffer
(
const_cast
<
char
*>
(
text
),
length
);
std
::
istream
is
(
&
buffer
);
std
::
istream
is
(
&
buffer
);
return
cif
::
File
(
is
);
return
cif
::
File
(
is
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
bool
init_unit_test
()
bool
init_unit_test
()
{
{
cif
::
VERBOSE
=
1
;
cif
::
VERBOSE
=
1
;
// not a test, just initialize test dir
// not a test, just initialize test dir
if
(
boost
::
unit_test
::
framework
::
master_test_suite
().
argc
==
2
)
if
(
boost
::
unit_test
::
framework
::
master_test_suite
().
argc
==
2
)
...
@@ -79,9 +78,9 @@ bool init_unit_test()
...
@@ -79,9 +78,9 @@ bool init_unit_test()
BOOST_AUTO_TEST_CASE
(
ut1
)
BOOST_AUTO_TEST_CASE
(
ut1
)
{
{
// using namespace mmcif;
// using namespace mmcif;
auto
f
=
R"(data_TEST
auto
f
=
R"(data_TEST
#
#
loop_
loop_
_test.id
_test.id
...
@@ -91,36 +90,36 @@ _test.name
...
@@ -91,36 +90,36 @@ _test.name
3 mies
3 mies
)"
_cf
;
)"
_cf
;
auto
&
db
=
f
.
firstDatablock
();
auto
&
db
=
f
.
firstDatablock
();
BOOST_CHECK
(
db
.
getName
()
==
"TEST"
);
auto
&
test
=
db
[
"test"
];
BOOST_CHECK
(
test
.
size
()
==
3
);
BOOST_CHECK
(
db
.
getName
()
==
"TEST"
);
// wrong! the next lines will crash. And that's OK, don't do that
// for (auto r: test)
auto
&
test
=
db
[
"test"
];
// test.erase(r);
BOOST_CHECK
(
test
.
size
()
==
3
);
// wrong! the next lines will crash. And that's OK, don't do that
// BOOST_CHECK(test.empty());
// for (auto r: test)
// test.erase(r);
// BOOST_CHECK(test.empty());
// test.purge();
// test.purge();
auto
n
=
test
.
erase
(
cif
::
Key
(
"id"
)
==
1
,
[](
const
cif
::
Row
&
r
)
{
auto
n
=
test
.
erase
(
cif
::
Key
(
"id"
)
==
1
,
[](
const
cif
::
Row
&
r
)
{
BOOST_CHECK_EQUAL
(
r
[
"id"
].
as
<
int
>
(),
1
);
BOOST_CHECK_EQUAL
(
r
[
"id"
].
as
<
int
>
(),
1
);
BOOST_CHECK_EQUAL
(
r
[
"name"
].
as
<
std
::
string
>
(),
"aap"
);
BOOST_CHECK_EQUAL
(
r
[
"name"
].
as
<
std
::
string
>
(),
"aap"
);
});
});
BOOST_CHECK_EQUAL
(
n
,
1
);
BOOST_CHECK_EQUAL
(
n
,
1
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
ut2
)
BOOST_AUTO_TEST_CASE
(
ut2
)
{
{
// using namespace mmcif;
// using namespace mmcif;
auto
f
=
R"(data_TEST
auto
f
=
R"(data_TEST
#
#
loop_
loop_
_test.id
_test.id
...
@@ -131,36 +130,36 @@ _test.value
...
@@ -131,36 +130,36 @@ _test.value
3 mies 1.2
3 mies 1.2
)"
_cf
;
)"
_cf
;
auto
&
db
=
f
.
firstDatablock
();
auto
&
db
=
f
.
firstDatablock
();
BOOST_CHECK
(
db
.
getName
()
==
"TEST"
);
BOOST_CHECK
(
db
.
getName
()
==
"TEST"
);
auto
&
test
=
db
[
"test"
];
auto
&
test
=
db
[
"test"
];
BOOST_CHECK
(
test
.
size
()
==
3
);
BOOST_CHECK
(
test
.
size
()
==
3
);
int
n
=
0
;
int
n
=
0
;
for
(
auto
r
:
test
.
find
(
cif
::
Key
(
"name"
)
==
"aap"
))
for
(
auto
r
:
test
.
find
(
cif
::
Key
(
"name"
)
==
"aap"
))
{
{
BOOST_CHECK
(
++
n
==
1
);
BOOST_CHECK
(
++
n
==
1
);
BOOST_CHECK
(
r
[
"id"
].
as
<
int
>
()
==
1
);
BOOST_CHECK
(
r
[
"id"
].
as
<
int
>
()
==
1
);
BOOST_CHECK
(
r
[
"name"
].
as
<
std
::
string
>
()
==
"aap"
);
BOOST_CHECK
(
r
[
"name"
].
as
<
std
::
string
>
()
==
"aap"
);
BOOST_CHECK
(
r
[
"value"
].
as
<
float
>
()
==
1.0
);
BOOST_CHECK
(
r
[
"value"
].
as
<
float
>
()
==
1.0
);
}
}
auto
t
=
test
.
find
(
cif
::
Key
(
"id"
)
==
1
);
auto
t
=
test
.
find
(
cif
::
Key
(
"id"
)
==
1
);
BOOST_CHECK
(
not
t
.
empty
());
BOOST_CHECK
(
not
t
.
empty
());
BOOST_CHECK
(
t
.
front
()[
"name"
].
as
<
std
::
string
>
()
==
"aap"
);
BOOST_CHECK
(
t
.
front
()[
"name"
].
as
<
std
::
string
>
()
==
"aap"
);
auto
t2
=
test
.
find
(
cif
::
Key
(
"value"
)
==
1.2
);
auto
t2
=
test
.
find
(
cif
::
Key
(
"value"
)
==
1.2
);
BOOST_CHECK
(
not
t2
.
empty
());
BOOST_CHECK
(
not
t2
.
empty
());
BOOST_CHECK
(
t2
.
front
()[
"name"
].
as
<
std
::
string
>
()
==
"mies"
);
BOOST_CHECK
(
t2
.
front
()[
"name"
].
as
<
std
::
string
>
()
==
"mies"
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
d1
)
BOOST_AUTO_TEST_CASE
(
d1
)
{
{
const
char
dict
[]
=
R"(
const
char
dict
[]
=
R"(
data_test_dict.dic
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.id test_dict.dic
_datablock.description
_datablock.description
...
@@ -253,24 +252,24 @@ save__cat_2.desc
...
@@ -253,24 +252,24 @@ save__cat_2.desc
save_
save_
)"
;
)"
;
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
setValidator
(
&
validator
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
data
[]
=
R"(
const
char
data
[]
=
R"(
data_test
data_test
loop_
loop_
_cat_1.id
_cat_1.id
...
@@ -286,48 +285,47 @@ _cat_2.desc
...
@@ -286,48 +285,47 @@ _cat_2.desc
1 1 'Een dier'
1 1 'Een dier'
2 1 'Een andere aap'
2 1 'Een andere aap'
3 2 'walnoot bijvoorbeeld'
3 2 'walnoot bijvoorbeeld'
)"
;
)"
;
struct
data_membuf
:
public
std
::
streambuf
struct
data_membuf
:
public
std
::
streambuf
{
{
data_membuf
(
char
*
text
,
size_t
length
)
data_membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
std
::
istream
is_data
(
&
data_buffer
);
std
::
istream
is_data
(
&
data_buffer
);
f
.
load
(
is_data
);
f
.
load
(
is_data
);
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
3
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
1
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
1
);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
BOOST_CHECK
(
cat2
.
size
()
==
1
);
BOOST_CHECK
(
cat2
.
size
()
==
1
);
// BOOST_CHECK_THROW(cat2.emplace({
// BOOST_CHECK_THROW(cat2.emplace({
// { "id", 4 },
// { "id", 4 },
// { "parent_id", 4 },
// { "parent_id", 4 },
// { "desc", "moet fout gaan" }
// { "desc", "moet fout gaan" }
// }), std::exception);
// }), std::exception);
BOOST_CHECK_THROW
(
cat2
.
emplace
({
BOOST_CHECK_THROW
(
cat2
.
emplace
({{
"id"
,
"vijf"
},
// <- invalid value
{
"id"
,
"vijf"
},
// <- invalid value
{
"parent_id"
,
2
},
{
"parent_id"
,
2
},
{
"desc"
,
"moet fout gaan"
}}),
{
"desc"
,
"moet fout gaan"
}
std
::
exception
);
}),
std
::
exception
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
d2
)
BOOST_AUTO_TEST_CASE
(
d2
)
{
{
const
char
dict
[]
=
R"(
const
char
dict
[]
=
R"(
data_test_dict.dic
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.id test_dict.dic
_datablock.description
_datablock.description
...
@@ -383,24 +381,24 @@ save__cat_1.c
...
@@ -383,24 +381,24 @@ save__cat_1.c
save_
save_
)"
;
)"
;
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
setValidator
(
&
validator
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
data
[]
=
R"(
const
char
data
[]
=
R"(
data_test
data_test
loop_
loop_
_cat_1.id
_cat_1.id
...
@@ -408,39 +406,37 @@ _cat_1.c
...
@@ -408,39 +406,37 @@ _cat_1.c
aap Aap
aap Aap
noot Noot
noot Noot
mies Mies
mies 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
);
std
::
istream
is_data
(
&
data_buffer
);
f
.
load
(
is_data
);
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
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
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
std
::
istream
is_data
(
&
data_buffer
);
f
.
load
(
is_data
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
"AAP"
)
;
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
]
;
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
"noot
"
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
"AAP
"
);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
"noot"
);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
d3
)
BOOST_AUTO_TEST_CASE
(
d3
)
{
{
const
char
dict
[]
=
R"(
const
char
dict
[]
=
R"(
data_test_dict.dic
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.id test_dict.dic
_datablock.description
_datablock.description
...
@@ -533,24 +529,24 @@ save__cat_2.desc
...
@@ -533,24 +529,24 @@ save__cat_2.desc
save_
save_
)"
;
)"
;
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
setValidator
(
&
validator
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
data
[]
=
R"(
const
char
data
[]
=
R"(
data_test
data_test
loop_
loop_
_cat_1.id
_cat_1.id
...
@@ -569,84 +565,79 @@ _cat_2.desc
...
@@ -569,84 +565,79 @@ _cat_2.desc
2 1 . 'Een andere aap'
2 1 . 'Een andere aap'
3 2 noot 'walnoot bijvoorbeeld'
3 2 noot 'walnoot bijvoorbeeld'
4 2 n2 hazelnoot
4 2 n2 hazelnoot
)"
;
)"
;
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
);
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
// check a rename in parent and child
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
))
struct
data_membuf
:
public
std
::
streambuf
{
{
r
[
"id"
]
=
10
;
data_membuf
(
char
*
text
,
size_t
length
)
break
;
{
}
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
std
::
istream
is_data
(
&
data_buffer
);
BOOST_CHECK
(
cat2
.
size
()
==
4
);
f
.
load
(
is_data
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
).
size
()
==
0
)
;
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
]
;
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
)
;
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
]
;
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
1
).
size
()
==
0
);
// check a rename in parent and child
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"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
::
Key
(
"id"
)
==
1
))
{
r
[
"id"
]
=
10
;
break
;
}
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
))
BOOST_CHECK
(
cat1
.
size
()
==
3
);
{
BOOST_CHECK
(
cat2
.
size
()
==
4
);
r
[
"id"
]
=
20
;
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
size
()
==
4
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
20
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
10
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
).
size
()
==
1
);
// check a rename in parent and child, this time only one child should be renamed
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
and
cif
::
Key
(
"name2"
)
==
"noot"
).
size
()
==
0
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
))
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
and
cif
::
Key
(
"name2"
)
==
"n2"
).
size
()
==
1
);
{
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
and
cif
::
Key
(
"name2"
)
==
"noot"
).
size
()
==
1
);
r
[
"id"
]
=
20
;
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
and
cif
::
Key
(
"name2"
)
==
"n2"
).
size
()
==
0
);
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
4
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
20
).
size
()
==
1
);
// // --------------------------------------------------------------------
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
).
size
()
==
1
);
// cat1.erase(cif::Key("id") == 10);
// BOOST_CHECK(cat1.size() == 2);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
and
cif
::
Key
(
"name2"
)
==
"noot"
).
size
()
==
0
);
// BOOST_CHECK(cat2.size() == 2);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
and
cif
::
Key
(
"name2"
)
==
"n2"
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
and
cif
::
Key
(
"name2"
)
==
"noot"
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
and
cif
::
Key
(
"name2"
)
==
"n2"
).
size
()
==
0
);
// cat1.erase(cif::Key("id") == 20);
// // --------------------------------------------------------------------
// BOOST_CHECK(cat1.size() == 1);
// cat1.erase(cif::Key("id") == 10);
// BOOST_CHECK(cat2.size() == 1);
// BOOST_CHECK(cat1.size() == 2);
// BOOST_CHECK(cat2.size() == 2);
// cat1.erase(cif::Key("id") == 20);
// BOOST_CHECK(cat1.size() == 1);
// BOOST_CHECK(cat2.size() == 1);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
d4
)
BOOST_AUTO_TEST_CASE
(
d4
)
{
{
const
char
dict
[]
=
R"(
const
char
dict
[]
=
R"(
data_test_dict.dic
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.id test_dict.dic
_datablock.description
_datablock.description
...
@@ -741,24 +732,24 @@ save__cat_2.parent_id3
...
@@ -741,24 +732,24 @@ save__cat_2.parent_id3
)"
;
)"
;
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
setValidator
(
&
validator
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
data
[]
=
R"(
const
char
data
[]
=
R"(
data_test
data_test
loop_
loop_
_cat_1.id
_cat_1.id
...
@@ -787,93 +778,90 @@ _cat_2.parent_id3
...
@@ -787,93 +778,90 @@ _cat_2.parent_id3
11 4 roos roos
11 4 roos roos
12 4 . roos
12 4 . roos
13 4 roos .
13 4 roos .
)"
;
)"
;
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
);
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
// check a rename in parent and child
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
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
))
std
::
istream
is_data
(
&
data_buffer
);
{
f
.
load
(
is_data
);
r
[
"id"
]
=
10
;
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
4
)
;
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
]
;
BOOST_CHECK
(
cat2
.
size
()
==
13
)
;
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
]
;
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
).
size
()
==
0
);
// check a rename in parent and child
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
1
).
size
()
==
1
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
))
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
10
).
size
()
==
2
);
{
r
[
"id"
]
=
10
;
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat2
.
size
()
==
13
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
))
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
).
size
()
==
0
);
{
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
r
[
"id"
]
=
20
;
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
1
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
size
()
==
13
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
10
).
size
()
==
2
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
).
size
()
==
0
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
))
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
20
).
size
()
==
1
);
{
r
[
"id"
]
=
20
;
break
;
}
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
).
size
()
==
2
);
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
size
()
==
13
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
20
).
size
()
==
1
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
))
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
).
size
()
==
2
);
{
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
).
size
()
==
2
);
r
[
"id"
]
=
30
;
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
4
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
))
BOOST_CHECK
(
cat2
.
size
()
==
13
);
{
r
[
"id"
]
=
30
;
break
;
}
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
size
()
==
13
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
3
).
size
()
==
2
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_
id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"
id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
3
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
30
).
size
()
==
1
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
4
))
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
4
))
{
{
r
[
"id"
]
=
40
;
r
[
"id"
]
=
40
;
break
;
break
;
}
}
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat2
.
size
()
==
13
);
BOOST_CHECK
(
cat2
.
size
()
==
13
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
4
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
4
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
4
).
size
()
==
3
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
4
).
size
()
==
3
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
40
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
40
).
size
()
==
0
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
d5
)
BOOST_AUTO_TEST_CASE
(
d5
)
{
{
const
char
dict
[]
=
R"(
const
char
dict
[]
=
R"(
data_test_dict.dic
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.id test_dict.dic
_datablock.description
_datablock.description
...
@@ -965,24 +953,24 @@ cat_2 2 cat_2:cat_1:2
...
@@ -965,24 +953,24 @@ cat_2 2 cat_2:cat_1:2
cat_2 3 cat_2:cat_1:3
cat_2 3 cat_2:cat_1:3
)"
;
)"
;
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
setValidator
(
&
validator
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
data
[]
=
R"(
const
char
data
[]
=
R"(
data_test
data_test
loop_
loop_
_cat_1.id
_cat_1.id
...
@@ -1004,119 +992,120 @@ _cat_2.parent_id3
...
@@ -1004,119 +992,120 @@ _cat_2.parent_id3
7 3 3 3
7 3 3 3
)"
;
)"
;
// --------------------------------------------------------------------
// --------------------------------------------------------------------
struct
data_membuf
:
public
std
::
streambuf
struct
data_membuf
:
public
std
::
streambuf
{
{
data_membuf
(
char
*
text
,
size_t
length
)
data_membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
std
::
istream
is_data
(
&
data_buffer
);
std
::
istream
is_data
(
&
data_buffer
);
f
.
load
(
is_data
);
f
.
load
(
is_data
);
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// check iterate children
// check iterate children
auto
PR2set
=
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
);
auto
PR2set
=
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
);
BOOST_ASSERT
(
PR2set
.
size
()
==
1
);
BOOST_ASSERT
(
PR2set
.
size
()
==
1
);
auto
PR2
=
PR2set
.
front
();
auto
PR2
=
PR2set
.
front
();
BOOST_CHECK
(
PR2
[
"id"
].
as
<
int
>
()
==
2
);
BOOST_CHECK
(
PR2
[
"id"
].
as
<
int
>
()
==
2
);
auto
CR2set
=
cat1
.
getChildren
(
PR2
,
"cat_2"
);
auto
CR2set
=
cat1
.
getChildren
(
PR2
,
"cat_2"
);
BOOST_ASSERT
(
CR2set
.
size
()
==
3
);
BOOST_ASSERT
(
CR2set
.
size
()
==
3
);
std
::
vector
<
int
>
CRids
;
std
::
vector
<
int
>
CRids
;
std
::
transform
(
CR2set
.
begin
(),
CR2set
.
end
(),
std
::
back_inserter
(
CRids
),
[](
cif
::
Row
r
)
{
return
r
[
"id"
].
as
<
int
>
();
});
std
::
transform
(
CR2set
.
begin
(),
CR2set
.
end
(),
std
::
back_inserter
(
CRids
),
[](
cif
::
Row
r
)
std
::
sort
(
CRids
.
begin
(),
CRids
.
end
());
{
return
r
[
"id"
].
as
<
int
>
();
});
BOOST_CHECK
(
CRids
==
std
::
vector
<
int
>
({
4
,
5
,
6
}));
std
::
sort
(
CRids
.
begin
(),
CRids
.
end
());
BOOST_CHECK
(
CRids
==
std
::
vector
<
int
>
({
4
,
5
,
6
}));
// check a rename in parent and child
// check a rename in parent and child
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
))
{
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
))
r
[
"id"
]
=
10
;
{
break
;
r
[
"id"
]
=
10
;
}
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
7
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
7
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
1
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
10
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
10
).
size
()
==
1
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
))
{
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
))
r
[
"id"
]
=
20
;
{
break
;
r
[
"id"
]
=
20
;
}
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
7
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
7
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
20
).
size
()
==
1
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
20
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
2
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
20
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
20
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
20
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
20
).
size
()
==
2
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
20
).
size
()
==
2
);
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
))
{
for
(
auto
r
:
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
))
r
[
"id"
]
=
30
;
{
break
;
r
[
"id"
]
=
30
;
}
break
;
}
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
7
);
BOOST_CHECK
(
cat1
.
size
()
==
3
);
BOOST_CHECK
(
cat2
.
size
()
==
7
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat1
.
find
(
cif
::
Key
(
"id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
3
).
size
()
==
0
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id2"
)
==
30
).
size
()
==
1
);
BOOST_CHECK
(
cat2
.
find
(
cif
::
Key
(
"parent_id3"
)
==
30
).
size
()
==
1
);
// test delete
// test delete
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
10
);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
10
);
BOOST_CHECK
(
cat2
.
size
()
==
4
);
BOOST_CHECK
(
cat1
.
size
()
==
2
);
BOOST_CHECK
(
cat2
.
size
()
==
4
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
20
);
BOOST_CHECK
(
cat1
.
size
()
==
1
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
20
);
BOOST_CHECK
(
cat2
.
size
()
==
1
);
BOOST_CHECK
(
cat1
.
size
()
==
1
);
BOOST_CHECK
(
cat2
.
size
()
==
1
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
30
);
BOOST_CHECK
(
cat1
.
size
()
==
0
);
cat1
.
erase
(
cif
::
Key
(
"id"
)
==
30
);
BOOST_CHECK
(
cat2
.
size
()
==
0
);
BOOST_CHECK
(
cat1
.
size
()
==
0
);
BOOST_CHECK
(
cat2
.
size
()
==
0
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE
(
c1
)
BOOST_AUTO_TEST_CASE
(
c1
)
{
{
cif
::
VERBOSE
=
1
;
cif
::
VERBOSE
=
1
;
auto
f
=
R"(data_TEST
auto
f
=
R"(data_TEST
#
#
loop_
loop_
_test.id
_test.id
...
@@ -1128,52 +1117,52 @@ _test.name
...
@@ -1128,52 +1117,52 @@ _test.name
5 ?
5 ?
)"
_cf
;
)"
_cf
;
auto
&
db
=
f
.
firstDatablock
();
auto
&
db
=
f
.
firstDatablock
();
for
(
auto
r
:
db
[
"test"
].
find
(
cif
::
Key
(
"id"
)
==
1
))
for
(
auto
r
:
db
[
"test"
].
find
(
cif
::
Key
(
"id"
)
==
1
))
{
{
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
string
>
({
"id"
,
"name"
});
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
string
>
({
"id"
,
"name"
});
BOOST_CHECK
(
id
==
1
);
BOOST_CHECK
(
id
==
1
);
BOOST_CHECK
(
name
==
"aap"
);
BOOST_CHECK
(
name
==
"aap"
);
}
}
for
(
auto
r
:
db
[
"test"
].
find
(
cif
::
Key
(
"id"
)
==
4
))
for
(
auto
r
:
db
[
"test"
].
find
(
cif
::
Key
(
"id"
)
==
4
))
{
{
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
string
>
({
"id"
,
"name"
});
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
string
>
({
"id"
,
"name"
});
BOOST_CHECK
(
id
==
4
);
BOOST_CHECK
(
id
==
4
);
BOOST_CHECK
(
name
.
empty
());
BOOST_CHECK
(
name
.
empty
());
}
}
for
(
auto
r
:
db
[
"test"
].
find
(
cif
::
Key
(
"id"
)
==
5
))
for
(
auto
r
:
db
[
"test"
].
find
(
cif
::
Key
(
"id"
)
==
5
))
{
{
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
string
>
({
"id"
,
"name"
});
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
string
>
({
"id"
,
"name"
});
BOOST_CHECK
(
id
==
5
);
BOOST_CHECK
(
id
==
5
);
BOOST_CHECK
(
name
.
empty
());
BOOST_CHECK
(
name
.
empty
());
}
}
// optional
// optional
for
(
auto
r
:
db
[
"test"
])
for
(
auto
r
:
db
[
"test"
])
{
{
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
optional
<
std
::
string
>>
({
"id"
,
"name"
});
const
auto
&
[
id
,
name
]
=
r
.
get
<
int
,
std
::
optional
<
std
::
string
>>
({
"id"
,
"name"
});
switch
(
id
)
switch
(
id
)
{
{
case
1
:
BOOST_CHECK
(
name
==
"aap"
);
break
;
case
1
:
BOOST_CHECK
(
name
==
"aap"
);
break
;
case
2
:
BOOST_CHECK
(
name
==
"noot"
);
break
;
case
2
:
BOOST_CHECK
(
name
==
"noot"
);
break
;
case
3
:
BOOST_CHECK
(
name
==
"mies"
);
break
;
case
3
:
BOOST_CHECK
(
name
==
"mies"
);
break
;
case
4
:
case
4
:
case
5
:
BOOST_CHECK
(
not
name
);
break
;
case
5
:
BOOST_CHECK
(
not
name
);
break
;
default
:
default
:
BOOST_CHECK
(
false
);
BOOST_CHECK
(
false
);
}
}
}
}
}
}
BOOST_AUTO_TEST_CASE
(
c2
)
BOOST_AUTO_TEST_CASE
(
c2
)
{
{
cif
::
VERBOSE
=
1
;
cif
::
VERBOSE
=
1
;
auto
f
=
R"(data_TEST
auto
f
=
R"(data_TEST
#
#
loop_
loop_
_test.id
_test.id
...
@@ -1185,31 +1174,30 @@ _test.name
...
@@ -1185,31 +1174,30 @@ _test.name
5 ?
5 ?
)"
_cf
;
)"
_cf
;
auto
&
db
=
f
.
firstDatablock
();
auto
&
db
=
f
.
firstDatablock
();
// query tests
for
(
const
auto
&
[
id
,
name
]
:
db
[
"test"
].
rows
<
int
,
std
::
optional
<
std
::
string
>>
(
"id"
,
"name"
))
{
switch
(
id
)
{
case
1
:
BOOST_CHECK
(
name
==
"aap"
);
break
;
case
2
:
BOOST_CHECK
(
name
==
"noot"
);
break
;
case
3
:
BOOST_CHECK
(
name
==
"mies"
);
break
;
case
4
:
case
5
:
BOOST_CHECK
(
not
name
);
break
;
default
:
BOOST_CHECK
(
false
);
}
}
}
// query tests
for
(
const
auto
&
[
id
,
name
]
:
db
[
"test"
].
rows
<
int
,
std
::
optional
<
std
::
string
>>
(
"id"
,
"name"
))
{
switch
(
id
)
{
case
1
:
BOOST_CHECK
(
name
==
"aap"
);
break
;
case
2
:
BOOST_CHECK
(
name
==
"noot"
);
break
;
case
3
:
BOOST_CHECK
(
name
==
"mies"
);
break
;
case
4
:
case
5
:
BOOST_CHECK
(
not
name
);
break
;
default
:
BOOST_CHECK
(
false
);
}
}
}
BOOST_AUTO_TEST_CASE
(
c3
)
BOOST_AUTO_TEST_CASE
(
c3
)
{
{
cif
::
VERBOSE
=
1
;
cif
::
VERBOSE
=
1
;
auto
f
=
R"(data_TEST
auto
f
=
R"(data_TEST
#
#
loop_
loop_
_test.id
_test.id
...
@@ -1221,27 +1209,27 @@ _test.name
...
@@ -1221,27 +1209,27 @@ _test.name
5 ?
5 ?
)"
_cf
;
)"
_cf
;
auto
&
db
=
f
.
firstDatablock
();
auto
&
db
=
f
.
firstDatablock
();
// query tests
// query tests
for
(
const
auto
&
[
id
,
name
]
:
db
[
"test"
].
find
<
int
,
std
::
optional
<
std
::
string
>>
(
cif
::
All
(),
"id"
,
"name"
))
for
(
const
auto
&
[
id
,
name
]
:
db
[
"test"
].
find
<
int
,
std
::
optional
<
std
::
string
>>
(
cif
::
All
(),
"id"
,
"name"
))
{
{
switch
(
id
)
switch
(
id
)
{
{
case
1
:
BOOST_CHECK
(
name
==
"aap"
);
break
;
case
1
:
BOOST_CHECK
(
name
==
"aap"
);
break
;
case
2
:
BOOST_CHECK
(
name
==
"noot"
);
break
;
case
2
:
BOOST_CHECK
(
name
==
"noot"
);
break
;
case
3
:
BOOST_CHECK
(
name
==
"mies"
);
break
;
case
3
:
BOOST_CHECK
(
name
==
"mies"
);
break
;
case
4
:
case
4
:
case
5
:
BOOST_CHECK
(
not
name
);
break
;
case
5
:
BOOST_CHECK
(
not
name
);
break
;
default
:
default
:
BOOST_CHECK
(
false
);
BOOST_CHECK
(
false
);
}
}
}
}
const
auto
&
[
id
,
name
]
=
db
[
"test"
].
find1
<
int
,
std
::
string
>
(
cif
::
Key
(
"id"
)
==
1
,
"id"
,
"name"
);
const
auto
&
[
id
,
name
]
=
db
[
"test"
].
find1
<
int
,
std
::
string
>
(
cif
::
Key
(
"id"
)
==
1
,
"id"
,
"name"
);
BOOST_CHECK
(
id
==
1
);
BOOST_CHECK
(
id
==
1
);
BOOST_CHECK
(
name
==
"aap"
);
BOOST_CHECK
(
name
==
"aap"
);
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -1250,22 +1238,22 @@ _test.name
...
@@ -1250,22 +1238,22 @@ _test.name
BOOST_AUTO_TEST_CASE
(
r1
)
BOOST_AUTO_TEST_CASE
(
r1
)
{
{
/*
/*
Rationale:
Rationale:
The pdbx_mmcif dictionary contains inconsistent child-parent relations. E.g. atom_site is parent
The pdbx_mmcif dictionary contains inconsistent child-parent relations. E.g. atom_site is parent
of pdbx_nonpoly_scheme which itself is a parent of pdbx_entity_nonpoly. If I want to rename a residue
of pdbx_nonpoly_scheme which itself is a parent of pdbx_entity_nonpoly. If I want to rename a residue
I cannot update pdbx_nonpoly_scheme since changing a parent changes children, but not vice versa.
I cannot update pdbx_nonpoly_scheme since changing a parent changes children, but not vice versa.
But if I change the comp_id in atom_site, the pdbx_nonpoly_scheme is update, that's good, and then
But if I change the comp_id in atom_site, the pdbx_nonpoly_scheme is update, that's good, and then
pdbx_entity_nonpoly is updated and that's bad.
pdbx_entity_nonpoly is updated and that's bad.
The idea is now that if we update a parent and a child that must change as well, we first check
The idea is now that if we update a parent and a child that must change as well, we first check
if there are more parents of this child that will not change. In that case we have to split the
if there are more parents of this child that will not change. In that case we have to split the
child into two, one with the new value and one with the old. We then of course have to split all
child into two, one with the new value and one with the old. We then of course have to split all
children of this split row that are direct children.
children of this split row that are direct children.
*/
*/
const
char
dict
[]
=
R"(
const
char
dict
[]
=
R"(
data_test_dict.dic
data_test_dict.dic
_datablock.id test_dict.dic
_datablock.id test_dict.dic
_datablock.description
_datablock.description
...
@@ -1394,23 +1382,23 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
...
@@ -1394,23 +1382,23 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
)"
;
)"
;
struct
membuf
:
public
std
::
streambuf
struct
membuf
:
public
std
::
streambuf
{
{
membuf
(
char
*
text
,
size_t
length
)
membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
}
buffer
(
const_cast
<
char
*>
(
dict
),
sizeof
(
dict
)
-
1
);
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
setValidator
(
&
validator
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
data
[]
=
R"(
const
char
data
[]
=
R"(
data_test
data_test
loop_
loop_
_cat_1.id
_cat_1.id
...
@@ -1435,29 +1423,29 @@ _cat_3.name
...
@@ -1435,29 +1423,29 @@ _cat_3.name
_cat_3.num
_cat_3.num
1 aap 1
1 aap 1
2 aap 2
2 aap 2
)"
;
)"
;
using
namespace
cif
::
literals
;
using
namespace
cif
::
literals
;
struct
data_membuf
:
public
std
::
streambuf
struct
data_membuf
:
public
std
::
streambuf
{
{
data_membuf
(
char
*
text
,
size_t
length
)
data_membuf
(
char
*
text
,
size_t
length
)
{
{
this
->
setg
(
text
,
text
,
text
+
length
);
this
->
setg
(
text
,
text
,
text
+
length
);
}
}
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
}
data_buffer
(
const_cast
<
char
*>
(
data
),
sizeof
(
data
)
-
1
);
std
::
istream
is_data
(
&
data_buffer
);
std
::
istream
is_data
(
&
data_buffer
);
f
.
load
(
is_data
);
f
.
load
(
is_data
);
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat1
=
f
.
firstDatablock
()[
"cat_1"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
auto
&
cat2
=
f
.
firstDatablock
()[
"cat_2"
];
auto
&
cat3
=
f
.
firstDatablock
()[
"cat_3"
];
auto
&
cat3
=
f
.
firstDatablock
()[
"cat_3"
];
cat3
.
update_value
(
"name"
_key
==
"aap"
and
"num"
_key
==
1
,
"name"
,
"aapje"
);
cat3
.
update_value
(
"name"
_key
==
"aap"
and
"num"
_key
==
1
,
"name"
,
"aapje"
);
BOOST_CHECK
(
cat3
.
size
()
==
2
);
BOOST_CHECK
(
cat3
.
size
()
==
2
);
{
{
int
id
,
num
;
int
id
,
num
;
std
::
string
name
;
std
::
string
name
;
...
@@ -1471,9 +1459,9 @@ _cat_3.num
...
@@ -1471,9 +1459,9 @@ _cat_3.num
BOOST_CHECK
(
num
==
2
);
BOOST_CHECK
(
num
==
2
);
BOOST_CHECK
(
name
==
"aap"
);
BOOST_CHECK
(
name
==
"aap"
);
}
}
int
i
=
0
;
int
i
=
0
;
for
(
const
auto
&
[
id
,
name
,
num
,
desc
]
:
cat2
.
rows
<
int
,
std
::
string
,
int
,
std
::
string
>
(
"id"
,
"name"
,
"num"
,
"desc"
))
for
(
const
auto
&
[
id
,
name
,
num
,
desc
]
:
cat2
.
rows
<
int
,
std
::
string
,
int
,
std
::
string
>
(
"id"
,
"name"
,
"num"
,
"desc"
))
{
{
switch
(
++
i
)
switch
(
++
i
)
{
{
...
@@ -1497,7 +1485,7 @@ _cat_3.num
...
@@ -1497,7 +1485,7 @@ _cat_3.num
BOOST_CHECK
(
name
==
"noot"
);
BOOST_CHECK
(
name
==
"noot"
);
BOOST_CHECK
(
desc
==
"walnoot bijvoorbeeld"
);
BOOST_CHECK
(
desc
==
"walnoot bijvoorbeeld"
);
break
;
break
;
default
:
default
:
BOOST_FAIL
(
"Unexpected record"
);
BOOST_FAIL
(
"Unexpected record"
);
}
}
...
@@ -1505,7 +1493,7 @@ _cat_3.num
...
@@ -1505,7 +1493,7 @@ _cat_3.num
BOOST_CHECK
(
cat1
.
size
()
==
4
);
BOOST_CHECK
(
cat1
.
size
()
==
4
);
i
=
0
;
i
=
0
;
for
(
const
auto
&
[
id
,
name
,
desc
]
:
cat1
.
rows
<
int
,
std
::
string
,
std
::
string
>
(
"id"
,
"name"
,
"desc"
))
for
(
const
auto
&
[
id
,
name
,
desc
]
:
cat1
.
rows
<
int
,
std
::
string
,
std
::
string
>
(
"id"
,
"name"
,
"desc"
))
{
{
switch
(
++
i
)
switch
(
++
i
)
{
{
...
@@ -1526,13 +1514,13 @@ _cat_3.num
...
@@ -1526,13 +1514,13 @@ _cat_3.num
BOOST_CHECK
(
name
==
"mies"
);
BOOST_CHECK
(
name
==
"mies"
);
BOOST_CHECK
(
desc
==
"Mies"
);
BOOST_CHECK
(
desc
==
"Mies"
);
break
;
break
;
case
4
:
case
4
:
BOOST_CHECK
(
id
==
4
);
BOOST_CHECK
(
id
==
4
);
BOOST_CHECK
(
name
==
"aap"
);
BOOST_CHECK
(
name
==
"aap"
);
BOOST_CHECK
(
desc
==
"Aap"
);
BOOST_CHECK
(
desc
==
"Aap"
);
break
;
break
;
default
:
default
:
BOOST_FAIL
(
"Unexpected record"
);
BOOST_FAIL
(
"Unexpected record"
);
}
}
...
@@ -1545,7 +1533,7 @@ _cat_3.num
...
@@ -1545,7 +1533,7 @@ _cat_3.num
BOOST_AUTO_TEST_CASE
(
bondmap_1
)
BOOST_AUTO_TEST_CASE
(
bondmap_1
)
{
{
cif
::
VERBOSE
=
2
;
cif
::
VERBOSE
=
2
;
// sections taken from CCD compounds.cif
// sections taken from CCD compounds.cif
auto
components
=
R"(
auto
components
=
R"(
...
@@ -1634,7 +1622,7 @@ PRO CD HD3 SING N N 16
...
@@ -1634,7 +1622,7 @@ PRO CD HD3 SING N N 16
PRO OXT HXT SING N N 17
PRO OXT HXT SING N N 17
)"
_cf
;
)"
_cf
;
const
std
::
filesystem
::
path
example
(
gTestDir
/
".."
/
"examples"
/
"1cbs.cif.gz"
);
const
std
::
filesystem
::
path
example
(
gTestDir
/
".."
/
"examples"
/
"1cbs.cif.gz"
);
mmcif
::
File
file
(
example
.
string
());
mmcif
::
File
file
(
example
.
string
());
mmcif
::
Structure
structure
(
file
);
mmcif
::
Structure
structure
(
file
);
...
@@ -1642,11 +1630,11 @@ PRO OXT HXT SING N N 17
...
@@ -1642,11 +1630,11 @@ PRO OXT HXT SING N N 17
mmcif
::
BondMap
bm
(
structure
);
mmcif
::
BondMap
bm
(
structure
);
// Test the bonds of the first three residues, that's PRO A 1, ASN A 2, PHE A 3
// Test the bonds of the first three residues, that's PRO A 1, ASN A 2, PHE A 3
for
(
const
auto
&
[
compound
,
seqnr
]
:
std
::
initializer_list
<
std
::
tuple
<
std
::
string
,
int
>>
{
{
"PRO"
,
1
},
{
"ASN"
,
2
},
{
"PHE"
,
3
}
})
for
(
const
auto
&
[
compound
,
seqnr
]
:
std
::
initializer_list
<
std
::
tuple
<
std
::
string
,
int
>>
{{
"PRO"
,
1
},
{
"ASN"
,
2
},
{
"PHE"
,
3
}
})
{
{
auto
&
res
=
structure
.
getResidue
(
"A"
,
compound
,
seqnr
);
auto
&
res
=
structure
.
getResidue
(
"A"
,
compound
,
seqnr
);
auto
atoms
=
res
.
atoms
();
auto
atoms
=
res
.
atoms
();
auto
dc
=
components
.
get
(
compound
);
auto
dc
=
components
.
get
(
compound
);
...
@@ -1655,14 +1643,14 @@ PRO OXT HXT SING N N 17
...
@@ -1655,14 +1643,14 @@ PRO OXT HXT SING N N 17
auto
cc
=
dc
->
get
(
"chem_comp_bond"
);
auto
cc
=
dc
->
get
(
"chem_comp_bond"
);
BOOST_ASSERT
(
cc
!=
nullptr
);
BOOST_ASSERT
(
cc
!=
nullptr
);
std
::
set
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
bonded
;
std
::
set
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
bonded
;
for
(
const
auto
&
[
atom_id_1
,
atom_id_2
]
:
cc
->
rows
<
std
::
string
,
std
::
string
>
(
"atom_id_1"
,
"atom_id_2"
))
for
(
const
auto
&
[
atom_id_1
,
atom_id_2
]
:
cc
->
rows
<
std
::
string
,
std
::
string
>
(
"atom_id_1"
,
"atom_id_2"
))
{
{
if
(
atom_id_1
>
atom_id_2
)
if
(
atom_id_1
>
atom_id_2
)
bonded
.
insert
({
atom_id_2
,
atom_id_1
});
bonded
.
insert
({
atom_id_2
,
atom_id_1
});
else
else
bonded
.
insert
({
atom_id_1
,
atom_id_2
});
bonded
.
insert
({
atom_id_1
,
atom_id_2
});
}
}
for
(
size_t
i
=
0
;
i
+
1
<
atoms
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
+
1
<
atoms
.
size
();
++
i
)
...
@@ -1677,8 +1665,8 @@ PRO OXT HXT SING N N 17
...
@@ -1677,8 +1665,8 @@ PRO OXT HXT SING N N 17
bool
bonded_1_i
=
bm
(
atoms
[
j
],
atoms
[
i
]);
bool
bonded_1_i
=
bm
(
atoms
[
j
],
atoms
[
i
]);
bool
bonded_t
=
label_i
>
label_j
bool
bonded_t
=
label_i
>
label_j
?
bonded
.
count
({
label_j
,
label_i
})
?
bonded
.
count
({
label_j
,
label_i
})
:
bonded
.
count
({
label_i
,
label_j
});
:
bonded
.
count
({
label_i
,
label_j
});
BOOST_CHECK
(
bonded_1
==
bonded_t
);
BOOST_CHECK
(
bonded_1
==
bonded_t
);
BOOST_CHECK
(
bonded_1_i
==
bonded_t
);
BOOST_CHECK
(
bonded_1_i
==
bonded_t
);
...
@@ -1718,20 +1706,19 @@ BOOST_AUTO_TEST_CASE(t1)
...
@@ -1718,20 +1706,19 @@ BOOST_AUTO_TEST_CASE(t1)
// q = Normalize(q);
// q = Normalize(q);
// Quaternion q{ 0.1, 0.2, 0.3, 0.4 };
// Quaternion q{ 0.1, 0.2, 0.3, 0.4 };
Quaternion
q
{
0.5
,
0.5
,
0.5
,
0.5
};
Quaternion
q
{
0.5
,
0.5
,
0.5
,
0.5
};
q
=
Normalize
(
q
);
q
=
Normalize
(
q
);
const
auto
&&
[
angle0
,
axis0
]
=
QuaternionToAngleAxis
(
q
);
const
auto
&&
[
angle0
,
axis0
]
=
QuaternionToAngleAxis
(
q
);
std
::
vector
<
Point
>
p1
{
std
::
vector
<
Point
>
p1
{
{
16.979
,
13.301
,
44.555
},
{
16.979
,
13.301
,
44.555
},
{
18.150
,
13.525
,
43.680
},
{
18.150
,
13.525
,
43.680
},
{
18.656
,
14.966
,
43.784
},
{
18.656
,
14.966
,
43.784
},
{
17.890
,
15.889
,
44.078
},
{
17.890
,
15.889
,
44.078
},
{
17.678
,
13.270
,
42.255
},
{
17.678
,
13.270
,
42.255
},
{
16.248
,
13.734
,
42.347
},
{
16.248
,
13.734
,
42.347
},
{
15.762
,
13.216
,
43.724
}
{
15.762
,
13.216
,
43.724
}};
};
auto
p2
=
p1
;
auto
p2
=
p1
;
...
@@ -1739,7 +1726,7 @@ BOOST_AUTO_TEST_CASE(t1)
...
@@ -1739,7 +1726,7 @@ BOOST_AUTO_TEST_CASE(t1)
for
(
auto
&
p
:
p2
)
for
(
auto
&
p
:
p2
)
p
.
rotate
(
q
);
p
.
rotate
(
q
);
CenterPoints
(
p2
);
CenterPoints
(
p2
);
auto
q2
=
AlignPoints
(
p1
,
p2
);
auto
q2
=
AlignPoints
(
p1
,
p2
);
...
@@ -1757,3 +1744,38 @@ BOOST_AUTO_TEST_CASE(t1)
...
@@ -1757,3 +1744,38 @@ BOOST_AUTO_TEST_CASE(t1)
// std::cout << "rmsd: " << RMSd(p1, p2) << std::endl;
// std::cout << "rmsd: " << RMSd(p1, p2) << std::endl;
}
}
BOOST_AUTO_TEST_CASE
(
parser_test_1
)
{
auto
data1
=
R"(
data_QM
_test.text ??
)"
_cf
;
auto
&
db1
=
data1
.
firstDatablock
();
auto
&
test1
=
db1
[
"test"
];
BOOST_CHECK_EQUAL
(
test1
.
size
(),
1
);
for
(
auto
r
:
test1
)
{
const
auto
&
[
text
]
=
r
.
get
<
std
::
string
>
({
"text"
});
BOOST_CHECK_EQUAL
(
text
,
"??"
);
}
std
::
stringstream
ss
;
data1
.
save
(
ss
);
auto
data2
=
cif
::
File
(
ss
);
auto
&
db2
=
data2
.
firstDatablock
();
auto
&
test2
=
db2
[
"test"
];
BOOST_CHECK_EQUAL
(
test2
.
size
(),
1
);
for
(
auto
r
:
test2
)
{
const
auto
&
[
text
]
=
r
.
get
<
std
::
string
>
({
"text"
});
BOOST_CHECK_EQUAL
(
text
,
"??"
);
}
}
\ No newline at end of file
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