Skip to content

Commit 43d7d8e

Browse files
sloedeskystrife
authored andcommitted
Allow use of cpptoml with RTTI disabled (#77)
* Create enum class "base_type" and add as member to base class * Add base_type_traits class and extent base_type enums by TABLE, ARRAY, and TABLE_ARRAY * Add macro "CPPTOML_NO_RTTI" to disable reliance on runtime type information * Guard all code snippets for supporting non-RTTI compilation by macros
1 parent b5f1aa6 commit 43d7d8e

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

include/cpptoml.h

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ using string_to_base_map
5151
= std::unordered_map<std::string, std::shared_ptr<base>>;
5252
#endif
5353

54+
// if defined, `base` will retain type information in form of an enum class
55+
// such that static_cast can be used instead of dynamic_cast
56+
// #define CPPTOML_NO_RTTI
57+
5458
template <class T>
5559
class option
5660
{
@@ -396,6 +400,95 @@ inline std::shared_ptr<T> make_element();
396400
inline std::shared_ptr<table> make_table();
397401
inline std::shared_ptr<table_array> make_table_array();
398402

403+
#if defined(CPPTOML_NO_RTTI)
404+
/// Base type used to store underlying data type explicitly if RTTI is disabled
405+
enum class base_type
406+
{
407+
NONE,
408+
STRING,
409+
LOCAL_TIME,
410+
LOCAL_DATE,
411+
LOCAL_DATETIME,
412+
OFFSET_DATETIME,
413+
INT,
414+
FLOAT,
415+
BOOL,
416+
TABLE,
417+
ARRAY,
418+
TABLE_ARRAY
419+
};
420+
421+
/// Type traits class to convert C++ types to enum member
422+
template <class T>
423+
struct base_type_traits;
424+
425+
template <>
426+
struct base_type_traits<std::string>
427+
{
428+
static const base_type type = base_type::STRING;
429+
};
430+
431+
template <>
432+
struct base_type_traits<local_time>
433+
{
434+
static const base_type type = base_type::LOCAL_TIME;
435+
};
436+
437+
template <>
438+
struct base_type_traits<local_date>
439+
{
440+
static const base_type type = base_type::LOCAL_DATE;
441+
};
442+
443+
template <>
444+
struct base_type_traits<local_datetime>
445+
{
446+
static const base_type type = base_type::LOCAL_DATETIME;
447+
};
448+
449+
template <>
450+
struct base_type_traits<offset_datetime>
451+
{
452+
static const base_type type = base_type::OFFSET_DATETIME;
453+
};
454+
455+
template <>
456+
struct base_type_traits<int64_t>
457+
{
458+
static const base_type type = base_type::INT;
459+
};
460+
461+
template <>
462+
struct base_type_traits<double>
463+
{
464+
static const base_type type = base_type::FLOAT;
465+
};
466+
467+
template <>
468+
struct base_type_traits<bool>
469+
{
470+
static const base_type type = base_type::BOOL;
471+
};
472+
473+
template <>
474+
struct base_type_traits<table>
475+
{
476+
static const base_type type = base_type::TABLE;
477+
};
478+
479+
template <>
480+
struct base_type_traits<array>
481+
{
482+
static const base_type type = base_type::ARRAY;
483+
};
484+
485+
template <>
486+
struct base_type_traits<table_array>
487+
{
488+
static const base_type type = base_type::TABLE_ARRAY;
489+
};
490+
#endif
491+
399492
/**
400493
* A generic base TOML value used for type erasure.
401494
*/
@@ -480,11 +573,28 @@ class base : public std::enable_shared_from_this<base>
480573
template <class Visitor, class... Args>
481574
void accept(Visitor&& visitor, Args&&... args) const;
482575

576+
#if defined(CPPTOML_NO_RTTI)
577+
base_type type() const
578+
{
579+
return type_;
580+
}
581+
582+
protected:
583+
base(const base_type t) : type_(t)
584+
{
585+
// nothing
586+
}
587+
588+
private:
589+
const base_type type_ = base_type::NONE;
590+
591+
#else
483592
protected:
484593
base()
485594
{
486595
// nothing
487596
}
597+
#endif
488598
};
489599

490600
/**
@@ -540,9 +650,15 @@ class value : public base
540650
/**
541651
* Constructs a value from the given data.
542652
*/
653+
#if defined(CPPTOML_NO_RTTI)
654+
value(const T& val) : base(base_type_traits<T>::type), data_(val)
655+
{
656+
}
657+
#else
543658
value(const T& val) : data_(val)
544659
{
545660
}
661+
#endif
546662

547663
value(const value& val) = delete;
548664
value& operator=(const value& val) = delete;
@@ -560,34 +676,71 @@ std::shared_ptr<typename value_traits<T>::type> make_value(T&& val)
560676
template <class T>
561677
inline std::shared_ptr<value<T>> base::as()
562678
{
679+
#if defined(CPPTOML_NO_RTTI)
680+
if (type() == base_type_traits<T>::type)
681+
return std::static_pointer_cast<value<T>>(shared_from_this());
682+
else
683+
return nullptr;
684+
#else
563685
return std::dynamic_pointer_cast<value<T>>(shared_from_this());
686+
#endif
564687
}
565688

566689
// special case value<double> to allow getting an integer parameter as a
567690
// double value
568691
template <>
569692
inline std::shared_ptr<value<double>> base::as()
570693
{
694+
#if defined(CPPTOML_NO_RTTI)
695+
if (type() == base_type::FLOAT)
696+
return std::static_pointer_cast<value<double>>(shared_from_this());
697+
698+
if (type() == base_type::INT)
699+
{
700+
auto v = std::static_pointer_cast<value<int64_t>>(shared_from_this());
701+
return make_value<double>(static_cast<double>(v->get()));;
702+
}
703+
#else
571704
if (auto v = std::dynamic_pointer_cast<value<double>>(shared_from_this()))
572705
return v;
573706

574707
if (auto v = std::dynamic_pointer_cast<value<int64_t>>(shared_from_this()))
575708
return make_value<double>(static_cast<double>(v->get()));
709+
#endif
576710

577711
return nullptr;
578712
}
579713

580714
template <class T>
581715
inline std::shared_ptr<const value<T>> base::as() const
582716
{
717+
#if defined(CPPTOML_NO_RTTI)
718+
if (type() == base_type_traits<T>::type)
719+
return std::static_pointer_cast<const value<T>>(shared_from_this());
720+
else
721+
return nullptr;
722+
#else
583723
return std::dynamic_pointer_cast<const value<T>>(shared_from_this());
724+
#endif
584725
}
585726

586727
// special case value<double> to allow getting an integer parameter as a
587728
// double value
588729
template <>
589730
inline std::shared_ptr<const value<double>> base::as() const
590731
{
732+
#if defined(CPPTOML_NO_RTTI)
733+
if (type() == base_type::FLOAT)
734+
return std::static_pointer_cast<const value<double>>(shared_from_this());
735+
736+
if (type() == base_type::INT)
737+
{
738+
auto v = as<int64_t>();
739+
// the below has to be a non-const value<double> due to a bug in
740+
// libc++: https://llvm.org/bugs/show_bug.cgi?id=18843
741+
return make_value<double>(static_cast<double>(v->get()));
742+
}
743+
#else
591744
if (auto v
592745
= std::dynamic_pointer_cast<const value<double>>(shared_from_this()))
593746
return v;
@@ -598,6 +751,7 @@ inline std::shared_ptr<const value<double>> base::as() const
598751
// libc++: https://llvm.org/bugs/show_bug.cgi?id=18843
599752
return make_value<double>(static_cast<double>(v->get()));
600753
}
754+
#endif
601755

602756
return nullptr;
603757
}
@@ -839,7 +993,14 @@ class array : public base
839993
}
840994

