Пример #1
0
    def generate(self):
        self.decl_includes = [
            "modules/protobuf/src/protobuf_utils.h",
            "modules/protobuf/src/protobuf_message.h",
        ]
        self.decl_forward_decls = [
            "OpScopeTPMessage",
            "OpProtobufField",
            "OpProtobufMessage",
        ]
        self.impl_includes = [
            "modules/protobuf/src/protobuf_utils.h",
            "modules/scope/src/scope_tp_message.h",
            "modules/scope/src/scope_default_message.h",
            "modules/scope/src/scope_manager.h",
            "modules/scope/src/generated/g_scope_manager.h",
        ]
        if "cpp_file" in self.service.options:
            cpp_file = self.service.options["cpp_file"].value
        else:
            cpp_file = utils.join_underscore(
                utils.split_camelcase(self.service.name))
        files = self.service.cpp.files()
        self.impl_includes.append(files["generatedServiceDeclaration"])
        self.impl_includes.append(files["serviceDeclaration"])

        commands = copy(self.sortedCommands())
        for command in commands:
            command.options["cpp_enum_name"] = commandEnumName(command.name)
        requests = [
            command for command in commands
            if issubclass(type(command), Request) and not is_deferred(command)
        ]
        events = [
            command for command in commands
            if issubclass(type(command), Event)
        ]
        async = [(command.toRequest(), command.toEvent())
                 for command in commands
                 if issubclass(type(command), Request) and is_deferred(command)
                 ]
        requests += [req[0] for req in async]
        events += [req[1] for req in async]

        self.service.version = self.getVersion()

        import hob.proto
        self.commands = commands
        self.requests = requests
        self.events = events
Пример #2
0
    def generate(self):
        self.decl_includes = ["modules/protobuf/src/protobuf_utils.h", "modules/protobuf/src/protobuf_message.h"]
        self.decl_forward_decls = ["OpScopeTPMessage", "OpProtobufField", "OpProtobufMessage"]
        self.impl_includes = [
            "modules/protobuf/src/protobuf_utils.h",
            "modules/scope/src/scope_tp_message.h",
            "modules/scope/src/scope_default_message.h",
            "modules/scope/src/scope_manager.h",
            "modules/scope/src/generated/g_scope_manager.h",
        ]
        if "cpp_file" in self.service.options:
            cpp_file = self.service.options["cpp_file"].value
        else:
            cpp_file = utils.join_underscore(utils.split_camelcase(self.service.name))
        files = self.service.cpp.files()
        self.impl_includes.append(files["generatedServiceDeclaration"])
        self.impl_includes.append(files["serviceDeclaration"])

        commands = copy(self.sortedCommands())
        for command in commands:
            command.options["cpp_enum_name"] = commandEnumName(command.name)
        requests = [command for command in commands if issubclass(type(command), Request) and not is_deferred(command)]
        events = [command for command in commands if issubclass(type(command), Event)]
        async = [
            (command.toRequest(), command.toEvent())
            for command in commands
            if issubclass(type(command), Request) and is_deferred(command)
        ]
        requests += [req[0] for req in async]
        events += [req[1] for req in async]

        self.service.version = self.getVersion()

        import hob.proto

        self.commands = commands
        self.requests = requests
        self.events = events
