Tulip  5.5.0
Large graphs analysis and drawing
DataSet.h
1 /*
2  *
3  * This file is part of Tulip (http://tulip.labri.fr)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 
20 #ifndef _TULIPREFLECT
21 #define _TULIPREFLECT
22 
23 #include <unordered_map>
24 #include <tulip/tulipconf.h>
25 #include <tulip/StlIterator.h>
26 
27 #include <string>
28 #include <sstream>
29 #include <typeinfo>
30 #include <list>
31 
32 namespace tlp {
33 
34 class Graph;
35 
36 ///@cond DOXYGEN_HIDDEN
37 // basic interface to embed a data of any type
38 struct TLP_SCOPE DataMem {
39  DataMem() {}
40  virtual ~DataMem() {}
41 };
42 
43 // basic template to embed a value of a known type
44 template <typename TYPE>
45 struct TypedValueContainer : public DataMem {
46  TYPE value;
47  TypedValueContainer() {}
48  TypedValueContainer(const TYPE &val) : value(val) {}
49  ~TypedValueContainer() override {}
50 };
51 ///@endcond
52 
53 /**
54  * @ingroup Structures
55  * @brief Describes a value of any type
56  */
57 struct TLP_SCOPE DataType : public DataMem {
58  DataType() {}
59  DataType(void *value) : value(value) {}
60 
61  /**
62  * @return A deep copy of the stored value.
63  */
64  virtual DataType *clone() const = 0;
65 
66  /**
67  * @return The C++ typename of the stored element
68  */
69  virtual std::string getTypeName() const = 0;
70 
71  /**
72  * @brief indicates if it is a Tulip property
73  */
74  static bool isTulipProperty(const std::string &typeName);
75 
76  /**
77  * @brief indicates if it is a Tulip property
78  */
79  bool isTulipProperty() const {
80  return isTulipProperty(getTypeName());
81  }
82 
83  /**
84  * @brief The actual pointer to the element's data
85  */
86  void *value;
87 };
88 
89 ///@cond DOXYGEN_HIDDEN
90 // template class to embed value of known type
91 template <typename T>
92 struct TypedData : public DataType {
93  TypedData(void *value) : DataType(value) {}
94  ~TypedData() override {
95  delete static_cast<T *>(value);
96  }
97  DataType *clone() const override {
98  return new TypedData<T>(new T(getValue()));
99  }
100 
101  std::string getTypeName() const override {
102  return std::string(typeid(T).name());
103  }
104 
105  const T &getValue() const {
106  return *(static_cast<const T *>(this->value));
107  }
108 };
109 
110 // forward declaration of DataSet
111 class DataSet;
112 
113 // Basic class for serialization of DataType embedded value
114 struct DataTypeSerializer {
115  // the readable type name the serializer is designed for
116  std::string outputTypeName;
117  // the current graph
118  Graph *graph;
119  DataTypeSerializer(const std::string &otn) : outputTypeName(otn), graph(nullptr) {}
120  virtual ~DataTypeSerializer() {}
121  // set the current graph if needed
122  void setGraph(Graph *g) {
123  graph = g;
124  }
125  // return a copy of this
126  virtual DataTypeSerializer *clone() const = 0;
127  // write the DataType embedded value into the output stream
128  virtual void writeData(std::ostream &os, const DataType *data) = 0;
129  // return the DataType embedded value as a std::string
130  virtual std::string toString(const DataType *data) {
131  std::stringstream ss;
132  writeData(ss, data);
133  return ss.str();
134  }
135  // build a DataType embedding value read from input stream
136  virtual DataType *readData(std::istream &is) = 0;
137  // set a value into a DataSet
138  virtual bool setData(DataSet &ds, const std::string &prop, const std::string &value) = 0;
139 };
140 
141 // a template class designs to simplify the developer's work
142 // when writing a serializer class
143 template <typename T>
144 struct TypedDataSerializer : public DataTypeSerializer {
145  TypedDataSerializer(const std::string &otn) : DataTypeSerializer(otn) {}
146  // declare new serialization virtual functions
147  virtual void write(std::ostream &os, const T &value) = 0;
148  // return true if the read of value succeeded, false if not
149  virtual bool read(std::istream &is, T &value) = 0;
150  // define virtually inherited functions using the previous ones
151  void writeData(std::ostream &os, const DataType *data) override {
152  write(os, *(static_cast<T *>(data->value)));
153  }
154  DataType *readData(std::istream &is) override {
155  T value;
156  bool ok = read(is, value);
157 
158  if (ok)
159  return new TypedData<T>(new T(value));
160 
161  return nullptr;
162  }
163  // set a value into a DataSet
164  bool setData(DataSet &ds, const std::string &prop, const std::string &value) override = 0;
165 };
166 
167 // This class is there to ensure the destruction of DataTypeSerializer objects
168 // when program ends
169 class DataTypeSerializerContainer {
170 
171 public:
172  ~DataTypeSerializerContainer() {
173  std::unordered_map<std::string, DataTypeSerializer *>::iterator it = tnTodts.begin();
174 
175  for (; it != tnTodts.end(); ++it) {
176  delete it->second;
177  }
178  }
179 
180  std::unordered_map<std::string, DataTypeSerializer *> tnTodts;
181  std::unordered_map<std::string, DataTypeSerializer *> otnTodts;
182 };
183 ///@endcond
184 
185 /**
186  * @ingroup Structures
187  * @brief A container that can store data from any type.
188  *
189  * The DataSet aggregate data of various types into a single structure and map each value to a key
190  *(std::string) describing its name.
191  * DataSet is mainly used in plugins. When creating a plugin, one can add input parameters (using
192  *tlp::WithParameter methods) and retrieve them from the dataSet member variable once they have been
193  *set by the user.
194  **/
195 class TLP_SCOPE DataSet {
196  // Internal list of key-value pairs.
197  std::list<std::pair<std::string, DataType *>> data;
198  /* management of data serialization
199  two hashmap to retrieve data serializer from their
200  type names and output type names
201  tnTodsts => typename to data type serializer
202  otnTodts => output type name to data type serializer */
203  static DataTypeSerializerContainer serializerContainer;
204  static void registerDataTypeSerializer(const std::string &typeName, DataTypeSerializer *dts);
205 
206 public:
207  DataSet() {}
208  DataSet(const DataSet &set);
209  ~DataSet();
210 
211  /**
212  * @brief Performs a deep copy of a DataSet into another
213  */
214  DataSet &operator=(const DataSet &set);
215 
216  /**
217  * @brief Returns the stored value associated with the given key.
218  * The stored value is a copy of the original value that was set.
219  * If there is no value associated with the given key, the input value is left untouched.
220  *
221  * @param key The key with which the data we want to retrieve is associated.
222  * @param value A variable which will be overwritten with the value to retrieve.
223  * @return bool Whether there is a value associated with given key or not.
224  **/
225  template <typename T>
226  bool get(const std::string &key, T &value) const;
227 
228  /**
229  * @brief Returns the stored value, and deletes the stored copy.
230  * If no value is found, nothing is deleted.
231  *
232  * @param key The key with which the data we want to retrieve is associated.
233  * @param value A variable which will be overwritten with the value to retrieve.
234  * @return bool Whether there is a value associated with given key or not.
235  **/
236  template <typename T>
237  bool getAndFree(const std::string &key, T &value);
238 
239  /**
240  * @brief Stores a copy of the given param, associated with the key.
241  * The value must have a well-formed copy constructor.
242  *
243  * @param key The key which can be used to retrieve the data.
244  * @param value The data to store.
245  * @return void
246  **/
247  template <typename T>
248  void set(const std::string &key, const T &value);
249 
250  /**
251  * @brief Returns the mangled name of a type.
252  *.
253  * @return std::string the mangled name (typeid(T).name())
254  **/
255  template <typename T>
256  std::string getTypeName() const {
257  return std::string(typeid(T).name());
258  }
259 
260  /**
261  * @brief Registers a serializer for a known type
262  *
263  * Serializers are used to write/read from std::ostream objects when saving DataSet instances.
264  */
265  template <typename T>
266  static void registerDataTypeSerializer(const DataTypeSerializer &serializer) {
267  registerDataTypeSerializer(std::string(typeid(T).name()), serializer.clone());
268  }
269 
270  /**
271  * @brief write an embedded value
272  */
273  void writeData(std::ostream &os, const std::string &prop, const DataType *dt) const;
274 
275  /**
276  * @brief Serializes a DataSet into a stream
277  */
278  static void write(std::ostream &os, const DataSet &ds);
279 
280  /**
281  * @brief Read a value and stores it into the specified type
282  */
283  bool readData(std::istream &is, const std::string &prop, const std::string &outputTypeName);
284 
285  /**
286  * @brief Reads a stream and stores its contents into a DataSet
287  */
288  static bool read(std::istream &is, DataSet &ds);
289 
290  /**
291  * @param str the name of the member to look for
292  * @return true if str exists into the DataSet.
293  */
294  bool exists(const std::string &str) const;
295 
296  /**
297  * @param str the name of the member to look for
298  * @return the mangled name of the type if str exists into the DataSet. An empty string if not.
299  */
300  std::string getTypeName(const std::string &str) const;
301 
302  /**
303  * @brief Removes an element from the DataSet
304  * @param str the name of the element to remove
305  */
306  void remove(const std::string &str);
307 
308  /**
309  * @param str The name of the element to retrieve
310  * @return A untyped value for a given element name. nullptr if the element does not exist
311  */
312  DataType *getData(const std::string &str) const;
313 
314  /**
315  * @brief Set from an untyped value
316  */
317  void setData(const std::string &str, const DataType *value);
318 
319  /**
320  * @return An iterator over stored values as a std::pair name => untyped value
321  */
323 
324  /**
325  * @brief Returns the number of registered values
326  */
327  unsigned int size() const;
328 
329  /**
330  * @brief Indicates whether the set is empty of not
331  */
332  bool empty() const;
333 
334  /**
335  * @return the data type serializer associated to the given typename. nullptr if no serializer is
336  * found
337  */
338  static DataTypeSerializer *typenameToSerializer(const std::string &name);
339 
340  /**
341  * @return A std::string representation of a DataSet
342  */
343  std::string toString() const;
344 };
345 } // namespace tlp
346 
347 #include "cxx/DataSet.cxx"
348 
349 #endif
tlp::DataType
Describes a value of any type.
Definition: DataSet.h:57
tlp::DataSet::getTypeName
std::string getTypeName() const
Returns the mangled name of a type.
Definition: DataSet.h:256
tlp::DataSet::registerDataTypeSerializer
static void registerDataTypeSerializer(const DataTypeSerializer &serializer)
Registers a serializer for a known type.
Definition: DataSet.h:266
tlp::DataType::isTulipProperty
bool isTulipProperty() const
indicates if it is a Tulip property
Definition: DataSet.h:79
tlp::Iterator
Interface for Tulip iterators. Allows basic iteration operations only.
Definition: Graph.h:43
tlp::DataSet
A container that can store data from any type.
Definition: DataSet.h:195
tlp
Definition: AbstractProperty.h:34
tlp::DataType::value
void * value
The actual pointer to the element's data.
Definition: DataSet.h:86