Merge fixes from branch 'xorn'
[geda-gaf.git] / xorn / src / storage / selection.cc
blob257e1b9a4b8a723222ac310dab34446025f99dcc
1 /* Copyright (C) 2013-2020 Roland Lutz
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software Foundation,
15 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17 #include "internal.h"
18 #include "key_iterator.h"
19 #include <algorithm>
22 /** \brief Create an empty selection. */
24 xorn_selection_t xorn_select_none()
26 try {
27 return new xorn_selection();
28 } catch (std::bad_alloc const &) {
29 return NULL;
33 /** \brief Create a selection containing a single object. */
35 xorn_selection_t xorn_select_object(xorn_object_t ob)
37 xorn_selection_t rsel;
38 try {
39 rsel = new xorn_selection();
40 } catch (std::bad_alloc const &) {
41 return NULL;
43 try {
44 rsel->insert(ob);
45 } catch (std::bad_alloc const &) {
46 delete rsel;
47 return NULL;
49 return rsel;
52 /** \brief Create a selection containing all objects in a revision
53 * attached to a given object.
55 * The object may be \c NULL, in which case the selection contains all
56 * objects which are *not* attached.
58 * \return Returns the new selection, or \c NULL if \a ob does not exist
59 * in \a rev or there is not enough memory. */
61 xorn_selection_t xorn_select_attached_to(xorn_revision_t rev, xorn_object_t ob)
63 if (ob != NULL && rev->obstates.find(ob) == rev->obstates.end())
64 return NULL;
66 xorn_selection_t rsel;
67 try {
68 rsel = new xorn_selection();
69 } catch (std::bad_alloc const &) {
70 return NULL;
73 std::map<xorn_object_t, std::vector<xorn_object_t> >::const_iterator i
74 = rev->children.find(ob);
75 if (i == rev->children.end())
76 return rsel;
78 try {
79 copy(i->second.begin(), i->second.end(),
80 inserter(*rsel, rsel->begin()));
81 } catch (std::bad_alloc const &) {
82 delete rsel;
83 return NULL;
85 return rsel;
88 /** \brief Create a selection containing all objects in a revision. */
90 xorn_selection_t xorn_select_all(xorn_revision_t rev)
92 xorn_selection_t rsel;
93 try {
94 rsel = new xorn_selection();
95 } catch (std::bad_alloc const &) {
96 return NULL;
98 try {
99 copy(iterate_keys(rev->obstates.begin()),
100 iterate_keys(rev->obstates.end()),
101 inserter(*rsel, rsel->begin()));
102 } catch (std::bad_alloc const &) {
103 delete rsel;
104 return NULL;
106 return rsel;
109 /** \brief Create a selection containing all objects in a revision
110 * except those in a given selection. */
112 xorn_selection_t xorn_select_all_except(
113 xorn_revision_t rev, xorn_selection_t sel)
115 xorn_selection_t rsel;
116 try {
117 rsel = new xorn_selection();
118 } catch (std::bad_alloc const &) {
119 return NULL;
121 try {
122 set_difference(iterate_keys(rev->obstates.begin()),
123 iterate_keys(rev->obstates.end()),
124 sel->begin(), sel->end(),
125 inserter(*rsel, rsel->begin()));
126 } catch (std::bad_alloc const &) {
127 delete rsel;
128 return NULL;
130 return rsel;
133 /** \brief Create a selection which contains all the objects in an
134 * existing selection plus a given object. */
136 xorn_selection_t xorn_select_including(xorn_selection_t sel, xorn_object_t ob)
138 xorn_selection_t rsel;
139 try {
140 rsel = new xorn_selection(*sel);
141 } catch (std::bad_alloc const &) {
142 return NULL;
144 try {
145 rsel->insert(ob);
146 } catch (std::bad_alloc const &) {
147 delete rsel;
148 return NULL;
150 return rsel;
153 /** \brief Create a selection which contains all the objects in an
154 * existing selection minus a given object. */
156 xorn_selection_t xorn_select_excluding(xorn_selection_t sel, xorn_object_t ob)
158 xorn_selection_t rsel;
159 try {
160 rsel = new xorn_selection(*sel);
161 } catch (std::bad_alloc const &) {
162 return NULL;
164 try {
165 xorn_selection::const_iterator i = rsel->find(ob);
166 if (i != rsel->end())
167 rsel->erase(i);
168 } catch (std::bad_alloc const &) {
169 delete rsel;
170 return NULL;
172 return rsel;
175 /** \brief Create a selection containing the objects in either given
176 * selection. */
178 xorn_selection_t xorn_select_union(
179 xorn_selection_t sel0, xorn_selection_t sel1)
181 xorn_selection_t rsel;
182 try {
183 rsel = new xorn_selection();
184 } catch (std::bad_alloc const &) {
185 return NULL;
187 try {
188 set_union(sel0->begin(), sel0->end(),
189 sel1->begin(), sel1->end(),
190 inserter(*rsel, rsel->begin()));
191 } catch (std::bad_alloc const &) {
192 delete rsel;
193 return NULL;
195 return rsel;
198 /** \brief Create a selection containing the objects in both given
199 * selections. */
201 xorn_selection_t xorn_select_intersection(
202 xorn_selection_t sel0, xorn_selection_t sel1)
204 xorn_selection_t rsel;
205 try {
206 rsel = new xorn_selection();
207 } catch (std::bad_alloc const &) {
208 return NULL;
210 try {
211 set_intersection(sel0->begin(), sel0->end(),
212 sel1->begin(), sel1->end(),
213 inserter(*rsel, rsel->begin()));
214 } catch (std::bad_alloc const &) {
215 delete rsel;
216 return NULL;
218 return rsel;
221 /** \brief Create a selection containing the objects contained in one
222 * given selection, but not the other. */
224 xorn_selection_t xorn_select_difference(
225 xorn_selection_t sel0, xorn_selection_t sel1)
227 xorn_selection_t rsel;
228 try {
229 rsel = new xorn_selection();
230 } catch (std::bad_alloc const &) {
231 return NULL;
233 try {
234 set_difference(sel0->begin(), sel0->end(),
235 sel1->begin(), sel1->end(),
236 inserter(*rsel, rsel->begin()));
237 } catch (std::bad_alloc const &) {
238 delete rsel;
239 return NULL;
241 return rsel;
244 /** \brief Return whether a selection is empty in a given revision. */
246 bool xorn_selection_is_empty(xorn_revision_t rev, xorn_selection_t sel)
248 std::map<xorn_object_t, obstate *>::const_iterator i
249 = rev->obstates.begin();
250 std::set<xorn_object_t>::const_iterator j = sel->begin();
252 while (i != rev->obstates.end() && j != sel->end())
253 if (i->first < *j)
254 ++i;
255 else if (i->first > *j)
256 ++j;
257 else
258 return false;
260 return true;
263 /** \brief Return whether an object exists in a revision and is
264 * selected in a selection. */
266 bool xorn_object_is_selected(
267 xorn_revision_t rev, xorn_selection_t sel, xorn_object_t ob)
269 return rev->obstates.find(ob) != rev->obstates.end() &&
270 sel->find(ob) != sel->end();
273 /** \brief Free the memory used for storing a selection.
275 * \warning \a sel must not be passed to any Xorn function again. */
277 void xorn_free_selection(xorn_selection_t sel)
279 delete sel;