Пример #3
0
    def renderServiceImplementation(self, service, requests, events, generate_instance):
        class_name = service.options["cpp_class"].value + "_SI"

        class_name_base = service.iparent.cpp.cppMessageSet().symbol()
        if class_name_base.find("_MessageSet"):
            cpp_descriptor_class_name = class_name_base.replace("_MessageSet", "_Descriptors")
        else:
            cpp_descriptor_class_name = class_name_base + "_Descriptors"

        text = "\n"

        text += (
            "\n"
            + render(
                """
            // Service implementation

            %(class)s::%(class)s(const uni_char* id, OpScopeServiceManager *manager, ControlType control)
            		: OpScopeService(id == NULL ? UNI_L(%(protocol_name_quoted)s) : id, manager, control)
            {
            }

            /*virtual*/
            %(class)s::~%(class)s()
            {
            }
            """,
                {
                    "class": class_name,
                    "protocol_name_quoted": strQuote(utils.join_dashed(utils.split_camelcase(service.name))),
                    "serviceVarName": self.varName(service.name),
                },
            )
            + "\n"
        )
        if not generate_instance:
            return text

        text += (
            "\n"
            + render(
                """
            /*virtual*/
            int
            %(class)s::GetCommandCount() const
            {
            	return Command_Count;
            }

            /*virtual*/
            OpScopeService::CommandRange
            %(class)s::GetCommands() const
            {
            	Descriptors *descriptors = g_scope_manager->GetDescriptorSet().%(serviceVarName)s;
            	OP_ASSERT(descriptors);
            	return CommandRange(descriptors ? descriptors->command_list : NULL, Command_Count);
            }

            /*virtual*/
            OP_STATUS
            %(class)s::DoReceive( OpScopeClient *client, const OpScopeTPMessage &msg )
            {
            	// Check for invalid request data
            	if (msg.Status() != OpScopeTPMessage::OK) // All calls must have status OK
            		return SetCommandError(OpScopeTPMessage::BadRequest, GetInvalidStatusFieldText());
            	if (msg.ServiceName().Compare(GetName()) != 0) // Make sure the service name matches the one in the message
            		return SetCommandError(OpScopeTPMessage::InternalError, GetIncorrectServiceText());
            """,
                {
                    "class": class_name,
                    "protocol_name_quoted": strQuote(utils.join_dashed(utils.split_camelcase(service.name))),
                    "serviceVarName": self.varName(service.name),
                },
            )
            + "\n\n"
        )

        if requests:
            text += (
                self.indent(
                    render(
                        """
                if (msg.CommandID() == %(requestID)s) // %(requestName)s
                {
                """,
                        {"requestID": enumName(requests[0]), "requestName": requests[0].name},
                    )
                )
                + self.renderRequestDecode(requests[0])
                + "	}\n"
            )

            for command in requests[1:]:
                text += (
                    self.indent(
                        render(
                            """
                    else if (msg.CommandID() == %(requestID)s) // %(requestName)s
                    {
                    """,
                            {"requestID": enumName(command), "requestName": command.name},
                        )
                    )
                    + self.renderRequestDecode(command)
                    + "	}\n"
                )

            text += (
                self.indent(
                    render(
                        """
                else
                {
                	SetCommandError(OpScopeTPMessage::CommandNotFound, GetCommandNotFoundText());
                	return OpStatus::ERR;
                }
                """
                    )
                )
                + "\n"
            )

        text += "	return OpStatus::OK;\n}\n\n"

        messages = [msg for msg in service.messages() if msg != defaultMessage]
        enums = self.enums()

        text += (
            render(
                """
            /*virtual*/
            const OpProtobufMessage *
            %(class)s::GetMessage(unsigned message_id) const
            {
            	Descriptors *descriptors = GetDescriptors();
            	if (!descriptors)
            		return NULL;
            	return descriptors->Get(message_id);
            }

            %(class)s::Descriptors *
            %(class)s::GetDescriptors() const
            {
            	Descriptors *d = g_scope_manager->GetDescriptorSet().%(serviceVarName)s;
            	OP_ASSERT(d);
            	return d;
            }

            /*virtual*/
            unsigned
            %(class)s::GetMessageCount() const
            {
            	return %(descriptorClass)s::_gen_Message_Count;
            }

            /*virtual*/
            OpScopeService::MessageIDRange
            %(class)s::GetMessageIDs() const
            {
            	unsigned start = %(descriptorClass)s::_gen_Message_Count > 0 ? 1 : 0;
            	return MessageIDRange(start, start + %(descriptorClass)s::_gen_Message_Count);
            }

            /*virtual*/
            OpScopeService::MessageRange
            %(class)s::GetMessages() const
            {
            	unsigned start = %(descriptorClass)s::_gen_Message_Count > 0 ? 1 : 0;
            	return MessageRange(this, start, start + %(descriptorClass)s::_gen_Message_Count);
            }
            """,
                {
                    "class": class_name,
                    "serviceVarName": self.varName(service.name),
                    "descriptorClass": cpp_descriptor_class_name,
                },
            )
            + "\n\n"
        )

        text += (
            render(
                """
            /* virtual */
            const char *
            %(class)s::GetVersionString() const
            {
            	return "%(version)s";
            }

            /* virtual */
            int
            %(class)s::GetMajorVersion() const
            {
            	return %(versionMajor)s;
            }

            /* virtual */
            int
            %(class)s::GetMinorVersion() const
            {
            	return %(versionMinor)s;
            }

            /* virtual */
            const char *
            %(class)s::GetPatchVersion() const
            {
            	return "%(versionPatch)s";
            }
            """,
                {
                    "class": class_name,
                    "version": service.options["version"].value,
                    "versionMajor": service.version[0],
                    "versionMinor": service.version[1],
                    "versionPatch": service.version[2],
                },
            )
            + "\n"
        )

        if events:
            for event in events:
                params = []
                if event.message.isNonEmpty():
                    params.append("const %s &msg" % message_className(event.message))
                if requiresAsyncResponse(event):
                    params.append("unsigned int tag")

                text += (
                    "\n"
                    + render(
                        """
                    OP_STATUS
                    %(class)s::%(eventMethod)s(%(eventParams)s) // %(eventName)s
                    {
                    """,
                        {
                            "class": class_name,
                            "eventMethod": event_functionName(event),
                            "eventParams": ", ".join(params),
                            "eventName": event.name,
                        },
                    )
                    + "\n"
                )

                if event.message.isNonEmpty():
                    text += (
                        "	OpProtobufInstanceProxy proxy(%(messageClass)s::GetMessageDescriptor(GetDescriptors()), const_cast<%(messageClass)s *>(&msg));\n"
                        % {"messageClass": message_className(event.message)}
                    )
                else:
                    text += "	OpProtobufInstanceProxy proxy(OpScopeDefaultMessage::GetMessageDescriptor(), &g_scope_manager->default_message_instance);\n"

                text += "	if (proxy.GetProtoMessage() == NULL)\n" + "		return OpStatus::ERR_NO_MEMORY;\n"

                if requiresAsyncResponse(event):
                    text += "	return SendAsyncResponse(tag, proxy, %(eventEnum)s);\n" % {"eventEnum": enumName(event)}
                else:
                    text += "	return SendEvent(proxy, %(eventEnum)s);\n" % {"eventEnum": enumName(event)}

                text += "}\n\n"

        if enums:
            text += (
                render(
                    """
                // Enum introspection: BEGIN

                /*virtual*/
                OpScopeService::EnumIDRange
                %(class)s::GetEnumIDs() const
                {
                	Descriptors *descriptors = GetDescriptors();
                	return EnumIDRange(descriptors ? descriptors->enum_id_list : NULL, %(descriptorClass)s::_gen_Enum_Count);
                }

                /*virtual*/
                unsigned
                %(class)s::GetEnumCount() const
                {
                	return %(descriptorClass)s::_gen_Enum_Count;
                }

                /*virtual*/
                BOOL
                %(class)s::HasEnum(unsigned enum_id) const
                {
                	switch (enum_id)
                	{
                """,
                    {"class": class_name, "descriptorClass": cpp_descriptor_class_name},
                )
                + "\n"
            )
            for enum in enums:
                text += "		case %(descriptorClass)s::_gen_EnumID_%(enumPath)s:\n" % {
                    "enumPath": "_".join(enum.path()),
                    "descriptorClass": cpp_descriptor_class_name,
                }

            text += "			return TRUE;\n" "	}\n" "	return FALSE;\n" "}\n" "\n"
            text += (
                render(
                    """
                /*virtual*/
                OP_STATUS
                %(class)s::GetEnum(unsigned enum_id, const uni_char *&name, unsigned &value_count) const
                {
                	switch (enum_id)
                	{
                """,
                    {"class": class_name},
                )
                + "\n"
            )

            for enum in enums:
                text += (
                    self.indent(
                        render(
                            """
                    // %(messageClassPath)s
                    case %(descriptorClass)s::_gen_EnumID_%(enumPath)s:
                    	name = UNI_L(%(enum)s);
                    	value_count = %(descriptorClass)s::_gen_EnumValueCount_%(enumPath)s;
                    	return OpStatus::OK;
                    """,
                            {
                                "messageClassPath": messageClassPath(enum)[1],
                                "enumPath": "_".join(enum.path()),
                                "enum": strQuote(enum.name),
                                "descriptorClass": cpp_descriptor_class_name,
                            },
                        ),
                        2,
                    )
                    + "\n"
                )

            text += "	}\n" "	return OpStatus::ERR_NO_SUCH_RESOURCE;\n" "}\n" "\n"
            text += (
                render(
                    """
                /*virtual*/
                OP_STATUS
                %(class)s::GetEnumValue(unsigned enum_id, unsigned idx, const uni_char *&value_name, unsigned &value_number) const
                {
                	switch (enum_id)
                	{
                """,
                    {"class": class_name},
                )
                + "\n"
            )

            for enum in enums:
                text += (
                    self.indent(
                        render(
                            """
                    // %(messageClassPath)s
                    case %(descriptorClass)s::_gen_EnumID_%(enumPath)s:
                    {
                    """,
                            {
                                "messageClassPath": messageClassPath(enum)[1],
                                "enumPath": "_".join(enum.path()),
                                "descriptorClass": cpp_descriptor_class_name,
                            },
                        ),
                        2,
                    )
                    + "\n"
                )
                if enum.values:
                    text += (
                        self.indent(
                            render(
                                """
                        if (idx > %(descriptorClass)s::_gen_EnumValueCount_%(enumPath)s)
                        	return OpStatus::ERR_OUT_OF_RANGE;
                        // Values for %(messageClassPath)s
                        const unsigned enum_numbers[] = {
                        	  %(enumValue)s
                        """,
                                {
                                    "enumPath": "_".join(enum.path()),
                                    "messageClassPath": messageClassPath(enum)[1],
                                    "enumValue": enum.values[0].value,
                                    "descriptorClass": cpp_descriptor_class_name,
                                },
                            ),
                            3,
                        )
                        + "\n"
                    )
                    for value in enum.values[1:]:
                        text += "				, %s\n" % value.value

                    text += (
                        self.indent(
                            render(
                                """
                        }; // ARRAY OK 2010-04-14 jborsodi
                        const unsigned name_offsets[] = {
                        	  0
                        """
                            ),
                            3,
                        )
                        + "\n"
                    )
                    for idx in range(1, len(enum.values)):
                        text += "				, %(offset)s\n" % {
                            "offset": sum([len(value.name) + 1 for value in enum.values[:idx]])
                        }

                    text += (
                        self.indent(
                            render(
                                """
                        }; // ARRAY OK 2010-04-14 jborsodi
                        const uni_char *names = UNI_L( %(enumStrings)s );
                        OP_ASSERT(idx < sizeof(name_offsets));
                        OP_ASSERT(idx < sizeof(enum_numbers));
                        value_name = names + name_offsets[idx];
                        value_number = enum_numbers[idx];
                        return OpStatus::OK;
                        """,
                                {
                                    "enumStrings": strQuote(
                                        "".join(
                                            [value.name + "\0" for value in enum.values[:-1]] + [enum.values[-1].name]
                                        )
                                    )
                                },
                            ),
                            3,
                        )
                        + "\n"
                    )
                else:
                    text += "			return OpStatus::ERR; // No values so return error\n"

                text += "		}\n\n"

            text += "	}\n" "	return OpStatus::ERR_NO_SUCH_RESOURCE;\n" "}\n" "// Enum introspection: END\n"
        return text
