444 lines
16 KiB
C++
444 lines
16 KiB
C++
//! \~\file picodeinfo.h
|
||
//! \~\ingroup Code
|
||
//! \~\brief
|
||
//! \~english C++ code info structs. See \ref code_model.
|
||
//! \~russian Структуры для C++ кода. Подробнее \ref code_model.
|
||
//! \~\details
|
||
//! \~english Contains structures for code generation and reflection: TypeInfo, FunctionInfo, ClassInfo, EnumInfo, EnumeratorInfo.
|
||
//! \~russian Содержит структуры для кодогенерации и рефлексии: TypeInfo, FunctionInfo, ClassInfo, EnumInfo, EnumeratorInfo.
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
C++ code info structs
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
|
||
#ifndef PICODEINFO_H
|
||
#define PICODEINFO_H
|
||
|
||
#include "piconstchars.h"
|
||
#include "pistringlist.h"
|
||
#include "pivarianttypes.h"
|
||
|
||
|
||
class PIVariant;
|
||
|
||
//! \~english Namespace contains structures for code generation. See \ref code_model.
|
||
//! \~russian Пространство имен содержит структуры для кодогенерации. Подробнее \ref code_model.
|
||
//! \~\details
|
||
//! \~english Provides classes and structures for code introspection, including type information, function details, class metadata, and enum
|
||
//! information.
|
||
//! \~russian Предоставляет классы и структуры для интроспекции кода, включая информацию о типах, детали функций, метаданные классов и
|
||
//! информацию о перечислениях.
|
||
namespace PICodeInfo {
|
||
|
||
|
||
//! \~english Type modifiers.
|
||
//! \~russian Модификаторы типа.
|
||
enum TypeFlag {
|
||
NoFlag /** \~english No modifiers. \~russian Модификаторы отсутствуют. */,
|
||
Const = 0x01 /** \~english \c const modifier. \~russian Модификатор \c const. */,
|
||
Static = 0x02 /** \~english \c static modifier. \~russian Модификатор \c static. */,
|
||
Mutable = 0x04 /** \~english \c mutable modifier. \~russian Модификатор \c mutable. */,
|
||
Volatile = 0x08 /** \~english \c volatile modifier. \~russian Модификатор \c volatile. */,
|
||
Inline = 0x10 /** \~english \c inline modifier. \~russian Модификатор \c inline. */,
|
||
Virtual = 0x20 /** \~english \c virtual modifier. \~russian Модификатор \c virtual. */,
|
||
Extern = 0x40 /** \~english \c extern modifier. \~russian Модификатор \c extern. */
|
||
};
|
||
|
||
//! \~english Bitmask of type modifiers.
|
||
//! \~russian Битовая маска модификаторов типа.
|
||
typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
|
||
//! \~english Custom metadata map produced by \c PIMETA.
|
||
//! \~russian Карта пользовательских метаданных, создаваемых \c PIMETA.
|
||
typedef PIMap<PIString, PIString> MetaMap;
|
||
//! \~english Callback returning serialized member data by member name.
|
||
//! \~russian Обратный вызов, возвращающий сериализованные данные члена по имени.
|
||
typedef PIByteArray (*AccessValueFunction)(const void *, const char *);
|
||
//! \~english Callback returning a member type name by member name.
|
||
//! \~russian Обратный вызов, возвращающий имя типа члена по его имени.
|
||
typedef const char * (*AccessTypeFunction)(const char *);
|
||
//! \~english Callback returning a member offset by member name.
|
||
//! \~russian Обратный вызов, возвращающий смещение члена по его имени.
|
||
typedef int (*AccessOffsetFunction)(const char *);
|
||
|
||
|
||
//! \~english Type information
|
||
//! \~russian Информация о типе
|
||
struct PIP_EXPORT TypeInfo {
|
||
//! \~english Constructs type information for one variable or argument.
|
||
//! \~russian Создает описание типа для одной переменной или аргумента.
|
||
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {
|
||
name = n;
|
||
type = t;
|
||
flags = f;
|
||
bits = b;
|
||
}
|
||
|
||
//! \~english Returns whether the described variable is a bitfield.
|
||
//! \~russian Возвращает, является ли описываемая переменная битовым полем.
|
||
bool isBitfield() const { return bits > 0; }
|
||
|
||
//! \~english Custom PIMETA content
|
||
//! \~russian Произвольное содержимое PIMETA
|
||
MetaMap meta;
|
||
|
||
//! \~english Name
|
||
//! \~russian Имя
|
||
PIConstChars name;
|
||
|
||
//! \~english Type
|
||
//! \~russian Тип
|
||
PIConstChars type;
|
||
|
||
//! \~english Modifiers
|
||
//! \~russian Модификаторы
|
||
PICodeInfo::TypeFlags flags;
|
||
|
||
//! \~english Bitfield variable bit count
|
||
//! \~russian Количество бит битового поля
|
||
int bits;
|
||
};
|
||
|
||
|
||
//! \~english Method information
|
||
//! \~russian Информация о методе
|
||
struct PIP_EXPORT FunctionInfo {
|
||
//! \~english Custom PIMETA content
|
||
//! \~russian Произвольное содержимое PIMETA
|
||
MetaMap meta;
|
||
|
||
//! \~english Name
|
||
//! \~russian Имя
|
||
PIConstChars name;
|
||
|
||
//! \~english Return type
|
||
//! \~russian Возвращаемый тип
|
||
TypeInfo return_type;
|
||
|
||
//! \~english Arguments types
|
||
//! \~russian Типы аргументов
|
||
PIVector<PICodeInfo::TypeInfo> arguments;
|
||
};
|
||
|
||
|
||
//! \~english Class or struct information
|
||
//! \~russian Информация о классе или структуре
|
||
struct PIP_EXPORT ClassInfo {
|
||
//! \~english Constructs an empty class description.
|
||
//! \~russian Создает пустое описание класса.
|
||
ClassInfo() { is_anonymous = false; }
|
||
|
||
//! \~english Custom PIMETA content
|
||
//! \~russian Произвольное содержимое PIMETA
|
||
MetaMap meta;
|
||
|
||
//! \~english Indicates that the type was declared without a name
|
||
//! \~russian Показывает, что тип был объявлен без имени
|
||
bool is_anonymous;
|
||
|
||
//! \~english Declaration kind, for example \c class or \c struct
|
||
//! \~russian Вид объявления, например \c class или \c struct
|
||
PIConstChars type;
|
||
|
||
//! \~english Name
|
||
//! \~russian Имя
|
||
PIConstChars name;
|
||
|
||
//! \~english Base class names
|
||
//! \~russian Имена базовых классов
|
||
PIVector<PIConstChars> parents;
|
||
|
||
//! \~english Variables
|
||
//! \~russian Переменные
|
||
PIVector<PICodeInfo::TypeInfo> variables;
|
||
|
||
//! \~english Methods
|
||
//! \~russian Методы
|
||
PIVector<PICodeInfo::FunctionInfo> functions;
|
||
|
||
//! \~english Registered derived class descriptions
|
||
//! \~russian Зарегистрированные описания производных классов
|
||
PIVector<PICodeInfo::ClassInfo *> children_info;
|
||
};
|
||
|
||
|
||
//! \~english Enumerator information
|
||
//! \~russian Информация об элементе перечисления
|
||
struct PIP_EXPORT EnumeratorInfo {
|
||
//! \~english Constructs one enum member description.
|
||
//! \~russian Создает описание одного элемента перечисления.
|
||
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {
|
||
name = n;
|
||
value = v;
|
||
}
|
||
//! \~english Converts the enumerator to the %PIVariantTypes representation.
|
||
//! \~russian Преобразует элемент перечисления в представление %PIVariantTypes.
|
||
PIVariantTypes::Enumerator toPIVariantEnumerator() { return PIVariantTypes::Enumerator(value, name.toString()); }
|
||
|
||
//! \~english Custom PIMETA content
|
||
//! \~russian Произвольное содержимое PIMETA
|
||
MetaMap meta;
|
||
|
||
//! \~english Name
|
||
//! \~russian Имя
|
||
PIConstChars name;
|
||
|
||
//! \~english Value
|
||
//! \~russian Значение
|
||
int value;
|
||
};
|
||
|
||
|
||
//! \~english Enum information
|
||
//! \~russian Информация о перечислении
|
||
struct PIP_EXPORT EnumInfo {
|
||
//! \~english Returns the member name for the value \a value.
|
||
//! \~russian Возвращает имя элемента для значения \a value.
|
||
PIString memberName(int value) const;
|
||
|
||
//! \~english Returns the member value for the name \a name.
|
||
//! \~russian Возвращает значение элемента для имени \a name.
|
||
int memberValue(const PIString & name) const;
|
||
|
||
//! \~english Converts the enum description to %PIVariantTypes::Enum.
|
||
//! \~russian Преобразует описание перечисления в %PIVariantTypes::Enum.
|
||
PIVariantTypes::Enum toPIVariantEnum();
|
||
|
||
//! \~english Custom PIMETA content
|
||
//! \~russian Произвольное содержимое PIMETA
|
||
MetaMap meta;
|
||
|
||
//! \~english Name
|
||
//! \~russian Имя
|
||
PIConstChars name;
|
||
|
||
//! \~english Members
|
||
//! \~russian Элементы
|
||
PIVector<PICodeInfo::EnumeratorInfo> members;
|
||
};
|
||
|
||
|
||
//! \~english Writes a declaration-like view of \a v to \a s.
|
||
//! \~russian Записывает в \a s представление \a v в стиле объявления.
|
||
inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
|
||
if (v.flags[Inline]) s << "inline ";
|
||
if (v.flags[Virtual]) s << "virtual ";
|
||
if (v.flags[Mutable]) s << "mutable ";
|
||
if (v.flags[Volatile]) s << "volatile ";
|
||
if (v.flags[Static]) s << "static ";
|
||
if (v.flags[Const]) s << "const ";
|
||
s << v.type;
|
||
if (!v.name.isEmpty()) s << " " << v.name;
|
||
return s;
|
||
}
|
||
|
||
//! \~english Writes an enum member description to \a s.
|
||
//! \~russian Записывает описание элемента перечисления в \a s.
|
||
inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) {
|
||
s << v.name << " = " << v.value << " Meta" << v.meta;
|
||
return s;
|
||
}
|
||
|
||
//! \~english Writes a human-readable class description to \a s.
|
||
//! \~russian Записывает в \a s человекочитаемое описание класса.
|
||
inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
|
||
s.saveAndSetControls(0);
|
||
s << "class " << v.name;
|
||
if (!v.parents.isEmpty()) {
|
||
s << ": ";
|
||
bool first = true;
|
||
for (const auto & i: v.parents) {
|
||
if (first)
|
||
first = false;
|
||
else
|
||
s << ", ";
|
||
s << i;
|
||
}
|
||
}
|
||
s << " Meta" << v.meta << " {\n";
|
||
for (const auto & i: v.functions) {
|
||
s << PICoutManipulators::Tab << i.return_type << " " << i.name << "(";
|
||
bool fa = true;
|
||
for (const auto & a: i.arguments) {
|
||
if (fa)
|
||
fa = false;
|
||
else
|
||
s << ", ";
|
||
s << a;
|
||
}
|
||
s << ") Meta" << i.meta << ";\n";
|
||
}
|
||
if (!v.functions.isEmpty() && !v.variables.isEmpty()) s << "\n";
|
||
for (const auto & i: v.variables) {
|
||
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
|
||
}
|
||
s << "}\n";
|
||
s.restoreControls();
|
||
return s;
|
||
}
|
||
|
||
//! \~english Writes a human-readable enum description to \a s.
|
||
//! \~russian Записывает в \a s человекочитаемое описание перечисления.
|
||
inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) {
|
||
s.saveAndSetControls(0);
|
||
s << "enum " << v.name << " Meta" << v.meta << " {\n";
|
||
for (const auto & i: v.members) {
|
||
bool f = true;
|
||
if (f)
|
||
f = false;
|
||
else
|
||
s << ", ";
|
||
s << PICoutManipulators::Tab << i << "\n";
|
||
}
|
||
s << "}\n";
|
||
s.restoreControls();
|
||
return s;
|
||
}
|
||
|
||
|
||
class PIP_EXPORT __Storage__ {
|
||
__Storage__();
|
||
~__Storage__();
|
||
|
||
public:
|
||
static __Storage__ * instance();
|
||
|
||
PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo;
|
||
PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo;
|
||
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
|
||
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
|
||
PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> * accessOffsetFunctions;
|
||
|
||
private:
|
||
NO_COPY_CLASS(__Storage__)
|
||
};
|
||
|
||
class PIP_EXPORT __StorageAccess__ {
|
||
public:
|
||
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() {
|
||
return *(__Storage__::instance()->classesInfo);
|
||
} // namespace PICodeInfo
|
||
|
||
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); }
|
||
|
||
static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() {
|
||
return *(__Storage__::instance()->accessValueFunctions);
|
||
}
|
||
|
||
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
|
||
return *(__Storage__::instance()->accessTypeFunctions);
|
||
}
|
||
|
||
static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() {
|
||
return *(__Storage__::instance()->accessOffsetFunctions);
|
||
}
|
||
};
|
||
|
||
//! \relatesalso PICodeInfo
|
||
//! \~english Macro for the global code model registries.
|
||
//! \~russian Макрос для доступа к глобальным реестрам модели кода.
|
||
#define PICODEINFO PICodeInfo::__StorageAccess__
|
||
|
||
|
||
class PIP_EXPORT ClassInfoInterface {
|
||
public:
|
||
const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") {
|
||
return __Storage__::instance()->classesInfo;
|
||
}
|
||
};
|
||
|
||
static ClassInfoInterface classesInfo;
|
||
|
||
|
||
class PIP_EXPORT EnumsInfoInterface {
|
||
public:
|
||
const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") {
|
||
return __Storage__::instance()->enumsInfo;
|
||
}
|
||
};
|
||
|
||
static EnumsInfoInterface enumsInfo;
|
||
|
||
|
||
class PIP_EXPORT AccessValueFunctionInterface {
|
||
public:
|
||
const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") {
|
||
return __Storage__::instance()->accessValueFunctions;
|
||
}
|
||
};
|
||
|
||
static AccessValueFunctionInterface accessValueFunctions;
|
||
|
||
|
||
class PIP_EXPORT AccessTypeFunctionInterface {
|
||
public:
|
||
const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") {
|
||
return __Storage__::instance()->accessTypeFunctions;
|
||
}
|
||
};
|
||
|
||
static AccessTypeFunctionInterface accessTypeFunctions;
|
||
|
||
|
||
STATIC_INITIALIZER_BEGIN
|
||
NO_UNUSED(classesInfo);
|
||
NO_UNUSED(enumsInfo);
|
||
NO_UNUSED(accessValueFunctions);
|
||
NO_UNUSED(accessTypeFunctions);
|
||
STATIC_INITIALIZER_END
|
||
|
||
|
||
//! \~english Returns a serialized value of \a member_name from an instance of \a class_name.
|
||
//! \~russian Возвращает сериализованное значение \a member_name из экземпляра \a class_name.
|
||
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
|
||
if (!p || !class_name || !member_name) return PIByteArray();
|
||
AccessValueFunction af = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction)0);
|
||
if (!af) return PIByteArray();
|
||
return af(p, member_name);
|
||
}
|
||
|
||
//! \~english Returns the registered type name of \a member_name in \a class_name.
|
||
//! \~russian Возвращает зарегистрированное имя типа \a member_name в \a class_name.
|
||
inline const char * getMemberType(const char * class_name, const char * member_name) {
|
||
if (!class_name || !member_name) return "";
|
||
AccessTypeFunction af = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction)0);
|
||
if (!af) return "";
|
||
return af(member_name);
|
||
}
|
||
|
||
//! \~english Returns \a member_name from \a class_name as %PIVariant when accessors are registered.
|
||
//! \~russian Возвращает \a member_name из \a class_name как %PIVariant, если зарегистрированы функции доступа.
|
||
PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name);
|
||
|
||
|
||
//! \~english Serializes assignable values into \a ret through the stream operator.
|
||
//! \~russian Сериализует присваиваемые значения в \a ret через оператор потока.
|
||
template<typename T, typename std::enable_if<std::is_assignable<T &, const T &>::value, int>::type = 0>
|
||
void serialize(PIByteArray & ret, const T & v) {
|
||
ret << v;
|
||
}
|
||
|
||
//! \~english Fallback overload for values that cannot be written to the byte-array stream.
|
||
//! \~russian Резервная перегрузка для значений, которые нельзя записать в поток массива байт.
|
||
template<typename T, typename std::enable_if<!std::is_assignable<T &, const T &>::value, int>::type = 0>
|
||
void serialize(PIByteArray & ret, const T & v) {}
|
||
|
||
} // namespace PICodeInfo
|
||
|
||
|
||
#endif // PICODEINFO_H
|