Implement prototype functions

fixes #8065
This commit is contained in:
Gunnar Beutner 2014-12-12 15:19:23 +01:00
parent 74d92b062a
commit aa38dde1fc
30 changed files with 633 additions and 51 deletions

View File

@ -23,13 +23,13 @@ mkclass_target(streamlogger.ti streamlogger.thpp)
mkclass_target(sysloglogger.ti sysloglogger.thpp) mkclass_target(sysloglogger.ti sysloglogger.thpp)
set(base_SOURCES set(base_SOURCES
application.cpp application-version.cpp application.thpp array.cpp console.cpp context.cpp application.cpp application-version.cpp application.thpp array.cpp array-script.cpp boolean.cpp boolean-script.cpp console.cpp context.cpp
convert.cpp debuginfo.cpp dictionary.cpp dynamicobject.cpp dynamicobject.thpp dynamictype.cpp convert.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp dynamicobject.cpp dynamicobject.thpp dynamictype.cpp
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp logger.cpp logger.thpp exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp logger.cpp logger.thpp
netstring.cpp networkstream.cpp object.cpp primitivetype.cpp process.cpp netstring.cpp networkstream.cpp number.cpp number-script.cpp object.cpp object-script.cpp primitivetype.cpp process.cpp
ringbuffer.cpp scripterror.cpp scriptfunction.cpp scriptfunctionwrapper.cpp scriptsignal.cpp ringbuffer.cpp scripterror.cpp scriptfunction.cpp scriptfunctionwrapper.cpp scriptsignal.cpp
scriptutils.cpp scriptvariable.cpp serializer.cpp socket.cpp stacktrace.cpp scriptutils.cpp scriptvariable.cpp serializer.cpp socket.cpp stacktrace.cpp
statsfunction.cpp stdiostream.cpp stream.cpp streamlogger.cpp streamlogger.thpp string.cpp statsfunction.cpp stdiostream.cpp stream.cpp streamlogger.cpp streamlogger.thpp string.cpp string-script.cpp
sysloglogger.cpp sysloglogger.thpp tcpsocket.cpp thinmutex.cpp threadpool.cpp timer.cpp sysloglogger.cpp sysloglogger.thpp tcpsocket.cpp thinmutex.cpp threadpool.cpp timer.cpp
tlsstream.cpp tlsutility.cpp type.cpp unixsocket.cpp utility.cpp value.cpp tlsstream.cpp tlsutility.cpp type.cpp unixsocket.cpp utility.cpp value.cpp
value-operators.cpp workqueue.cpp value-operators.cpp workqueue.cpp

93
lib/base/array-script.cpp Normal file
View File

@ -0,0 +1,93 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/array.hpp"
#include "base/scriptfunction.hpp"
#include "base/scriptfunctionwrapper.hpp"
#include "config/vmframe.hpp"
using namespace icinga;
static double ArrayLen(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
return self->GetLength();
}
static void ArraySet(int index, const Value& value)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
self->Set(index, value);
}
static void ArrayAdd(const Value& value)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
self->Add(value);
}
static void ArrayRemove(int index)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
self->Remove(index);
}
static bool ArrayContains(const Value& value)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
return self->Contains(value);
}
static void ArrayClear(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
self->Clear();
}
static void ArrayClone(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Array::Ptr self = static_cast<Array::Ptr>(vframe->Self);
self->ShallowClone();
}
Object::Ptr Array::GetPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
prototype->Set("len", new ScriptFunction(WrapScriptFunction(ArrayLen)));
prototype->Set("set", new ScriptFunction(WrapScriptFunction(ArraySet)));
prototype->Set("add", new ScriptFunction(WrapScriptFunction(ArrayAdd)));
prototype->Set("remove", new ScriptFunction(WrapScriptFunction(ArrayRemove)));
prototype->Set("contains", new ScriptFunction(WrapScriptFunction(ArrayContains)));
prototype->Set("clear", new ScriptFunction(WrapScriptFunction(ArrayClear)));
prototype->Set("clone", new ScriptFunction(WrapScriptFunction(ArrayClone)));
}
return prototype;
}

