2019-02-25 14:48:22 +01:00
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2013-10-26 09:41:45 +02:00
2014-05-25 16:23:35 +02:00
# include "classcompiler.hpp"
2013-10-26 09:41:45 +02:00
# include <iostream>
2014-11-30 23:32:13 +01:00
# include <sstream>
2013-10-26 09:41:45 +02:00
# include <fstream>
# include <stdexcept>
2013-12-13 12:54:14 +01:00
# include <map>
2014-11-30 23:32:13 +01:00
# include <set>
2018-01-04 08:54:18 +01:00
# include <utility>
2013-12-13 12:54:14 +01:00
# include <vector>
2014-09-09 13:30:54 +02:00
# include <cstring>
2015-08-04 14:47:44 +02:00
# include <locale>
2014-09-09 16:43:21 +02:00
# ifndef _WIN32
# include <libgen.h>
2014-09-10 15:24:08 +02:00
# else /* _WIN32 */
# include <shlwapi.h>
2014-09-09 16:43:21 +02:00
# endif /* _WIN32 */
2013-10-26 09:41:45 +02:00
using namespace icinga ;
2018-01-04 08:54:18 +01:00
ClassCompiler : : ClassCompiler ( std : : string path , std : : istream & input ,
2017-12-19 15:50:05 +01:00
std : : ostream & oimpl , std : : ostream & oheader )
2018-01-04 08:54:18 +01:00
: m_Path ( std : : move ( path ) ) , m_Input ( input ) , m_Impl ( oimpl ) , m_Header ( oheader )
2013-10-26 09:41:45 +02:00
{
InitializeScanner ( ) ;
}
2018-01-04 04:25:35 +01:00
ClassCompiler : : ~ ClassCompiler ( )
2013-10-26 09:41:45 +02:00
{
DestroyScanner ( ) ;
}
2018-01-04 04:25:35 +01:00
std : : string ClassCompiler : : GetPath ( ) const
2013-10-26 09:41:45 +02:00
{
return m_Path ;
}
2018-01-04 04:25:35 +01:00
void * ClassCompiler : : GetScanner ( )
2013-10-26 09:41:45 +02:00
{
return m_Scanner ;
}
size_t ClassCompiler : : ReadInput ( char * buffer , size_t max_size )
{
2015-03-28 11:04:42 +01:00
m_Input . read ( buffer , max_size ) ;
return static_cast < size_t > ( m_Input . gcount ( ) ) ;
2013-10-26 09:41:45 +02:00
}
2014-05-11 06:30:50 +02:00
void ClassCompiler : : HandleInclude ( const std : : string & path , const ClassDebugInfo & )
2013-10-26 09:41:45 +02:00
{
2015-03-28 11:04:42 +01:00
m_Header < < " #include \" " < < path < < " \" " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2014-05-11 06:30:50 +02:00
void ClassCompiler : : HandleAngleInclude ( const std : : string & path , const ClassDebugInfo & )
2013-10-26 09:41:45 +02:00
{
2015-03-28 11:04:42 +01:00
m_Header < < " #include < " < < path < < " > " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2015-08-25 13:53:43 +02:00
void ClassCompiler : : HandleImplInclude ( const std : : string & path , const ClassDebugInfo & )
{
m_Impl < < " #include \" " < < path < < " \" " < < std : : endl < < std : : endl ;
}
void ClassCompiler : : HandleAngleImplInclude ( const std : : string & path , const ClassDebugInfo & )
{
m_Impl < < " #include < " < < path < < " > " < < std : : endl < < std : : endl ;
}
2014-05-11 06:30:50 +02:00
void ClassCompiler : : HandleNamespaceBegin ( const std : : string & name , const ClassDebugInfo & )
2013-10-26 09:41:45 +02:00
{
2015-03-28 11:04:42 +01:00
m_Header < < " namespace " < < name < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl < < std : : endl ;
2015-03-28 11:04:42 +01:00
m_Impl < < " namespace " < < name < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2014-05-11 06:30:50 +02:00
void ClassCompiler : : HandleNamespaceEnd ( const ClassDebugInfo & )
2013-10-26 09:41:45 +02:00
{
2014-11-30 23:32:13 +01:00
HandleMissingValidators ( ) ;
2015-03-28 11:04:42 +01:00
m_Header < < " } " < < std : : endl ;
m_Impl < < " } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2014-05-11 06:30:50 +02:00
void ClassCompiler : : HandleCode ( const std : : string & code , const ClassDebugInfo & )
2013-10-26 09:41:45 +02:00
{
2015-03-28 11:04:42 +01:00
m_Header < < code < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2016-08-24 19:59:13 +02:00
void ClassCompiler : : HandleLibrary ( const std : : string & library , const ClassDebugInfo & )
2015-08-04 14:47:44 +02:00
{
m_Library = library ;
}
2013-12-13 12:54:14 +01:00
unsigned long ClassCompiler : : SDBM ( const std : : string & str , size_t len = std : : string : : npos )
{
unsigned long hash = 0 ;
size_t current = 0 ;
2016-08-27 12:17:10 +02:00
for ( const char & ch : str ) {
2013-12-13 12:54:14 +01:00
if ( current > = len )
2014-11-30 23:32:13 +01:00
break ;
2013-12-13 12:54:14 +01:00
2016-08-27 12:17:10 +02:00
hash = ch + ( hash < < 6 ) + ( hash < < 16 ) - hash ;
2013-12-13 12:54:14 +01:00
2014-11-30 23:32:13 +01:00
current + + ;
}
2013-12-13 12:54:14 +01:00
2014-11-30 23:32:13 +01:00
return hash ;
2013-12-13 12:54:14 +01:00
}
2014-11-07 23:07:02 +01:00
static int TypePreference ( const std : : string & type )
{
if ( type = = " Value " )
return 0 ;
else if ( type = = " String " )
return 1 ;
else if ( type = = " double " )
return 2 ;
else if ( type . find ( " ::Ptr " ) ! = std : : string : : npos )
return 3 ;
else if ( type = = " int " )
return 4 ;
else
return 5 ;
}
static bool FieldLayoutCmp ( const Field & a , const Field & b )
{
2014-11-30 23:32:13 +01:00
return TypePreference ( a . Type . GetRealType ( ) ) < TypePreference ( b . Type . GetRealType ( ) ) ;
2014-11-07 23:07:02 +01:00
}
static bool FieldTypeCmp ( const Field & a , const Field & b )
{
2014-11-30 23:32:13 +01:00
return a . Type . GetRealType ( ) < b . Type . GetRealType ( ) ;
2014-11-07 23:07:02 +01:00
}
2016-03-24 09:15:09 +01:00
static std : : string FieldTypeToIcingaName ( const Field & field , bool inner )
{
std : : string ftype = field . Type . TypeName ;
if ( ! inner & & field . Type . ArrayRank > 0 )
return " Array " ;
if ( field . Type . IsName )
return " String " ;
if ( field . Attributes & FAEnum )
return " Number " ;
if ( ftype = = " bool " | | ftype = = " int " | | ftype = = " double " )
return " Number " ;
if ( ftype = = " int " | | ftype = = " double " )
return " Number " ;
else if ( ftype = = " bool " )
return " Boolean " ;
if ( ftype . find ( " ::Ptr " ) ! = std : : string : : npos )
return ftype . substr ( 0 , ftype . size ( ) - strlen ( " ::Ptr " ) ) ;
return ftype ;
}
2014-11-07 23:07:02 +01:00
void ClassCompiler : : OptimizeStructLayout ( std : : vector < Field > & fields )
{
std : : sort ( fields . begin ( ) , fields . end ( ) , FieldTypeCmp ) ;
std : : stable_sort ( fields . begin ( ) , fields . end ( ) , FieldLayoutCmp ) ;
}
2014-05-11 06:30:50 +02:00
void ClassCompiler : : HandleClass ( const Klass & klass , const ClassDebugInfo & )
2013-10-26 09:41:45 +02:00
{
2013-11-04 19:12:34 +01:00
/* forward declaration */
2013-10-26 09:41:45 +02:00
if ( klass . Name . find_first_of ( ' : ' ) = = std : : string : : npos )
2015-03-28 11:04:42 +01:00
m_Header < < " class " < < klass . Name < < " ; " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2014-11-07 12:32:25 +01:00
/* TypeHelper */
if ( klass . Attributes & TAAbstract ) {
2015-03-28 11:04:42 +01:00
m_Header < < " template<> " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " struct TypeHelper< " < < klass . Name < < " , " < < ( ( klass . Attributes & TAVarArgConstructor ) ? " true " : " false " ) < < " > " < < std : : endl
< < " { " < < std : : endl
2018-01-04 04:25:35 +01:00
< < " \t " < < " static ObjectFactory GetFactory() " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " { " < < std : : endl
< < " \t \t " < < " return nullptr; " < < std : : endl
< < " \t " < < " } " < < std : : endl
< < " }; " < < std : : endl < < std : : endl ;
2014-11-07 12:32:25 +01:00
}
2013-11-04 23:14:34 +01:00
/* TypeImpl */
2015-03-28 11:04:42 +01:00
m_Header < < " template<> " < < std : : endl
2017-12-31 07:22:16 +01:00
< < " class TypeImpl< " < < klass . Name < < " > "
2017-12-19 15:50:05 +01:00
< < " : public Type " ;
2016-08-16 11:02:10 +02:00
if ( ! klass . Parent . empty ( ) )
m_Header < < " Impl< " < < klass . Parent < < " > " ;
2014-04-05 22:17:20 +02:00
if ( ! klass . TypeBase . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Header < < " , public " + klass . TypeBase ;
2014-04-05 22:17:20 +02:00
2015-03-28 11:04:42 +01:00
m_Header < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " public: " < < std : : endl
2018-01-03 06:01:02 +01:00
< < " \t " < < " DECLARE_PTR_TYPEDEFS(TypeImpl< " < < klass . Name < < " >); " < < std : : endl < < std : : endl
2018-01-04 04:25:35 +01:00
< < " \t " < < " TypeImpl(); " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t " < < " ~TypeImpl() override; " < < std : : endl < < std : : endl ;
2018-01-03 06:01:02 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " TypeImpl< " < < klass . Name < < " >::TypeImpl() " < < std : : endl
2018-01-03 06:01:02 +01:00
< < " { } " < < std : : endl < < std : : endl
2018-01-04 04:25:35 +01:00
< < " TypeImpl< " < < klass . Name < < " >::~TypeImpl() " < < std : : endl
2018-01-03 06:01:02 +01:00
< < " { } " < < std : : endl < < std : : endl ;
2013-11-04 19:12:34 +01:00
2013-11-08 11:17:46 +01:00
/* GetName */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " String GetName() const override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " String TypeImpl< " < < klass . Name < < " >::GetName() const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < " return \" " < < klass . Name < < " \" ; " < < std : : endl
< < " } " < < std : : endl < < std : : endl ;
2013-11-08 11:17:46 +01:00
2013-12-18 10:18:57 +01:00
/* GetAttributes */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " int GetAttributes() const override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " int TypeImpl< " < < klass . Name < < " >::GetAttributes() const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < " return " < < klass . Attributes < < " ; " < < std : : endl
< < " } " < < std : : endl < < std : : endl ;
2013-11-08 11:17:46 +01:00
2013-11-05 08:48:45 +01:00
/* GetBaseType */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " Type::Ptr GetBaseType() const override; " < < std : : endl ;
2013-11-05 08:48:45 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " Type::Ptr TypeImpl< " < < klass . Name < < " >::GetBaseType() const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < " return " ;
2013-11-05 08:48:45 +01:00
if ( ! klass . Parent . empty ( ) )
2015-08-04 14:47:44 +02:00
m_Impl < < klass . Parent < < " ::TypeInstance " ;
2013-11-05 08:48:45 +01:00
else
2015-08-04 14:47:44 +02:00
m_Impl < < " Object::TypeInstance " ;
2013-11-05 08:48:45 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2013-11-05 08:48:45 +01:00
2013-11-04 19:12:34 +01:00
/* GetFieldId */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " int GetFieldId(const String& name) const override; " < < std : : endl ;
2013-11-04 19:12:34 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < " int TypeImpl< " < < klass . Name < < " >::GetFieldId(const String& name) const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2013-11-04 19:12:34 +01:00
2013-12-17 07:33:39 +01:00
if ( ! klass . Fields . empty ( ) ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " int offset = " ;
2013-12-17 07:33:39 +01:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < klass . Parent < < " ::TypeInstance->GetFieldCount() " ;
2013-12-17 07:33:39 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " 0 " ;
2013-11-04 19:12:34 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ; " < < std : : endl < < std : : endl ;
2013-12-17 07:33:39 +01:00
}
2013-11-04 19:12:34 +01:00
2013-12-13 12:54:14 +01:00
std : : map < int , std : : vector < std : : pair < int , std : : string > > > jumptable ;
int hlen = 0 , collisions = 0 ;
do {
int num = 0 ;
hlen + + ;
jumptable . clear ( ) ;
collisions = 0 ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2018-01-04 09:07:03 +01:00
auto hash = static_cast < int > ( SDBM ( field . Name , hlen ) ) ;
2018-01-04 09:14:55 +01:00
jumptable [ hash ] . emplace_back ( num , field . Name ) ;
2013-12-13 12:54:14 +01:00
num + + ;
if ( jumptable [ hash ] . size ( ) > 1 )
collisions + + ;
}
} while ( collisions > = 5 & & hlen < 8 ) ;
if ( ! klass . Fields . empty ( ) ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t switch (static_cast<int>(Utility::SDBM(name, " < < hlen < < " ))) { " < < std : : endl ;
2013-12-13 12:54:14 +01:00
2016-08-27 12:17:10 +02:00
for ( const auto & itj : jumptable ) {
m_Impl < < " \t \t case " < < itj . first < < " : " < < std : : endl ;
2013-12-13 12:54:14 +01:00
2016-08-27 12:17:10 +02:00
for ( const auto & itf : itj . second ) {
m_Impl < < " \t \t \t " < < " if (name == \" " < < itf . second < < " \" ) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t \t " < < " return offset + " < < itf . first < < " ; " < < std : : endl ;
2013-12-13 12:54:14 +01:00
}
2015-03-28 11:04:42 +01:00
m_Impl < < std : : endl
2018-01-04 07:06:33 +01:00
< < " \t \t \t break; " < < std : : endl ;
2013-12-13 12:54:14 +01:00
}
2015-03-28 11:04:42 +01:00
m_Impl < < " \t } " < < std : : endl ;
2013-11-04 19:12:34 +01:00
}
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " return " ;
2013-10-26 09:41:45 +02:00
2013-11-04 19:12:34 +01:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < klass . Parent < < " ::TypeInstance->GetFieldId(name) " ;
2013-11-04 19:12:34 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " -1 " ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2013-11-04 19:12:34 +01:00
/* GetFieldInfo */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " Field GetFieldInfo(int id) const override; " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " Field TypeImpl< " < < klass . Name < < " >::GetFieldInfo(int id) const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2013-11-04 19:12:34 +01:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " int real_id = id - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (real_id < 0) { return " < < klass . Parent < < " ::TypeInstance->GetFieldInfo(id); } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2017-12-13 12:49:04 +01:00
if ( ! klass . Fields . empty ( ) ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " switch ( " ;
2013-10-26 09:41:45 +02:00
2013-11-08 21:45:27 +01:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " real_id " ;
2013-11-08 21:45:27 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " id " ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ) { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2013-12-13 12:54:14 +01:00
size_t num = 0 ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
std : : string ftype = FieldTypeToIcingaName ( field , false ) ;
2014-10-31 08:49:14 +01:00
2014-11-30 23:32:13 +01:00
std : : string nameref ;
2016-08-27 12:17:10 +02:00
if ( field . Type . IsName )
nameref = " \" " + field . Type . TypeName + " \" " ;
2014-11-30 23:32:13 +01:00
else
2017-12-14 15:37:20 +01:00
nameref = " nullptr " ;
2014-11-30 23:32:13 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2018-01-04 09:28:24 +01:00
< < " \t \t \t " < < " return { " < < num < < " , \" " < < ftype < < " \" , \" " < < field . Name < < " \" , \" " < < ( field . NavigationName . empty ( ) ? field . Name : field . NavigationName ) < < " \" , " < < nameref < < " , " < < field . Attributes < < " , " < < field . Type . ArrayRank < < " }; " < < std : : endl ;
2013-11-08 21:45:27 +01:00
num + + ;
}
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " ;
2013-11-04 19:12:34 +01:00
}
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl ;
2013-11-08 21:45:27 +01:00
2017-12-13 12:49:04 +01:00
if ( ! klass . Fields . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2013-11-04 19:12:34 +01:00
/* GetFieldCount */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " int GetFieldCount() const override; " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2018-01-04 04:25:35 +01:00
m_Impl < < " int TypeImpl< " < < klass . Name < < " >::GetFieldCount() const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < " return " < < klass . Fields . size ( ) ;
2013-10-26 09:41:45 +02:00
2013-11-04 19:12:34 +01:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " + " < < klass . Parent < < " ::TypeInstance->GetFieldCount() " ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2014-11-07 12:32:25 +01:00
/* GetFactory */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " ObjectFactory GetFactory() const override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " ObjectFactory TypeImpl< " < < klass . Name < < " >::GetFactory() const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < " return TypeHelper< " < < klass . Name < < " , " < < ( ( klass . Attributes & TAVarArgConstructor ) ? " true " : " false " ) < < " >::GetFactory(); " < < std : : endl
< < " } " < < std : : endl < < std : : endl ;
2014-11-07 12:32:25 +01:00
2015-02-25 12:43:03 +01:00
/* GetLoadDependencies */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " std::vector<String> GetLoadDependencies() const override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " std::vector<String> TypeImpl< " < < klass . Name < < " >::GetLoadDependencies() const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < " std::vector<String> deps; " < < std : : endl ;
2015-02-25 12:43:03 +01:00
2016-08-27 12:17:10 +02:00
for ( const std : : string & dep : klass . LoadDependencies )
2018-01-04 09:14:55 +01:00
m_Impl < < " \t " < < " deps.emplace_back( \" " < < dep < < " \" ); " < < std : : endl ;
2015-02-25 12:43:03 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " return deps; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2015-08-04 14:47:44 +02:00
2018-04-26 15:53:11 +02:00
/* GetActivationPriority */
m_Header < < " \t " < < " int GetActivationPriority() const override; " < < std : : endl ;
m_Impl < < " int TypeImpl< " < < klass . Name < < " >::GetActivationPriority() const " < < std : : endl
< < " { " < < std : : endl
< < " \t " < < " return " < < klass . ActivationPriority < < " ; " < < std : : endl
< < " } " < < std : : endl < < std : : endl ;
2015-08-04 14:47:44 +02:00
/* RegisterAttributeHandler */
m_Header < < " public: " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t " < < " void RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback) override; " < < std : : endl ;
2015-02-25 12:43:03 +01:00
2015-08-04 14:47:44 +02:00
m_Impl < < " void TypeImpl< " < < klass . Name < < " >::RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-08-04 14:47:44 +02:00
if ( ! klass . Parent . empty ( ) )
m_Impl < < " \t " < < " int real_id = fieldId - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (real_id < 0) { " < < klass . Parent < < " ::TypeInstance->RegisterAttributeHandler(fieldId, callback); return; } " < < std : : endl ;
2015-08-04 14:47:44 +02:00
2017-12-13 12:49:04 +01:00
if ( ! klass . Fields . empty ( ) ) {
m_Impl < < " \t " < < " switch ( " ;
2015-08-04 14:47:44 +02:00
2017-12-13 12:49:04 +01:00
if ( ! klass . Parent . empty ( ) )
m_Impl < < " real_id " ;
else
m_Impl < < " fieldId " ;
2015-08-04 14:47:44 +02:00
2017-12-13 12:49:04 +01:00
m_Impl < < " ) { " < < std : : endl ;
2015-08-04 14:47:44 +02:00
2017-12-13 12:49:04 +01:00
int num = 0 ;
for ( const Field & field : klass . Fields ) {
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " ObjectImpl< " < < klass . Name < < " >::On " < < field . GetFriendlyName ( ) < < " Changed.connect(callback); " < < std : : endl
< < " \t \t \t " < < " break; " < < std : : endl ;
2017-12-13 12:49:04 +01:00
num + + ;
}
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " ;
2015-08-04 14:47:44 +02:00
}
2017-12-13 12:49:04 +01:00
m_Impl < < " \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl ;
2015-08-04 14:47:44 +02:00
2017-12-13 12:49:04 +01:00
if ( ! klass . Fields . empty ( ) )
m_Impl < < " \t " < < " } " < < std : : endl ;
2015-08-04 14:47:44 +02:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2017-12-13 12:49:04 +01:00
2015-03-28 11:04:42 +01:00
m_Header < < " }; " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Header < < std : : endl ;
2014-11-30 23:32:13 +01:00
2013-11-04 23:14:34 +01:00
/* ObjectImpl */
2015-03-28 11:04:42 +01:00
m_Header < < " template<> " < < std : : endl
2018-01-03 06:01:02 +01:00
< < " class ObjectImpl< " < < klass . Name < < " > "
< < " : public " < < ( klass . Parent . empty ( ) ? " Object " : klass . Parent ) < < std : : endl
< < " { " < < std : : endl
< < " public: " < < std : : endl
< < " \t " < < " DECLARE_PTR_TYPEDEFS(ObjectImpl< " < < klass . Name < < " >); " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
/* Validate */
2018-01-04 05:12:56 +01:00
m_Header < < " \t " < < " void Validate(int types, const ValidationUtils& utils) override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::Validate(int types, const ValidationUtils& utils) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2014-11-30 23:32:13 +01:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < klass . Parent < < " ::Validate(types, utils); " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
m_Impl < < " \t " < < " if ( " < < ( field . Attributes & ( FAEphemeral | FAConfig | FAState ) ) < < " & types) " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t \t " < < " Validate " < < field . GetFriendlyName ( ) < < " (Lazy< " < < field . Type . GetRealType ( ) < < " >([this]() { return Get " < < field . GetFriendlyName ( ) < < " (); }), utils); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2018-01-11 07:08:09 +01:00
std : : string argName , valName ;
2015-03-28 11:04:42 +01:00
2018-01-11 07:08:09 +01:00
if ( field . Type . ArrayRank > 0 ) {
2016-08-27 12:17:10 +02:00
argName = " avalue " ;
2018-01-11 07:08:09 +01:00
valName = " value " ;
} else {
2016-08-27 12:17:10 +02:00
argName = " value " ;
2018-01-11 07:08:09 +01:00
valName = " value() " ;
}
2014-11-30 23:32:13 +01:00
2018-01-11 07:08:09 +01:00
m_Header < < " \t " < < " void SimpleValidate " < < field . GetFriendlyName ( ) < < " (const Lazy< " < < field . Type . GetRealType ( ) < < " >& " < < argName < < " , const ValidationUtils& utils); " < < std : : endl ;
2016-08-27 12:17:10 +02:00
2018-01-11 07:08:09 +01:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::SimpleValidate " < < field . GetFriendlyName ( ) < < " (const Lazy< " < < field . Type . GetRealType ( ) < < " >& " < < argName < < " , const ValidationUtils& utils) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2014-11-30 23:32:13 +01:00
2016-03-24 09:15:09 +01:00
if ( field . Attributes & FARequired ) {
if ( field . Type . GetRealType ( ) . find ( " ::Ptr " ) ! = std : : string : : npos )
2018-01-11 07:08:09 +01:00
m_Impl < < " \t " < < " if (! " < < argName < < " ()) " < < std : : endl ;
2016-03-24 09:15:09 +01:00
else
2018-01-11 07:08:09 +01:00
m_Impl < < " \t " < < " if ( " < < argName < < " ().IsEmpty()) " < < std : : endl ;
2016-03-24 09:15:09 +01:00
2018-01-04 08:59:00 +01:00
m_Impl < < " \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \" " < < field . Name < < R " ( " } , " Attribute must not be empty. " ) ) ; ) " << std::endl << std::endl;
2016-03-24 09:15:09 +01:00
}
2014-11-30 23:32:13 +01:00
2017-10-16 15:32:57 +02:00
if ( field . Attributes & FADeprecated ) {
if ( field . Type . GetRealType ( ) . find ( " ::Ptr " ) ! = std : : string : : npos )
2018-01-11 07:08:09 +01:00
m_Impl < < " \t " < < " if ( " < < argName < < " ()) " < < std : : endl ;
2017-10-16 15:32:57 +02:00
else
2018-01-11 07:08:09 +01:00
m_Impl < < " \t " < < " if ( " < < argName < < " () != GetDefault " < < field . GetFriendlyName ( ) < < " ()) " < < std : : endl ;
2017-10-16 15:32:57 +02:00
2018-01-04 08:59:00 +01:00
m_Impl < < " \t \t " < < " Log(LogWarning, \" " < < klass . Name < < " \" ) << \" Attribute ' " < < field . Name < < R " (' for object ' " < < dynamic_cast < ConfigObject * > ( this ) - > GetName ( ) < < " ' of type ' " < < dynamic_cast < ConfigObject * > ( this ) - > GetReflectionType ( ) - > GetName ( ) < < " ' is deprecated and should not be used. " ; ) " << std::endl;
2017-10-16 15:32:57 +02:00
}
2016-03-24 09:15:09 +01:00
if ( field . Type . ArrayRank > 0 ) {
2018-01-11 07:08:09 +01:00
m_Impl < < " \t " < < " if (avalue()) { " < < std : : endl
< < " \t \t " < < " ObjectLock olock(avalue()); " < < std : : endl
< < " \t \t " < < " for (const Value& value : avalue()) { " < < std : : endl ;
2016-08-27 12:17:10 +02:00
}
2016-08-10 15:40:02 +02:00
2016-03-24 09:15:09 +01:00
std : : string ftype = FieldTypeToIcingaName ( field , true ) ;
2016-08-27 12:17:10 +02:00
if ( ftype = = " Value " ) {
2018-01-11 07:08:09 +01:00
m_Impl < < " \t " < < " if ( " < < valName < < " .IsObjectType<Function>()) { " < < std : : endl
< < " \t \t " < < " Function::Ptr func = " < < valName < < " ; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " if (func->IsDeprecated()) " < < std : : endl
2018-01-04 08:59:00 +01:00
< < " \t \t \t " < < " Log(LogWarning, \" " < < klass . Name < < " \" ) << \" Attribute ' " < < field . Name < < R " (' for object ' " < < dynamic_cast < ConfigObject * > ( this ) - > GetName ( ) < < " ' of type ' " < < dynamic_cast < ConfigObject * > ( this ) - > GetReflectionType ( ) - > GetName ( ) < < " ' is set to a deprecated function: " < < func - > GetName ( ) ; ) " << std::endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " } " < < std : : endl < < std : : endl ;
2016-08-27 12:17:10 +02:00
}
2016-03-24 09:15:09 +01:00
if ( field . Type . IsName ) {
2021-11-22 14:02:50 +01:00
if ( field . Type . ArrayRank > 0 ) {
m_Impl < < " \t \t \t " < < " if (! " < < valName < < " .IsEmpty() && " ;
m_Impl < < " ! " < < valName < < " .IsString()) " < < std : : endl
< < " \t \t \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \" "
< < field . Name < < R " ( " } , " It is not allowed to specify ' " + ) " << valName << R " ( + " ' of type ' " + ) "
< < valName < < " .GetTypeName() " < < R " ( + " ' as ' ) " << field.Type.TypeName
< < " ' name. Expected type of ' " < < field . Type . TypeName < < " ' name: 'String'. \" )); " < < std : : endl ;
}
m_Impl < < " \t \t \t " < < " if ( " ;
2016-08-26 10:36:53 +02:00
if ( field . Type . ArrayRank > 0 )
2018-01-11 07:08:09 +01:00
m_Impl < < valName < < " .IsEmpty() || " ;
2016-08-26 10:36:53 +02:00
else
2018-01-11 07:08:09 +01:00
m_Impl < < " ! " < < valName < < " .IsEmpty() && " ;
2016-08-26 10:36:53 +02:00
2018-01-11 07:08:09 +01:00
m_Impl < < " !utils.ValidateName( \" " < < field . Type . TypeName < < " \" , " < < valName < < " )) " < < std : : endl
2021-11-22 14:02:50 +01:00
< < " \t \t \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \" " < < field . Name < < R " ( " } , " Object ' " + ) " << valName << R " ( + " ' of type ') " < < field . Type . TypeName
2017-12-19 15:50:05 +01:00
< < " ' does not exist. \" )); " < < std : : endl ;
2016-03-24 09:15:09 +01:00
} else if ( field . Type . ArrayRank > 0 & & ( ftype = = " Number " | | ftype = = " Boolean " ) ) {
m_Impl < < " \t " < < " try { " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t \t " < < " Convert::ToDouble( " < < valName < < " ); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " } catch (const std::invalid_argument&) { " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \" " < < field . Name < < R " ( " , " Array element ' " + " << valName << " + " ' of type ' " + " << valName << " . GetReflectionType ( ) - > GetName ( ) + " ' is not valid here; expected type ') " < < ftype < < " '. \" )); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " } " < < std : : endl ;
2016-03-24 09:15:09 +01:00
}
2014-11-30 23:32:13 +01:00
2016-03-24 09:15:09 +01:00
if ( field . Type . ArrayRank > 0 ) {
m_Impl < < " \t \t " < < " } " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " } " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2013-11-04 19:12:34 +01:00
2018-01-03 06:01:02 +01:00
/* constructor */
m_Header < < " public: " < < std : : endl
2018-01-04 04:25:35 +01:00
< < " \t " < < " ObjectImpl< " < < klass . Name < < " >(); " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " ObjectImpl< " < < klass . Name < < " >::ObjectImpl() " < < std : : endl
2018-01-03 06:01:02 +01:00
< < " { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2018-01-03 06:01:02 +01:00
for ( const Field & field : klass . Fields ) {
2018-08-10 10:39:17 +02:00
if ( ! field . PureSetAccessor )
m_Impl < < " \t " < < " Set " < < field . GetFriendlyName ( ) < < " ( " < < " GetDefault " < < field . GetFriendlyName ( ) < < " (), true); " < < std : : endl ;
2018-01-03 06:01:02 +01:00
}
2013-10-26 09:41:45 +02:00
2018-01-03 06:01:02 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-03 06:01:02 +01:00
/* destructor */
m_Header < < " public: " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t " < < " ~ObjectImpl< " < < klass . Name < < " >() override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < " ObjectImpl< " < < klass . Name < < " >::~ObjectImpl() " < < std : : endl
2018-01-03 06:01:02 +01:00
< < " { } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2018-01-03 06:01:02 +01:00
if ( ! klass . Fields . empty ( ) ) {
2013-10-26 09:41:45 +02:00
/* SetField */
2015-09-23 08:33:18 +02:00
m_Header < < " public: " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t " < < " void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty) override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2015-08-04 14:47:44 +02:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::SetField(int id, const Value& value, bool suppress_events, const Value& cookie) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " int real_id = id - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (real_id < 0) { " < < klass . Parent < < " ::SetField(id, value, suppress_events, cookie); return; } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " switch ( " ;
2013-10-26 09:41:45 +02:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " real_id " ;
2013-10-26 09:41:45 +02:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " id " ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ) { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2013-12-13 12:54:14 +01:00
size_t num = 0 ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " Set " < < field . GetFriendlyName ( ) < < " ( " ;
2013-10-26 09:41:45 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FAEnum )
m_Impl < < " static_cast< " < < field . Type . GetRealType ( ) < < " >(static_cast<int>( " ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " value " ;
2013-10-26 09:41:45 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FAEnum )
2015-03-28 11:04:42 +01:00
m_Impl < < " )) " ;
2013-10-26 09:41:45 +02:00
2015-08-04 14:47:44 +02:00
m_Impl < < " , suppress_events, cookie); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " break; " < < std : : endl ;
2013-10-26 09:41:45 +02:00
num + + ;
}
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl
< < " \t " < < " } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
/* GetField */
2015-09-23 08:33:18 +02:00
m_Header < < " public: " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t " < < " Value GetField(int id) const override; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
m_Impl < < " Value ObjectImpl< " < < klass . Name < < " >::GetField(int id) const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " int real_id = id - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (real_id < 0) { return " < < klass . Parent < < " ::GetField(id); } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " switch ( " ;
2013-10-26 09:41:45 +02:00
if ( ! klass . Parent . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " real_id " ;
2013-10-26 09:41:45 +02:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " id " ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " ) { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
num = 0 ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " return Get " < < field . GetFriendlyName ( ) < < " (); " < < std : : endl ;
2013-10-26 09:41:45 +02:00
num + + ;
}
2015-08-04 14:47:44 +02:00
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl
< < " \t " < < " } " < < std : : endl ;
2015-08-04 14:47:44 +02:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2015-08-13 08:52:00 +02:00
/* ValidateField */
2015-09-23 08:33:18 +02:00
m_Header < < " public: " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t " < < " void ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils) override; " < < std : : endl ;
2015-08-13 08:52:00 +02:00
2018-01-11 07:08:09 +01:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-08-13 08:52:00 +02:00
if ( ! klass . Parent . empty ( ) )
m_Impl < < " \t " < < " int real_id = id - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t " < < " if (real_id < 0) { " < < klass . Parent < < " ::ValidateField(id, lvalue, utils); return; } " < < std : : endl ;
2015-08-13 08:52:00 +02:00
m_Impl < < " \t " < < " switch ( " ;
if ( ! klass . Parent . empty ( ) )
m_Impl < < " real_id " ;
else
m_Impl < < " id " ;
m_Impl < < " ) { " < < std : : endl ;
num = 0 ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2015-08-13 08:52:00 +02:00
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " Validate " < < field . GetFriendlyName ( ) < < " ( " ;
2015-08-13 08:52:00 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FAEnum )
2018-01-11 07:08:09 +01:00
m_Impl < < " static_cast<Lazy< " < < field . Type . GetRealType ( ) < < " > >(static_cast<Lazy<int> >( " ;
2015-08-13 08:52:00 +02:00
2018-01-11 07:08:09 +01:00
m_Impl < < " lvalue " ;
2015-08-13 08:52:00 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FAEnum )
2015-08-13 08:52:00 +02:00
m_Impl < < " )) " ;
m_Impl < < " , utils); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " break; " < < std : : endl ;
2015-08-13 08:52:00 +02:00
num + + ;
}
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl
< < " \t " < < " } " < < std : : endl ;
2015-08-13 08:52:00 +02:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2015-08-04 14:47:44 +02:00
/* NotifyField */
2015-09-23 08:33:18 +02:00
m_Header < < " public: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " void NotifyField(int id, const Value& cookie = Empty) override; " < < std : : endl ;
2015-08-04 14:47:44 +02:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::NotifyField(int id, const Value& cookie) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-08-04 14:47:44 +02:00
if ( ! klass . Parent . empty ( ) )
m_Impl < < " \t " < < " int real_id = id - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (real_id < 0) { " < < klass . Parent < < " ::NotifyField(id, cookie); return; } " < < std : : endl ;
2015-08-04 14:47:44 +02:00
m_Impl < < " \t " < < " switch ( " ;
if ( ! klass . Parent . empty ( ) )
m_Impl < < " real_id " ;
else
m_Impl < < " id " ;
m_Impl < < " ) { " < < std : : endl ;
num = 0 ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2015-08-04 14:47:44 +02:00
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " Notify " < < field . GetFriendlyName ( ) < < " (cookie); " < < std : : endl
< < " \t \t \t " < < " break; " < < std : : endl ;
2015-08-04 14:47:44 +02:00
num + + ;
}
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl
< < " \t " < < " } " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-09-22 09:42:30 +02:00
/* NavigateField */
2015-09-23 08:33:18 +02:00
m_Header < < " public: " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t " < < " Object::Ptr NavigateField(int id) const override; " < < std : : endl ;
2015-09-22 09:42:30 +02:00
m_Impl < < " Object::Ptr ObjectImpl< " < < klass . Name < < " >::NavigateField(int id) const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-09-22 09:42:30 +02:00
if ( ! klass . Parent . empty ( ) )
m_Impl < < " \t " < < " int real_id = id - " < < klass . Parent < < " ::TypeInstance->GetFieldCount(); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (real_id < 0) { return " < < klass . Parent < < " ::NavigateField(id); } " < < std : : endl ;
2015-09-22 09:42:30 +02:00
2017-12-13 12:49:04 +01:00
bool haveNavigationFields = false ;
2015-09-22 09:42:30 +02:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
if ( field . Attributes & FANavigation ) {
2017-12-13 12:49:04 +01:00
haveNavigationFields = true ;
break ;
2015-09-22 09:42:30 +02:00
}
2017-12-13 12:49:04 +01:00
}
2015-09-22 09:42:30 +02:00
2017-12-13 12:49:04 +01:00
if ( haveNavigationFields ) {
m_Impl < < " \t " < < " switch ( " ;
if ( ! klass . Parent . empty ( ) )
m_Impl < < " real_id " ;
else
m_Impl < < " id " ;
m_Impl < < " ) { " < < std : : endl ;
num = 0 ;
for ( const Field & field : klass . Fields ) {
if ( field . Attributes & FANavigation ) {
m_Impl < < " \t \t " < < " case " < < num < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " return Navigate " < < field . GetFriendlyName ( ) < < " (); " < < std : : endl ;
2017-12-13 12:49:04 +01:00
}
num + + ;
}
m_Impl < < " \t \t " < < " default: " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " ;
2015-09-22 09:42:30 +02:00
}
2017-12-13 12:49:04 +01:00
m_Impl < < " \t " < < " throw std::runtime_error( \" Invalid field ID. \" ); " < < std : : endl ;
if ( haveNavigationFields )
m_Impl < < " \t " < < " } " < < std : : endl ;
2015-09-22 09:42:30 +02:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
/* getters */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2013-10-26 09:41:45 +02:00
std : : string prot ;
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FAGetProtected )
2013-10-26 09:41:45 +02:00
prot = " protected " ;
else
prot = " public " ;
2015-03-28 11:04:42 +01:00
m_Header < < prot < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " ;
2017-11-15 09:47:23 +01:00
if ( field . Attributes & FAGetVirtual | | field . PureGetAccessor )
m_Header < < " virtual " ;
2018-01-04 04:25:35 +01:00
m_Header < < field . Type . GetRealType ( ) < < " Get " < < field . GetFriendlyName ( ) < < " () const " ;
2015-02-09 08:50:17 +01:00
2016-08-27 12:17:10 +02:00
if ( field . PureGetAccessor ) {
2015-03-28 11:04:42 +01:00
m_Header < < " = 0; " < < std : : endl ;
2015-02-09 08:50:17 +01:00
} else {
2015-03-28 11:04:42 +01:00
m_Header < < " ; " < < std : : endl ;
2018-01-04 04:25:35 +01:00
m_Impl < < field . Type . GetRealType ( ) < < " ObjectImpl< " < < klass . Name < < " >::Get " < < field . GetFriendlyName ( ) < < " () const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2016-08-27 12:17:10 +02:00
if ( field . GetAccessor . empty ( ) & & ! ( field . Attributes & FANoStorage ) )
2020-03-10 13:19:56 +01:00
m_Impl < < " \t " < < " return m_ " < < field . GetFriendlyName ( ) < < " .load(); " < < std : : endl ;
2015-02-09 08:50:17 +01:00
else
2016-08-27 12:17:10 +02:00
m_Impl < < field . GetAccessor < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2015-02-09 08:50:17 +01:00
}
2013-10-26 09:41:45 +02:00
}
/* setters */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2013-10-26 09:41:45 +02:00
std : : string prot ;
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FASetProtected )
2013-10-26 09:41:45 +02:00
prot = " protected " ;
else
prot = " public " ;
2015-03-28 11:04:42 +01:00
m_Header < < prot < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " ;
2017-11-15 09:47:23 +01:00
if ( field . Attributes & FASetVirtual | | field . PureSetAccessor )
m_Header < < " virtual " ;
m_Header < < " void Set " < < field . GetFriendlyName ( ) < < " ( " < < field . Type . GetArgumentType ( ) < < " value, bool suppress_events = false, const Value& cookie = Empty) " ;
2013-10-26 09:41:45 +02:00
2016-08-27 12:17:10 +02:00
if ( field . PureSetAccessor ) {
2015-03-28 11:04:42 +01:00
m_Header < < " = 0; " < < std : : endl ;
2015-02-09 08:50:17 +01:00
} else {
2015-03-28 11:04:42 +01:00
m_Header < < " ; " < < std : : endl ;
2016-08-27 12:17:10 +02:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::Set " < < field . GetFriendlyName ( ) < < " ( " < < field . Type . GetArgumentType ( ) < < " value, bool suppress_events, const Value& cookie) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-02-09 08:50:17 +01:00
2021-10-08 16:43:09 +02:00
if ( field . Type . IsName | | ! field . TrackAccessor . empty ( ) | | field . Attributes & FASignalWithOldValue )
m_Impl < < " \t " < < " Value oldValue = Get " < < field . GetFriendlyName ( ) < < " (); " < < std : : endl
< < " \t " < < " auto *dobj = dynamic_cast<ConfigObject *>(this); " < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
if ( field . SetAccessor . empty ( ) & & ! ( field . Attributes & FANoStorage ) )
2020-03-10 13:19:56 +01:00
m_Impl < < " \t " < < " m_ " < < field . GetFriendlyName ( ) < < " .store(value); " < < std : : endl ;
2015-02-09 08:50:17 +01:00
else
2016-08-27 12:17:10 +02:00
m_Impl < < field . SetAccessor < < std : : endl < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Type . IsName | | ! field . TrackAccessor . empty ( ) ) {
if ( field . Name ! = " active " ) {
2021-10-08 16:43:09 +02:00
m_Impl < < " \t " < < " if (!dobj || dobj->IsActive()) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " ;
2015-08-25 13:53:43 +02:00
}
2016-08-27 12:17:10 +02:00
m_Impl < < " \t " < < " Track " < < field . GetFriendlyName ( ) < < " (oldValue, value); " < < std : : endl ;
2015-08-25 13:53:43 +02:00
}
2021-10-08 16:43:09 +02:00
m_Impl < < " \t " < < " if (!suppress_events) { " < < std : : endl
< < " \t \t " < < " Notify " < < field . GetFriendlyName ( ) < < " (cookie); " < < std : : endl ;
if ( field . Attributes & FASignalWithOldValue ) {
m_Impl < < " \t \t " < < " if (!dobj || dobj->IsActive()) " < < std : : endl
< < " \t \t \t " < < " On " < < field . GetFriendlyName ( ) < < " ChangedWithOldValue(static_cast< " < < klass . Name < < " *>(this), oldValue, value); " < < std : : endl ;
}
m_Impl < < " \t " " } " < < std : : endl < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2015-02-09 08:50:17 +01:00
}
2013-10-26 09:41:45 +02:00
}
2015-08-25 13:53:43 +02:00
m_Header < < " protected: " < < std : : endl ;
bool needs_tracking = false ;
/* tracking */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
if ( ! field . Type . IsName & & field . TrackAccessor . empty ( ) )
2015-08-25 13:53:43 +02:00
continue ;
needs_tracking = true ;
2017-11-15 09:47:23 +01:00
m_Header < < " \t " < < " void Track " < < field . GetFriendlyName ( ) < < " ( " < < field . Type . GetArgumentType ( ) < < " oldValue, " < < field . Type . GetArgumentType ( ) < < " newValue); " < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::Track " < < field . GetFriendlyName ( ) < < " ( " < < field . Type . GetArgumentType ( ) < < " oldValue, " < < field . Type . GetArgumentType ( ) < < " newValue) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
if ( ! field . TrackAccessor . empty ( ) )
m_Impl < < " \t " < < field . TrackAccessor < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Type . TypeName ! = " String " ) {
if ( field . Type . ArrayRank > 0 ) {
2016-08-16 11:02:10 +02:00
m_Impl < < " \t " < < " if (oldValue) { " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " ObjectLock olock(oldValue); " < < std : : endl
< < " \t \t " < < " for (const String& ref : oldValue) { " < < std : : endl
< < " \t \t \t " < < " DependencyGraph::RemoveDependency(this, ConfigObject::GetObject " ;
2016-08-16 11:02:10 +02:00
/* Ew */
2016-08-27 12:17:10 +02:00
if ( field . Type . TypeName = = " Zone " & & m_Library = = " base " )
2016-08-16 11:02:10 +02:00
m_Impl < < " ( \" Zone \" , " ;
else
2016-08-27 12:17:10 +02:00
m_Impl < < " < " < < field . Type . TypeName < < " >( " ;
2016-08-16 11:02:10 +02:00
m_Impl < < " ref).get()); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " } " < < std : : endl
< < " \t " < < " } " < < std : : endl
< < " \t " < < " if (newValue) { " < < std : : endl
< < " \t \t " < < " ObjectLock olock(newValue); " < < std : : endl
< < " \t \t " < < " for (const String& ref : newValue) { " < < std : : endl
< < " \t \t \t " < < " DependencyGraph::AddDependency(this, ConfigObject::GetObject " ;
2016-08-16 11:02:10 +02:00
/* Ew */
2016-08-27 12:17:10 +02:00
if ( field . Type . TypeName = = " Zone " & & m_Library = = " base " )
2016-08-16 11:02:10 +02:00
m_Impl < < " ( \" Zone \" , " ;
else
2016-08-27 12:17:10 +02:00
m_Impl < < " < " < < field . Type . TypeName < < " >( " ;
2016-08-16 11:02:10 +02:00
m_Impl < < " ref).get()); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " } " < < std : : endl
< < " \t " < < " } " < < std : : endl ;
2016-08-16 11:02:10 +02:00
} else {
m_Impl < < " \t " < < " if (!oldValue.IsEmpty()) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " DependencyGraph::RemoveDependency(this, ConfigObject::GetObject " ;
2016-08-16 11:02:10 +02:00
/* Ew */
2016-08-27 12:17:10 +02:00
if ( field . Type . TypeName = = " Zone " & & m_Library = = " base " )
2016-08-16 11:02:10 +02:00
m_Impl < < " ( \" Zone \" , " ;
else
2016-08-27 12:17:10 +02:00
m_Impl < < " < " < < field . Type . TypeName < < " >( " ;
2016-08-16 11:02:10 +02:00
m_Impl < < " oldValue).get()); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (!newValue.IsEmpty()) " < < std : : endl
< < " \t \t " < < " DependencyGraph::AddDependency(this, ConfigObject::GetObject " ;
2016-08-16 11:02:10 +02:00
/* Ew */
2016-08-27 12:17:10 +02:00
if ( field . Type . TypeName = = " Zone " & & m_Library = = " base " )
2016-08-16 11:02:10 +02:00
m_Impl < < " ( \" Zone \" , " ;
else
2016-08-27 12:17:10 +02:00
m_Impl < < " < " < < field . Type . TypeName < < " >( " ;
2016-08-16 11:02:10 +02:00
m_Impl < < " newValue).get()); " < < std : : endl ;
}
2015-08-25 13:53:43 +02:00
}
m_Impl < < " } " < < std : : endl < < std : : endl ;
}
2015-09-22 09:42:30 +02:00
/* navigation */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
if ( ( field . Attributes & FANavigation ) = = 0 )
2015-09-22 09:42:30 +02:00
continue ;
m_Header < < " public: " < < std : : endl
2018-01-04 04:25:35 +01:00
< < " \t " < < " Object::Ptr Navigate " < < field . GetFriendlyName ( ) < < " () const " ;
2015-09-22 09:42:30 +02:00
2016-08-27 12:17:10 +02:00
if ( field . PureNavigateAccessor ) {
2015-09-22 09:42:30 +02:00
m_Header < < " = 0; " < < std : : endl ;
} else {
m_Header < < " ; " < < std : : endl ;
2018-01-04 04:25:35 +01:00
m_Impl < < " Object::Ptr ObjectImpl< " < < klass . Name < < " >::Navigate " < < field . GetFriendlyName ( ) < < " () const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-09-22 09:42:30 +02:00
2016-08-27 12:17:10 +02:00
if ( field . NavigateAccessor . empty ( ) )
m_Impl < < " \t " < < " return Get " < < field . GetFriendlyName ( ) < < " (); " < < std : : endl ;
2015-09-22 09:42:30 +02:00
else
2016-08-27 12:17:10 +02:00
m_Impl < < " \t " < < field . NavigateAccessor < < std : : endl ;
2015-09-22 09:42:30 +02:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
}
}
2015-08-25 13:53:43 +02:00
/* start/stop */
if ( needs_tracking ) {
2017-11-15 09:47:23 +01:00
m_Header < < " protected: " < < std : : endl
2018-01-04 05:12:56 +01:00
< < " \t void Start(bool runtimeCreated = false) override; " < < std : : endl
< < " \t void Stop(bool runtimeRemoved = false) override; " < < std : : endl ;
2015-08-25 13:53:43 +02:00
2015-08-20 17:18:48 +02:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::Start(bool runtimeCreated) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
< < " \t " < < klass . Parent < < " ::Start(runtimeCreated); " < < std : : endl < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
if ( ! field . Type . IsName & & field . TrackAccessor . empty ( ) )
2015-08-25 13:53:43 +02:00
continue ;
2016-08-27 12:17:10 +02:00
m_Impl < < " \t " < < " Track " < < field . GetFriendlyName ( ) < < " (Empty, Get " < < field . GetFriendlyName ( ) < < " ()); " < < std : : endl ;
2015-08-25 13:53:43 +02:00
}
m_Impl < < " } " < < std : : endl < < std : : endl
2017-12-19 15:50:05 +01:00
< < " void ObjectImpl< " < < klass . Name < < " >::Stop(bool runtimeRemoved) " < < std : : endl
< < " { " < < std : : endl
< < " \t " < < klass . Parent < < " ::Stop(runtimeRemoved); " < < std : : endl < < std : : endl ;
2015-08-25 13:53:43 +02:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
if ( ! field . Type . IsName & & field . TrackAccessor . empty ( ) )
2015-08-25 13:53:43 +02:00
continue ;
2016-08-27 12:17:10 +02:00
m_Impl < < " \t " < < " Track " < < field . GetFriendlyName ( ) < < " (Get " < < field . GetFriendlyName ( ) < < " (), Empty); " < < std : : endl ;
2015-08-25 13:53:43 +02:00
}
m_Impl < < " } " < < std : : endl < < std : : endl ;
}
2015-08-04 14:47:44 +02:00
/* notify */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2015-08-04 14:47:44 +02:00
std : : string prot ;
2016-08-27 12:17:10 +02:00
if ( field . Attributes & FASetProtected )
2015-08-04 14:47:44 +02:00
prot = " protected " ;
else
prot = " public " ;
m_Header < < prot < < " : " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " virtual void Notify " < < field . GetFriendlyName ( ) < < " (const Value& cookie = Empty); " < < std : : endl ;
2015-08-04 14:47:44 +02:00
2016-08-27 12:17:10 +02:00
m_Impl < < " void ObjectImpl< " < < klass . Name < < " >::Notify " < < field . GetFriendlyName ( ) < < " (const Value& cookie) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2015-08-04 14:47:44 +02:00
2016-08-27 12:17:10 +02:00
if ( field . Name ! = " active " ) {
2018-01-04 09:07:03 +01:00
m_Impl < < " \t " < < " auto *dobj = dynamic_cast<ConfigObject *>(this); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " if (!dobj || dobj->IsActive()) " < < std : : endl
< < " \t " ;
2015-08-04 14:47:44 +02:00
}
2016-08-27 12:17:10 +02:00
m_Impl < < " \t " < < " On " < < field . GetFriendlyName ( ) < < " Changed(static_cast< " < < klass . Name < < " *>(this), cookie); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2015-08-04 14:47:44 +02:00
}
2013-10-26 09:41:45 +02:00
/* default */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
std : : string realType = field . Type . GetRealType ( ) ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
m_Header < < " private: " < < std : : endl
2018-01-04 04:25:35 +01:00
< < " \t " < < " inline " < < realType < < " GetDefault " < < field . GetFriendlyName ( ) < < " () const; " < < std : : endl ;
2015-03-28 11:04:42 +01:00
2018-01-04 04:25:35 +01:00
m_Impl < < realType < < " ObjectImpl< " < < klass . Name < < " >::GetDefault " < < field . GetFriendlyName ( ) < < " () const " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2016-08-27 12:17:10 +02:00
if ( field . DefaultAccessor . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " return " < < realType < < " (); " < < std : : endl ;
2013-10-26 09:41:45 +02:00
else
2016-08-27 12:17:10 +02:00
m_Impl < < " \t " < < field . DefaultAccessor < < std : : endl ;
2013-10-26 09:41:45 +02:00
2015-08-21 14:38:56 +02:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2014-11-30 23:32:13 +01:00
/* validators */
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
2015-03-28 11:04:42 +01:00
m_Header < < " protected: " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t " < < " virtual void Validate " < < field . GetFriendlyName ( ) < < " (const Lazy< " < < field . Type . GetRealType ( ) < < " >& lvalue, const ValidationUtils& utils); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2013-10-26 09:41:45 +02:00
/* instance variables */
2015-03-28 11:04:42 +01:00
m_Header < < " private: " < < std : : endl ;
2013-10-26 09:41:45 +02:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
if ( field . Attributes & FANoStorage )
2015-08-25 13:53:43 +02:00
continue ;
2020-03-10 13:19:56 +01:00
m_Header < < " \t EventuallyAtomic< " < < field . Type . GetRealType ( ) < < " >::type m_ " < < field . GetFriendlyName ( ) < < " ; " < < std : : endl ;
2013-10-26 09:41:45 +02:00
}
2015-08-04 14:47:44 +02:00
/* signal */
m_Header < < " public: " < < std : : endl ;
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
m_Header < < " \t " < < " static boost::signals2::signal<void (const intrusive_ptr< " < < klass . Name < < " >&, const Value&)> On " < < field . GetFriendlyName ( ) < < " Changed; " < < std : : endl ;
m_Impl < < std : : endl < < " boost::signals2::signal<void (const intrusive_ptr< " < < klass . Name < < " >&, const Value&)> ObjectImpl< " < < klass . Name < < " >::On " < < field . GetFriendlyName ( ) < < " Changed; " < < std : : endl < < std : : endl ;
2021-10-08 16:43:09 +02:00
if ( field . Attributes & FASignalWithOldValue ) {
m_Header < < " \t " < < " static boost::signals2::signal<void (const intrusive_ptr< " < < klass . Name
< < " >&, const Value&, const Value&)> On " < < field . GetFriendlyName ( ) < < " ChangedWithOldValue; "
< < std : : endl ;
m_Impl < < std : : endl < < " boost::signals2::signal<void (const intrusive_ptr< " < < klass . Name
< < " >&, const Value&, const Value&)> ObjectImpl< " < < klass . Name < < " >::On "
< < field . GetFriendlyName ( ) < < " ChangedWithOldValue; " < < std : : endl < < std : : endl ;
}
2015-08-04 14:47:44 +02:00
}
2013-10-26 09:41:45 +02:00
}
2015-08-15 20:28:05 +02:00
if ( klass . Name = = " ConfigObject " )
2015-03-28 11:04:42 +01:00
m_Header < < " \t " < < " friend class ConfigItem; " < < std : : endl ;
2014-11-06 19:35:47 +01:00
if ( ! klass . TypeBase . empty ( ) )
2015-03-28 11:04:42 +01:00
m_Header < < " \t " < < " friend class " < < klass . TypeBase < < " ; " < < std : : endl ;
2014-11-06 19:35:47 +01:00
2015-03-28 11:04:42 +01:00
m_Header < < " }; " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
2016-08-27 12:17:10 +02:00
for ( const Field & field : klass . Fields ) {
m_MissingValidators [ std : : make_pair ( klass . Name , field . GetFriendlyName ( ) ) ] = field ;
2014-11-30 23:32:13 +01:00
}
}
2015-03-28 11:04:42 +01:00
void ClassCompiler : : CodeGenValidator ( const std : : string & name , const std : : string & klass , const std : : vector < Rule > & rules , const std : : string & field , const FieldType & fieldType , ValidatorType validatorType )
2014-11-30 23:32:13 +01:00
{
2015-03-28 23:38:05 +01:00
m_Impl < < " static void TIValidate " < < name < < " (const intrusive_ptr<ObjectImpl< " < < klass < < " > >& object, " ;
2014-11-30 23:32:13 +01:00
2015-03-28 23:38:05 +01:00
if ( validatorType ! = ValidatorField )
2015-03-28 11:04:42 +01:00
m_Impl < < " const String& key, " ;
2014-11-30 23:32:13 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < fieldType . GetArgumentType ( ) < < " value, std::vector<String>& location, const ValidationUtils& utils) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl ;
2014-11-30 23:32:13 +01:00
if ( validatorType = = ValidatorField ) {
bool required = false ;
2016-08-25 06:19:44 +02:00
for ( const Rule & rule : rules ) {
2014-11-30 23:32:13 +01:00
if ( ( rule . Attributes & RARequired ) & & rule . Pattern = = field ) {
required = true ;
break ;
}
}
if ( fieldType . GetRealType ( ) ! = " int " & & fieldType . GetRealType ( ) ! = " double " ) {
if ( fieldType . GetRealType ( ) = = " Value " | | fieldType . GetRealType ( ) = = " String " )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " if (value.IsEmpty()) " < < std : : endl ;
2014-11-30 23:32:13 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " if (!value) " < < std : : endl ;
2014-11-30 23:32:13 +01:00
if ( required )
2015-08-15 20:28:05 +02:00
m_Impl < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), location, \" This attribute must not be empty. \" )); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " return; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
}
2015-04-20 14:16:19 +02:00
if ( validatorType ! = ValidatorField )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " bool known_attribute = false; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
bool type_check = false ;
2016-08-25 06:19:44 +02:00
int i = 0 ;
2014-11-30 23:32:13 +01:00
2016-08-25 06:19:44 +02:00
for ( const Rule & rule : rules ) {
2014-11-30 23:32:13 +01:00
if ( rule . Attributes & RARequired )
continue ;
2016-08-25 06:19:44 +02:00
i + + ;
2014-11-30 23:32:13 +01:00
if ( validatorType = = ValidatorField & & rule . Pattern ! = field )
continue ;
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " do { " < < std : : endl ;
2014-11-30 23:32:13 +01:00
if ( validatorType ! = ValidatorField ) {
if ( rule . Pattern ! = " * " ) {
if ( rule . Pattern . find_first_of ( " *? " ) ! = std : : string : : npos )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " if (!Utility::Match( \" " < < rule . Pattern < < " \" , key)) " < < std : : endl ;
2014-11-30 23:32:13 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " if (key != \" " < < rule . Pattern < < " \" ) " < < std : : endl ;
2014-11-30 23:32:13 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t \t " < < " break; " < < std : : endl ;
2015-04-20 14:16:19 +02:00
}
2014-11-30 23:32:13 +01:00
2015-04-20 14:16:19 +02:00
m_Impl < < " \t \t " < < " known_attribute = true; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
if ( rule . IsName ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " if (value.IsScalar()) { " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " if (utils.ValidateName( \" " < < rule . Type < < " \" , value)) " < < std : : endl
< < " \t \t \t \t " < < " return; " < < std : : endl
< < " \t \t \t " < < " else " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t \t \t \t " < < R " (BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, " Object ' " + " ) " << " xxx " << R " ( + " ' of type ') " < < rule . Type < < " ' does not exist. \" )); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " } " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
if ( fieldType . GetRealType ( ) = = " Value " ) {
if ( rule . Type = = " String " )
2015-03-30 14:55:41 +02:00
m_Impl < < " \t \t " < < " if (value.IsEmpty() || value.IsScalar()) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " return; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
else if ( rule . Type = = " Number " ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " try { " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t \t " < < " Convert::ToDouble(value); " < < std : : endl
< < " \t \t \t " < < " return; " < < std : : endl
< < " \t \t " < < " } catch (...) { } " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
}
if ( rule . Type = = " Dictionary " | | rule . Type = = " Array " | | rule . Type = = " Function " ) {
if ( fieldType . GetRealType ( ) = = " Value " ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " if (value.IsObjectType< " < < rule . Type < < " >()) { " < < std : : endl ;
2014-11-30 23:32:13 +01:00
type_check = true ;
} else if ( fieldType . GetRealType ( ) ! = rule . Type + " ::Ptr " ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " if (dynamic_pointer_cast< " < < rule . Type < < " >(value)) { " < < std : : endl ;
2014-11-30 23:32:13 +01:00
type_check = true ;
}
if ( ! rule . Rules . empty ( ) ) {
bool indent = false ;
if ( rule . Type = = " Dictionary " ) {
if ( type_check )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t \t " < < " Dictionary::Ptr dict = value; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " const Dictionary::Ptr& dict = value; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
2015-09-28 08:57:25 +02:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t " < < " { " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " ObjectLock olock(dict); " < < std : : endl
< < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " for (const Dictionary::Pair& kv : dict) { " < < std : : endl
< < ( type_check ? " \t " : " " ) < < " \t \t \t \t " < < " const String& akey = kv.first; " < < std : : endl
< < ( type_check ? " \t " : " " ) < < " \t \t \t \t " < < " const Value& avalue = kv.second; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
indent = true ;
} else if ( rule . Type = = " Array " ) {
if ( type_check )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t \t " < < " Array::Ptr arr = value; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
else
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " const Array::Ptr& arr = value; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
2015-03-28 11:04:42 +01:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t " < < " Array::SizeType anum = 0; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < " \t \t " < < " { " < < std : : endl
< < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " ObjectLock olock(arr); " < < std : : endl
< < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " for (const Value& avalue : arr) { " < < std : : endl
< < ( type_check ? " \t " : " " ) < < " \t \t \t \t " < < " String akey = Convert::ToString(anum); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
indent = true ;
} else {
2015-03-28 11:04:42 +01:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t " < < " String akey = \" \" ; " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < " \t \t " < < " const Value& avalue = value; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
std : : string subvalidator_prefix ;
if ( validatorType = = ValidatorField )
subvalidator_prefix = klass ;
else
subvalidator_prefix = name ;
2018-01-04 09:14:55 +01:00
m_Impl < < ( type_check ? " \t " : " " ) < < ( indent ? " \t \t " : " " ) < < " \t \t " < < " location.emplace_back(akey); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < ( indent ? " \t \t " : " " ) < < " \t \t " < < " TIValidate " < < subvalidator_prefix < < " _ " < < i < < " (object, akey, avalue, location, utils); " < < std : : endl
< < ( type_check ? " \t " : " " ) < < ( indent ? " \t \t " : " " ) < < " \t \t " < < " location.pop_back(); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
if ( rule . Type = = " Array " )
2015-09-28 08:57:25 +02:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t \t \t " < < " anum++; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
2015-09-28 08:57:25 +02:00
if ( rule . Type = = " Dictionary " | | rule . Type = = " Array " ) {
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " } " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < " \t \t " < < " } " < < std : : endl ;
2015-09-28 08:57:25 +02:00
}
2014-11-30 23:32:13 +01:00
2016-08-25 06:19:44 +02:00
for ( const Rule & srule : rule . Rules ) {
2014-11-30 23:32:13 +01:00
if ( ( srule . Attributes & RARequired ) = = 0 )
continue ;
if ( rule . Type = = " Dictionary " ) {
2015-09-28 08:57:25 +02:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t " < < " if (dict->Get( \" " < < srule . Pattern < < " \" ).IsEmpty()) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, \" Required dictionary item ' " < < srule . Pattern < < " ' is not set. \" )); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
} else if ( rule . Type = = " Array " ) {
int index = - 1 ;
std : : stringstream idxbuf ;
idxbuf < < srule . Pattern ;
idxbuf > > index ;
if ( index = = - 1 ) {
std : : cerr < < " Invalid index for 'required' keyword: " < < srule . Pattern ;
std : : exit ( 1 ) ;
}
2015-03-28 11:04:42 +01:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t " < < " if (arr.GetLength() < " < < ( index + 1 ) < < " ) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < ( type_check ? " \t " : " " ) < < " \t \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), location, \" Required index ' " < < index < < " ' is not set. \" )); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
}
}
2015-03-28 11:04:42 +01:00
m_Impl < < ( type_check ? " \t " : " " ) < < " \t \t " < < " return; " < < std : : endl ;
2014-11-30 23:32:13 +01:00
if ( fieldType . GetRealType ( ) = = " Value " | | fieldType . GetRealType ( ) ! = rule . Type + " ::Ptr " )
2015-03-28 11:04:42 +01:00
m_Impl < < " \t \t " < < " } " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " } while (0); " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
if ( type_check | | validatorType ! = ValidatorField ) {
2015-04-20 14:16:19 +02:00
if ( validatorType ! = ValidatorField ) {
2015-03-28 11:04:42 +01:00
m_Impl < < " \t " < < " if (!known_attribute) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, \" Invalid attribute: \" + key)); " < < std : : endl
< < " \t " < < " else " < < std : : endl ;
2015-04-20 14:16:19 +02:00
}
2014-11-30 23:32:13 +01:00
2015-08-15 20:28:05 +02:00
m_Impl < < ( validatorType ! = ValidatorField ? " \t " : " " ) < < " \t " < < " BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, \" Invalid type. \" )); " < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2015-03-28 11:04:42 +01:00
m_Impl < < " } " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
2015-03-28 11:04:42 +01:00
void ClassCompiler : : CodeGenValidatorSubrules ( const std : : string & name , const std : : string & klass , const std : : vector < Rule > & rules )
2014-11-30 23:32:13 +01:00
{
2016-08-25 06:19:44 +02:00
int i = 0 ;
2014-11-30 23:32:13 +01:00
2016-08-25 06:19:44 +02:00
for ( const Rule & rule : rules ) {
2014-11-30 23:32:13 +01:00
if ( rule . Attributes & RARequired )
continue ;
2016-08-25 06:19:44 +02:00
i + + ;
2014-11-30 23:32:13 +01:00
if ( ! rule . Rules . empty ( ) ) {
ValidatorType subtype ;
if ( rule . Type = = " Array " )
subtype = ValidatorArray ;
else if ( rule . Type = = " Dictionary " )
subtype = ValidatorDictionary ;
else {
std : : cerr < < " Invalid sub-validator type: " < < rule . Type < < std : : endl ;
std : : exit ( EXIT_FAILURE ) ;
}
std : : ostringstream namebuf ;
namebuf < < name < < " _ " < < i ;
CodeGenValidatorSubrules ( namebuf . str ( ) , klass , rule . Rules ) ;
FieldType ftype ;
ftype . IsName = false ;
ftype . TypeName = " Value " ;
CodeGenValidator ( namebuf . str ( ) , klass , rule . Rules , rule . Pattern , ftype , subtype ) ;
}
}
}
void ClassCompiler : : HandleValidator ( const Validator & validator , const ClassDebugInfo & )
{
CodeGenValidatorSubrules ( validator . Name , validator . Name , validator . Rules ) ;
2016-08-27 12:17:10 +02:00
for ( const auto & it : m_MissingValidators )
CodeGenValidator ( it . first . first + it . first . second , it . first . first , validator . Rules , it . second . Name , it . second . Type , ValidatorField ) ;
2014-11-30 23:32:13 +01:00
2016-08-27 12:17:10 +02:00
for ( const auto & it : m_MissingValidators ) {
2018-01-11 07:08:09 +01:00
m_Impl < < " void ObjectImpl< " < < it . first . first < < " >::Validate " < < it . first . second < < " (const Lazy< " < < it . second . Type . GetRealType ( ) < < " >& lvalue, const ValidationUtils& utils) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t " < < " SimpleValidate " < < it . first . second < < " (lvalue, utils); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " std::vector<String> location; " < < std : : endl
2018-01-04 09:14:55 +01:00
< < " \t " < < " location.emplace_back( \" " < < it . second . Name < < " \" ); " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t " < < " TIValidate " < < it . first . first < < it . first . second < < " (this, lvalue(), location, utils); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " \t " < < " location.pop_back(); " < < std : : endl
< < " } " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
m_MissingValidators . clear ( ) ;
}
2018-01-04 04:25:35 +01:00
void ClassCompiler : : HandleMissingValidators ( )
2014-11-30 23:32:13 +01:00
{
2016-08-27 12:17:10 +02:00
for ( const auto & it : m_MissingValidators ) {
2018-01-11 07:08:09 +01:00
m_Impl < < " void ObjectImpl< " < < it . first . first < < " >::Validate " < < it . first . second < < " (const Lazy< " < < it . second . Type . GetRealType ( ) < < " >& lvalue, const ValidationUtils& utils) " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " { " < < std : : endl
2018-01-11 07:08:09 +01:00
< < " \t " < < " SimpleValidate " < < it . first . second < < " (lvalue, utils); " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " } " < < std : : endl < < std : : endl ;
2014-11-30 23:32:13 +01:00
}
m_MissingValidators . clear ( ) ;
2013-10-26 09:41:45 +02:00
}
2015-03-28 11:04:42 +01:00
void ClassCompiler : : CompileFile ( const std : : string & inputpath ,
2017-12-19 15:50:05 +01:00
const std : : string & implpath , const std : : string & headerpath )
2013-10-26 09:41:45 +02:00
{
2015-03-28 11:04:42 +01:00
std : : ifstream input ;
input . open ( inputpath . c_str ( ) , std : : ifstream : : in ) ;
if ( ! input ) {
std : : cerr < < " Could not open input file: " < < inputpath < < std : : endl ;
std : : exit ( EXIT_FAILURE ) ;
}
std : : string tmpheaderpath = headerpath + " .tmp " ;
std : : ofstream oheader ;
oheader . open ( tmpheaderpath . c_str ( ) , std : : ofstream : : out ) ;
if ( ! oheader ) {
std : : cerr < < " Could not open header file: " < < tmpheaderpath < < std : : endl ;
std : : exit ( EXIT_FAILURE ) ;
}
std : : string tmpimplpath = implpath + " .tmp " ;
std : : ofstream oimpl ;
oimpl . open ( tmpimplpath . c_str ( ) , std : : ofstream : : out ) ;
if ( ! oimpl ) {
std : : cerr < < " Could not open implementation file: " < < tmpimplpath < < std : : endl ;
std : : exit ( EXIT_FAILURE ) ;
}
CompileStream ( inputpath , input , oimpl , oheader ) ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
input . close ( ) ;
oimpl . close ( ) ;
oheader . close ( ) ;
2013-10-26 09:41:45 +02:00
2015-03-28 11:04:42 +01:00
# ifdef _WIN32
_unlink ( headerpath . c_str ( ) ) ;
# endif /* _WIN32 */
if ( rename ( tmpheaderpath . c_str ( ) , headerpath . c_str ( ) ) < 0 ) {
std : : cerr < < " Could not rename header file: " < < tmpheaderpath < < " -> " < < headerpath < < std : : endl ;
std : : exit ( EXIT_FAILURE ) ;
}
# ifdef _WIN32
_unlink ( implpath . c_str ( ) ) ;
# endif /* _WIN32 */
if ( rename ( tmpimplpath . c_str ( ) , implpath . c_str ( ) ) < 0 ) {
std : : cerr < < " Could not rename implementation file: " < < tmpimplpath < < " -> " < < implpath < < std : : endl ;
std : : exit ( EXIT_FAILURE ) ;
}
2013-10-26 09:41:45 +02:00
}
2014-11-30 23:32:13 +01:00
std : : string ClassCompiler : : BaseName ( const std : : string & path )
2014-09-09 13:30:54 +02:00
{
char * dir = strdup ( path . c_str ( ) ) ;
std : : string result ;
2017-12-14 15:37:20 +01:00
if ( ! dir )
2014-09-09 13:30:54 +02:00
throw std : : bad_alloc ( ) ;
# ifndef _WIN32
result = basename ( dir ) ;
# else /* _WIN32 */
result = PathFindFileName ( dir ) ;
# endif /* _WIN32 */
free ( dir ) ;
return result ;
}
std : : string ClassCompiler : : FileNameToGuardName ( const std : : string & fname )
{
std : : string result = fname ;
2016-08-25 06:19:44 +02:00
std : : locale locale ;
2014-09-09 13:30:54 +02:00
2016-08-25 06:19:44 +02:00
for ( auto & ch : result ) {
ch = std : : toupper ( ch , locale ) ;
2014-09-09 13:30:54 +02:00
2016-08-25 06:19:44 +02:00
if ( ch = = ' . ' )
ch = ' _ ' ;
2014-09-09 13:30:54 +02:00
}
return result ;
}
2015-03-28 11:04:42 +01:00
void ClassCompiler : : CompileStream ( const std : : string & path , std : : istream & input ,
2017-12-19 15:50:05 +01:00
std : : ostream & oimpl , std : : ostream & oheader )
2013-10-26 09:41:45 +02:00
{
2015-03-28 11:04:42 +01:00
input . exceptions ( std : : istream : : badbit ) ;
2013-10-26 09:41:45 +02:00
2014-09-09 13:30:54 +02:00
std : : string guard_name = FileNameToGuardName ( BaseName ( path ) ) ;
2015-03-28 11:04:42 +01:00
oheader < < " #ifndef " < < guard_name < < std : : endl
< < " #define " < < guard_name < < std : : endl < < std : : endl ;
oheader < < " #include \" base/object.hpp \" " < < std : : endl
< < " #include \" base/type.hpp \" " < < std : : endl
< < " #include \" base/value.hpp \" " < < std : : endl
< < " #include \" base/array.hpp \" " < < std : : endl
2020-03-10 13:19:56 +01:00
< < " #include \" base/atomic.hpp \" " < < std : : endl
2015-08-04 14:47:44 +02:00
< < " #include \" base/dictionary.hpp \" " < < std : : endl
< < " #include <boost/signals2.hpp> " < < std : : endl < < std : : endl ;
2015-03-28 11:04:42 +01:00
oimpl < < " #include \" base/exception.hpp \" " < < std : : endl
2017-12-19 15:50:05 +01:00
< < " #include \" base/objectlock.hpp \" " < < std : : endl
< < " #include \" base/utility.hpp \" " < < std : : endl
< < " #include \" base/convert.hpp \" " < < std : : endl
< < " #include \" base/dependencygraph.hpp \" " < < std : : endl
< < " #include \" base/logger.hpp \" " < < std : : endl
< < " #include \" base/function.hpp \" " < < std : : endl
< < " #include \" base/configtype.hpp \" " < < std : : endl
< < " #ifdef _MSC_VER " < < std : : endl
< < " #pragma warning( push ) " < < std : : endl
< < " #pragma warning( disable : 4244 ) " < < std : : endl
< < " #pragma warning( disable : 4800 ) " < < std : : endl
< < " #endif /* _MSC_VER */ " < < std : : endl < < std : : endl ;
2015-03-28 11:04:42 +01:00
ClassCompiler ctx ( path , input , oimpl , oheader ) ;
2013-10-26 09:41:45 +02:00
ctx . Compile ( ) ;
2015-03-28 11:04:42 +01:00
oheader < < " #endif /* " < < guard_name < < " */ " < < std : : endl ;
2014-09-09 13:30:54 +02:00
2015-03-28 11:04:42 +01:00
oimpl < < " #ifdef _MSC_VER " < < std : : endl
< < " #pragma warning ( pop ) " < < std : : endl
< < " #endif /* _MSC_VER */ " < < std : : endl ;
2013-10-26 09:41:45 +02:00
}