Tulip  5.4.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  DataTypeSerializer(const std::string &otn) : outputTypeName(otn) {}
118  virtual ~DataTypeSerializer() {}
119  // return a copy of this
120  virtual DataTypeSerializer *clone() const = 0;
121  // write the DataType embedded value into the output stream
122  virtual void writeData(std::ostream &os, const DataType *data) = 0;
123  // return the DataType embedded value as a std::string
124  virtual std::string toString(const DataType *data) {
125  std::stringstream ss;
126  writeData(ss, data);
127  return ss.str();
128  }
129  // build a DataType embedding value read from input stream
130  virtual DataType *readData(std::istream &is) = 0;
131  // set a value into a DataSet
132  virtual bool setData(DataSet &ds, const std::string &prop, const std::string &value) = 0;
133 };
134 
135 // a template class designs to simplify the developer's work
136 // when writing a serializer class
137 template <typename T>
138 struct TypedDataSerializer : public DataTypeSerializer {
139  TypedDataSerializer(const std::string &otn) : DataTypeSerializer(otn) {}
140  // declare new serialization virtual functions
141  virtual void write(std::ostream &os, const T &value) = 0;
142  // return true if the read of value succeeded, false if not
143  virtual bool read(std::istream &is, T &value) = 0;
144  // define virtually inherited functions using the previous ones
145  void writeData(std::ostream &os, const DataType *data) override {
146  write(os, *(static_cast<T *>(data->value)));
147  }
148  DataType *readData(std::istream &is) override {
149  T value;
150  bool ok = read(is, value);
151 
152  if (ok)
153  return new TypedData<T>(new T(value));
154 
155  return nullptr;
156  }
157  // set a value into a DataSet
158  bool setData(DataSet &ds, const std::string &prop, const std::string &value) override = 0;
159 };
160 
161 // This class is there to ensure the destruction of DataTypeSerializer objects
162 // when program ends
163 class DataTypeSerializerContainer {
164 
165 public:
166  ~DataTypeSerializerContainer() {
167  std::unordered_map<std::string, DataTypeSerializer *>::iterator it = tnTodts.begin();
168 
169  for (; it != tnTodts.end(); ++it) {
170  delete it->second;
171  }
172  }
173 
174  std::unordered_map<std::string, DataTypeSerializer *> tnTodts;
175  std::unordered_map<std::string, DataTypeSerializer *> otnTodts;
176 };
177 ///@endcond
178 
179 /**
180  * @ingroup Structures
181  * @brief A container that can store data from any type.
182  *
183  * The DataSet aggregate data of various types into a single structure and map each value to a key
184  *(std::string) describing its name.
185  * DataSet is mainly used in plugins. When creating a plugin, one can add input parameters (using
186  *tlp::WithParameter methods) and retrieve them from the dataSet member variable once they have been
187  *set by the user.
188  **/
189 class TLP_SCOPE DataSet {
190  // Internal list of key-value pairs.
191  std::list<std::pair<std::string, DataType *>> data;
192  /* management of data serialization
193  two hashmap to retrieve data serializer from their
194  type names and output type names
195  tnTodsts => typename to data type serializer
196  otnTodts => output type name to data type serializer */
197  static DataTypeSerializerContainer serializerContainer;
198  static void registerDataTypeSerializer(const std::string &typeName, DataTypeSerializer *dts);
199 
200 public:
201  DataSet() {}
202  DataSet(const DataSet &set);
203  ~DataSet();
204 
205  /**
206  * @brief Performs a deep copy of a DataSet into another
207  */
208  DataSet &operator=(const DataSet &set);
209 
210  /**
211  * @brief Returns the stored value associated with the given key.
212  * The stored value is a copy of the original value that was set.
213  * If there is no value associated with the given key, the input value is left untouched.
214  *
215  * @param key The key with which the data we want to retrieve is associated.
216  * @param value A variable which will be overwritten with the value to retrieve.
217  * @return bool Whether there is a value associated with given key or not.
218  **/
219  template <typename T>
220  bool get(const std::string &key, T &value) const;
221 
222  /**
223  * @brief Returns the stored value, and deletes the stored copy.
224  * If no value is found, nothing is deleted.
225  *
226  * @param key The key with which the data we want to retrieve is associated.
227  * @param value A variable which will be overwritten with the value to retrieve.
228  * @return bool Whether there is a value associated with given key or not.
229  **/
230  template <typename T>
231  bool getAndFree(const std::string &key, T &value);
232 
233  /**
234  * @brief Stores a copy of the given param, associated with the key.
235  * The value must have a well-formed copy constructor.
236  *
237  * @param key The key which can be used to retrieve the data.
238  * @param value The data to store.
239  * @return void
240  **/
241  template <typename T>
242  void set(const std::string &key, const T &value);
243 
244  /**
245  * @brief Returns the mangled name of a type.
246  *.
247  * @return std::string the mangled name (typeid(T).name())
248  **/
249  template <typename T>
250  std::string getTypeName() const {
251  return std::string(typeid(T).name());
252  }
253 
254  /**
255  * @brief Registers a serializer for a known type
256  *
257  * Serializers are used to write/read from std::ostream objects when saving DataSet instances.
258  */
259  template <typename T>
260  static void registerDataTypeSerializer(const DataTypeSerializer &serializer) {
261  registerDataTypeSerializer(std::string(typeid(T).name()), serializer.clone());
262  }
263 
264  /**
265  * @brief write an embedded value
266  */
267  void writeData(std::ostream &os, const std::string &prop, const DataType *dt) const;
268 
269  /**
270  * @brief Serializes a DataSet into a stream
271  */
272  static void write(std::ostream &os, const DataSet &ds);
273 
274  /**
275  * @brief Read a value and stores it into the specified type
276  */
277  bool readData(std::istream &is, const std::string &prop, const std::string &outputTypeName);
278 
279  /**
280  * @brief Reads a stream and stores its contents into a DataSet
281  */
282  static bool read(std::istream &is, DataSet &ds);
283 
284  /**
285  * @param str the name of the member to look for
286  * @return true if str exists into the DataSet.
287  */
288  bool exists(const std::string &str) const;
289 
290  /**
291  * @param str the name of the member to look for
292  * @return the mangled name of the type if str exists into the DataSet. An empty string if not.
293  */
294  std::string getTypeName(const std::string &str) const;
295 
296  /**
297  * @brief Removes an element from the DataSet
298  * @param str the name of the element to remove
299  */
300  void remove(const std::string &str);
301 
302  /**
303  * @param str The name of the element to retrieve
304  * @return A untyped value for a given element name. nullptr if the element does not exist
305  */
306  DataType *getData(const std::string &str) const;
307 
308  /**
309  * @brief Set from an untyped value
310  */
311  void setData(const std::string &str, const DataType *value);
312 
313  /**
314  * @return An iterator over stored values as a std::pair name => untyped value
315  */
317 
318  /**
319  * @brief Returns the number of registered values
320  */
321  unsigned int size() const;
322 
323  /**
324  * @brief Indicates whether the set is empty of not
325  */
326  bool empty() const;
327 
328  /**
329  * @return the data type serializer associated to the given typename. nullptr if no serializer is
330  * found
331  */
332  static DataTypeSerializer *typenameToSerializer(const std::string &name);
333 
334  /**
335  * @return A std::string representation of a DataSet
336  */
337  std::string toString() const;
338 };
339 } // namespace tlp
340 
341 #include "cxx/DataSet.cxx"
342 
343 #endif
static void registerDataTypeSerializer(const DataTypeSerializer &serializer)
Registers a serializer for a known type.
Definition: DataSet.h:260
Interface for Tulip iterators. Allows basic iteration operations only.
Definition: Graph.h:43
Describes a value of any type.
Definition: DataSet.h:57
A container that can store data from any type.
Definition: DataSet.h:189
std::string getTypeName() const
Returns the mangled name of a type.
Definition: DataSet.h:250
void * value
The actual pointer to the element&#39;s data.
Definition: DataSet.h:86
bool isTulipProperty() const
indicates if it is a Tulip property
Definition: DataSet.h:79