Graphite Version 3
An experimental 3D geometry processing program
Loading...
Searching...
No Matches
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
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
55namespace 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
101 bool is_a(const MetaType* type) const;
102
106 void reset() {
107 destroy();
108 }
109
114 Any(const Any& rhs) :
115 value_(nullptr), in_buffer_(false), meta_type_(nullptr) {
116 copy(rhs);
117 }
118
124 Any& operator=(const Any& rhs) {
125 if(&rhs != this) {
126 destroy();
127 copy(rhs);
128 }
129 return *this;
130 }
131
136 std::string as_string() const {
137 std::string result;
138 if(value_ != nullptr) {
139 convert_to_string(meta_type_, result, value_);
140 }
141 return result;
142 }
143
150 return meta_type_;
151 }
152
160
165 template <class T> void set_value(const T& value) {
166 MetaType* new_type = resolve_meta_type<T>();
167 if(new_type == meta_type_) {
168 life_cycle()->assign(value_, Memory::pointer(&value));
169 return;
170 }
171 destroy();
172 meta_type_ = new_type;
173
174#if defined(GEO_COMPILER_GCC)
175// GCC does not see that we use placement new in the buffer
176// only if object size is smaller than BUFFER_SIZE and
177// generates a warning.
178#pragma GCC diagnostic push
179#pragma GCC diagnostic ignored "-Wplacement-new"
180#elif defined(GEO_COMPILER_MSVC)
181// MSVC barks on test with constant condition.
182#pragma warning(push)
183#pragma warning(disable:4127)
184#endif
185
186 if(sizeof(T) <= BUFFER_SIZE) {
187 in_buffer_ = true;
188 value_ = buffer_;
189 new(value_)T(value);
190 } else {
191 in_buffer_ = false;
192 value_ = Memory::pointer(new T(value));
193 }
194
195#if defined(GEO_COMPILER_GCC)
196#pragma GCC diagnostic pop
197#elif defined(GEO_COMPILER_MSVC)
198#pragma warning(pop)
199#endif
200
201 }
202
210 void set_value(const char* value) {
211 set_value<std::string>(std::string(value));
212 }
213
220 template <class T> bool get_value(SmartPointer<T>& value) const {
221 T* value_as_ptr = nullptr;
222 if(!get_value(value_as_ptr)) {
223 return false;
224 }
225 value = value_as_ptr;
226 return true;
227 }
228
235 template <class T> bool get_value(T& value) const {
236 if(value_ == nullptr) {
237 return false;
238 }
239 // Test if the stored value is of type T
240 if(meta_type_ == resolve_meta_type<T>()) {
241 value = value_as<T>();
242 return true;
243 }
244 // If the stored value is a string, convert it to T
245 if(meta_type_ == resolve_meta_type<std::string>()) {
246 const std::string& string_value = value_as<std::string>();
247 convert_from_string(
248 resolve_meta_type<T>(),
249 string_value, (Memory::pointer)(&value)
250 );
251 return true;
252 }
253 return false;
254 }
255
262 bool get_value(std::string& value) const {
263 value = as_string();
264 return true;
265 }
266
273 bool get_value(index_t& value) const {
274 if(get_value<index_t>(value)) {
275 return true;
276 }
277 {
278 signed_index_t tmp;
279 if(get_value<signed_index_t>(tmp)) {
280 value = index_t(tmp);
281 return true;
282 }
283 }
284 {
285 float tmp;
286 if(get_value<float>(tmp)) {
287 value = index_t(tmp);
288 return true;
289 }
290
291 }
292 {
293 double tmp;
294 if(get_value<double>(tmp)) {
295 value = index_t(tmp);
296 return true;
297 }
298
299 }
300 return false;
301 }
302
309 bool get_value(signed_index_t& value) const {
310 if(get_value<signed_index_t>(value)) {
311 return true;
312 }
313 {
314 index_t tmp;
315 if(get_value<index_t>(tmp)) {
316 value = signed_index_t(tmp);
317 return true;
318 }
319 }
320 {
321 float tmp;
322 if(get_value<float>(tmp)) {
323 value = signed_index_t(tmp);
324 return true;
325 }
326
327 }
328 {
329 double tmp;
330 if(get_value<double>(tmp)) {
331 value = signed_index_t(tmp);
332 return true;
333 }
334
335 }
336 return false;
337 }
338
345 bool get_value(float& value) const {
346 if(get_value<float>(value)) {
347 return true;
348 }
349 {
350 double tmp;
351 if(get_value<double>(tmp)) {
352 value = float(tmp);
353 return true;
354 }
355 }
356 {
357 index_t tmp;
358 if(get_value<index_t>(tmp)) {
359 value = float(tmp);
360 return true;
361 }
362 }
363 {
364 signed_index_t tmp;
365 if(get_value<signed_index_t>(tmp)) {
366 value = float(tmp);
367 return true;
368 }
369 }
370 return false;
371 }
372
379 bool get_value(double& value) const {
380 if(get_value<double>(value)) {
381 return true;
382 }
383 {
384 float tmp;
385 if(get_value<float>(tmp)) {
386 value = double(tmp);
387 return true;
388 }
389 }
390 {
391 index_t tmp;
392 if(get_value<index_t>(tmp)) {
393 value = double(tmp);
394 return true;
395 }
396 }
397 {
398 signed_index_t tmp;
399 if(get_value<signed_index_t>(tmp)) {
400 value = double(tmp);
401 return true;
402 }
403 }
404 return false;
405 }
406
417 template <class T> bool get_value(T*& value) const {
418 value = nullptr;
419 if(is_null()) {
420 return true;
421 }
422
423 if(is_smart_pointer_type(meta_type())) {
424 // TODO: check pointer types
425 Counted* counted = value_as<Counted*>();
426 value = reinterpret_cast<T*>(counted);
427 return true;
428 }
429
430 if(!is_pointer_type(meta_type())) {
431 Logger::warn("GOM")
432 << "Invalid Any to pointer conversion: not pointer type "
433 << std::endl;
434 Logger::warn("GOM")
435 << "type = "
436 << meta_type_name(meta_type())
437 << std::endl;
438 Logger::warn("GOM")
439 << "value = "
440 << as_string()
441 << std::endl;
442 return false;
443 }
444
445 /*
446 // TODO: check pointer types ? (but I do not want to include
447 // <meta.h> I think, to be checked).
448 if(!pointer_can_be_casted_to(meta_type(), ogf_meta<T>::type())) {
449 Logger::warn("GOM")
450 << "Invalid Any to pointer conversion: invalid cast"
451 << std::endl;
452 return false;
453 }
454 */
455
456 value = (T*)(value_as<Memory::pointer>());
457 return true;
458 }
459
465 void create(MetaType* meta_type) {
466 destroy();
467 meta_type_ = meta_type;
468 if(life_cycle()->object_size() <= BUFFER_SIZE) {
469 in_buffer_ = true;
470 value_ = buffer_;
471 life_cycle()->construct(value_);
472 } else {
473 in_buffer_ = false;
474 value_ = life_cycle()->new_object();
475 }
476 }
477
484 void copy_from(Memory::pointer addr, MetaType* meta_type) {
485 if(value_ != nullptr && this->meta_type() == meta_type) {
486 life_cycle()->assign(value_, addr);
487 return;
488 }
489 if(value_ != nullptr) {
490 destroy();
491 }
492 meta_type_ = meta_type;
493 if(life_cycle()->object_size() <= BUFFER_SIZE) {
494 in_buffer_ = true;
495 value_ = buffer_;
496 life_cycle()->copy_construct(value_, addr);
497 } else {
498 in_buffer_ = false;
499 value_ = life_cycle()->new_object(addr);
500 }
501 }
502
511 bool copy_to(Memory::pointer addr, MetaType* meta_type) const {
512 if(value_ == nullptr) {
513 return false;
514 }
515 if(meta_type == this->meta_type()) {
516 life_cycle()->assign(addr, value_);
517 return true;
518 }
519 // If meta types do not match, try conversions.
520 return copy_convert_to(addr, meta_type);
521 }
522
535 static bool convert_to_string(
536 MetaType* meta_type, std::string& string, Memory::pointer value
537 );
538
552 MetaType* meta_type,
553 const std::string& string, Memory::pointer value
554 );
555
561 static bool is_pointer_type(const MetaType* mtype);
562
568 static bool is_smart_pointer_type(const MetaType* mtype);
569
575 static MetaType* pointed_type(const MetaType* mtype);
576
588 const MetaType* derived_pointer_type,
589 const MetaType* base_pointer_type
590 );
591
603 const std::string& typeid_name
604 );
605
610 template <class T> static MetaType* resolve_meta_type() {
611 static MetaType* mtype =
612 resolve_meta_type_by_typeid_name(typeid(T).name());
613 return mtype;
614 }
615
616 protected:
617
626 bool copy_convert_to(Memory::pointer addr, MetaType* meta_type) const;
627
635 template <class T> const T& value_as() const {
636 return *(T*)(value_);
637 }
638
642 void destroy() {
643 if(value_ == nullptr) {
644 return;
645 }
646 if(in_buffer_) {
647 life_cycle()->destroy(value_);
648 in_buffer_ = false;
649 } else {
650 life_cycle()->delete_object(value_);
651 }
652 value_ = nullptr;
653 meta_type_ = nullptr;
654 }
655
660 void copy(const Any& rhs) {
661 geo_debug_assert(&rhs != this);
662 if(rhs.is_null()) {
663 destroy();
664 return;
665 }
666 meta_type_ = rhs.meta_type();
667 if(life_cycle()->object_size() <= BUFFER_SIZE) {
668 in_buffer_ = true;
669 value_ = buffer_;
670 life_cycle()->copy_construct(value_, rhs.value_);
671 } else {
672 in_buffer_ = false;
673 value_ = life_cycle()->new_object(rhs.value_);
674 }
675 }
676
677 static std::string meta_type_name(const MetaType* mt);
678
679 public:
686 return value_;
687 }
688
689 private:
690 Memory::pointer value_;
691 Memory::byte buffer_[BUFFER_SIZE];
692 bool in_buffer_;
693 MetaType* meta_type_;
694 };
695
696}
697
698#ifdef GEO_COMPILER_CLANG
699#pragma GCC diagnostic pop
700#endif
701
702#endif
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
Base class for reference-counted objects.
Definition counted.h:71
Manages the life cycle of an object.
Definition life_cycle.h:66
A smart pointer with reference-counted copy semantics.
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:309
bool get_value(SmartPointer< T > &value) const
Gets the stored value as a SmartPointer.
Definition any.h:220
bool get_value(T *&value) const
Gets the stored value (pointers overload).
Definition any.h:417
void set_value(const T &value)
Sets the value of this Any.
Definition any.h:165
static MetaType * pointed_type(const MetaType *mtype)
Gets the deferenced type.
std::string as_string() const
Gets a string representation.
Definition any.h:136
const T & value_as() const
Gets the value as a specific type.
Definition any.h:635
void set_value(const char *value)
Sets the value of this Any (overload for string literals).
Definition any.h:210
LifeCycle * life_cycle() const
Gets the LifeCycle.
void destroy()
Deallocates the stored variable.
Definition any.h:642
void reset()
Resets this Any to the initial null value.
Definition any.h:106
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...
bool get_value(T &value) const
Gets the stored value.
Definition any.h:235
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.
static bool convert_to_string(MetaType *meta_type, std::string &string, Memory::pointer value)
Converts an object of a given type into a string.
MetaType * meta_type() const
Gets the MetaType of the stored value.
Definition any.h:149
void copy(const Any &rhs)
Copies another Any.
Definition any.h:660
Memory::pointer data()
Gets a pointer to the stored value.
Definition any.h:685
static MetaType * resolve_meta_type_by_typeid_name(const std::string &typeid_name)
Finds a MetaType by typeid name.
static bool is_smart_pointer_type(const MetaType *mtype)
Tests whether a MetaType is a smart pointer type.
bool get_value(std::string &value) const
Gets the stored value (std::string overload).
Definition any.h:262
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:484
bool copy_to(Memory::pointer addr, MetaType *meta_type) const
Copies the value stored in this Any at a specified address.
Definition any.h:511
static MetaType * resolve_meta_type()
Gets the MetaType associated with a type.
Definition any.h:610
bool get_value(index_t &value) const
Gets the stored value (index_t overload).
Definition any.h:273
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:345
Any & operator=(const Any &rhs)
Any affectation operator.
Definition any.h:124
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:465
~Any()
Any destructor.
Definition any.h:82
Any(const Any &rhs)
Any copy constructor.
Definition any.h:114
bool is_a(const MetaType *type) const
Tests whether the stored object inherits a given type.
bool get_value(double &value) const
Gets the stored value (double overload).
Definition any.h:379
static bool convert_from_string(MetaType *meta_type, const std::string &string, Memory::pointer value)
Converts a string into an object of a given type.
The representation of a type in the Meta repository.
Definition meta_type.h:222
Implementation of generic object lifecycle service.
unsigned char byte
Unsigned byte type.
Definition memory.h:92
byte * pointer
Pointer to unsigned byte(s)
Definition memory.h:104
geo_signed_index_t signed_index_t
The type for storing and manipulating indices differences.
Definition numeric.h:344
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:330
Global Graphite namespace.
Definition common.h:76
Definitions common to all include files in the gom library.