Graphite  Version 3
An experimental 3D geometry processing program
any.h
Go to the documentation of this file.
1 /*
2  * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
3  * Copyright (C) 2000 Bruno Levy
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * If you modify this software, you should include a notice giving the
20  * name of the person performing the modification, the date of modification,
21  * and the reason for such modification.
22  *
23  * Contact: Bruno Levy
24  *
25  * levy@loria.fr
26  *
27  * ISA Project
28  * LORIA, INRIA Lorraine,
29  * Campus Scientifique, BP 239
30  * 54506 VANDOEUVRE LES NANCY CEDEX
31  * FRANCE
32  *
33  * Note that the GNU General Public License does not permit incorporating
34  * the Software into proprietary programs.
35  */
36 
37 #ifndef H_OGF_BASIC_TYPES_ANY_H
38 #define H_OGF_BASIC_TYPES_ANY_H
39 
40 #include <OGF/gom/common/common.h>
41 #include <OGF/gom/services/life_cycle.h>
42 #include <typeinfo>
43 
49 #ifdef GEO_COMPILER_CLANG
50 #pragma GCC diagnostic push
51 #pragma GCC diagnostic ignored "-Wcast-align"
52 #endif
53 
54 
55 namespace OGF {
56 
57  class MetaType;
58 
62  class GOM_API Any {
63  private:
64 
69  enum { BUFFER_SIZE = 40 };
70 
71  public:
72 
76  Any() : value_(nullptr), in_buffer_(false), meta_type_(nullptr) {
77  }
78 
82  ~Any() {
83  destroy();
84  }
85 
91  bool is_null() const {
92  return value_ == nullptr;
93  }
94 
98  void reset() {
99  destroy();
100  }
101 
106  Any(const Any& rhs) :
107  value_(nullptr), in_buffer_(false), meta_type_(nullptr) {
108  copy(rhs);
109  }
110 
116  Any& operator=(const Any& rhs) {
117  if(&rhs != this) {
118  destroy();
119  copy(rhs);
120  }
121  return *this;
122  }
123 
128  std::string as_string() const {
129  std::string result;
130  if(value_ != nullptr) {
131  convert_to_string(meta_type_, result, value_);
132  }
133  return result;
134  }
135 
141  MetaType* meta_type() const {
142  return meta_type_;
143  }
144 
150 
155  template <class T> void set_value(const T& value) {
156  MetaType* new_type = resolve_meta_type<T>();
157  if(new_type == meta_type_) {
158  life_cycle()->assign(value_, Memory::pointer(&value));
159  return;
160  }
161  destroy();
162  meta_type_ = new_type;
163 
164 #if defined(GEO_COMPILER_GCC)
165 // GCC does not see that we use placement new in the buffer
166 // only if object size is smaller than BUFFER_SIZE and
167 // generates a warning.
168 #pragma GCC diagnostic push
169 #pragma GCC diagnostic ignored "-Wplacement-new"
170 #elif defined(GEO_COMPILER_MSVC)
171 // MSVC barks on test with constant condition.
172 #pragma warning(push)
173 #pragma warning(disable:4127)
174 #endif
175 
176  if(sizeof(T) <= BUFFER_SIZE) {
177  in_buffer_ = true;
178  value_ = buffer_;
179  new(value_)T(value);
180  } else {
181  in_buffer_ = false;
182  value_ = Memory::pointer(new T(value));
183  }
184 
185 #if defined(GEO_COMPILER_GCC)
186 #pragma GCC diagnostic pop
187 #elif defined(GEO_COMPILER_MSVC)
188 #pragma warning(pop)
189 #endif
190 
191  }
192 
200  void set_value(const char* value) {
201  set_value<std::string>(std::string(value));
202  }
203 
210  template <class T> bool get_value(T& value) const {
211  if(value_ == nullptr) {
212  return false;
213  }
214  // Test if the stored value is of type T
215  if(meta_type_ == resolve_meta_type<T>()) {
216  value = value_as<T>();
217  return true;
218  }
219  // If the stored value is a string, convert it to T
220  if(meta_type_ == resolve_meta_type<std::string>()) {
221  const std::string& string_value = value_as<std::string>();
222  convert_from_string(
223  resolve_meta_type<T>(),
224  string_value, (Memory::pointer)(&value)
225  );
226  return true;
227  }
228  return false;
229  }
230 
237  bool get_value(std::string& value) const {
238  value = as_string();
239  return true;
240  }
241 
248  bool get_value(index_t& value) const {
249  if(get_value<index_t>(value)) {
250  return true;
251  }
252  {
253  signed_index_t tmp;
254  if(get_value<signed_index_t>(tmp)) {
255  value = index_t(tmp);
256  return true;
257  }
258  }
259  {
260  float tmp;
261  if(get_value<float>(tmp)) {
262  value = index_t(tmp);
263  return true;
264  }
265 
266  }
267  {
268  double tmp;
269  if(get_value<double>(tmp)) {
270  value = index_t(tmp);
271  return true;
272  }
273 
274  }
275  return false;
276  }
277 
284  bool get_value(signed_index_t& value) const {
285  if(get_value<signed_index_t>(value)) {
286  return true;
287  }
288  {
289  index_t tmp;
290  if(get_value<index_t>(tmp)) {
291  value = signed_index_t(tmp);
292  return true;
293  }
294  }
295  {
296  float tmp;
297  if(get_value<float>(tmp)) {
298  value = signed_index_t(tmp);
299  return true;
300  }
301 
302  }
303  {
304  double tmp;
305  if(get_value<double>(tmp)) {
306  value = signed_index_t(tmp);
307  return true;
308  }
309 
310  }
311  return false;
312  }
313 
320  bool get_value(float& value) const {
321  if(get_value<float>(value)) {
322  return true;
323  }
324  {
325  double tmp;
326  if(get_value<double>(tmp)) {
327  value = float(tmp);
328  return true;
329  }
330  }
331  {
332  index_t tmp;
333  if(get_value<index_t>(tmp)) {
334  value = float(tmp);
335  return true;
336  }
337  }
338  {
339  signed_index_t tmp;
340  if(get_value<signed_index_t>(tmp)) {
341  value = float(tmp);
342  return true;
343  }
344  }
345  return false;
346  }
347 
354  bool get_value(double& value) const {
355  if(get_value<double>(value)) {
356  return true;
357  }
358  {
359  float tmp;
360  if(get_value<float>(tmp)) {
361  value = double(tmp);
362  return true;
363  }
364  }
365  {
366  index_t tmp;
367  if(get_value<index_t>(tmp)) {
368  value = double(tmp);
369  return true;
370  }
371  }
372  {
373  signed_index_t tmp;
374  if(get_value<signed_index_t>(tmp)) {
375  value = double(tmp);
376  return true;
377  }
378  }
379  return false;
380  }
381 
392  template <class T> bool get_value(T*& value) const {
393  value = nullptr;
394  if(is_null()) {
395  return true;
396  }
397 
398  if(!is_pointer_type(meta_type())) {
399  Logger::warn("GOM")
400  << "Invalid Any to pointer conversion: not pointer type "
401  << std::endl;
402  Logger::warn("GOM")
403  << "type = "
404  << meta_type_name(meta_type())
405  << std::endl;
406  Logger::warn("GOM")
407  << "value = "
408  << as_string()
409  << std::endl;
410  return false;
411  }
412 
413  /*
414  // TODO: check pointer types ? (but I do not want to include
415  // <meta.h> I think, to be checked).
416  if(!pointer_can_be_casted_to(meta_type(), ogf_meta<T>::type())) {
417  Logger::warn("GOM")
418  << "Invalid Any to pointer conversion: invalid cast"
419  << std::endl;
420  return false;
421  }
422  */
423 
424  value = (T*)(value_as<Memory::pointer>());
425  return true;
426  }
427 
433  void create(MetaType* meta_type) {
434  destroy();
435  meta_type_ = meta_type;
436  if(life_cycle()->object_size() <= BUFFER_SIZE) {
437  in_buffer_ = true;
438  value_ = buffer_;
439  life_cycle()->construct(value_);
440  } else {
441  in_buffer_ = false;
442  value_ = life_cycle()->new_object();
443  }
444  }
445 
452  void copy_from(Memory::pointer addr, MetaType* meta_type) {
453  if(value_ != nullptr && this->meta_type() == meta_type) {
454  life_cycle()->assign(value_, addr);
455  return;
456  }
457  if(value_ != nullptr) {
458  destroy();
459  }
460  meta_type_ = meta_type;
461  if(life_cycle()->object_size() <= BUFFER_SIZE) {
462  in_buffer_ = true;
463  value_ = buffer_;
464  life_cycle()->copy_construct(value_, addr);
465  } else {
466  in_buffer_ = false;
467  value_ = life_cycle()->new_object(addr);
468  }
469  }
470 
479  bool copy_to(Memory::pointer addr, MetaType* meta_type) const {
480  if(value_ == nullptr) {
481  return false;
482  }
483  if(meta_type == this->meta_type()) {
484  life_cycle()->assign(addr, value_);
485  return true;
486  }
487  // If meta types do not match, try conversions.
488  return copy_convert_to(addr, meta_type);
489  }
490 
501  static void convert_to_string(
502  MetaType* meta_type,
503  std::string& string, Memory::pointer value
504  );
505 
516  static void convert_from_string(
517  MetaType* meta_type,
518  const std::string& string, Memory::pointer value
519  );
520 
526  static bool is_pointer_type(const MetaType* mtype);
527 
533  static MetaType* pointed_type(const MetaType* mtype);
534 
546  const MetaType* derived_pointer_type,
547  const MetaType* base_pointer_type
548  );
549 
561  const std::string& typeid_name
562  );
563 
568  template <class T> static MetaType* resolve_meta_type() {
569  static MetaType* mtype =
570  resolve_meta_type_by_typeid_name(typeid(T).name());
571  return mtype;
572  }
573 
574  protected:
575 
584  bool copy_convert_to(Memory::pointer addr, MetaType* meta_type) const;
585 
593  template <class T> const T& value_as() const {
594  return *(T*)(value_);
595  }
596 
600  void destroy() {
601  if(value_ == nullptr) {
602  return;
603  }
604  if(in_buffer_) {
605  life_cycle()->destroy(value_);
606  in_buffer_ = false;
607  } else {
608  life_cycle()->delete_object(value_);
609  }
610  value_ = nullptr;
611  meta_type_ = nullptr;
612  }
613 
618  void copy(const Any& rhs) {
619  geo_debug_assert(&rhs != this);
620  if(rhs.is_null()) {
621  destroy();
622  return;
623  }
624  meta_type_ = rhs.meta_type();
625  if(life_cycle()->object_size() <= BUFFER_SIZE) {
626  in_buffer_ = true;
627  value_ = buffer_;
628  life_cycle()->copy_construct(value_, rhs.value_);
629  } else {
630  in_buffer_ = false;
631  value_ = life_cycle()->new_object(rhs.value_);
632  }
633  }
634 
635  static std::string meta_type_name(const MetaType* mt);
636 
637  private:
638  Memory::pointer value_;
639  Memory::byte buffer_[BUFFER_SIZE];
640  bool in_buffer_;
641  MetaType* meta_type_;
642  };
643 
644 }
645 
646 #ifdef GEO_COMPILER_CLANG
647 #pragma GCC diagnostic pop
648 #endif
649 
650 #endif
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition: assert.h:196
A class that stores a variable of arbitrary type.
Definition: any.h:62
Any()
Any constructor.
Definition: any.h:76
bool get_value(signed_index_t &value) const
Gets the stored value (signed_index_t overload).
Definition: any.h:284
bool get_value(T *&value) const
Gets the stored value (pointers overload).
Definition: any.h:392
static void convert_to_string(MetaType *meta_type, std::string &string, Memory::pointer value)
Converts an object of a given type into a string.
void set_value(const T &value)
Sets the value of this Any.
Definition: any.h:155
const T & value_as() const
Gets the value as a specific type.
Definition: any.h:593
std::string as_string() const
Gets a string representation.
Definition: any.h:128
LifeCycle * life_cycle() const
Gets the LifeCycle.
static MetaType * pointed_type(const MetaType *mtype)
Gets the deferenced type.
void set_value(const char *value)
Sets the value of this Any (overload for string literals).
Definition: any.h:200
Any & operator=(const Any &rhs)
Any affectation operator.
Definition: any.h:116
MetaType * meta_type() const
Gets the MetaType of the stored value.
Definition: any.h:141
void destroy()
Deallocates the stored variable.
Definition: any.h:600
void reset()
Resets this Any to the initial null value.
Definition: any.h:98
bool copy_convert_to(Memory::pointer addr, MetaType *meta_type) const
Tentatively converts the value stored in this Any to a type and if successful, store it at a specifie...
static MetaType * resolve_meta_type_by_typeid_name(const std::string &typeid_name)
Finds a MetaType by typeid name.
bool get_value(T &value) const
Gets the stored value.
Definition: any.h:210
static bool pointer_can_be_casted_to(const MetaType *derived_pointer_type, const MetaType *base_pointer_type)
Tests whether a pointer type can be casted to an object type.
void copy(const Any &rhs)
Copies another Any.
Definition: any.h:618
bool get_value(std::string &value) const
Gets the stored value (std::string overload).
Definition: any.h:237
void copy_from(Memory::pointer addr, MetaType *meta_type)
Assigns a value from a specifed address and specified type to this Any.
Definition: any.h:452
bool copy_to(Memory::pointer addr, MetaType *meta_type) const
Copies the value stored in this Any at a specified address.
Definition: any.h:479
bool get_value(index_t &value) const
Gets the stored value (index_t overload).
Definition: any.h:248
static MetaType * resolve_meta_type()
Gets the MetaType associated with a type.
Definition: any.h:568
static bool is_pointer_type(const MetaType *mtype)
Tests whether a MetaType is a pointer type.
bool get_value(float &value) const
Gets the stored value (float overload).
Definition: any.h:320
bool is_null() const
Tests whether this Any is null.
Definition: any.h:91
void create(MetaType *meta_type)
Initializes this Any with the default value of a specified MetaType.
Definition: any.h:433
~Any()
Any destructor.
Definition: any.h:82
Any(const Any &rhs)
Any copy constructor.
Definition: any.h:106
bool get_value(double &value) const
Gets the stored value (double overload).
Definition: any.h:354
static void convert_from_string(MetaType *meta_type, const std::string &string, Memory::pointer value)
Converts a string into an object of a given type.
Manages the life cycle of an object.
Definition: life_cycle.h:59
The representation of a type in the Meta repository.
Definition: meta_type.h:221
unsigned char byte
Unsigned byte type.
Definition: memory.h:92
byte * pointer
Pointer to unsigned byte(s)
Definition: memory.h:104
void copy(void *to, const void *from, size_t size)
Copies a memory block.
Definition: memory.h:129
geo_signed_index_t signed_index_t
The type for storing and manipulating indices differences.
Definition: numeric.h:343
geo_index_t index_t
The type for storing and manipulating indices.
Definition: numeric.h:329
Global Graphite namespace.
Definition: common.h:76
Definitions common to all include files in the gom library.