View File

@ -21,11 +21,12 @@
#include "base/objectlock.hpp" #include "base/objectlock.hpp"
#include "base/debug.hpp" #include "base/debug.hpp"
#include "base/primitivetype.hpp" #include "base/primitivetype.hpp"
#include "base/dictionary.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
using namespace icinga; using namespace icinga;
REGISTER_PRIMITIVE_TYPE(Array); REGISTER_PRIMITIVE_TYPE(Array, Array::GetPrototype());
/** /**
* Restrieves a value from an array. * Restrieves a value from an array.

View File

@ -65,6 +65,8 @@ public:
void CopyTo(const Array::Ptr& dest) const; void CopyTo(const Array::Ptr& dest) const;
Array::Ptr ShallowClone(void) const; Array::Ptr ShallowClone(void) const;
static Object::Ptr GetPrototype(void);
private: private:
std::vector<Value> m_Data; /**< The data for the array. */ std::vector<Value> m_Data; /**< The data for the array. */
}; };

View File

@ -0,0 +1,46 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/boolean.hpp"
#include "base/convert.hpp"
#include "base/scriptfunction.hpp"
#include "base/scriptfunctionwrapper.hpp"
#include "config/vmframe.hpp"
using namespace icinga;
static String BooleanToString(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
bool self = vframe->Self;
return self ? "true" : "false";
}
Object::Ptr Boolean::GetPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
prototype->Set("to_string", new ScriptFunction(WrapScriptFunction(BooleanToString)));
}
return prototype;
}

26
lib/base/boolean.cpp Normal file
View File

@ -0,0 +1,26 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/boolean.hpp"
#include "base/primitivetype.hpp"
using namespace icinga;
REGISTER_BUILTIN_TYPE(Boolean, Boolean::GetPrototype());

44
lib/base/boolean.hpp Normal file
View File

@ -0,0 +1,44 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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 BOOLEAN_H
#define BOOLEAN_H
#include "base/i2-base.hpp"
#include "base/object.hpp"
namespace icinga {
class Value;
/**
* Boolean class.
*/
class I2_BASE_API Boolean
{
public:
static Object::Ptr GetPrototype(void);
private:
Boolean(void);
};
}
#endif /* BOOLEAN_H */

View File

@ -0,0 +1,77 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/dictionary.hpp"
#include "base/scriptfunction.hpp"
#include "base/scriptfunctionwrapper.hpp"
#include "config/vmframe.hpp"
using namespace icinga;
static double DictionaryLen(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
return self->GetLength();
}
static void DictionarySet(const String& key, const Value& value)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
self->Set(key, value);
}
static void DictionaryRemove(const String& key)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
self->Remove(key);
}
static bool DictionaryContains(const String& key)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
return self->Contains(key);
}
static void DictionaryClone(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
self->ShallowClone();
}
Object::Ptr Dictionary::GetPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
prototype->Set("len", new ScriptFunction(WrapScriptFunction(DictionaryLen)));
prototype->Set("set", new ScriptFunction(WrapScriptFunction(DictionarySet)));
prototype->Set("remove", new ScriptFunction(WrapScriptFunction(DictionaryRemove)));
prototype->Set("contains", new ScriptFunction(WrapScriptFunction(DictionaryContains)));
prototype->Set("clone", new ScriptFunction(WrapScriptFunction(DictionaryClone)));
}
return prototype;
}

View File

@ -25,7 +25,7 @@
using namespace icinga; using namespace icinga;
REGISTER_PRIMITIVE_TYPE(Dictionary); REGISTER_PRIMITIVE_TYPE(Dictionary, Dictionary::GetPrototype());
/** /**
* Compares dictionary keys using the less operator. * Compares dictionary keys using the less operator.

View File

@ -64,6 +64,8 @@ public:
void CopyTo(const Dictionary::Ptr& dest) const; void CopyTo(const Dictionary::Ptr& dest) const;
Dictionary::Ptr ShallowClone(void) const; Dictionary::Ptr ShallowClone(void) const;
static Object::Ptr GetPrototype(void);
private: private:
std::map<String, Value> m_Data; /**< The data for the dictionary. */ std::map<String, Value> m_Data; /**< The data for the dictionary. */
}; };

