mkclass_target(application.ti application.tcpp application.thpp)
mkclass_target(configobject.ti configobject.tcpp configobject.thpp)
+mkclass_target(datetime.ti datetime.tcpp datetime.thpp)
mkclass_target(filelogger.ti filelogger.tcpp filelogger.thpp)
mkclass_target(logger.ti logger.tcpp logger.thpp)
mkclass_target(streamlogger.ti streamlogger.tcpp streamlogger.thpp)
set(base_SOURCES
application.cpp application.thpp application-version.cpp array.cpp
array-script.cpp boolean.cpp boolean-script.cpp console.cpp context.cpp
- convert.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
+ convert.cpp datetime.cpp datetime.thpp datetime-script.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp configwriter.cpp dependencygraph.cpp
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp
json-script.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
******************************************************************************/
#include "base/convert.hpp"
+#include "base/datetime.hpp"
#include <boost/lexical_cast.hpp>
using namespace icinga;
{
return val;
}
+
+double Convert::ToDateTimeValue(double val)
+{
+ return val;
+}
+
+double Convert::ToDateTimeValue(const Value& val)
+{
+ if (val.IsNumber())
+ return val;
+ else if (val.IsObjectType<DateTime>())
+ return static_cast<DateTime::Ptr>(val)->GetValue();
+ else
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Not a DateTime value."));
+}
static String ToString(const String& val);
static String ToString(const Value& val);
+ static double ToDateTimeValue(double val);
+ static double ToDateTimeValue(const Value& val);
+
private:
Convert(void);
};
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "base/datetime.hpp"
+#include "base/function.hpp"
+#include "base/functionwrapper.hpp"
+#include "base/scriptframe.hpp"
+#include "base/objectlock.hpp"
+
+using namespace icinga;
+
+static String DateTimeFormat(const String& format)
+{
+ ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
+ DateTime::Ptr self = static_cast<DateTime::Ptr>(vframe->Self);
+
+ return self->Format(format);
+}
+
+Object::Ptr DateTime::GetPrototype(void)
+{
+ static Dictionary::Ptr prototype;
+
+ if (!prototype) {
+ prototype = new Dictionary();
+ prototype->Set("format", new Function(WrapFunction(DateTimeFormat)));
+ }
+
+ return prototype;
+}
+
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "base/datetime.hpp"
+#include "base/datetime.tcpp"
+#include "base/utility.hpp"
+#include "base/primitivetype.hpp"
+
+using namespace icinga;
+
+REGISTER_TYPE_WITH_PROTOTYPE(DateTime, DateTime::GetPrototype());
+
+DateTime::DateTime(double value)
+ : m_Value(value)
+{ }
+
+DateTime::DateTime(const std::vector<Value>& args)
+{
+ if (args.empty())
+ m_Value = Utility::GetTime();
+ else if (args.size() == 3 || args.size() == 6) {
+ struct tm tms;
+ tms.tm_year = args[0] - 1900;
+ tms.tm_mon = args[1] - 1;
+ tms.tm_mday = args[2];
+
+ if (args.size() == 6) {
+ tms.tm_hour = args[3];
+ tms.tm_min = args[4];
+ tms.tm_sec = args[5];
+ } else {
+ tms.tm_hour = 0;
+ tms.tm_min = 0;
+ tms.tm_sec = 0;
+ }
+
+ tms.tm_isdst = -1;
+
+ m_Value = mktime(&tms);
+ } else if (args.size() == 1)
+ m_Value = args[0];
+ else
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid number of arguments for the DateTime constructor."));
+}
+
+double DateTime::GetValue(void) const
+{
+ return m_Value;
+}
+
+String DateTime::Format(const String& format) const
+{
+ return Utility::FormatDateTime(format.CStr(), m_Value);
+}
+
+String DateTime::ToString(void) const
+{
+ return Format("%Y-%m-%d %H:%M:%S %z");
+}
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef DATETIME_H
+#define DATETIME_H
+
+#include "base/i2-base.hpp"
+#include "base/datetime.thpp"
+#include "base/value.hpp"
+#include <vector>
+
+namespace icinga
+{
+
+/**
+ * A date/time value.
+ *
+ * @ingroup base
+ */
+class I2_BASE_API DateTime : public ObjectImpl<DateTime>
+{
+public:
+ DECLARE_OBJECT(DateTime);
+
+ DateTime(double value);
+ DateTime(const std::vector<Value>& args);
+
+ String Format(const String& format) const;
+
+ virtual double GetValue(void) const override;
+ virtual String ToString(void) const override;
+
+ static Object::Ptr GetPrototype(void);
+
+private:
+ double m_Value;
+};
+
+}
+
+#endif /* DATETIME_H */
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+library base;
+
+namespace icinga
+{
+
+vararg_constructor class DateTime
+{
+ [state, no_storage] double value {
+ get;
+ };
+};
+
+}
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <vector>
using boost::intrusive_ptr;
using boost::dynamic_pointer_cast;
IMPL_TYPE_LOOKUP();
template<typename T>
-intrusive_ptr<Object> DefaultObjectFactory(void)
+intrusive_ptr<Object> DefaultObjectFactory(const std::vector<Value>& args)
{
+ if (!args.empty())
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Constructor does not take any arguments."));
+
return new T();
}
-typedef intrusive_ptr<Object> (*ObjectFactory)(void);
-
template<typename T>
+intrusive_ptr<Object> DefaultObjectFactoryVA(const std::vector<Value>& args)
+{
+ return new T(args);
+}
+
+typedef intrusive_ptr<Object> (*ObjectFactory)(const std::vector<Value>&);
+
+template<typename T, bool VA>
struct TypeHelper
+{
+};
+
+template<typename T>
+struct TypeHelper<T, false>
{
static ObjectFactory GetFactory(void)
{
}
};
+template<typename T>
+struct TypeHelper<T, true>
+{
+ static ObjectFactory GetFactory(void)
+ {
+ return DefaultObjectFactoryVA<T>;
+ }
+};
+
/**
* Base class for all heap-allocated objects. At least one of its methods
* has to be virtual for RTTI to work.
#define REGISTER_PRIMITIVE_TYPE(type, base, prototype) \
REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, DefaultObjectFactory<type>)
+#define REGISTER_PRIMITIVE_TYPE_VA(type, base, prototype) \
+ REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, DefaultObjectFactoryVA<type>)
+
#define REGISTER_PRIMITIVE_TYPE_NOINST(type, base, prototype) \
REGISTER_PRIMITIVE_TYPE_FACTORY(type, base, prototype, NULL)
return name + "s";
}
-Object::Ptr Type::Instantiate(void) const
+Object::Ptr Type::Instantiate(const std::vector<Value>& args) const
{
ObjectFactory factory = GetFactory();
if (!factory)
BOOST_THROW_EXCEPTION(std::runtime_error("Type does not have a factory function."));
- return factory();
+ return factory(args);
}
bool Type::IsAbstract(void) const
String GetPluralName(void) const;
- Object::Ptr Instantiate(void) const;
+ Object::Ptr Instantiate(const std::vector<Value>& args = std::vector<Value>()) const;
bool IsAssignableFrom(const Type::Ptr& other) const;
#include "base/value.hpp"
#include "base/array.hpp"
#include "base/dictionary.hpp"
+#include "base/datetime.hpp"
+#include "base/convert.hpp"
#include "base/utility.hpp"
#include "base/objectlock.hpp"
#include <boost/foreach.hpp>
return false;
if (IsObject()) {
+ if (IsObjectType<DateTime>() && rhs.IsObjectType<DateTime>()) {
+ DateTime::Ptr dt1 = *this;
+ DateTime::Ptr dt2 = rhs;
+
+ return dt1->GetValue() == dt2->GetValue();
+ }
+
if (IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
Array::Ptr arr1 = *this;
Array::Ptr arr2 = rhs;
return static_cast<String>(lhs) + static_cast<String>(rhs);
else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) + static_cast<double>(rhs);
+ else if (lhs.IsObjectType<DateTime>() && rhs.IsNumber())
+ return new DateTime(Convert::ToDateTimeValue(lhs) + rhs);
else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
Array::Ptr result = new Array();
if (!lhs.IsEmpty())
{
if ((lhs.IsNumber() || lhs.IsEmpty()) && !lhs.IsString() && (rhs.IsNumber() || rhs.IsEmpty()) && !rhs.IsString() && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) - static_cast<double>(rhs);
+ else if (lhs.IsObjectType<DateTime>() && rhs.IsNumber())
+ return new DateTime(Convert::ToDateTimeValue(lhs) - rhs);
+ else if (lhs.IsObjectType<DateTime>() && rhs.IsObjectType<DateTime>())
+ return Convert::ToDateTimeValue(lhs) - Convert::ToDateTimeValue(rhs);
+ else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+ return new DateTime(Convert::ToDateTimeValue(lhs) - Convert::ToDateTimeValue(rhs));
else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
if (lhs.IsEmpty())
return new Array();
return static_cast<String>(lhs) < static_cast<String>(rhs);
else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) < static_cast<double>(rhs);
+ else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+ return Convert::ToDateTimeValue(lhs) < Convert::ToDateTimeValue(rhs);
else
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator < cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
}
return static_cast<String>(lhs) > static_cast<String>(rhs);
else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) > static_cast<double>(rhs);
+ else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+ return Convert::ToDateTimeValue(lhs) > Convert::ToDateTimeValue(rhs);
else
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator > cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
}
return static_cast<String>(lhs) <= static_cast<String>(rhs);
else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) <= static_cast<double>(rhs);
+ else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+ return Convert::ToDateTimeValue(lhs) <= Convert::ToDateTimeValue(rhs);
else
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator <= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
}
return static_cast<String>(lhs) >= static_cast<String>(rhs);
else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
return static_cast<double>(lhs) >= static_cast<double>(rhs);
+ else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
+ return Convert::ToDateTimeValue(lhs) >= Convert::ToDateTimeValue(rhs);
else
BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
}
}
if (vfunc.IsObjectType<Type>()) {
- if (m_Args.empty())
- return VMOps::ConstructorCall(vfunc, m_DebugInfo);
- else if (m_Args.size() == 1) {
- ExpressionResult argres = m_Args[0]->Evaluate(frame);
+ std::vector<Value> arguments;
+ BOOST_FOREACH(Expression *arg, m_Args) {
+ ExpressionResult argres = arg->Evaluate(frame);
CHECK_RESULT(argres);
- return VMOps::CopyConstructorCall(vfunc, argres.GetValue(), m_DebugInfo);
- } else
- BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor.", m_DebugInfo));
+ arguments.push_back(argres.GetValue());
+ }
+
+ return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
}
if (!vfunc.IsObjectType<Function>())
return ScriptGlobal::Get(name);
}
- static inline Value CopyConstructorCall(const Type::Ptr& type, const Value& value, const DebugInfo& debugInfo = DebugInfo())
+ static inline Value ConstructorCall(const Type::Ptr& type, const std::vector<Value>& args, const DebugInfo& debugInfo = DebugInfo())
{
- if (type->GetName() == "String")
- return Convert::ToString(value);
- else if (type->GetName() == "Number")
- return Convert::ToDouble(value);
- else if (type->GetName() == "Boolean")
- return Convert::ToBool(value);
- else if (!value.IsEmpty() && !type->IsAssignableFrom(value.GetReflectionType()))
- BOOST_THROW_EXCEPTION(ScriptError("Invalid cast: Tried to cast object of type '" + value.GetReflectionType()->GetName() + "' to type '" + type->GetName() + "'", debugInfo));
+ if (type->GetName() == "String") {
+ if (args.empty())
+ return "";
+ else if (args.size() == 1)
+ return Convert::ToString(args[0]);
+ else
+ BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor."));
+ } else if (type->GetName() == "Number") {
+ if (args.empty())
+ return 0;
+ else if (args.size() == 1)
+ return Convert::ToDouble(args[0]);
+ else
+ BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor."));
+ } else if (type->GetName() == "Boolean") {
+ if (args.empty())
+ return 0;
+ else if (args.size() == 1)
+ return Convert::ToBool(args[0]);
+ else
+ BOOST_THROW_EXCEPTION(ScriptError("Too many arguments for constructor."));
+ } else if (args.size() == 1 && type->IsAssignableFrom(args[0].GetReflectionType()))
+ return args[0];
else
- return value;
- }
-
- static inline Value ConstructorCall(const Type::Ptr& type, const DebugInfo& debugInfo = DebugInfo())
- {
- if (type->GetName() == "String")
- return "";
- else if (type->GetName() == "Number")
- return 0;
- else if (type->GetName() == "Boolean")
- return false;
- else {
- Object::Ptr object = type->Instantiate();
-
- if (!object)
- BOOST_THROW_EXCEPTION(ScriptError("Failed to instantiate object of type '" + type->GetName() + "'", debugInfo));
-
- return object;
- }
+ return type->Instantiate(args);
}
static inline Value FunctionCall(ScriptFrame& frame, const Value& self, const Function::Ptr& func, const std::vector<Value>& arguments)
load_after { return T_LOAD_AFTER; }
library { return T_LIBRARY; }
abstract { yylval->num = TAAbstract; return T_CLASS_ATTRIBUTE; }
+vararg_constructor { yylval->num = TAVarArgConstructor; return T_CLASS_ATTRIBUTE; }
config { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; }
state { yylval->num = FAState; return T_FIELD_ATTRIBUTE; }
enum { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; }
/* TypeHelper */
if (klass.Attributes & TAAbstract) {
m_Header << "template<>" << std::endl
- << "struct TypeHelper<" << klass.Name << ">" << std::endl
+ << "struct TypeHelper<" << klass.Name << ", " << ((klass.Attributes & TAVarArgConstructor) ? "true" : "false") << ">" << std::endl
<< "{" << std::endl
<< "\t" << "static ObjectFactory GetFactory(void)" << std::endl
<< "\t" << "{" << std::endl
m_Impl << "ObjectFactory TypeImpl<" << klass.Name << ">::GetFactory(void) const" << std::endl
<< "{" << std::endl
- << "\t" << "return TypeHelper<" << klass.Name << ">::GetFactory();" << std::endl
+ << "\t" << "return TypeHelper<" << klass.Name << ", " << ((klass.Attributes & TAVarArgConstructor) ? "true" : "false") << ">::GetFactory();" << std::endl
<< "}" << std::endl << std::endl;
/* GetLoadDependencies */
enum TypeAttribute
{
- TAAbstract = 1
+ TAAbstract = 1,
+ TAVarArgConstructor = 2
};
struct Klass