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
1f6b86d5
Unverified
Commit
1f6b86d5
authored
Nov 11, 2021
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop
parents
31499b97
7f39d401
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
527 additions
and
394 deletions
+527
-394
include/cif++/Cif++.hpp
+26
-17
include/cif++/CifParser.hpp
+27
-29
include/cif++/CifUtils.hpp
+0
-2
include/cif++/CifValidator.hpp
+30
-3
include/cif++/Structure.hpp
+4
-4
include/cif++/Symmetry.hpp
+7
-1
src/Cif++.cpp
+103
-158
src/CifParser.cpp
+118
-102
src/CifUtils.cpp
+3
-29
src/CifValidator.cpp
+86
-2
src/Point.cpp
+3
-3
src/Structure.cpp
+40
-31
src/Symmetry.cpp
+62
-0
test/pdb2cif-test.cpp
+0
-7
test/unit-test.cpp
+18
-6
No files found.
include/cif++/Cif++.hpp
View file @
1f6b86d5
...
@@ -36,6 +36,7 @@
...
@@ -36,6 +36,7 @@
#include <regex>
#include <regex>
#include <set>
#include <set>
#include <sstream>
#include <sstream>
#include <shared_mutex>
#include "cif++/CifUtils.hpp"
#include "cif++/CifUtils.hpp"
...
@@ -142,13 +143,13 @@ class Item
...
@@ -142,13 +143,13 @@ class Item
Item
()
{}
Item
()
{}
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
Item
(
const
std
::
string
&
name
,
const
T
&
value
)
Item
(
const
std
::
string
_view
name
,
const
T
&
value
)
:
mName
(
name
)
:
mName
(
name
)
,
mValue
(
std
::
to_string
(
value
))
,
mValue
(
std
::
to_string
(
value
))
{
{
}
}
Item
(
const
std
::
string
&
name
,
const
std
::
string
&
value
)
Item
(
const
std
::
string
_view
name
,
const
std
::
string_view
value
)
:
mName
(
name
)
:
mName
(
name
)
,
mValue
(
value
)
,
mValue
(
value
)
{
{
...
@@ -221,7 +222,7 @@ class Datablock
...
@@ -221,7 +222,7 @@ class Datablock
using
iterator
=
CategoryList
::
iterator
;
using
iterator
=
CategoryList
::
iterator
;
using
const_iterator
=
CategoryList
::
const_iterator
;
using
const_iterator
=
CategoryList
::
const_iterator
;
Datablock
(
const
std
::
string
&
name
);
Datablock
(
const
std
::
string
_view
name
);
~
Datablock
();
~
Datablock
();
Datablock
(
const
Datablock
&
)
=
delete
;
Datablock
(
const
Datablock
&
)
=
delete
;
...
@@ -230,8 +231,6 @@ class Datablock
...
@@ -230,8 +231,6 @@ class Datablock
std
::
string
getName
()
const
{
return
mName
;
}
std
::
string
getName
()
const
{
return
mName
;
}
void
setName
(
const
std
::
string
&
n
)
{
mName
=
n
;
}
void
setName
(
const
std
::
string
&
n
)
{
mName
=
n
;
}
std
::
string
firstItem
(
const
std
::
string
&
tag
)
const
;
iterator
begin
()
{
return
mCategories
.
begin
();
}
iterator
begin
()
{
return
mCategories
.
begin
();
}
iterator
end
()
{
return
mCategories
.
end
();
}
iterator
end
()
{
return
mCategories
.
end
();
}
...
@@ -245,7 +244,7 @@ class Datablock
...
@@ -245,7 +244,7 @@ class Datablock
bool
isValid
();
bool
isValid
();
void
validateLinks
()
const
;
void
validateLinks
()
const
;
void
setValidator
(
Validator
*
v
);
void
setValidator
(
const
Validator
*
v
);
// this one only looks up a Category, returns nullptr if it does not exist
// this one only looks up a Category, returns nullptr if it does not exist
const
Category
*
get
(
std
::
string_view
name
)
const
;
const
Category
*
get
(
std
::
string_view
name
)
const
;
...
@@ -256,7 +255,7 @@ class Datablock
...
@@ -256,7 +255,7 @@ class Datablock
void
write
(
std
::
ostream
&
os
);
void
write
(
std
::
ostream
&
os
);
// convenience function, add a line to the software category
// convenience function, add a line to the software category
void
add_software
(
const
std
::
string
&
name
,
const
std
::
string
&
classification
,
void
add_software
(
const
std
::
string
_view
name
,
const
std
::
string
&
classification
,
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
);
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
);
friend
bool
operator
==
(
const
Datablock
&
lhs
,
const
Datablock
&
rhs
);
friend
bool
operator
==
(
const
Datablock
&
lhs
,
const
Datablock
&
rhs
);
...
@@ -264,9 +263,10 @@ class Datablock
...
@@ -264,9 +263,10 @@ class Datablock
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Datablock
&
data
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Datablock
&
data
);
private
:
private
:
std
::
list
<
Category
>
mCategories
;
CategoryList
mCategories
;
// LRU
mutable
std
::
shared_mutex
mLock
;
std
::
string
mName
;
std
::
string
mName
;
Validator
*
mValidator
;
const
Validator
*
mValidator
;
Datablock
*
mNext
;
Datablock
*
mNext
;
};
};
...
@@ -1816,12 +1816,12 @@ class Category
...
@@ -1816,12 +1816,12 @@ class Category
friend
class
Row
;
friend
class
Row
;
friend
class
detail
::
ItemReference
;
friend
class
detail
::
ItemReference
;
Category
(
Datablock
&
db
,
const
std
::
string
&
name
,
Validator
*
Validator
);
Category
(
Datablock
&
db
,
const
std
::
string
_view
name
,
const
Validator
*
Validator
);
Category
(
const
Category
&
)
=
delete
;
Category
(
const
Category
&
)
=
delete
;
Category
&
operator
=
(
const
Category
&
)
=
delete
;
Category
&
operator
=
(
const
Category
&
)
=
delete
;
~
Category
();
~
Category
();
const
std
::
string
name
()
const
{
return
mName
;
}
const
std
::
string
&
name
()
const
{
return
mName
;
}
using
iterator
=
iterator_impl
<
Row
>
;
using
iterator
=
iterator_impl
<
Row
>
;
using
const_iterator
=
iterator_impl
<
const
Row
>
;
using
const_iterator
=
iterator_impl
<
const
Row
>
;
...
@@ -2064,7 +2064,7 @@ class Category
...
@@ -2064,7 +2064,7 @@ class Category
Datablock
&
db
()
{
return
mDb
;
}
Datablock
&
db
()
{
return
mDb
;
}
void
setValidator
(
Validator
*
v
);
void
setValidator
(
const
Validator
*
v
);
iset
fields
()
const
;
iset
fields
()
const
;
iset
mandatoryFields
()
const
;
iset
mandatoryFields
()
const
;
...
@@ -2121,14 +2121,24 @@ class Category
...
@@ -2121,14 +2121,24 @@ class Category
size_t
addColumn
(
std
::
string_view
name
);
size_t
addColumn
(
std
::
string_view
name
);
struct
Linked
{
Category
*
linked
;
const
ValidateLink
*
v
;
};
void
updateLinks
();
Datablock
&
mDb
;
Datablock
&
mDb
;
std
::
string
mName
;
std
::
string
mName
;
Validator
*
mValidator
;
const
Validator
*
mValidator
;
const
ValidateCategory
*
mCatValidator
=
nullptr
;
const
ValidateCategory
*
mCatValidator
=
nullptr
;
std
::
vector
<
ItemColumn
>
mColumns
;
std
::
vector
<
ItemColumn
>
mColumns
;
ItemRow
*
mHead
;
ItemRow
*
mHead
;
ItemRow
*
mTail
;
ItemRow
*
mTail
;
class
CatIndex
*
mIndex
;
class
CatIndex
*
mIndex
;
std
::
vector
<
Linked
>
mParentLinks
,
mChildLinks
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -2162,7 +2172,8 @@ class File
...
@@ -2162,7 +2172,8 @@ class File
void
loadDictionary
();
// load the default dictionary, that is mmcifDdl in this case
void
loadDictionary
();
// load the default dictionary, that is mmcifDdl in this case
void
loadDictionary
(
const
char
*
dict
);
// load one of the compiled in dictionaries
void
loadDictionary
(
const
char
*
dict
);
// load one of the compiled in dictionaries
void
loadDictionary
(
std
::
istream
&
is
);
// load dictionary from input stream
void
setValidator
(
const
Validator
*
v
);
bool
isValid
();
bool
isValid
();
void
validateLinks
()
const
;
void
validateLinks
()
const
;
...
@@ -2226,10 +2237,8 @@ class File
...
@@ -2226,10 +2237,8 @@ class File
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
void
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
;
private
:
private
:
void
setValidator
(
Validator
*
v
);
Datablock
*
mHead
;
Datablock
*
mHead
;
Validator
*
mValidator
;
const
Validator
*
mValidator
;
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
...
include/cif++/CifParser.hpp
View file @
1f6b86d5
...
@@ -28,8 +28,8 @@
...
@@ -28,8 +28,8 @@
#include "cif++/Cif++.hpp"
#include "cif++/Cif++.hpp"
#include <stack>
#include <map>
#include <map>
#include <stack>
namespace
cif
namespace
cif
{
{
...
@@ -39,7 +39,7 @@ namespace cif
...
@@ -39,7 +39,7 @@ namespace cif
class
CifParserError
:
public
std
::
runtime_error
class
CifParserError
:
public
std
::
runtime_error
{
{
public
:
public
:
CifParserError
(
uint32_t
lineNr
,
const
std
::
string
&
message
);
CifParserError
(
uint32_t
lineNr
,
const
std
::
string
&
message
);
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -48,7 +48,8 @@ extern const uint32_t kMaxLineLength;
...
@@ -48,7 +48,8 @@ extern const uint32_t kMaxLineLength;
extern
const
uint8_t
kCharTraitsTable
[
128
];
extern
const
uint8_t
kCharTraitsTable
[
128
];
enum
CharTraitsMask
:
uint8_t
{
enum
CharTraitsMask
:
uint8_t
{
kOrdinaryMask
=
1
<<
0
,
kOrdinaryMask
=
1
<<
0
,
kNonBlankMask
=
1
<<
1
,
kNonBlankMask
=
1
<<
1
,
kTextLeadMask
=
1
<<
2
,
kTextLeadMask
=
1
<<
2
,
...
@@ -81,7 +82,7 @@ inline bool isAnyPrint(int ch)
...
@@ -81,7 +82,7 @@ inline bool isAnyPrint(int ch)
(
ch
>=
0x20
and
ch
<=
0x7f
and
(
kCharTraitsTable
[
ch
-
0x20
]
&
kAnyPrintMask
)
!=
0
);
(
ch
>=
0x20
and
ch
<=
0x7f
and
(
kCharTraitsTable
[
ch
-
0x20
]
&
kAnyPrintMask
)
!=
0
);
}
}
inline
bool
isUnquotedString
(
const
char
*
s
)
inline
bool
isUnquotedString
(
const
char
*
s
)
{
{
bool
result
=
isOrdinary
(
*
s
++
);
bool
result
=
isOrdinary
(
*
s
++
);
while
(
result
and
*
s
!=
0
)
while
(
result
and
*
s
!=
0
)
...
@@ -94,7 +95,7 @@ inline bool isUnquotedString(const char* s)
...
@@ -94,7 +95,7 @@ inline bool isUnquotedString(const char* s)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
using
DatablockIndex
=
std
::
map
<
std
::
string
,
std
::
size_t
>
;
using
DatablockIndex
=
std
::
map
<
std
::
string
,
std
::
size_t
>
;
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// sac Parser, analogous to SAX Parser (simple api for xml)
// sac Parser, analogous to SAX Parser (simple api for xml)
...
@@ -102,7 +103,7 @@ using DatablockIndex = std::map<std::string,std::size_t>;
...
@@ -102,7 +103,7 @@ using DatablockIndex = std::map<std::string,std::size_t>;
class
SacParser
class
SacParser
{
{
public
:
public
:
SacParser
(
std
::
istream
&
is
,
bool
init
=
true
);
SacParser
(
std
::
istream
&
is
,
bool
init
=
true
);
virtual
~
SacParser
()
{}
virtual
~
SacParser
()
{}
enum
CIFToken
enum
CIFToken
...
@@ -120,7 +121,7 @@ class SacParser
...
@@ -120,7 +121,7 @@ class SacParser
eCIFTokenValue
,
eCIFTokenValue
,
};
};
static
const
char
*
kTokenName
[];
static
const
char
*
kTokenName
[];
enum
CIFValueType
enum
CIFValueType
{
{
...
@@ -133,7 +134,7 @@ class SacParser
...
@@ -133,7 +134,7 @@ class SacParser
eCIFValueUnknown
eCIFValueUnknown
};
};
static
const
char
*
kValueName
[];
static
const
char
*
kValueName
[];
int
getNextChar
();
int
getNextChar
();
...
@@ -143,10 +144,10 @@ class SacParser
...
@@ -143,10 +144,10 @@ class SacParser
CIFToken
getNextToken
();
CIFToken
getNextToken
();
void
match
(
CIFToken
token
);
void
match
(
CIFToken
token
);
bool
parseSingleDatablock
(
const
std
::
string
&
datablock
);
bool
parseSingleDatablock
(
const
std
::
string
&
datablock
);
DatablockIndex
indexDatablocks
();
DatablockIndex
indexDatablocks
();
bool
parseSingleDatablock
(
const
std
::
string
&
datablock
,
const
DatablockIndex
&
index
);
bool
parseSingleDatablock
(
const
std
::
string
&
datablock
,
const
DatablockIndex
&
index
);
void
parseFile
();
void
parseFile
();
void
parseGlobal
();
void
parseGlobal
();
...
@@ -156,17 +157,16 @@ class SacParser
...
@@ -156,17 +157,16 @@ class SacParser
void
parseDictionary
();
void
parseDictionary
();
void
error
(
const
std
::
string
&
msg
);
void
error
(
const
std
::
string
&
msg
);
// production methods, these are pure virtual here
// production methods, these are pure virtual here
virtual
void
produceDatablock
(
const
std
::
string
&
name
)
=
0
;
virtual
void
produceDatablock
(
const
std
::
string
&
name
)
=
0
;
virtual
void
produceCategory
(
const
std
::
string
&
name
)
=
0
;
virtual
void
produceCategory
(
const
std
::
string
&
name
)
=
0
;
virtual
void
produceRow
()
=
0
;
virtual
void
produceRow
()
=
0
;
virtual
void
produceItem
(
const
std
::
string
&
category
,
const
std
::
string
&
item
,
const
std
::
string
&
value
)
=
0
;
virtual
void
produceItem
(
const
std
::
string
&
category
,
const
std
::
string
&
item
,
const
std
::
string
&
value
)
=
0
;
protected
:
protected
:
enum
State
enum
State
{
{
eStateStart
,
eStateStart
,
...
@@ -181,11 +181,11 @@ class SacParser
...
@@ -181,11 +181,11 @@ class SacParser
eStateTextField
,
eStateTextField
,
eStateFloat
=
100
,
eStateFloat
=
100
,
eStateInt
=
110
,
eStateInt
=
110
,
// eStateNumericSuffix = 200,
// eStateNumericSuffix = 200,
eStateValue
=
300
eStateValue
=
300
};
};
std
::
istream
&
mData
;
std
::
istream
&
mData
;
// Parser state
// Parser state
bool
mValidate
;
bool
mValidate
;
...
@@ -203,16 +203,16 @@ class SacParser
...
@@ -203,16 +203,16 @@ class SacParser
class
Parser
:
public
SacParser
class
Parser
:
public
SacParser
{
{
public
:
public
:
Parser
(
std
::
istream
&
is
,
File
&
f
,
bool
init
=
true
);
Parser
(
std
::
istream
&
is
,
File
&
f
,
bool
init
=
true
);
virtual
void
produceDatablock
(
const
std
::
string
&
name
);
virtual
void
produceDatablock
(
const
std
::
string
&
name
);
virtual
void
produceCategory
(
const
std
::
string
&
name
);
virtual
void
produceCategory
(
const
std
::
string
&
name
);
virtual
void
produceRow
();
virtual
void
produceRow
();
virtual
void
produceItem
(
const
std
::
string
&
category
,
const
std
::
string
&
item
,
const
std
::
string
&
value
);
virtual
void
produceItem
(
const
std
::
string
&
category
,
const
std
::
string
&
item
,
const
std
::
string
&
value
);
protected
:
protected
:
File
&
mFile
;
File
&
mFile
;
Datablock
*
mDataBlock
;
Datablock
*
mDataBlock
;
Datablock
::
iterator
mCat
;
Datablock
::
iterator
mCat
;
Row
mRow
;
Row
mRow
;
};
};
...
@@ -222,23 +222,21 @@ class Parser : public SacParser
...
@@ -222,23 +222,21 @@ class Parser : public SacParser
class
DictParser
:
public
Parser
class
DictParser
:
public
Parser
{
{
public
:
public
:
DictParser
(
Validator
&
validator
,
std
::
istream
&
is
);
DictParser
(
Validator
&
validator
,
std
::
istream
&
is
);
~
DictParser
();
~
DictParser
();
void
loadDictionary
();
void
loadDictionary
();
private
:
private
:
virtual
void
parseSaveFrame
();
virtual
void
parseSaveFrame
();
bool
collectItemTypes
();
bool
collectItemTypes
();
void
linkItems
();
void
linkItems
();
Validator
&
mValidator
;
Validator
&
mValidator
;
File
mFile
;
File
mFile
;
struct
DictParserDataImpl
*
mImpl
;
struct
DictParserDataImpl
*
mImpl
;
bool
mCollectedItemTypes
=
false
;
bool
mCollectedItemTypes
=
false
;
};
};
}
}
// namespace cif
include/cif++/CifUtils.hpp
View file @
1f6b86d5
...
@@ -67,9 +67,7 @@ std::string get_version_nr();
...
@@ -67,9 +67,7 @@ std::string get_version_nr();
// some basic utilities: Since we're using ASCII input only, we define for optimisation
// some basic utilities: Since we're using ASCII input only, we define for optimisation
// our own case conversion routines.
// our own case conversion routines.
// bool iequals(const std::string &a, const std::string &b);
bool
iequals
(
std
::
string_view
a
,
std
::
string_view
b
);
bool
iequals
(
std
::
string_view
a
,
std
::
string_view
b
);
// int icompare(const std::string &a, const std::string &b);
int
icompare
(
std
::
string_view
a
,
std
::
string_view
b
);
int
icompare
(
std
::
string_view
a
,
std
::
string_view
b
);
bool
iequals
(
const
char
*
a
,
const
char
*
b
);
bool
iequals
(
const
char
*
a
,
const
char
*
b
);
...
...
include/cif++/CifValidator.hpp
View file @
1f6b86d5
...
@@ -38,6 +38,7 @@ namespace cif
...
@@ -38,6 +38,7 @@ namespace cif
{
{
struct
ValidateCategory
;
struct
ValidateCategory
;
class
ValidatorFactory
;
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -154,9 +155,8 @@ struct ValidateLink
...
@@ -154,9 +155,8 @@ struct ValidateLink
class
Validator
class
Validator
{
{
public
:
public
:
friend
class
DictParser
;
Validator
();
Validator
(
std
::
string_view
name
,
std
::
istream
&
is
);
~
Validator
();
~
Validator
();
Validator
(
const
Validator
&
rhs
)
=
delete
;
Validator
(
const
Validator
&
rhs
)
=
delete
;
...
@@ -165,6 +165,9 @@ class Validator
...
@@ -165,6 +165,9 @@ class Validator
Validator
(
Validator
&&
rhs
);
Validator
(
Validator
&&
rhs
);
Validator
&
operator
=
(
Validator
&&
rhs
);
Validator
&
operator
=
(
Validator
&&
rhs
);
friend
class
DictParser
;
friend
class
ValidatorFactory
;
void
addTypeValidator
(
ValidateType
&&
v
);
void
addTypeValidator
(
ValidateType
&&
v
);
const
ValidateType
*
getValidatorForType
(
std
::
string_view
typeCode
)
const
;
const
ValidateType
*
getValidatorForType
(
std
::
string_view
typeCode
)
const
;
...
@@ -175,7 +178,7 @@ class Validator
...
@@ -175,7 +178,7 @@ class Validator
std
::
vector
<
const
ValidateLink
*>
getLinksForParent
(
std
::
string_view
category
)
const
;
std
::
vector
<
const
ValidateLink
*>
getLinksForParent
(
std
::
string_view
category
)
const
;
std
::
vector
<
const
ValidateLink
*>
getLinksForChild
(
std
::
string_view
category
)
const
;
std
::
vector
<
const
ValidateLink
*>
getLinksForChild
(
std
::
string_view
category
)
const
;
void
reportError
(
const
std
::
string
&
msg
,
bool
fatal
);
void
reportError
(
const
std
::
string
&
msg
,
bool
fatal
)
const
;
std
::
string
dictName
()
const
{
return
mName
;
}
std
::
string
dictName
()
const
{
return
mName
;
}
void
dictName
(
const
std
::
string
&
name
)
{
mName
=
name
;
}
void
dictName
(
const
std
::
string
&
name
)
{
mName
=
name
;
}
...
@@ -184,6 +187,7 @@ class Validator
...
@@ -184,6 +187,7 @@ class Validator
void
dictVersion
(
const
std
::
string
&
version
)
{
mVersion
=
version
;
}
void
dictVersion
(
const
std
::
string
&
version
)
{
mVersion
=
version
;
}
private
:
private
:
// name is fully qualified here:
// name is fully qualified here:
ValidateItem
*
getValidatorForItem
(
std
::
string_view
name
)
const
;
ValidateItem
*
getValidatorForItem
(
std
::
string_view
name
)
const
;
...
@@ -196,4 +200,27 @@ class Validator
...
@@ -196,4 +200,27 @@ class Validator
std
::
vector
<
ValidateLink
>
mLinkValidators
;
std
::
vector
<
ValidateLink
>
mLinkValidators
;
};
};
// --------------------------------------------------------------------
class
ValidatorFactory
{
public
:
static
ValidatorFactory
&
instance
()
{
return
sInstance
;
}
const
Validator
&
operator
[](
std
::
string_view
dictionary
);
private
:
static
ValidatorFactory
sInstance
;
ValidatorFactory
();
std
::
mutex
mMutex
;
std
::
list
<
Validator
>
mValidators
;
};
}
// namespace cif
}
// namespace cif
include/cif++/Structure.hpp
View file @
1f6b86d5
...
@@ -109,12 +109,12 @@ class Atom
...
@@ -109,12 +109,12 @@ class Atom
float
occupancy
()
const
;
float
occupancy
()
const
;
template
<
typename
T
>
template
<
typename
T
>
T
property
(
const
std
::
string
&
name
)
const
;
T
property
(
const
std
::
string
_view
name
)
const
;
void
property
(
const
std
::
string
&
name
,
const
std
::
string
&
value
);
void
property
(
const
std
::
string
_view
name
,
const
std
::
string
&
value
);
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
template
<
typename
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
,
int
>
=
0
>
void
property
(
const
std
::
string
&
name
,
const
T
&
value
)
void
property
(
const
std
::
string
_view
name
,
const
T
&
value
)
{
{
property
(
name
,
std
::
to_string
(
value
));
property
(
name
,
std
::
to_string
(
value
));
}
}
...
@@ -404,7 +404,7 @@ class File : public std::enable_shared_from_this<File>
...
@@ -404,7 +404,7 @@ class File : public std::enable_shared_from_this<File>
File
(
const
File
&
)
=
delete
;
File
(
const
File
&
)
=
delete
;
File
&
operator
=
(
const
File
&
)
=
delete
;
File
&
operator
=
(
const
File
&
)
=
delete
;
cif
::
Datablock
&
createDatablock
(
const
std
::
string
&
name
);
cif
::
Datablock
&
createDatablock
(
const
std
::
string
_view
name
);
void
load
(
const
std
::
filesystem
::
path
&
path
);
void
load
(
const
std
::
filesystem
::
path
&
path
);
void
save
(
const
std
::
filesystem
::
path
&
path
);
void
save
(
const
std
::
filesystem
::
path
&
path
);
...
...
include/cif++/Symmetry.hpp
View file @
1f6b86d5
...
@@ -37,6 +37,11 @@ namespace mmcif
...
@@ -37,6 +37,11 @@ namespace mmcif
// --------------------------------------------------------------------
// --------------------------------------------------------------------
enum
class
SpacegroupName
{
full
,
xHM
,
Hall
};
struct
Spacegroup
struct
Spacegroup
{
{
const
char
*
name
;
const
char
*
name
;
...
@@ -133,6 +138,7 @@ CIFPP_EXPORT extern const std::size_t kSymopNrTableSize;
...
@@ -133,6 +138,7 @@ CIFPP_EXPORT extern const std::size_t kSymopNrTableSize;
// --------------------------------------------------------------------
// --------------------------------------------------------------------
int
GetSpacegroupNumber
(
std
::
string
spacegroup
);
// alternative for clipper's parsing code
int
GetSpacegroupNumber
(
std
::
string
spacegroup
);
// alternative for clipper's parsing code, using SpacegroupName::full
int
GetSpacegroupNumber
(
std
::
string
spacegroup
,
SpacegroupName
type
);
// alternative for clipper's parsing code
}
}
src/Cif++.cpp
View file @
1f6b86d5
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include <stack>
#include <stack>
#include <tuple>
#include <tuple>
#include <unordered_map>
#include <unordered_map>
#include <shared_mutex>
#include <filesystem>
#include <filesystem>
...
@@ -351,7 +352,7 @@ namespace detail
...
@@ -351,7 +352,7 @@ namespace detail
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Datablock implementation
// Datablock implementation
Datablock
::
Datablock
(
const
std
::
string
&
name
)
Datablock
::
Datablock
(
const
std
::
string
_view
name
)
:
mName
(
name
)
:
mName
(
name
)
,
mValidator
(
nullptr
)
,
mValidator
(
nullptr
)
,
mNext
(
nullptr
)
,
mNext
(
nullptr
)
...
@@ -363,43 +364,42 @@ Datablock::~Datablock()
...
@@ -363,43 +364,42 @@ Datablock::~Datablock()
delete
mNext
;
delete
mNext
;
}
}
std
::
string
Datablock
::
firstItem
(
const
std
::
string
&
tag
)
const
auto
Datablock
::
emplace
(
std
::
string_view
name
)
->
std
::
tuple
<
iterator
,
bool
>
{
{
std
::
string
result
;
// LRU code
std
::
string
catName
,
itemName
;
std
::
shared_lock
lock
(
mLock
);
std
::
tie
(
catName
,
itemName
)
=
splitTagName
(
tag
);
for
(
auto
&
cat
:
mCategories
)
bool
isNew
=
true
;
auto
i
=
begin
();
while
(
i
!=
end
())
{
{
if
(
iequals
(
cat
.
name
(),
catName
))
if
(
iequals
(
name
,
i
->
name
()
))
{
{
for
(
auto
row
:
cat
)
isNew
=
false
;
if
(
i
!=
begin
())
{
{
result
=
row
[
itemName
].
as
<
std
::
string
>
(
);
auto
n
=
std
::
next
(
i
);
break
;
mCategories
.
splice
(
begin
(),
mCategories
,
i
,
n
)
;
}
}
break
;
break
;
}
}
}
return
result
;
++
i
;
}
}
auto
Datablock
::
emplace
(
std
::
string_view
name
)
->
std
::
tuple
<
iterator
,
bool
>
{
bool
isNew
=
false
;
iterator
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
{
return
iequals
(
cat
.
name
(),
name
);
});
if
(
i
==
end
()
)
if
(
i
sNew
)
{
{
isNew
=
true
;
mCategories
.
emplace
(
begin
(),
*
this
,
std
::
string
(
name
),
mValidator
);
i
=
mCategories
.
emplace
(
end
(),
*
this
,
std
::
string
(
name
),
mValidator
);
for
(
auto
&
cat
:
mCategories
)
cat
.
updateLinks
();
}
}
return
std
::
make_tuple
(
i
,
isNew
);
return
std
::
make_tuple
(
begin
()
,
isNew
);
}
}
Category
&
Datablock
::
operator
[](
std
::
string_view
name
)
Category
&
Datablock
::
operator
[](
std
::
string_view
name
)
...
@@ -411,22 +411,34 @@ Category &Datablock::operator[](std::string_view name)
...
@@ -411,22 +411,34 @@ Category &Datablock::operator[](std::string_view name)
Category
*
Datablock
::
get
(
std
::
string_view
name
)
Category
*
Datablock
::
get
(
std
::
string_view
name
)
{
{
auto
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
std
::
shared_lock
lock
(
mLock
);
{
return
iequals
(
cat
.
name
(),
name
);
});
for
(
auto
&
cat
:
mCategories
)
{
if
(
iequals
(
cat
.
name
(),
name
))
return
&
cat
;
}
return
i
==
end
()
?
nullptr
:
&*
i
;
return
nullptr
;
}
}
const
Category
*
Datablock
::
get
(
std
::
string_view
name
)
const
const
Category
*
Datablock
::
get
(
std
::
string_view
name
)
const
{
{
auto
i
=
find_if
(
begin
(),
end
(),
[
name
](
const
Category
&
cat
)
->
bool
std
::
shared_lock
lock
(
mLock
);
{
return
iequals
(
cat
.
name
(),
name
);
});
return
i
==
end
()
?
nullptr
:
&*
i
;
for
(
auto
&
cat
:
mCategories
)
{
if
(
iequals
(
cat
.
name
(),
name
))
return
&
cat
;
}
return
nullptr
;
}
}
bool
Datablock
::
isValid
()
bool
Datablock
::
isValid
()
{
{
std
::
shared_lock
lock
(
mLock
);
if
(
mValidator
==
nullptr
)
if
(
mValidator
==
nullptr
)
throw
std
::
runtime_error
(
"Validator not specified"
);
throw
std
::
runtime_error
(
"Validator not specified"
);
...
@@ -438,20 +450,26 @@ bool Datablock::isValid()
...
@@ -438,20 +450,26 @@ bool Datablock::isValid()
void
Datablock
::
validateLinks
()
const
void
Datablock
::
validateLinks
()
const
{
{
std
::
shared_lock
lock
(
mLock
);
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
cat
.
validateLinks
();
cat
.
validateLinks
();
}
}
void
Datablock
::
setValidator
(
Validator
*
v
)
void
Datablock
::
setValidator
(
const
Validator
*
v
)
{
{
std
::
shared_lock
lock
(
mLock
);
mValidator
=
v
;
mValidator
=
v
;
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
cat
.
setValidator
(
v
);
cat
.
setValidator
(
v
);
}
}
void
Datablock
::
add_software
(
const
std
::
string
&
name
,
const
std
::
string
&
classification
,
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
)
void
Datablock
::
add_software
(
const
std
::
string
_view
name
,
const
std
::
string
&
classification
,
const
std
::
string
&
versionNr
,
const
std
::
string
&
versionDate
)
{
{
std
::
shared_lock
lock
(
mLock
);
Category
&
cat
=
operator
[](
"software"
);
Category
&
cat
=
operator
[](
"software"
);
auto
ordNr
=
cat
.
size
()
+
1
;
auto
ordNr
=
cat
.
size
()
+
1
;
// TODO: should we check this ordinal number???
// TODO: should we check this ordinal number???
...
@@ -465,12 +483,16 @@ void Datablock::add_software(const std::string &name, const std::string &classif
...
@@ -465,12 +483,16 @@ void Datablock::add_software(const std::string &name, const std::string &classif
void
Datablock
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
void
Datablock
::
getTagOrder
(
std
::
vector
<
std
::
string
>
&
tags
)
const
{
{
std
::
shared_lock
lock
(
mLock
);
for
(
auto
&
cat
:
*
this
)
for
(
auto
&
cat
:
*
this
)
cat
.
getTagOrder
(
tags
);
cat
.
getTagOrder
(
tags
);
}
}
void
Datablock
::
write
(
std
::
ostream
&
os
)
void
Datablock
::
write
(
std
::
ostream
&
os
)
{
{
std
::
shared_lock
lock
(
mLock
);
os
<<
"data_"
<<
mName
<<
std
::
endl
os
<<
"data_"
<<
mName
<<
std
::
endl
<<
"# "
<<
std
::
endl
;
<<
"# "
<<
std
::
endl
;
...
@@ -505,6 +527,8 @@ void Datablock::write(std::ostream &os)
...
@@ -505,6 +527,8 @@ void Datablock::write(std::ostream &os)
void
Datablock
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
)
void
Datablock
::
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
std
::
string
>
&
order
)
{
{
std
::
shared_lock
lock
(
mLock
);
os
<<
"data_"
<<
mName
<<
std
::
endl
os
<<
"data_"
<<
mName
<<
std
::
endl
<<
"# "
<<
std
::
endl
;
<<
"# "
<<
std
::
endl
;
...
@@ -580,6 +604,9 @@ void Datablock::write(std::ostream &os, const std::vector<std::string> &order)
...
@@ -580,6 +604,9 @@ void Datablock::write(std::ostream &os, const std::vector<std::string> &order)
bool
operator
==
(
const
cif
::
Datablock
&
dbA
,
const
cif
::
Datablock
&
dbB
)
bool
operator
==
(
const
cif
::
Datablock
&
dbA
,
const
cif
::
Datablock
&
dbB
)
{
{
std
::
shared_lock
lockA
(
dbA
.
mLock
);
std
::
shared_lock
lockB
(
dbB
.
mLock
);
std
::
vector
<
std
::
string
>
catA
,
catB
;
std
::
vector
<
std
::
string
>
catA
,
catB
;
for
(
auto
&
cat
:
dbA
)
for
(
auto
&
cat
:
dbA
)
...
@@ -1311,7 +1338,7 @@ RowSet &RowSet::orderBy(std::initializer_list<std::string> items)
...
@@ -1311,7 +1338,7 @@ RowSet &RowSet::orderBy(std::initializer_list<std::string> items)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
Category
::
Category
(
Datablock
&
db
,
const
std
::
string
&
name
,
Validator
*
Validator
)
Category
::
Category
(
Datablock
&
db
,
const
std
::
string
_view
name
,
const
Validator
*
Validator
)
:
mDb
(
db
)
:
mDb
(
db
)
,
mName
(
name
)
,
mName
(
name
)
,
mValidator
(
Validator
)
,
mValidator
(
Validator
)
...
@@ -1346,7 +1373,7 @@ Category::~Category()
...
@@ -1346,7 +1373,7 @@ Category::~Category()
delete
mIndex
;
delete
mIndex
;
}
}
void
Category
::
setValidator
(
Validator
*
v
)
void
Category
::
setValidator
(
const
Validator
*
v
)
{
{
mValidator
=
v
;
mValidator
=
v
;
...
@@ -1371,6 +1398,33 @@ void Category::setValidator(Validator *v)
...
@@ -1371,6 +1398,33 @@ void Category::setValidator(Validator *v)
}
}
else
else
mCatValidator
=
nullptr
;
mCatValidator
=
nullptr
;
updateLinks
();
}
void
Category
::
updateLinks
()
{
mChildLinks
.
clear
();
mParentLinks
.
clear
();
if
(
mValidator
!=
nullptr
)
{
for
(
auto
link
:
mValidator
->
getLinksForParent
(
mName
))
{
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
if
(
childCat
==
nullptr
)
continue
;
mChildLinks
.
push_back
({
childCat
,
link
});
}
for
(
auto
link
:
mValidator
->
getLinksForChild
(
mName
))
{
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
if
(
parentCat
==
nullptr
)
continue
;
mParentLinks
.
push_back
({
parentCat
,
link
});
}
}
}
}
bool
Category
::
hasColumn
(
std
::
string_view
name
)
const
bool
Category
::
hasColumn
(
std
::
string_view
name
)
const
...
@@ -1816,12 +1870,8 @@ auto Category::erase(iterator pos) -> iterator
...
@@ -1816,12 +1870,8 @@ auto Category::erase(iterator pos) -> iterator
if
(
mValidator
!=
nullptr
)
if
(
mValidator
!=
nullptr
)
{
{
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
)
)
for
(
auto
&
&
[
childCat
,
link
]
:
mChildLinks
)
{
{
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
if
(
childCat
==
nullptr
)
continue
;
Condition
cond
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
...
@@ -1959,12 +2009,8 @@ bool Category::isOrphan(Row r)
...
@@ -1959,12 +2009,8 @@ bool Category::isOrphan(Row r)
return
false
;
return
false
;
bool
isOrphan
=
true
;
bool
isOrphan
=
true
;
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
)
)
for
(
auto
&
&
[
parentCat
,
link
]
:
mParentLinks
)
{
{
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
if
(
parentCat
==
nullptr
)
continue
;
Condition
cond
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
{
{
...
@@ -1995,12 +2041,8 @@ bool Category::hasChildren(Row r) const
...
@@ -1995,12 +2041,8 @@ bool Category::hasChildren(Row r) const
bool
result
=
false
;
bool
result
=
false
;
for
(
auto
&
link
:
mValidator
->
getLinksForParent
(
mName
)
)
for
(
auto
&
&
[
childCat
,
link
]
:
mChildLinks
)
{
{
auto
childCat
=
mDb
.
get
(
link
->
mChildCategory
);
if
(
childCat
==
nullptr
)
continue
;
Condition
cond
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mParentKeys
.
size
();
++
ix
)
...
@@ -2026,12 +2068,8 @@ bool Category::hasParents(Row r) const
...
@@ -2026,12 +2068,8 @@ bool Category::hasParents(Row r) const
bool
result
=
false
;
bool
result
=
false
;
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
)
)
for
(
auto
&
&
[
parentCat
,
link
]
:
mParentLinks
)
{
{
auto
parentCat
=
mDb
.
get
(
link
->
mParentCategory
);
if
(
parentCat
==
nullptr
)
continue
;
Condition
cond
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
...
@@ -2240,23 +2278,17 @@ bool Category::isValid()
...
@@ -2240,23 +2278,17 @@ bool Category::isValid()
void
Category
::
validateLinks
()
const
void
Category
::
validateLinks
()
const
{
{
auto
&
validator
=
getValidator
();
for
(
auto
&&
[
parentCat
,
link
]
:
mParentLinks
)
for
(
auto
linkValidator
:
validator
.
getLinksForChild
(
mName
))
{
{
auto
parent
=
mDb
.
get
(
linkValidator
->
mParentCategory
);
if
(
parent
==
nullptr
)
continue
;
size_t
missing
=
0
;
size_t
missing
=
0
;
for
(
auto
r
:
*
this
)
for
(
auto
r
:
*
this
)
if
(
not
hasParent
(
r
,
*
parent
,
*
linkValidator
))
if
(
not
hasParent
(
r
,
*
parent
Cat
,
*
link
))
++
missing
;
++
missing
;
if
(
missing
)
if
(
missing
)
{
{
std
::
cerr
<<
"Links for "
<<
link
Validator
->
mLinkGroupLabel
<<
" are incomplete"
<<
std
::
endl
std
::
cerr
<<
"Links for "
<<
link
->
mLinkGroupLabel
<<
" are incomplete"
<<
std
::
endl
<<
" There are "
<<
missing
<<
" items in "
<<
mName
<<
" that don't have matching parent items in "
<<
parent
->
mName
<<
std
::
endl
;
<<
" There are "
<<
missing
<<
" items in "
<<
mName
<<
" that don't have matching parent items in "
<<
parent
Cat
->
mName
<<
std
::
endl
;
}
}
}
}
}
}
...
@@ -2697,17 +2729,10 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
...
@@ -2697,17 +2729,10 @@ void Category::update_value(RowSet &&rows, const std::string &tag, const std::st
row
.
assign
(
colIx
,
value
,
true
);
row
.
assign
(
colIx
,
value
,
true
);
// see if we need to update any child categories that depend on this value
// see if we need to update any child categories that depend on this value
auto
&
validator
=
getValidator
();
auto
&
db
=
mDb
;
for
(
auto
parent
:
rows
)
for
(
auto
parent
:
rows
)
{
{
for
(
auto
linked
:
validator
.
getLinksForParent
(
mName
)
)
for
(
auto
&&
[
childCat
,
linked
]
:
mChildLinks
)
{
{
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
if
(
childCat
==
nullptr
)
continue
;
if
(
std
::
find
(
linked
->
mParentKeys
.
begin
(),
linked
->
mParentKeys
.
end
(),
tag
)
==
linked
->
mParentKeys
.
end
())
if
(
std
::
find
(
linked
->
mParentKeys
.
begin
(),
linked
->
mParentKeys
.
end
(),
tag
)
==
linked
->
mParentKeys
.
end
())
continue
;
continue
;
...
@@ -2864,18 +2889,8 @@ void Row::assign(const std::vector<Item> &values)
...
@@ -2864,18 +2889,8 @@ void Row::assign(const std::vector<Item> &values)
// auto iv = col.mValidator;
// auto iv = col.mValidator;
if
(
mCascade
)
if
(
mCascade
)
{
{
auto
&
validator
=
cat
->
getValidator
();
for
(
auto
&&
[
childCat
,
linked
]
:
cat
->
mChildLinks
)
auto
&
db
=
cat
->
db
();
for
(
auto
linked
:
validator
.
getLinksForParent
(
cat
->
mName
))
{
{
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
if
(
childCat
==
nullptr
)
continue
;
// if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end())
// continue;
Condition
cond
;
Condition
cond
;
std
::
string
childTag
;
std
::
string
childTag
;
...
@@ -3016,15 +3031,8 @@ void Row::assign(size_t column, const std::string &value, bool skipUpdateLinked)
...
@@ -3016,15 +3031,8 @@ void Row::assign(size_t column, const std::string &value, bool skipUpdateLinked)
auto
iv
=
col
.
mValidator
;
auto
iv
=
col
.
mValidator
;
if
(
not
skipUpdateLinked
and
iv
!=
nullptr
and
mCascade
)
if
(
not
skipUpdateLinked
and
iv
!=
nullptr
and
mCascade
)
{
{
auto
&
validator
=
cat
->
getValidator
();
for
(
auto
&&
[
childCat
,
linked
]
:
cat
->
mChildLinks
)
auto
&
db
=
cat
->
db
();
for
(
auto
linked
:
validator
.
getLinksForParent
(
cat
->
mName
))
{
{
auto
childCat
=
db
.
get
(
linked
->
mChildCategory
);
if
(
childCat
==
nullptr
)
continue
;
if
(
find
(
linked
->
mParentKeys
.
begin
(),
linked
->
mParentKeys
.
end
(),
iv
->
mTag
)
==
linked
->
mParentKeys
.
end
())
if
(
find
(
linked
->
mParentKeys
.
begin
(),
linked
->
mParentKeys
.
end
(),
iv
->
mTag
)
==
linked
->
mParentKeys
.
end
())
continue
;
continue
;
...
@@ -3203,18 +3211,13 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b)
...
@@ -3203,18 +3211,13 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b)
auto
parentColName
=
cat
->
getColumnName
(
cix
);
auto
parentColName
=
cat
->
getColumnName
(
cix
);
// see if we need to update any child categories that depend on these values
// see if we need to update any child categories that depend on these values
auto
&
validator
=
cat
->
getValidator
();
auto
parentCatValidator
=
cat
->
getCatValidator
();
auto
parentCatValidator
=
cat
->
getCatValidator
();
for
(
auto
&
link
:
validator
.
getLinksForParent
(
cat
->
mName
)
)
for
(
auto
&
&
[
childCat
,
link
]
:
cat
->
mChildLinks
)
{
{
if
(
find
(
link
->
mParentKeys
.
begin
(),
link
->
mParentKeys
.
end
(),
parentColName
)
==
link
->
mParentKeys
.
end
())
if
(
find
(
link
->
mParentKeys
.
begin
(),
link
->
mParentKeys
.
end
(),
parentColName
)
==
link
->
mParentKeys
.
end
())
continue
;
continue
;
auto
childCat
=
cat
->
db
().
get
(
link
->
mChildCategory
);
if
(
childCat
==
nullptr
or
childCat
->
empty
())
continue
;
auto
childCatValidator
=
childCat
->
getCatValidator
();
auto
childCatValidator
=
childCat
->
getCatValidator
();
if
(
childCatValidator
==
nullptr
)
if
(
childCatValidator
==
nullptr
)
continue
;
continue
;
...
@@ -3426,7 +3429,6 @@ File::File(File &&rhs)
...
@@ -3426,7 +3429,6 @@ File::File(File &&rhs)
File
::~
File
()
File
::~
File
()
{
{
delete
mHead
;
delete
mHead
;
delete
mValidator
;
}
}
void
File
::
append
(
Datablock
*
e
)
void
File
::
append
(
Datablock
*
e
)
...
@@ -3503,7 +3505,7 @@ void File::save(const std::filesystem::path &p)
...
@@ -3503,7 +3505,7 @@ void File::save(const std::filesystem::path &p)
void
File
::
load
(
std
::
istream
&
is
)
void
File
::
load
(
std
::
istream
&
is
)
{
{
Validator
*
saved
=
mValidator
;
auto
saved
=
mValidator
;
setValidator
(
nullptr
);
setValidator
(
nullptr
);
Parser
p
(
is
,
*
this
);
Parser
p
(
is
,
*
this
);
...
@@ -3518,7 +3520,7 @@ void File::load(std::istream &is)
...
@@ -3518,7 +3520,7 @@ void File::load(std::istream &is)
void
File
::
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
)
void
File
::
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
)
{
{
Validator
*
saved
=
mValidator
;
auto
saved
=
mValidator
;
setValidator
(
nullptr
);
setValidator
(
nullptr
);
Parser
p
(
is
,
*
this
);
Parser
p
(
is
,
*
this
);
...
@@ -3607,67 +3609,10 @@ void File::loadDictionary()
...
@@ -3607,67 +3609,10 @@ void File::loadDictionary()
void
File
::
loadDictionary
(
const
char
*
dict
)
void
File
::
loadDictionary
(
const
char
*
dict
)
{
{
fs
::
path
dict_name
(
dict
);
setValidator
(
&
ValidatorFactory
::
instance
()[
dict
]);
auto
data
=
loadResource
(
dict
);
if
(
not
data
and
dict_name
.
extension
().
string
()
!=
".dic"
)
data
=
loadResource
(
dict_name
.
parent_path
()
/
(
dict_name
.
filename
().
string
()
+
".dic"
));
if
(
data
)
loadDictionary
(
*
data
);
else
{
// might be a compressed dictionary on disk
fs
::
path
p
=
dict
;
if
(
p
.
extension
()
==
".dic"
)
p
=
p
.
parent_path
()
/
(
p
.
filename
().
string
()
+
".gz"
);
else
p
=
p
.
parent_path
()
/
(
p
.
filename
().
string
()
+
".dic.gz"
);
#if defined(CACHE_DIR) and defined(DATA_DIR)
if
(
not
fs
::
exists
(
p
))
{
for
(
const
char
*
dir
:
{
CACHE_DIR
,
DATA_DIR
})
{
auto
p2
=
fs
::
path
(
dir
)
/
p
;
if
(
fs
::
exists
(
p2
))
{
swap
(
p
,
p2
);
break
;
}
}
}
#endif
if
(
fs
::
exists
(
p
))
{
std
::
ifstream
file
(
p
,
std
::
ios
::
binary
);
if
(
not
file
.
is_open
())
throw
std
::
runtime_error
(
"Could not open dictionary ("
+
p
.
string
()
+
")"
);
io
::
filtering_stream
<
io
::
input
>
in
;
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
file
);
loadDictionary
(
in
);
}
else
throw
std
::
runtime_error
(
"Dictionary not found or defined ("
+
dict_name
.
string
()
+
")"
);
}
}
void
File
::
loadDictionary
(
std
::
istream
&
is
)
{
std
::
unique_ptr
<
Validator
>
v
(
new
Validator
());
DictParser
p
(
*
v
,
is
);
p
.
loadDictionary
();
setValidator
(
v
.
release
());
}
}
void
File
::
setValidator
(
Validator
*
v
)
void
File
::
setValidator
(
const
Validator
*
v
)
{
{
mValidator
=
v
;
mValidator
=
v
;
...
...
src/CifParser.cpp
View file @
1f6b86d5
...
@@ -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
...
@@ -53,14 +53,14 @@ const uint8_t kCharTraitsTable[128] = {
...
@@ -53,14 +53,14 @@ const uint8_t kCharTraitsTable[128] = {
// --------------------------------------------------------------------
// --------------------------------------------------------------------
CifParserError
::
CifParserError
(
uint32_t
lineNr
,
const
std
::
string
&
message
)
CifParserError
::
CifParserError
(
uint32_t
lineNr
,
const
std
::
string
&
message
)
:
std
::
runtime_error
(
"parse error at line "
+
std
::
to_string
(
lineNr
)
+
": "
+
message
)
:
std
::
runtime_error
(
"parse error at line "
+
std
::
to_string
(
lineNr
)
+
": "
+
message
)
{
{
}
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
const
char
*
SacParser
::
kTokenName
[]
=
{
const
char
*
SacParser
::
kTokenName
[]
=
{
"unknown"
,
"unknown"
,
"EOF"
,
"EOF"
,
"DATA"
,
"DATA"
,
...
@@ -69,22 +69,20 @@ const char* SacParser::kTokenName[] = {
...
@@ -69,22 +69,20 @@ const char* SacParser::kTokenName[] = {
"SAVE"
,
"SAVE"
,
"STOP"
,
"STOP"
,
"Tag"
,
"Tag"
,
"Value"
"Value"
};
};
const
char
*
SacParser
::
kValueName
[]
=
{
const
char
*
SacParser
::
kValueName
[]
=
{
"Int"
,
"Int"
,
"Float"
,
"Float"
,
"Numeric"
,
"Numeric"
,
"String"
,
"String"
,
"TextField"
,
"TextField"
,
"Inapplicable"
,
"Inapplicable"
,
"Unknown"
"Unknown"
};
};
// --------------------------------------------------------------------
// --------------------------------------------------------------------
SacParser
::
SacParser
(
std
::
istream
&
is
,
bool
init
)
SacParser
::
SacParser
(
std
::
istream
&
is
,
bool
init
)
:
mData
(
is
)
:
mData
(
is
)
{
{
mValidate
=
true
;
mValidate
=
true
;
...
@@ -95,7 +93,7 @@ SacParser::SacParser(std::istream& is, bool init)
...
@@ -95,7 +93,7 @@ SacParser::SacParser(std::istream& is, bool init)
mLookahead
=
getNextToken
();
mLookahead
=
getNextToken
();
}
}
void
SacParser
::
error
(
const
std
::
string
&
msg
)
void
SacParser
::
error
(
const
std
::
string
&
msg
)
{
{
throw
CifParserError
(
mLineNr
,
msg
);
throw
CifParserError
(
mLineNr
,
msg
);
}
}
...
@@ -291,8 +289,8 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -291,8 +289,8 @@ SacParser::CIFToken SacParser::getNextToken()
else
if
(
ch
==
kEOF
)
else
if
(
ch
==
kEOF
)
error
(
"unterminated textfield"
);
error
(
"unterminated textfield"
);
else
if
(
not
isAnyPrint
(
ch
))
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
:
...
@@ -360,9 +358,9 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -360,9 +358,9 @@ SacParser::CIFToken SacParser::getNextToken()
break
;
break
;
case
eStateFloat
+
1
:
case
eStateFloat
+
1
:
// if (ch == '(') // numeric???
// if (ch == '(') // numeric???
// mState = eStateNumericSuffix;
// mState = eStateNumericSuffix;
// else
// else
if
(
ch
==
'.'
)
if
(
ch
==
'.'
)
mState
=
eStateFloat
+
2
;
mState
=
eStateFloat
+
2
;
else
if
(
tolower
(
ch
)
==
'e'
)
else
if
(
tolower
(
ch
)
==
'e'
)
...
@@ -379,9 +377,9 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -379,9 +377,9 @@ SacParser::CIFToken SacParser::getNextToken()
// parsed '.'
// parsed '.'
case
eStateFloat
+
2
:
case
eStateFloat
+
2
:
// if (ch == '(') // numeric???
// if (ch == '(') // numeric???
// mState = eStateNumericSuffix;
// mState = eStateNumericSuffix;
// else
// else
if
(
tolower
(
ch
)
==
'e'
)
if
(
tolower
(
ch
)
==
'e'
)
mState
=
eStateFloat
+
3
;
mState
=
eStateFloat
+
3
;
else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
...
@@ -412,9 +410,9 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -412,9 +410,9 @@ SacParser::CIFToken SacParser::getNextToken()
break
;
break
;
case
eStateFloat
+
5
:
case
eStateFloat
+
5
:
// if (ch == '(')
// if (ch == '(')
// mState = eStateNumericSuffix;
// mState = eStateNumericSuffix;
// else
// else
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
if
(
isWhite
(
ch
)
or
ch
==
kEOF
)
{
{
retract
();
retract
();
...
@@ -443,22 +441,22 @@ SacParser::CIFToken SacParser::getNextToken()
...
@@ -443,22 +441,22 @@ SacParser::CIFToken SacParser::getNextToken()
restart
();
restart
();
break
;
break
;
// case eStateNumericSuffix:
// case eStateNumericSuffix:
// if (isdigit(ch))
// if (isdigit(ch))
// mState = eStateNumericSuffix + 1;
// mState = eStateNumericSuffix + 1;
// else
// else
// restart();
// restart();
// break;
// break;
//
//
// case eStateNumericSuffix + 1:
// case eStateNumericSuffix + 1:
// if (ch == ')')
// if (ch == ')')
// {
// {
// result = eCIFTokenValue;
// result = eCIFTokenValue;
// mTokenType = eCIFValueNumeric;
// mTokenType = eCIFValueNumeric;
// }
// }
// else if (not isdigit(ch))
// else if (not isdigit(ch))
// restart();
// restart();
// break;
// break;
case
eStateValue
:
case
eStateValue
:
if
(
isNonBlank
(
ch
))
if
(
isNonBlank
(
ch
))
...
@@ -530,8 +528,15 @@ DatablockIndex SacParser::indexDatablocks()
...
@@ -530,8 +528,15 @@ DatablockIndex SacParser::indexDatablocks()
// first locate the start, as fast as we can
// first locate the start, as fast as we can
auto
&
sb
=
*
mData
.
rdbuf
();
auto
&
sb
=
*
mData
.
rdbuf
();
enum
{
enum
start
,
comment
,
string
,
string_quote
,
qstring
,
data
,
data_name
{
start
,
comment
,
string
,
string_quote
,
qstring
,
data
,
data_name
}
state
=
start
;
}
state
=
start
;
int
quote
=
0
;
int
quote
=
0
;
...
@@ -590,7 +595,7 @@ DatablockIndex SacParser::indexDatablocks()
...
@@ -590,7 +595,7 @@ DatablockIndex SacParser::indexDatablocks()
case
data
:
case
data
:
if
(
dblk
[
si
]
==
0
and
isNonBlank
(
ch
))
if
(
dblk
[
si
]
==
0
and
isNonBlank
(
ch
))
{
{
datablock
=
{
static_cast
<
char
>
(
ch
)
};
datablock
=
{
static_cast
<
char
>
(
ch
)
};
state
=
data_name
;
state
=
data_name
;
}
}
else
if
(
dblk
[
si
++
]
!=
ch
)
else
if
(
dblk
[
si
++
]
!=
ch
)
...
@@ -618,13 +623,19 @@ DatablockIndex SacParser::indexDatablocks()
...
@@ -618,13 +623,19 @@ DatablockIndex SacParser::indexDatablocks()
return
index
;
return
index
;
}
}
bool
SacParser
::
parseSingleDatablock
(
const
std
::
string
&
datablock
)
bool
SacParser
::
parseSingleDatablock
(
const
std
::
string
&
datablock
)
{
{
// first locate the start, as fast as we can
// first locate the start, as fast as we can
auto
&
sb
=
*
mData
.
rdbuf
();
auto
&
sb
=
*
mData
.
rdbuf
();
enum
{
enum
start
,
comment
,
string
,
string_quote
,
qstring
,
data
{
start
,
comment
,
string
,
string_quote
,
qstring
,
data
}
state
=
start
;
}
state
=
start
;
int
quote
=
0
;
int
quote
=
0
;
...
@@ -701,7 +712,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock)
...
@@ -701,7 +712,7 @@ bool SacParser::parseSingleDatablock(const std::string& datablock)
return
found
;
return
found
;
}
}
bool
SacParser
::
parseSingleDatablock
(
const
std
::
string
&
datablock
,
const
DatablockIndex
&
index
)
bool
SacParser
::
parseSingleDatablock
(
const
std
::
string
&
datablock
,
const
DatablockIndex
&
index
)
{
{
bool
result
=
false
;
bool
result
=
false
;
...
@@ -792,7 +803,7 @@ void SacParser::parseDataBlock()
...
@@ -792,7 +803,7 @@ void SacParser::parseDataBlock()
{
{
produceRow
();
produceRow
();
for
(
auto
tag
:
tags
)
for
(
auto
tag
:
tags
)
{
{
produceItem
(
cat
,
tag
,
mTokenValue
);
produceItem
(
cat
,
tag
,
mTokenValue
);
match
(
eCIFTokenValue
);
match
(
eCIFTokenValue
);
...
@@ -841,18 +852,20 @@ void SacParser::parseSaveFrame()
...
@@ -841,18 +852,20 @@ void SacParser::parseSaveFrame()
// --------------------------------------------------------------------
// --------------------------------------------------------------------
Parser
::
Parser
(
std
::
istream
&
is
,
File
&
f
,
bool
init
)
Parser
::
Parser
(
std
::
istream
&
is
,
File
&
f
,
bool
init
)
:
SacParser
(
is
,
init
),
mFile
(
f
),
mDataBlock
(
nullptr
)
:
SacParser
(
is
,
init
)
,
mFile
(
f
)
,
mDataBlock
(
nullptr
)
{
{
}
}
void
Parser
::
produceDatablock
(
const
std
::
string
&
name
)
void
Parser
::
produceDatablock
(
const
std
::
string
&
name
)
{
{
mDataBlock
=
new
Datablock
(
name
);
mDataBlock
=
new
Datablock
(
name
);
mFile
.
append
(
mDataBlock
);
mFile
.
append
(
mDataBlock
);
}
}
void
Parser
::
produceCategory
(
const
std
::
string
&
name
)
void
Parser
::
produceCategory
(
const
std
::
string
&
name
)
{
{
if
(
VERBOSE
>=
4
)
if
(
VERBOSE
>=
4
)
std
::
cerr
<<
"producing category "
<<
name
<<
std
::
endl
;
std
::
cerr
<<
"producing category "
<<
name
<<
std
::
endl
;
...
@@ -870,7 +883,7 @@ void Parser::produceRow()
...
@@ -870,7 +883,7 @@ void Parser::produceRow()
mRow
.
lineNr
(
mLineNr
);
mRow
.
lineNr
(
mLineNr
);
}
}
void
Parser
::
produceItem
(
const
std
::
string
&
category
,
const
std
::
string
&
item
,
const
std
::
string
&
value
)
void
Parser
::
produceItem
(
const
std
::
string
&
category
,
const
std
::
string
&
item
,
const
std
::
string
&
value
)
{
{
if
(
VERBOSE
>=
4
)
if
(
VERBOSE
>=
4
)
std
::
cerr
<<
"producing _"
<<
category
<<
'.'
<<
item
<<
" -> "
<<
value
<<
std
::
endl
;
std
::
cerr
<<
"producing _"
<<
category
<<
'.'
<<
item
<<
" -> "
<<
value
<<
std
::
endl
;
...
@@ -887,12 +900,14 @@ struct DictParserDataImpl
...
@@ -887,12 +900,14 @@ struct DictParserDataImpl
{
{
// temporary values for constructing dictionaries
// temporary values for constructing dictionaries
std
::
vector
<
ValidateCategory
>
mCategoryValidators
;
std
::
vector
<
ValidateCategory
>
mCategoryValidators
;
std
::
map
<
std
::
string
,
std
::
vector
<
ValidateItem
>>
mItemValidators
;
std
::
map
<
std
::
string
,
std
::
vector
<
ValidateItem
>>
mItemValidators
;
std
::
set
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
mLinkedItems
;
std
::
set
<
std
::
tuple
<
std
::
string
,
std
::
string
>>
mLinkedItems
;
};
};
DictParser
::
DictParser
(
Validator
&
validator
,
std
::
istream
&
is
)
DictParser
::
DictParser
(
Validator
&
validator
,
std
::
istream
&
is
)
:
Parser
(
is
,
mFile
),
mValidator
(
validator
),
mImpl
(
new
DictParserDataImpl
)
:
Parser
(
is
,
mFile
)
,
mValidator
(
validator
)
,
mImpl
(
new
DictParserDataImpl
)
{
{
}
}
...
@@ -945,7 +960,7 @@ void DictParser::parseSaveFrame()
...
@@ -945,7 +960,7 @@ void DictParser::parseSaveFrame()
cat
->
emplace
({});
cat
->
emplace
({});
auto
row
=
cat
->
back
();
auto
row
=
cat
->
back
();
for
(
auto
tag
:
tags
)
for
(
auto
tag
:
tags
)
{
{
row
[
tag
]
=
mTokenValue
;
row
[
tag
]
=
mTokenValue
;
match
(
eCIFTokenValue
);
match
(
eCIFTokenValue
);
...
@@ -976,14 +991,15 @@ void DictParser::parseSaveFrame()
...
@@ -976,14 +991,15 @@ void DictParser::parseSaveFrame()
if
(
isCategorySaveFrame
)
if
(
isCategorySaveFrame
)
{
{
std
::
string
category
=
dict
.
firstItem
(
"_category.id"
);
std
::
string
category
;
cif
::
tie
(
category
)
=
dict
[
"category"
].
front
().
get
(
"id"
);
std
::
vector
<
std
::
string
>
keys
;
std
::
vector
<
std
::
string
>
keys
;
for
(
auto
k
:
dict
[
"category_key"
])
for
(
auto
k
:
dict
[
"category_key"
])
keys
.
push_back
(
std
::
get
<
1
>
(
splitTagName
(
k
[
"name"
].
as
<
std
::
string
>
())));
keys
.
push_back
(
std
::
get
<
1
>
(
splitTagName
(
k
[
"name"
].
as
<
std
::
string
>
())));
iset
groups
;
iset
groups
;
for
(
auto
g
:
dict
[
"category_group"
])
for
(
auto
g
:
dict
[
"category_group"
])
groups
.
insert
(
g
[
"id"
].
as
<
std
::
string
>
());
groups
.
insert
(
g
[
"id"
].
as
<
std
::
string
>
());
mImpl
->
mCategoryValidators
.
push_back
(
ValidateCategory
{
category
,
keys
,
groups
});
mImpl
->
mCategoryValidators
.
push_back
(
ValidateCategory
{
category
,
keys
,
groups
});
...
@@ -991,21 +1007,23 @@ void DictParser::parseSaveFrame()
...
@@ -991,21 +1007,23 @@ void DictParser::parseSaveFrame()
else
else
{
{
// if the type code is missing, this must be a pointer, just skip it
// if the type code is missing, this must be a pointer, just skip it
std
::
string
typeCode
=
dict
.
firstItem
(
"_item_type.code"
);
std
::
string
typeCode
;
cif
::
tie
(
typeCode
)
=
dict
[
"item_type"
].
front
().
get
(
"code"
);
const
ValidateType
*
tv
=
nullptr
;
const
ValidateType
*
tv
=
nullptr
;
if
(
not
(
typeCode
.
empty
()
or
typeCode
==
"?"
))
if
(
not
(
typeCode
.
empty
()
or
typeCode
==
"?"
))
tv
=
mValidator
.
getValidatorForType
(
typeCode
);
tv
=
mValidator
.
getValidatorForType
(
typeCode
);
iset
ess
;
iset
ess
;
for
(
auto
e
:
dict
[
"item_enumeration"
])
for
(
auto
e
:
dict
[
"item_enumeration"
])
ess
.
insert
(
e
[
"value"
].
as
<
std
::
string
>
());
ess
.
insert
(
e
[
"value"
].
as
<
std
::
string
>
());
std
::
string
defaultValue
=
dict
.
firstItem
(
"_item_default.value"
);
std
::
string
defaultValue
;
cif
::
tie
(
defaultValue
)
=
dict
[
"item_default"
].
front
().
get
(
"value"
);
bool
defaultIsNull
=
false
;
bool
defaultIsNull
=
false
;
if
(
defaultValue
.
empty
())
if
(
defaultValue
.
empty
())
{
{
for
(
auto
&
r
:
dict
[
"_item_default"
])
for
(
auto
&
r
:
dict
[
"_item_default"
])
{
{
defaultIsNull
=
r
[
"value"
].
is_null
();
defaultIsNull
=
r
[
"value"
].
is_null
();
break
;
break
;
...
@@ -1013,7 +1031,7 @@ void DictParser::parseSaveFrame()
...
@@ -1013,7 +1031,7 @@ void DictParser::parseSaveFrame()
}
}
// collect the dict from our dataBlock and construct validators
// collect the dict from our dataBlock and construct validators
for
(
auto
i
:
dict
[
"item"
])
for
(
auto
i
:
dict
[
"item"
])
{
{
std
::
string
tagName
,
category
,
mandatory
;
std
::
string
tagName
,
category
,
mandatory
;
...
@@ -1025,12 +1043,12 @@ void DictParser::parseSaveFrame()
...
@@ -1025,12 +1043,12 @@ void DictParser::parseSaveFrame()
if
(
catName
.
empty
()
or
itemName
.
empty
())
if
(
catName
.
empty
()
or
itemName
.
empty
())
error
(
"Invalid tag name in _item.name "
+
tagName
);
error
(
"Invalid tag name in _item.name "
+
tagName
);
if
(
not
iequals
(
category
,
catName
)
and
not
(
category
.
empty
()
or
category
==
"?"
))
if
(
not
iequals
(
category
,
catName
)
and
not
(
category
.
empty
()
or
category
==
"?"
))
error
(
"specified category id does match the implicit category name for tag '"
+
tagName
+
'\''
);
error
(
"specified category id does match the implicit category name for tag '"
+
tagName
+
'\''
);
else
else
category
=
catName
;
category
=
catName
;
auto
&
ivs
=
mImpl
->
mItemValidators
[
category
];
auto
&
ivs
=
mImpl
->
mItemValidators
[
category
];
auto
vi
=
find
(
ivs
.
begin
(),
ivs
.
end
(),
ValidateItem
{
itemName
});
auto
vi
=
find
(
ivs
.
begin
(),
ivs
.
end
(),
ValidateItem
{
itemName
});
if
(
vi
==
ivs
.
end
())
if
(
vi
==
ivs
.
end
())
...
@@ -1060,7 +1078,7 @@ void DictParser::parseSaveFrame()
...
@@ -1060,7 +1078,7 @@ void DictParser::parseSaveFrame()
std
::
cerr
<<
"inconsistent type for "
<<
tagName
<<
" in dictionary"
<<
std
::
endl
;
std
::
cerr
<<
"inconsistent type for "
<<
tagName
<<
" in dictionary"
<<
std
::
endl
;
}
}
// vi->mMandatory = (iequals(mandatory, "yes"));
// vi->mMandatory = (iequals(mandatory, "yes"));
if
(
vi
->
mType
==
nullptr
)
if
(
vi
->
mType
==
nullptr
)
vi
->
mType
=
tv
;
vi
->
mType
=
tv
;
...
@@ -1072,7 +1090,7 @@ void DictParser::parseSaveFrame()
...
@@ -1072,7 +1090,7 @@ void DictParser::parseSaveFrame()
}
}
// collect the dict from our dataBlock and construct validators
// collect the dict from our dataBlock and construct validators
for
(
auto
i
:
dict
[
"item_linked"
])
for
(
auto
i
:
dict
[
"item_linked"
])
{
{
std
::
string
childTagName
,
parentTagName
;
std
::
string
childTagName
,
parentTagName
;
...
@@ -1088,20 +1106,20 @@ void DictParser::linkItems()
...
@@ -1088,20 +1106,20 @@ void DictParser::linkItems()
if
(
not
mDataBlock
)
if
(
not
mDataBlock
)
error
(
"no datablock"
);
error
(
"no datablock"
);
auto
&
dict
=
*
mDataBlock
;
auto
&
dict
=
*
mDataBlock
;
// links are identified by a parent category, a child category and a group ID
// links are identified by a parent category, a child category and a group ID
using
key_type
=
std
::
tuple
<
std
::
string
,
std
::
string
,
int
>
;
using
key_type
=
std
::
tuple
<
std
::
string
,
std
::
string
,
int
>
;
std
::
map
<
key_type
,
size_t
>
linkIndex
;
std
::
map
<
key_type
,
size_t
>
linkIndex
;
// Each link group consists of a set of keys
// Each link group consists of a set of keys
std
::
vector
<
std
::
tuple
<
std
::
vector
<
std
::
string
>
,
std
::
vector
<
std
::
string
>>>
linkKeys
;
std
::
vector
<
std
::
tuple
<
std
::
vector
<
std
::
string
>
,
std
::
vector
<
std
::
string
>>>
linkKeys
;
auto
addLink
=
[
&
](
size_t
ix
,
const
std
::
string
&
pk
,
const
std
::
string
&
ck
)
auto
addLink
=
[
&
](
size_t
ix
,
const
std
::
string
&
pk
,
const
std
::
string
&
ck
)
{
{
auto
&&
[
pkeys
,
ckeys
]
=
linkKeys
.
at
(
ix
);
auto
&&
[
pkeys
,
ckeys
]
=
linkKeys
.
at
(
ix
);
bool
found
=
false
;
bool
found
=
false
;
for
(
size_t
i
=
0
;
i
<
pkeys
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
pkeys
.
size
();
++
i
)
...
@@ -1120,9 +1138,9 @@ void DictParser::linkItems()
...
@@ -1120,9 +1138,9 @@ void DictParser::linkItems()
}
}
};
};
auto
&
linkedGroupList
=
dict
[
"pdbx_item_linked_group_list"
];
auto
&
linkedGroupList
=
dict
[
"pdbx_item_linked_group_list"
];
for
(
auto
gl
:
linkedGroupList
)
for
(
auto
gl
:
linkedGroupList
)
{
{
std
::
string
child
,
parent
;
std
::
string
child
,
parent
;
int
link_group_id
;
int
link_group_id
;
...
@@ -1136,7 +1154,7 @@ void DictParser::linkItems()
...
@@ -1136,7 +1154,7 @@ void DictParser::linkItems()
if
(
piv
==
nullptr
)
if
(
piv
==
nullptr
)
error
(
"in pdbx_item_linked_group_list, item '"
+
parent
+
"' is not specified"
);
error
(
"in pdbx_item_linked_group_list, item '"
+
parent
+
"' is not specified"
);
key_type
key
{
piv
->
mCategory
->
mName
,
civ
->
mCategory
->
mName
,
link_group_id
};
key_type
key
{
piv
->
mCategory
->
mName
,
civ
->
mCategory
->
mName
,
link_group_id
};
if
(
not
linkIndex
.
count
(
key
))
if
(
not
linkIndex
.
count
(
key
))
{
{
linkIndex
[
key
]
=
linkKeys
.
size
();
linkIndex
[
key
]
=
linkKeys
.
size
();
...
@@ -1151,7 +1169,7 @@ void DictParser::linkItems()
...
@@ -1151,7 +1169,7 @@ void DictParser::linkItems()
if
(
linkedGroupList
.
empty
())
if
(
linkedGroupList
.
empty
())
{
{
// for links recorded in categories but not in pdbx_item_linked_group_list
// for links recorded in categories but not in pdbx_item_linked_group_list
for
(
auto
li
:
mImpl
->
mLinkedItems
)
for
(
auto
li
:
mImpl
->
mLinkedItems
)
{
{
std
::
string
child
,
parent
;
std
::
string
child
,
parent
;
std
::
tie
(
child
,
parent
)
=
li
;
std
::
tie
(
child
,
parent
)
=
li
;
...
@@ -1164,7 +1182,7 @@ void DictParser::linkItems()
...
@@ -1164,7 +1182,7 @@ void DictParser::linkItems()
if
(
piv
==
nullptr
)
if
(
piv
==
nullptr
)
error
(
"in pdbx_item_linked_group_list, item '"
+
parent
+
"' is not specified"
);
error
(
"in pdbx_item_linked_group_list, item '"
+
parent
+
"' is not specified"
);
key_type
key
{
piv
->
mCategory
->
mName
,
civ
->
mCategory
->
mName
,
0
};
key_type
key
{
piv
->
mCategory
->
mName
,
civ
->
mCategory
->
mName
,
0
};
if
(
not
linkIndex
.
count
(
key
))
if
(
not
linkIndex
.
count
(
key
))
{
{
linkIndex
[
key
]
=
linkKeys
.
size
();
linkIndex
[
key
]
=
linkKeys
.
size
();
...
@@ -1176,10 +1194,10 @@ void DictParser::linkItems()
...
@@ -1176,10 +1194,10 @@ void DictParser::linkItems()
}
}
}
}
auto
&
linkedGroup
=
dict
[
"pdbx_item_linked_group"
];
auto
&
linkedGroup
=
dict
[
"pdbx_item_linked_group"
];
// now store the links in the validator
// now store the links in the validator
for
(
auto
&
kv
:
linkIndex
)
for
(
auto
&
kv
:
linkIndex
)
{
{
ValidateLink
link
=
{};
ValidateLink
link
=
{};
std
::
tie
(
link
.
mParentCategory
,
link
.
mChildCategory
,
link
.
mLinkGroupID
)
=
kv
.
first
;
std
::
tie
(
link
.
mParentCategory
,
link
.
mChildCategory
,
link
.
mLinkGroupID
)
=
kv
.
first
;
...
@@ -1187,7 +1205,7 @@ void DictParser::linkItems()
...
@@ -1187,7 +1205,7 @@ void DictParser::linkItems()
std
::
tie
(
link
.
mParentKeys
,
link
.
mChildKeys
)
=
linkKeys
[
kv
.
second
];
std
::
tie
(
link
.
mParentKeys
,
link
.
mChildKeys
)
=
linkKeys
[
kv
.
second
];
// look up the label
// look up the label
for
(
auto
r
:
linkedGroup
.
find
(
cif
::
Key
(
"category_id"
)
==
link
.
mChildCategory
and
cif
::
Key
(
"link_group_id"
)
==
link
.
mLinkGroupID
))
for
(
auto
r
:
linkedGroup
.
find
(
cif
::
Key
(
"category_id"
)
==
link
.
mChildCategory
and
cif
::
Key
(
"link_group_id"
)
==
link
.
mLinkGroupID
))
{
{
link
.
mLinkGroupLabel
=
r
[
"label"
].
as
<
std
::
string
>
();
link
.
mLinkGroupLabel
=
r
[
"label"
].
as
<
std
::
string
>
();
break
;
break
;
...
@@ -1198,9 +1216,9 @@ void DictParser::linkItems()
...
@@ -1198,9 +1216,9 @@ void DictParser::linkItems()
// now make sure the itemType is specified for all itemValidators
// now make sure the itemType is specified for all itemValidators
for
(
auto
&
cv
:
mValidator
.
mCategoryValidators
)
for
(
auto
&
cv
:
mValidator
.
mCategoryValidators
)
{
{
for
(
auto
&
iv
:
cv
.
mItemValidators
)
for
(
auto
&
iv
:
cv
.
mItemValidators
)
{
{
if
(
iv
.
mType
==
nullptr
)
if
(
iv
.
mType
==
nullptr
)
std
::
cerr
<<
"Missing item_type for "
<<
iv
.
mTag
<<
std
::
endl
;
std
::
cerr
<<
"Missing item_type for "
<<
iv
.
mTag
<<
std
::
endl
;
...
@@ -1211,7 +1229,7 @@ void DictParser::linkItems()
...
@@ -1211,7 +1229,7 @@ void DictParser::linkItems()
void
DictParser
::
loadDictionary
()
void
DictParser
::
loadDictionary
()
{
{
std
::
unique_ptr
<
Datablock
>
dict
;
std
::
unique_ptr
<
Datablock
>
dict
;
Datablock
*
savedDatablock
=
mDataBlock
;
Datablock
*
savedDatablock
=
mDataBlock
;
try
try
{
{
...
@@ -1235,25 +1253,25 @@ void DictParser::loadDictionary()
...
@@ -1235,25 +1253,25 @@ void DictParser::loadDictionary()
}
}
}
}
}
}
catch
(
const
std
::
exception
&
)
catch
(
const
std
::
exception
&
)
{
{
std
::
cerr
<<
"Error parsing dictionary"
<<
std
::
endl
;
std
::
cerr
<<
"Error parsing dictionary"
<<
std
::
endl
;
throw
;
throw
;
}
}
// store all validators
// store all validators
for
(
auto
&
ic
:
mImpl
->
mCategoryValidators
)
for
(
auto
&
ic
:
mImpl
->
mCategoryValidators
)
mValidator
.
addCategoryValidator
(
std
::
move
(
ic
));
mValidator
.
addCategoryValidator
(
std
::
move
(
ic
));
mImpl
->
mCategoryValidators
.
clear
();
mImpl
->
mCategoryValidators
.
clear
();
for
(
auto
&
iv
:
mImpl
->
mItemValidators
)
for
(
auto
&
iv
:
mImpl
->
mItemValidators
)
{
{
auto
cv
=
mValidator
.
getValidatorForCategory
(
iv
.
first
);
auto
cv
=
mValidator
.
getValidatorForCategory
(
iv
.
first
);
if
(
cv
==
nullptr
)
if
(
cv
==
nullptr
)
error
(
"Undefined category '"
+
iv
.
first
);
error
(
"Undefined category '"
+
iv
.
first
);
for
(
auto
&
v
:
iv
.
second
)
for
(
auto
&
v
:
iv
.
second
)
const_cast
<
ValidateCategory
*>
(
cv
)
->
addItemValidator
(
std
::
move
(
v
));
const_cast
<
ValidateCategory
*>
(
cv
)
->
addItemValidator
(
std
::
move
(
v
));
}
}
// check all item validators for having a typeValidator
// check all item validators for having a typeValidator
...
@@ -1284,9 +1302,9 @@ bool DictParser::collectItemTypes()
...
@@ -1284,9 +1302,9 @@ bool DictParser::collectItemTypes()
if
(
not
mDataBlock
)
if
(
not
mDataBlock
)
error
(
"no datablock"
);
error
(
"no datablock"
);
auto
&
dict
=
*
mDataBlock
;
auto
&
dict
=
*
mDataBlock
;
for
(
auto
&
t
:
dict
[
"item_type_list"
])
for
(
auto
&
t
:
dict
[
"item_type_list"
])
{
{
std
::
string
code
,
primitiveCode
,
construct
;
std
::
string
code
,
primitiveCode
,
construct
;
cif
::
tie
(
code
,
primitiveCode
,
construct
)
=
t
.
get
(
"code"
,
"primitive_code"
,
"construct"
);
cif
::
tie
(
code
,
primitiveCode
,
construct
)
=
t
.
get
(
"code"
,
"primitive_code"
,
"construct"
);
...
@@ -1298,20 +1316,19 @@ bool DictParser::collectItemTypes()
...
@@ -1298,20 +1316,19 @@ bool DictParser::collectItemTypes()
try
try
{
{
ValidateType
v
=
{
ValidateType
v
=
{
code
,
mapToPrimitiveType
(
primitiveCode
),
boost
::
regex
(
construct
,
boost
::
regex
::
extended
|
boost
::
regex
::
optimize
)
code
,
mapToPrimitiveType
(
primitiveCode
),
boost
::
regex
(
construct
,
boost
::
regex
::
extended
|
boost
::
regex
::
optimize
)};
};
mValidator
.
addTypeValidator
(
std
::
move
(
v
));
mValidator
.
addTypeValidator
(
std
::
move
(
v
));
}
}
catch
(
const
std
::
exception
&
)
catch
(
const
std
::
exception
&
)
{
{
throw_with_nested
(
CifParserError
(
t
.
lineNr
(),
"error in regular expression"
));
throw_with_nested
(
CifParserError
(
t
.
lineNr
(),
"error in regular expression"
));
}
}
// Do not replace an already defined type validator, this won't work with pdbx_v40
// Do not replace an already defined type validator, this won't work with pdbx_v40
// as it has a name that is too strict for its own names :-)
// as it has a name that is too strict for its own names :-)
// if (mFileImpl.mTypeValidators.count(v))
// if (mFileImpl.mTypeValidators.count(v))
// mFileImpl.mTypeValidators.erase(v);
// mFileImpl.mTypeValidators.erase(v);
if
(
VERBOSE
>=
5
)
if
(
VERBOSE
>=
5
)
std
::
cerr
<<
"Added type "
<<
code
<<
" ("
<<
primitiveCode
<<
") => "
<<
construct
<<
std
::
endl
;
std
::
cerr
<<
"Added type "
<<
code
<<
" ("
<<
primitiveCode
<<
") => "
<<
construct
<<
std
::
endl
;
...
@@ -1322,5 +1339,4 @@ bool DictParser::collectItemTypes()
...
@@ -1322,5 +1339,4 @@ bool DictParser::collectItemTypes()
return
result
;
return
result
;
}
}
}
// namespace cif
}
src/CifUtils.cpp
View file @
1f6b86d5
...
@@ -123,19 +123,12 @@ const uint8_t kCharToLowerMap[256] =
...
@@ -123,19 +123,12 @@ const uint8_t kCharToLowerMap[256] =
// --------------------------------------------------------------------
// --------------------------------------------------------------------
bool
iequals
(
const
std
::
string
&
a
,
const
std
::
string
&
b
)
{
bool
result
=
a
.
length
()
==
b
.
length
();
for
(
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
result
and
ai
!=
a
.
end
()
and
bi
!=
b
.
end
();
++
ai
,
++
bi
)
result
=
tolower
(
*
ai
)
==
tolower
(
*
bi
);
return
result
;
}
bool
iequals
(
std
::
string_view
a
,
std
::
string_view
b
)
bool
iequals
(
std
::
string_view
a
,
std
::
string_view
b
)
{
{
bool
result
=
a
.
length
()
==
b
.
length
();
bool
result
=
a
.
length
()
==
b
.
length
();
for
(
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
result
and
ai
!=
a
.
end
()
and
bi
!=
b
.
end
();
++
ai
,
++
bi
)
for
(
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
result
and
ai
!=
a
.
end
();
++
ai
,
++
bi
)
result
=
tolower
(
*
ai
)
==
tolower
(
*
bi
);
result
=
kCharToLowerMap
[
uint8_t
(
*
ai
)]
==
kCharToLowerMap
[
uint8_t
(
*
bi
)];
// result = tolower(*ai) == tolower(*bi);
return
result
;
return
result
;
}
}
...
@@ -148,25 +141,6 @@ bool iequals(const char *a, const char *b)
...
@@ -148,25 +141,6 @@ bool iequals(const char *a, const char *b)
return
result
and
*
a
==
*
b
;
return
result
and
*
a
==
*
b
;
}
}
int
icompare
(
const
std
::
string
&
a
,
const
std
::
string
&
b
)
{
int
d
=
0
;
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
for
(;
d
==
0
and
ai
!=
a
.
end
()
and
bi
!=
b
.
end
();
++
ai
,
++
bi
)
d
=
tolower
(
*
ai
)
-
tolower
(
*
bi
);
if
(
d
==
0
)
{
if
(
ai
!=
a
.
end
())
d
=
1
;
else
if
(
bi
!=
b
.
end
())
d
=
-
1
;
}
return
d
;
}
int
icompare
(
std
::
string_view
a
,
std
::
string_view
b
)
int
icompare
(
std
::
string_view
a
,
std
::
string_view
b
)
{
{
int
d
=
0
;
int
d
=
0
;
...
...
src/CifValidator.cpp
View file @
1f6b86d5
...
@@ -24,13 +24,20 @@
...
@@ -24,13 +24,20 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include <fstream>
#include <filesystem>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include "cif++/Cif++.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/CifParser.hpp"
#include "cif++/CifParser.hpp"
#include "cif++/CifValidator.hpp"
#include "cif++/CifValidator.hpp"
namespace
ba
=
boost
::
algorithm
;
namespace
ba
=
boost
::
algorithm
;
namespace
fs
=
std
::
filesystem
;
namespace
io
=
boost
::
iostreams
;
extern
int
VERBOSE
;
extern
int
VERBOSE
;
...
@@ -219,8 +226,11 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
...
@@ -219,8 +226,11 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
// --------------------------------------------------------------------
// --------------------------------------------------------------------
Validator
::
Validator
()
Validator
::
Validator
(
std
::
string_view
name
,
std
::
istream
&
is
)
:
mName
(
name
)
{
{
DictParser
p
(
*
this
,
is
);
p
.
loadDictionary
();
}
}
Validator
::~
Validator
()
Validator
::~
Validator
()
...
@@ -340,7 +350,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c
...
@@ -340,7 +350,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c
return
result
;
return
result
;
}
}
void
Validator
::
reportError
(
const
std
::
string
&
msg
,
bool
fatal
)
void
Validator
::
reportError
(
const
std
::
string
&
msg
,
bool
fatal
)
const
{
{
if
(
mStrict
or
fatal
)
if
(
mStrict
or
fatal
)
throw
ValidationError
(
msg
);
throw
ValidationError
(
msg
);
...
@@ -348,4 +358,78 @@ void Validator::reportError(const std::string &msg, bool fatal)
...
@@ -348,4 +358,78 @@ void Validator::reportError(const std::string &msg, bool fatal)
std
::
cerr
<<
msg
<<
std
::
endl
;
std
::
cerr
<<
msg
<<
std
::
endl
;
}
}
// --------------------------------------------------------------------
ValidatorFactory
ValidatorFactory
::
sInstance
;
ValidatorFactory
::
ValidatorFactory
()
{
}
const
Validator
&
ValidatorFactory
::
operator
[](
std
::
string_view
dictionary
)
{
std
::
lock_guard
lock
(
mMutex
);
for
(
auto
&
validator
:
mValidators
)
{
if
(
iequals
(
validator
.
mName
,
dictionary
))
return
validator
;
}
// not found, add it
fs
::
path
dict_name
(
dictionary
);
auto
data
=
loadResource
(
dictionary
);
if
(
not
data
and
dict_name
.
extension
().
string
()
!=
".dic"
)
data
=
loadResource
(
dict_name
.
parent_path
()
/
(
dict_name
.
filename
().
string
()
+
".dic"
));
if
(
data
)
mValidators
.
emplace_back
(
dictionary
,
*
data
);
else
{
// might be a compressed dictionary on disk
fs
::
path
p
=
dictionary
;
if
(
p
.
extension
()
==
".dic"
)
p
=
p
.
parent_path
()
/
(
p
.
filename
().
string
()
+
".gz"
);
else
p
=
p
.
parent_path
()
/
(
p
.
filename
().
string
()
+
".dic.gz"
);
#if defined(CACHE_DIR) and defined(DATA_DIR)
if
(
not
fs
::
exists
(
p
))
{
for
(
const
char
*
dir
:
{
CACHE_DIR
,
DATA_DIR
})
{
auto
p2
=
fs
::
path
(
dir
)
/
p
;
if
(
fs
::
exists
(
p2
))
{
swap
(
p
,
p2
);
break
;
}
}
}
#endif
if
(
fs
::
exists
(
p
))
{
std
::
ifstream
file
(
p
,
std
::
ios
::
binary
);
if
(
not
file
.
is_open
())
throw
std
::
runtime_error
(
"Could not open dictionary ("
+
p
.
string
()
+
")"
);
io
::
filtering_stream
<
io
::
input
>
in
;
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
file
);
mValidators
.
emplace_back
(
dictionary
,
in
);
}
else
throw
std
::
runtime_error
(
"Dictionary not found or defined ("
+
dict_name
.
string
()
+
")"
);
}
assert
(
iequals
(
mValidators
.
back
().
mName
,
dictionary
));
return
mValidators
.
back
();
}
}
// namespace cif
}
// namespace cif
src/Point.cpp
View file @
1f6b86d5
...
@@ -468,14 +468,14 @@ Point CenterPoints(std::vector<Point>& Points)
...
@@ -468,14 +468,14 @@ Point CenterPoints(std::vector<Point>& Points)
return
t
;
return
t
;
}
}
Point
Centroid
(
std
::
vector
<
Point
>&
Poin
ts
)
Point
Centroid
(
const
std
::
vector
<
Point
>&
p
ts
)
{
{
Point
result
;
Point
result
;
for
(
Point
&
pt
:
Poin
ts
)
for
(
auto
&
pt
:
p
ts
)
result
+=
pt
;
result
+=
pt
;
result
/=
static_cast
<
float
>
(
Poin
ts
.
size
());
result
/=
static_cast
<
float
>
(
p
ts
.
size
());
return
result
;
return
result
;
}
}
...
...
src/Structure.cpp
View file @
1f6b86d5
...
@@ -216,9 +216,9 @@ struct AtomImpl
...
@@ -216,9 +216,9 @@ struct AtomImpl
,
mLocation
(
i
.
mLocation
)
,
mLocation
(
i
.
mLocation
)
,
mRefcount
(
1
)
,
mRefcount
(
1
)
,
mRow
(
i
.
mRow
)
,
mRow
(
i
.
mRow
)
,
mCachedRefs
(
i
.
mCachedRefs
)
,
mCompound
(
i
.
mCompound
)
,
mCompound
(
i
.
mCompound
)
,
mRadius
(
i
.
mRadius
)
,
mRadius
(
i
.
mRadius
)
,
mCachedProperties
(
i
.
mCachedProperties
)
,
mSymmetryCopy
(
i
.
mSymmetryCopy
)
,
mSymmetryCopy
(
i
.
mSymmetryCopy
)
,
mClone
(
true
)
,
mClone
(
true
)
// , mRTop(i.mRTop), mD(i.mD)
// , mRTop(i.mRTop), mD(i.mD)
...
@@ -270,9 +270,9 @@ struct AtomImpl
...
@@ -270,9 +270,9 @@ struct AtomImpl
,
mLocation
(
loc
)
,
mLocation
(
loc
)
,
mRefcount
(
1
)
,
mRefcount
(
1
)
,
mRow
(
impl
.
mRow
)
,
mRow
(
impl
.
mRow
)
,
mCachedRefs
(
impl
.
mCachedRefs
)
,
mCompound
(
impl
.
mCompound
)
,
mCompound
(
impl
.
mCompound
)
,
mRadius
(
impl
.
mRadius
)
,
mRadius
(
impl
.
mRadius
)
,
mCachedProperties
(
impl
.
mCachedProperties
)
,
mSymmetryCopy
(
true
)
,
mSymmetryCopy
(
true
)
,
mSymmetryOperator
(
sym_op
)
,
mSymmetryOperator
(
sym_op
)
{
{
...
@@ -317,13 +317,15 @@ struct AtomImpl
...
@@ -317,13 +317,15 @@ struct AtomImpl
auto
cat
=
mDb
.
get
(
"atom_site_anisotrop"
);
auto
cat
=
mDb
.
get
(
"atom_site_anisotrop"
);
if
(
cat
)
if
(
cat
)
{
{
auto
r
=
cat
->
find1
(
cif
::
Key
(
"id"
)
==
mID
);
try
if
(
not
r
.
empty
())
{
{
result
=
true
;
auto
r
=
cat
->
find1
(
cif
::
Key
(
"id"
)
==
mID
)
;
cif
::
tie
(
anisou
[
0
],
anisou
[
1
],
anisou
[
2
],
anisou
[
3
],
anisou
[
4
],
anisou
[
5
])
=
cif
::
tie
(
anisou
[
0
],
anisou
[
1
],
anisou
[
2
],
anisou
[
3
],
anisou
[
4
],
anisou
[
5
])
=
r
.
get
(
"U[1][1]"
,
"U[1][2]"
,
"U[1][3]"
,
"U[2][2]"
,
"U[2][3]"
,
"U[3][3]"
);
r
.
get
(
"U[1][1]"
,
"U[1][2]"
,
"U[1][3]"
,
"U[2][2]"
,
"U[2][3]"
,
"U[3][3]"
);
result
=
true
;
}
catch
(
const
std
::
exception
&
e
)
{
}
}
}
}
...
@@ -338,9 +340,9 @@ struct AtomImpl
...
@@ -338,9 +340,9 @@ struct AtomImpl
if
(
not
mClone
)
if
(
not
mClone
)
{
{
mRow
[
"Cartn_x"
]
=
p
.
getX
(
);
property
(
"Cartn_x"
,
std
::
to_string
(
p
.
getX
())
);
mRow
[
"Cartn_y"
]
=
p
.
getY
(
);
property
(
"Cartn_y"
,
std
::
to_string
(
p
.
getY
())
);
mRow
[
"Cartn_z"
]
=
p
.
getZ
(
);
property
(
"Cartn_z"
,
std
::
to_string
(
p
.
getZ
())
);
}
}
// boost::format kPosFmt("%.3f");
// boost::format kPosFmt("%.3f");
...
@@ -382,26 +384,31 @@ struct AtomImpl
...
@@ -382,26 +384,31 @@ struct AtomImpl
return
mRadius
;
return
mRadius
;
}
}
const
std
::
string
&
property
(
const
std
::
string
&
name
)
const
const
std
::
string
property
(
const
std
::
string_view
name
)
const
{
{
static
std
::
string
kEmptyString
;
for
(
auto
&&
[
tag
,
ref
]
:
mCachedRefs
)
auto
i
=
mCachedProperties
.
find
(
name
);
if
(
i
==
mCachedProperties
.
end
())
{
{
auto
v
=
mRow
[
name
];
if
(
tag
==
name
)
if
(
v
.
empty
())
return
ref
.
as
<
std
::
string
>
();
return
kEmptyString
;
return
mCachedProperties
[
name
]
=
v
.
as
<
std
::
string
>
();
}
}
else
return
i
->
second
;
mCachedRefs
.
emplace_back
(
name
,
mRow
[
name
]);
return
std
::
get
<
1
>
(
mCachedRefs
.
back
()).
as
<
std
::
string
>
();
}
}
void
property
(
const
std
::
string
&
name
,
const
std
::
string
&
value
)
void
property
(
const
std
::
string_view
name
,
const
std
::
string
&
value
)
{
for
(
auto
&&
[
tag
,
ref
]
:
mCachedRefs
)
{
{
mRow
[
name
]
=
value
;
if
(
tag
!=
name
)
continue
;
ref
=
value
;
return
;
}
mCachedRefs
.
emplace_back
(
name
,
mRow
[
name
]);
std
::
get
<
1
>
(
mCachedRefs
.
back
())
=
value
;
}
}
int
compare
(
const
AtomImpl
&
b
)
const
int
compare
(
const
AtomImpl
&
b
)
const
...
@@ -432,9 +439,11 @@ struct AtomImpl
...
@@ -432,9 +439,11 @@ struct AtomImpl
Point
mLocation
;
Point
mLocation
;
int
mRefcount
;
int
mRefcount
;
cif
::
Row
mRow
;
cif
::
Row
mRow
;
mutable
std
::
vector
<
std
::
tuple
<
std
::
string
,
cif
::
detail
::
ItemReference
>>
mCachedRefs
;
mutable
const
Compound
*
mCompound
=
nullptr
;
mutable
const
Compound
*
mCompound
=
nullptr
;
float
mRadius
=
std
::
nanf
(
"4"
);
float
mRadius
=
std
::
nanf
(
"4"
);
mutable
std
::
map
<
std
::
string
,
std
::
string
>
mCachedProperties
;
bool
mSymmetryCopy
=
false
;
bool
mSymmetryCopy
=
false
;
bool
mClone
=
false
;
bool
mClone
=
false
;
...
@@ -533,25 +542,25 @@ const cif::Row Atom::getRowAniso() const
...
@@ -533,25 +542,25 @@ const cif::Row Atom::getRowAniso() const
}
}
template
<>
template
<>
std
::
string
Atom
::
property
<
std
::
string
>
(
const
std
::
string
&
name
)
const
std
::
string
Atom
::
property
<
std
::
string
>
(
const
std
::
string
_view
name
)
const
{
{
return
impl
()
->
property
(
name
);
return
impl
()
->
property
(
name
);
}
}
template
<>
template
<>
int
Atom
::
property
<
int
>
(
const
std
::
string
&
name
)
const
int
Atom
::
property
<
int
>
(
const
std
::
string
_view
name
)
const
{
{
auto
v
=
impl
()
->
property
(
name
);
auto
v
=
impl
()
->
property
(
name
);
return
v
.
empty
()
?
0
:
stoi
(
v
);
return
v
.
empty
()
?
0
:
stoi
(
v
);
}
}
template
<>
template
<>
float
Atom
::
property
<
float
>
(
const
std
::
string
&
name
)
const
float
Atom
::
property
<
float
>
(
const
std
::
string
_view
name
)
const
{
{
return
stof
(
impl
()
->
property
(
name
));
return
stof
(
impl
()
->
property
(
name
));
}
}
void
Atom
::
property
(
const
std
::
string
&
name
,
const
std
::
string
&
value
)
void
Atom
::
property
(
const
std
::
string
_view
name
,
const
std
::
string
&
value
)
{
{
impl
()
->
property
(
name
,
value
);
impl
()
->
property
(
name
,
value
);
}
}
...
@@ -1736,7 +1745,7 @@ File::~File()
...
@@ -1736,7 +1745,7 @@ File::~File()
delete
mImpl
;
delete
mImpl
;
}
}
cif
::
Datablock
&
File
::
createDatablock
(
const
std
::
string
&
name
)
cif
::
Datablock
&
File
::
createDatablock
(
const
std
::
string
_view
name
)
{
{
auto
db
=
new
cif
::
Datablock
(
name
);
auto
db
=
new
cif
::
Datablock
(
name
);
...
@@ -1807,8 +1816,8 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
...
@@ -1807,8 +1816,8 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
}
}
if
(
mAtoms
.
empty
())
if
(
mAtoms
.
empty
())
throw
std
::
runtime_error
(
"No atoms loaded, refuse to continue"
)
;
std
::
cerr
<<
"Warning: no atoms loaded"
<<
std
::
endl
;
else
loadData
();
loadData
();
}
}
...
...
src/Symmetry.cpp
View file @
1f6b86d5
...
@@ -90,4 +90,66 @@ int GetSpacegroupNumber(std::string spacegroup)
...
@@ -90,4 +90,66 @@ int GetSpacegroupNumber(std::string spacegroup)
return
result
;
return
result
;
}
}
// --------------------------------------------------------------------
int
GetSpacegroupNumber
(
std
::
string
spacegroup
,
SpacegroupName
type
)
{
if
(
spacegroup
==
"P 21 21 2 A"
)
spacegroup
=
"P 21 21 2 (a)"
;
else
if
(
spacegroup
.
empty
())
throw
std
::
runtime_error
(
"No spacegroup, cannot continue"
);
int
result
=
0
;
if
(
type
==
SpacegroupName
::
full
)
{
const
size_t
N
=
kNrOfSpaceGroups
;
int32_t
L
=
0
,
R
=
static_cast
<
int32_t
>
(
N
-
1
);
while
(
L
<=
R
)
{
int32_t
i
=
(
L
+
R
)
/
2
;
int
d
=
spacegroup
.
compare
(
kSpaceGroups
[
i
].
name
);
if
(
d
>
0
)
L
=
i
+
1
;
else
if
(
d
<
0
)
R
=
i
-
1
;
else
{
result
=
kSpaceGroups
[
i
].
nr
;
break
;
}
}
}
else
if
(
type
==
SpacegroupName
::
xHM
)
{
for
(
auto
&
sg
:
kSpaceGroups
)
{
if
(
sg
.
xHM
==
spacegroup
)
{
result
=
sg
.
nr
;
break
;
}
}
}
else
{
for
(
auto
&
sg
:
kSpaceGroups
)
{
if
(
sg
.
Hall
==
spacegroup
)
{
result
=
sg
.
nr
;
break
;
}
}
}
// not found, see if we can find a match based on xHM name
if
(
result
==
0
)
throw
std
::
runtime_error
(
"Spacegroup name "
+
spacegroup
+
" was not found in table"
);
return
result
;
}
}
}
test/pdb2cif-test.cpp
View file @
1f6b86d5
...
@@ -18,7 +18,6 @@ int main(int argc, char* argv[])
...
@@ -18,7 +18,6 @@ int main(int argc, char* argv[])
desc
.
add_options
()
desc
.
add_options
()
(
"input,i"
,
po
::
value
<
std
::
string
>
(),
"Input file"
)
(
"input,i"
,
po
::
value
<
std
::
string
>
(),
"Input file"
)
(
"help,h"
,
"Display help message"
)
(
"help,h"
,
"Display help message"
)
(
"version"
,
"Print version"
)
(
"verbose,v"
,
"Verbose output"
)
(
"verbose,v"
,
"Verbose output"
)
(
"debug,d"
,
po
::
value
<
int
>
(),
"Debug level (for even more verbose output)"
);
(
"debug,d"
,
po
::
value
<
int
>
(),
"Debug level (for even more verbose output)"
);
...
@@ -29,12 +28,6 @@ int main(int argc, char* argv[])
...
@@ -29,12 +28,6 @@ int main(int argc, char* argv[])
po
::
store
(
po
::
command_line_parser
(
argc
,
argv
).
options
(
desc
).
positional
(
p
).
run
(),
vm
);
po
::
store
(
po
::
command_line_parser
(
argc
,
argv
).
options
(
desc
).
positional
(
p
).
run
(),
vm
);
po
::
notify
(
vm
);
po
::
notify
(
vm
);
if
(
vm
.
count
(
"version"
))
{
std
::
cout
<<
argv
[
0
]
<<
" version "
PACKAGE_VERSION
<<
std
::
endl
;
exit
(
0
);
}
if
(
vm
.
count
(
"help"
)
or
vm
.
count
(
"input"
)
==
0
)
if
(
vm
.
count
(
"help"
)
or
vm
.
count
(
"input"
)
==
0
)
{
{
std
::
cerr
<<
desc
<<
std
::
endl
;
std
::
cerr
<<
desc
<<
std
::
endl
;
...
...
test/unit-test.cpp
View file @
1f6b86d5
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
// #include "cif++/DistanceMap.hpp"
// #include "cif++/DistanceMap.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/Cif++.hpp"
#include "cif++/BondMap.hpp"
#include "cif++/BondMap.hpp"
#include "cif++/CifValidator.hpp"
std
::
filesystem
::
path
gTestDir
=
std
::
filesystem
::
current_path
();
// filled in first test
std
::
filesystem
::
path
gTestDir
=
std
::
filesystem
::
current_path
();
// filled in first test
...
@@ -259,8 +260,10 @@ save__cat_2.desc
...
@@ -259,8 +260,10 @@ save__cat_2.desc
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
loadDictionary
(
is_dict
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -387,8 +390,10 @@ save__cat_1.c
...
@@ -387,8 +390,10 @@ save__cat_1.c
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
loadDictionary
(
is_dict
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -535,8 +540,10 @@ save__cat_2.desc
...
@@ -535,8 +540,10 @@ save__cat_2.desc
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
loadDictionary
(
is_dict
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -741,8 +748,10 @@ save__cat_2.parent_id3
...
@@ -741,8 +748,10 @@ save__cat_2.parent_id3
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
loadDictionary
(
is_dict
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -963,8 +972,10 @@ cat_2 3 cat_2:cat_1:3
...
@@ -963,8 +972,10 @@ cat_2 3 cat_2:cat_1:3
std
::
istream
is_dict
(
&
buffer
);
std
::
istream
is_dict
(
&
buffer
);
cif
::
Validator
validator
(
"test"
,
is_dict
);
cif
::
File
f
;
cif
::
File
f
;
f
.
loadDictionary
(
is_dict
);
f
.
setValidator
(
&
validator
);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
...
@@ -1389,9 +1400,10 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
...
@@ -1389,9 +1400,10 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
}
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
::
File
f
;
cif
::
File
f
;
f
.
loadDictionary
(
is_dict
);
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