From: Gunnar Beutner Date: Thu, 11 Jan 2018 06:08:09 +0000 (+0100) Subject: Avoid accessing attributes for validators where not necessary X-Git-Tag: v2.9.0~231^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=21254fb610aa0ec6982e81129c6649d716692606;p=icinga2 Avoid accessing attributes for validators where not necessary --- diff --git a/lib/base/application.cpp b/lib/base/application.cpp index d135592a1..0c325c728 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -1564,10 +1564,10 @@ void Application::SetLastReloadFailed(double ts) m_LastReloadFailed = ts; } -void Application::ValidateName(const String& value, const ValidationUtils& utils) +void Application::ValidateName(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateName(value, utils); + ObjectImpl::ValidateName(lvalue, utils); - if (value != "app") + if (lvalue() != "app") BOOST_THROW_EXCEPTION(ValidationError(this, { "name" }, "Application object must be named 'app'.")); } diff --git a/lib/base/application.hpp b/lib/base/application.hpp index 6811c8936..429d06aba 100644 --- a/lib/base/application.hpp +++ b/lib/base/application.hpp @@ -174,7 +174,7 @@ protected: virtual void OnShutdown(); - void ValidateName(const String& value, const ValidationUtils& utils) final; + void ValidateName(const Lazy& lvalue, const ValidationUtils& utils) final; private: static Application::Ptr m_Instance; /**< The application instance. */ diff --git a/lib/base/configobject.cpp b/lib/base/configobject.cpp index d725afe92..824ec2630 100644 --- a/lib/base/configobject.cpp +++ b/lib/base/configobject.cpp @@ -210,7 +210,7 @@ void ConfigObject::ModifyAttribute(const String& attr, const Value& value, bool } ModAttrValidationUtils utils; - ValidateField(fid, newValue, utils); + ValidateField(fid, Lazy{newValue}, utils); SetField(fid, newValue); diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index 227ed3694..9425a7fd1 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -183,14 +183,14 @@ bool Logger::IsTimestampEnabled() return m_TimestampEnabled; } -void Logger::ValidateSeverity(const String& value, const ValidationUtils& utils) +void Logger::ValidateSeverity(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateSeverity(value, utils); + ObjectImpl::ValidateSeverity(lvalue, utils); try { - StringToSeverity(value); + StringToSeverity(lvalue()); } catch (...) { - BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + value)); + BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + lvalue())); } } diff --git a/lib/base/logger.hpp b/lib/base/logger.hpp index 1ed79b197..40f4b455d 100644 --- a/lib/base/logger.hpp +++ b/lib/base/logger.hpp @@ -90,7 +90,7 @@ public: static void SetConsoleLogSeverity(LogSeverity logSeverity); static LogSeverity GetConsoleLogSeverity(); - void ValidateSeverity(const String& value, const ValidationUtils& utils) final; + void ValidateSeverity(const Lazy& lvalue, const ValidationUtils& utils) final; protected: void Start(bool runtimeCreated) override; diff --git a/lib/base/object.cpp b/lib/base/object.cpp index fe91de5ac..68dfa0431 100644 --- a/lib/base/object.cpp +++ b/lib/base/object.cpp @@ -168,7 +168,7 @@ void Object::Validate(int types, const ValidationUtils& utils) /* Nothing to do here. */ } -void Object::ValidateField(int id, const Value& value, const ValidationUtils& utils) +void Object::ValidateField(int id, const Lazy& lvalue, const ValidationUtils& utils) { /* Nothing to do here. */ } diff --git a/lib/base/object.hpp b/lib/base/object.hpp index d6d9bc79f..2b5d00379 100644 --- a/lib/base/object.hpp +++ b/lib/base/object.hpp @@ -98,6 +98,63 @@ struct TypeHelper } }; +template +struct Lazy +{ + using Accessor = std::function; + + explicit Lazy(T value) + : m_Cached(true), m_Value(value) + { } + + explicit Lazy(Accessor accessor) + : m_Accessor(accessor) + { } + + template + explicit Lazy(const Lazy& other) + { + if (other.m_Cached) { + m_Accessor = Accessor(); + m_Value = static_cast(other.m_Value); + m_Cached = true; + } else { + auto accessor = other.m_Accessor; + m_Accessor = [accessor]() { return static_cast(accessor()); }; + m_Cached = false; + } + } + + template + operator Lazy() const + { + if (m_Cached) + return Lazy(m_Value); + else { + Accessor accessor = m_Accessor; + return Lazy([accessor]() { return static_cast(accessor()); }); + } + } + + const T& operator()() const + { + if (!m_Cached) { + m_Value = m_Accessor(); + m_Cached = true; + } + + return m_Value; + } + +private: + Accessor m_Accessor; + mutable bool m_Cached{false}; + mutable T m_Value; + + template + friend struct Lazy; +}; + /** * Base class for all heap-allocated objects. At least one of its methods * has to be virtual for RTTI to work. @@ -124,7 +181,7 @@ public: virtual void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo); virtual bool HasOwnField(const String& field) const; virtual bool GetOwnField(const String& field, Value *result) const; - virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils); + virtual void ValidateField(int id, const Lazy& lvalue, const ValidationUtils& utils); virtual void NotifyField(int id, const Value& cookie = Empty); virtual Object::Ptr NavigateField(int id) const; diff --git a/lib/base/sysloglogger.cpp b/lib/base/sysloglogger.cpp index af95fa3da..fb719997c 100644 --- a/lib/base/sysloglogger.cpp +++ b/lib/base/sysloglogger.cpp @@ -103,13 +103,13 @@ void SyslogLogger::OnConfigLoaded() m_Facility = Convert::ToLong(facilityString); } -void SyslogLogger::ValidateFacility(const String& value, const ValidationUtils& utils) +void SyslogLogger::ValidateFacility(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateFacility(value, utils); + ObjectImpl::ValidateFacility(lvalue, utils); - if (m_FacilityMap.find(value) == m_FacilityMap.end()) { + if (m_FacilityMap.find(lvalue()) == m_FacilityMap.end()) { try { - Convert::ToLong(value); + Convert::ToLong(lvalue()); } catch (const std::exception&) { BOOST_THROW_EXCEPTION(ValidationError(this, { "facility" }, "Invalid facility specified.")); } diff --git a/lib/base/sysloglogger.hpp b/lib/base/sysloglogger.hpp index f61848b41..e81ffe700 100644 --- a/lib/base/sysloglogger.hpp +++ b/lib/base/sysloglogger.hpp @@ -42,7 +42,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); void OnConfigLoaded() override; - void ValidateFacility(const String& value, const ValidationUtils& utils) override; + void ValidateFacility(const Lazy& lvalue, const ValidationUtils& utils) override; protected: static std::map m_FacilityMap; diff --git a/lib/compat/compatlogger.cpp b/lib/compat/compatlogger.cpp index d618b6caa..498b434f3 100644 --- a/lib/compat/compatlogger.cpp +++ b/lib/compat/compatlogger.cpp @@ -598,12 +598,12 @@ void CompatLogger::RotationTimerHandler() ScheduleNextRotation(); } -void CompatLogger::ValidateRotationMethod(const String& value, const ValidationUtils& utils) +void CompatLogger::ValidateRotationMethod(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateRotationMethod(value, utils); + ObjectImpl::ValidateRotationMethod(lvalue, utils); - if (value != "HOURLY" && value != "DAILY" && - value != "WEEKLY" && value != "MONTHLY" && value != "NONE") { - BOOST_THROW_EXCEPTION(ValidationError(this, { "rotation_method" }, "Rotation method '" + value + "' is invalid.")); + if (lvalue() != "HOURLY" && lvalue() != "DAILY" && + lvalue() != "WEEKLY" && lvalue() != "MONTHLY" && lvalue() != "NONE") { + BOOST_THROW_EXCEPTION(ValidationError(this, { "rotation_method" }, "Rotation method '" + lvalue() + "' is invalid.")); } } diff --git a/lib/compat/compatlogger.hpp b/lib/compat/compatlogger.hpp index 1cfb2a28e..f12ae2e4a 100644 --- a/lib/compat/compatlogger.hpp +++ b/lib/compat/compatlogger.hpp @@ -41,7 +41,7 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); - void ValidateRotationMethod(const String& value, const ValidationUtils& utils) override; + void ValidateRotationMethod(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void Start(bool runtimeCreated) override; diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 9249697de..7202a2447 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -440,19 +440,19 @@ void DbConnection::PrepareDatabase() } } -void DbConnection::ValidateFailoverTimeout(double value, const ValidationUtils& utils) +void DbConnection::ValidateFailoverTimeout(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateFailoverTimeout(value, utils); + ObjectImpl::ValidateFailoverTimeout(lvalue, utils); - if (value < 60) + if (lvalue() < 60) BOOST_THROW_EXCEPTION(ValidationError(this, { "failover_timeout" }, "Failover timeout minimum is 60s.")); } -void DbConnection::ValidateCategories(const Array::Ptr& value, const ValidationUtils& utils) +void DbConnection::ValidateCategories(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateCategories(value, utils); + ObjectImpl::ValidateCategories(lvalue, utils); - int filter = FilterArrayToInt(value, DbQuery::GetCategoryFilterMap(), 0); + int filter = FilterArrayToInt(lvalue(), DbQuery::GetCategoryFilterMap(), 0); if (filter != DbCatEverything && (filter & ~(DbCatInvalid | DbCatEverything | DbCatConfig | DbCatState | DbCatAcknowledgement | DbCatComment | DbCatDowntime | DbCatEventHandler | DbCatExternalCommand | diff --git a/lib/db_ido/dbconnection.hpp b/lib/db_ido/dbconnection.hpp index 932e3e1b4..e1eb50633 100644 --- a/lib/db_ido/dbconnection.hpp +++ b/lib/db_ido/dbconnection.hpp @@ -74,8 +74,8 @@ public: int GetQueryCount(RingBuffer::SizeType span); virtual int GetPendingQueryCount() const = 0; - void ValidateFailoverTimeout(double value, const ValidationUtils& utils) final; - void ValidateCategories(const Array::Ptr& value, const ValidationUtils& utils) final; + void ValidateFailoverTimeout(const Lazy& lvalue, const ValidationUtils& utils) final; + void ValidateCategories(const Lazy& lvalue, const ValidationUtils& utils) final; protected: void OnConfigLoaded() override; diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index 13852e94e..9b66eb240 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -187,18 +187,18 @@ void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime) OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr); } -void Checkable::ValidateCheckInterval(double value, const ValidationUtils& utils) +void Checkable::ValidateCheckInterval(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateCheckInterval(value, utils); + ObjectImpl::ValidateCheckInterval(lvalue, utils); - if (value <= 0) + if (lvalue() <= 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0.")); } -void Checkable::ValidateMaxCheckAttempts(int value, const ValidationUtils& utils) +void Checkable::ValidateMaxCheckAttempts(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateMaxCheckAttempts(value, utils); + ObjectImpl::ValidateMaxCheckAttempts(lvalue, utils); - if (value <= 0) + if (lvalue() <= 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0.")); } diff --git a/lib/icinga/checkable.hpp b/lib/icinga/checkable.hpp index b2061be29..107def55f 100644 --- a/lib/icinga/checkable.hpp +++ b/lib/icinga/checkable.hpp @@ -191,8 +191,8 @@ public: void RemoveReverseDependency(const intrusive_ptr& dep); std::vector > GetReverseDependencies() const; - void ValidateCheckInterval(double value, const ValidationUtils& utils) final; - void ValidateMaxCheckAttempts(int value, const ValidationUtils& utils) final; + void ValidateCheckInterval(const Lazy& lvalue, const ValidationUtils& value) final; + void ValidateMaxCheckAttempts(const Lazy& lvalue, const ValidationUtils& value) final; static void IncreasePendingChecks(); static void DecreasePendingChecks(); diff --git a/lib/icinga/customvarobject.cpp b/lib/icinga/customvarobject.cpp index 0487def73..16d31df66 100644 --- a/lib/icinga/customvarobject.cpp +++ b/lib/icinga/customvarobject.cpp @@ -29,9 +29,9 @@ using namespace icinga; REGISTER_TYPE(CustomVarObject); -void CustomVarObject::ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) +void CustomVarObject::ValidateVars(const Lazy& lvalue, const ValidationUtils& utils) { - MacroProcessor::ValidateCustomVars(this, value); + MacroProcessor::ValidateCustomVars(this, lvalue()); } int icinga::FilterArrayToInt(const Array::Ptr& typeFilters, const std::map& filterMap, int defaultValue) diff --git a/lib/icinga/customvarobject.hpp b/lib/icinga/customvarobject.hpp index 4cf16f66a..dbb14531e 100644 --- a/lib/icinga/customvarobject.hpp +++ b/lib/icinga/customvarobject.hpp @@ -38,7 +38,7 @@ class CustomVarObject : public ObjectImpl public: DECLARE_OBJECT(CustomVarObject); - void ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) final; + void ValidateVars(const Lazy& lvalue, const ValidationUtils& utils) final; }; int FilterArrayToInt(const Array::Ptr& typeFilters, const std::map& filterMap, int defaultValue); diff --git a/lib/icinga/dependency.cpp b/lib/icinga/dependency.cpp index 42c5f4e64..6e02cfd40 100644 --- a/lib/icinga/dependency.cpp +++ b/lib/icinga/dependency.cpp @@ -209,11 +209,11 @@ TimePeriod::Ptr Dependency::GetPeriod() const return TimePeriod::GetByName(GetPeriodRaw()); } -void Dependency::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) +void Dependency::ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateStates(value, utils); + ObjectImpl::ValidateStates(lvalue, utils); - int sfilter = FilterArrayToInt(value, Notification::GetStateFilterMap(), 0); + int sfilter = FilterArrayToInt(lvalue(), Notification::GetStateFilterMap(), 0); if (GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid for host dependency.")); diff --git a/lib/icinga/dependency.hpp b/lib/icinga/dependency.hpp index 3f5775f34..820e0efb4 100644 --- a/lib/icinga/dependency.hpp +++ b/lib/icinga/dependency.hpp @@ -49,7 +49,7 @@ public: bool IsAvailable(DependencyType dt) const; - void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override; + void ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) override; static void EvaluateApplyRules(const intrusive_ptr& host); static void EvaluateApplyRules(const intrusive_ptr& service); diff --git a/lib/icinga/downtime.cpp b/lib/icinga/downtime.cpp index 226c5af91..7428332d0 100644 --- a/lib/icinga/downtime.cpp +++ b/lib/icinga/downtime.cpp @@ -409,18 +409,18 @@ void Downtime::DowntimesExpireTimerHandler() } } -void Downtime::ValidateStartTime(const Timestamp& value, const ValidationUtils& utils) +void Downtime::ValidateStartTime(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateStartTime(value, utils); + ObjectImpl::ValidateStartTime(lvalue, utils); - if (value <= 0) + if (lvalue() <= 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "start_time" }, "Start time must be greater than 0.")); } -void Downtime::ValidateEndTime(const Timestamp& value, const ValidationUtils& utils) +void Downtime::ValidateEndTime(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateEndTime(value, utils); + ObjectImpl::ValidateEndTime(lvalue, utils); - if (value <= 0) + if (lvalue() <= 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "end_time" }, "End time must be greater than 0.")); } diff --git a/lib/icinga/downtime.hpp b/lib/icinga/downtime.hpp index 1c120c019..5149762b1 100644 --- a/lib/icinga/downtime.hpp +++ b/lib/icinga/downtime.hpp @@ -70,8 +70,8 @@ protected: void Start(bool runtimeCreated) override; void Stop(bool runtimeRemoved) override; - void ValidateStartTime(const Timestamp& value, const ValidationUtils& utils) override; - void ValidateEndTime(const Timestamp& value, const ValidationUtils& utils) override; + void ValidateStartTime(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateEndTime(const Lazy& lvalue, const ValidationUtils& utils) override; private: ObjectImpl::Ptr m_Checkable; diff --git a/lib/icinga/icingaapplication.cpp b/lib/icinga/icingaapplication.cpp index 3008bfb96..3a32586a4 100644 --- a/lib/icinga/icingaapplication.cpp +++ b/lib/icinga/icingaapplication.cpp @@ -289,7 +289,7 @@ String IcingaApplication::GetNodeName() const return ScriptGlobal::Get("NodeName"); } -void IcingaApplication::ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) +void IcingaApplication::ValidateVars(const Lazy& lvalue, const ValidationUtils& utils) { - MacroProcessor::ValidateCustomVars(this, value); + MacroProcessor::ValidateCustomVars(this, lvalue()); } diff --git a/lib/icinga/icingaapplication.hpp b/lib/icinga/icingaapplication.hpp index 9329a202a..b5b1b951b 100644 --- a/lib/icinga/icingaapplication.hpp +++ b/lib/icinga/icingaapplication.hpp @@ -52,7 +52,7 @@ public: String GetNodeName() const; - void ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) override; + void ValidateVars(const Lazy& lvalue, const ValidationUtils& utils) override; private: void DumpProgramState(); diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index f85c90a43..8771f4240 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -642,11 +642,11 @@ void Notification::Validate(int types, const ValidationUtils& utils) BOOST_THROW_EXCEPTION(ValidationError(this, std::vector(), "Validation failed: No users/user_groups specified.")); } -void Notification::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) +void Notification::ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateStates(value, utils); + ObjectImpl::ValidateStates(lvalue, utils); - int filter = FilterArrayToInt(value, GetStateFilterMap(), 0); + int filter = FilterArrayToInt(lvalue(), GetStateFilterMap(), 0); if (GetServiceName().IsEmpty() && (filter == -1 || (filter & ~(StateFilterUp | StateFilterDown)) != 0)) BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid.")); @@ -655,11 +655,11 @@ void Notification::ValidateStates(const Array::Ptr& value, const ValidationUtils BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid.")); } -void Notification::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) +void Notification::ValidateTypes(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateTypes(value, utils); + ObjectImpl::ValidateTypes(lvalue, utils); - int filter = FilterArrayToInt(value, GetTypeFilterMap(), 0); + int filter = FilterArrayToInt(lvalue(), GetTypeFilterMap(), 0); if (filter == -1 || (filter & ~(NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved | NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery | diff --git a/lib/icinga/notification.hpp b/lib/icinga/notification.hpp index b87bb702c..27b78f531 100644 --- a/lib/icinga/notification.hpp +++ b/lib/icinga/notification.hpp @@ -106,8 +106,8 @@ public: void Validate(int types, const ValidationUtils& utils) override; - void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override; - void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override; + void ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateTypes(const Lazy& lvalue, const ValidationUtils& utils) override; static void EvaluateApplyRules(const intrusive_ptr& host); static void EvaluateApplyRules(const intrusive_ptr& service); diff --git a/lib/icinga/scheduleddowntime.cpp b/lib/icinga/scheduleddowntime.cpp index b19480964..6c702946e 100644 --- a/lib/icinga/scheduleddowntime.cpp +++ b/lib/icinga/scheduleddowntime.cpp @@ -196,11 +196,11 @@ void ScheduledDowntime::CreateNextDowntime() GetFixed(), String(), GetDuration(), GetName(), GetName()); } -void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) +void ScheduledDowntime::ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateRanges(value, utils); + ObjectImpl::ValidateRanges(lvalue, utils); - if (!value) + if (!lvalue()) return; /* create a fake time environment to validate the definitions */ @@ -208,8 +208,8 @@ void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const Valid tm reference = Utility::LocalTime(refts); Array::Ptr segments = new Array(); - ObjectLock olock(value); - for (const Dictionary::Pair& kv : value) { + ObjectLock olock(lvalue()); + for (const Dictionary::Pair& kv : lvalue()) { try { tm begin_tm, end_tm; int stride; diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index 2b27eaaa8..9e5751e41 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -48,7 +48,7 @@ public: static void EvaluateApplyRules(const intrusive_ptr& host); static void EvaluateApplyRules(const intrusive_ptr& service); - void ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) override; + void ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void OnAllConfigLoaded() override; diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp index 626d03f98..13ee6bcfb 100644 --- a/lib/icinga/timeperiod.cpp +++ b/lib/icinga/timeperiod.cpp @@ -381,9 +381,9 @@ void TimePeriod::Dump() Log(LogDebug, "TimePeriod", "---"); } -void TimePeriod::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) +void TimePeriod::ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils) { - if (!value) + if (!lvalue()) return; /* create a fake time environment to validate the definitions */ @@ -391,8 +391,8 @@ void TimePeriod::ValidateRanges(const Dictionary::Ptr& value, const ValidationUt tm reference = Utility::LocalTime(refts); Array::Ptr segments = new Array(); - ObjectLock olock(value); - for (const Dictionary::Pair& kv : value) { + ObjectLock olock(lvalue()); + for (const Dictionary::Pair& kv : lvalue()) { try { tm begin_tm, end_tm; int stride; diff --git a/lib/icinga/timeperiod.hpp b/lib/icinga/timeperiod.hpp index 9fc01850a..fe1c7d651 100644 --- a/lib/icinga/timeperiod.hpp +++ b/lib/icinga/timeperiod.hpp @@ -46,7 +46,7 @@ public: bool IsInside(double ts) const; double FindNextTransition(double begin); - void ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) override; + void ValidateRanges(const Lazy& lvalue, const ValidationUtils& utils) override; private: void AddSegment(double s, double end); diff --git a/lib/icinga/user.cpp b/lib/icinga/user.cpp index b7e92b03d..7059c8438 100644 --- a/lib/icinga/user.cpp +++ b/lib/icinga/user.cpp @@ -97,21 +97,21 @@ TimePeriod::Ptr User::GetPeriod() const return TimePeriod::GetByName(GetPeriodRaw()); } -void User::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) +void User::ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateStates(value, utils); + ObjectImpl::ValidateStates(lvalue, utils); - int filter = FilterArrayToInt(value, Notification::GetStateFilterMap(), 0); + int filter = FilterArrayToInt(lvalue(), Notification::GetStateFilterMap(), 0); if (filter == -1 || (filter & ~(StateFilterUp | StateFilterDown | StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid.")); } -void User::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) +void User::ValidateTypes(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateTypes(value, utils); + ObjectImpl::ValidateTypes(lvalue, utils); - int filter = FilterArrayToInt(value, Notification::GetTypeFilterMap(), 0); + int filter = FilterArrayToInt(lvalue(), Notification::GetTypeFilterMap(), 0); if (filter == -1 || (filter & ~(NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved | NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery | diff --git a/lib/icinga/user.hpp b/lib/icinga/user.hpp index 527777cec..28e0b8bcb 100644 --- a/lib/icinga/user.hpp +++ b/lib/icinga/user.hpp @@ -44,8 +44,8 @@ public: /* Notifications */ TimePeriod::Ptr GetPeriod() const; - void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override; - void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override; + void ValidateStates(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateTypes(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void Stop(bool runtimeRemoved) override; diff --git a/lib/livestatus/livestatuslistener.cpp b/lib/livestatus/livestatuslistener.cpp index 6a5b86418..164b44fc1 100644 --- a/lib/livestatus/livestatuslistener.cpp +++ b/lib/livestatus/livestatuslistener.cpp @@ -220,10 +220,10 @@ void LivestatusListener::ClientHandler(const Socket::Ptr& client) } -void LivestatusListener::ValidateSocketType(const String& value, const ValidationUtils& utils) +void LivestatusListener::ValidateSocketType(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateSocketType(value, utils); + ObjectImpl::ValidateSocketType(lvalue, utils); - if (value != "unix" && value != "tcp") - BOOST_THROW_EXCEPTION(ValidationError(this, { "socket_type" }, "Socket type '" + value + "' is invalid.")); + if (lvalue() != "unix" && lvalue() != "tcp") + BOOST_THROW_EXCEPTION(ValidationError(this, { "socket_type" }, "Socket type '" + lvalue() + "' is invalid.")); } diff --git a/lib/livestatus/livestatuslistener.hpp b/lib/livestatus/livestatuslistener.hpp index b917bb3e4..3292a3eb8 100644 --- a/lib/livestatus/livestatuslistener.hpp +++ b/lib/livestatus/livestatuslistener.hpp @@ -45,7 +45,7 @@ public: static int GetClientsConnected(); static int GetConnections(); - void ValidateSocketType(const String& value, const ValidationUtils& utils) override; + void ValidateSocketType(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void Start(bool runtimeCreated) override; diff --git a/lib/perfdata/graphitewriter.cpp b/lib/perfdata/graphitewriter.cpp index c1e832128..b21c139d6 100644 --- a/lib/perfdata/graphitewriter.cpp +++ b/lib/perfdata/graphitewriter.cpp @@ -342,18 +342,18 @@ Value GraphiteWriter::EscapeMacroMetric(const Value& value) return EscapeMetric(value); } -void GraphiteWriter::ValidateHostNameTemplate(const String& value, const ValidationUtils& utils) +void GraphiteWriter::ValidateHostNameTemplate(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateHostNameTemplate(value, utils); + ObjectImpl::ValidateHostNameTemplate(lvalue, utils); - if (!MacroProcessor::ValidateMacroString(value)) - BOOST_THROW_EXCEPTION(ValidationError(this, { "host_name_template" }, "Closing $ not found in macro format string '" + value + "'.")); + if (!MacroProcessor::ValidateMacroString(lvalue())) + BOOST_THROW_EXCEPTION(ValidationError(this, { "host_name_template" }, "Closing $ not found in macro format string '" + lvalue() + "'.")); } -void GraphiteWriter::ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils) +void GraphiteWriter::ValidateServiceNameTemplate(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateServiceNameTemplate(value, utils); + ObjectImpl::ValidateServiceNameTemplate(lvalue, utils); - if (!MacroProcessor::ValidateMacroString(value)) - BOOST_THROW_EXCEPTION(ValidationError(this, { "service_name_template" }, "Closing $ not found in macro format string '" + value + "'.")); + if (!MacroProcessor::ValidateMacroString(lvalue())) + BOOST_THROW_EXCEPTION(ValidationError(this, { "service_name_template" }, "Closing $ not found in macro format string '" + lvalue() + "'.")); } diff --git a/lib/perfdata/graphitewriter.hpp b/lib/perfdata/graphitewriter.hpp index e5652add0..05bc8bb43 100644 --- a/lib/perfdata/graphitewriter.hpp +++ b/lib/perfdata/graphitewriter.hpp @@ -44,8 +44,8 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); - void ValidateHostNameTemplate(const String& value, const ValidationUtils& utils) override; - void ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils) override; + void ValidateHostNameTemplate(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateServiceNameTemplate(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void OnConfigLoaded() override; diff --git a/lib/perfdata/influxdbwriter.cpp b/lib/perfdata/influxdbwriter.cpp index ef1a4dd52..a61406450 100644 --- a/lib/perfdata/influxdbwriter.cpp +++ b/lib/perfdata/influxdbwriter.cpp @@ -494,15 +494,15 @@ void InfluxdbWriter::Flush() } } -void InfluxdbWriter::ValidateHostTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils) +void InfluxdbWriter::ValidateHostTemplate(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateHostTemplate(value, utils); + ObjectImpl::ValidateHostTemplate(lvalue, utils); - String measurement = value->Get("measurement"); + String measurement = lvalue()->Get("measurement"); if (!MacroProcessor::ValidateMacroString(measurement)) BOOST_THROW_EXCEPTION(ValidationError(this, { "host_template", "measurement" }, "Closing $ not found in macro format string '" + measurement + "'.")); - Dictionary::Ptr tags = value->Get("tags"); + Dictionary::Ptr tags = lvalue()->Get("tags"); if (tags) { ObjectLock olock(tags); for (const Dictionary::Pair& pair : tags) { @@ -512,15 +512,15 @@ void InfluxdbWriter::ValidateHostTemplate(const Dictionary::Ptr& value, const Va } } -void InfluxdbWriter::ValidateServiceTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils) +void InfluxdbWriter::ValidateServiceTemplate(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateServiceTemplate(value, utils); + ObjectImpl::ValidateServiceTemplate(lvalue, utils); - String measurement = value->Get("measurement"); + String measurement = lvalue()->Get("measurement"); if (!MacroProcessor::ValidateMacroString(measurement)) BOOST_THROW_EXCEPTION(ValidationError(this, { "service_template", "measurement" }, "Closing $ not found in macro format string '" + measurement + "'.")); - Dictionary::Ptr tags = value->Get("tags"); + Dictionary::Ptr tags = lvalue()->Get("tags"); if (tags) { ObjectLock olock(tags); for (const Dictionary::Pair& pair : tags) { diff --git a/lib/perfdata/influxdbwriter.hpp b/lib/perfdata/influxdbwriter.hpp index 8332c2fb2..323d1f911 100644 --- a/lib/perfdata/influxdbwriter.hpp +++ b/lib/perfdata/influxdbwriter.hpp @@ -44,8 +44,8 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); - void ValidateHostTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils) override; - void ValidateServiceTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils) override; + void ValidateHostTemplate(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateServiceTemplate(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void OnConfigLoaded() override; diff --git a/lib/perfdata/perfdatawriter.cpp b/lib/perfdata/perfdatawriter.cpp index 5b726a937..9d987c7d8 100644 --- a/lib/perfdata/perfdatawriter.cpp +++ b/lib/perfdata/perfdatawriter.cpp @@ -158,18 +158,18 @@ void PerfdataWriter::RotationTimerHandler() RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath()); } -void PerfdataWriter::ValidateHostFormatTemplate(const String& value, const ValidationUtils& utils) +void PerfdataWriter::ValidateHostFormatTemplate(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateHostFormatTemplate(value, utils); + ObjectImpl::ValidateHostFormatTemplate(lvalue, utils); - if (!MacroProcessor::ValidateMacroString(value)) - BOOST_THROW_EXCEPTION(ValidationError(this, { "host_format_template" }, "Closing $ not found in macro format string '" + value + "'.")); + if (!MacroProcessor::ValidateMacroString(lvalue())) + BOOST_THROW_EXCEPTION(ValidationError(this, { "host_format_template" }, "Closing $ not found in macro format string '" + lvalue() + "'.")); } -void PerfdataWriter::ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils) +void PerfdataWriter::ValidateServiceFormatTemplate(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateServiceFormatTemplate(value, utils); + ObjectImpl::ValidateServiceFormatTemplate(lvalue, utils); - if (!MacroProcessor::ValidateMacroString(value)) - BOOST_THROW_EXCEPTION(ValidationError(this, { "service_format_template" }, "Closing $ not found in macro format string '" + value + "'.")); + if (!MacroProcessor::ValidateMacroString(lvalue())) + BOOST_THROW_EXCEPTION(ValidationError(this, { "service_format_template" }, "Closing $ not found in macro format string '" + lvalue() + "'.")); } diff --git a/lib/perfdata/perfdatawriter.hpp b/lib/perfdata/perfdatawriter.hpp index 64bd36fb5..098fb8454 100644 --- a/lib/perfdata/perfdatawriter.hpp +++ b/lib/perfdata/perfdatawriter.hpp @@ -42,8 +42,8 @@ public: static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata); - void ValidateHostFormatTemplate(const String& value, const ValidationUtils& utils) override; - void ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils) override; + void ValidateHostFormatTemplate(const Lazy& lvalue, const ValidationUtils& utils) override; + void ValidateServiceFormatTemplate(const Lazy& lvalue, const ValidationUtils& utils) override; protected: void Start(bool runtimeCreated) override; diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index e639ee8c0..65ad4d64c 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -1399,14 +1399,14 @@ Endpoint::Ptr ApiListener::GetLocalEndpoint() const return m_LocalEndpoint; } -void ApiListener::ValidateTlsProtocolmin(const String& value, const ValidationUtils& utils) +void ApiListener::ValidateTlsProtocolmin(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateTlsProtocolmin(value, utils); + ObjectImpl::ValidateTlsProtocolmin(lvalue, utils); - if (value != SSL_TXT_TLSV1 + if (lvalue() != SSL_TXT_TLSV1 #ifdef SSL_TXT_TLSV1_1 - && value != SSL_TXT_TLSV1_1 && - value != SSL_TXT_TLSV1_2 + && lvalue() != SSL_TXT_TLSV1_1 && + lvalue() != SSL_TXT_TLSV1_2 #endif /* SSL_TXT_TLSV1_1 */ ) { String message = "Invalid TLS version. Must be one of '" SSL_TXT_TLSV1 "'"; diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 5405914a6..ecd1b38cb 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -114,7 +114,7 @@ protected: void Start(bool runtimeCreated) override; void Stop(bool runtimeDeleted) override; - void ValidateTlsProtocolmin(const String& value, const ValidationUtils& utils) override; + void ValidateTlsProtocolmin(const Lazy& lvalue, const ValidationUtils& utils) override; private: std::shared_ptr m_SSLContext; diff --git a/lib/remote/zone.cpp b/lib/remote/zone.cpp index c171c78f4..acfff3c5a 100644 --- a/lib/remote/zone.cpp +++ b/lib/remote/zone.cpp @@ -144,11 +144,11 @@ Zone::Ptr Zone::GetLocalZone() return local->GetZone(); } -void Zone::ValidateEndpointsRaw(const Array::Ptr& value, const ValidationUtils& utils) +void Zone::ValidateEndpointsRaw(const Lazy& lvalue, const ValidationUtils& utils) { - ObjectImpl::ValidateEndpointsRaw(value, utils); + ObjectImpl::ValidateEndpointsRaw(lvalue, utils); - if (value && value->GetLength() > 2) { + if (lvalue() && lvalue()->GetLength() > 2) { Log(LogWarning, "Zone") << "The Zone object '" << GetName() << "' has more than two endpoints." << " Due to a known issue this type of configuration is strongly" diff --git a/lib/remote/zone.hpp b/lib/remote/zone.hpp index dd5918641..158847de6 100644 --- a/lib/remote/zone.hpp +++ b/lib/remote/zone.hpp @@ -50,7 +50,7 @@ public: static Zone::Ptr GetLocalZone(); protected: - void ValidateEndpointsRaw(const Array::Ptr& value, const ValidationUtils& utils) override; + void ValidateEndpointsRaw(const Lazy& lvalue, const ValidationUtils& utils) override; private: Zone::Ptr m_Parent; diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index c8ade32ea..1899e6d29 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -470,53 +470,56 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) for (const Field& field : klass.Fields) { m_Impl << "\t" << "if (" << (field.Attributes & (FAEphemeral|FAConfig|FAState)) << " & types)" << std::endl - << "\t\t" << "Validate" << field.GetFriendlyName() << "(Get" << field.GetFriendlyName() << "(), utils);" << std::endl; + << "\t\t" << "Validate" << field.GetFriendlyName() << "(Lazy<" << field.Type.GetRealType() << ">([this]() { return Get" << field.GetFriendlyName() << "(); }), utils);" << std::endl; } m_Impl << "}" << std::endl << std::endl; for (const Field& field : klass.Fields) { - std::string argName; + std::string argName, valName; - if (field.Type.ArrayRank > 0) + if (field.Type.ArrayRank > 0) { argName = "avalue"; - else + valName = "value"; + } else { argName = "value"; + valName = "value()"; + } - m_Header << "\t" << "void SimpleValidate" << field.GetFriendlyName() << "(" << field.Type.GetArgumentType() << " " << argName << ", const ValidationUtils& utils);" << std::endl; + m_Header << "\t" << "void SimpleValidate" << field.GetFriendlyName() << "(const Lazy<" << field.Type.GetRealType() << ">& " << argName << ", const ValidationUtils& utils);" << std::endl; - m_Impl << "void ObjectImpl<" << klass.Name << ">::SimpleValidate" << field.GetFriendlyName() << "(" << field.Type.GetArgumentType() << " " << argName << ", const ValidationUtils& utils)" << std::endl + m_Impl << "void ObjectImpl<" << klass.Name << ">::SimpleValidate" << field.GetFriendlyName() << "(const Lazy<" << field.Type.GetRealType() << ">& " << argName << ", const ValidationUtils& utils)" << std::endl << "{" << std::endl; if (field.Attributes & FARequired) { if (field.Type.GetRealType().find("::Ptr") != std::string::npos) - m_Impl << "\t" << "if (!" << argName << ")" << std::endl; + m_Impl << "\t" << "if (!" << argName << "())" << std::endl; else - m_Impl << "\t" << "if (" << argName << ".IsEmpty())" << std::endl; + m_Impl << "\t" << "if (" << argName << "().IsEmpty())" << std::endl; m_Impl << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast(this), { \"" << field.Name << R"(" }, "Attribute must not be empty."));)" << std::endl << std::endl; } if (field.Attributes & FADeprecated) { if (field.Type.GetRealType().find("::Ptr") != std::string::npos) - m_Impl << "\t" << "if (" << argName << ")" << std::endl; + m_Impl << "\t" << "if (" << argName << "())" << std::endl; else - m_Impl << "\t" << "if (" << argName << " != GetDefault" << field.GetFriendlyName() << "())" << std::endl; + m_Impl << "\t" << "if (" << argName << "() != GetDefault" << field.GetFriendlyName() << "())" << std::endl; m_Impl << "\t\t" << "Log(LogWarning, \"" << klass.Name << "\") << \"Attribute '" << field.Name << R"(' for object '" << dynamic_cast(this)->GetName() << "' of type '" << dynamic_cast(this)->GetReflectionType()->GetName() << "' is deprecated and should not be used.";)" << std::endl; } if (field.Type.ArrayRank > 0) { - m_Impl << "\t" << "if (avalue) {" << std::endl - << "\t\t" << "ObjectLock olock(avalue);" << std::endl - << "\t\t" << "for (const Value& value : avalue) {" << std::endl; + m_Impl << "\t" << "if (avalue()) {" << std::endl + << "\t\t" << "ObjectLock olock(avalue());" << std::endl + << "\t\t" << "for (const Value& value : avalue()) {" << std::endl; } std::string ftype = FieldTypeToIcingaName(field, true); if (ftype == "Value") { - m_Impl << "\t" << "if (value.IsObjectType()) {" << std::endl - << "\t\t" << "Function::Ptr func = value;" << std::endl + m_Impl << "\t" << "if (" << valName << ".IsObjectType()) {" << std::endl + << "\t\t" << "Function::Ptr func = " << valName << ";" << std::endl << "\t\t" << "if (func->IsDeprecated())" << std::endl << "\t\t\t" << "Log(LogWarning, \"" << klass.Name << "\") << \"Attribute '" << field.Name << R"(' for object '" << dynamic_cast(this)->GetName() << "' of type '" << dynamic_cast(this)->GetReflectionType()->GetName() << "' is set to a deprecated function: " << func->GetName();)" << std::endl << "\t" << "}" << std::endl << std::endl; @@ -526,18 +529,18 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) m_Impl << "\t" << "if ("; if (field.Type.ArrayRank > 0) - m_Impl << "value.IsEmpty() || "; + m_Impl << valName << ".IsEmpty() || "; else - m_Impl << "!value.IsEmpty() && "; + m_Impl << "!" << valName << ".IsEmpty() && "; - m_Impl << "!utils.ValidateName(\"" << field.Type.TypeName << "\", value))" << std::endl - << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast(this), { \"" << field.Name << R"(" }, "Object '" + value + "' of type ')" << field.Type.TypeName + m_Impl << "!utils.ValidateName(\"" << field.Type.TypeName << "\", " << valName << "))" << std::endl + << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast(this), { \"" << field.Name << R"(" }, "Object '" + )" << valName << R"( + "' of type ')" << field.Type.TypeName << "' does not exist.\"));" << std::endl; } else if (field.Type.ArrayRank > 0 && (ftype == "Number" || ftype == "Boolean")) { m_Impl << "\t" << "try {" << std::endl - << "\t\t" << "Convert::ToDouble(value);" << std::endl + << "\t\t" << "Convert::ToDouble(" << valName << ");" << std::endl << "\t" << "} catch (const std::invalid_argument&) {" << std::endl - << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast(this), { \"" << field.Name << R"(", "Array element '" + value + "' of type '" + value.GetReflectionType()->GetName() + "' is not valid here; expected type ')" << ftype << "'.\"));" << std::endl + << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast(this), { \"" << field.Name << R"(", "Array element '" + " << valName << " + "' of type '" + " << valName << ".GetReflectionType()->GetName() + "' is not valid here; expected type ')" << ftype << "'.\"));" << std::endl << "\t" << "}" << std::endl; } @@ -649,14 +652,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) /* ValidateField */ m_Header << "public:" << std::endl - << "\t" << "void ValidateField(int id, const Value& value, const ValidationUtils& utils) override;" << std::endl; + << "\t" << "void ValidateField(int id, const Lazy& lvalue, const ValidationUtils& utils) override;" << std::endl; - m_Impl << "void ObjectImpl<" << klass.Name << ">::ValidateField(int id, const Value& value, const ValidationUtils& utils)" << std::endl + m_Impl << "void ObjectImpl<" << klass.Name << ">::ValidateField(int id, const Lazy& lvalue, const ValidationUtils& utils)" << std::endl << "{" << std::endl; if (!klass.Parent.empty()) m_Impl << "\t" << "int real_id = id - " << klass.Parent << "::TypeInstance->GetFieldCount(); " << std::endl - << "\t" << "if (real_id < 0) { " << klass.Parent << "::ValidateField(id, value, utils); return; }" << std::endl; + << "\t" << "if (real_id < 0) { " << klass.Parent << "::ValidateField(id, lvalue, utils); return; }" << std::endl; m_Impl << "\t" << "switch ("; @@ -673,9 +676,9 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) << "\t\t\t" << "Validate" << field.GetFriendlyName() << "("; if (field.Attributes & FAEnum) - m_Impl << "static_cast<" << field.Type.GetRealType() << ">(static_cast("; + m_Impl << "static_cast >(static_cast >("; - m_Impl << "value"; + m_Impl << "lvalue"; if (field.Attributes & FAEnum) m_Impl << "))"; @@ -1039,7 +1042,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&) /* validators */ for (const Field& field : klass.Fields) { m_Header << "protected:" << std::endl - << "\t" << "virtual void Validate" << field.GetFriendlyName() << "(" << field.Type.GetArgumentType() << " value, const ValidationUtils& utils);" << std::endl; + << "\t" << "virtual void Validate" << field.GetFriendlyName() << "(const Lazy<" << field.Type.GetRealType() << ">& lvalue, const ValidationUtils& utils);" << std::endl; } /* instance variables */ @@ -1144,7 +1147,7 @@ void ClassCompiler::CodeGenValidator(const std::string& name, const std::string& << "\t\t\t" << "if (utils.ValidateName(\"" << rule.Type << "\", value))" << std::endl << "\t\t\t\t" << "return;" << std::endl << "\t\t\t" << "else" << std::endl - << "\t\t\t\t" << R"(BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast(object), location, "Object '" + value + "' of type ')" << rule.Type << "' does not exist.\"));" << std::endl + << "\t\t\t\t" << R"(BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast(object), location, "Object '" + ")" << "xxx" << R"( + "' of type ')" << rule.Type << "' does not exist.\"));" << std::endl << "\t\t" << "}" << std::endl; } @@ -1309,12 +1312,12 @@ void ClassCompiler::HandleValidator(const Validator& validator, const ClassDebug CodeGenValidator(it.first.first + it.first.second, it.first.first, validator.Rules, it.second.Name, it.second.Type, ValidatorField); for (const auto& it : m_MissingValidators) { - m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(" << it.second.Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl + m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(const Lazy<" << it.second.Type.GetRealType() << ">& lvalue, const ValidationUtils& utils)" << std::endl << "{" << std::endl - << "\t" << "SimpleValidate" << it.first.second << "(value, utils);" << std::endl + << "\t" << "SimpleValidate" << it.first.second << "(lvalue, utils);" << std::endl << "\t" << "std::vector location;" << std::endl << "\t" << "location.emplace_back(\"" << it.second.Name << "\");" << std::endl - << "\t" << "TIValidate" << it.first.first << it.first.second << "(this, value, location, utils);" << std::endl + << "\t" << "TIValidate" << it.first.first << it.first.second << "(this, lvalue(), location, utils);" << std::endl << "\t" << "location.pop_back();" << std::endl << "}" << std::endl << std::endl; } @@ -1325,9 +1328,9 @@ void ClassCompiler::HandleValidator(const Validator& validator, const ClassDebug void ClassCompiler::HandleMissingValidators() { for (const auto& it : m_MissingValidators) { - m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(" << it.second.Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl + m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(const Lazy<" << it.second.Type.GetRealType() << ">& lvalue, const ValidationUtils& utils)" << std::endl << "{" << std::endl - << "\t" << "SimpleValidate" << it.first.second << "(value, utils);" << std::endl + << "\t" << "SimpleValidate" << it.first.second << "(lvalue, utils);" << std::endl << "}" << std::endl << std::endl; }