Cleaned up the Variant class.

This commit is contained in:
Gunnar Beutner 2012-07-11 20:55:46 +02:00
parent 6c03c495b5
commit 1405d1961a
13 changed files with 146 additions and 287 deletions

View File

@ -400,7 +400,7 @@ int Application::Run(int argc, char **argv)
Application::m_Instance.reset();
Logger::Write(LogCritical, "base", "---");
Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(ex));
Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(typeid(ex)));
Logger::Write(LogCritical, "base", "Message: " + string(ex.what()));
return EXIT_FAILURE;

View File

@ -57,27 +57,6 @@ public:
return true;
}
/**
* Retrieves a value from the dictionary.
*
* @param key The key.
* @param[out] value Pointer to the value.
* @returns true if the value was retrieved, false otherwise.
*/
bool Get(const string& key, Dictionary::Ptr *value)
{
Object::Ptr object;
if (!Get(key, &object))
return false;
*value = dynamic_pointer_cast<Dictionary>(object);
if (!*value)
throw runtime_error("Object is not a dictionary.");
return true;
}
/**
* Sets a value in the dictionary.
*

View File

@ -108,11 +108,14 @@ using std::ostream;
using std::ofstream;
using std::exception;
using std::bad_cast;
using std::runtime_error;
using std::logic_error;
using std::invalid_argument;
using std::domain_error;
using std::type_info;
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
@ -121,6 +124,8 @@ using std::domain_error;
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/thread.hpp>
#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>
using boost::shared_ptr;
using boost::weak_ptr;

View File

@ -24,6 +24,30 @@ using namespace icinga;
bool I2_EXPORT Utility::m_SSLInitialized = false;
/**
* Returns a human-readable type name of a type_info object.
*
* @param ti A type_info object.
* @returns The type name of the object.
*/
string Utility::GetTypeName(const type_info& ti)
{
string klass = ti.name();
#ifdef HAVE_GCC_ABI_DEMANGLE
int status;
char *realname = abi::__cxa_demangle(klass.c_str(), 0, 0, &status);
if (realname != NULL) {
klass = string(realname);
free(realname);
}
#endif /* HAVE_GCC_ABI_DEMANGLE */
return klass;
}
/**
* Detaches from the controlling terminal.
*/

View File