View File

@ -0,0 +1,46 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/number.hpp"
#include "base/convert.hpp"
#include "base/scriptfunction.hpp"
#include "base/scriptfunctionwrapper.hpp"
#include "config/vmframe.hpp"
using namespace icinga;
static String NumberToString(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
double self = vframe->Self;
return Convert::ToString(self);
}
Object::Ptr Number::GetPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
prototype->Set("to_string", new ScriptFunction(WrapScriptFunction(NumberToString)));
}
return prototype;
}

26
lib/base/number.cpp Normal file
View File

@ -0,0 +1,26 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/number.hpp"
#include "base/primitivetype.hpp"
using namespace icinga;
REGISTER_BUILTIN_TYPE(Number, Number::GetPrototype());

44
lib/base/number.hpp Normal file
View File

@ -0,0 +1,44 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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 NUMBER_H
#define NUMBER_H
#include "base/i2-base.hpp"
#include "base/object.hpp"
namespace icinga {
class Value;
/**
* Number class.
*/
class I2_BASE_API Number
{
public:
static Object::Ptr GetPrototype(void);
private:
Number(void);
};
}
#endif /* NUMBER_H */

View File

@ -0,0 +1,46 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/object.hpp"
#include "base/dictionary.hpp"
#include "base/scriptfunction.hpp"
#include "base/scriptfunctionwrapper.hpp"
#include "config/vmframe.hpp"
using namespace icinga;
static String ObjectToString(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
Object::Ptr self = static_cast<Object::Ptr>(vframe->Self);
return self->ToString();
}
Object::Ptr Object::GetPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
prototype->Set("to_string", new ScriptFunction(WrapScriptFunction(ObjectToString)));
}
return prototype;
}

View File

@ -19,12 +19,24 @@
#include "base/object.hpp" #include "base/object.hpp"
#include "base/value.hpp" #include "base/value.hpp"
#include "base/dictionary.hpp"
#include "base/primitivetype.hpp" #include "base/primitivetype.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
using namespace icinga; using namespace icinga;
REGISTER_PRIMITIVE_TYPE(Object); static Object::Ptr GetObjectPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
}
return prototype;
}
REGISTER_PRIMITIVE_TYPE(Object, GetObjectPrototype());
/** /**
* Default constructor for the Object class. * Default constructor for the Object class.

View File

@ -104,6 +104,8 @@ public:
void InflateMutex(void); void InflateMutex(void);
static Object::Ptr GetPrototype(void);
private: private:
Object(const Object& other); Object(const Object& other);
Object& operator=(const Object& rhs); Object& operator=(const Object& rhs);

View File

@ -18,12 +18,10 @@
******************************************************************************/ ******************************************************************************/
#include "base/primitivetype.hpp" #include "base/primitivetype.hpp"
#include "base/dictionary.hpp"
using namespace icinga; using namespace icinga;
REGISTER_BUILTIN_TYPE(Number);
REGISTER_BUILTIN_TYPE(Boolean);
PrimitiveType::PrimitiveType(const String& name) PrimitiveType::PrimitiveType(const String& name)
: m_Name(name) : m_Name(name)
{ } { }

View File

