Tulip  4.2.0
Better Visualization Through Research
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Groups Pages
DataSet.h
1 /*
2  *
3  * This file is part of Tulip (www.tulip-software.org)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux 1 and Inria Bordeaux - Sud Ouest
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 <iostream>
26 #include <string>
27 #include <cassert>
28 #include <typeinfo>
29 #include <list>
30 #include <tulip/StlIterator.h>
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> struct TypedValueContainer: public DataMem {
45  TYPE value;
46  TypedValueContainer() {}
47  TypedValueContainer(const TYPE& val) : value(val) {}
48  ~TypedValueContainer() {
49  }
50 };
51 ///@endcond
52 
53 /**
54  * @ingroup Structures
55  * @brief Describes a value of any type
56  */
57 struct 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 The actual pointer to the element's data
73  */
74  void *value;
75 };
76 
77 ///@cond DOXYGEN_HIDDEN
78 // template class to embed value of known type
79 template<typename T>
80 struct TypedData :public DataType {
81  TypedData(void *value) :DataType(value) {}
82  ~TypedData() {
83  delete (T*) value;
84  }
85  DataType* clone() const {
86  return new TypedData<T>(new T(*(T*)value));
87  }
88 
89  std::string getTypeName() const {
90  return std::string(typeid(T).name());
91  }
92 };
93 
94 // forward declaration of DataSet
95 class DataSet;
96 
97 // Basic class for serialization of DataType embedded value
98 struct DataTypeSerializer {
99  // the readable type name the serializer is designed for
100  std::string outputTypeName;
101  DataTypeSerializer(const std::string& otn):outputTypeName(otn) {}
102  virtual ~DataTypeSerializer() {}
103  // return a copy of this
104  virtual DataTypeSerializer* clone() const = 0;
105  // write the DataType embedded value into the output stream
106  virtual void writeData(std::ostream& os, const DataType *data)=0;
107  // build a DataType embedding value read from input stream
108  virtual DataType* readData(std::istream &is)=0;
109  // set a value into a DataSet
110  virtual bool setData(DataSet& ds, const std::string& prop, const std::string& value)=0;
111 };
112 
113 // a template class designs to simplify the developer's work
114 // when writing a serializer class
115 template<typename T>
116 struct TypedDataSerializer :public DataTypeSerializer {
117  TypedDataSerializer(const std::string& otn):DataTypeSerializer(otn) {}
118  // declare new serialization virtual functions
119  virtual void write(std::ostream& os, const T& value)=0;
120  // return true if the read of value succeed, false if not
121  virtual bool read(std::istream& is, T& value)=0;
122  // define virtually inherited functions using the previous ones
123  void writeData(std::ostream& os, const DataType* data) {
124  write(os, *((T*) data->value));
125  }
126  DataType* readData(std::istream& is) {
127  T value;
128  bool ok = read(is, value);
129 
130  if (ok)
131  return new TypedData<T>(new T(value));
132 
133  return NULL;
134  }
135  // set a value into a DataSet
136  virtual bool setData(DataSet& ds, const std::string& prop, const std::string& value)=0;
137 };
138 
139 // This class is there to ensure the destruction of DataTypeSerializer objects
140 // when program ends
141 class DataTypeSerializerContainer {
142 
143 public :
144 
145  ~DataTypeSerializerContainer() {
146  TLP_HASH_MAP<std::string, DataTypeSerializer*>::iterator it = tnTodts.begin();
147 
148  for (; it != tnTodts.end() ; ++it) {
149  delete it->second;
150  }
151  }
152 
153  TLP_HASH_MAP<std::string, DataTypeSerializer*> tnTodts;
154  TLP_HASH_MAP<std::string, DataTypeSerializer*> otnTodts;
155 
156 };
157 ///@endcond
158 
159 /**
160  * @ingroup Structures
161  * @brief A container that can store data from any type.
162  *
163  * The DataSet aggregate data of various types into a single structure and map each value to a key (std::string) describing its name.
164  * DataSet is mainly used in plugins. When creating a plugin, one can add input parameters (using tlp::WithParameter methods) and retrieve them from the dataSet member variable once they have been set by the user.
165  **/
166 class TLP_SCOPE DataSet {
167  //Internal list of key-value pairs.
168  std::list< std::pair<std::string, DataType*> > data;
169  /* management of data serialization
170  two hashmap to retrieve data serializer from their
171  type names and output type names
172  tnTodsts => typename to data type serializer
173  otnTodts => output type name to data type serializer */
174  static DataTypeSerializerContainer serializerContainer;
175  static void registerDataTypeSerializer(const std::string& typeName,
176  DataTypeSerializer* dts);
177 public:
178  DataSet() {}
179  DataSet(const DataSet &set);
180  ~DataSet();
181 
182  /**
183  * @brief Performs a deep copy of a DataSet into another
184  */
185  DataSet& operator=(const DataSet &set);
186 
187  /**
188  * @brief Returns the stored value associated with the given key.
189  * The stored value is a copy of the original value that was set.
190  * If there is no value associated with the given key, the input value is left untouched.
191  *
192  * @param key The key with which the data we want to retrieve is associated.
193  * @param value A variable wich will be overwritten with the value to retrieve.
194  * @return bool Whether there is a value associated with given key or not.
195  **/
196  template<typename T> bool get(const std::string &key, T& value) const;
197 
198  /**
199  * @brief Returns the stored value, and deletes the stored copy.
200  * If no value is found, nothing is deleted.
201  *
202  * @param key The key with which the data we want to retrieve is associated.
203  * @param value A variable wich will be overwritten with the value to retrieve.
204  * @return bool Whether there is a value associated with given key or not.
205  **/
206  template<typename T> bool getAndFree(const std::string &key, T& value);
207 
208  /**
209  * @brief Stores a copy of the given param, associated with the key.
210  * The value must have a well-formed copy constructor.
211  *
212  * @param key The key which can be used to retrieve the data.
213  * @param value The data to store.
214  * @return void
215  **/
216  template<typename T> void set(const std::string &key, const T& value);
217 
218  /**
219  * @brief Registers a serializer for a known type
220  *
221  * Serializers are used to write/read from std::ostream objects when saving DataSet instances.
222  */
223  template<typename T> static void registerDataTypeSerializer(const DataTypeSerializer &serializer) {
224  registerDataTypeSerializer(std::string(typeid(T).name()), serializer.clone());
225  }
226 
227  /**
228  * @brief write an embedded value
229  */
230  void writeData(std::ostream& os, const std::string& prop,const DataType* dt) const;
231 
232  /**
233  * @brief Serializes a DataSet into a stream
234  */
235  static void write(std::ostream& os, const DataSet& ds);
236 
237  /**
238  * @brief Read a value and stores it into the specified type
239  */
240  bool readData(std::istream& is, const std::string& prop, const std::string& outputTypeName);
241 
242  /**
243  * @brief Reads a stream and stores its contents into a DataSet
244  */
245  static bool read(std::istream& is, DataSet& ds);
246 
247  /**
248  * @param str the name of the member to look for
249  * @return true if str exists into the DataSet.
250  */
251  bool exist(const std::string &str) const;
252 
253  /**
254  * @brief Removes an element from the DataSet
255  * @param str the name of the element to remove
256  */
257  void remove(const std::string &str);
258 
259  /**
260  * @param str The name of the element to retrieve
261  * @return A untyped value for a given element name. NULL if the element does not exist
262  */
263  DataType* getData(const std::string &str) const;
264 
265  /**
266  * @brief Set from an untyped value
267  */
268  void setData(const std::string &str, const DataType* value);
269 
270  /**
271  * @return An iterator over stored values as a std::pair name => untyped value
272  */
273  tlp::Iterator< std::pair<std::string, DataType*> > *getValues() const;
274 
275  /**
276  * @brief Returns the number of registered values
277  */
278  unsigned int size() const;
279 
280  /**
281  * @brief Indicates whether the set is empty of not
282  */
283  bool empty() const;
284 
285  /**
286  * @return the data type serializer associated to the given typename. NULL if no serializer is found
287  */
288  static DataTypeSerializer *typenameToSerializer(const std::string &name);
289 
290  /**
291  * @return A std::string representation of a DataSet
292  */
293  std::string toString() const;
294 };
295 
296 }
297 
298 #include "cxx/DataSet.cxx"
299 
300 #endif