Ported from hz::any_type to std::any.

This commit is contained in:
Alexander Shaduri
2017-12-30 21:35:28 +00:00
parent 02cfa33907
commit d4c06f61d6
18 changed files with 77 additions and 1054 deletions
+1 -1
View File
@@ -194,7 +194,7 @@ LIBS="$LIBS $PCRECPP_LIBS"
# Ideally, gcc should use the "latest" standard, but it just uses the latest option.
# TODO For now, since gtkmm3 uses dynamic exception specifications, we have
# to enable 14 instead of 17.
CXXFLAGS="$CXXFLAGS -std=c++14"
CXXFLAGS="$CXXFLAGS -std=c++17"
# -------------------------------------------------------------------------------------
@@ -9,7 +9,11 @@
/// \weakgroup applib
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // Glib::shell_quote()
#undef throw
#include "smartctl_executor.h"
@@ -14,12 +14,18 @@
#include <string>
#include <vector>
#include <glibmm.h>
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // Glib::shell_quote()
#undef throw
#include "executor_factory.h"
#include "storage_device.h"
#include "rconfig/rconfig_mini.h"
#include "app_pcrecpp.h"
#include "hz/string_num.h"
@@ -9,6 +9,12 @@
/// \weakgroup gsc
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // NOT NEEDED
#undef throw
#include <gtkmm.h>
#include "gsc_executor_log_window.h"
@@ -9,6 +9,12 @@
/// \weakgroup gsc
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // NOT NEEDED
#undef throw
#include <sstream>
#include <cstddef> // std::size_t
#include <gtkmm.h>
+6
View File
@@ -9,6 +9,12 @@
/// \weakgroup gsc
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // NOT NEEDED
#undef throw
#include <gtkmm.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
#include <vector> // better use vector, it's needed by others too
+6 -1
View File
@@ -9,6 +9,12 @@
/// \weakgroup gsc
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // NOT NEEDED
#undef throw
#include <string>
// #include <locale.h> // _configthreadlocale (win32)
#include <stdexcept> // std::runtime_error
@@ -18,7 +24,6 @@
#include <limits>
#include <gtkmm.h>
#include <glib.h> // g_, G*
#include <glibmm.h> // set_application_name
#ifdef _WIN32
#include <windows.h>
+7
View File
@@ -9,10 +9,17 @@
/// \weakgroup gsc
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // NOT NEEDED
#undef throw
#include <gtkmm.h>
#include <vector>
#include "hz/string_algo.h" // string_split
#include "hz/string_num.h"
#include "hz/fs_file.h" // hz::File
#include "hz/debug.h"
#include "hz/scoped_ptr.h"
@@ -9,6 +9,12 @@
/// \weakgroup gsc
/// @{
// TODO Remove this in gtkmm4.
#include <bits/stdc++.h> // to avoid throw() macro errors.
#define throw(a) // glibmm uses dynamic exception specifications, remove them.
#include <glibmm.h> // NOT NEEDED
#undef throw
#include <map>
#include <gtkmm.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
+2 -3
View File
@@ -1,7 +1,7 @@
AM_CPPFLAGS = $(all_includes)
METASOURCES = AUTO
noinst_HEADERS = any_convert.h any_type.h any_type_holder.h ascii.h \
noinst_HEADERS = ascii.h \
bad_cast_exception.h bin2ascii_encoder.h common_types.h cstdint.h cstdint_impl_msvc.h \
data_file.h debug.h env_tools.h errno_string.h error.h error_holder.h \
format_unit.h fs_common.h fs_dir.h fs_dir_platform.h fs_error_holder.h \
@@ -14,7 +14,6 @@ noinst_HEADERS = any_convert.h any_type.h any_type_holder.h ascii.h \
sync_policy_glib.h sync_policy_glibmm.h sync_policy_pthread.h \
sync_policy_win32.h system_specific.h type_categories.h type_properties.h win32_tools.h
any_type_test_SOURCES = any_type_test.cpp
bin2ascii_encoder_test_SOURCES = bin2ascii_encoder_test.cpp
errno_string_test_SOURCES = errno_string_test.cpp
format_unit_test_SOURCES = format_unit_test.cpp
@@ -31,7 +30,7 @@ sync_multilock_test_SOURCES = sync_multilock_test.cpp
# we don't list them in a separate variable because otherwise kdevelop won't see them.
noinst_PROGRAMS =
if ENABLE_TESTS
noinst_PROGRAMS += any_type_test bin2ascii_encoder_test errno_string_test \
noinst_PROGRAMS += bin2ascii_encoder_test errno_string_test \
format_unit_test fs_dir_test fs_file_test fs_path_test string_algo_test string_num_test \
string_wcmatch_test sync_test sync_multilock_test
endif
-190
View File
@@ -1,190 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_zlib.txt file
***************************************************************************/
/// \file
/// \author Alexander Shaduri
/// \ingroup hz
/// \weakgroup hz
/// @{
#ifndef HZ_ANY_CONVERT_H
#define HZ_ANY_CONVERT_H
#include "hz_config.h" // feature macros
#include <string>
#include "string_num.h" // string_is_numeric(), number_to_string()
#include "type_categories.h" // type_check_category
/// \file
/// Loose conversions:
/// Try to convert any type to any other type as long as specialization
/// for any_convert is defined.
/// String conversions to numbers are _not_ strictly checked.
/// Numeric types are converted by static_cast between each other.
namespace hz {
/// This can be used for inheritance to provide a const static \c value member
/// that is either true or false.
template<bool v = false>
struct AnyConvertibleValue {
static const bool value = v;
};
/// Convert \c from to \c to using loose conversion methods.
template<typename From, typename To>
inline bool any_convert(From from, To& to)
{
return false;
}
/// Convert \c from to \c to using loose conversion methods.
/// This is a same-type specialization.
template<typename From>
inline bool any_convert(From from, From& to)
{
to = from;
return true;
}
/// The structure that says whether type \c From is convertible to type \c To
/// using loose conversion methods.
/// This is the master struct, defaults to non-convertible.
template<typename From, typename To>
struct any_convertible : public AnyConvertibleValue<false> { };
/// The structure that says whether type \c From is convertible to type \c To
/// using loose conversion methods.
// Same-type specialization
template<typename From>
struct any_convertible<From, From> : public AnyConvertibleValue<true> { };
// specific type specs - see below.
/// Define \c any_convertible specialization for \c from_type and \c to_type, saying that
/// they're convertible. Also print \c any_convert function header.
#define DEFINE_ANY_CONVERT_SPEC(from_type, to_type) \
template<> \
struct any_convertible<from_type, to_type> : public AnyConvertibleValue<true> { }; \
\
template<> \
inline bool any_convert<from_type, to_type>(from_type from, to_type& to) \
/// Define \c any_convertible and \c any_convert specializations using static_cast.
#define DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, to_type) \
DEFINE_ANY_CONVERT_SPEC(from_type, to_type) \
{ \
to = static_cast<to_type>(from); \
return true; \
}
/// Define \c any_convertible and \c any_convert specializations using static_cast using bool.
#define DEFINE_ANY_CONVERT_SPEC_STATIC_TOBOOL(from_type) \
DEFINE_ANY_CONVERT_SPEC(from_type, bool) \
{ \
to = static_cast<bool>(static_cast<int>(from)); /* this disables gcc warning about unsafe != */ \
return true; \
}
/// Define \c any_convertible and \c any_convert specializations using hz::number_to_string().
#define DEFINE_ANY_CONVERT_SPEC_NUMTOSTRING(from_type) \
DEFINE_ANY_CONVERT_SPEC(from_type, std::string) \
{ \
to = hz::number_to_string(from); \
return true; \
}
/// Define \c any_convertible and \c any_convert specializations using hz::string_is_numeric().
#define DEFINE_ANY_CONVERT_SPEC_STRINGTONUM(to_type) \
DEFINE_ANY_CONVERT_SPEC(std::string, to_type) \
{ \
return hz::string_is_numeric(from, to, false); \
} \
DEFINE_ANY_CONVERT_SPEC(const std::string&, to_type) \
{ \
return hz::string_is_numeric(from, to, false); \
}
/// Define \c any_convertible and \c any_convert specializations for all built-in types as \c To.
#define DEFINE_ANY_CONVERT_SPEC_ALL(from_type) \
DEFINE_ANY_CONVERT_SPEC_STATIC_TOBOOL(from_type) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, char) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, signed char) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned char) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, wchar_t) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, short int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned short int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned long int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long long int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, unsigned long long int) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, double) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, float) \
DEFINE_ANY_CONVERT_SPEC_STATIC(from_type, long double) \
DEFINE_ANY_CONVERT_SPEC_NUMTOSTRING(from_type) \
DEFINE_ANY_CONVERT_SPEC_STRINGTONUM(from_type)
DEFINE_ANY_CONVERT_SPEC_ALL(bool)
DEFINE_ANY_CONVERT_SPEC_ALL(char)
DEFINE_ANY_CONVERT_SPEC_ALL(signed char)
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned char)
DEFINE_ANY_CONVERT_SPEC_ALL(wchar_t)
DEFINE_ANY_CONVERT_SPEC_ALL(short int)
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned short int)
DEFINE_ANY_CONVERT_SPEC_ALL(int)
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned int)
DEFINE_ANY_CONVERT_SPEC_ALL(long int)
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned long int)
DEFINE_ANY_CONVERT_SPEC_ALL(long long int)
DEFINE_ANY_CONVERT_SPEC_ALL(unsigned long long int)
DEFINE_ANY_CONVERT_SPEC_ALL(double)
DEFINE_ANY_CONVERT_SPEC_ALL(float)
DEFINE_ANY_CONVERT_SPEC_ALL(long double)
#undef DEFINE_ANY_CONVERT_SPEC
#undef DEFINE_ANY_CONVERT_SPEC_STATIC
#undef DEFINE_ANY_CONVERT_SPEC_NUMTOSTRING
#undef DEFINE_ANY_CONVERT_SPEC_STRINGTONUM
#undef DEFINE_ANY_CONVERT_SPEC_ALL
} // ns
#endif
/// @}
-424
View File
@@ -1,424 +0,0 @@
/**************************************************************************
Copyright:
(C) 2000 - 2010 Kevlin Henney
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_boost_1_0.txt file
***************************************************************************/
/// \file
/// \author Kevlin Henney
/// \author Alexander Shaduri
/// \ingroup hz
/// \weakgroup hz
/// @{
#ifndef HZ_ANY_TYPE_H
#define HZ_ANY_TYPE_H
#include "hz_config.h" // feature macros
/**
\file
any_type library (any type one-element container), based on boost::any.
Original notes and copyright info follow:
// what: variant type boost::any
// who: contributed by Kevlin Henney,
// with features contributed and bugs found by
// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
// when: July 2001
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Compilation options:
// - Define DISABLE_ANY_CONVERT=1 to disable all .convert functions
// (avoids dependency on any_convert.h)
*/
#include <typeinfo> // std::type_info
#include <iosfwd> // std::ostream
#include <string> // to enable std::string printing. <string> is included already from any_type_holder.h.
#include "type_properties.h"
#include "bad_cast_exception.h"
#include "any_type_holder.h"
namespace hz {
/// An object of this type can contain any variable of any type in it.
class any_type {
public:
/// Constructor
any_type()
: content(0)
{ }
/// Construct from a value
template<typename ValueType>
any_type(const ValueType& value)
: content(new internal::AnyHolder<ValueType>(value))
{ }
/// Copy constructor
any_type(const any_type& other)
: content(other.content ? other.content->clone() : 0)
{ }
/// Destructor
~any_type()
{
delete content;
}
/// Swap *this with rhs
inline any_type& swap(any_type& rhs);
/// Check whether the wrapped variable is set
bool empty() const
{
return !content;
}
/// Remove the wrapped variable
void clear()
{
delete content;
content = 0;
}
/// Get type info of the wrapped variable
const std::type_info& type() const
{
return (content ? content->type() : typeid(void));
}
/// Check whether the wrapped variable is of type T.
template<typename T> inline
bool is_type() const; // e.g. is_type<int>
/// Get the value into a variable of _exactly_ the same type.
/// \return false if casting fails
template<typename T> inline
bool get(T& put_it_here) const;
/// Get the value using _exactly_ the same type.
/// \throw bad_any_cast if casting fails
template<typename T> inline
T get() const; // this may throw if cast fails!
#if !(defined DISABLE_ANY_CONVERT && DISABLE_ANY_CONVERT)
/// Convert the value into a castable type using any_convert().
template<typename T> inline
bool convert(T& val) const;
/// Convert the value into a castable type using any_convert().
/// \throw bad_any_cast if casting fails
template<typename T> inline
T convert() const;
#endif
/// Assignment operator from specific type
template<typename ValueType>
any_type& operator= (const ValueType& value)
{
delete content;
content = new internal::AnyHolder<ValueType>(value);
return *this;
}
/// Assignment operator from another any_type
any_type& operator= (const any_type& other)
{
delete content;
content = other.content->clone();
return *this;
}
/// A helper class for easy operator<<() usage.
struct StreamHelper {
StreamHelper(internal::AnyHolderBase* c) : content(c) { }
internal::AnyHolderBase* content;
};
/// A helper function to send any_type to a stream.
/// Example: std::cerr << any_type_object.to_stream()
StreamHelper to_stream() const
{
return StreamHelper(content);
}
// helper classes for enabling <<.
/// A helper struct for operator<<()
template<typename T>
struct is_default_printable
: public type_integral_constant<bool, (type_is_integral<T>::value
|| type_is_floating_point<T>::value || type_is_pointer<T>::value)> { };
/// A helper struct for operator<<()
template<bool b>
struct printable {
static const bool value = b;
};
/// A helper struct for operator<<().
// You may specialize this to <A>, with "public printable<true>" to enable default printing
template<typename T>
struct set_printable : public printable<false> { };
/// A helper struct for operator<<()
template<typename T>
struct is_printable {
static const bool value = (is_default_printable<T>::value || set_printable<T>::value);
};
internal::AnyHolderBase* content; ///< Pointer to internal::AnyHolder<T>
};
/// Operator<<() for any_type::StreamHelper. See any_type::to_stream().
inline std::ostream& operator<< (std::ostream& os, const any_type::StreamHelper& sh)
{
if (sh.content)
sh.content->to_stream(os);
return os;
}
/// This is thrown in case of bad reference casts
DEFINE_BAD_CAST_EXCEPTION(bad_any_cast,
"Data type mismatch for AnyType. Original type: \"%s\", requested type: \"%s\".",
"Data type mismatch for AnyType.");
// ---------------------------------------------------------
// any_cast operators
/// Cast a "pointer to any_type" to a "pointer to value_type"
template<typename ValueType>
ValueType any_cast(any_type* operand)
{
typedef typename type_remove_pointer<ValueType>::type nopointer;
if (operand && operand->content
&& operand->type() == typeid(nopointer)
) {
return &static_cast<internal::AnyHolder<nopointer>*>(operand->content)->value;
}
return 0;
}
/// Cast a "pointer to any_type" to a "pointer to value_type"
template<typename ValueType>
const ValueType any_cast(const any_type* operand)
{
return any_cast<ValueType>(const_cast<any_type*>(operand));
}
/// Cast an any_type object to value_type
template<typename ValueType>
ValueType any_cast(any_type& operand)
{
typedef typename type_remove_reference<ValueType>::type nonref;
if (!operand.content)
throw bad_any_cast(operand.type(), typeid(nonref));
if (operand.type() != typeid(nonref))
throw bad_any_cast(operand.type(), typeid(nonref));
return static_cast<internal::AnyHolder<nonref>*>(operand.content)->value;
}
/// Cast an any_type object to value_type
template<typename ValueType>
ValueType any_cast(const any_type& operand)
{
typedef typename type_remove_reference<ValueType>::type nonref;
if (!operand.content)
throw bad_any_cast(operand.type(), typeid(nonref));
if (operand.type() != typeid(nonref))
throw bad_any_cast(operand.type(), typeid(nonref));
return static_cast<const internal::AnyHolder<nonref>*>(operand.content)->value;
}
// ---------------------------------------------------------
inline any_type& any_type::swap(any_type& rhs)
{
// don't use std::swap(), we don't need <algorithm> just for one function.
internal::AnyHolderBase* tmp = rhs.content;
rhs.content = content;
content = tmp;
return *this;
}
template<typename T> inline
bool any_type::is_type() const
{
// without rtti, any_cast<T*> will always return true.
return static_cast<bool>(any_cast<T*>(this));
}
template<typename T> inline
bool any_type::get(T& put_it_here) const
{
T* a = any_cast<T*>(this);
if (!a)
return false;
put_it_here = *a;
return true;
}
template<typename T> inline
T any_type::get() const
{
return any_cast<T>(*this);
}
#if !(defined DISABLE_ANY_CONVERT && DISABLE_ANY_CONVERT)
template<typename T> inline
bool any_type::convert(T& val) const
{
return (content ? content->convert(val) : false);
}
template<typename T> inline
T any_type::convert() const
{
typedef typename type_remove_reference<T>::type nonref;
nonref result;
if (!this->convert(result))
throw bad_any_cast(this->type(), typeid(nonref));
return result;
}
#endif
// ---------------------------------------------------------
namespace internal {
/// You may specialize this for <T, true> to enable custom printing.
template <class ValueType, bool b = !any_type::is_printable<ValueType>::value >
struct AnyPrinter {
static void to_stream(std::ostream& os, const ValueType& value)
{
os << "[non-representable]";
}
};
/// Specialization
template <class ValueType>
struct AnyPrinter<ValueType, false> {
static void to_stream(std::ostream& os, const ValueType& value)
{
os << value;
}
};
template<typename ValueType> inline
void AnyHolder<ValueType>::to_stream(std::ostream& os) const
{
AnyPrinter<ValueType>::to_stream(os, value);
}
}
// Do NOT define operator<< for any_type !
// Since any C++ type is implicitly convertable to any_type, and it will
// serve all unrelated types and may even end up in an endless loop.
/// Use this to add supported types to any_type::to_stream().
/// Any type may be added if it supports operator <<.
#define ANY_TYPE_SET_PRINTABLE(type, truefalse) \
namespace hz { \
template<> struct any_type::set_printable<type> : public any_type::printable<truefalse> { }; \
}
} // ns
/// Make std::string printable using any_type::to_stream().
ANY_TYPE_SET_PRINTABLE(std::string, true)
#endif
/// @}
-169
View File
@@ -1,169 +0,0 @@
/**************************************************************************
Copyright:
(C) 2000 - 2010 Kevlin Henney
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_boost_1_0.txt file
***************************************************************************/
/// \file
/// \author Kevlin Henney
/// \author Alexander Shaduri
/// \ingroup hz
/// \weakgroup hz
/// @{
#ifndef HZ_ANY_TYPE_HOLDER_H
#define HZ_ANY_TYPE_HOLDER_H
#include "hz_config.h" // feature macros
/**
\file
Internal header, do not include manually.
*/
#include <typeinfo> // std::type_info
#include <iosfwd> // std::ostream
#include <string>
#if !(defined DISABLE_ANY_CONVERT && DISABLE_ANY_CONVERT)
#include "any_convert.h" // any_convert
#endif
namespace hz {
namespace internal {
/// Base class for content of hz::any_type
struct AnyHolderBase {
/// Virtual destructor
virtual ~AnyHolderBase() { }
/// Get std::type_info for the wrapped variable
virtual const std::type_info& type() const = 0;
/// Clone the wrapped variable
virtual AnyHolderBase* clone() const = 0;
/// Send the wrapped variable to std::ostream
virtual void to_stream(std::ostream& os) const = 0;
#if !(defined DISABLE_ANY_CONVERT && DISABLE_ANY_CONVERT)
/// Convert the wrapped variable to argument type
virtual bool convert(bool& val) const = 0;
virtual bool convert(char& val) const = 0;
virtual bool convert(signed char& val) const = 0;
virtual bool convert(unsigned char& val) const = 0;
virtual bool convert(wchar_t& val) const = 0;
virtual bool convert(short int& val) const = 0;
virtual bool convert(unsigned short int& val) const = 0;
virtual bool convert(int& val) const = 0;
virtual bool convert(unsigned int& val) const = 0;
virtual bool convert(long int& val) const = 0;
virtual bool convert(unsigned long int& val) const = 0;
virtual bool convert(long long int& val) const = 0;
virtual bool convert(unsigned long long int& val) const = 0;
virtual bool convert(double& val) const = 0;
virtual bool convert(float& val) const = 0;
virtual bool convert(long double& val) const = 0;
virtual bool convert(std::string& val) const = 0;
#endif // DISABLE_ANY_CONVERT
};
/// Child class for content, holds the actual value
template<typename ValueType>
struct AnyHolder : public AnyHolderBase {
/// Type of the wrapped variable
typedef ValueType value_type;
/// Constructor
AnyHolder(const ValueType& val)
: value(val)
{ }
/// Get std::type_info object for the wrapped variable
const std::type_info& type() const
{
return typeid(ValueType);
}
/// Clone the wrapped variable. Note that this is not a deep clone.
AnyHolderBase* clone() const
{
return new AnyHolder(value);
}
/// Send the wrapped variable to std::ostream
inline void to_stream(std::ostream& os) const;
// {
// AnyPrinter<ValueType>::to_stream(os, value);
// }
#if !(defined DISABLE_ANY_CONVERT && DISABLE_ANY_CONVERT)
// Reimplemented from AnyHolderBase
bool convert(bool& val) const { return any_convert(value, val); }
bool convert(char& val) const { return any_convert(value, val); }
bool convert(signed char& val) const { return any_convert(value, val); }
bool convert(unsigned char& val) const { return any_convert(value, val); }
bool convert(wchar_t& val) const { return any_convert(value, val); }
bool convert(short int& val) const { return any_convert(value, val); }
bool convert(unsigned short int& val) const { return any_convert(value, val); }
bool convert(int& val) const { return any_convert(value, val); }
bool convert(unsigned int& val) const { return any_convert(value, val); }
bool convert(long int& val) const { return any_convert(value, val); }
bool convert(unsigned long int& val) const { return any_convert(value, val); }
bool convert(long long int& val) const { return any_convert(value, val); }
bool convert(unsigned long long int& val) const { return any_convert(value, val); }
bool convert(double& val) const { return any_convert(value, val); }
bool convert(float& val) const { return any_convert(value, val); }
bool convert(long double& val) const { return any_convert(value, val); }
bool convert(std::string& val) const { return any_convert(value, val); }
#endif // DISABLE_ANY_CONVERT
ValueType value; ///< The wrapped data
};
} // ns
} // ns
#endif
/// @}
-160
View File
@@ -1,160 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_unlicense.txt
***************************************************************************/
/// \file
/// \author Alexander Shaduri
/// \ingroup hz_tests
/// \weakgroup hz_tests
/// @{
// disable libdebug, we don't link to it
#undef HZ_USE_LIBDEBUG
#define HZ_USE_LIBDEBUG 0
// enable libdebug emulation through std::cerr
#undef HZ_EMULATE_LIBDEBUG
#define HZ_EMULATE_LIBDEBUG 1
// define this to disable any_convert.h dependency
// #define DISABLE_ANY_CONVERT
// The first header should be then one we're testing, to avoid missing
// header pitfalls.
#include "any_type.h"
#include <iostream>
#include <list>
#include <string>
using namespace hz;
/// TestClass test structure
struct TestClass {
typedef std::list<any_type> any_list;
void append_int(any_list& values, int value)
{
any_type to_append = value;
values.push_back(to_append);
}
void append_string(any_list& values, const std::string& value)
{
values.push_back(value);
}
void append_char_ptr(any_list& values, const char* value)
{
values.push_back(value);
}
void append_any(any_list& values, const any_type& value)
{
values.push_back(value);
}
void append_nothing(any_list& values)
{
values.push_back(any_type());
}
std::string get_string(any_list& values)
{
any_type a = values.back();
any_cast<std::string>(a);
std::string b;
a.get(b);
a.get<std::string>();
if (a.is_type<std::string>())
return any_cast<std::string>(a);
return std::string();
}
};
/// enable printing TestClass.
/// This needs operator<< and and ANY_TYPE_SET_PRINTABLE specialization.
inline std::ostream& operator<< (std::ostream& os, TestClass a)
{
return (os << "TestClass\n");
}
ANY_TYPE_SET_PRINTABLE(TestClass, true);
/// Main function for the test
int main()
{
any_type a1;
a1 = 4;
std::cerr << a1.to_stream() << "\n";
TestClass b;
any_type b1 = b;
// std::cerr << b;
std::cerr << b1.to_stream() << "\n";
#if !(defined DISABLE_ANY_CONVERT && DISABLE_ANY_CONVERT)
any_type a2 = std::string("5.444");
double a2val = 0;
std::cerr << "conversion " << (a2.convert(a2val) ? "succeeded" : "failed") << ", ";
std::cerr << "value: " << a2val << "\n";
any_type a3 = 6.55;
std::string a3val;
std::cerr << "conversion " << (a3.convert(a3val) ? "succeeded" : "failed") << ", ";
std::cerr << "value: " << a3val << "\n";
any_type a4 = std::string("7");
int a4val = 0;
std::cerr << "conversion " << (a4.convert(a4val) ? "succeeded" : "failed") << ", ";
std::cerr << "value: " << a4val << "\n";
any_type a5 = 'a';
double a5val = 0;
std::cerr << "conversion " << (a5.convert(a5val) ? "succeeded" : "failed") << ", ";
std::cerr << "value: " << a5val << "\n";
char b1val = 0;
std::cerr << "conversion " << (b1.convert(b1val) ? "succeeded" : "failed") << ", ";
std::cerr << "value: " << int(b1val) << "\n";
#endif
return 0;
}
/// @}
-33
View File
@@ -447,39 +447,6 @@ T get_data(const std::string& path)
/// Similar to get_data(), but with looser conversion - can convert between
/// C++ built-in types and std::string. Uses hz::any_convert<>.
/// \return false if casting failed, or empty or invalid type.
template<typename T> inline
bool convert_data(const std::string& path, T& put_it_here) // returns false if cast failed
{
ConfigLockPolicy::ScopedLock locker(RootHolder::mutex);
node_ptr node = get_node(path);
if (!node)
return false; // no such node
return node->convert_data(put_it_here);
}
/// Similar to get_data(), but with looser conversion - can convert between
/// C++ built-in types and std::string. Uses hz::any_convert<>.
/// \throw rmn::no_such_node No such node
/// \throw rmn::empty_data_retrieval Data is empty
/// \throw rmn::type_mismatch Type mismatch
template<typename T> inline
T convert_data(const std::string& path)
{
ConfigLockPolicy::ScopedLock locker(RootHolder::mutex);
node_ptr node = get_node(path);
if (!node)
throw rmn::no_such_node(path);
return node->convert_data<T>();
}
+8 -9
View File
@@ -66,17 +66,16 @@ int main()
// loose typing:
int int_var2 = 0;
rconfig::convert_data("app/int_var2", int_var2); // this will do the type conversion
std::cerr << "app/int_var2: " << int_var2 << "\n"; // this will get out 11, not 10 (default)
// int int_var2 = 0;
// rconfig::convert_data("app/int_var2", int_var2); // this will do the type conversion
// std::cerr << "app/int_var2: " << int_var2 << "\n"; // this will get out 11, not 10 (default)
// std::cerr << "app/some_string1: " << rconfig::convert_data<std::string>("app/some_string1") << "\n";
std::cerr << "app/some_string1: " << rconfig::convert_data<std::string>("app/some_string1") << "\n";
std::string huh;
rconfig::convert_data("app/huh", huh); // float -> string conversion, should work.
std::cerr << "app/huh: " << huh << "\n";
// std::string huh;
// rconfig::convert_data("app/huh", huh); // float -> string conversion, should work.
// std::cerr << "app/huh: " << huh << "\n";
std::cerr << "\"app/empty\" exists: " << std::boolalpha << rconfig::data_is_empty("app/empty") << "\n";
+18 -43
View File
@@ -31,8 +31,8 @@
#include <string>
#include <iosfwd> // std::ostream
#include <any>
#include "hz/any_type.h"
#include "resource_data_types.h"
#include "resource_exception.h"
@@ -56,7 +56,11 @@ struct ResourceDataAnyDumper {
/// Dump resource data into \c os
void dump(std::ostream& os) const
{
os << obj->data_.to_stream();
const std::type_info& type = obj->data_.type();
if (type == typeid(char)) {
os << std::any_cast<char>(std::any_cast<char>(obj->data_));
}
// TODO other types.
}
T* obj; ///< ResourceDataAny object
@@ -98,14 +102,14 @@ class ResourceDataAny {
/// Check whether data is empty
bool data_is_empty() const
{
return data_.empty();
return !data_.has_value();
}
/// Clear the data, making it empty
void clear_data()
{
data_.clear();
data_.reset();
}
@@ -131,7 +135,7 @@ class ResourceDataAny {
template<typename T>
inline bool data_is_type() const
{
return data_.template is_type<T>();
return data_.type() == typeid(T);
}
@@ -140,7 +144,11 @@ class ResourceDataAny {
template<typename T>
inline bool get_data(T& put_it_here) const
{
return data_.get(put_it_here); // returns false if empty or invalid type
if (const T* value = std::any_cast<T>(&data_)) {
put_it_here = *value;
return true;
}
return false;
}
@@ -150,52 +158,19 @@ class ResourceDataAny {
template<typename T>
T get_data() const
{
if (data_.empty())
if (!data_.has_value())
throw empty_data_retrieval();
try {
// template is needed for gcc 3.3
return data_.template get<T>(); // won't work if empty or invalid type
return std::any_cast<T>(data_);
}
catch (hz::bad_any_cast& e) { // convert any_type exception to rmn exception.
catch (std::bad_any_cast& e) { // convert std::any exception to rmn exception.
throw type_mismatch(data_.type(), typeid(T));
}
}
/// Similar to get_data(), but with looser conversion - can convert between
/// C++ built-in types and std::string. Uses hz::any_convert<>.
/// \return false if casting failed, or empty or invalid type.
template<typename T>
inline bool convert_data(T& put_it_here) const
{
return data_.convert(put_it_here);
}
/// Similar to get_data(), but with looser conversion - can convert between
/// C++ built-in types and std::string. Uses hz::any_convert<>.
/// \throw rmn::empty_data_retrieval Data is empty
/// \throw rmn::type_mismatch Type mismatch
template<typename T>
T convert_data() const
{
if (data_.empty())
throw empty_data_retrieval();
try {
// Note: This throws only if RTTI is enabled.
// template is needed for gcc 3.3
return data_.template convert<T>(); // won't work if empty or invalid type
}
catch (hz::bad_any_cast& e) {
throw type_convert_error(data_.type(), typeid(T));
}
}
template<class T>
friend struct ResourceDataAnyDumper;
@@ -210,7 +185,7 @@ class ResourceDataAny {
private:
hz::any_type data_; ///< The data
std::any data_; ///< The data
};
-20
View File
@@ -173,26 +173,6 @@ class ResourceDataOne {
}
/// Get data (use static_cast conversion).
template<typename T>
inline bool convert_data(T& put_it_here) const // returns false if cast failed
{
put_it_here = static_cast<T>(data_);
return true; // static_cast will check it at compile-time.
}
/// Get a copy of data (use static_cast conversion).
/// \throw rmn::empty_data_retrieval if data is empty
template<typename T>
T convert_data() const
{
if (empty_)
throw empty_data_retrieval();
return static_cast<T>(data_);
}
template<class T>
friend struct ResourceDataOneDumper;