@ -31,29 +31,7 @@ namespace icinga
class I2_BASE_API Utility
{
public:
/**
* Returns a human-readable type name of an object (using RTTI).
*
* @param value An object.
* @returns The type name of the object.
*/
template<class T>
static string GetTypeName(const T& value)
{
string klass = typeid(value).name();
#ifdef HAVE_GCC_ABI_DEMANGLE
int status;
char *realname = abi::__cxa_demangle(klass.c_str(), 0, 0, &status);
if (realname != NULL) {
klass = string(realname);
free(realname);
}
#endif /* HAVE_GCC_ABI_DEMANGLE */
return klass;
}
static string GetTypeName(const type_info& ti);
static void Daemonize(void);

View File

@ -21,94 +21,6 @@
using namespace icinga;
/**
* Converts the variant's value to a new type.
*
* @param newType The new type of the variant.
*/
void Variant::Convert(VariantType newType) const
{
if (newType == m_Type)
return;
if (m_Type == VariantString && newType == VariantInteger) {
m_IntegerValue = strtol(m_StringValue.c_str(), NULL, 10);
m_Type = VariantInteger;
return;
}
if (m_Type == VariantInteger && newType == VariantString) {
stringstream sbuf;
sbuf << m_IntegerValue;
m_StringValue = sbuf.str();
m_Type = VariantString;
return;
}
// TODO: convert variant data
throw runtime_error("Invalid variant conversion.");
}
/**
* Retrieves the variant value's type.
*
* @returns The variant's type.
*/
VariantType Variant::GetType(void) const
{
return m_Type;
}
/**
* Retrieves the variant's value as an integer.
*
* @returns The variant's value as an integer.
*/
long Variant::GetInteger(void) const
{
Convert(VariantInteger);
return m_IntegerValue;
}
/**
* Retrieves the variant's value as a bool.
*
* @returns The variant's value as a bool.
*/
bool Variant::GetBool(void) const
{
Convert(VariantInteger);
return (m_IntegerValue != 0);
}
/**
* Retrieves the variant's value as a string.
*
* @returns The variant's value as a string.
*/
string Variant::GetString(void) const
{
Convert(VariantString);
return m_StringValue;
}
/**
* Retrieves the variant's value as an object.
*
* @returns The variant's value as an object.
*/
Object::Ptr Variant::GetObject(void) const
{
Convert(VariantObject);
return m_ObjectValue;
}
/**
* Checks whether the variant is empty.
*
@ -116,45 +28,15 @@ Object::Ptr Variant::GetObject(void) const
*/
bool Variant::IsEmpty(void) const
{
return (m_Type == VariantEmpty);
return (m_Value.empty());
}
/**
* Retrieves the variant's value as an integer.
*
* @returns The variant's value as an integer.
*/
Variant::operator long(void) const
bool Variant::IsScalar(void) const
{
return GetInteger();
return !IsEmpty() && !IsObject();
}
/**
* Retrieves the variant's value as a bool.
*
* @returns The variant's value as a bool.
*/
Variant::operator bool(void) const
bool Variant::IsObject(void) const
{
return GetBool();
}
/**
* Retrieves the variant's value as a string.
*
* @returns The variant's value as a string.
*/
Variant::operator string(void) const
{
return GetString();
}
/**
* Retrieves the variant's value as an object.
*
* @returns The variant's value as an object.
*/
Variant::operator Object::Ptr(void) const
{
return GetObject();
return !IsEmpty() && (m_Value.type() == typeid(Object::Ptr));
}

View File

@ -23,20 +23,6 @@
namespace icinga
{
/**
* The type of a Variant object.
*
* @ingroup base
*/
enum VariantType
{
VariantEmpty, /**< Denotes that the Variant is empty. */
VariantInteger, /**< Denotes that the Variant is holding an integer. */
VariantString, /**< Denotes that the Variant is holding a string. */
VariantObject /**< Denotes that the Variant is holding an object
that inherits from the Object class. */
};
/**
* A type that can hold an arbitrary value.
*
@ -45,52 +31,81 @@ enum VariantType
class I2_BASE_API Variant
{
public:
inline Variant(void) : m_Type(VariantEmpty) { }
inline Variant(void)
: m_Value()
{ }
inline Variant(int value)
: m_Type(VariantInteger), m_IntegerValue(value) { }
inline Variant(double value)
: m_Value(value)
{ }
inline Variant(bool value)
: m_Type(VariantInteger), m_IntegerValue(value ? 1 : 0) { }
inline Variant(long value)
: m_Type(VariantInteger), m_IntegerValue(value) { }
inline Variant(const string& value)
: m_Value(value)
{ }
inline Variant(const char *value)
: m_Type(VariantString), m_StringValue(string(value)) { }
inline Variant(string value)
: m_Type(VariantString), m_StringValue(value) { }
: m_Value(string(value))
{ }
template<typename T>
Variant(const shared_ptr<T>& value)
: m_Type(VariantObject), m_ObjectValue(value) { }
inline Variant(const shared_ptr<T>& value)
{
Object::Ptr object = dynamic_pointer_cast<Object>(value);
VariantType GetType(void) const;
if (!object)
throw invalid_argument("shared_ptr value type must inherit from Object class.");
long GetInteger(void) const;
bool GetBool(void) const;
string GetString(void) const;
Object::Ptr GetObject(void) const;
m_Value = object;
}
operator double(void) const
{
if (m_Value.type() != typeid(double)) {
double result = boost::lexical_cast<double>(m_Value);
m_Value = result;
return result;
} else {
return boost::get<double>(m_Value);
}
}
operator string(void) const
{
if (m_Value.type() != typeid(string)) {
string result = boost::lexical_cast<string>(m_Value);
m_Value = result;
return result;
} else {
return boost::get<string>(m_Value);
}
}
template<typename T>
operator shared_ptr<T>(void) const
{
shared_ptr<T> object = dynamic_pointer_cast<T>(boost::get<Object::Ptr>(m_Value));
if (!object)
throw bad_cast();
return object;
}
bool IsEmpty(void) const;
bool IsScalar(void) const;
bool IsObject(void) const;
operator long(void) const;
operator bool(void) const;
operator string(void) const;
operator Object::Ptr(void) const;
template<typename T>
bool IsObjectType(void) const
{
if (!IsObject())
return false;
return (dynamic_pointer_cast<T>(boost::get<Object::Ptr>(m_Value)));
}
private:
mutable VariantType m_Type; /**< The type of the Variant. */
mutable long m_IntegerValue; /**< The value of the Variant
if m_Type == VariantInteger */
mutable string m_StringValue; /**< The value of the Variant
if m_Type == VariantString */
mutable Object::Ptr m_ObjectValue; /**< The value of the Variant
if m_Type == VariantObject */
void Convert(VariantType newType) const;
mutable boost::variant<double, string, Object::Ptr> m_Value;
};
}