@ -46,21 +46,23 @@ private:
String m_Name; String m_Name;
}; };
#define REGISTER_BUILTIN_TYPE(type) \ #define REGISTER_BUILTIN_TYPE(type, prototype) \
namespace { namespace UNIQUE_NAME(prt) { namespace prt ## type { \ namespace { namespace UNIQUE_NAME(prt) { namespace prt ## type { \
void RegisterBuiltinType(void) \ void RegisterBuiltinType(void) \
{ \ { \
icinga::Type::Ptr t = new PrimitiveType(#type); \ icinga::Type::Ptr t = new PrimitiveType(#type); \
t->SetPrototype(prototype); \
icinga::Type::Register(t); \ icinga::Type::Register(t); \
} \ } \
INITIALIZE_ONCE(RegisterBuiltinType); \ INITIALIZE_ONCE(RegisterBuiltinType); \
} } } } } }
#define REGISTER_PRIMITIVE_TYPE(type) \ #define REGISTER_PRIMITIVE_TYPE(type, prototype) \
namespace { namespace UNIQUE_NAME(prt) { namespace prt ## type { \ namespace { namespace UNIQUE_NAME(prt) { namespace prt ## type { \
void RegisterPrimitiveType(void) \ void RegisterPrimitiveType(void) \
{ \ { \
icinga::Type::Ptr t = new PrimitiveType(#type); \ icinga::Type::Ptr t = new PrimitiveType(#type); \
t->SetPrototype(prototype); \
icinga::Type::Register(t); \ icinga::Type::Register(t); \
type::TypeInstance = t; \ type::TypeInstance = t; \
} \ } \

View File

@ -20,10 +20,22 @@
#include "base/scriptfunction.hpp" #include "base/scriptfunction.hpp"
#include "base/scriptvariable.hpp" #include "base/scriptvariable.hpp"
#include "base/primitivetype.hpp" #include "base/primitivetype.hpp"
#include "base/dictionary.hpp"
using namespace icinga; using namespace icinga;
REGISTER_PRIMITIVE_TYPE(ScriptFunction); static Object::Ptr GetScriptFunctionPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
}
return prototype;
}
REGISTER_PRIMITIVE_TYPE(ScriptFunction, GetScriptFunctionPrototype());
ScriptFunction::ScriptFunction(const Callback& function) ScriptFunction::ScriptFunction(const Callback& function)
: m_Callback(function) : m_Callback(function)

View File

@ -0,0 +1,53 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 Icinga Development Team (http://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/object.hpp"
#include "base/dictionary.hpp"
#include "base/scriptfunction.hpp"
#include "base/scriptfunctionwrapper.hpp"
#include "config/vmframe.hpp"
using namespace icinga;
static int StringLen(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
String self = vframe->Self;
return self.GetLength();
}
static String StringToString(void)
{
VMFrame *vframe = VMFrame::GetCurrentFrame();
return vframe->Self;
}
Object::Ptr String::GetPrototype(void)
{
static Dictionary::Ptr prototype;
if (!prototype) {
prototype = new Dictionary();
prototype->Set("len", new ScriptFunction(WrapScriptFunction(StringLen)));
prototype->Set("to_string", new ScriptFunction(WrapScriptFunction(StringToString)));
}
return prototype;
}

View File

@ -20,12 +20,13 @@
#include "base/string.hpp" #include "base/string.hpp"
#include "base/value.hpp" #include "base/value.hpp"
#include "base/primitivetype.hpp" #include "base/primitivetype.hpp"
#include "base/dictionary.hpp"
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
#include <ostream> #include <ostream>
using namespace icinga; using namespace icinga;
REGISTER_BUILTIN_TYPE(String); REGISTER_BUILTIN_TYPE(String, String::GetPrototype());
const String::SizeType String::NPos = std::string::npos; const String::SizeType String::NPos = std::string::npos;

View File

@ -21,6 +21,7 @@
#define STRING_H #define STRING_H
#include "base/i2-base.hpp" #include "base/i2-base.hpp"
#include "base/object.hpp"
#include <boost/range/iterator.hpp> #include <boost/range/iterator.hpp>
#include <string.h> #include <string.h>
#include <functional> #include <functional>
@ -246,6 +247,8 @@ public:
static const SizeType NPos; static const SizeType NPos;
static Object::Ptr GetPrototype(void);
private: private:
std::string m_Data; std::string m_Data;
}; };

View File

@ -74,3 +74,13 @@ bool Type::IsAssignableFrom(const Type::Ptr& other) const
return false; return false;
} }
Object::Ptr Type::GetPrototype(void) const
{
return m_Prototype;
}
void Type::SetPrototype(const Object::Ptr& object)
{
m_Prototype = object;
}

