document types
parent
6f8aaadbe9
commit
c654be28b4
|
@ -9,122 +9,360 @@
|
|||
|
||||
namespace sirEdit::data
|
||||
{
|
||||
/**
|
||||
* The state of a type
|
||||
*/
|
||||
enum struct TYPE_STATE {
|
||||
NO,
|
||||
UNUSED,
|
||||
READ,
|
||||
WRITE,
|
||||
DELETE
|
||||
NO, /// Use the state that match best.
|
||||
UNUSED, /// Set force unused
|
||||
READ, /// Allow access to instances of the type
|
||||
WRITE, /// Allow access and add/insert instances of the type
|
||||
DELETE /// Delete every kind of instance from this field. Subtypes will be removed too
|
||||
};
|
||||
|
||||
class TypeWithFields;
|
||||
/**
|
||||
* Basic type defintion.
|
||||
*
|
||||
* How to init: subTypes, metaType and cllide will be set for you
|
||||
* Set name of the type, comment, hints and restrictions
|
||||
* Use this only for build in types
|
||||
* For classes use TypeClass
|
||||
* For interfaces use TypeInterface
|
||||
* For enums use TypeEnum
|
||||
* For typedefinitions use TypeTypedef
|
||||
* You can use the id to save information that you need internal. It's not required.
|
||||
*/
|
||||
class Type {
|
||||
private:
|
||||
std::string __name;
|
||||
std::string __comment;
|
||||
std::vector<Type*> __subTypes;
|
||||
size_t __id = -1;
|
||||
std::string __metaTypeName = "<NOT SET>";
|
||||
std::unordered_map<std::string, std::vector<std::string>> __hints;
|
||||
std::unordered_map<std::string, std::vector<std::string>> __restrictions;
|
||||
std::vector<const Type*> __collide;
|
||||
std::string __name; /// The name of the type
|
||||
std::string __comment; /// The comment of the type
|
||||
std::vector<Type*> __subTypes; /// List of know subtypes. Will be generated
|
||||
size_t __id = -1; /// Serializer internal id, when required
|
||||
std::string __metaTypeName = "<NOT SET>"; /// The name of the kind of type
|
||||
std::unordered_map<std::string, std::vector<std::string>> __hints; /// The hints of the type
|
||||
std::unordered_map<std::string, std::vector<std::string>> __restrictions; /// The restrictions of the type
|
||||
std::vector<const Type*> __collide; /// List of clieded types with same name
|
||||
|
||||
public:
|
||||
/**
|
||||
* Copy type without the subsets
|
||||
* @param type the type to copy
|
||||
*/
|
||||
Type(const Type& type) : __name(type.__name), __comment(type.__comment), __hints(type.__hints), __restrictions(type.__restrictions) {}
|
||||
/**
|
||||
* Constructor for a type
|
||||
* @param name The name of the type
|
||||
* @param comment The comment of the type
|
||||
*/
|
||||
Type(std::string name, std::string comment) : __name(std::move(name)), __comment(std::move(comment)) {}
|
||||
/**
|
||||
* Requires virtual deconstructor to deserialize subtypes
|
||||
*/
|
||||
virtual ~Type() {}
|
||||
|
||||
/**
|
||||
* Support cast to types with fields.
|
||||
* @return type with fields or nullptr when not
|
||||
*/
|
||||
operator TypeWithFields*();
|
||||
/**
|
||||
* Support cast to types with fields.
|
||||
* @return type with fields or nullptr when not
|
||||
*/
|
||||
operator const TypeWithFields*() const;
|
||||
|
||||
/**
|
||||
* Mostly with have subtypes, so don't do it!
|
||||
*/
|
||||
Type& operator =(const Type&) = delete;
|
||||
/**
|
||||
* Mostly with have subtypes, so don't do it!
|
||||
*/
|
||||
Type& operator =(Type&& data) = delete;
|
||||
|
||||
/**
|
||||
* Returns the name of the type.
|
||||
* @param the name of the type
|
||||
*/
|
||||
const std::string& getName() const { return this->__name; }
|
||||
/**
|
||||
* Returns the comment of the type.
|
||||
* @param the comment of the type
|
||||
*/
|
||||
const std::string& getComment() const { return this->__comment; }
|
||||
/**
|
||||
* Returns the sub types of the type.
|
||||
* @param the sub types of the type
|
||||
*/
|
||||
const std::vector<Type*>& getSubTypes() const { return this->__subTypes; }
|
||||
/**
|
||||
* Returns the serializer internal id of the type. Can describe all/nothing, so don't change it.
|
||||
* @param the serializer internal id of the type
|
||||
*/
|
||||
const size_t getID() const { return this->__id; }
|
||||
/**
|
||||
* Returns the meta type name of the type.
|
||||
* @param the meta type name of the type
|
||||
*/
|
||||
const std::string& getMetaTypeName() const { return this->__metaTypeName; }
|
||||
/**
|
||||
* Returns the hints of the type.
|
||||
* @param the hints of the type
|
||||
*/
|
||||
const std::unordered_map<std::string, std::vector<std::string>>& getHints() const { return this->__hints; }
|
||||
/**
|
||||
* Returns the restrictions of the type.
|
||||
* @param the restrictions of the type
|
||||
*/
|
||||
const std::unordered_map<std::string, std::vector<std::string>>& getRestrictions() const { return this->__restrictions; }
|
||||
/**
|
||||
* Returns a list collision with other types.
|
||||
* @param a list of collisions to other types
|
||||
*/
|
||||
const std::vector<const Type*>& getCollides() const { return this->__collide; }
|
||||
/**
|
||||
* Returns a reference to the name variable. Can be used as a setter.
|
||||
* @return name of the type
|
||||
*/
|
||||
std::string& getName() { return this->__name; }
|
||||
/**
|
||||
* Returns a reference to the comment variable. Can be used as a setter.
|
||||
* @return comment of the type
|
||||
*/
|
||||
std::string& getComment() { return this->__comment; }
|
||||
/**
|
||||
* Returns a reference to the sub type variable. Can be used as a setter.
|
||||
* @return sub types of the type
|
||||
*/
|
||||
std::vector<Type*>& getSubTypes() { return this->__subTypes; }
|
||||
/**
|
||||
* Returns a reference to the serializer id variable. Can be used as a setter.
|
||||
* @return serializer id of the type
|
||||
*/
|
||||
size_t& getID() { return this->__id; }
|
||||
/**
|
||||
* Returns a reference to the meta type name variable. Can be used as a setter.
|
||||
* @return meta type name of the type
|
||||
*/
|
||||
std::string& getMetaTypeName() { return this->__metaTypeName; }
|
||||
/**
|
||||
* Returns a reference to the hints variable. Can be used as a setter.
|
||||
* @return hints of the type
|
||||
*/
|
||||
std::unordered_map<std::string, std::vector<std::string>>& getHints() { return this->__hints; }
|
||||
/**
|
||||
* Returns a reference to the restrictions variable. Can be used as a setter.
|
||||
* @return restrictions of the type
|
||||
*/
|
||||
std::unordered_map<std::string, std::vector<std::string>>& getRestrictions() { return this->__restrictions; }
|
||||
/**
|
||||
* Returns a reference to the collitions to other types. Can be used as a setter.
|
||||
* @return collitions to other types
|
||||
*/
|
||||
std::vector<const Type*>& getCollides() { return this->__collide; }
|
||||
};
|
||||
/**
|
||||
* Type that can have fields.
|
||||
*/
|
||||
class TypeWithFields : public Type {
|
||||
private:
|
||||
std::vector<Field> __fields;
|
||||
std::vector<Field> __fields; /// The fields of the type
|
||||
|
||||
public:
|
||||
/**
|
||||
* Copy constructor, to copy the fields
|
||||
* @param twf the source of the fields
|
||||
*/
|
||||
TypeWithFields(const TypeWithFields& twf) : Type(twf), __fields(twf.__fields) {}
|
||||
/**
|
||||
* Create a new type with fields
|
||||
* @param name the name of the type
|
||||
* @param comment the comment of the type
|
||||
* @param fields the fields of the type
|
||||
*/
|
||||
TypeWithFields(std::string name, std::string comment, std::vector<Field> fields) : Type(std::move(name), std::move(comment)), __fields(std::move(fields)) {}
|
||||
/**
|
||||
* Creates a new type with fields
|
||||
* @param type the source type to copy
|
||||
* @param fields the fields of the type
|
||||
*/
|
||||
TypeWithFields(const Type& type, std::vector<Field> fields) : Type(type), __fields(std::move(fields)) {}
|
||||
|
||||
/**
|
||||
* Don't copy it. Fields are dependent on their memory location.
|
||||
*/
|
||||
TypeWithFields& operator =(const TypeWithFields&) = delete;
|
||||
/**
|
||||
* Don't copy it. Fields are dependent on their memory location.
|
||||
*/
|
||||
TypeWithFields& operator =(TypeWithFields&&) = delete;
|
||||
|
||||
/**
|
||||
* Returns the fields of the type.
|
||||
* @param the fields of the type
|
||||
*/
|
||||
const std::vector<Field>& getFields() const { return this->__fields; }
|
||||
/**
|
||||
* Returns a refernce of the fields. Can be used as setter.
|
||||
* @return refernce to the fields
|
||||
*/
|
||||
std::vector<Field>& getFields() { return this->__fields; }
|
||||
};
|
||||
/**
|
||||
* Describs an interface.
|
||||
*/
|
||||
class TypeInterface : public TypeWithFields {
|
||||
private:
|
||||
std::vector<TypeInterface*> __interfaces;
|
||||
Type* __super;
|
||||
std::vector<TypeInterface*> __interfaces; /// The interfaces of the type
|
||||
Type* __super; /// The super type
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new interface.
|
||||
* @param name the name of the type
|
||||
* @param commente the comment of the type
|
||||
* @param fields the fields of the type
|
||||
* @param interfaces the implemented interfaces of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeInterface(std::string name, std::string comment, std::vector<Field> fields, std::vector<TypeInterface*> interfaces, Type* super) : TypeWithFields(std::move(name), std::move(comment), std::move(fields)), __interfaces(std::move(interfaces)), __super(super) {
|
||||
this->getMetaTypeName() = "INTERFACE";
|
||||
}
|
||||
/**
|
||||
* Create a new interface.
|
||||
* @param type the source type to copy
|
||||
* @param fields the fields of the type
|
||||
* @param interfaces the implemented interfaces of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeInterface(const Type& type, std::vector<Field> fields, std::vector<TypeInterface*> interfaces, Type* super) : TypeWithFields(type, std::move(fields)), __interfaces(std::move(interfaces)), __super(super) {
|
||||
this->getMetaTypeName() = "INTERFACE";
|
||||
}
|
||||
/**
|
||||
* Create a new interface.
|
||||
* @param fields the source type to copy
|
||||
* @param interfaces the implemented interfaces of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeInterface(const TypeWithFields& fields, std::vector<TypeInterface*> interfaces, Type* super) : TypeWithFields(fields), __interfaces(std::move(interfaces)), __super(super) {
|
||||
this->getMetaTypeName() = "INTERFACE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of interfaces that the type implements
|
||||
* @return implemented interfaces
|
||||
*/
|
||||
const std::vector<TypeInterface*>& getInterfaces() const { return this->__interfaces; }
|
||||
/**
|
||||
* Returns the super type of this type
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
const Type* getSuper() const { return this->__super; }
|
||||
/**
|
||||
* Returns a reference of a list of interfaces that the type implements. Can be used as setter
|
||||
* @return implemented interfaces
|
||||
*/
|
||||
std::vector<TypeInterface*>& getInterfaces() { return this->__interfaces; }
|
||||
/**
|
||||
* Returns a refernce to super type of this type. Can be used as a setter
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
Type*& getSuper() { return this->__super; }
|
||||
};
|
||||
/**
|
||||
* Describs a class.
|
||||
*/
|
||||
class TypeClass : public TypeWithFields {
|
||||
private:
|
||||
std::vector<TypeInterface*> __interfaces;
|
||||
Type* __super;
|
||||
std::vector<TypeInterface*> __interfaces; /// The interfaces of the type
|
||||
Type* __super; /// The super type
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new class.
|
||||
* @param name the name of the type
|
||||
* @param commente the comment of the type
|
||||
* @param fields the fields of the type
|
||||
* @param interfaces the implemented interfaces of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeClass(std::string name, std::string comment, std::vector<Field> fields, std::vector<TypeInterface*> interfaces, Type* super) : TypeWithFields(std::move(name), std::move(comment), std::move(fields)), __interfaces(std::move(interfaces)), __super(super) {
|
||||
this->getMetaTypeName() = "CLASS";
|
||||
}
|
||||
/**
|
||||
* Create a new class.
|
||||
* @param type the source type to copy
|
||||
* @param fields the fields of the type
|
||||
* @param interfaces the implemented interfaces of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeClass(const Type& type, std::vector<Field> fields, std::vector<TypeInterface*> interfaces, Type* super) : TypeWithFields(std::move(type), std::move(fields)), __interfaces(std::move(interfaces)), __super(super) {
|
||||
this->getMetaTypeName() = "CLASS";
|
||||
}
|
||||
/**
|
||||
* Create a new class.
|
||||
* @param fields the source type to copy
|
||||
* @param interfaces the implemented interfaces of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeClass(const TypeWithFields& fields, std::vector<TypeInterface*> interfaces, Type* super) : TypeWithFields(std::move(fields)), __interfaces(std::move(interfaces)), __super(super) {
|
||||
this->getMetaTypeName() = "CLASS";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of interfaces that the type implements
|
||||
* @return implemented interfaces
|
||||
*/
|
||||
const std::vector<TypeInterface*>& getInterfaces() const { return this->__interfaces; }
|
||||
/**
|
||||
* Returns the super type of this type
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
const Type* getSuper() const { return this->__super; }
|
||||
/**
|
||||
* Returns a reference of a list of interfaces that the type implements. Can be used as setter
|
||||
* @return implemented interfaces
|
||||
*/
|
||||
std::vector<TypeInterface*>& getInterfaces() { return this->__interfaces; }
|
||||
/**
|
||||
* Returns a refernce to super type of this type. Can be used as a setter
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
Type*& getSuper() { return this->__super; }
|
||||
};
|
||||
/**
|
||||
* Describs an enum.
|
||||
*/
|
||||
class TypeEnum : public TypeWithFields {
|
||||
private:
|
||||
Type* __super;
|
||||
Type* __super; /// The super type
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new enum.
|
||||
* @param name the name of the type
|
||||
* @param commente the comment of the type
|
||||
* @param fields the fields of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeEnum(std::string name, std::string comment, std::vector<Field> fields, Type* super) : TypeWithFields(std::move(name), std::move(comment), std::move(fields)), __super(super) {
|
||||
this->getMetaTypeName() = "ENUM";
|
||||
}
|
||||
/**
|
||||
* Create a new enum.
|
||||
* @param type the source type to copy
|
||||
* @param fields the fields of the type
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeEnum(const Type& type, std::vector<Field> fields, Type* super) : TypeWithFields(std::move(type), std::move(fields)), __super(super) {
|
||||
this->getMetaTypeName() = "ENUM";
|
||||
}
|
||||
/**
|
||||
* Create a new enum.
|
||||
* @param fields the source type to copy
|
||||
* @param super the super types of the type
|
||||
*/
|
||||
TypeEnum(const TypeWithFields& fields, Type* super) : TypeWithFields(std::move(fields)), __super(super) {
|
||||
this->getMetaTypeName() = "ENUM";
|
||||
}
|
||||
|
@ -132,22 +370,60 @@ namespace sirEdit::data
|
|||
const Type* getSuper() const { return this->__super; }
|
||||
Type*& getSuper() { return this->__super; }
|
||||
};
|
||||
/**
|
||||
* Describs a typedefintion.
|
||||
* Is like a subclass/interface/... of a type without own implementations or fields
|
||||
*/
|
||||
class TypeTypedef : public Type {
|
||||
private:
|
||||
const Type* __reference;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new typedef.
|
||||
* @param type the source type to copy
|
||||
* @param reference the referenced types of the type
|
||||
*/
|
||||
TypeTypedef(const Type& type, const Type* reference) : Type(type), __reference(reference) {
|
||||
this->getMetaTypeName() = "TYPEDEF";
|
||||
}
|
||||
/**
|
||||
* Create a new typedef.
|
||||
* @param name the name of the type
|
||||
* @param commente the comment of the type
|
||||
* @param reference the referenced types of the type
|
||||
*/
|
||||
TypeTypedef(std::string name, std::string comment, const Type* reference) : Type(std::move(name), std::move(comment)), __reference(reference) {
|
||||
this->getMetaTypeName() = "TYPEDEF";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the super type of this type
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
const Type* getReference() const { return this->__reference; }
|
||||
/**
|
||||
* Returns a refernce to super type of this type. Can be used as a setter
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
const Type*& getReference() { return this->__reference; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function witch decies if it is a base type, interface, class, enum or a typedef. Don with a dynamic cast.
|
||||
* @tparam FUNC_BASE the type of the function/lambda/... for a base type
|
||||
* @tparam FUNC_INTERFACE the type of the function/lambda/... for a interface
|
||||
* @tparam FUNC_CLASS the type of the function/lambda/... for a class
|
||||
* @tparam FUNC_ENUM the type of the function/lambda/... for a enum
|
||||
* @tparam FUNC_TYPEDEF the type of the function/lambda/... for a typedef
|
||||
* @param type the type to check
|
||||
* @param funcBase the function for a base type
|
||||
* @param funcInterface the function for a interface
|
||||
* @param funcClass the function for a class
|
||||
* @param funcEnum the function for a enum
|
||||
* @param funcTypedef the function for a typedef
|
||||
* @return the return value of the function
|
||||
*/
|
||||
template<class FUNC_BASE, class FUNC_INTERFACE, class FUNC_CLASS, class FUNC_ENUM, class FUNC_TYPEDEF>
|
||||
inline decltype((*static_cast<FUNC_BASE*>(nullptr))()) doBaseType(const Type* type, FUNC_BASE funcBase, FUNC_INTERFACE funcInterface, FUNC_CLASS funcClass, FUNC_ENUM funcEnum, FUNC_TYPEDEF funcTypedef) {
|
||||
if(dynamic_cast<const TypeInterface*>(type) != nullptr)
|
||||
|
@ -173,6 +449,11 @@ namespace sirEdit::data
|
|||
return doBaseType(this, withoutFields, withFields, withFields, withFields, withoutFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the super type of a type
|
||||
* @param type the type to find it's super
|
||||
* @return the super type or nullptr
|
||||
*/
|
||||
inline const Type* getSuper(const Type& type) {
|
||||
auto isBase = []() -> const Type* { return nullptr; };
|
||||
auto isInterface = [&type]() -> const Type* { return dynamic_cast<const TypeInterface*>(&type)->getSuper(); };
|
||||
|
@ -182,7 +463,12 @@ namespace sirEdit::data
|
|||
return doBaseType(&type, isBase, isInterface, isClass, isEnum, isTypedef);
|
||||
}
|
||||
|
||||
static const std::vector<TypeInterface*> __getInterfacesEmpty;
|
||||
static const std::vector<TypeInterface*> __getInterfacesEmpty; /// local variable for no interfaces
|
||||
/**
|
||||
* Returns a refernce to a list of the interfaces.
|
||||
* @param type The type to find it's interfaces
|
||||
* @return a list with the interfaces
|
||||
*/
|
||||
inline const std::vector<TypeInterface*>& getInterfaces(const Type& type) {
|
||||
auto isBase = []() -> const std::vector<TypeInterface*>& { return __getInterfacesEmpty; };
|
||||
auto isInterface = [&type]() -> const std::vector<TypeInterface*>& { return dynamic_cast<const TypeInterface*>(&type)->getInterfaces(); };
|
||||
|
@ -190,7 +476,12 @@ namespace sirEdit::data
|
|||
return doBaseType(&type, isBase, isInterface, isClass, isBase, isBase);
|
||||
}
|
||||
|
||||
static const std::vector<Field> __getFieldsEmpty;
|
||||
static const std::vector<Field> __getFieldsEmpty; /// Empty list of fields
|
||||
/**
|
||||
* Returns a reference to a list of the fields.
|
||||
* @param type the source type to find it's fields
|
||||
* @return a list of fields
|
||||
*/
|
||||
inline const std::vector<Field>& getFields(const Type& type) {
|
||||
auto isBase = []() -> const std::vector<Field>& { return __getFieldsEmpty; };
|
||||
auto isInterface = [&type]() -> const std::vector<Field>& { return dynamic_cast<const TypeInterface*>(&type)->getFields(); };
|
||||
|
@ -199,6 +490,11 @@ namespace sirEdit::data
|
|||
return doBaseType(&type, isBase, isInterface, isClass, isEnum, isBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of all fields of a type. This means the parents too.
|
||||
* @param type the source type to search
|
||||
* @return list of all fields of the type
|
||||
*/
|
||||
inline std::unordered_set<const Field*> listAllFields(const Type& type) {
|
||||
// Add own fields
|
||||
std::unordered_set<const Field*> result;
|
||||
|
@ -223,32 +519,37 @@ namespace sirEdit::data
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The implementaiton of printing the field declaration.
|
||||
* It's hear, because else no access to the types is possible.
|
||||
* @return declaration of the field as string
|
||||
*/
|
||||
inline std::string Field::printType() const {
|
||||
// Type parse
|
||||
std::string result;
|
||||
std::string end; // End of the printing
|
||||
switch(this->__type.combination) {
|
||||
case FieldType::TYPE_COMBINATION::SINGLE_TYPE:
|
||||
case FieldType::TYPE_COMBINATION::SINGLE_TYPE: // Normal reference
|
||||
if(this->__type.types.size() != 1)
|
||||
throw; // That sould never happen!
|
||||
return this->__type.types[0]->getName();
|
||||
case FieldType::TYPE_COMBINATION::DYNAMIC_ARRAY:
|
||||
case FieldType::TYPE_COMBINATION::DYNAMIC_ARRAY: // A dynamic sized array
|
||||
if(this->__type.types.size() != 1)
|
||||
throw; // That sould never happen!
|
||||
return std::move(this->__type.types[0]->getName() + "[]");
|
||||
case FieldType::TYPE_COMBINATION::STATIC_ARRAY:
|
||||
case FieldType::TYPE_COMBINATION::STATIC_ARRAY: // A static sized array
|
||||
if(this->__type.types.size() != 1)
|
||||
throw; // That sould never happen!
|
||||
return std::move(this->__type.types[0]->getName() + "[" + std::to_string(this->__type.arraySize) + "]");
|
||||
case FieldType::TYPE_COMBINATION::LIST:
|
||||
case FieldType::TYPE_COMBINATION::LIST: // It's a list
|
||||
result = "list<";
|
||||
end = ">";
|
||||
break;
|
||||
case FieldType::TYPE_COMBINATION::SET:
|
||||
case FieldType::TYPE_COMBINATION::SET: // It's a set
|
||||
result = "set<";
|
||||
end = ">";
|
||||
break;
|
||||
case FieldType::TYPE_COMBINATION::MAP:
|
||||
case FieldType::TYPE_COMBINATION::MAP: // It's a map
|
||||
result = "map<";
|
||||
end = ">";
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue