Sivelkiria Operating System repository

Commit 962f3b07 authored by Alexey's avatar Alexey
Browse files

refactoring: working version

parent 60451beb
#include "interface_parser.hpp"
interface_parser::interface_parser( const std::string filename ) {
doc.LoadFile( filename.c_str() );
tinyxml2::XMLElement *ptr;
ptr= doc.FirstChildElement( "Interface" )->FirstChildElement();
has_template= strcmp( ptr->Name(), "Template" ) == 0;
if ( has_template ) parse_template( ptr );
ptr= doc.FirstChildElement( "Interface" );
if ( ptr != nullptr ) parse_interface( ptr );
}
void interface_parser::parse_template( tinyxml2::XMLElement *ptr ) {
tinyxml2::XMLNode *tmpnode;
for ( tinyxml2::XMLNode *node= ptr->FirstChild(); node != nullptr;
node= node->NextSibling() ) {
tinyxml2::XMLElement *elem= node->ToElement();
std::pair<std::string, std::string> tmp=
std::pair<std::string, std::string>(
std::string( elem->Attribute( "name" ) ),
std::string( elem->Attribute( "defval" ) ) );
templates.push_back( tmp );
tmpnode= node->FirstChild();
description_template_names.push_back(
std::string( tmpnode->ToElement()->GetText() ) ); // description
// tmpnode->ToElement()->Attribute(language)
}
}
void interface_parser::parse_interface( tinyxml2::XMLElement *ptr ) {
// ptr->ToElement()->Attribute("xsi:schemaLocation");
const char ch[]= "support-type";
supp_type= std::string( ptr->Attribute( ch ) );
tinyxml2::XMLNode *ptr2= ptr->FirstChild();
if ( strcmp( ptr2->ToElement()->Name(), "Template" ) == 0 )
ptr2= ptr2->NextSibling();
// name
name= std::string( ptr2->ToElement()->GetText() );
ptr2= ptr2->NextSibling(); // major
major= std::string( ptr2->ToElement()->GetText() );
ptr2= ptr2->NextSibling(); // minor-max
minor= std::string( ptr2->ToElement()->GetText() );
ptr2= ptr2->NextSibling(); // parse_permision()
parse_permission( ptr2, &perm );
ptr2= ptr2->NextSibling();
while ( strcmp( ptr2->ToElement()->Name(), "method" ) == 0 ) {
parse_method( ptr2 );
ptr2= ptr2->NextSibling();
}
description= std::string( ptr2->ToElement()->GetText() ); // get description
}
void interface_parser::parse_permission(
tinyxml2::XMLNode *ptr, permission *_perm ) {
//надо прописать как права выглядят//
tinyxml2::XMLElement *perm= ptr->ToElement();
const char *default_= perm->Attribute( "default" );
if ( default_ != nullptr )
_perm->default_perm= std::string( default_ ); // may be parse other fields
const char *caller_int= perm->Attribute( "caller-interface" );
if ( caller_int != nullptr ) _perm->caller_int= std::string( caller_int );
const char *caller_method= perm->Attribute( "caller-method" );
if ( caller_method != nullptr )
_perm->caller_method= std::string( caller_method );
const char *caller_obj= perm->Attribute( "caller-object" );
if ( caller_obj != nullptr ) _perm->caller_obj= std::string( caller_obj );
tinyxml2::XMLNode *tmp= ptr->FirstChild();
if ( tmp != nullptr ) { //если есть вложенные права
if ( _perm->subperm == nullptr ) //если нет вектора подправ
_perm->subperm= new std::vector<permission>; //то создаем его
while ( tmp != nullptr ) { //пока подправа еще не перебраны
_perm->subperm->push_back( *( new permission ) ); //добавляем право
parse_permission( tmp, &*_perm->subperm->rbegin() ); //применяем право
tmp= tmp->NextSibling(); //переключаемся на следующее подправо
}
} else
_perm->subperm= nullptr; //инициализируем на всякий
}
void interface_parser::parse_method( tinyxml2::XMLNode *ptr ) {
tinyxml2::XMLElement *method= ptr->ToElement();
methods.resize( methods.size() + 1 );
methods.rbegin()->name= std::string( method->Attribute( "name" ) );
methods.rbegin()->id= std::string( method->Attribute( "id" ) );
methods.rbegin()->minor_since=
std::string( method->Attribute( "minor-since" ) );
tinyxml2::XMLNode *tmp= ptr->FirstChild();
if ( strcmp( tmp->ToElement()->Name(), "cdata-default" ) == 0 ) {
// insert to generator//how?
tmp= tmp->NextSibling();
}
parse_permission( tmp, &( methods.rbegin()->perm ) );
description_methods.push_back( descr_method() );
tmp= tmp->NextSibling();
description_methods.rbegin()->descr_main=
std::string( tmp->ToElement()->GetText() ); // description
tmp= tmp->NextSibling();
std::string ret_type= std::string( tmp->ToElement()->Attribute( "type" ) );
std::pair<std::string, std::string> *p= nullptr;
for ( std::vector<std::pair<std::string, std::string>>::iterator it=
templates.begin();
it != templates.end(); ++it ) // find in templates
if ( it->first == ret_type ) {
p= &*it;
break;
}
methods.rbegin()->ret.first= ret_type;
methods.rbegin()->ret.second= p;
if ( tmp->FirstChildElement() != nullptr )
description_methods.rbegin()->descr_ret= std::string(
tmp->FirstChildElement()->GetText() ); // add description of return
else
description_methods.rbegin()->descr_ret= "";
tmp= tmp->NextSibling(); // arg
while ( tmp != nullptr ) {
parse_arg( tmp );
tmp= tmp->NextSibling(); // arg
}
}
void interface_parser::parse_arg( tinyxml2::XMLNode *ptr ) {
tinyxml2::XMLElement *arg= ptr->ToElement();
methods.rbegin()->args.resize( methods.rbegin()->args.size() + 1 );
std::vector<std::pair<_arg, std::pair<std::string, std::string> *>>::
reverse_iterator gt= methods.rbegin()->args.rbegin();
gt->first.mode= std::string( arg->Attribute( "mode" ) ); // get mode
gt->first.type= std::string( arg->Attribute( "type" ) ); // get type
gt->second= nullptr;
for ( std::vector<std::pair<std::string, std::string>>::iterator it=
templates.begin();
it != templates.end(); ++it ) // find in templates
if ( it->first == gt->first.type ) {
gt->second= &*it;
break;
}
gt->first.name= std::string( arg->Attribute( "name" ) ); // get name arg
gt->first.id= std::string( arg->Attribute( "id" ) ); // get arg id
std::string tmp= std::string( ptr->FirstChild()->ToElement()->GetText() );
description_methods.rbegin()->descr_arg.resize(
description_methods.rbegin()->descr_arg.size() + 1 );
*description_methods.rbegin()->descr_arg.rbegin()= tmp; // get description
}
#include "interfaceParser.hpp"
using namespace Sivelkiria::sdkBuilder;
interfaceParser::interfaceParser( const std::string filename )
: parser( filename, &parse_data ) {
if ( parse_data != nullptr ) parse( parse_data );
}
void interfaceParser::parse( tinyxml2::XMLElement *ptr ) {
// ptr->ToElement()->Attribute("xsi:schemaLocation");
parse_permission( ptr->FirstChildElement( "security-permissions" ), &perm );
for ( tinyxml2::XMLElement *method= ptr->FirstChildElement( "method" );
method != nullptr; method= method->NextSiblingElement( "method" ) )
parse_method( method );
}
void interfaceParser::parse_permission(
tinyxml2::XMLElement *ptr, permission *_perm ) {
//надо прописать как права выглядят//
const char *default_= ptr->Attribute( "default" );
if ( default_ != nullptr )
_perm->default_perm= std::string( default_ ); // may be parse other fields
const char *caller_int= ptr->Attribute( "caller-interface" );
if ( caller_int != nullptr ) _perm->caller_int= std::string( caller_int );
const char *caller_method= ptr->Attribute( "caller-method" );
if ( caller_method != nullptr )
_perm->caller_method= std::string( caller_method );
const char *caller_obj= ptr->Attribute( "caller-object" );
if ( caller_obj != nullptr ) _perm->caller_obj= std::string( caller_obj );
tinyxml2::XMLElement *tmp= ptr->FirstChildElement( "security-permission" );
if ( tmp != nullptr ) { //если есть вложенные права
if ( _perm->subperm == nullptr ) //если нет вектора подправ
_perm->subperm= new std::vector<permission>; //то создаем его
while ( tmp != nullptr ) { //пока подправа еще не перебраны
_perm->subperm->push_back( *( new permission ) ); //добавляем право
parse_permission( tmp, &( _perm->subperm->back() ) ); //применяем право
tmp= tmp->NextSiblingElement(
"security-permission" ); //переключаемся на следующее подправо
}
} else
_perm->subperm= nullptr; //инициализируем на всякий
}
void interfaceParser::parse_method( tinyxml2::XMLElement *ptr ) {
methods.resize( methods.size() + 1 );
methods.back().name= std::string( ptr->Attribute( "name" ) );
methods.back().id= std::string( ptr->Attribute( "id" ) );
methods.back().minor_since= std::string( ptr->Attribute( "minor-since" ) );
tinyxml2::XMLElement *tmp= ptr->FirstChildElement( "cdata-default" );
if ( tmp == nullptr ) {
// insert to generator//how?
}
parse_permission(
ptr->FirstChildElement( "security-permissions" ),
&( methods.back().perm ) );
description_methods.push_back( descr_method() );
description_methods.back().descr_main= std::string(
ptr->FirstChildElement( "description" )->GetText() ); // description
std::string ret_type=
std::string( ptr->FirstChildElement( "return" )->Attribute( "type" ) );
std::pair<std::string, std::string> *p= nullptr;
for ( std::vector<std::pair<std::string, std::string>>::iterator it=
templates.begin();
it != templates.end(); ++it ) // find in templates
if ( it->first == ret_type ) {
p= &*it;
break;
}
methods.back().ret.first= ret_type;
methods.back().ret.second= p;
if ( ptr->FirstChildElement( "return" )->FirstChildElement( "description" ) !=
nullptr )
description_methods.back().descr_ret=
std::string( ptr->FirstChildElement( "return" )
->FirstChildElement( "description" )
->GetText() ); // add description of return
else
description_methods.back().descr_ret= "";
for ( tinyxml2::XMLElement *arg= ptr->FirstChildElement( "arg" );
arg != nullptr; arg= arg->NextSiblingElement( "arg" ) )
parse_arg( arg );
}
void interfaceParser::parse_arg( tinyxml2::XMLElement *ptr ) {
methods.back().args.resize( methods.back().args.size() + 1 );
std::vector<std::pair<_arg, std::pair<std::string, std::string> *>>::
reverse_iterator gt= methods.back().args.rbegin();
gt->first.mode= std::string( ptr->Attribute( "mode" ) ); // get mode
gt->first.type= std::string( ptr->Attribute( "type" ) ); // get type
gt->second= nullptr;
for ( std::vector<std::pair<std::string, std::string>>::iterator it=
templates.begin();
it != templates.end(); ++it ) // find in templates
if ( it->first == gt->first.type ) {
gt->second= &*it;
break;
}
gt->first.name= std::string( ptr->Attribute( "name" ) ); // get name arg
gt->first.id= std::string( ptr->Attribute( "id" ) ); // get arg id
description_methods.back().descr_arg.push_back(
std::string( ptr->FirstChildElement()->GetText() ) ); // get description
}
#pragma once
#include "./tinyxml2.h"
#include <exception>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <iterator>
#include "parser.hpp"
namespace Sivelkiria::sdkBuilder {
struct _arg {
std::string mode, type, name, id;
};
......@@ -34,23 +29,17 @@ struct descr_method {
std::vector<std::string> descr_arg;
};
class interface_parser {
class interfaceParser : public parser {
public:
std::string description;
bool has_template;
tinyxml2::XMLDocument doc;
std::vector<std::pair<std::string, std::string>> templates; // name and defval
std::vector<std::string> description_template_names;
std::vector<method> methods;
std::vector<descr_method> description_methods;
std::string supp_type, name, major, minor;
permission perm;
interface_parser( const std::string filename );
interfaceParser( const std::string filename );
private:
void parse_template( tinyxml2::XMLElement *ptr );
void parse_interface( tinyxml2::XMLElement *ptr );
void parse_permission( tinyxml2::XMLNode *ptr, permission *_perm );
void parse_method( tinyxml2::XMLNode *ptr );
void parse_arg( tinyxml2::XMLNode *ptr );
void parse( tinyxml2::XMLElement *ptr );
void parse_permission( tinyxml2::XMLElement *ptr, permission *_perm );
void parse_method( tinyxml2::XMLElement *ptr );
void parse_arg( tinyxml2::XMLElement *ptr );
};
}; // namespace Sivelkiria::sdkBuilder
\ No newline at end of file
#include "parser.hpp"
using namespace Sivelkiria::sdkBuilder;
parser::parser( const std::string filename, tinyxml2::XMLElement **ptr ) {
doc.LoadFile( filename.c_str() );
( *ptr )= doc.FirstChildElement()->FirstChildElement( "Template" );
has_template= ( *ptr ) != nullptr;
if ( has_template ) parse_templates( ( *ptr ) );
( *ptr )= doc.FirstChildElement();
if ( ( *ptr ) != nullptr ) {
const char ch[]= "support-type";
supp_type= std::string( ( *ptr )->Attribute( ch ) );
name= std::string( ( *ptr )->FirstChildElement( "name" )->GetText() );
major= std::string(
( *ptr )->FirstChildElement( "version-major" )->GetText() );
minor= std::string(
( *ptr )->FirstChildElement( "version-minor-max" )->GetText() );
description= std::string( ( *ptr )
->FirstChildElement( "description" )
->GetText() ); // get description
}
}
void parser::parse_templates( tinyxml2::XMLElement *ptr ) {
for ( tinyxml2::XMLNode *node= ptr->FirstChild(); node != nullptr;
node= node->NextSibling() ) {
tinyxml2::XMLElement *elem= node->ToElement();
std::pair<std::string, std::string> tmp=
std::pair<std::string, std::string>(
std::string( elem->Attribute( "name" ) ),
std::string( elem->Attribute( "defval" ) ) );
templates.push_back( tmp );
tinyxml2::XMLNode *tmpnode= node->FirstChild();
description_template_names.push_back(
std::string( tmpnode->ToElement()->GetText() ) ); // description
// tmpnode->ToElement()->Attribute(language)
}
}
#pragma once
#include "./tinyxml2.h"
#include <exception>
#include "../../3rdparty/tinyxml2/tinyxml2.h"
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <iterator>
struct _field {
std::string type, name, id;
};
class struct_parser {
namespace Sivelkiria::sdkBuilder {
class parser {
public:
tinyxml2::XMLElement *parse_data= nullptr;
std::string description;
bool has_template;
tinyxml2::XMLDocument doc;
std::vector<std::pair<std::string, std::string>> templates; // name and defval
std::vector<std::string> description_template_names;
std::vector<std::pair<_field, std::pair<std::string, std::string> *>> fields;
std::vector<std::string> fields_descriptions;
std::string supp_type, name, major, minor;
struct_parser( const std::string filename );
parser( const std::string filename, tinyxml2::XMLElement **ptr );
private:
void parse_template( tinyxml2::XMLElement *ptr );
void parse_struct( tinyxml2::XMLElement *ptr );
void parse_field( tinyxml2::XMLNode *ptr );
protected:
void parse_templates( tinyxml2::XMLElement *ptr );
virtual void parse( tinyxml2::XMLElement *ptr )= 0;
};
}; // namespace Sivelkiria::sdkBuilder
#include "structParser.hpp"
using namespace Sivelkiria::sdkBuilder;
structParser::structParser( const std::string filename )
: parser( filename, &parse_data ) {
if ( parse_data != nullptr ) parse( parse_data );
}
void structParser::parse( tinyxml2::XMLElement *ptr ) {
// ptr->ToElement()->Attribute("xsi:schemaLocation");
for ( tinyxml2::XMLElement *field= ptr->FirstChildElement( "field" );
field != nullptr; field= field->NextSiblingElement( "field" ) )
parse_field( field );
}
void structParser::parse_field( tinyxml2::XMLElement *field ) {
fields.resize( fields.size() + 1 );
std::vector<std::pair<_field, std::pair<std::string, std::string> *>>::
reverse_iterator gt= fields.rbegin();
gt->first.type= std::string( field->Attribute( "type" ) ); // get type
gt->second= nullptr;
for ( std::vector<std::pair<std::string, std::string>>::iterator it=
templates.begin();
it != templates.end(); ++it ) // find in templates
if ( it->first == gt->first.type ) {
gt->second= &*it;
break;
}
gt->first.name= std::string( field->Attribute( "name" ) ); // get name field
gt->first.id= std::string( field->Attribute( "id" ) ); // get field id
fields_descriptions.push_back(
std::string( field->FirstChildElement()->GetText() ) ); // get description
}
#pragma once
#include "parser.hpp"
namespace Sivelkiria::sdkBuilder {
struct _field {
std::string type, name, id;
};
class structParser : public parser {
public:
std::vector<std::pair<_field, std::pair<std::string, std::string> *>> fields;
std::vector<std::string> fields_descriptions;
structParser( const std::string filename );
private:
void parse( tinyxml2::XMLElement *ptr );
void parse_field( tinyxml2::XMLElement *field );
};
}; // namespace Sivelkiria::sdkBuilder
\ No newline at end of file
#include "cppGenerator.hpp"
#include <fstream>
using namespace Sivelkiria::sdkBuilder;
void cppGenerator::construct(
const std::vector<std::string> &descr_templ,
const std::vector<std::pair<std::string, std::string>> &templ,
const bool &has_template, const std::string type_obj,
const std::string name, const std::string &body ) {
std::string _templ;
std::string description_template;
if ( has_template ) {
description_template= "/*";
_templ= "template<";
std::vector<std::string>::const_iterator gt= descr_templ.begin();
for ( std::vector<std::pair<std::string, std::string>>::const_iterator it=
templ.begin();
it != templ.end(); ++it ) {
description_template= description_template + "\n*" + it->first + " - " +
*( gt++ ) + " Default:" + it->second;
_templ=
_templ + " " + type_obj + " " + it->first + " = " + it->second + ',';
}
description_template= description_template + "\n*/\n";
_templ.back()= ' '; //вставляем вместо последней запятой
_templ+= ">\n" + description_template;
}
construct_hpp( _templ, type_obj, body, name );
}
void cppGenerator::construct_hpp(
const std::string _template, const std::string type_obj,
const std::string &body, const std::string &name ) {
std::string filename= build_dir + name + ".hpp";
std::ofstream hpp_file( filename );
hpp_file << "namespace SivDK{\n"
<< "namespace ";
if ( type_obj == "class" ) hpp_file << "Interfaces";
else if ( type_obj == "struct" )
hpp_file << "Structures";
else
hpp_file << "Error";
hpp_file << "{\n" << _template << type_obj;
hpp_file << " " << name << body << "};\n};\n};";
}
\ No newline at end of file
#pragma once
#include <vector>
#include <string>
namespace Sivelkiria::sdkBuilder {
class cppGenerator {
protected:
std::string build_dir= "./";
/*\brief write sdk
*\details wrtite sdk to build_dir folder
*\date 05.2020
*\param [in] descr_templ all descriptions of templates
*\param [in] templ all templates with default values
*\param [in] has_template flag indicate "is there a template?"
*\param [in] type_obj struct or class
*\param [in] normal_name name with him major and sometimes minor
*\param [in] body body of object
*\return void
*/
void construct(
const std::vector<std::string> &descr_templ,
const std::vector<std::pair<std::string, std::string>> &templ,
const bool &has_template, const std::string type_obj,
const std::string name, const std::string &body );
/*\brief write hpp file
*\details write to build_dir/objname.hpp
*\param [in] _template template code
*\param [in] type_obj struct or class
*\param [in] body body of object
*\param [in] name name of object
*\return void
*/
void construct_hpp(
const std::string _template, const std::string type_obj,
const std::string &body, const std::string &name );
virtual void
build( const std::string &filename, const std::string out_dir )= 0;
};
}; // namespace Sivelkiria::sdkBuilder
\ No newline at end of file
#include "cppInterfaceGenerator.hpp"
using namespace Sivelkiria::sdkBuilder;
std::string cppInterfaceGenerator::generate_body(
const interfaceParser &interface, const std::string normal_name ) {
std::string body= " : public virtual ";
std::string name= normal_name;
if ( interface.minor != "0" ) body+= "SivDK::Object {";
else
body+= name + " {"; //наследуем от 0-й мажорной версии
//тут еще описания методов добавить
if ( interface.minor != "0" ) ( name+= "_" )+= interface.minor;
body+= "\n\tprotected:\n\t\t";
body+= name + "( SivDK::interface_handle handle );\n\t\t";
body+= name + "();\n\tpublic: virtual ~" + name;
body+= "() = default;\n";
std::vector<descr_method>::const_iterator gt=
interface.description_methods.begin();
for ( std::vector<method>::const_iterator it= interface.methods.begin();
it != interface.methods.end(); ++it, ++gt ) {
body+= "/*\n";
body+= gt->descr_main + "\nreturn_type:" + gt->descr_ret;
body+= "\n*/\n\t";
//где-то тут вывести описания аргументов
if ( it->perm.default_perm == "allow" ) body+= "public: virtual ";
else if ( it->perm.default_perm == "deny" )
body+= "private: virtual ";
else {
; //выбросить ошибку или посмотреть вложенные правила
}
//каким-то образом запретить обращаться по правилам
//для вложенных allow friend методы?
body+= it->name + "("; //вывели имя метода
write_args( body, it );
body+= ") = 0;\n";
}
return body;
}
void cppInterfaceGenerator::write_args(
std::string &body, std::vector<method>::const_iterator &it ) {
for ( std::vector<std::pair<_arg, std::pair<std::string, std::string> *>>::
const_iterator gt= it->args.begin();
gt != it->args.end(); ++gt ) {
body+= " ";
if ( gt->first.mode == "in" )
body+= "const "; //но это не защитит-напр const int *p - данные можно
//менять
body+= gt->first.type + " ";
if ( gt->first.mode != "in" ) body+= "&";
body+= gt->first.name + ",";
}
body= body.substr( 0, body.size() - 2 ); //удаляем последнюю запятую