View File

@ -75,11 +75,17 @@ public:
bool IsAbstract(void) const; bool IsAbstract(void) const;
Object::Ptr GetPrototype(void) const;
void SetPrototype(const Object::Ptr& object);
static void Register(const Type::Ptr& type); static void Register(const Type::Ptr& type);
static Type::Ptr GetByName(const String& name); static Type::Ptr GetByName(const String& name);
protected: protected:
virtual ObjectFactory GetFactory(void) const = 0; virtual ObjectFactory GetFactory(void) const = 0;
private:
Object::Ptr m_Prototype;
}; };
template<typename T> template<typename T>

View File

@ -85,3 +85,22 @@ String Value::GetTypeName(void) const
return "Invalid"; return "Invalid";
} }
} }
Type::Ptr Value::GetReflectionType(void) const
{
switch (GetType()) {
case ValueEmpty:
return Type::GetByName("Object");
case ValueNumber:
return Type::GetByName("Number");
case ValueBoolean:
return Type::GetByName("Boolean");
case ValueString:
return Type::GetByName("String");
case ValueObject:
return static_cast<Object::Ptr>(*this)->GetReflectionType();
default:
return Type::Ptr();
}
}

View File

@ -234,6 +234,8 @@ public:
String GetTypeName(void) const; String GetTypeName(void) const;
Type::Ptr GetReflectionType(void) const;
private: private:
boost::variant<boost::blank, double, bool, String, Object::Ptr> m_Value; boost::variant<boost::blank, double, bool, String, Object::Ptr> m_Value;

View File

