//------------------------------------------------------------------------------ // idlcodegenerator.cc // (C) 2006 Radon Labs GmbH //------------------------------------------------------------------------------ #include "stdneb.h" #include "tools/idlcompiler/idlcodegenerator.h" #include "io/ioserver.h" namespace Tools { __ImplementClass(Tools::IDLCodeGenerator, 'IDCG', Core::RefCounted); using namespace Util; using namespace IO; //------------------------------------------------------------------------------ /** */ IDLCodeGenerator::IDLCodeGenerator() { // empty } //------------------------------------------------------------------------------ /** */ URI IDLCodeGenerator::BuildHeaderUri() const { Util::String str = this->uri.AsString(); str.StripFileExtension(); str.Append(".h"); URI uri(str); return uri; } //------------------------------------------------------------------------------ /** */ URI IDLCodeGenerator::BuildSourceUri() const { Util::String str = this->uri.AsString(); str.StripFileExtension(); str.Append(".cc"); URI uri(str); return uri; } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::SetError(const char* fmt, ...) { va_list argList; va_start(argList, fmt); this->error.FormatArgList(fmt, argList); va_end(argList); } //------------------------------------------------------------------------------ /** */ bool IDLCodeGenerator::GenerateIncludeFile() { n_assert(this->uri.IsValid()); n_assert(this->document.isvalid()); // open header file URI uri = this->BuildHeaderUri(); Ptr stream = IoServer::Instance()->CreateStream(uri); stream->SetAccessMode(Stream::WriteAccess); if (stream->Open()) { Ptr writer = TextWriter::Create(); writer->SetStream(stream); if (writer->Open()) { this->WriteIncludeHeader(writer); this->WriteLibraryDeclarations(writer); this->WriteProtocolDeclarations(writer); this->WriteIncludeFooter(writer); writer->Close(); } else { n_printf("Could not open text writer on stream '%s'!\n", uri.AsString().AsCharPtr()); return false; } stream->Close(); } else { n_printf("Could not open stream '%s' for writing!\n", uri.AsString().AsCharPtr()); return false; } return true; } //------------------------------------------------------------------------------ /** */ bool IDLCodeGenerator::GenerateSourceFile() { n_assert(this->uri.IsValid()); n_assert(this->document.isvalid()); // open source file URI uri = this->BuildSourceUri(); Ptr stream = IoServer::Instance()->CreateStream(uri); stream->SetAccessMode(Stream::WriteAccess); if (stream->Open()) { Ptr writer = TextWriter::Create(); writer->SetStream(stream); if (writer->Open()) { this->WriteSourceHeader(writer); this->WriteLibraryImplementations(writer); this->WriteSourceFooter(writer); writer->Close(); } else { n_printf("Could not open text writer on stream '%s'!\n", uri.AsString().AsCharPtr()); return false; } stream->Close(); } else { n_printf("Could not open stream '%s' for writing!\n", uri.AsString().AsCharPtr()); return false; } return true; } //------------------------------------------------------------------------------ /** Converts a IDL type string into a Nebula C++ reference type. OBSOLETE??? -> old math types? */ String IDLCodeGenerator::GetNebulaRefType(const String& type) const { if ("string" == type) return "const Util::String&"; else if ("vector3" == type) return "const Math::vector3&"; else if ("vector4" == type) return "const Math::vector4&"; else if ("matrix44" == type) return "const Math::matrix44&"; else if ("bool" == type) return "bool"; else if ("guid" == type) return "const Util::Guid&"; else if ("int" == type) return "int"; else if ("intArray" == type) return "const Util::Array&"; else if ("floatArray" == type) return "const Util::Array&"; else if ("boolArray" == type) return "const Util::Array&"; else if ("stringArray" == type) return "const Util::Array&"; else if ("vector3Array" == type) return "const Util::Array&"; else if ("vector4Array" == type) return "const Util::Array&"; else if ("matrix44Array" == type) return "const Util::Array&"; else if ("guidArray" == type) return "const Util::Array&"; else { n_error("Invalid IDL type '%s'!", type.AsCharPtr()); return ""; } } //------------------------------------------------------------------------------ /** Converts a IDL type string into a Nebula C++ type. OBSOLETE??? -> old math types? */ String IDLCodeGenerator::GetNebulaType(const String& type) const { if ("string" == type) return "Util::String"; else if ("vector3" == type) return "Math::vector3"; else if ("vector4" == type) return "Math::vector4"; else if ("matrix44" == type) return "Math::matrix44"; else if ("bool" == type) return "bool"; else if ("guid" == type) return "Util::Guid"; else if ("int" == type) return "int"; else if ("intArray" == type) return "Util::Array"; else if ("floatArray" == type) return "Util::Array"; else if ("boolArray" == type) return "Util::Array"; else if ("stringArray" == type) return "Util::Array"; else if ("vector3Array" == type) return "Util::Array"; else if ("vector4Array" == type) return "Util::Array"; else if ("matrix44Array" == type) return "Util::Array"; else if ("guidArray" == type) return "Util::Array"; else { n_error("Invalid IDL type '%s'!", type.AsCharPtr()); return ""; } } //------------------------------------------------------------------------------ /** Converts a IDL type string into a Nebula C++ type. OBSOLETE??? -> old math types? */ String IDLCodeGenerator::GetNebulaArgType(const String& type) const { if ("string" == type) return "Scripting::Arg::String"; else if ("vector3" == type) return "Scripting::Arg::Vector3"; else if ("vector4" == type) return "Scripting::Arg::Vector4"; else if ("matrix44" == type) return "Scripting::Arg::Matrix44"; else if ("bool" == type) return "Scripting::Arg::Bool"; else if ("guid" == type) return "Scripting::Arg::Guid"; else if ("int" == type) return "Scripting::Arg::Int"; else if ("intArray" == type) return "Scripting::Arg::IntArray"; else if ("floatArray" == type) return "Scripting::Arg::FloatArray"; else if ("boolArray" == type) return "Scripting::Arg::BoolArray"; else if ("stringArray" == type) return "Scripting::Arg::StringArray"; else if ("vector3Array" == type) return "Scripting::Arg::Vector3Array"; else if ("vector4Array" == type) return "Scripting::Arg::Vector4Array"; else if ("matrix44Array" == type) return "Scripting::Arg::Matrix44Array"; else if ("guidArray" == type) return "Scripting::Arg::GuidArray"; else { n_error("Invalid IDL type '%s'!", type.AsCharPtr()); return ""; } } //------------------------------------------------------------------------------ /** Converts a IDL type string into a Nebula getter method name. OBSOLETE??? -> old math types? */ String IDLCodeGenerator::GetNebulaGetterMethod(const String& type) const { if ("string" == type) return "GetString()"; else if ("vector3" == type) return "GetVector3()"; else if ("vector4" == type) return "GetVector4()"; else if ("matrix44" == type) return "GetMatrix44()"; else if ("bool" == type) return "GetBool()"; else if ("guid" == type) return "GetGuid()"; else if ("int" == type) return "GetInt()"; else if ("intArray" == type) return "GetIntArray()"; else if ("floatArray" == type) return "GetFloatArray()"; else if ("boolArray" == type) return "GetBoolArray()"; else if ("stringArray" == type) return "GetStringArray()"; else if ("vector3Array" == type) return "GetVector3Array()"; else if ("vector4Array" == type) return "GetVector4Array()"; else if ("matrix44Array" == type) return "GetMatrix44Array()"; else if ("guidArray" == type) return "GetGuidArray"; else { n_error("Invalid IDL type '%s'!", type.AsCharPtr()); return ""; } } //------------------------------------------------------------------------------ /** Converts a IDL type string into a Nebula setter method name. OBSOLETE??? -> old math types? */ String IDLCodeGenerator::GetNebulaSetterMethod(const String& type) const { if ("string" == type) return "SetString"; else if ("vector3" == type) return "SetVector3"; else if ("vector4" == type) return "SetVector4"; else if ("matrix44" == type) return "SetMatrix44"; else if ("bool" == type) return "SetBool"; else if ("guid" == type) return "SetGuid"; else if ("int" == type) return "SetInt"; else if ("intArray" == type) return "SetIntArray"; else if ("floatArray" == type) return "SetFloatArray"; else if ("boolArray" == type) return "SetBoolArray"; else if ("stringArray" == type) return "SetStringArray"; else if ("vector3Array" == type) return "SetVector3Array"; else if ("vector4Array" == type) return "SetVector4Array"; else if ("matrix44Array" == type) return "SetMatrix44Array"; else if ("guidArray" == type) return "SetGuidArray"; else { n_error("Invalid IDL type '%s'!", type.AsCharPtr()); return ""; } } //------------------------------------------------------------------------------ /** */ String IDLCodeGenerator::BuildCallbackPrototype(IDLCommand* cmd, bool withClassName) const { const Util::Array> inArgs = cmd->GetInputArgs(); const Util::Array> outArgs = cmd->GetOutputArgs(); n_assert(outArgs.Size() <= 1); String str; if (outArgs.Size() > 0) { str.Append(this->GetNebulaType(outArgs[0]->GetType())); } else { str.Append("void"); } str.Append(" "); if (withClassName) { str.Append(cmd->GetName()); str.Append("::"); } str.Append("Callback("); IndexT inArgIndex; for (inArgIndex = 0; inArgIndex < inArgs.Size(); inArgIndex++) { str.Append(this->GetNebulaRefType(inArgs[inArgIndex]->GetType())); str.Append(" "); str.Append(inArgs[inArgIndex]->GetName()); if (inArgIndex < (inArgs.Size() - 1)) { str.Append(", "); } } str.Append(")"); return str; } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteIncludeHeader(TextWriter* writer) const { n_assert(0 != writer); writer->WriteLine("#pragma once"); writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("/**"); writer->WriteLine(" This file was generated with Nebula3's idlc compiler tool."); writer->WriteLine(" DO NOT EDIT"); writer->WriteLine("*/"); if (!this->document->GetLibraries().IsEmpty()) { writer->WriteLine("#include \"scripting/command.h\""); } if (!this->document->GetProtocols().IsEmpty()) { if (this->document->GetProtocols()[0]->IsMangalore()) { // Mangalore messages are derived from Message::Msg writer->WriteLine("#include \"message/msg.h\""); } else { writer->WriteLine("#include \"messaging/message.h\""); } } // write dependencies const Array>& libs = this->document->GetLibraries(); IndexT libIndex; for (libIndex = 0; libIndex < libs.Size(); libIndex++) { const Ptr& curLib = libs[libIndex]; IndexT depIndex; for (depIndex = 0; depIndex < curLib->GetDependencies().Size(); depIndex++) { IDLDependency* dep = curLib->GetDependencies()[depIndex]; writer->WriteFormatted("#include \"%s\"\n", dep->GetHeader().AsCharPtr()); } } const Array>& protocols = this->document->GetProtocols(); IndexT protIndex; for (protIndex = 0; protIndex < protocols.Size(); protIndex++) { const Ptr& curProt = protocols[protIndex]; IndexT depIndex; for (depIndex = 0; depIndex < curProt->GetDependencies().Size(); depIndex++) { IDLDependency* dep = curProt->GetDependencies()[depIndex]; writer->WriteFormatted("#include \"%s\"\n", dep->GetHeader().AsCharPtr()); } } writer->WriteLine(""); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteLibraryDeclarations(TextWriter* writer) const { n_assert(0 != writer); if (!this->document->GetLibraries().IsEmpty()) { writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("namespace Commands"); writer->WriteLine("{"); // for each library definition... const Array>& libs = this->document->GetLibraries(); IndexT libIndex; SizeT numLibs = libs.Size(); for (libIndex = 0; libIndex < numLibs; libIndex++) { IDLLibrary* curLib = libs[libIndex]; // write library class definition writer->WriteFormatted("class %s\n", curLib->GetName().AsCharPtr()); writer->WriteLine("{"); writer->WriteLine("public:"); writer->WriteLine(" /// register commands"); writer->WriteLine(" static void Register();"); writer->WriteLine("};"); // for each command in the library... const Array>& cmds = curLib->GetCommands(); IndexT cmdIndex; SizeT numCmds = cmds.Size(); for (cmdIndex = 0; cmdIndex < numCmds; cmdIndex++) { this->WriteCommandDeclaration(cmds[cmdIndex], writer); } } writer->WriteLine("} // namespace Commands"); } } //------------------------------------------------------------------------------ /** FIXME: hmm, enable different namespaces for message protocols? */ void IDLCodeGenerator::WriteProtocolDeclarations(TextWriter* writer) const { n_assert(0 != writer); if (!this->document->GetProtocols().IsEmpty()) { // for each protocol definition... const Array>& protocols = this->document->GetProtocols(); IndexT protocolIndex; SizeT numProtocols = protocols.Size(); for (protocolIndex = 0; protocolIndex < numProtocols; protocolIndex++) { IDLProtocol* curProtocol = protocols[protocolIndex]; writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteFormatted("namespace %s\n", curProtocol->GetNameSpace().AsCharPtr()); writer->WriteLine("{"); // for each message in the protocol: const Array>& msgs = curProtocol->GetMessages(); IndexT msgIndex; for (msgIndex = 0; msgIndex < msgs.Size(); msgIndex++) { this->WriteMessageDeclaration(curProtocol, msgs[msgIndex], writer); } writer->WriteFormatted("} // namespace %s\n", curProtocol->GetNameSpace().AsCharPtr()); } } } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteCommandDeclaration(IDLCommand* cmd, TextWriter* writer) const { n_assert(0 != cmd); n_assert(0 != writer); writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteFormatted("class %s : public Scripting::Command\n", cmd->GetName().AsCharPtr()); writer->WriteLine("{"); writer->WriteFormatted(" __DeclareClass(%s);\n", cmd->GetName().AsCharPtr()); writer->WriteLine("public:"); writer->WriteLine(" virtual void OnRegister();"); writer->WriteLine(" virtual bool OnExecute();"); writer->WriteLine(" virtual Util::String GetHelp() const;"); writer->WriteLine("private:"); writer->WriteLine(" " + this->BuildCallbackPrototype(cmd, false) + ";"); writer->WriteLine("};"); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteMessageDeclaration(IDLProtocol* prot, IDLMessage* msg, TextWriter* writer) const { n_assert(0 != prot); n_assert(0 != msg); n_assert(0 != writer); // build parent class name String parentClass = msg->GetParentClass(); n_assert(parentClass.IsValid()); writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteFormatted("class %s : public %s\n", msg->GetName().AsCharPtr(), parentClass.AsCharPtr()); writer->WriteLine("{"); if (prot->IsMangalore()) { writer->WriteFormatted(" DeclareClass(%s);\n", msg->GetName().AsCharPtr()); writer->WriteLine(" DeclareMsgId;"); } else { writer->WriteFormatted(" __DeclareClass(%s);\n", msg->GetName().AsCharPtr()); writer->WriteLine(" __DeclareMsgId;"); } writer->WriteLine("public:"); // write constructor String initList; Array> args = msg->GetInputArgs(); args.AppendArray(msg->GetOutputArgs()); IndexT i; for (i = 0; i < args.Size(); i++) { if (args[i]->GetDefaultValue().IsValid()) { if (!initList.IsEmpty()) { initList.Append(",\n"); } String argMemberName = args[i]->GetName(); argMemberName.ToLower(); initList.Append(" "); initList.Append(argMemberName); initList.Append("("); initList.Append(args[i]->GetDefaultValue()); initList.Append(")"); } } writer->WriteFormatted(" %s() %s\n", msg->GetName().AsCharPtr(), initList.IsValid() ? ":" : ""); if (initList.IsValid()) { writer->WriteString(initList); writer->WriteLine(""); } writer->WriteLine(" { };"); // write input args const Array>& inArgs = msg->GetInputArgs(); IndexT argIndex; for (argIndex = 0; argIndex < inArgs.Size(); argIndex++) { this->WriteMessageArg(prot, msg, inArgs[argIndex], writer, true); } // write output args const Array>& outArgs = msg->GetOutputArgs(); for (argIndex = 0; argIndex < outArgs.Size(); argIndex++) { this->WriteMessageArg(prot, msg, outArgs[argIndex], writer, false); } // write encode and decode if (!prot->IsMangalore()) { this->WriteEncodeImplementation(msg, writer); this->WriteDecodeImplementation(msg, writer); } writer->WriteLine("};"); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteMessageArg(IDLProtocol* prot, IDLMessage* msg, IDLArg* arg, TextWriter* writer, bool isInputArg) const { n_assert(0 != arg); n_assert(0 != writer); // build some string which are needed multiple times String argMemberName = arg->GetName(); argMemberName.ToLower(); String argTypeString; if ((arg->GetType().FindStringIndex("::") != InvalidIndex) && (arg->GetType().FindStringIndex("*") == InvalidIndex)) { // a complex type, pass by reference argTypeString.Append("const "); argTypeString.Append(arg->GetType()); argTypeString.Append("&"); } else { // a simple builtin type argTypeString = arg->GetType(); } // write setter String str; str.Append("public:\n"); str.Append(" void Set"); str.Append(arg->GetName()); str.Append("("); str.Append(argTypeString); str.Append(" val)\n"); str.Append(" {\n"); if (!prot->IsMangalore()) { str.Append(" n_assert(!this->handled);\n"); } str.Append(" this->"); str.Append(argMemberName); str.Append(" = val;\n"); str.Append(" };\n"); // write getter str.Append(" "); str.Append(argTypeString); str.Append(" Get"); str.Append(arg->GetName()); str.Append("() const\n"); str.Append(" {\n"); if ((!isInputArg) && (!prot->IsMangalore())) { str.Append(" n_assert(this->handled);\n"); } str.Append(" return this->"); str.Append(argMemberName); str.Append(";\n"); str.Append(" };\n"); // write member str.Append("private:\n"); str.Append(" "); str.Append(arg->GetType()); str.Append(" "); str.Append(argMemberName); str.Append(";\n"); // write setter, getter and member to TextWriter writer->WriteString(str); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteIncludeFooter(TextWriter* writer) const { n_assert(0 != writer); writer->WriteLine("//------------------------------------------------------------------------------"); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteSourceHeader(TextWriter* writer) const { n_assert(0 != writer); writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("// MACHINE GENERATED, DON'T EDIT!"); writer->WriteLine("//------------------------------------------------------------------------------"); URI headerUri = this->BuildHeaderUri(); String headerFile = headerUri.AsString().ExtractFileName(); writer->WriteLine("#include \"stdneb.h\""); if (!this->document->GetLibraries().IsEmpty()) { writer->WriteLine("#include \"scripting/scriptserver.h\""); writer->WriteLine("#include \"scripting/arg.h\""); } writer->WriteFormatted("#include \"%s\"\n", headerFile.AsCharPtr()); writer->WriteLine(""); // write __ImplementClass macros if (!this->document->GetLibraries().IsEmpty()) { const Array>& libs = this->document->GetLibraries(); IndexT libIndex; for (libIndex = 0; libIndex < libs.Size(); libIndex++) { const Ptr& curLib = libs[libIndex]; IndexT cmdIndex; for (cmdIndex = 0; cmdIndex < curLib->GetCommands().Size(); cmdIndex++) { const Ptr& cmd = curLib->GetCommands()[cmdIndex]; writer->WriteFormatted("__ImplementClass(Commands::%s, '%s', Scripting::Command);\n", cmd->GetName().AsCharPtr(), cmd->GetFourCC().AsCharPtr()); } } } if (!this->document->GetProtocols().IsEmpty()) { const Array>& protocols = this->document->GetProtocols(); IndexT protIndex; for (protIndex = 0; protIndex < protocols.Size(); protIndex++) { const Ptr& curProt = protocols[protIndex]; writer->WriteFormatted("namespace %s\n", curProt->GetNameSpace().AsCharPtr()); writer->WriteLine("{"); IndexT msgIndex; for (msgIndex = 0; msgIndex < curProt->GetMessages().Size(); msgIndex++) { const Ptr& msg = curProt->GetMessages()[msgIndex]; if (curProt->IsMangalore()) { writer->WriteFormatted(" ImplementClass(%s::%s, %s);\n", curProt->GetNameSpace().AsCharPtr(), msg->GetName().AsCharPtr(), msg->GetParentClass().AsCharPtr()); writer->WriteFormatted(" ImplementMsgId(%s);\n", msg->GetName().AsCharPtr()); } else { writer->WriteFormatted(" __ImplementClass(%s::%s, '%s', %s);\n", curProt->GetNameSpace().AsCharPtr(), msg->GetName().AsCharPtr(), msg->GetFourCC().AsCharPtr(), msg->GetParentClass().AsCharPtr()); writer->WriteFormatted(" __ImplementMsgId(%s);\n", msg->GetName().AsCharPtr()); } } writer->WriteFormatted("} // %s\n", curProt->GetNameSpace().AsCharPtr()); } } writer->WriteLine(""); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteSourceFooter(TextWriter* writer) const { n_assert(0 != writer); writer->WriteLine("//------------------------------------------------------------------------------"); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteLibraryImplementations(TextWriter* writer) const { n_assert(0 != writer); writer->WriteLine("namespace Commands"); writer->WriteLine("{"); // for each library definition... const Array>& libs = this->document->GetLibraries(); IndexT libIndex; SizeT numLibs = libs.Size(); for (libIndex = 0; libIndex < numLibs; libIndex++) { IDLLibrary* curLib = libs[libIndex]; writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("/**"); writer->WriteLine("*/"); writer->WriteLine("void"); writer->WriteFormatted("%s::Register()\n", curLib->GetName().AsCharPtr()); writer->WriteLine("{"); writer->WriteLine(" Scripting::ScriptServer* scriptServer = Scripting::ScriptServer::Instance();"); IndexT cmdIndex; for (cmdIndex = 0; cmdIndex < curLib->GetCommands().Size(); cmdIndex++) { IDLCommand* cmd = curLib->GetCommands()[cmdIndex]; String scriptCommandName = cmd->GetName(); scriptCommandName.ToLower(); writer->WriteFormatted(" scriptServer->RegisterCommand(\"%s\", %s::Create());\n", scriptCommandName.AsCharPtr(), cmd->GetName().AsCharPtr()); } writer->WriteLine("}"); writer->WriteLine(""); // write command implementations for (cmdIndex = 0; cmdIndex < curLib->GetCommands().Size(); cmdIndex++) { IDLCommand* cmd = curLib->GetCommands()[cmdIndex]; this->WriteCommandImplementation(cmd, writer); } } writer->WriteLine("} // namespace Commands"); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteCommandImplementation(IDLCommand* cmd, TextWriter* writer) const { n_assert(0 != cmd); n_assert(0 != writer); // OnRegister() writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("/**"); writer->WriteLine("*/"); writer->WriteLine("void"); writer->WriteFormatted("%s::OnRegister()\n", cmd->GetName().AsCharPtr()); writer->WriteLine("{"); writer->WriteLine(" Scripting::Command::OnRegister();"); IndexT inArgIndex; for (inArgIndex = 0; inArgIndex < cmd->GetInputArgs().Size(); inArgIndex++) { IDLArg* arg = cmd->GetInputArgs()[inArgIndex]; writer->WriteFormatted(" this->args.AddArg(\"%s\", %s);\n", arg->GetName().AsCharPtr(), this->GetNebulaArgType(arg->GetType()).AsCharPtr()); } IndexT outArgIndex; for (outArgIndex = 0; outArgIndex < cmd->GetOutputArgs().Size(); outArgIndex++) { IDLArg* arg = cmd->GetOutputArgs()[outArgIndex]; writer->WriteFormatted(" this->results.AddArg(\"%s\", %s);\n", arg->GetName().AsCharPtr(), this->GetNebulaArgType(arg->GetType()).AsCharPtr()); } writer->WriteLine("}"); writer->WriteLine(""); // GetHelp() writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("/**"); writer->WriteLine("*/"); writer->WriteLine("Util::String"); writer->WriteFormatted("%s::GetHelp() const\n", cmd->GetName().AsCharPtr()); writer->WriteLine("{"); writer->WriteFormatted(" return \"%s\";\n", cmd->GetDesc().AsCharPtr()); writer->WriteLine("}"); // OnExecute() writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("/**"); writer->WriteLine("*/"); writer->WriteLine("bool"); writer->WriteFormatted("%s::OnExecute()\n", cmd->GetName().AsCharPtr()); writer->WriteLine("{"); // marshal input args for (inArgIndex = 0; inArgIndex < cmd->GetInputArgs().Size(); inArgIndex++) { IDLArg* arg = cmd->GetInputArgs()[inArgIndex]; writer->WriteFormatted(" %s %s = this->args.GetArgValue(%d).%s;\n", this->GetNebulaRefType(arg->GetType()).AsCharPtr(), arg->GetName().AsCharPtr(), inArgIndex, this->GetNebulaGetterMethod(arg->GetType()).AsCharPtr()); } // generate callback method call String str; str.Append(" "); if (cmd->GetOutputArgs().Size() > 0) { str.Append(this->GetNebulaType(cmd->GetOutputArgs()[0]->GetType())); str.Append(" "); str.Append(cmd->GetOutputArgs()[0]->GetName()); str.Append(" = "); } str.Append("this->Callback("); for (inArgIndex = 0; inArgIndex < cmd->GetInputArgs().Size(); inArgIndex++) { IDLArg* arg = cmd->GetInputArgs()[inArgIndex]; str.Append(arg->GetName().AsCharPtr()); if (inArgIndex < (cmd->GetInputArgs().Size() - 1)) { str.Append(", "); } } str.Append(");"); writer->WriteLine(str); // optionally set result if (cmd->GetOutputArgs().Size() > 0) { IDLArg* arg = cmd->GetOutputArgs()[0]; writer->WriteFormatted(" this->results.ArgValue(0).%s(%s);\n", this->GetNebulaSetterMethod(arg->GetType()).AsCharPtr(), arg->GetName().AsCharPtr()); } writer->WriteLine(" return true;"); writer->WriteLine("}"); writer->WriteLine(""); // Callback() method writer->WriteLine("//------------------------------------------------------------------------------"); writer->WriteLine("/**"); writer->WriteLine("*/"); writer->WriteLine(this->BuildCallbackPrototype(cmd, true)); writer->WriteLine("{"); writer->WriteLine(cmd->GetCode()); writer->WriteLine("}"); writer->WriteLine(""); } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteEncodeImplementation(IDLMessage* msg, IO::TextWriter* writer) const { String str; str.Append("public:\n"); str.Append(" void Encode"); str.Append("(const Ptr& writer)\n"); str.Append(" {\n"); bool writeString = false; // check all input args const Array>& inArgs = msg->GetInputArgs(); IndexT argIndex; for (argIndex = 0; argIndex < inArgs.Size(); argIndex++) { if (inArgs[argIndex]->IsSerialized()) { String type = inArgs[argIndex]->GetType(); // remove possible namespace IndexT namespaceIdx = type.FindCharIndex(':', 0); if (InvalidIndex != namespaceIdx) { type = type.ExtractToEnd(namespaceIdx+2); } type = this->ConvertToCamelNotation(type); // check valid type if (!IDLArg::IsValidType(type)) { n_error("Message %s, type %s not valid for serialization!!!", msg->GetName().AsCharPtr(), type.AsCharPtr()); } String name = inArgs[argIndex]->GetName(); str.Append(" writer->Write" + type + "(this->Get" + name + "());\n"); writeString = true; } } // call subclass encode function if (writeString && msg->GetParentClass().IsValid()) { str.Append(" " + msg->GetParentClass() + "::Encode(writer);\n"); } str.Append(" };\n"); if (writeString) { writer->WriteString(str); } } //------------------------------------------------------------------------------ /** */ void IDLCodeGenerator::WriteDecodeImplementation(IDLMessage* msg, IO::TextWriter* writer) const { String str; str.Append("public:\n"); str.Append(" void Decode"); str.Append("(const Ptr& reader)\n"); str.Append(" {\n"); bool writeString = false; // check all input args const Array>& inArgs = msg->GetInputArgs(); IndexT argIndex; for (argIndex = 0; argIndex < inArgs.Size(); argIndex++) { if (inArgs[argIndex]->IsSerialized()) { String type = inArgs[argIndex]->GetType(); // remove possible namespace IndexT namespaceIdx = type.FindCharIndex(':', 0); if (InvalidIndex != namespaceIdx) { type = type.ExtractToEnd(namespaceIdx+2); } type = this->ConvertToCamelNotation(type); // check valid type if (!IDLArg::IsValidType(type)) { n_error("Message %s, type %s not valid for serialization!!!", msg->GetName().AsCharPtr(), type.AsCharPtr()); } String name = inArgs[argIndex]->GetName(); str.Append(" this->Set" + name + "(reader->Read" + type + "());\n"); writeString = true; } } // call subclass encode function if (writeString && msg->GetParentClass().IsValid()) { str.Append(" " + msg->GetParentClass() + "::Decode(reader);\n"); } str.Append(" };\n"); if (writeString) { writer->WriteString(str); } } //------------------------------------------------------------------------------ /** */ Util::String IDLCodeGenerator::ConvertToCamelNotation(const Util::String& lowerCaseType) const { if (lowerCaseType == "char") return "Char"; else if (lowerCaseType == "float") return "Float"; else if (lowerCaseType == "int") return "Int"; else if (lowerCaseType == "uint") return "UInt"; else if (lowerCaseType == "bool") return "Bool"; else if (lowerCaseType == "double") return "Double"; else if (lowerCaseType == "short") return "Short"; else if (lowerCaseType == "ushort") return "UShort"; else if (lowerCaseType == "string" || lowerCaseType == "String") return "String"; // class names are uppercase else if (lowerCaseType == "matrix44" || lowerCaseType == "Matrix44") return "Matrix44"; else if (lowerCaseType == "float2" || lowerCaseType == "Float2") return "Float2"; else if (lowerCaseType == "float4" || lowerCaseType == "Float4") return "Float4"; else if (lowerCaseType == "point" || lowerCaseType == "Point") return "Point"; else if (lowerCaseType == "vector" || lowerCaseType == "Vector") return "Vector"; else if (lowerCaseType == "blob" || lowerCaseType == "Blob") return "Blob"; else if (lowerCaseType == "guid" || lowerCaseType == "Guid") return "Guid"; n_error("Invalid type %s", lowerCaseType.AsCharPtr()); return ""; } } // namespace Tools