pack_graph.h
Go to the documentation of this file.
1 /*
2  @copyright Russell Standish 2000-2013
3  @author Russell Standish
4  This file is part of Classdesc
5 
6  Open source licensed under the MIT license. See LICENSE for details.
7 */
8 
13 #ifndef PACK_GRAPH_H
14 #define PACK_GRAPH_H
15 
16 #include <vector>
17 #include <map>
18 
19 #include <pack_base.h>
20 /*
21  treenodes should really be deprecated in favour of graphnodes
22 */
23 
24 namespace classdesc
25 {
27  template <class T>
28  void pack(pack_t& targ, const string& desc, is_treenode dum, const T* const& arg)
29  {
30  int valid=0;
31  if (arg==NULL)
32  pack(targ,desc,valid);
33  else
34  {
35  valid=1;
36  pack(targ,desc,valid);
37  pack(targ,desc,*arg);
38  }
39  }
40 
42 
43  template <class T>
44  void unpack(unpack_t& targ, const string& desc, is_treenode dum, T*& arg)
45  {
46  int valid;
47  unpack(targ,desc,valid);
48  if (valid)
49  {
50  // arg=new T;
51  // targ->alloced.push_back(arg);
52  targ.alloced.push_back(new classdesc::PtrStore<T>);
53  arg=static_cast<T*>(targ.alloced.back().data());
54  unpack(targ,desc,*arg);
55  }
56  }
57 
58  /*
59  pack up a graph (possibly containing cycles).
60  T must have the following members:
61  V& operator*() - dereference operator
62  operator bool() - returns true if valid, false otherwise
63  T& operator=(const T&) - assignable x=y => &*x==&*y
64  T() - construct an invalid object
65  T(const T&) - copyable
66 
67  Alloc<T>(T& x) - allocates a new object referenced by x
68 
69  V must be serialisable.
70  */
71 
73  template <class T> struct Alloc;
74  template <class T>
75  struct Alloc<T*>
76  {
77  void operator()(pack_t& buf, T*& x) {
78  buf.alloced.push_back(new PtrStore<T>);
79  x=static_cast<T*>(buf.alloced.back().data());
80  }
81  };
82 
83  template <class T>
84  inline void pack_graph(pack_t& buf, T& arg)
85  {
86  static std::map<T,int> graph_map;
87  static std::vector<T*> restart;
88  static unsigned recur_level=0;
89  int nought=0;
90 
91  if (recur_level==0)
92  pack(buf,string(),buf.recur_max);
93  recur_level++;
94 
95  if (recur_level==buf.recur_max)
96  restart.push_back(&arg); //save ref for restart
97  else if (!arg) //reference is invalid
98  pack(buf,string(),nought);
99  else if (graph_map.count(arg)==0)
100  {
101  int ID=graph_map.size()+1;
102  graph_map[arg]=ID;
103  pack(buf,string(),ID);
104  pack(buf,string(),*arg);
105  }
106  else
107  pack(buf,string(),graph_map[arg]);
108 
109  recur_level--;
110  if (recur_level==0) //process restarts
111  {
112  while (restart.size())
113  {
114  T& arg=*restart.back(); //we need to pop_back() before packing
115  restart.pop_back(); //in case further restarts are needed
116  pack_graph(buf,arg);
117  }
118  graph_map.clear();
119  }
120  }
121 
122  template <class T>
123  void unpack_graph(pack_t& buf, T& arg)
124  {
125  static std::map<int,T> graph_map;
126  static std::vector<T*> restart;
127  static unsigned recur_level=0;
128  int myid;
129  Alloc<T> alloc;
130 
131  if (recur_level==0)
132  unpack(buf,string(),buf.recur_max);
133  recur_level++;
134 
135  if (recur_level==buf.recur_max)
136  restart.push_back(&arg); //save ref for restart
137  else
138  {
139  unpack(buf,string(),myid);
140  if (myid==0)
141  arg=T(); //reset arg to invalid state
142  else if (graph_map.count(myid))
143  arg=graph_map[myid];
144  else
145  {
146  alloc(buf,arg);
147  graph_map[myid]=arg;
148  unpack(buf,string(),*arg);
149  }
150 
151  }
152  recur_level--;
153  if (recur_level==0) //process restarts
154  {
155  while (restart.size())
156  {
157  T& arg=*restart.back(); //we need to pop_back() before packing
158  restart.pop_back(); //in case further restarts are needed
159  unpack_graph(buf,arg);
160  }
161  graph_map.clear();
162  }
163 
164  }
165 
167 
169  template <class T>
170  inline void pack(pack_t& targ, const string& desc,is_graphnode dum,const T& arg)
171  {pack_graph(targ,arg);}
172 
174 
175  template <class T>
176  inline void unpack(pack_t& targ, const string& desc,is_graphnode dum,T& arg)
177  {unpack_graph(targ,arg);}
178 
179 }
180 #endif
unsigned myid
main window of application
Definition: pack_base.h:100
serialisation descriptor
Definition: classdesc.h:631
void pack(pack_t &targ, const string &desc, is_treenode dum, const T *const &arg)
serialise a tree (or DAG)
Definition: pack_graph.h:28
Definition: classdesc.h:630
Contains definitions related to classdesc functionality.
Definition: arrays.h:2514
Definition: pack_base.h:124
unsigned recur_max
recursion limit for pack_graph
Definition: pack_base.h:150
Definition: pack_graph.h:73
void unpack(unpack_t &targ, const string &desc, is_treenode dum, T *&arg)
unserialise a tree.
Definition: pack_graph.h:44