View File

@ -125,13 +125,10 @@ void ConvenienceComponent::HostCommittedHandler(const ConfigItem::Ptr& item)
CopyServiceAttributes(host, host->GetProperties(), builder);
if (svcdesc.GetType() == VariantString) {
if (svcdesc.IsScalar()) {
builder->AddParent(svcdesc);
} else if (svcdesc.GetType() == VariantObject) {
Dictionary::Ptr service = dynamic_pointer_cast<Dictionary>(svcdesc.GetObject());
if (!service)
throw invalid_argument("Service description invalid.");
} else if (svcdesc.IsObjectType<Dictionary>()) {
Dictionary::Ptr service = svcdesc;
string parent;
if (!service->Get("service", &parent))
@ -154,7 +151,7 @@ void ConvenienceComponent::HostCommittedHandler(const ConfigItem::Ptr& item)
if (oldServices) {
Dictionary::Iterator it;
for (it = oldServices->Begin(); it != oldServices->End(); it++) {
ConfigItem::Ptr service = static_pointer_cast<ConfigItem>(it->second.GetObject());
ConfigItem::Ptr service = it->second;
if (!newServices->Contains(service->GetName()))
service->Unregister();
@ -182,7 +179,7 @@ void ConvenienceComponent::HostRemovedHandler(const ConfigItem::Ptr& item)
Dictionary::Iterator it;
for (it = services->Begin(); it != services->End(); it++) {
ConfigItem::Ptr service = static_pointer_cast<ConfigItem>(it->second.GetObject());
ConfigItem::Ptr service = it->second;
service->Unregister();
}
}

View File

@ -327,16 +327,12 @@ bool DiscoveryComponent::HasMessagePermission(const Dictionary::Ptr& roles, cons
for (ConfigObject::TMap::Iterator ip = range.first; ip != range.second; ip++) {
ConfigObject::Ptr role = ip->second;
Object::Ptr object;
if (!role->GetProperty(messageType, &object))
Dictionary::Ptr permissions;
if (!role->GetProperty(messageType, &permissions))
continue;
Dictionary::Ptr permissions = dynamic_pointer_cast<Dictionary>(object);
if (!permissions)
throw runtime_error("Object is not a dictionary.");
for (Dictionary::Iterator is = permissions->Begin(); is != permissions->End(); is++) {
if (Utility::Match(is->second.GetString(), message))
if (Utility::Match(is->second, message))
return true;
}
}
@ -372,14 +368,8 @@ void DiscoveryComponent::ProcessDiscoveryMessage(const string& identity, const D
ConfigObject::Ptr endpointConfig = ConfigObject::GetObject("endpoint", identity);
Dictionary::Ptr roles;
if (endpointConfig) {
Object::Ptr object;
if (endpointConfig->GetProperty("roles", &object)) {
roles = dynamic_pointer_cast<Dictionary>(object);
if (!roles)
throw runtime_error("Object is not a dictionary.");
}
}
if (endpointConfig)
endpointConfig->GetProperty("roles", &roles);
Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(identity);

View File

@ -535,9 +535,9 @@ static const yytype_int8 yyrhs[] =
static const yytype_uint8 yyrline[] =
{
0, 94, 94, 95, 98, 98, 101, 107, 112, 107,
132, 133, 136, 140, 146, 147, 150, 157, 158, 162,
161, 173, 174, 176, 177, 178, 181, 189, 203, 212,
213, 214, 215, 216, 222, 227, 231, 237, 238
131, 132, 135, 139, 145, 146, 149, 156, 157, 161,
160, 172, 173, 175, 176, 177, 180, 188, 202, 211,
212, 213, 214, 215, 221, 226, 230, 236, 237
};
#endif
@ -1582,9 +1582,8 @@ yyreduce:
/* Line 1806 of yacc.c */
#line 118 "config_parser.yy"
{
Object::Ptr exprl_object = *(yyvsp[(8) - (8)].variant);
ExpressionList::Ptr exprl = *(yyvsp[(8) - (8)].variant);
delete (yyvsp[(8) - (8)].variant);
ExpressionList::Ptr exprl = dynamic_pointer_cast<ExpressionList>(exprl_object);
m_Item->AddExpressionList(exprl);
m_Item->SetLocal(m_Local);
@ -1598,7 +1597,7 @@ yyreduce:
case 12:
/* Line 1806 of yacc.c */
#line 137 "config_parser.yy"
#line 136 "config_parser.yy"
{
m_Abstract = true;
}
@ -1607,7 +1606,7 @@ yyreduce:
case 13:
/* Line 1806 of yacc.c */
#line 141 "config_parser.yy"
#line 140 "config_parser.yy"
{
m_Local = true;
}
@ -1616,7 +1615,7 @@ yyreduce:
case 16:
/* Line 1806 of yacc.c */
#line 151 "config_parser.yy"
#line 150 "config_parser.yy"
{
m_Item->AddParent((yyvsp[(1) - (1)].text));
free((yyvsp[(1) - (1)].text));
@ -1626,7 +1625,7 @@ yyreduce:
case 19:
/* Line 1806 of yacc.c */
#line 162 "config_parser.yy"
#line 161 "config_parser.yy"
{
m_ExpressionLists.push(boost::make_shared<ExpressionList>());
}
@ -1635,7 +1634,7 @@ yyreduce:
case 20:
/* Line 1806 of yacc.c */
#line 167 "config_parser.yy"
#line 166 "config_parser.yy"
{
(yyval.variant) = new Variant(m_ExpressionLists.top());
m_ExpressionLists.pop();
@ -1645,7 +1644,7 @@ yyreduce:
case 26:
/* Line 1806 of yacc.c */
#line 182 "config_parser.yy"
#line 181 "config_parser.yy"
{
Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc);
free((yyvsp[(1) - (3)].text));
@ -1658,7 +1657,7 @@ yyreduce:
case 27:
/* Line 1806 of yacc.c */
#line 190 "config_parser.yy"
#line 189 "config_parser.yy"
{
Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc);
free((yyvsp[(3) - (6)].text));
@ -1677,7 +1676,7 @@ yyreduce:
case 28:
/* Line 1806 of yacc.c */
#line 204 "config_parser.yy"
#line 203 "config_parser.yy"
{
Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc);
free((yyvsp[(1) - (1)].text));
@ -1689,7 +1688,7 @@ yyreduce:
case 33:
/* Line 1806 of yacc.c */
#line 217 "config_parser.yy"
#line 216 "config_parser.yy"
{
(yyval.op) = (yyvsp[(1) - (1)].op);
}
@ -1698,7 +1697,7 @@ yyreduce:
case 34:
/* Line 1806 of yacc.c */
#line 223 "config_parser.yy"
#line 222 "config_parser.yy"
{
(yyval.variant) = new Variant((yyvsp[(1) - (1)].text));
free((yyvsp[(1) - (1)].text));
@ -1708,7 +1707,7 @@ yyreduce:
case 35:
/* Line 1806 of yacc.c */
#line 228 "config_parser.yy"
#line 227 "config_parser.yy"
{
(yyval.variant) = new Variant((yyvsp[(1) - (1)].num));
}
@ -1717,7 +1716,7 @@ yyreduce:
case 36:
/* Line 1806 of yacc.c */
#line 232 "config_parser.yy"
#line 231 "config_parser.yy"
{
(yyval.variant) = new Variant();
}
@ -1726,7 +1725,7 @@ yyreduce:
case 38:
/* Line 1806 of yacc.c */
#line 239 "config_parser.yy"
#line 238 "config_parser.yy"
{
(yyval.variant) = (yyvsp[(1) - (1)].variant);
}
@ -1735,7 +1734,7 @@ yyreduce:
/* Line 1806 of yacc.c */
#line 1739 "config_parser.cc"
#line 1738 "config_parser.cc"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@ -1973,6 +1972,6 @@ yyreturn:
/* Line 2067 of yacc.c */
#line 243 "config_parser.yy"
#line 242 "config_parser.yy"

View File

@ -116,9 +116,8 @@ attributes T_OBJECT T_IDENTIFIER T_STRING
}
inherits_specifier expressionlist
{
Object::Ptr exprl_object = *$8;
ExpressionList::Ptr exprl = *$8;
delete $8;
ExpressionList::Ptr exprl = dynamic_pointer_cast<ExpressionList>(exprl_object);
m_Item->AddExpressionList(exprl);
m_Item->SetLocal(m_Local);

View File

@ -32,10 +32,11 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
ExpressionList::Ptr valueExprl;
Dictionary::Ptr valueDict;
if (m_Value.GetType() == VariantObject) {
valueExprl = dynamic_pointer_cast<ExpressionList>(m_Value.GetObject());
valueDict = dynamic_pointer_cast<Dictionary>(m_Value.GetObject());
}
if (m_Value.IsObjectType<ExpressionList>())
valueExprl = m_Value;
if (m_Value.IsObjectType<Dictionary>())
valueDict = m_Value;
newValue = m_Value;
@ -62,8 +63,8 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const
case OperatorPlus:
dictionary->Get(m_Key, &oldValue);
if (oldValue.GetType() == VariantObject)
dict = dynamic_pointer_cast<Dictionary>(oldValue.GetObject());
if (oldValue.IsObjectType<Dictionary>())
dict = oldValue;
if (!dict) {
if (!oldValue.IsEmpty()) {

View File

@ -113,21 +113,15 @@ json_t *MessagePart::GetJsonFromDictionary(const Dictionary::Ptr& dictionary)
json = cJSON_CreateObject();
for (Dictionary::Iterator i = dictionary->Begin(); i != dictionary->End(); i++) {
switch (i->second.GetType()) {
case VariantInteger:
cJSON_AddNumberToObject(json, i->first.c_str(), i->second.GetInteger());
break;
case VariantString:
valueString = i->second.GetString();
cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str());
break;
case VariantObject:
valueDictionary = dynamic_pointer_cast<Dictionary>(i->second.GetObject());
if (valueDictionary)
cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(valueDictionary));
default:
break;
if (i->second.IsScalar()) {
valueString = static_cast<string>(i->second);
cJSON_AddStringToObject(json, i->first.c_str(), valueString.c_str());
} else if (i->second.IsObjectType<Dictionary>()) {
cJSON_AddItemToObject(json, i->first.c_str(), GetJsonFromDictionary(i->second));
} else {
stringstream msgbuf;
msgbuf << "Dictionary serialization: Ignored property '" << i->first << "' (unknown type)";
Logger::Write(LogDebug, "jsonrpc", msgbuf.str());
}
}
@ -178,14 +172,10 @@ Dictionary::Ptr MessagePart::GetDictionary(void) const
*/
bool MessagePart::Get(string key, MessagePart *value) const
{
Object::Ptr object;
if (!GetDictionary()->Get(key, &object))
Dictionary::Ptr dictionary;
if (!GetDictionary()->Get(key, &dictionary))
return false;
Dictionary::Ptr dictionary = dynamic_pointer_cast<Dictionary>(object);
if (!dictionary)
throw runtime_error("Object is not a dictionary.");
*value = MessagePart(dictionary);
return true;
}