841995
private:
996+
#if defined(CPPTOML_NO_RTTI)
997+
array() : base(base_type::ARRAY)
998+
{
999+
// empty
1000+
}
1001+
#else
8421002
array() = default;
1003+
#endif
8431004

8441005
template <class InputIterator>
8451006
array(InputIterator begin, InputIterator end) : values_{begin, end}
@@ -992,10 +1153,17 @@ class table_array : public base
9921153
}
9931154

9941155
private:
1156+
#if defined(CPPTOML_NO_RTTI)
1157+
table_array() : base(base_type::TABLE_ARRAY)
1158+
{
1159+
// nothing
1160+
}
1161+
#else
9951162
table_array()
9961163
{
9971164
// nothing
9981165
}
1166+
#endif
9991167

10001168
table_array(const table_array& obj) = delete;
10011169
table_array& operator=(const table_array& rhs) = delete;
@@ -1369,10 +1537,17 @@ class table : public base
13691537
}
13701538

13711539
private:
1540+
#if defined(CPPTOML_NO_RTTI)
1541+
table() : base(base_type::TABLE)
1542+
{
1543+
// nothing
1544+
}
1545+
#else
13721546
table()
13731547
{
13741548
// nothing
13751549
}
1550+
#endif
13761551

13771552
table(const table& obj) = delete;
13781553
table& operator=(const table& rhs) = delete;

0 commit comments

Comments
 (0)