Xorn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
manipulate.cc
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016 Roland Lutz
2 
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.
7 
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.
12 
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. */
16 
17 #include "internal.h"
18 #include <assert.h>
19 #include <algorithm>
20 
21 static const char *next_object_id = NULL;
22 
23 
24 static void set_object_data(xorn_revision_t rev, xorn_object_t ob,
25  xorn_obtype_t type, void const *data)
26 {
27  obstate *tmp = new obstate(type, data);
28  try {
29  obstate *&p = rev->obstates[ob];
30  if (p != NULL)
31  p->dec_refcnt();
32  p = tmp;
33  } catch (std::bad_alloc const &) {
34  tmp->dec_refcnt();
35  throw;
36  }
37 }
38 
61  xorn_obtype_t type, void const *data)
62 {
63  if (!rev->is_transient)
64  return NULL;
65 
66  xorn_object_t ob = (xorn_object_t)++next_object_id;
67  try {
68  rev->children[NULL].push_back(ob);
69  } catch (std::bad_alloc const &) {
70  return NULL;
71  }
72  try {
73  rev->parent[ob] = NULL;
74  } catch (std::bad_alloc const &) {
75  rev->children[NULL].pop_back();
76  return NULL;
77  }
78  try {
79  set_object_data(rev, ob, type, data);
80  } catch (std::bad_alloc const &) {
81  rev->parent.erase(rev->parent.find(ob));
82  rev->children[NULL].pop_back();
83  return NULL;
84  }
85  return ob;
86 }
87 
132  xorn_obtype_t type, void const *data)
133 {
134  if (!rev->is_transient)
135  return -1;
136 
137  if (type != xornsch_obtype_net &&
138  type != xornsch_obtype_component) {
139  std::map<xorn_object_t,
140  std::vector<xorn_object_t> >::const_iterator i
141  = rev->children.find(ob);
142  if (i != rev->children.end() && !i->second.empty())
143  return -1;
144  }
145 
146  std::map<xorn_object_t, xorn_object_t>::const_iterator i
147  = rev->parent.find(ob);
148  if (type != xornsch_obtype_text &&
149  i != rev->parent.end() && i->second != NULL)
150  return -1;
151 
152  bool add = i == rev->parent.end();
153  if (add) {
154  try {
155  rev->children[NULL].push_back(ob);
156  } catch (std::bad_alloc const &) {
157  return -1;
158  }
159  try {
160  rev->parent[ob] = NULL;
161  } catch (std::bad_alloc const &) {
162  rev->children[NULL].pop_back();
163  return -1;
164  }
165  }
166 
167  try {
168  set_object_data(rev, ob, type, data);
169  } catch (std::bad_alloc const &) {
170  if (add) {
171  rev->parent.erase(rev->parent.find(ob));
172  rev->children[NULL].pop_back();
173  }
174  return -1;
175  }
176  return 0;
177 }
178 
220  xorn_object_t attach_to, xorn_object_t insert_before)
221 {
222  if (!rev->is_transient)
223  return -1;
224 
225  if (attach_to != NULL) {
227  return -1;
228  xorn_obtype_t type = xorn_get_object_type(rev, attach_to);
229  if (type != xornsch_obtype_net &&
230  type != xornsch_obtype_component)
231  return -1;
232  } else if (!xorn_object_exists_in_revision(rev, ob))
233  return -1;
234 
235  xorn_object_t &parent = rev->parent[ob];
236  std::vector<xorn_object_t> &old_children = rev->children[parent];
237  std::vector<xorn_object_t> &new_children = rev->children[attach_to];
238 
239  std::vector<xorn_object_t>::iterator i = find(old_children.begin(),
240  old_children.end(), ob);
241  assert(i != old_children.end());
242  std::vector<xorn_object_t>::size_type pos = i - old_children.begin();
243 
244  /* Try adding the new entry first, removing the old one won't fail. */
245 
246  try {
247  if (insert_before == NULL)
248  new_children.push_back(ob);
249  else {
250  std::vector<xorn_object_t>::iterator j =
251  find(new_children.begin(),
252  new_children.end(), insert_before);
253  if (j == new_children.end())
254  return -1;
255  if (&new_children == &old_children && j <= i)
256  ++pos;
257  new_children.insert(j, ob);
258  }
259  } catch (std::bad_alloc const &) {
260  return -1;
261  }
262 
263  old_children.erase(old_children.begin() + pos);
264  parent = attach_to;
265  return 0;
266 }
267 
268 static void delete_object_but_leave_entry(
270 {
271  std::map<xorn_object_t, obstate *>::iterator i
272  = rev->obstates.find(ob);
273  i->second->dec_refcnt();
274  rev->obstates.erase(i);
275 
276  rev->parent.erase(rev->parent.find(ob));
277 
278  std::map<xorn_object_t, std::vector<xorn_object_t> >::iterator j
279  = rev->children.find(ob);
280 
281  if (j == rev->children.end())
282  return;
283 
284  for (std::vector<xorn_object_t>::const_iterator k = j->second.begin();
285  k != j->second.end(); ++k)
286  delete_object_but_leave_entry(rev, *k);
287 
288  rev->children.erase(j);
289 }
290 
302 {
303  if (!rev->is_transient)
304  return;
305 
306  std::map<xorn_object_t, xorn_object_t>::const_iterator i
307  = rev->parent.find(ob);
308  if (i == rev->parent.end())
309  return;
310  xorn_object_t parent = i->second;
311 
312  delete_object_but_leave_entry(rev, ob);
313 
314  std::vector<xorn_object_t> &children = rev->children[parent];
315  children.erase(find(children.begin(), children.end(), ob));
316 }
317 
329 {
330  if (!rev->is_transient)
331  return;
332 
333  for (std::set<xorn_object_t>::const_iterator i = sel->begin();
334  i != sel->end(); ++i)
335  xorn_delete_object(rev, *i);
336 }
337 
338 static xorn_object_t copy_object(
340  obstate *obstate, xorn_object_t attach_to,
341  std::vector<xorn_object_t> &copied)
342 {
343  xorn_object_t dest_ob = (xorn_object_t)++next_object_id;
344  dest->children[attach_to].push_back(dest_ob);
345  try {
346  dest->parent[dest_ob] = attach_to;
347  } catch (std::bad_alloc const &) {
348  dest->children[attach_to].pop_back();
349  throw;
350  }
351  try {
352  dest->obstates[dest_ob] = obstate;
353  obstate->inc_refcnt();
354  } catch (std::bad_alloc const &) {
355  dest->parent.erase(dest->parent.find(dest_ob));
356  dest->children[attach_to].pop_back();
357  throw;
358  }
359  try {
360  copied.push_back(dest_ob);
361  } catch (std::bad_alloc const &) {
362  xorn_delete_object(dest, dest_ob);
363  throw;
364  }
365 
366  std::map<xorn_object_t, std::vector<xorn_object_t> >::const_iterator i
367  = src->children.find(src_ob);
368 
369  if (i != src->children.end())
370  for (std::vector<xorn_object_t>::const_iterator j
371  = i->second.begin(); j != i->second.end(); ++j)
372  copy_object(dest, src, *j, src->obstates[*j],
373  dest_ob, copied);
374 
375  return dest_ob;
376 }
377 
394 {
395  if (!dest->is_transient)
396  return NULL;
397 
398  std::map<xorn_object_t, obstate *>::const_iterator i
399  = src->obstates.find(ob);
400 
401  if (i == src->obstates.end())
402  return NULL;
403 
404  std::vector<xorn_object_t> copied;
405 
406  try {
407  return copy_object(dest, src, ob, i->second, NULL, copied);
408  } catch (std::bad_alloc const &) {
409  for (std::vector<xorn_object_t>::const_iterator i
410  = copied.begin(); i != copied.end(); ++i)
411  xorn_delete_object(dest, *i);
412  return NULL;
413  }
414 }
415 
435 {
436  if (!dest->is_transient)
437  return NULL;
438 
439  xorn_selection_t rsel;
440  try {
441  rsel = new xorn_selection();
442  } catch (std::bad_alloc const &) {
443  return NULL;
444  }
445 
446  std::map<xorn_object_t, obstate *>::const_iterator i
447  = src->obstates.begin();
448  std::set<xorn_object_t>::const_iterator j = sel->begin();
449  std::vector<xorn_object_t> copied;
450 
451  while (i != src->obstates.end() && j != sel->end())
452  if (i->first < *j)
453  ++i;
454  else if (i->first > *j)
455  ++j;
456  else {
457  try {
458  xorn_object_t ob = copy_object(
459  dest, src, i->first, i->second, NULL, copied);
460  rsel->insert(ob);
461  } catch (std::bad_alloc const &) {
462  for (std::vector<xorn_object_t>::const_iterator i
463  = copied.begin(); i != copied.end(); ++i)
464  xorn_delete_object(dest, *i);
465  delete rsel;
466  return NULL;
467  }
468  ++i;
469  ++j;
470  }
471 
472  return rsel;
473 }
xorn_selection_t xorn_copy_objects(xorn_revision_t dest, xorn_revision_t src, xorn_selection_t sel)
Copy some objects to a transient revision.
Definition: manipulate.cc:433
struct xorn_revision * xorn_revision_t
Opaque type representing the contents of a file.
Definition: xornstorage.h:54
bool xorn_object_exists_in_revision(xorn_revision_t rev, xorn_object_t ob)
Return whether an object exists in a revision.
Definition: object.cc:25
xorn_obtype_t xorn_get_object_type(xorn_revision_t rev, xorn_object_t ob)
Get the type of an object in a given revision.
Definition: object.cc:35
struct xorn_selection * xorn_selection_t
Opaque type representing the identity of a set of objects.
Definition: xornstorage.h:56
int xorn_set_object_data(xorn_revision_t rev, xorn_object_t ob, xorn_obtype_t type, void const *data)
Set an object in a transient revision to the given object type and data.
Definition: manipulate.cc:131
void xorn_delete_selected_objects(xorn_revision_t rev, xorn_selection_t sel)
Delete some objects from a transient revision.
Definition: manipulate.cc:328
int xorn_relocate_object(xorn_revision_t rev, xorn_object_t ob, xorn_object_t attach_to, xorn_object_t insert_before)
Change the location of an object in the object structure of a transient revision. ...
Definition: manipulate.cc:219
struct xorn_object * xorn_object_t
Opaque type representing the identity of an object.
Definition: xornstorage.h:55
xorn_obtype_t
Object types, each corresponding to a data structure.
Definition: xornstorage.h:27
xorn_object_t xorn_add_object(xorn_revision_t rev, xorn_obtype_t type, void const *data)
Add a new object to a transient revision.
Definition: manipulate.cc:60
void xorn_delete_object(xorn_revision_t rev, xorn_object_t ob)
Delete an object from a transient revision.
Definition: manipulate.cc:301
xorn_object_t xorn_copy_object(xorn_revision_t dest, xorn_revision_t src, xorn_object_t ob)
Copy an object to a transient revision.
Definition: manipulate.cc:392