Skip to content

Commit f401d3f

Browse files
committed
Add way to load dictionary extensions along with main dictionary
1 parent fd43687 commit f401d3f

File tree

4 files changed

+63
-37
lines changed

4 files changed

+63
-37
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ cmake_minimum_required(VERSION 3.23)
2727
# set the project name
2828
project(
2929
libcifpp
30-
VERSION 7.0.8
30+
VERSION 7.0.9
3131
LANGUAGES CXX)
3232

3333
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

changelog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Version 7.0.9
2+
- Using cif::file::load_dictionary it is now possible to
3+
load a dictionary along with its extensions in one go.
4+
E.g. file.load_dictionary("mmcif_pdbx;dssp-extension")
5+
16
Version 7.0.8
27
- Fix PDB Remark 3 parser
38

include/cif++/file.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,17 @@ class file : public std::list<datablock>
176176
* @brief Attempt to load the named dictionary @a name and
177177
* create a validator based on it.
178178
*
179+
* Tje @a name can be the name of a single file, or even the
180+
* stem of that filename. So, e.g. mmcif_pdbx is valid.
181+
*
182+
* Since libcifpp can use extensions to validators, you
183+
* can add them to the name. So if you would like to add
184+
* the dssp extensions you would have to write:
185+
*
186+
* @code{cpp}
187+
* file.load_dictionary("mmcif_pdbx;dssp-extension");
188+
* @endcode
189+
*
179190
* @param name The name of the dictionary to load
180191
*/
181192
void load_dictionary(std::string_view name);

src/validate.cpp

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ int type_validator::compare(std::string_view a, std::string_view b) const
138138
ra = selected_charconv<double>::from_chars(a.data(), a.data() + a.length(), da);
139139
rb = selected_charconv<double>::from_chars(b.data(), b.data() + b.length(), db);
140140

141-
if (not (bool)ra.ec and not (bool)rb.ec)
141+
if (not(bool) ra.ec and not(bool) rb.ec)
142142
{
143143
auto d = da - db;
144144
if (std::abs(d) > std::numeric_limits<double>::epsilon())
@@ -232,7 +232,7 @@ bool item_validator::validate_value(std::string_view value, std::error_code &ec)
232232
ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
233233
}
234234

235-
return not (bool)ec;
235+
return not(bool) ec;
236236
}
237237

238238
// --------------------------------------------------------------------
@@ -408,9 +408,7 @@ void validator::report_error(std::error_code ec, bool fatal) const
408408
void validator::report_error(std::error_code ec, std::string_view category,
409409
std::string_view item, bool fatal) const
410410
{
411-
auto ex = item.empty() ?
412-
validation_exception(ec, category) :
413-
validation_exception(ec, category, item);
411+
auto ex = item.empty() ? validation_exception(ec, category) : validation_exception(ec, category, item);
414412

415413
if (m_strict or fatal)
416414
throw ex;
@@ -455,59 +453,71 @@ const validator &validator_factory::operator[](std::string_view dictionary_name)
455453
}
456454

457455
// not found, add it
458-
auto data = load_resource(dictionary_name);
459456

460-
if (not data and dictionary.extension().string() != ".dic")
461-
data = load_resource(dictionary.parent_path() / (dictionary.filename().string() + ".dic"));
457+
validator v(dictionary_name);
462458

463-
if (data)
464-
construct_validator(dictionary_name, *data);
465-
else
459+
for (bool first = true; auto part_name : cif::split(dictionary_name, ";", true))
466460
{
467-
std::error_code ec;
461+
auto data = load_resource(part_name);
462+
dictionary.assign(part_name.begin(), part_name.end());
468463

469-
// might be a compressed dictionary on disk
470-
std::filesystem::path p = dictionary;
471-
if (p.extension() == ".dic")
472-
p = p.parent_path() / (p.filename().string() + ".gz");
473-
else
474-
p = p.parent_path() / (p.filename().string() + ".dic.gz");
464+
if (not data and dictionary.extension().string() != ".dic")
465+
data = load_resource(dictionary.parent_path() / (dictionary.filename().string() + ".dic"));
475466

476-
#if defined(CACHE_DIR) or defined(DATA_DIR)
477-
if (not std::filesystem::exists(p, ec) or ec)
467+
if (not data)
478468
{
479-
for (const char *dir : {
469+
std::error_code ec;
470+
471+
// might be a compressed dictionary on disk
472+
std::filesystem::path p = dictionary;
473+
if (p.extension() == ".dic")
474+
p = p.parent_path() / (p.filename().string() + ".gz");
475+
else
476+
p = p.parent_path() / (p.filename().string() + ".dic.gz");
477+
478+
#if defined(CACHE_DIR) or defined(DATA_DIR)
479+
if (not std::filesystem::exists(p, ec) or ec)
480+
{
481+
for (const char *dir : {
480482
# if defined(CACHE_DIR)
481-
CACHE_DIR,
483+
CACHE_DIR,
482484
# endif
483485
# if defined(DATA_DIR)
484486
DATA_DIR
485487
# endif
486-
})
487-
{
488-
auto p2 = std::filesystem::path(dir) / p;
489-
if (std::filesystem::exists(p2, ec) and not ec)
488+
})
490489
{
491-
swap(p, p2);
492-
break;
490+
auto p2 = std::filesystem::path(dir) / p;
491+
if (std::filesystem::exists(p2, ec) and not ec)
492+
{
493+
swap(p, p2);
494+
break;
495+
}
493496
}
494497
}
495-
}
496498
#endif
497499

498-
if (std::filesystem::exists(p, ec) and not ec)
499-
{
500-
gzio::ifstream in(p);
500+
if (std::filesystem::exists(p, ec) and not ec)
501+
{
502+
auto in = std::make_unique<gzio::ifstream>(p);
501503

502-
if (not in.is_open())
503-
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
504+
if (not in->is_open())
505+
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
504506

505-
construct_validator(dictionary_name, in);
507+
data.reset(in.release());
508+
}
509+
else
510+
throw std::runtime_error("Dictionary not found or defined (" + dictionary.string() + ")");
506511
}
512+
513+
if (std::exchange(first, false))
514+
v = parse_dictionary(part_name, *data);
507515
else
508-
throw std::runtime_error("Dictionary not found or defined (" + dictionary.string() + ")");
516+
extend_dictionary(v, *data);
509517
}
510518

519+
m_validators.emplace_back(std::move(v));
520+
511521
return m_validators.back();
512522
}
513523
catch (const std::exception &ex)

0 commit comments

Comments
 (0)