@ -224,18 +224,13 @@ Value LogicalOrExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
Value FunctionCallExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const Value FunctionCallExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{ {
Object::Ptr self; Value self, funcName;
Value funcName;
if (!m_IName.empty()) { if (!m_IName.empty()) {
Value result = m_IName[0]->Evaluate(frame); Value result = m_IName[0]->Evaluate(frame);
if (m_IName.size() == 2) { if (m_IName.size() == 2)
if (!result.IsObject())
BOOST_THROW_EXCEPTION(ScriptError("Tried to invoke method on something that is not an Object.", GetDebugInfo()));
self = result; self = result;
}
for (int i = 1; i < m_IName.size(); i++) { for (int i = 1; i < m_IName.size(); i++) {
if (result.IsEmpty()) if (result.IsEmpty())
@ -244,13 +239,9 @@ Value FunctionCallExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
Value index = m_IName[i]->Evaluate(frame); Value index = m_IName[i]->Evaluate(frame);
result = VMOps::GetField(result, index, GetDebugInfo()); result = VMOps::GetField(result, index, GetDebugInfo());
if (i == m_IName.size() - 2) { if (i == m_IName.size() - 2)
if (!result.IsObject())
BOOST_THROW_EXCEPTION(ScriptError("Tried to invoke method on something that is not an Object.", GetDebugInfo()));
self = result; self = result;
} }
}
funcName = result; funcName = result;
} }
@ -336,9 +327,12 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
psdhint = &sdhint; psdhint = &sdhint;
} }
if (i == 0) if (i == 0) {
parent = m_Local ? frame.Locals : frame.Self; if (m_Local)
parent = frame.Locals;
else else
parent = frame.Self;
} else
parent = object; parent = object;
if (i == m_Indexer.size() - 1) { if (i == m_Indexer.size() - 1) {

View File

@ -30,7 +30,7 @@ namespace icinga
struct VMFrame struct VMFrame
{ {
Dictionary::Ptr Locals; Dictionary::Ptr Locals;
Object::Ptr Self; Value Self;
VMFrame *NextFrame; VMFrame *NextFrame;
VMFrame(void) VMFrame(void)
@ -40,7 +40,7 @@ struct VMFrame
SetCurrentFrame(this); SetCurrentFrame(this);
} }
VMFrame(const Object::Ptr& self) VMFrame(const Value& self)
: Locals(new Dictionary()), Self(self) : Locals(new Dictionary()), Self(self)
{ {
NextFrame = GetCurrentFrame(); NextFrame = GetCurrentFrame();

View File

@ -52,13 +52,13 @@ public:
if (frame.Locals && frame.Locals->Contains(name)) if (frame.Locals && frame.Locals->Contains(name))
return frame.Locals->Get(name); return frame.Locals->Get(name);
else if (frame.Locals != frame.Self && HasField(frame.Self, name)) else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && HasField(frame.Self, name))
return GetField(frame.Self, name, debugInfo); return GetField(frame.Self, name, debugInfo);
else else
return ScriptVariable::Get(name); return ScriptVariable::Get(name);
} }
static inline Value FunctionCall(VMFrame& frame, const Object::Ptr& self, const Value& funcName, const std::vector<Value>& arguments) static inline Value FunctionCall(VMFrame& frame, const Value& self, const Value& funcName, const std::vector<Value>& arguments)
{ {
ScriptFunction::Ptr func; ScriptFunction::Ptr func;
@ -72,7 +72,7 @@ public:
boost::shared_ptr<VMFrame> vframe; boost::shared_ptr<VMFrame> vframe;
if (self) if (!self.IsEmpty())
vframe = boost::make_shared<VMFrame>(self); /* passes self to the callee using a TLS variable */ vframe = boost::make_shared<VMFrame>(self); /* passes self to the callee using a TLS variable */
else else
vframe = boost::make_shared<VMFrame>(); vframe = boost::make_shared<VMFrame>();
@ -232,30 +232,49 @@ public:
} }
} }
static inline Value GetField(const Value& context, const String& field, const DebugInfo& debugInfo = DebugInfo()) static inline Value GetPrototypeField(const Value& context, const String& field, const DebugInfo& debugInfo = DebugInfo())
{ {
if (context.IsString()) { Type::Ptr type = context.GetReflectionType();
String str = context;
int index = Convert::ToLong(field); do {
if (index < 0 || index >= str.GetLength()) Object::Ptr object = type->GetPrototype();
BOOST_THROW_EXCEPTION(ScriptError("Index is out of bounds", debugInfo));
return String(1, str[index]); if (HasField(object, field))
return GetField(object, field);
type = type->GetBaseType();
} while (type);
return Empty;
} }
static inline Value GetField(const Value& context, const String& field, const DebugInfo& debugInfo = DebugInfo())
{
if (!context.IsObject()) if (!context.IsObject())
BOOST_THROW_EXCEPTION(ScriptError("Tried to access invalid field '" + field + "' on object of type '" + context.GetTypeName() + "'", debugInfo)); return GetPrototypeField(context, field);
Object::Ptr object = context; Object::Ptr object = context;
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(object); Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(object);
if (dict) if (dict) {
if (dict->Contains(field))
return dict->Get(field); return dict->Get(field);
else
return GetPrototypeField(context, field);
}
Array::Ptr arr = dynamic_pointer_cast<Array>(object); Array::Ptr arr = dynamic_pointer_cast<Array>(object);
if (arr) { if (arr) {
int index = Convert::ToLong(field); int index;
try {
index = Convert::ToLong(field);
} catch (...) {
return GetPrototypeField(context, field);
}
return arr->Get(index); return arr->Get(index);
} }
@ -267,7 +286,7 @@ public:
int fid = type->GetFieldId(field); int fid = type->GetFieldId(field);
if (fid == -1) if (fid == -1)
return Empty; return GetPrototypeField(context, field);
return object->GetField(fid); return object->GetField(fid);
} }

View File

@ -294,10 +294,6 @@ BOOST_AUTO_TEST_CASE(advanced)
expr = ConfigCompiler::CompileText("<test>", "7 & 15 > 6"); expr = ConfigCompiler::CompileText("<test>", "7 & 15 > 6");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame));
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "s = \"test\"; s[2]");
BOOST_CHECK(expr->Evaluate(frame) == "s");
delete expr;
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()