Пример #4
0
    def renderDeclaration(self, services):
        text = ""

        text += "\n" + render("""

            // Includes

            #include "modules/scope/src/scope_service.h"

            // Includes for shared variables

            """) + "\n\n"

        for include in self.manager_options.includes:
            text += """#include "%s"\n""" % include

        text += "\n" + render("""

            // Forward declarations

            """) + "\n\n"

        for service in services:
            if "cpp_instance" not in service.options or service.options["cpp_instance"].value == "true":
                if "cpp_feature" in service.options:
                    text += "#ifdef %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

                text += "class %(class)s;\n" % {"class": service.options["cpp_class"].value}

                if "cpp_feature" in service.options:
                    text += "#endif // %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

        text += "\n" + render("""

            // Interface definitions

            """) + "\n\n"

        for service in services:
            if "cpp_feature" in service.options:
                text += "#ifdef %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

            prefix = "g_scope_"
            basename = utils.join_underscore(utils.split_camelcase(service.name))
            if "cpp_file" in service.options:
                basename = service.options["cpp_file"].value
                prefix = "g_"
            text += """# include "%(cpp_gen_base)s/%(file)s_interface.h"\n""" % {
                "file": prefix + basename,
                "cpp_gen_base": service.options["cpp_gen_base"].value,
                }

            if "cpp_feature" in service.options:
                text += "#endif // %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

        text += "\n" + render("""

class OpScopeDescriptorSet;
class OpScopeManager;
class OpScopeServiceManager;

/**
 * This is a generated class which defines all services which are use in scope.
 * It provides methods for registering meta-services as well as creating all
 * service objects.
 * In addition it keeps an instance of the OpScopeDescriptorSet class, this is
 * used to provide descriptor objects for messages in each service.
 *
 * This class is meant to be sub-classed into a real scope manager. The sub-class
 * must call RegisterMetaService() to register meta-services, and then call
 * CreateServices() and CreateServiceDescriptors() at a convenient time to
 * initialize the class properly.
 *
 * @note This class is generated.
 */
class OpScopeServiceFactory
{
public:
	/**
	 * Initializes the generated manager with all service pointers set to NULL.
	 */
	OpScopeServiceFactory();
	/**
	 * Deletes all active services and the descriptor set.
	 */
	virtual ~OpScopeServiceFactory();

	/**
	 * Get a reference to the descriptor set. Can only be used
	 * after a successful call to CreateServiceDescriptors.
	 */
	OpScopeDescriptorSet &GetDescriptorSet();

	/**
	 * Add a new meta-service named @a name. Meta-services are services
	 * which have no functionality, no version and cannot be introspected.
	 *
	 * The actual service will be created when CreateServices() is called
	 * by a sub-class. Adding a meta-service after that point will have no
	 * effect.
	 *
	 * If the meta-service has already been registered it will return OpStatus::ERR.
	 *
	 * @param name The name of the meta-service.
	 * @return OpStatus::OK, OpStatus::ERR or OpStatus::ERR_NO_MEMORY
	 *
	 */
	OP_STATUS RegisterMetaService(const uni_char *name);
	/**
	 * @see RegisterMetaService(const uni_char *name);
	 */
	OP_STATUS RegisterMetaService(const OpString &name) { return RegisterMetaService(name.CStr()); }

protected:

	/**
	 * Creates all services.
	 *
	 * @param manager The manager that owns the services.
	 * @return OpStatus::OK on success, OpStatus::ERR_NO_MEMORY otherwise.
	 */
	OP_STATUS CreateServices(OpScopeServiceManager *manager);

	/**
	 * Deletes all services. No more events will be accepted from Core
	 * after this method is called, even events triggered by service
	 * destruction.
	 */
	void DeleteServices();

	/**
	 * Create service descriptions.
	 *
	 * @return OpStatus::OK on success, OpStatus::ERR_NO_MEMORY otherwise.
	 */
	 OP_STATUS CreateServiceDescriptors();

public:

	OpScopeDescriptorSet *descriptors;

	// Services:

""") + "\n\n"

        for service in services:
            if "cpp_instance" not in service.options or service.options["cpp_instance"].value == "true":
                if "cpp_feature" in service.options:
                    text += "#ifdef %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

                text += "	%(class)s *%(name)s;\n" % {
                    "class": service.options["cpp_class"].value,
                    "name": self.memberName(service.name),
                    }

                if "cpp_feature" in service.options:
                    text += "#endif // %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

        text += "\n" + render("""

            private:
            	/**
            	 * Defines the name of a meta-service and manages the service object.
            	 * The meta-service is first initailized with a name and later on in the
            	 * CreateServices() a service object is created and placed in service.
            	 * When the MetaService is destructed it will delete the service object.
            	 */
            	struct MetaService : public ListElement<MetaService>
            	{
            		MetaService() : service(NULL) {}
            		~MetaService() { OP_DELETE(service); }
            		OpString name;
            		OpScopeService *service;
            	};
            	/**
            	 * List of meta-services currently registered.
            	 */
            	List<MetaService> meta_services;

            	// NOTE: These two methods are meant to be manually created outside of these classes
            	//       See modules/scope/src/scope_manager.cpp for the implementation
            	/**
            	 * Initializes any shared member variables, called before the services are created.
            	 */
            	OP_STATUS InitializeShared();
            	/**
            	 * Cleans up the shared member variables, called after the services has been deleted.
            	 */
            	void CleanupShared();

            	// Shared member variables. See cpp.conf for more information.
            """) + "\n"

        for field in self.manager_options.shared_fields:
            text += "	%s;\n" % field

        text += render("""
            }; // OpScopeServiceFactory

            /**
             * Contains the descriptors of all services in use by scope.
             *
             * @note This class is generated.
             */
            class OpScopeDescriptorSet
            {
            public:
            	OpScopeDescriptorSet();
            	~OpScopeDescriptorSet();

            	OP_STATUS Construct();

            private:
            	// Not really used for anything, except to prevent errors on certain
            	// compile configurations.
            	int dummy;

            public:
            """) + "\n"

        for service in services:
            if "cpp_feature" in service.options:
                text += "#ifdef %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

            text += "	%(class)s_SI::Descriptors *%(name)s;\n" % {
                "class": service.options["cpp_class"].value,
                "name": self.varName(service.name),
                }

            if "cpp_feature" in service.options:
                text += "#endif // %(feature)s\n" % {"feature": service.options["cpp_feature"].value}

        text += "\n" + render("""
            }; // OpScopeDescriptorSet
            """) + "\n"

        return text
