Xmipp  v3.23.11-Nereus
condition.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++/category.hpp"
28 #include "cif++/condition.hpp"
29 #include "cif++/file.hpp"
30 
31 namespace cif
32 {
33 
34 iset get_category_fields(const category &cat)
35 {
36  return cat.key_fields();
37 }
38 
39 uint16_t get_column_ix(const category &cat, std::string_view col)
40 {
41  return cat.get_column_ix(col);
42 }
43 
44 bool is_column_type_uchar(const category &cat, std::string_view col)
45 {
46  bool result = false;
47 
48  auto cv = cat.get_cat_validator();
49  if (cv)
50  {
51  auto iv = cv->get_validator_for_item(col);
52  if (iv != nullptr and iv->m_type != nullptr)
53  {
54  auto type = iv->m_type;
55  result = type->m_primitive_type == DDL_PrimitiveType::UChar;
56  }
57  }
58 
59  return result;
60 }
61 
62 namespace detail
63 {
64 
65  condition_impl *key_equals_condition_impl::prepare(const category &c)
66  {
67  m_item_ix = c.get_column_ix(m_item_tag);
68  m_icase = is_column_type_uchar(c, m_item_tag);
69 
70  if (c.get_cat_validator() != nullptr and
71  c.key_field_indices().size() == 1)
72  {
73  const auto field_keys = c.key_field_indices();
74  if (field_keys.find(m_item_ix) != field_keys.end()) {
75  m_single_hit = c[{ { m_item_tag, m_value } }];
76  }
77  }
78 
79  return this;
80  }
81 
82  bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
83  {
84  bool result = true;
85 
86  for (auto s = b; s != e; ++s)
87  {
88  auto &cs = (*s)->m_sub;
89 
90  if (find_if(cs.begin(), cs.end(), [c](const condition_impl *i) { return i->equals(c); }) == cs.end())
91  {
92  result = false;
93  break;
94  }
95  }
96 
97  return result;
98  }
99 
100  condition_impl *and_condition_impl::combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc)
101  {
102  and_condition_impl *and_result = nullptr;
103 
104  auto first = subs.front();
105  auto &fc = first->m_sub;
106 
107  for (auto c : fc)
108  {
109  if (not found_in_range(c, subs.begin() + 1, subs.end()))
110  continue;
111 
112  if (and_result == nullptr)
113  and_result = new and_condition_impl();
114 
115  and_result->m_sub.push_back(c);
116  fc.erase(remove(fc.begin(), fc.end(), c), fc.end());
117 
118  for (auto sub : subs)
119  {
120  auto &ssub = sub->m_sub;
121 
122  for (auto sc : ssub)
123  {
124  if (not sc->equals(c))
125  continue;
126 
127  ssub.erase(remove(ssub.begin(), ssub.end(), sc), ssub.end());
128  delete sc;
129  break;
130  }
131  }
132  }
133 
134  if (and_result != nullptr)
135  {
136  and_result->m_sub.push_back(oc);
137  return and_result;
138  }
139 
140  return oc;
141  }
142 
143  condition_impl *or_condition_impl::prepare(const category &c)
144  {
145  std::vector<and_condition_impl *> and_conditions;
146 
147  for (auto &sub : m_sub)
148  {
149  sub = sub->prepare(c);
150  if (typeid(*sub) == typeid(and_condition_impl))
151  and_conditions.push_back(static_cast<and_condition_impl *>(sub));
152  }
153 
154  if (and_conditions.size() == m_sub.size())
155  return and_condition_impl::combine_equal(and_conditions, this);
156 
157  return this;
158  }
159 
160 } // namespace detail
161 
162 void condition::prepare(const category &c)
163 {
164  if (m_impl)
165  m_impl = m_impl->prepare(c);
166 
167  m_prepared = true;
168 }
169 
170 } // namespace cif
bool found_in_range(condition_impl *c, std::vector< and_condition_impl *>::iterator b, std::vector< and_condition_impl *>::iterator e)
Definition: condition.cpp:82
bool is_column_type_uchar(const category &cat, std::string_view col)
Definition: condition.cpp:44
doublereal * c
uint16_t get_column_ix(const category &cat, std::string_view col)
Definition: condition.cpp:39
#define i
glob_log first
doublereal * b
struct _constraint * cs
viol type
iset get_category_fields(const category &cat)
Definition: condition.cpp:34