Tulip  6.0.0
Large graphs analysis and drawing
DataSet.h
1 /*
2  *
3  * This file is part of Tulip (https://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 <tulip/tulipconf.h>
24 #include <tulip/tuliphash.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  tlp_hash_map<std::string, DataTypeSerializer *>::iterator it = tnTodts.begin();
174 
175  for (; it != tnTodts.end(); ++it) {
176  delete it->second;
177  }
178  }
179 
180  tlp_hash_map<std::string, DataTypeSerializer *> tnTodts;
181  tlp_hash_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 
199  // list of deprecated properties
200  std::list<std::pair<std::string, std::string>> *deprecated;
201  // add a deprecated property name for compatibility management
202  void addDeprecated(const std::string &oldName, const std::string &usedName);
203  // return the property to be used
204  const std::string &getUsedName(const std::string &oldName) const;
205 
206  /* management of data serialization
207  two hashmap to retrieve data serializer from their
208  type names and output type names
209  tnTodsts => typename to data type serializer
210  otnTodts => output type name to data type serializer */
211  static DataTypeSerializerContainer serializerContainer;
212  static void registerDataTypeSerializer(const std::string &typeName, DataTypeSerializer *dts);
213 
214 public:
215  DataSet() : deprecated(nullptr) {}
216  DataSet(const DataSet &set);
217  ~DataSet();
218 
219  /**
220  * @brief Performs a deep copy of a DataSet into another
221  */
222  DataSet &operator=(const DataSet &set);
223 
224  /**
225  * @brief Returns the stored value associated with the given key.
226  * The stored value is a copy of the original value that was set.
227  * If there is no value associated with the given key, the input value is left untouched.
228  *
229  * @param key The key with which the data we want to retrieve is associated.
230  * @param value A variable which will be overwritten with the value to retrieve.
231  * @return bool Whether there is a value associated with given key or not.
232  **/
233  template <typename T>
234  bool get(const std::string &key, T &value) const;
235 
236  /**
237  * @brief Returns the stored value associated with the given key or the deprecated version of the
238  *key The stored value is a copy of the original value that was set. If there is no value
239  *associated with both keys, the input value is left untouched.
240  *
241  * @param key The key with which the data we want to retrieve is associated.
242  * @param oldKey The deprecated version of the key.
243  * @param value A variable which will be overwritten with the value to retrieve.
244  * @return bool Whether there is a value associated with one of the keys or not.
245  **/
246  template <typename T>
247  bool getDeprecated(const std::string &key, const std::string &oldKey, T &value) const;
248 
249  /**
250  * @brief Returns the stored value, and deletes the stored copy.
251  * If no value is found, nothing is deleted.
252  *
253  * @param key The key with which the data we want to retrieve is associated.
254  * @param value A variable which will be overwritten with the value to retrieve.
255  * @return bool Whether there is a value associated with given key or not.
256  **/
257  template <typename T>
258  bool getAndFree(const std::string &key, T &value);
259 
260  /**
261  * @brief Stores a copy of the given param, associated with the key.
262  * The value must have a well-formed copy constructor.
263  *
264  * @param key The key which can be used to retrieve the data.
265  * @param value The data to store.
266  * @return void
267  **/
268  template <typename T>
269  void set(const std::string &key, const T &value);
270 
271  /**
272  * @brief Stores a copy of the given param, associated with a key and a deprected version of the
273  *key The value must have a well-formed copy constructor.
274  *
275  * @param key The key which can be used to retrieve the data.
276  * @param oldKey The deprecated version of the key.
277  * @param value The data to store.
278  * @return void
279  **/
280  template <typename T>
281  void setDeprecated(const std::string &key, const std::string &deprecatedKey, const T &value);
282 
283  /**
284  * @brief Returns the mangled name of a type.
285  *.
286  * @return std::string the mangled name (typeid(T).name())
287  **/
288  template <typename T>
289  std::string getTypeName() const {
290  return std::string(typeid(T).name());
291  }
292 
293  /**
294  * @brief Registers a serializer for a known type
295  *
296  * Serializers are used to write/read from std::ostream objects when saving DataSet instances.
297  */
298  template <typename T>
299  static void registerDataTypeSerializer(const DataTypeSerializer &serializer) {
300  registerDataTypeSerializer(std::string(typeid(T).name()), serializer.clone());
301  }
302 
303  /**
304  * @brief write an embedded value
305  */
306  void writeData(std::ostream &os, const std::string &prop, const DataType *dt) const;
307 
308  /**
309  * @brief Serializes a DataSet into a stream
310  */
311  static void write(std::ostream &os, const DataSet &ds);
312 
313  /**
314  * @brief Read a value and stores it into the specified type
315  */
316  bool readData(std::istream &is, const std::string &prop, const std::string &outputTypeName);
317 
318  /**
319  * @brief Reads a stream and stores its contents into a DataSet
320  */
321  static bool read(std::istream &is, DataSet &ds);
322 
323  /**
324  * @param str the name of the member to look for
325  * @return true if str exists into the DataSet.
326  */
327  bool exists(const std::string &str) const;
328 
329  /**
330  * @param str the name of the member to look for
331  * @return the mangled name of the type if str exists into the DataSet. An empty string if not.
332  */
333  std::string getTypeName(const std::string &str) const;
334 
335  /**
336  * @brief Removes an element from the DataSet
337  * @param str the name of the element to remove
338  */
339  void remove(const std::string &str);
340 
341  /**
342  * @param str The name of the element to retrieve
343  * @return A untyped value for a given element name. nullptr if the element does not exist
344  */
345  DataType *getData(const std::string &str) const;
346 
347  /**
348  * @brief Set from an untyped value
349  */
350  void setData(const std::string &str, const DataType *value);
351 
352  /**
353  * @return An iterator over stored values as a std::pair name => untyped value
354  */
356 
357  /**
358  * @brief Returns the number of registered values
359  */
360  unsigned int size() const;
361 
362  /**
363  * @brief Indicates whether the set is empty of not
364  */
365  bool empty() const;
366 
367  /**
368  * @return the data type serializer associated to the given typename. nullptr if no serializer is
369  * found
370  */
371  static DataTypeSerializer *typenameToSerializer(const std::string &name);
372 
373  /**
374  * @return A std::string representation of a DataSet
375  */
376  std::string toString() const;
377 };
378 } // namespace tlp
379 
380 #include "cxx/DataSet.cxx"
381 
382 #endif
A container that can store data from any type.
Definition: DataSet.h:195
void writeData(std::ostream &os, const std::string &prop, const DataType *dt) const
write an embedded value
bool empty() const
Indicates whether the set is empty of not.
tlp::Iterator< std::pair< std::string, DataType * > > * getValues() const
std::string getTypeName(const std::string &str) const
DataSet & operator=(const DataSet &set)
Performs a deep copy of a DataSet into another.
void remove(const std::string &str)
Removes an element from the DataSet.
unsigned int size() const
Returns the number of registered values.
static void registerDataTypeSerializer(const DataTypeSerializer &serializer)
Registers a serializer for a known type.
Definition: DataSet.h:299
bool exists(const std::string &str) const
bool readData(std::istream &is, const std::string &prop, const std::string &outputTypeName)
Read a value and stores it into the specified type.
static DataTypeSerializer * typenameToSerializer(const std::string &name)
std::string getTypeName() const
Returns the mangled name of a type.
Definition: DataSet.h:289
static void write(std::ostream &os, const DataSet &ds)
Serializes a DataSet into a stream.
void setData(const std::string &str, const DataType *value)
Set from an untyped value.
DataType * getData(const std::string &str) const
std::string toString() const
static bool read(std::istream &is, DataSet &ds)
Reads a stream and stores its contents into a DataSet.
Describes a value of any type.
Definition: DataSet.h:57
bool isTulipProperty() const
indicates if it is a Tulip property
Definition: DataSet.h:79
static bool isTulipProperty(const std::string &typeName)
indicates if it is a Tulip property
virtual std::string getTypeName() const =0
void * value
The actual pointer to the element's data.
Definition: DataSet.h:86
virtual DataType * clone() const =0
Interface for Tulip iterators. Allows basic iteration operations only.
Definition: Iterator.h:74