Пример #5
0
    def renderDeclaration(self, services):
        text = ""

        text += "\n" + render("""

            // Includes

            #include "modules/scope/src/scope_service.h"

            // Includes for shared variables

            """) + "\n\n"

        for include in self.manager_options.includes:
            text += """#include "%s"\n""" % include

        text += "\n" + render("""

            // Forward declarations

            """) + "\n\n"

        for service in services:
            if "cpp_instance" not in service.options or service.options[
                    "cpp_instance"].value == "true":
                if "cpp_feature" in service.options:
                    text += "#ifdef %(feature)s\n" % {
                        "feature": service.options["cpp_feature"].value
                    }

                text += "class %(class)s;\n" % {
                    "class": service.options["cpp_class"].value
                }

                if "cpp_feature" in service.options:
                    text += "#endif // %(feature)s\n" % {
                        "feature": service.options["cpp_feature"].value
                    }

        text += "\n" + render("""

            // Interface definitions

            """) + "\n\n"

        for service in services:
            if "cpp_feature" in service.options:
                text += "#ifdef %(feature)s\n" % {
                    "feature": service.options["cpp_feature"].value
                }

            prefix = "g_scope_"
            basename = utils.join_underscore(
                utils.split_camelcase(service.name))
            if "cpp_file" in service.options:
                basename = service.options["cpp_file"].value
                prefix = "g_"
            text += """# include "%(cpp_gen_base)s/%(file)s_interface.h"\n""" % {
                "file": prefix + basename,
                "cpp_gen_base": service.options["cpp_gen_base"].value,
            }

            if "cpp_feature" in service.options:
                text += "#endif // %(feature)s\n" % {
                    "feature": service.options["cpp_feature"].value
                }

        text += "\n" + render("""

class OpScopeDescriptorSet;
class OpScopeManager;
class OpScopeServiceManager;

/**
 * This is a generated class which defines all services which are use in scope.
 * It provides methods for registering meta-services as well as creating all
 * service objects.
 * In addition it keeps an instance of the OpScopeDescriptorSet class, this is
 * used to provide descriptor objects for messages in each service.
 *
 * This class is meant to be sub-classed into a real scope manager. The sub-class
 * must call RegisterMetaService() to register meta-services, and then call
 * CreateServices() and CreateServiceDescriptors() at a convenient time to
 * initialize the class properly.
 *
 * @note This class is generated.
 */
class OpScopeServiceFactory
{
public:
	/**
	 * Initializes the generated manager with all service pointers set to NULL.
	 */
	OpScopeServiceFactory();
	/**
	 * Deletes all active services and the descriptor set.
	 */
	virtual ~OpScopeServiceFactory();

	/**
	 * Get a reference to the descriptor set. Can only be used
	 * after a successful call to CreateServiceDescriptors.
	 */
	OpScopeDescriptorSet &GetDescriptorSet();

	/**
	 * Add a new meta-service named @a name. Meta-services are services
	 * which have no functionality, no version and cannot be introspected.
	 *
	 * The actual service will be created when CreateServices() is called
	 * by a sub-class. Adding a meta-service after that point will have no
	 * effect.
	 *
	 * If the meta-service has already been registered it will return OpStatus::ERR.
	 *
	 * @param name The name of the meta-service.
	 * @return OpStatus::OK, OpStatus::ERR or OpStatus::ERR_NO_MEMORY
	 *
	 */
	OP_STATUS RegisterMetaService(const uni_char *name);
	/**
	 * @see RegisterMetaService(const uni_char *name);
	 */
	OP_STATUS RegisterMetaService(const OpString &name) { return RegisterMetaService(name.CStr()); }

protected:

	/**
	 * Creates all services.
	 *
	 * @param manager The manager that owns the services.
	 * @return OpStatus::OK on success, OpStatus::ERR_NO_MEMORY otherwise.
	 */
	OP_STATUS CreateServices(OpScopeServiceManager *manager);

	/**
	 * Deletes all services. No more events will be accepted from Core
	 * after this method is called, even events triggered by service
	 * destruction.
	 */
	void DeleteServices();

	/**
	 * Create service descriptions.
	 *
	 * @return OpStatus::OK on success, OpStatus::ERR_NO_MEMORY otherwise.
	 */
	 OP_STATUS CreateServiceDescriptors();

public:

	OpScopeDescriptorSet *descriptors;

	// Services:

""") + "\n\n"

        for service in services:
            if "cpp_instance" not in service.options or service.options[
                    "cpp_instance"].value == "true":
                if "cpp_feature" in service.options:
                    text += "#ifdef %(feature)s\n" % {
                        "feature": service.options["cpp_feature"].value
                    }

                text += "	%(class)s *%(name)s;\n" % {
                    "class": service.options["cpp_class"].value,
                    "name": self.memberName(service.name),
                }

                if "cpp_feature" in service.options:
                    text += "#endif // %(feature)s\n" % {
                        "feature": service.options["cpp_feature"].value
                    }

        text += "\n" + render("""

            private:
            	/**
            	 * Defines the name of a meta-service and manages the service object.
            	 * The meta-service is first initailized with a name and later on in the
            	 * CreateServices() a service object is created and placed in service.
            	 * When the MetaService is destructed it will delete the service object.
            	 */
            	struct MetaService : public ListElement<MetaService>
            	{
            		MetaService() : service(NULL) {}
            		~MetaService() { OP_DELETE(service); }
            		OpString name;
            		OpScopeService *service;
            	};
            	/**
            	 * List of meta-services currently registered.
            	 */
            	List<MetaService> meta_services;

            	// NOTE: These two methods are meant to be manually created outside of these classes
            	//       See modules/scope/src/scope_manager.cpp for the implementation
            	/**
            	 * Initializes any shared member variables, called before the services are created.
            	 */
            	OP_STATUS InitializeShared();
            	/**
            	 * Cleans up the shared member variables, called after the services has been deleted.
            	 */
            	void CleanupShared();

            	// Shared member variables. See cpp.conf for more information.
            """) + "\n"

        for field in self.manager_options.shared_fields:
            text += "	%s;\n" % field

        text += render("""
            }; // OpScopeServiceFactory

            /**
             * Contains the descriptors of all services in use by scope.
             *
             * @note This class is generated.
             */
            class OpScopeDescriptorSet
            {
            public:
            	OpScopeDescriptorSet();
            	~OpScopeDescriptorSet();

            	OP_STATUS Construct();

            private:
            	// Not really used for anything, except to prevent errors on certain
            	// compile configurations.
            	int dummy;

            public:
            """) + "\n"

        for service in services:
            if "cpp_feature" in service.options:
                text += "#ifdef %(feature)s\n" % {
                    "feature": service.options["cpp_feature"].value
                }

            text += "	%(class)s_SI::Descriptors *%(name)s;\n" % {
                "class": service.options["cpp_class"].value,
                "name": self.varName(service.name),
            }

            if "cpp_feature" in service.options:
                text += "#endif // %(feature)s\n" % {
                    "feature": service.options["cpp_feature"].value
                }

        text += "\n" + render("""
            }; // OpScopeDescriptorSet
            """) + "\n"

        return text
