Xmipp  v3.23.11-Nereus
file.cpp
Go to the documentation of this file.
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "cif++/file.hpp"
28 #include "cif++/gzio.hpp"
29 
30 namespace cif
31 {
32 
33 // --------------------------------------------------------------------
34 void file::set_validator(const validator *v)
35 {
36  m_validator = v;
37  for (auto &db : *this)
38  db.set_validator(v);
39 }
40 
41 bool file::is_valid() const
42 {
43  if (m_validator == nullptr)
44  std::runtime_error("No validator loaded explicitly, cannot continue");
45 
46  bool result = true;
47  for (auto &d : *this)
48  result = d.is_valid() and result;
49 
50  if (result)
51  result = validate_links();
52 
53  return result;
54 }
55 
56 bool file::is_valid()
57 {
58  if (m_validator == nullptr)
59  {
60  if (VERBOSE > 0)
61  std::cerr << "No dictionary loaded explicitly, loading default" << std::endl;
62 
63  load_dictionary();
64  }
65 
66  bool result = not empty();
67 
68  for (auto &d : *this)
69  result = d.is_valid() and result;
70 
71  if (result)
72  result = validate_links();
73 
74  return result;
75 }
76 
77 bool file::validate_links() const
78 {
79  if (m_validator == nullptr)
80  std::runtime_error("No validator loaded explicitly, cannot continue");
81 
82  bool result = true;
83 
84  for (auto &db : *this)
85  result = db.validate_links() and result;
86 
87  return result;
88 }
89 
90 void file::load_dictionary()
91 {
92  if (not empty())
93  {
94  auto *audit_conform = front().get("audit_conform");
95  if (audit_conform and not audit_conform->empty())
96  {
97  std::string name = audit_conform->front().get<std::string>("dict_name");
98 
99  if (name == "mmcif_pdbx_v50")
100  name = "mmcif_pdbx.dic"; // we had a bug here in libcifpp...
101 
102  if (not name.empty())
103  {
104  try
105  {
106  load_dictionary(name);
107  }
108  catch (const std::exception &ex)
109  {
110  if (VERBOSE)
111  std::cerr << "Failed to load dictionary " << std::quoted(name) << ": " << ex.what() << std::endl;
112  }
113  }
114  }
115  }
116 
117  // if (not m_validator)
118  // load_dictionary("mmcif_pdbx.dic"); // TODO: maybe incorrect? Perhaps improve?
119 }
120 
121 void file::load_dictionary(std::string_view name)
122 {
123  set_validator(&validator_factory::instance()[name]);
124 }
125 
126 bool file::contains(std::string_view name) const
127 {
128  return std::find_if(begin(), end(), [name](const datablock &db) { return iequals(db.name(), name); }) != end();
129 }
130 
131 datablock &file::operator[](std::string_view name)
132 {
133  auto i = std::find_if(begin(), end(), [name](const datablock &c)
134  { return iequals(c.name(), name); });
135 
136  if (i != end())
137  return *i;
138 
139  emplace_back(name);
140  return back();
141 }
142 
143 const datablock &file::operator[](std::string_view name) const
144 {
145  static const datablock s_empty;
146  auto i = std::find_if(begin(), end(), [name](const datablock &c)
147  { return iequals(c.name(), name); });
148  return i == end() ? s_empty : *i;
149 }
150 
151 std::tuple<file::iterator, bool> file::emplace(std::string_view name)
152 {
153  bool is_new = true;
154 
155  auto i = begin();
156  while (i != end())
157  {
158  if (iequals(name, i->name()))
159  {
160  is_new = false;
161 
162  if (i != begin())
163  {
164  auto n = std::next(i);
165  splice(begin(), *this, i, n);
166  }
167 
168  break;
169  }
170 
171  ++i;
172  }
173 
174  if (is_new)
175  {
176  auto &db = emplace_front(name);
177  db.set_validator(m_validator);
178  }
179 
180  return std::make_tuple(begin(), is_new);
181 }
182 
183 void file::load(const std::filesystem::path &p)
184 {
185  try
186  {
187  gzio::ifstream in(p);
188  if (not in.is_open())
189  throw std::runtime_error("Could not open file " + p.string());
190 
191  load(in);
192  }
193  catch (const std::exception &)
194  {
195  throw_with_nested(std::runtime_error("Error reading file " + p.string()));
196  }
197 }
198 
199 void file::load(std::istream &is)
200 {
201  auto saved = m_validator;
202  set_validator(nullptr);
203 
204  parser p(is, *this);
205  p.parse_file();
206 
207  if (saved != nullptr)
208  set_validator(saved);
209  else
210  load_dictionary();
211 }
212 
213 void file::save(const std::filesystem::path &p) const
214 {
215  gzio::ofstream outFile(p);
216  save(outFile);
217 }
218 
219 void file::save(std::ostream &os) const
220 {
221  // if (not is_valid())
222  // std::cout << "File is not valid!" << std::endl;
223 
224  for (auto &db : *this)
225  db.write(os);
226 }
227 
228 } // namespace cif
doublereal * c
bool iequals(std::string_view a, std::string_view b)
Definition: text.cpp:59
#define i
doublereal * d
int in
int VERBOSE
Definition: utilities.cpp:58
basic_istream< char, std::char_traits< char > > istream
Definition: utilities.cpp:815
int * n