def generate(self): package = self.cppPackage.package guard = re.sub( "_+", "_", re.sub("[^a-zA-Z0-9]+", "_", os.path.basename(self.filePath))).strip("_").upper() includes = [ cpp_path_norm(package.cpp.filenames["opMessageDeclaration"]), "modules/protobuf/src/protobuf_input.h", "modules/protobuf/src/protobuf_output.h", "modules/protobuf/src/protobuf_message.h", "modules/protobuf/src/protobuf_data.h", "modules/protobuf/src/generated/g_protobuf_descriptors.h", ] text = fileHeader() text += "\n" + render( """ // Generated from %(proto_file)s #include "core/pch.h" #ifndef %(guard)s #define %(guard)s %(defines)s %(includes)s """, { "proto_file": self.cppPackage.makeRelativePath( package.filename), "guard": guard, "defines": self.renderDefines(self.cppPackage.defines), "includes": self.renderIncludes(includes), }) + "\n" set_gen = CppOpMessageSetGenerator(package, self.cppPackage.messages, options=self.cppPackage) text += set_gen.getImplementation() text += render( """ %(endifs)s #endif // %(guard)s """, { "endifs": self.renderEndifs(self.cppPackage.defines), "guard": guard, }) + "\n" return text
def renderServiceDeclaration(self, service, requests, events): enums = self.enums() text = "\n" + self.indent( render(""" virtual OP_STATUS DoReceive( OpScopeClient *client, const OpScopeTPMessage &msg ); virtual int GetCommandCount() const; virtual CommandRange GetCommands() const; virtual const OpProtobufMessage *GetMessage(unsigned int message_id) const; virtual unsigned GetMessageCount() const; virtual MessageIDRange GetMessageIDs() const; virtual MessageRange GetMessages() const; """)) + "\n\n" if enums: text += self.indent( render(""" // Introspection of enums virtual EnumIDRange GetEnumIDs() const; virtual unsigned GetEnumCount() const; virtual BOOL HasEnum(unsigned enum_id) const; virtual OP_STATUS GetEnum(unsigned enum_id, const uni_char *&name, unsigned &value_count) const; virtual OP_STATUS GetEnumValue(unsigned enum_id, unsigned idx, const uni_char *&value_name, unsigned &value_number) const; """)) + "\n\n" text += self.indent( render(""" virtual const char *GetVersionString() const; virtual int GetMajorVersion() const; virtual int GetMinorVersion() const; virtual const char *GetPatchVersion() const; """)) + "\n\n" if requests: text += " // Request/Response functions\n" for command in requests: text += " %(function)s\n" % { "function": request_functionSignature(command) } text += "\n" if events: text += " // Event functions\n" for command in events: text += " %(function)s\n" % { "function": event_functionSignature(command) } text += "\n" text += "\n Descriptors *GetDescriptors() const;\n" return text
def generate(self): package = self.cppPackage.package guard = re.sub( "_+", "_", re.sub("[^a-zA-Z0-9]+", "_", os.path.basename(self.filePath))).strip("_").upper() includes = [ cpp_path_norm(package.cpp.filenames["messageDeclaration"]), "modules/hardcore/component/OpTypedMessage.h", ] text = fileHeader() text += "\n" + render( """ // Generated from %(proto_file)s #ifndef %(guard)s #define %(guard)s %(defines)s %(includes)s """, { "proto_file": self.cppPackage.makeRelativePath( package.filename), "guard": guard, "defines": self.renderDefines(self.cppPackage.defines), "includes": self.renderIncludes(includes), }) + "\n" set_gen = CppOpMessageSetGenerator(package, self.cppPackage.messages, options=self.cppPackage) text += set_gen.getInterface() text += render( """ %(endifs)s #endif // %(guard)s """, { "endifs": self.renderEndifs(self.cppPackage.defines), "guard": guard, }) + "\n" return text
def generate(self): text = fileHeader() text += ( "\n" + render( """ #include "core/pch.h" %(defines)s #include "%(interfaceInclude)s" """, { "defines": self.renderDefines(self.defines), "interfaceInclude": cpp_path_norm(self.includes["interfaceDeclaration"]), "serviceStr": strQuote(self.service.name), }, ) + "\n" ) className = self.service.iparent.cpp.cppMessageSet().name set_gen = CppMessageSetGenerator( self.service.iparent, serviceMessages2(self.service), className, self.operaRoot ) text += set_gen.renderDescriptorImplementation() text += set_gen.getImplementation() gen = CppServiceGenerator(self.service) text += gen.getInterfaceImplementation() text += "\n// Service implementation: BEGIN\n" text += gen.getServiceImplementation(generate_instance=self.cppService.generateInstance) text += "\n// Service implementation: END\n\n" text += ( render( """ %(endifs)s """, {"endifs": self.renderEndifs(self.defines)}, ) + "\n" ) return text
def renderInterface(self): # all_messages are sorted topologically all_messages = [msg for msg in self.messages if msg != defaultMessage] # sorted_messages are sorted alphabetically sorted_messages = sorted(all_messages, key=lambda i: i.name) message_count = len(sorted_messages) # generators are sorted topologically to ensure class references compiles message_set = self.package.cpp.cppOpMessageSet() text = "" if self.package.cpp.useOpMessageSet: text += "\n" + render(""" class %(class)s { public: """, { "class": message_set.name, }) + "\n\n" text += "\n // BEGIN: Message classes\n" for msg in sorted_messages: text += self.indent(self.renderMessage(msg)) + "\n\n" text += "\n // END: Message classes\n" if self.package.cpp.useOpMessageSet: text += "\n};\n\n" return text
def code(): text = "" for message in messages: message_defines = getPackage( message).cpp.defines() + message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text += self.indent( render( """ case %(class)s::Type: // %(file)s: %(messagePath)s return %(class)s::Deserialize(src, dst, delay, data); """, { "opMessageID": message.cpp.opMessageID, "messagePath": ".".join(message.path()), "file": os.path.normpath( getPackage(message).filename).replace( "\\", "/"), "class": message.cpp.opMessage().symbol(), })) + "\n\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" return text
def renderInterface(self): # all_messages are sorted topologically all_messages = [msg for msg in self.messages if msg != defaultMessage] # sorted_messages are sorted alphabetically sorted_messages = sorted(all_messages, key=lambda i: i.name) message_count = len(sorted_messages) # generators are sorted topologically to ensure class references compiles message_set = self.package.cpp.cppOpMessageSet() text = "" if self.package.cpp.useOpMessageSet: text += "\n" + render( """ class %(class)s { public: """, { "class": message_set.name, }) + "\n\n" text += "\n // BEGIN: Message classes\n" for msg in sorted_messages: text += self.indent(self.renderMessage(msg)) + "\n\n" text += "\n // END: Message classes\n" if self.package.cpp.useOpMessageSet: text += "\n};\n\n" return text
def generate(self): package = self.cppPackage.package guard = re.sub("_+", "_", re.sub("[^a-zA-Z0-9]+", "_", os.path.basename(self.filePath))).strip("_").upper() includes = [cpp_path_norm(package.cpp.filenames["opMessageDeclaration"]), "modules/protobuf/src/protobuf_input.h", "modules/protobuf/src/protobuf_output.h", "modules/protobuf/src/protobuf_message.h", "modules/protobuf/src/protobuf_data.h", "modules/protobuf/src/generated/g_protobuf_descriptors.h", ] text = fileHeader() text += "\n" + render(""" // Generated from %(proto_file)s #include "core/pch.h" #ifndef %(guard)s #define %(guard)s %(defines)s %(includes)s """, { "proto_file": self.cppPackage.makeRelativePath(package.filename), "guard": guard, "defines": self.renderDefines(self.cppPackage.defines), "includes": self.renderIncludes(includes), }) + "\n" set_gen = CppOpMessageSetGenerator(package, self.cppPackage.messages, options=self.cppPackage) text += set_gen.getImplementation() text += render(""" %(endifs)s #endif // %(guard)s """, { "endifs": self.renderEndifs(self.cppPackage.defines), "guard": guard, }) + "\n" return text
def renderVerify(self, messages): text = "\n" + render( """ /*static*/ BOOL %(class)s::VerifyType(int type) { \tswitch(type) \t{ """, { "class": "OpTypedMessageBase", }) + "\n" for message in messages: message_defines = getPackage( message).cpp.defines() + message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text += self.indent( render( """ case %(class)s::Type: // %(file)s: %(messagePath)s """, { "opMessageID": message.cpp.opMessageID, "messagePath": ".".join(message.path()), "file": os.path.normpath(getPackage(message).filename).replace( "\\", "/"), "class": message.cpp.opMessage().symbol(), }), 2) + "\n\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" text += "\n\t\t\t" + render( """ \t\t\treturn TRUE; \t\tdefault: \t\t\treturn FALSE; \t} } """, { "class": "OpTypedMessageBase", }) + "\n" return text
def renderVerify(self, enums): text = "\n" + render(""" /** * Check if the type value @a type can be mapped to a type in an OpTypedMessage sub-class. * @param type Integer value corresponding to type. * @return @c TRUE if the value is valid, @c FALSE otherwise. */ static BOOL VerifyType(int type); """) + "\n" return text
def generate(self): text = fileHeader() text += "\n" + render( """ #include "core/pch.h" %(defines)s #include "%(interfaceInclude)s" """, { "defines": self.renderDefines(self.defines), "interfaceInclude": cpp_path_norm(self.includes["interfaceDeclaration"]), "serviceStr": strQuote(self.service.name), }) + "\n" className = self.service.iparent.cpp.cppMessageSet().name set_gen = CppMessageSetGenerator(self.service.iparent, serviceMessages2(self.service), className, self.operaRoot) text += set_gen.renderDescriptorImplementation() text += set_gen.getImplementation() gen = CppServiceGenerator(self.service) text += gen.getInterfaceImplementation() text += "\n// Service implementation: BEGIN\n" text += gen.getServiceImplementation( generate_instance=self.cppService.generateInstance) text += "\n// Service implementation: END\n\n" text += render(""" %(endifs)s """, { "endifs": self.renderEndifs(self.defines), }) + "\n" return text
def renderDeserialize(self, messages): def code(): text = "" for message in messages: message_defines = getPackage( message).cpp.defines() + message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text += self.indent( render( """ case %(class)s::Type: // %(file)s: %(messagePath)s return %(class)s::Deserialize(src, dst, delay, data); """, { "opMessageID": message.cpp.opMessageID, "messagePath": ".".join(message.path()), "file": os.path.normpath( getPackage(message).filename).replace( "\\", "/"), "class": message.cpp.opMessage().symbol(), })) + "\n\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" return text text = "\n" + render( """ /*static*/ OpTypedMessage* OpTypedMessageBase::DeserializeData( int type, const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data) { \t// Decode the serialized data by matching @a type against the Type in one of the sub-classes of OpTypedMessage \tswitch(type) \t{ %(code)s \t\tdefault: \t\t\tOP_ASSERT(!"Unknown message type, cannot decode"); \t\t\treturn NULL; \t} } """, { "code": self.indent(code()), }) + "\n" return text
def generate(self): text = "" text += fileHeader() text += "\n" + render(""" #include "core/pch.h" #ifdef SCOPE_SUPPORT #include "modules/scope/src/generated/g_scope_manager.h" """) + "\n" gen = CppManagerGenerator(self.services) text += gen.getImplementation() text += render(""" #endif // SCOPE_SUPPORT """) + "\n" return text
def generate(self): package = self.cppPackage.package guard = re.sub("_+", "_", re.sub("[^a-zA-Z0-9]+", "_", os.path.basename(self.filePath))).strip("_").upper() includes = [cpp_path_norm(package.cpp.filenames["messageDeclaration"]), "modules/hardcore/component/OpTypedMessage.h", ] text = fileHeader() text += "\n" + render(""" // Generated from %(proto_file)s #ifndef %(guard)s #define %(guard)s %(defines)s %(includes)s """, { "proto_file": self.cppPackage.makeRelativePath(package.filename), "guard": guard, "defines": self.renderDefines(self.cppPackage.defines), "includes": self.renderIncludes(includes), }) + "\n" set_gen = CppOpMessageSetGenerator(package, self.cppPackage.messages, options=self.cppPackage) text += set_gen.getInterface() text += render(""" %(endifs)s #endif // %(guard)s """, { "endifs": self.renderEndifs(self.cppPackage.defines), "guard": guard, }) + "\n" return text
def generate(self): includes = [ "modules/hardcore/src/generated/OpTypedMessageBase.h", ] includes_set = set(includes) for message in self.messages: package = getPackage(message) for include in package.cpp.opMessageIncludes(): if include not in includes_set: includes_set.add(include) includes.append(include) text = fileHeader() text += "\n" + render( """ // Generated from proto files in the system #include "core/pch.h" %(defines)s %(includes)s """, { "defines": self.renderDefines(self.defines), "includes": self.renderIncludes(includes), }) + "\n" text += self.renderVerify(self.messages) + "\n" text += self.renderDeserialize(self.messages) + "\n" text += render(""" %(endifs)s """, { "endifs": self.renderEndifs(self.defines), }) + "\n" return text
def generate(self): includes = ["modules/hardcore/src/generated/OpTypedMessageBase.h", ] includes_set = set(includes) for message in self.messages: package = getPackage(message) for include in package.cpp.opMessageIncludes(): if include not in includes_set: includes_set.add(include) includes.append(include) text = fileHeader() text += "\n" + render(""" // Generated from proto files in the system #include "core/pch.h" %(defines)s %(includes)s """, { "defines": self.renderDefines(self.defines), "includes": self.renderIncludes(includes), }) + "\n" text += self.renderVerify(self.messages) + "\n" text += self.renderDeserialize(self.messages) + "\n" text += render(""" %(endifs)s """, { "endifs": self.renderEndifs(self.defines), }) + "\n" return text
def generate(self): text = "" text += fileHeader() text += "\n" + render(""" #ifndef OP_SCOPE_MANAGER_G_H #define OP_SCOPE_MANAGER_G_H #ifdef SCOPE_SUPPORT """) + "\n" gen = CppManagerGenerator(self.services) text += gen.getDeclaration() text += render(""" #endif // SCOPE_SUPPORT #endif // OP_SCOPE_MANAGER_G_H """) + "\n" return text
def renderVerify(self, messages): text = "\n" + render(""" /*static*/ BOOL %(class)s::VerifyType(int type) { \tswitch(type) \t{ """, { "class": "OpTypedMessageBase", }) + "\n" for message in messages: message_defines = getPackage(message).cpp.defines() + message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text += self.indent(render(""" case %(class)s::Type: // %(file)s: %(messagePath)s """, { "opMessageID": message.cpp.opMessageID, "messagePath": ".".join(message.path()), "file": os.path.normpath(getPackage(message).filename).replace("\\", "/"), "class": message.cpp.opMessage().symbol(), }), 2) + "\n\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" text += "\n\t\t\t" + render(""" \t\t\treturn TRUE; \t\tdefault: \t\t\treturn FALSE; \t} } """, { "class": "OpTypedMessageBase", }) + "\n" return text
def renderDeserialize(self, messages): def code(): text = "" for message in messages: message_defines = getPackage(message).cpp.defines() + message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text += self.indent(render(""" case %(class)s::Type: // %(file)s: %(messagePath)s return %(class)s::Deserialize(src, dst, delay, data); """, { "opMessageID": message.cpp.opMessageID, "messagePath": ".".join(message.path()), "file": os.path.normpath(getPackage(message).filename).replace("\\", "/"), "class": message.cpp.opMessage().symbol(), })) + "\n\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" return text text = "\n" + render(""" /*static*/ OpTypedMessage* OpTypedMessageBase::DeserializeData( int type, const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data) { \t// Decode the serialized data by matching @a type against the Type in one of the sub-classes of OpTypedMessage \tswitch(type) \t{ %(code)s \t\tdefault: \t\t\tOP_ASSERT(!"Unknown message type, cannot decode"); \t\t\treturn NULL; \t} } """, { "code": self.indent(code()), }) + "\n" return text
def code(): text = "" for message in messages: message_defines = getPackage(message).cpp.defines() + message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text += self.indent(render(""" case %(class)s::Type: // %(file)s: %(messagePath)s return %(class)s::Deserialize(src, dst, delay, data); """, { "opMessageID": message.cpp.opMessageID, "messagePath": ".".join(message.path()), "file": os.path.normpath(getPackage(message).filename).replace("\\", "/"), "class": message.cpp.opMessage().symbol(), })) + "\n\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" return text
def renderInterfaceImplementation(self, service, includes, commands): messages = [ msg for msg in self.sortedMessages() if msg != defaultMessage ] all_messages = [ msg for msg in self.sortedMessages(with_inline=True) if msg != defaultMessage ] enums = self.enums() text = "\n" for include in includes: text += "#include %(include)s\n" % {"include": strQuote(include)} text += "\n" + render( """ // BEGIN: %(class)s_SI::Descriptors %(class)s_SI::Descriptors::Descriptors() { """, { "class": service.options["cpp_class"].value, }) + "\n" text += render( """ } %(class)s_SI::Descriptors::~Descriptors() { """, { "class": service.options["cpp_class"].value, }) + "\n" text += render( """ } OP_STATUS %(class)s_SI::Descriptors::Construct() { RETURN_IF_ERROR(%(descriptorClass)s::Construct()); """, { "class": service.options["cpp_class"].value, "descriptorClass": self.package.cpp.descriptorClass().symbol(), }) + "\n" text += " // Initialize commands\n" for idx, command in enumerate(commands): text += self.indent( render( """ command_list[%(idx)s] = OpScopeCommand(%(command)s, %(commandEnum)s """, { "idx": idx, "command": strQuote(command.name), "commandEnum": enumName(command), })) if isinstance(command, proto.Event): text += ",\n OpScopeCommand::Type_Event" else: text += ",\n OpScopeCommand::Type_Call" if isinstance(command, proto.Event): text += render( """ , _gen_void_MsgID, %(requestIdentifier)s """, { "requestIdentifier": self.renderMessageID( command.message), }) else: text += render( """ , %(requestIdentifier)s, %(responseIdentifier)s """, { "requestIdentifier": self.renderMessageID(command.message), "responseIdentifier": self.renderMessageID(command.response), }) text += "\n );\n" text += " " + render( """ return OpStatus::OK; } // END: %(class)s_SI::Descriptors """, { "class": service.options["cpp_class"].value, }) return text
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
def renderImplementation(self, services): text = "" fields = {} for service in services: fields[service] = { "name": service.name, "memberName": self.memberName(service.name), "varName": self.varName(service.name), "class": service.options["cpp_class"].value, } if "cpp_feature" in service.options: fields[service]["feature"] = service.options["cpp_feature"].value if "cpp_construct" in service.options: fields[service]["construct"] = service.options["cpp_construct"].value text += "\n\n" + render(""" #include "modules/scope/src/generated/g_scope_manager.h" // Services we need to instantiate """) + "\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 += """# include "%(file)s"\n""" % {"file": service.cpp.files()["serviceDeclaration"]} if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % {"feature": service.options["cpp_feature"].value} text += "\n" + render(""" /* OpScopeServiceFactory */ OpScopeServiceFactory::OpScopeServiceFactory() : descriptors(NULL) """) + "\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" % fields[service] text += " , %(memberName)s(NULL)\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += render(""" { } OP_STATUS OpScopeServiceFactory::CreateServices(OpScopeServiceManager *manager) { RETURN_IF_ERROR(InitializeShared()); """) + "\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" % fields[service] text += self.indent(render(""" { %(memberName)s = OP_NEW(%(class)s, ()); RETURN_OOM_IF_NULL(%(memberName)s); %(memberName)s->SetManager(manager); """, fields[service]) + "\n") if "cpp_construct" in service.options: text += " OP_STATUS status = %(memberName)s->Construct(%(construct)s);\n" % fields[service] else: text += " OP_STATUS status = %(memberName)s->Construct();\n" % fields[service] if "cpp_is_essential" in service.options and service.options["cpp_is_essential"].value == "true": text += self.indent(render(""" // Ensure that service '%(name)s' is initialized, cannot work without it if (OpStatus::IsError(status)) return status; manager->RegisterService(%(memberName)s); """, fields[service]), 2) else: text += self.indent(render(""" if (OpStatus::IsMemoryError(status)) return status; // Only register the service if there are no errors while constructing it if (OpStatus::IsSuccess(status)) manager->RegisterService(%(memberName)s); """, fields[service]), 2) text += "\n }\n" if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += "\n" + self.indent(render(""" // Add meta-services for (MetaService *meta_service = meta_services.First(); meta_service; meta_service = meta_service->Suc()) { meta_service->service = OP_NEW_L(OpScopeMetaService, (meta_service->name.CStr())); RETURN_OOM_IF_NULL(meta_service->service); meta_service->service->SetManager(manager); OP_STATUS status = meta_service->service->Construct(); if (OpStatus::IsMemoryError(status)) return status; // Only register the service if there are no errors while constructing it if (OpStatus::IsSuccess(status)) manager->RegisterService(meta_service->service); } // All services has been initialized, now continue with the intra-service setup OpScopeServiceManager::ServiceRange range = manager->GetServices(); for (; !range.IsEmpty(); range.PopFront()) { OP_STATUS status = range.Front()->OnPostInitialization(); if (OpStatus::IsMemoryError(status)) return status; // Any errors in post initialization makes the service unavailable if (OpStatus::IsError(status)) { manager->UnregisterService(range.Front()); """) + "\n") for service in services: if "cpp_instance" not in service.options or service.options["cpp_instance"].value == "true": if "cpp_is_essential" in service.options and service.options["cpp_is_essential"].value == "true": if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += self.indent(render(""" // Ensure that post initialization of service '%(name)s' succeeds, cannot work without it if (range.Front() == %(memberName)s) return status; """, fields[service]) + "\n", 3) if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += " " + render(""" } } return OpStatus::OK; } void OpScopeServiceFactory::DeleteServices() { // Once we have starting shutting down services, we don't want any new // events from Core. This protects against shutdown crashes. """) + "\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" % fields[service] text += self.indent(render(""" %(class)s *tmp_%(memberName)s = %(memberName)s; %(memberName)s = NULL; """, fields[service]) + "\n") if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += "\n // Now destroy all 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" % fields[service] text += " OP_DELETE(tmp_%(memberName)s);\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += "\n " + render(""" // Delete meta-services meta_services.Clear(); // Cleanup any shared member variables CleanupShared(); } /* OpScopeDescriptorSet */ OpScopeDescriptorSet::OpScopeDescriptorSet() : dummy(0) """) + "\n" for service in services: if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += " , %(varName)s(NULL)\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += render(""" { (void)dummy; } OpScopeDescriptorSet::~OpScopeDescriptorSet() { """) + "\n" for service in services: if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += " OP_DELETE(%(varName)s);\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += render(""" } OP_STATUS OpScopeDescriptorSet::Construct() { """) + "\n" for service in services: if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += self.indent(render(""" %(varName)s = OP_NEW(%(class)s_SI::Descriptors, ()); RETURN_OOM_IF_NULL(%(varName)s); RETURN_IF_ERROR(%(varName)s->Construct()); """, fields[service]) + "\n") if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += " return OpStatus::OK;\n}\n" return text
def renderRequestDecode(self, command): text = "\n OP_STATUS status = OpStatus::OK;\n" if requiresAsyncResponse(command): text += self.indent( render(""" unsigned async_tag; status = InitAsyncCommand(msg, async_tag); // Needed for async requests, the response will use this info when request is done if (OpStatus::IsError(status)) { RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetInitAsyncCommandFailedText())); return status; } """), 2) + "\n" if command.message.isNonEmpty(): text += " %(requestMessage)s in;\n" % { "requestMessage": message_className(command.message) } if hasattr(command, 'response') and command.response.isNonEmpty(): text += " %(responseMessage)s out;\n" % { "responseMessage": message_className(command.response) } text += "\n" if command.message.isNonEmpty(): text += self.indent( render( """ OpProtobufInstanceProxy in_proxy(%(requestMessage)s::GetMessageDescriptor(GetDescriptors()), &in); if (in_proxy.GetProtoMessage() == NULL) return OpStatus::ERR_NO_MEMORY; status = ParseMessage(client, msg, in_proxy); if (OpStatus::IsError(status)) { if (GetCommandError().GetStatus() == OpScopeTPHeader::OK) // Set a generic error if none was set by a parser RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetParseCommandMessageFailedText())); return status; } """, { "requestMessage": message_className(command.message), }), 2) + "\n\n" text += self.indent( render(""" status = %(commandCall)s; if (OpStatus::IsError(status)) { if (GetCommandError().GetStatus() == OpScopeTPHeader::OK) // Set a generic error if none was set by command """) % { "commandCall": request_functionCall(command), }, 2) + "\n" if requiresAsyncResponse(command): text += self.indent( render(""" { OP_STATUS tmp_status = SetCommandError(OpScopeTPHeader::InternalError, GetCommandExecutionFailedText()); OpStatus::Ignore(tmp_status); } // Remove the async command since the command failed to send an async response CleanupAsyncCommand(async_tag); """), 3) + "\n" else: text += " RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetCommandExecutionFailedText()));\n" text += (" return status;\n" + " }\n") if hasattr(command, 'response') and command.response.isNonEmpty(): text += "\n" + self.indent( render( """ OpProtobufInstanceProxy out_proxy(%(responseMessage)s::GetMessageDescriptor(GetDescriptors()), &out); if (out_proxy.GetProtoMessage() == NULL) return OpStatus::ERR_NO_MEMORY; RETURN_IF_ERROR(SendResponse(client, msg, out_proxy)); """, { "responseMessage": message_className(command.response), }), 2) + "\n" elif not requiresAsyncResponse(command): text += "\n" + self.indent( render( """ // The request does not define a response message so we send the default response which is an empty message OpProtobufInstanceProxy out_proxy(OpScopeDefaultMessage::GetMessageDescriptor(), &g_scope_manager->default_message_instance); if (out_proxy.GetProtoMessage() == NULL) return OpStatus::ERR_NO_MEMORY; status = SendResponse(client, msg, out_proxy); if (OpStatus::IsError(status)) { if (!IsResponseSent() && GetCommandError().GetStatus() == OpScopeTPHeader::OK) // Set a generic error if response sending failed or no error was set by response code RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetCommandResponseFailedText())); return status; } """, {}), 2) + "\n" return text
def generate(self): enums = self.enums guard = re.sub("_+", "_", re.sub("[^a-zA-Z0-9]+", "_", os.path.basename(self.filePath))).strip("_").upper() text = fileHeader() text += "\n" + render(""" // Generated from proto files in the system #ifndef %(guard)s #define %(guard)s %(defines)s class OpTypedMessage; struct OpMessageAddress; class OpData; class OpTypedMessageBase { public: """, { "defines": self.renderDefines(self.defines), "guard": guard, }) + "\n" text += self.indent(self.renderVerify(enums)) + "\n" text += self.indent(render(""" /** * Deserializes the message data in @p data based on the @p type. * It will call the Class::Deserialize() method on the class that * belongs to the type. * * @param type The type of message data to decode. This determines * the class of the returned instance. * @param src Source address of the message. This will be placed in * the returned object. * @param dst Destination address of the message. This will be * placed in the returned object. * @param delay Number of milliseconds until this message should * be processed. This will be recorded in the returned object. * @param data The data-stream from which to de-serialize the * message object. * @return The deserialized message object or @c NULL on failure. */ static OpTypedMessage* DeserializeData( int type, const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data); """)) text += render(""" }; %(endifs)s #endif // %(guard)s """, { "endifs": self.renderEndifs(self.defines), "guard": guard, }) + "\n" return text
def renderMessageImplementation(self, message): klass = message.cpp.opMessage() protoKlass = message.cpp.klass() message_gen = CppMessageGenerator( message, self.package.cpp.cppMessageSet().symbol()) message_gen.initMembers() message_gen.cpp_class_path = klass.symbol() members = "" for member in message_gen.redirect_members: if not member.is_inline: members += message_gen.renderFunctionImplementation( member) + "\n\n" text = render( """ %(classPath)s::~%(class)s() { } /* static */ %(classPath)s* %(classPath)s::Cast(const OpTypedMessage* msg) { OP_ASSERT(msg && msg->GetType() == Type); return static_cast<%(classPath)s*>(const_cast<OpTypedMessage*>(msg)); } /* static */ %(classPath)s* %(classPath)s::Deserialize( const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data) { OpProtobufInputStream stream; RETURN_VALUE_IF_ERROR(stream.Construct(data), NULL); %(classPathRelative)s *msg = %(classPathRelative)s::Create(src, dst, delay); if (!msg) return NULL; OpProtobufInstanceProxy instance(%(protoClassPath)s::GetMessageDescriptor(PROTOBUF_DESCRIPTOR(%(descriptorID)s)), &msg->protobuf_data); if (OpStatus::IsError(stream.Read(instance))) { OP_DELETE(msg); return NULL; } return msg; } OP_STATUS %(classPath)s::Serialize(OpData& data) const { OpProtobufOpDataOutputRange range(data); OpProtobufOutputStream stream(&range); %(protoClassPath)s *proto = const_cast<%(protoClassPath)s *>(&protobuf_data); void *proto_ptr = proto; OpProtobufInstanceProxy instance(%(protoClassPath)s::GetMessageDescriptor(PROTOBUF_DESCRIPTOR(%(descriptorID)s)), proto_ptr); return stream.Write(instance); } const char * %(classPath)s::GetTypeString() const { const OpProtobufMessage *d = %(protoClassPath)s::GetMessageDescriptor(PROTOBUF_DESCRIPTOR(%(descriptorID)s)); return d ? d->GetName() : NULL; } """, { "classPath": klass.symbol(), "classPathRelative": klass.symbol(relative=klass), "class": klass.name, "protoClassPath": protoKlass.symbol(), "globalModule": "g_%s" % self.options.module, "descriptorID": self.package.cpp.descriptorIdentifier(), }) text += members return text
def renderServiceInterface(self, service, commands, generate_instance): text = "\n" + render( """ class %(class)s_SI : public OpScopeService , public %(class)s_MessageSet { public: %(class)s_SI(const uni_char* id = NULL, OpScopeServiceManager *manager = NULL, ControlType control = CONTROL_MANUAL); virtual ~%(class)s_SI(); enum CommandEnum { """, { "class": service.options["cpp_class"]. value, # TODO: Store fully generated class name on service object }) + "\n" for command in commands[:1]: text += " %(enumName)s = %(enumValue)s\n" % { "enumName": command.options["cpp_enum_name"].value, "enumValue": command.id, } for command in commands[1:]: text += " , %(enumName)s = %(enumValue)s\n" % { "enumName": command.options["cpp_enum_name"].value, "enumValue": command.id, } text += "\n , Command_Count = %(commandCount)s // Number of commands in this service\n" % { "commandCount": len(commands), } text += self.indent(render(""" }; """)) text += "\n" + self.indent( render( """ // This class contains the descriptors or all commands of this service class Descriptors : public %(descriptorClass)s { public: \tDescriptors(); \t~Descriptors(); \tOP_STATUS Construct(); """, { "class": service.options["cpp_class"].value, "descriptorClass": self.package.cpp.descriptorClass().symbol(), })) + "\n\n" text += "\n" text += (" // List of commands\n" + " OpScopeCommand command_list[Command_Count];\n" + " };\n\n") if generate_instance: text += "\n// Service API implementation: BEGIN\n\n" text += self.renderServiceDeclaration(self.service, self.requests, self.events) + "\n\n" text += "\n// Service API implementation: END\n" text += "\n};\n\n" text += "\n" return text
def renderImplementation(self, services): text = "" fields = {} for service in services: fields[service] = { "name": service.name, "memberName": self.memberName(service.name), "varName": self.varName(service.name), "class": service.options["cpp_class"].value, } if "cpp_feature" in service.options: fields[service]["feature"] = service.options[ "cpp_feature"].value if "cpp_construct" in service.options: fields[service]["construct"] = service.options[ "cpp_construct"].value text += "\n\n" + render(""" #include "modules/scope/src/generated/g_scope_manager.h" // Services we need to instantiate """) + "\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 += """# include "%(file)s"\n""" % { "file": service.cpp.files()["serviceDeclaration"] } if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % { "feature": service.options["cpp_feature"].value } text += "\n" + render(""" /* OpScopeServiceFactory */ OpScopeServiceFactory::OpScopeServiceFactory() : descriptors(NULL) """) + "\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" % fields[service] text += " , %(memberName)s(NULL)\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += render(""" { } OP_STATUS OpScopeServiceFactory::CreateServices(OpScopeServiceManager *manager) { RETURN_IF_ERROR(InitializeShared()); """) + "\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" % fields[service] text += self.indent( render( """ { %(memberName)s = OP_NEW(%(class)s, ()); RETURN_OOM_IF_NULL(%(memberName)s); %(memberName)s->SetManager(manager); """, fields[service]) + "\n") if "cpp_construct" in service.options: text += " OP_STATUS status = %(memberName)s->Construct(%(construct)s);\n" % fields[ service] else: text += " OP_STATUS status = %(memberName)s->Construct();\n" % fields[ service] if "cpp_is_essential" in service.options and service.options[ "cpp_is_essential"].value == "true": text += self.indent( render( """ // Ensure that service '%(name)s' is initialized, cannot work without it if (OpStatus::IsError(status)) return status; manager->RegisterService(%(memberName)s); """, fields[service]), 2) else: text += self.indent( render( """ if (OpStatus::IsMemoryError(status)) return status; // Only register the service if there are no errors while constructing it if (OpStatus::IsSuccess(status)) manager->RegisterService(%(memberName)s); """, fields[service]), 2) text += "\n }\n" if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += "\n" + self.indent( render(""" // Add meta-services for (MetaService *meta_service = meta_services.First(); meta_service; meta_service = meta_service->Suc()) { meta_service->service = OP_NEW_L(OpScopeMetaService, (meta_service->name.CStr())); RETURN_OOM_IF_NULL(meta_service->service); meta_service->service->SetManager(manager); OP_STATUS status = meta_service->service->Construct(); if (OpStatus::IsMemoryError(status)) return status; // Only register the service if there are no errors while constructing it if (OpStatus::IsSuccess(status)) manager->RegisterService(meta_service->service); } // All services has been initialized, now continue with the intra-service setup OpScopeServiceManager::ServiceRange range = manager->GetServices(); for (; !range.IsEmpty(); range.PopFront()) { OP_STATUS status = range.Front()->OnPostInitialization(); if (OpStatus::IsMemoryError(status)) return status; // Any errors in post initialization makes the service unavailable if (OpStatus::IsError(status)) { manager->UnregisterService(range.Front()); """) + "\n") for service in services: if "cpp_instance" not in service.options or service.options[ "cpp_instance"].value == "true": if "cpp_is_essential" in service.options and service.options[ "cpp_is_essential"].value == "true": if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += self.indent( render( """ // Ensure that post initialization of service '%(name)s' succeeds, cannot work without it if (range.Front() == %(memberName)s) return status; """, fields[service]) + "\n", 3) if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += " " + render(""" } } return OpStatus::OK; } void OpScopeServiceFactory::DeleteServices() { // Once we have starting shutting down services, we don't want any new // events from Core. This protects against shutdown crashes. """) + "\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" % fields[service] text += self.indent( render( """ %(class)s *tmp_%(memberName)s = %(memberName)s; %(memberName)s = NULL; """, fields[service]) + "\n") if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += "\n // Now destroy all 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" % fields[service] text += " OP_DELETE(tmp_%(memberName)s);\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += "\n " + render(""" // Delete meta-services meta_services.Clear(); // Cleanup any shared member variables CleanupShared(); } /* OpScopeDescriptorSet */ OpScopeDescriptorSet::OpScopeDescriptorSet() : dummy(0) """) + "\n" for service in services: if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += " , %(varName)s(NULL)\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += render(""" { (void)dummy; } OpScopeDescriptorSet::~OpScopeDescriptorSet() { """) + "\n" for service in services: if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += " OP_DELETE(%(varName)s);\n" % fields[service] if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += render(""" } OP_STATUS OpScopeDescriptorSet::Construct() { """) + "\n" for service in services: if "cpp_feature" in service.options: text += "#ifdef %(feature)s\n" % fields[service] text += self.indent( render( """ %(varName)s = OP_NEW(%(class)s_SI::Descriptors, ()); RETURN_OOM_IF_NULL(%(varName)s); RETURN_IF_ERROR(%(varName)s->Construct()); """, fields[service]) + "\n") if "cpp_feature" in service.options: text += "#endif // %(feature)s\n" % fields[service] text += " return OpStatus::OK;\n}\n" return text
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
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
def renderServiceDeclaration(self, service, requests, events): enums = self.enums() text = ( "\n" + self.indent( render( """ virtual OP_STATUS DoReceive( OpScopeClient *client, const OpScopeTPMessage &msg ); virtual int GetCommandCount() const; virtual CommandRange GetCommands() const; virtual const OpProtobufMessage *GetMessage(unsigned int message_id) const; virtual unsigned GetMessageCount() const; virtual MessageIDRange GetMessageIDs() const; virtual MessageRange GetMessages() const; """ ) ) + "\n\n" ) if enums: text += ( self.indent( render( """ // Introspection of enums virtual EnumIDRange GetEnumIDs() const; virtual unsigned GetEnumCount() const; virtual BOOL HasEnum(unsigned enum_id) const; virtual OP_STATUS GetEnum(unsigned enum_id, const uni_char *&name, unsigned &value_count) const; virtual OP_STATUS GetEnumValue(unsigned enum_id, unsigned idx, const uni_char *&value_name, unsigned &value_number) const; """ ) ) + "\n\n" ) text += ( self.indent( render( """ virtual const char *GetVersionString() const; virtual int GetMajorVersion() const; virtual int GetMinorVersion() const; virtual const char *GetPatchVersion() const; """ ) ) + "\n\n" ) if requests: text += " // Request/Response functions\n" for command in requests: text += " %(function)s\n" % {"function": request_functionSignature(command)} text += "\n" if events: text += " // Event functions\n" for command in events: text += " %(function)s\n" % {"function": event_functionSignature(command)} text += "\n" text += "\n Descriptors *GetDescriptors() const;\n" return text
def renderMessage(self, message): klass = message.cpp.opMessage() protobuf_klass = message.cpp.klass() message_gen = CppMessageGenerator( message, self.package.cpp.cppMessageSet().symbol()) message_gen.initMembers() members = "" for member in message_gen.redirect_members: members += self.indent( message_gen.renderFunctionDefinition( member, use_rtype_outer=True)) + "\n\n" all_args = message_gen.construct + message_gen.constructor all_args.sort(key=lambda i: i[0].default != None) args = "\n ".join( [arg.declaration(relative=klass) + "," for arg, idx in all_args]) constructor_args = "\n ".join([ ", " + arg.declaration(relative=klass) for arg, idx in sorted(message_gen.constructor, key=lambda i: i[0].default != None) ]) construct_args = "\n ".join([ arg[0].declaration(relative=klass) + comma for arg, comma in commaList( sorted(message_gen.construct, key=lambda i: i[0].default != None)) ]) arg_call = ", ".join([ arg.symbol(relative=klass) for arg, idx in sorted(message_gen.constructor, key=lambda i: i[0].default != None) ]) arg_call_comma = arg_call and ", " + arg_call arg_call2 = ", ".join([ arg.symbol(relative=klass) for arg, idx in sorted(message_gen.construct, key=lambda i: i[0].default != None) ]) allocateDefs = "" if message.cpp.opMessageAlloc == AllocationStrategy.ALLOCATE_OPMEMORYPOOL: allocateDefs = render( """ /** Use OpMemoryPool allocation with OP_NEW */ OP_USE_MEMORY_POOL_DECL; """, {"class": klass.name}) + "\n" custom_create = "" default_create = "" need_default_create = not all_args if all_args: # See if we need a default Create() method with no args, if all args # to the custom Create() method have default values then it is not # needed for arg in all_args: if not arg[0].default: need_default_create = True break custom_create = self.indent( render( """ static %(class)s* Create( %(args)s const OpMessageAddress& src = OpMessageAddress(), const OpMessageAddress& dst = OpMessageAddress(), double delay = 0) { %(class)s *obj = OP_NEW(%(class)s, (src, dst, delay%(arg_call_comma)s)); if (obj) { if (OpStatus::IsSuccess(obj->Construct(%(arg_call2)s))) return obj; OP_DELETE(obj); } return NULL; } """, { "class": klass.name, "args": args, "arg_call2": arg_call2, "arg_call_comma": arg_call_comma, })) if need_default_create: makeCode = "OP_NEW(%(class)s, (src, dst, delay))" % { "class": klass.name, } default_create = self.indent( render( """ static %(class)s* Create() { OpMessageAddress src; OpMessageAddress dst; double delay = 0; return %(makeCode)s; } """, { "class": klass.name, "makeCode": makeCode, })) defaultConstructor = "" for arg in message_gen.constructor: if not arg[0].default: defaultConstructor = self.indent( render( """ %(class)s( const OpMessageAddress& src, const OpMessageAddress& dst, double delay ) : OpTypedMessage(Type, src, dst, delay) , protobuf_data() { } """, { "class": klass.name, })) break doc = "" if klass.doc: doc = klass.doc.toComment() + "\n" text = "" message_defines = message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text = render( """ %(doc)sclass %(class)s : public OpTypedMessage { public: \t/** \t * The type for this message class. \t * \t * @note The reason this contains a integer value and not an enum \t * is to avoid uneccesary dependencies and helps avoid \t * re-compiles whenever a message is added, removed or renamed. \t */ \tstatic const unsigned Type = %(messageIdentifier)du; virtual ~%(class)s(); %(default_create)s static %(class)s* Create( const OpMessageAddress& src, const OpMessageAddress& dst = OpMessageAddress(), double delay = 0) { return OP_NEW(%(class)s, (src, dst, delay)); } %(custom_create)s static %(class)s* Cast(const OpTypedMessage* msg); static %(class)s* Deserialize( const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data); virtual OP_STATUS Serialize(OpData& data) const; virtual const char *GetTypeString() const; // Accessors/modifiers comes here %(members)s protected: %(allocateDefs)s %(class)s( const OpMessageAddress& src, const OpMessageAddress& dst, double delay %(constructor_args)s ) : OpTypedMessage(Type, src, dst, delay) , protobuf_data(%(arg_call)s) { } %(defaultConstructor)s OP_STATUS Construct( %(construct_args)s ) { return protobuf_data.Construct(%(arg_call2)s); } private: %(protobuf_class)s protobuf_data; }; """, { "class": klass.name, "protobuf_class": protobuf_klass.symbol(), "messageIdentifier": message.cpp.opMessageID, "doc": doc, "protobuf_message": "TODO: Fill in protobuf message here", "members": members, "args": args, "arg_call": arg_call, "arg_call_comma": arg_call_comma, "arg_call2": arg_call2, "constructor_args": constructor_args, "construct_args": construct_args, "default_create": default_create, "custom_create": custom_create, "defaultConstructor": defaultConstructor, "allocateDefs": self.indent(allocateDefs), }) + "\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" return text
def renderInterfaceImplementation(self, service, includes, commands): messages = [msg for msg in self.sortedMessages() if msg != defaultMessage] all_messages = [msg for msg in self.sortedMessages(with_inline=True) if msg != defaultMessage] enums = self.enums() text = "\n" for include in includes: text += "#include %(include)s\n" % {"include": strQuote(include)} text += ( "\n" + render( """ // BEGIN: %(class)s_SI::Descriptors %(class)s_SI::Descriptors::Descriptors() { """, {"class": service.options["cpp_class"].value}, ) + "\n" ) text += ( render( """ } %(class)s_SI::Descriptors::~Descriptors() { """, {"class": service.options["cpp_class"].value}, ) + "\n" ) text += ( render( """ } OP_STATUS %(class)s_SI::Descriptors::Construct() { RETURN_IF_ERROR(%(descriptorClass)s::Construct()); """, { "class": service.options["cpp_class"].value, "descriptorClass": self.package.cpp.descriptorClass().symbol(), }, ) + "\n" ) text += " // Initialize commands\n" for idx, command in enumerate(commands): text += self.indent( render( """ command_list[%(idx)s] = OpScopeCommand(%(command)s, %(commandEnum)s """, {"idx": idx, "command": strQuote(command.name), "commandEnum": enumName(command)}, ) ) if isinstance(command, proto.Event): text += ",\n OpScopeCommand::Type_Event" else: text += ",\n OpScopeCommand::Type_Call" if isinstance(command, proto.Event): text += render( """ , _gen_void_MsgID, %(requestIdentifier)s """, {"requestIdentifier": self.renderMessageID(command.message)}, ) else: text += render( """ , %(requestIdentifier)s, %(responseIdentifier)s """, { "requestIdentifier": self.renderMessageID(command.message), "responseIdentifier": self.renderMessageID(command.response), }, ) text += "\n );\n" text += " " + render( """ return OpStatus::OK; } // END: %(class)s_SI::Descriptors """, {"class": service.options["cpp_class"].value}, ) return text
def renderServiceInterface(self, service, commands, generate_instance): text = ( "\n" + render( """ class %(class)s_SI : public OpScopeService , public %(class)s_MessageSet { public: %(class)s_SI(const uni_char* id = NULL, OpScopeServiceManager *manager = NULL, ControlType control = CONTROL_MANUAL); virtual ~%(class)s_SI(); enum CommandEnum { """, { "class": service.options[ "cpp_class" ].value # TODO: Store fully generated class name on service object }, ) + "\n" ) for command in commands[:1]: text += " %(enumName)s = %(enumValue)s\n" % { "enumName": command.options["cpp_enum_name"].value, "enumValue": command.id, } for command in commands[1:]: text += " , %(enumName)s = %(enumValue)s\n" % { "enumName": command.options["cpp_enum_name"].value, "enumValue": command.id, } text += "\n , Command_Count = %(commandCount)s // Number of commands in this service\n" % { "commandCount": len(commands) } text += self.indent( render( """ }; """ ) ) text += ( "\n" + self.indent( render( """ // This class contains the descriptors or all commands of this service class Descriptors : public %(descriptorClass)s { public: \tDescriptors(); \t~Descriptors(); \tOP_STATUS Construct(); """, { "class": service.options["cpp_class"].value, "descriptorClass": self.package.cpp.descriptorClass().symbol(), }, ) ) + "\n\n" ) text += "\n" text += " // List of commands\n" + " OpScopeCommand command_list[Command_Count];\n" + " };\n\n" if generate_instance: text += "\n// Service API implementation: BEGIN\n\n" text += self.renderServiceDeclaration(self.service, self.requests, self.events) + "\n\n" text += "\n// Service API implementation: END\n" text += "\n};\n\n" text += "\n" return text
def generate(self): enums = self.enums guard = re.sub( "_+", "_", re.sub("[^a-zA-Z0-9]+", "_", os.path.basename(self.filePath))).strip("_").upper() text = fileHeader() text += "\n" + render( """ // Generated from proto files in the system #ifndef %(guard)s #define %(guard)s %(defines)s class OpTypedMessage; struct OpMessageAddress; class OpData; class OpTypedMessageBase { public: """, { "defines": self.renderDefines(self.defines), "guard": guard, }) + "\n" text += self.indent(self.renderVerify(enums)) + "\n" text += self.indent( render(""" /** * Deserializes the message data in @p data based on the @p type. * It will call the Class::Deserialize() method on the class that * belongs to the type. * * @param type The type of message data to decode. This determines * the class of the returned instance. * @param src Source address of the message. This will be placed in * the returned object. * @param dst Destination address of the message. This will be * placed in the returned object. * @param delay Number of milliseconds until this message should * be processed. This will be recorded in the returned object. * @param data The data-stream from which to de-serialize the * message object. * @return The deserialized message object or @c NULL on failure. */ static OpTypedMessage* DeserializeData( int type, const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data); """)) text += render( """ }; %(endifs)s #endif // %(guard)s """, { "endifs": self.renderEndifs(self.defines), "guard": guard, }) + "\n" return text
def renderRequestDecode(self, command): text = "\n OP_STATUS status = OpStatus::OK;\n" if requiresAsyncResponse(command): text += ( self.indent( render( """ unsigned async_tag; status = InitAsyncCommand(msg, async_tag); // Needed for async requests, the response will use this info when request is done if (OpStatus::IsError(status)) { RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetInitAsyncCommandFailedText())); return status; } """ ), 2, ) + "\n" ) if command.message.isNonEmpty(): text += " %(requestMessage)s in;\n" % {"requestMessage": message_className(command.message)} if hasattr(command, "response") and command.response.isNonEmpty(): text += " %(responseMessage)s out;\n" % {"responseMessage": message_className(command.response)} text += "\n" if command.message.isNonEmpty(): text += ( self.indent( render( """ OpProtobufInstanceProxy in_proxy(%(requestMessage)s::GetMessageDescriptor(GetDescriptors()), &in); if (in_proxy.GetProtoMessage() == NULL) return OpStatus::ERR_NO_MEMORY; status = ParseMessage(client, msg, in_proxy); if (OpStatus::IsError(status)) { if (GetCommandError().GetStatus() == OpScopeTPHeader::OK) // Set a generic error if none was set by a parser RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetParseCommandMessageFailedText())); return status; } """, {"requestMessage": message_className(command.message)}, ), 2, ) + "\n\n" ) text += ( self.indent( render( """ status = %(commandCall)s; if (OpStatus::IsError(status)) { if (GetCommandError().GetStatus() == OpScopeTPHeader::OK) // Set a generic error if none was set by command """ ) % {"commandCall": request_functionCall(command)}, 2, ) + "\n" ) if requiresAsyncResponse(command): text += ( self.indent( render( """ { OP_STATUS tmp_status = SetCommandError(OpScopeTPHeader::InternalError, GetCommandExecutionFailedText()); OpStatus::Ignore(tmp_status); } // Remove the async command since the command failed to send an async response CleanupAsyncCommand(async_tag); """ ), 3, ) + "\n" ) else: text += " RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetCommandExecutionFailedText()));\n" text += " return status;\n" + " }\n" if hasattr(command, "response") and command.response.isNonEmpty(): text += ( "\n" + self.indent( render( """ OpProtobufInstanceProxy out_proxy(%(responseMessage)s::GetMessageDescriptor(GetDescriptors()), &out); if (out_proxy.GetProtoMessage() == NULL) return OpStatus::ERR_NO_MEMORY; RETURN_IF_ERROR(SendResponse(client, msg, out_proxy)); """, {"responseMessage": message_className(command.response)}, ), 2, ) + "\n" ) elif not requiresAsyncResponse(command): text += ( "\n" + self.indent( render( """ // The request does not define a response message so we send the default response which is an empty message OpProtobufInstanceProxy out_proxy(OpScopeDefaultMessage::GetMessageDescriptor(), &g_scope_manager->default_message_instance); if (out_proxy.GetProtoMessage() == NULL) return OpStatus::ERR_NO_MEMORY; status = SendResponse(client, msg, out_proxy); if (OpStatus::IsError(status)) { if (!IsResponseSent() && GetCommandError().GetStatus() == OpScopeTPHeader::OK) // Set a generic error if response sending failed or no error was set by response code RETURN_IF_ERROR(SetCommandError(OpScopeTPHeader::InternalError, GetCommandResponseFailedText())); return status; } """, {}, ), 2, ) + "\n" ) return text
def renderMessageImplementation(self, message): klass = message.cpp.opMessage() protoKlass = message.cpp.klass() message_gen = CppMessageGenerator(message, self.package.cpp.cppMessageSet().symbol()) message_gen.initMembers() message_gen.cpp_class_path = klass.symbol() members = "" for member in message_gen.redirect_members: if not member.is_inline: members += message_gen.renderFunctionImplementation(member) + "\n\n" text = render(""" %(classPath)s::~%(class)s() { } /* static */ %(classPath)s* %(classPath)s::Cast(const OpTypedMessage* msg) { OP_ASSERT(msg && msg->GetType() == Type); return static_cast<%(classPath)s*>(const_cast<OpTypedMessage*>(msg)); } /* static */ %(classPath)s* %(classPath)s::Deserialize( const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data) { OpProtobufInputStream stream; RETURN_VALUE_IF_ERROR(stream.Construct(data), NULL); %(classPathRelative)s *msg = %(classPathRelative)s::Create(src, dst, delay); if (!msg) return NULL; OpProtobufInstanceProxy instance(%(protoClassPath)s::GetMessageDescriptor(PROTOBUF_DESCRIPTOR(%(descriptorID)s)), &msg->protobuf_data); if (OpStatus::IsError(stream.Read(instance))) { OP_DELETE(msg); return NULL; } return msg; } OP_STATUS %(classPath)s::Serialize(OpData& data) const { OpProtobufOpDataOutputRange range(data); OpProtobufOutputStream stream(&range); %(protoClassPath)s *proto = const_cast<%(protoClassPath)s *>(&protobuf_data); void *proto_ptr = proto; OpProtobufInstanceProxy instance(%(protoClassPath)s::GetMessageDescriptor(PROTOBUF_DESCRIPTOR(%(descriptorID)s)), proto_ptr); return stream.Write(instance); } const char * %(classPath)s::GetTypeString() const { const OpProtobufMessage *d = %(protoClassPath)s::GetMessageDescriptor(PROTOBUF_DESCRIPTOR(%(descriptorID)s)); return d ? d->GetName() : NULL; } """, { "classPath": klass.symbol(), "classPathRelative": klass.symbol(relative=klass), "class": klass.name, "protoClassPath": protoKlass.symbol(), "globalModule": "g_%s" % self.options.module, "descriptorID": self.package.cpp.descriptorIdentifier(), }) text += members return text
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
def renderMessage(self, message): klass = message.cpp.opMessage() protobuf_klass = message.cpp.klass() message_gen = CppMessageGenerator(message, self.package.cpp.cppMessageSet().symbol()) message_gen.initMembers() members = "" for member in message_gen.redirect_members: members += self.indent(message_gen.renderFunctionDefinition(member, use_rtype_outer=True)) + "\n\n" all_args = message_gen.construct + message_gen.constructor all_args.sort(key=lambda i: i[0].default != None) args = "\n ".join([arg.declaration(relative=klass) + "," for arg, idx in all_args]) constructor_args = "\n ".join([", " + arg.declaration(relative=klass) for arg, idx in sorted(message_gen.constructor, key=lambda i: i[0].default != None)]) construct_args = "\n ".join([arg[0].declaration(relative=klass) + comma for arg, comma in commaList(sorted(message_gen.construct, key=lambda i: i[0].default != None))]) arg_call = ", ".join([arg.symbol(relative=klass) for arg, idx in sorted(message_gen.constructor, key=lambda i: i[0].default != None)]) arg_call_comma = arg_call and ", " + arg_call arg_call2 = ", ".join([arg.symbol(relative=klass) for arg, idx in sorted(message_gen.construct, key=lambda i: i[0].default != None)]) allocateDefs = "" if message.cpp.opMessageAlloc == AllocationStrategy.ALLOCATE_OPMEMORYPOOL: allocateDefs = render(""" /** Use OpMemoryPool allocation with OP_NEW */ OP_USE_MEMORY_POOL_DECL; """, { "class": klass.name }) + "\n" custom_create = "" default_create = "" need_default_create = not all_args if all_args: # See if we need a default Create() method with no args, if all args # to the custom Create() method have default values then it is not # needed for arg in all_args: if not arg[0].default: need_default_create = True break custom_create = self.indent(render(""" static %(class)s* Create( %(args)s const OpMessageAddress& src = OpMessageAddress(), const OpMessageAddress& dst = OpMessageAddress(), double delay = 0) { %(class)s *obj = OP_NEW(%(class)s, (src, dst, delay%(arg_call_comma)s)); if (obj) { if (OpStatus::IsSuccess(obj->Construct(%(arg_call2)s))) return obj; OP_DELETE(obj); } return NULL; } """, { "class": klass.name, "args": args, "arg_call2": arg_call2, "arg_call_comma": arg_call_comma, })) if need_default_create: makeCode = "OP_NEW(%(class)s, (src, dst, delay))" % { "class": klass.name, } default_create = self.indent(render(""" static %(class)s* Create() { OpMessageAddress src; OpMessageAddress dst; double delay = 0; return %(makeCode)s; } """, { "class": klass.name, "makeCode": makeCode, })) defaultConstructor = "" for arg in message_gen.constructor: if not arg[0].default: defaultConstructor = self.indent(render(""" %(class)s( const OpMessageAddress& src, const OpMessageAddress& dst, double delay ) : OpTypedMessage(Type, src, dst, delay) , protobuf_data() { } """, { "class": klass.name, })) break doc = "" if klass.doc: doc = klass.doc.toComment() + "\n" text = "" message_defines = message.cpp.defines() if message_defines: text += self.renderDefines(message_defines) + "\n" text = render(""" %(doc)sclass %(class)s : public OpTypedMessage { public: \t/** \t * The type for this message class. \t * \t * @note The reason this contains a integer value and not an enum \t * is to avoid uneccesary dependencies and helps avoid \t * re-compiles whenever a message is added, removed or renamed. \t */ \tstatic const unsigned Type = %(messageIdentifier)du; virtual ~%(class)s(); %(default_create)s static %(class)s* Create( const OpMessageAddress& src, const OpMessageAddress& dst = OpMessageAddress(), double delay = 0) { return OP_NEW(%(class)s, (src, dst, delay)); } %(custom_create)s static %(class)s* Cast(const OpTypedMessage* msg); static %(class)s* Deserialize( const OpMessageAddress& src, const OpMessageAddress& dst, double delay, const OpData& data); virtual OP_STATUS Serialize(OpData& data) const; virtual const char *GetTypeString() const; // Accessors/modifiers comes here %(members)s protected: %(allocateDefs)s %(class)s( const OpMessageAddress& src, const OpMessageAddress& dst, double delay %(constructor_args)s ) : OpTypedMessage(Type, src, dst, delay) , protobuf_data(%(arg_call)s) { } %(defaultConstructor)s OP_STATUS Construct( %(construct_args)s ) { return protobuf_data.Construct(%(arg_call2)s); } private: %(protobuf_class)s protobuf_data; }; """, { "class": klass.name, "protobuf_class": protobuf_klass.symbol(), "messageIdentifier": message.cpp.opMessageID, "doc": doc, "protobuf_message": "TODO: Fill in protobuf message here", "members": members, "args": args, "arg_call": arg_call, "arg_call_comma": arg_call_comma, "arg_call2": arg_call2, "constructor_args": constructor_args, "construct_args": construct_args, "default_create": default_create, "custom_create": custom_create, "defaultConstructor": defaultConstructor, "allocateDefs": self.indent(allocateDefs), }) + "\n" if message_defines: text += self.renderEndifs(message_defines) + "\n" return text