Пример #6
0
    def renderServiceImplementation(self, service, requests, events,
                                    generate_instance):
        class_name = service.options["cpp_class"].value + "_SI"

        class_name_base = service.iparent.cpp.cppMessageSet().symbol()
        if class_name_base.find("_MessageSet"):
            cpp_descriptor_class_name = class_name_base.replace(
                "_MessageSet", "_Descriptors")
        else:
            cpp_descriptor_class_name = class_name_base + "_Descriptors"

        text = "\n"

        text += "\n" + render(
            """
            // Service implementation

            %(class)s::%(class)s(const uni_char* id, OpScopeServiceManager *manager, ControlType control)
            		: OpScopeService(id == NULL ? UNI_L(%(protocol_name_quoted)s) : id, manager, control)
            {
            }

            /*virtual*/
            %(class)s::~%(class)s()
            {
            }
            """, {
                "class":
                class_name,
                "protocol_name_quoted":
                strQuote(utils.join_dashed(utils.split_camelcase(
                    service.name))),
                "serviceVarName":
                self.varName(service.name),
            }) + "\n"
        if not generate_instance:
            return text

        text += "\n" + render(
            """
            /*virtual*/
            int
            %(class)s::GetCommandCount() const
            {
            	return Command_Count;
            }

            /*virtual*/
            OpScopeService::CommandRange
            %(class)s::GetCommands() const
            {
            	Descriptors *descriptors = g_scope_manager->GetDescriptorSet().%(serviceVarName)s;
            	OP_ASSERT(descriptors);
            	return CommandRange(descriptors ? descriptors->command_list : NULL, Command_Count);
            }

            /*virtual*/
            OP_STATUS
            %(class)s::DoReceive( OpScopeClient *client, const OpScopeTPMessage &msg )
            {
            	// Check for invalid request data
            	if (msg.Status() != OpScopeTPMessage::OK) // All calls must have status OK
            		return SetCommandError(OpScopeTPMessage::BadRequest, GetInvalidStatusFieldText());
            	if (msg.ServiceName().Compare(GetName()) != 0) // Make sure the service name matches the one in the message
            		return SetCommandError(OpScopeTPMessage::InternalError, GetIncorrectServiceText());
            """, {
                "class":
                class_name,
                "protocol_name_quoted":
                strQuote(utils.join_dashed(utils.split_camelcase(
                    service.name))),
                "serviceVarName":
                self.varName(service.name),
            }) + "\n\n"

        if requests:
            text += self.indent(
                render(
                    """
                if (msg.CommandID() == %(requestID)s) // %(requestName)s
                {
                """, {
                        "requestID": enumName(requests[0]),
                        "requestName": requests[0].name,
                    })) + self.renderRequestDecode(requests[0]) + "	}\n"

            for command in requests[1:]:
                text += self.indent(
                    render(
                        """
                    else if (msg.CommandID() == %(requestID)s) // %(requestName)s
                    {
                    """, {
                            "requestID": enumName(command),
                            "requestName": command.name,
                        })) + self.renderRequestDecode(command) + "	}\n"

            text += self.indent(
                render("""
                else
                {
                	SetCommandError(OpScopeTPMessage::CommandNotFound, GetCommandNotFoundText());
                	return OpStatus::ERR;
                }
                """)) + "\n"

        text += "	return OpStatus::OK;\n}\n\n"

        messages = [msg for msg in service.messages() if msg != defaultMessage]
        enums = self.enums()

        text += render(
            """
            /*virtual*/
            const OpProtobufMessage *
            %(class)s::GetMessage(unsigned message_id) const
            {
            	Descriptors *descriptors = GetDescriptors();
            	if (!descriptors)
            		return NULL;
            	return descriptors->Get(message_id);
            }

            %(class)s::Descriptors *
            %(class)s::GetDescriptors() const
            {
            	Descriptors *d = g_scope_manager->GetDescriptorSet().%(serviceVarName)s;
            	OP_ASSERT(d);
            	return d;
            }

            /*virtual*/
            unsigned
            %(class)s::GetMessageCount() const
            {
            	return %(descriptorClass)s::_gen_Message_Count;
            }

            /*virtual*/
            OpScopeService::MessageIDRange
            %(class)s::GetMessageIDs() const
            {
            	unsigned start = %(descriptorClass)s::_gen_Message_Count > 0 ? 1 : 0;
            	return MessageIDRange(start, start + %(descriptorClass)s::_gen_Message_Count);
            }

            /*virtual*/
            OpScopeService::MessageRange
            %(class)s::GetMessages() const
            {
            	unsigned start = %(descriptorClass)s::_gen_Message_Count > 0 ? 1 : 0;
            	return MessageRange(this, start, start + %(descriptorClass)s::_gen_Message_Count);
            }
            """, {
                "class": class_name,
                "serviceVarName": self.varName(service.name),
                "descriptorClass": cpp_descriptor_class_name,
            }) + "\n\n"

        text += render(
            """
            /* virtual */
            const char *
            %(class)s::GetVersionString() const
            {
            	return "%(version)s";
            }

            /* virtual */
            int
            %(class)s::GetMajorVersion() const
            {
            	return %(versionMajor)s;
            }

            /* virtual */
            int
            %(class)s::GetMinorVersion() const
            {
            	return %(versionMinor)s;
            }

            /* virtual */
            const char *
            %(class)s::GetPatchVersion() const
            {
            	return "%(versionPatch)s";
            }
            """, {
                "class": class_name,
                "version": service.options["version"].value,
                "versionMajor": service.version[0],
                "versionMinor": service.version[1],
                "versionPatch": service.version[2],
            }) + "\n"

        if events:
            for event in events:
                params = []
                if event.message.isNonEmpty():
                    params.append("const %s &msg" %
                                  message_className(event.message))
                if requiresAsyncResponse(event):
                    params.append("unsigned int tag")

                text += "\n" + render(
                    """
                    OP_STATUS
                    %(class)s::%(eventMethod)s(%(eventParams)s) // %(eventName)s
                    {
                    """, {
                        "class": class_name,
                        "eventMethod": event_functionName(event),
                        "eventParams": ", ".join(params),
                        "eventName": event.name,
                    }) + "\n"

                if event.message.isNonEmpty():
                    text += "	OpProtobufInstanceProxy proxy(%(messageClass)s::GetMessageDescriptor(GetDescriptors()), const_cast<%(messageClass)s *>(&msg));\n" % {
                        "messageClass": message_className(event.message),
                    }
                else:
                    text += "	OpProtobufInstanceProxy proxy(OpScopeDefaultMessage::GetMessageDescriptor(), &g_scope_manager->default_message_instance);\n"

                text += ("	if (proxy.GetProtoMessage() == NULL)\n" +
                         "		return OpStatus::ERR_NO_MEMORY;\n")

                if requiresAsyncResponse(event):
                    text += "	return SendAsyncResponse(tag, proxy, %(eventEnum)s);\n" % {
                        "eventEnum": enumName(event)
                    }
                else:
                    text += "	return SendEvent(proxy, %(eventEnum)s);\n" % {
                        "eventEnum": enumName(event)
                    }

                text += "}\n\n"

        if enums:
            text += render(
                """
                // Enum introspection: BEGIN

                /*virtual*/
                OpScopeService::EnumIDRange
                %(class)s::GetEnumIDs() const
                {
                	Descriptors *descriptors = GetDescriptors();
                	return EnumIDRange(descriptors ? descriptors->enum_id_list : NULL, %(descriptorClass)s::_gen_Enum_Count);
                }

                /*virtual*/
                unsigned
                %(class)s::GetEnumCount() const
                {
                	return %(descriptorClass)s::_gen_Enum_Count;
                }

                /*virtual*/
                BOOL
                %(class)s::HasEnum(unsigned enum_id) const
                {
                	switch (enum_id)
                	{
                """, {
                    "class": class_name,
                    "descriptorClass": cpp_descriptor_class_name,
                }) + "\n"
            for enum in enums:
                text += "		case %(descriptorClass)s::_gen_EnumID_%(enumPath)s:\n" % {
                    "enumPath": "_".join(enum.path()),
                    "descriptorClass": cpp_descriptor_class_name,
                }

            text += ("			return TRUE;\n" "	}\n" "	return FALSE;\n" "}\n" "\n")
            text += render(
                """
                /*virtual*/
                OP_STATUS
                %(class)s::GetEnum(unsigned enum_id, const uni_char *&name, unsigned &value_count) const
                {
                	switch (enum_id)
                	{
                """, {
                    "class": class_name,
                }) + "\n"

            for enum in enums:
                text += self.indent(
                    render(
                        """
                    // %(messageClassPath)s
                    case %(descriptorClass)s::_gen_EnumID_%(enumPath)s:
                    	name = UNI_L(%(enum)s);
                    	value_count = %(descriptorClass)s::_gen_EnumValueCount_%(enumPath)s;
                    	return OpStatus::OK;
                    """, {
                            "messageClassPath": messageClassPath(enum)[1],
                            "enumPath": "_".join(enum.path()),
                            "enum": strQuote(enum.name),
                            "descriptorClass": cpp_descriptor_class_name,
                        }), 2) + "\n"

            text += ("	}\n"
                     "	return OpStatus::ERR_NO_SUCH_RESOURCE;\n"
                     "}\n"
                     "\n")
            text += render(
                """
                /*virtual*/
                OP_STATUS
                %(class)s::GetEnumValue(unsigned enum_id, unsigned idx, const uni_char *&value_name, unsigned &value_number) const
                {
                	switch (enum_id)
                	{
                """, {
                    "class": class_name,
                }) + "\n"

            for enum in enums:
                text += self.indent(
                    render(
                        """
                    // %(messageClassPath)s
                    case %(descriptorClass)s::_gen_EnumID_%(enumPath)s:
                    {
                    """, {
                            "messageClassPath": messageClassPath(enum)[1],
                            "enumPath": "_".join(enum.path()),
                            "descriptorClass": cpp_descriptor_class_name,
                        }), 2) + "\n"
                if enum.values:
                    text += self.indent(
                        render(
                            """
                        if (idx > %(descriptorClass)s::_gen_EnumValueCount_%(enumPath)s)
                        	return OpStatus::ERR_OUT_OF_RANGE;
                        // Values for %(messageClassPath)s
                        const unsigned enum_numbers[] = {
                        	  %(enumValue)s
                        """, {
                                "enumPath": "_".join(enum.path()),
                                "messageClassPath": messageClassPath(enum)[1],
                                "enumValue": enum.values[0].value,
                                "descriptorClass": cpp_descriptor_class_name,
                            }), 3) + "\n"
                    for value in enum.values[1:]:
                        text += "				, %s\n" % value.value

                    text += self.indent(
                        render("""
                        }; // ARRAY OK 2010-04-14 jborsodi
                        const unsigned name_offsets[] = {
                        	  0
                        """), 3) + "\n"
                    for idx in range(1, len(enum.values)):
                        text += "				, %(offset)s\n" % {
                            "offset":
                            sum([
                                len(value.name) + 1
                                for value in enum.values[:idx]
                            ])
                        }

                    text += self.indent(
                        render(
                            """
                        }; // ARRAY OK 2010-04-14 jborsodi
                        const uni_char *names = UNI_L( %(enumStrings)s );
                        OP_ASSERT(idx < sizeof(name_offsets));
                        OP_ASSERT(idx < sizeof(enum_numbers));
                        value_name = names + name_offsets[idx];
                        value_number = enum_numbers[idx];
                        return OpStatus::OK;
                        """, {
                                "enumStrings":
                                strQuote("".join([
                                    value.name + "\0"
                                    for value in enum.values[:-1]
                                ] + [enum.values[-1].name]))
                            }), 3) + "\n"
                else:
                    text += "			return OpStatus::ERR; // No values so return error\n"

                text += "		}\n\n"

            text += ("	}\n"
                     "	return OpStatus::ERR_NO_SUCH_RESOURCE;\n"
                     "}\n"
                     "// Enum introspection: END\n")
        return text