using System; using System.Text; using System.IO; using System.Collections.Generic; namespace spgen { public class CPPGenerator : GeneratorBase { static string[] CPP_TYPE_NAMES = new string[] { "bool", "short", "unsigned short", "char", "unsigned char", "int", "unsigned int", "int64_t", "u__int64_t", "double", "float", "CSimpleStringA", "CSimpleStringW", "CBlob", // blob "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", "CAutoArray", }; static string GetCodeType(ParamType type) { return CPP_TYPE_NAMES[(int)type]; } public override void GenerateCode(string dir, Entity entity, bool inSourceDir) { if (!inSourceDir) dir = Path.Combine(dir, "generate"); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); string deffilename = string.Format("{0}_def_g.h", entity.Name); string deffilepath = Path.Combine(dir, deffilename); GenerateDef(deffilepath, deffilename, entity); if (entity.ClassList.Count > 0) { string serverfile = string.Format("{0}_server_g.h", entity.Name); serverfile = Path.Combine(dir, serverfile); GenerateServer(deffilename, serverfile, entity); string clientfile = string.Format("{0}_client_g.h", entity.Name); clientfile = Path.Combine(dir, clientfile); GenerateClient(deffilename, clientfile, entity); } if (entity.MsgList.Count > 0) { string msgfile = string.Format("{0}_msg_g.h", entity.Name); msgfile = Path.Combine(dir, msgfile); GenerateMsg(msgfile, entity); } } string GetMethodEnumName(Entity entity, EntityClass cls, Method m) { return string.Format("{0}_Method_{1}", cls.Name, m.Name); } string GetMethodSignatureEnumName(Entity entity, EntityClass cls, Method m) { return string.Format("{0}_MethodSignature_{1}", cls.Name, m.Name); } void WriteConst(StreamWriter sw, Entity entity) { sw.WriteLine("//"); sw.WriteLine("// const goes here"); sw.WriteLine("//"); foreach (ConstItem i in entity.ConstList) { WriteLineDefine(sw, entity, i.Name, i.Value.ToString()); } sw.WriteLine(); } void WriteLineDefine(StreamWriter sw, Entity entity, string name, string num, bool tryReplace = true) { string value = ""; if (tryReplace && entity.defineDic.TryGetValue(name, out value)) { //success ,judge if len > 3, len > 3, replace the new value; len <=3, must the same if (value.Length > 3) num = value; else { if (num != value) { Console.WriteLine("sequence changed ,failed!! {0}, {1}", name, num); Environment.Exit(-1); } } } sw.WriteLine("#define {0} {1}", name, num); } void WriteMethodEnum(StreamWriter sw, Entity entity, EntityClass cls) { foreach (Method m in cls.MethodList) { if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; WriteLineDefine(sw, entity, string.Format("{0}_Method_{1}", cls.Name, subscribe.Name), subscribe.Id.ToString()); WriteLineDefine(sw, entity, string.Format("{0}_Method_{1}", cls.Name, subscribe.Cancel.Name), subscribe.Cancel.Id.ToString()); WriteLineDefine(sw, entity, string.Format("{0}_Method_{1}", cls.Name, subscribe.Message.Name), subscribe.Message.Id.ToString()); } else { WriteLineDefine(sw, entity, string.Format("{0}_Method_{1}", cls.Name, m.Name), m.Id.ToString()); } } sw.WriteLine(); } bool WriteLogCode(StreamWriter sw, Entity entity, EntityClass cls) { if (!Entity.entityDic.ContainsKey(entity.Name)) return false; foreach (Method m in cls.MethodList) { if (typeof(Subscribe).IsInstanceOfType(m)) { continue; } else { if (m.Id > 256) m.Id = 99; string nameStr = string.Format("{0}_LogCode_{1}", cls.Name, m.Name); string defineStr = string.Format("\"QLR0402{0}{1}\"", Entity.entityDic[entity.Name], m.Id.ToString("D2")); WriteLineDefine(sw, entity, nameStr, defineStr, false); } } sw.WriteLine(); return true; } void WriteMethodSignatureEnum(StreamWriter sw, Entity entity, EntityClass cls) { foreach (Method m in cls.MethodList) { if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; WriteLineDefine(sw, entity, string.Format("{0}_MethodSignature_{1}", cls.Name, subscribe.Name), subscribe.Signature.ToString()); WriteLineDefine(sw, entity, string.Format("{0}_MethodSignature_{1}", cls.Name, subscribe.Cancel.Name), subscribe.Cancel.Signature.ToString()); WriteLineDefine(sw, entity, string.Format("{0}_MethodSignature_{1}", cls.Name, subscribe.Message.Name), subscribe.Message.Signature.ToString()); } else { WriteLineDefine(sw, entity, string.Format("{0}_MethodSignature_{1}", cls.Name, m.Name), m.Signature.ToString()); } } sw.WriteLine(); } void WriteStruct(StreamWriter sw, string name, List ParamList) { sw.WriteLine("struct {0}", name); sw.WriteLine("{"); foreach (Param i in ParamList) { sw.WriteLine("\t{0} {1};", GetCodeType(i.Type), i.Name); } sw.WriteLine(); sw.WriteLine("\tvoid Serialize(SpBuffer &Buf)"); sw.WriteLine("\t{"); if (ParamList.Count > 0) { sw.Write("\t\tauto & buf = Buf"); foreach (Param i in ParamList) { sw.Write(" & {0}", i.Name); } sw.WriteLine(";"); } sw.WriteLine("\t}"); sw.WriteLine(""); sw.WriteLine("};"); } string GetInfoStructName(Entity entity, EntityClass cls, Method m) { return string.Format("{0}_{1}_Info", cls.Name, m.Name); } string GetReqStructName(Entity entity, EntityClass cls, Method m) { return string.Format("{0}_{1}_Req", cls.Name, m.Name); } string GetAnsStructName(Entity entity, EntityClass cls, Method m) { return string.Format("{0}_{1}_Ans", cls.Name, m.Name); } string GetSubStructName(Entity entity, EntityClass cls, Method m) { return string.Format("{0}_{1}_Sub", cls.Name, m.Name); } void WriteMethodParam(StreamWriter sw, Entity entity, EntityClass cls) { foreach (Method m in cls.MethodList) { if (typeof(Oneway).IsInstanceOfType(m)) { Oneway oneway = m as Oneway; string iname = GetInfoStructName(entity, cls, m); WriteStruct(sw, iname, oneway.InfoParamList); sw.WriteLine(); } else if (typeof(Twoway).IsInstanceOfType(m)) { Twoway twoway = m as Twoway; string reqname = GetReqStructName(entity, cls, m); WriteStruct(sw, reqname, twoway.ReqParamList); sw.WriteLine(); string ansname = GetAnsStructName(entity, cls, m); WriteStruct(sw, ansname, twoway.ResParamList); sw.WriteLine(); } else if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; string subname = GetSubStructName(entity, cls, m); WriteStruct(sw, subname, subscribe.SubParamList); sw.WriteLine(); string canname = GetInfoStructName(entity, cls, subscribe.Cancel); WriteStruct(sw, canname, subscribe.Cancel.InfoParamList); sw.WriteLine(); string msgname = GetInfoStructName(entity, cls, subscribe.Message); WriteStruct(sw, msgname, subscribe.Message.InfoParamList); sw.WriteLine(); } else { throw new Exception("unknown"); } } } void GenerateDef(string file, string file_name, Entity entity) { using (StreamWriter sw = new StreamWriter(file, false, Encoding.GetEncoding("gb2312"))) { string guard_marco = string.Format("__{0}", file_name.Replace('.', '_').ToUpper()); sw.WriteLine("#ifndef " + guard_marco); sw.WriteLine("#define " + guard_marco); sw.WriteLine(); sw.WriteLine("#pragma once"); sw.WriteLine(); sw.WriteLine("// This code is generated by spgen tool!"); sw.WriteLine(); sw.WriteLine("#include \"SpHelper.h\""); sw.WriteLine(); sw.WriteLine("namespace {0} {{", entity.Name); WriteConst(sw, entity); foreach (EntityClass cls in entity.ClassList) { WriteMethodEnum(sw, entity, cls); WriteMethodSignatureEnum(sw, entity, cls); WriteLogCode(sw, entity, cls); WriteMethodParam(sw, entity, cls); sw.WriteLine(); sw.WriteLine("///////////////////////////"); sw.WriteLine(); } sw.WriteLine("}} // namespace {0}", entity.Name); sw.WriteLine(); sw.WriteLine(string.Format("#endif // {0}", guard_marco)); } } void WriteServerConstructor(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\t{0}()", GetServerClassName(entity, cls)); sw.WriteLine("\t{"); sw.WriteLine("\t\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteServerDestructor(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tvirtual ~{0}()", GetServerClassName(entity, cls)); sw.WriteLine("\t{"); sw.WriteLine("\t\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteSeverIsExclusive(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tvirtual bool IsExclusive() {{ return {0}; }}", cls.Exclusive.ToString().ToLower()); sw.WriteLine(); } void WriteServerGetMessageAttr(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tvirtual ErrorCodeEnum GetMessageAttr(DWORD dwMessageID, DWORD dwSignature, bool &bOverlap)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tErrorCodeEnum Error = Error_Succeed;"); sw.WriteLine("\t\tswitch (dwMessageID) {"); foreach (Method m in cls.MethodList) { sw.WriteLine("\t\tcase {0}:", GetMethodEnumName(entity, cls, m)); sw.WriteLine("\t\t\tif (dwSignature == {0}) {{", GetMethodSignatureEnumName(entity, cls, m)); sw.WriteLine("\t\t\t\tbOverlap = {0};", m.Overlap.ToString().ToLower()); sw.WriteLine("\t\t\t} else {"); sw.WriteLine("\t\t\t\tError = Error_MethodSignatureFailed;"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tbreak;"); if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; sw.WriteLine("\t\tcase {0}:", GetMethodEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\tif (dwSignature == {0}) {{", GetMethodSignatureEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\t\tbOverlap = {0};", subscribe.Cancel.Overlap.ToString().ToLower()); sw.WriteLine("\t\t\t} else {"); sw.WriteLine("\t\t\t\tError = Error_MethodSignatureFailed;"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tbreak;"); } } sw.WriteLine("\t\tdefault:"); sw.WriteLine("\t\t\tError = Error_MethodNotFound;"); sw.WriteLine("\t\t\tbreak;"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteServerCheckMessageSignature(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tint CheckMessageSignature(DWORD dwMessageID, DWORD dwSignature)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tErrorCodeEnum Error = Error_Succeed;"); sw.WriteLine("\t\tswitch (dwMessageID) {"); foreach (Method m in cls.MethodList) { sw.WriteLine("\t\tcase {0}:", GetMethodEnumName(entity, cls, m)); sw.WriteLine("\t\t\tif (dwSignature != {0}) {{", GetMethodSignatureEnumName(entity, cls, m)); sw.WriteLine("\t\t\t\tError = Error_MethodSignatureFailed;"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tbreak;"); // gen cancel method signature check if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; sw.WriteLine("\t\tcase {0}:", GetMethodEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\tif (dwSignature != {0}) {{", GetMethodSignatureEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\t\tError = Error_MethodSignatureFailed;"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tbreak;"); } } sw.WriteLine("\t\tdefault:"); sw.WriteLine("\t\t\tError = Error_MethodNotFound;"); sw.WriteLine("\t\t\tbreak;"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteServerIsSessionOverlap(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tvirtual bool IsSessionOverlap() {{ return {0}; }}", cls.Overlap.ToString().ToLower()); sw.WriteLine(); } void WriteServerOnewayHandler(StreamWriter sw, Entity entity, EntityClass cls, Oneway oneway) { sw.WriteLine("\tvirtual void Handle_{0}(SpOnewayCallContext<{1}>::Pointer ctx)", oneway.Name, GetInfoStructName(entity, cls, oneway)); sw.WriteLine("\t{"); sw.WriteLine("\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine(""); } void WriteServerTwowayHandler(StreamWriter sw, Entity entity, EntityClass cls, Twoway twoway) { sw.WriteLine("\tvirtual void Handle_{0}(SpReqAnsContext<{1}, {2}>::Pointer ctx)", twoway.Name, GetReqStructName(entity, cls, twoway), GetAnsStructName(entity, cls, twoway)); sw.WriteLine("\t{"); sw.WriteLine("\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine(""); } void WriteServerSubscibeHandler(StreamWriter sw, Entity entity, EntityClass cls, Subscribe subscribe) { // subscribe sw.WriteLine("\tvirtual void Handle_{0}(SpSubscribeContext<{1}, {2}>::Pointer ctx)", subscribe.Name, GetSubStructName(entity, cls, subscribe), GetInfoStructName(entity, cls, subscribe.Message)); sw.WriteLine("\t{"); sw.WriteLine("\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine(""); // cancel sw.WriteLine("\tvirtual void Handle_{0}(SpOnewayCallContext<{1}>::Pointer ctx)", subscribe.Cancel.Name, GetInfoStructName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t{"); sw.WriteLine("\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine(""); } void WriteServerOnRequest(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tvirtual void OnRequest(CSmartPointer pTransactionContext)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tCAutoBuffer Buf;"); sw.WriteLine("\t\tDWORD dwMessageID;"); sw.WriteLine("\t\tDWORD dwMessageSignature;"); sw.WriteLine("\t\tErrorCodeEnum Error = pTransactionContext->GetReceiveBuffer(dwMessageID, dwMessageSignature, Buf);"); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("#ifdef DEBUG"); sw.WriteLine("\t\t\tassert(CheckMessageSignature(dwMessageID, dwMessageSignature) == Error_Succeed);"); sw.WriteLine("#else"); sw.WriteLine("\t\t\tif (CheckMessageSignature(dwMessageID, dwMessageSignature) != Error_Succeed) {"); sw.WriteLine("\t\t\t\tpTransactionContext->SendAnswer(Error_MethodSignatureFailed);"); sw.WriteLine("\t\t\t\treturn;"); sw.WriteLine("\t\t\t}"); sw.WriteLine("#endif"); //sw.WriteLine("\t\tEntityResource::clearLink();"); sw.WriteLine("\t\t\tswitch (dwMessageID) {"); foreach (Method m in cls.MethodList) { if (typeof(Oneway).IsInstanceOfType(m)) { Oneway oneway = m as Oneway; sw.WriteLine("\t\t\t\tcase {0}:", GetMethodEnumName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t{"); sw.WriteLine("\t\t\t\t\t\tSpOnewayCallContext<{0}>::Pointer ctx;", GetInfoStructName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t\tctx.Attach(new SpOnewayCallContext<{0}>());", GetInfoStructName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t\tSpBuffer2Object(Buf, ctx->Info);"); sw.WriteLine("\t\t\t\t\t\tpTransactionContext->GetLinkContext(ctx->link);"); sw.WriteLine("\t\t\t\t\t\tEntityResource::setLink(ctx->link);"); sw.WriteLine("\t\t\t\t\t\tHandle_{0}(ctx);", m.Name); sw.WriteLine("\t\t\t\t\t}"); sw.WriteLine("\t\t\t\t\tbreak;"); } else if (typeof(Twoway).IsInstanceOfType(m)) { Twoway twoway = m as Twoway; sw.WriteLine("\t\t\t\tcase {0}:", GetMethodEnumName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t{"); sw.WriteLine("\t\t\t\t\t\tSpReqAnsContext<{0},{1}>::Pointer ctx;", GetReqStructName(entity, cls, m), GetAnsStructName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t\tctx.Attach(new SpReqAnsContext<{0},{1}>(pTransactionContext));", GetReqStructName(entity, cls, m), GetAnsStructName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t\tSpBuffer2Object(Buf, ctx->Req);"); sw.WriteLine("\t\t\t\t\t\tpTransactionContext->GetLinkContext(ctx->link);"); sw.WriteLine("\t\t\t\t\t\tEntityResource::setLink(ctx->link);"); sw.WriteLine("\t\t\t\t\t\tHandle_{0}(ctx);", m.Name); sw.WriteLine("\t\t\t\t\t}"); sw.WriteLine("\t\t\t\t\tbreak;"); } else if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; sw.WriteLine("\t\t\t\tcase {0}:", GetMethodEnumName(entity, cls, m)); sw.WriteLine("\t\t\t\t\t{"); sw.WriteLine("\t\t\t\t\t\tSpSubscribeContext<{0},{1}>::Pointer ctx;", GetSubStructName(entity, cls, m), GetInfoStructName(entity, cls, subscribe.Message)); sw.WriteLine("\t\t\t\t\t\tctx.Attach(new SpSubscribeContext<{0},{1}>(pTransactionContext));", GetSubStructName(entity, cls, m), GetInfoStructName(entity, cls, subscribe.Message)); sw.WriteLine("\t\t\t\t\t\tSpBuffer2Object(Buf, ctx->Req);"); sw.WriteLine("\t\t\t\t\t\tHandle_{0}(ctx);", m.Name); sw.WriteLine("\t\t\t\t\t}"); sw.WriteLine("\t\t\t\t\tbreak;"); sw.WriteLine("\t\t\t\tcase {0}:", GetMethodEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\t\t\t{"); sw.WriteLine("\t\t\t\t\t\tSpOnewayCallContext<{0}>::Pointer ctx;", GetInfoStructName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\t\t\t\tctx.Attach(new SpOnewayCallContext<{0}>());", GetInfoStructName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t\t\t\t\t\tSpBuffer2Object(Buf, ctx->Info);"); sw.WriteLine("\t\t\t\t\t\tHandle_{0}(ctx);", subscribe.Cancel.Name); sw.WriteLine("\t\t\t\t\t}"); sw.WriteLine("\t\t\t\t\tbreak;"); } else { throw new Exception("unknown method!"); } } sw.WriteLine("\t\t\t\tdefault:"); sw.WriteLine("\t\t\t\t\tassert(0);"); sw.WriteLine("\t\t\t\t\tbreak;"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\t"); sw.WriteLine("\t\t} else {"); sw.WriteLine("\t\t\tpTransactionContext->SendAnswer(Error);"); sw.WriteLine("\t\t}"); sw.WriteLine("\t}"); sw.WriteLine(""); } string GetServerClassName(Entity entity, EntityClass cls) { return string.Format("{0}_ServerSessionBase", cls.Name); } void WriteClassServer(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("class {0} : public CServerSessionBase", GetServerClassName(entity, cls)); sw.WriteLine("{"); sw.WriteLine("public:"); WriteServerConstructor(sw, entity, cls); WriteServerDestructor(sw, entity, cls); WriteSeverIsExclusive(sw, entity, cls); WriteServerIsSessionOverlap(sw, entity, cls); WriteServerGetMessageAttr(sw, entity, cls); WriteServerCheckMessageSignature(sw, entity, cls); foreach (Method m in cls.MethodList) { if (typeof(Oneway).IsInstanceOfType(m)) { WriteServerOnewayHandler(sw, entity, cls, m as Oneway); } else if (typeof(Twoway).IsInstanceOfType(m)) { WriteServerTwowayHandler(sw, entity, cls, m as Twoway); } else if (typeof(Subscribe).IsInstanceOfType(m)) { WriteServerSubscibeHandler(sw, entity, cls, m as Subscribe); } else { throw new Exception("unknown method!"); } } WriteServerOnRequest(sw, entity, cls); sw.WriteLine("};"); sw.WriteLine(); } void GenerateServer(string deffilename, string file, Entity entity) { string file_name = System.IO.Path.GetFileName(file); using (StreamWriter sw = new StreamWriter(file, false, Encoding.GetEncoding("gb2312"))) { string guard_marco = string.Format("__{0}", file_name.Replace('.', '_').ToUpper()); sw.WriteLine(); sw.WriteLine("#ifndef " + guard_marco); sw.WriteLine("#define " + guard_marco); sw.WriteLine(); sw.WriteLine("#pragma once"); sw.WriteLine(); sw.WriteLine("// This code is generated by spgen tool!"); sw.WriteLine(); sw.WriteLine("#include \"{0}\"", deffilename); sw.WriteLine(); sw.WriteLine("namespace {0} {{", entity.Name); foreach (EntityClass cls in entity.ClassList) { WriteClassServer(sw, entity, cls); sw.WriteLine(); sw.WriteLine("///////////////////////////"); sw.WriteLine(); } sw.WriteLine("}} // namespace {0}", entity.Name); sw.WriteLine(string.Format("#endif // {0}", guard_marco)); } } void WriteClientOneway(StreamWriter sw, Entity entity, EntityClass cls, Oneway oneway) { string iname = GetInfoStructName(entity, cls, oneway); if (oneway.InfoParamList.Count > 0) { sw.WriteLine("\tErrorCodeEnum {0}({1} &Info)", oneway.Name, iname); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = GetFunction();"); sw.WriteLine("\t\tif (m_context.checkEmpty())"); sw.WriteLine("\t\t{"); sw.WriteLine("\t\t\tm_context.AutoGenerate();"); sw.WriteLine("\t\t\tDbgToBeidou(m_context, m_pEntityBase != NULL ? m_pEntityBase->GetEntityName() : \"\")();"); sw.WriteLine("\t\t\tm_context = m_context.upgradeLink();"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\tCAutoBuffer Buf = SpObject2Buffer(Info);"); sw.WriteLine("\t\tauto ret = pFunc->OnewayCall({0}, {1}, Buf, m_context);", GetMethodEnumName(entity, cls, oneway), GetMethodSignatureEnumName(entity, cls, oneway)); sw.WriteLine("\t\tm_context.clear();"); sw.WriteLine("\t\treturn ret;"); sw.WriteLine("\t}"); } else { sw.WriteLine("\tErrorCodeEnum {0}()", oneway.Name); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = GetFunction();"); sw.WriteLine("\t\tif (m_context.checkEmpty())"); sw.WriteLine("\t\t{"); sw.WriteLine("\t\t\tm_context.AutoGenerate();"); sw.WriteLine("\t\t\tDbgToBeidou(m_context, m_pEntityBase != NULL ? m_pEntityBase->GetEntityName() : \"\")();"); sw.WriteLine("\t\t\tm_context = m_context.upgradeLink();"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\tauto ret = pFunc->OnewayCall({0}, {1}, m_context);", GetMethodEnumName(entity, cls, oneway), GetMethodSignatureEnumName(entity, cls, oneway)); sw.WriteLine("\t\tm_context.clear();"); sw.WriteLine("\t\treturn ret;"); sw.WriteLine("\t}"); } sw.WriteLine(); } void WriteClientTwoway(StreamWriter sw, Entity entity, EntityClass cls, Twoway twoway) { // async sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, CSmartPointer &spAsyncWait, DWORD dwTimeout)", twoway.Name, GetReqStructName(entity, cls, twoway)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = GetFunction();"); sw.WriteLine("\t\tCAutoBuffer Buf = SpObject2Buffer(Req);"); sw.WriteLine("\t\tif (m_context.checkEmpty())"); sw.WriteLine("\t\t{"); sw.WriteLine("\t\t\tm_context.AutoGenerate();"); sw.WriteLine("\t\t\tDbgToBeidou(m_context, m_pEntityBase != NULL ? m_pEntityBase->GetEntityName() : \"\")();"); sw.WriteLine("\t\t\tm_context = m_context.upgradeLink();"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\tauto ret = pFunc->AsyncRequest({0}, {1}, Buf, spAsyncWait, m_context, dwTimeout);", GetMethodEnumName(entity, cls, twoway), GetMethodSignatureEnumName(entity, cls, twoway)); sw.WriteLine("\t\tm_context.clear();"); sw.WriteLine("\t\treturn ret;"); sw.WriteLine("\t}"); // sync sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, {2} &Ans, DWORD dwTimeout)", twoway.Name, GetReqStructName(entity, cls, twoway), GetAnsStructName(entity, cls, twoway)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer spAsyncWait;"); sw.WriteLine("\t\tErrorCodeEnum Error = {0}(Req, spAsyncWait, dwTimeout);", twoway.Name); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\tbool bEnd = false;"); sw.WriteLine("\t\t\tError = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwTimeout);"); sw.WriteLine("\t\t\tLOG_ASSERT(Error || bEnd);"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); // sync with user error + buf sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, {2} &Ans, DWORD dwTimeout, DWORD &dwUserError, CSimpleString &str)", twoway.Name, GetReqStructName(entity, cls, twoway), GetAnsStructName(entity, cls, twoway)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer spAsyncWait;"); sw.WriteLine("\t\tErrorCodeEnum Error = {0}(Req, spAsyncWait, dwTimeout);", twoway.Name); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\tbool bEnd = false;"); sw.WriteLine("\t\t\tError = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwUserError, str, dwTimeout);"); sw.WriteLine("\t\t\tLOG_ASSERT(Error || bEnd);"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); // sync with user error sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, {2} &Ans, DWORD dwTimeout, DWORD &dwUserError)", twoway.Name, GetReqStructName(entity, cls, twoway), GetAnsStructName(entity, cls, twoway)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer spAsyncWait;"); sw.WriteLine("\t\tErrorCodeEnum Error = {0}(Req, spAsyncWait, dwTimeout);", twoway.Name); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\tbool bEnd = false;"); sw.WriteLine("\t\t\tCSimpleString str;"); sw.WriteLine("\t\t\tError = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwUserError, str, dwTimeout);"); sw.WriteLine("\t\t\tLOG_ASSERT(Error || bEnd);"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteClientSubscribe(StreamWriter sw, Entity entity, EntityClass cls, Subscribe subscribe) { sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, CSmartPointer &spAsyncWait)", subscribe.Name, GetSubStructName(entity, cls, subscribe)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = GetFunction();"); sw.WriteLine("\t\tCAutoBuffer Buf = SpObject2Buffer(Req);"); sw.WriteLine("\t\tErrorCodeEnum Error = pFunc->AsyncRequest({0}, {1}, Buf, spAsyncWait, -1);", GetMethodEnumName(entity, cls, subscribe), GetMethodSignatureEnumName(entity, cls, subscribe)); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, ICallbackListener *pCallback,IReleasable *pData = NULL)", subscribe.Name, GetSubStructName(entity, cls, subscribe)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer spAsyncWait;"); sw.WriteLine("\t\tErrorCodeEnum Error = {0}(Req, spAsyncWait);", subscribe.Name); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\tspAsyncWait->SetCallback(pCallback, pData);"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine("\tErrorCodeEnum {0}({1} &Req, IReleasable *pData = NULL)", subscribe.Name, GetSubStructName(entity, cls, subscribe)); sw.WriteLine("\t{"); sw.WriteLine("\t\treturn {0}(Req, this, pData);", subscribe.Name); sw.WriteLine("\t}"); if (subscribe.Cancel.InfoParamList.Count > 0) { sw.WriteLine("\tErrorCodeEnum {0}({1} &CancelInfo)", subscribe.Cancel.Name, GetInfoStructName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = GetFunction();"); sw.WriteLine("\t\tCAutoBuffer Buf = SpObject2Buffer(CancelInfo);"); sw.WriteLine("\t\treturn pFunc->OnewayCall({0}, {1}, Buf);", GetMethodEnumName(entity, cls, subscribe.Cancel), GetMethodSignatureEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t}"); } else { sw.WriteLine("\tErrorCodeEnum {0}({1} &CancelInfo)", subscribe.Cancel.Name, GetInfoStructName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = GetFunction();"); sw.WriteLine("\t\treturn pFunc->OnewayCall({0}, {1});", GetMethodEnumName(entity, cls, subscribe.Cancel), GetMethodSignatureEnumName(entity, cls, subscribe.Cancel)); sw.WriteLine("\t}"); } sw.WriteLine("\tvirtual void OnMessage(ErrorCodeEnum Error, {0} &Msg, CSmartPointer pData)", GetInfoStructName(entity, cls, subscribe.Message)); sw.WriteLine("\t{"); sw.WriteLine("\t\t/// implement by user"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteOnAnswer(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("private:"); sw.WriteLine("\tvirtual void OnAnswer(CSmartPointer pAsynWaitSp)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tCAutoBuffer Buf;"); sw.WriteLine("\t\tbool bEnd;"); sw.WriteLine("\t\tCSmartPointer pData;"); sw.WriteLine("\t\tErrorCodeEnum Error = pAsynWaitSp->AsyncGetAnswer(Buf, bEnd);"); sw.WriteLine("\t\tDWORD dwMessageId = pAsynWaitSp->GetMessageID();"); sw.WriteLine("\t\tCSmartPointer pCallbackListener;"); sw.WriteLine("\t\tpAsynWaitSp->GetCallback(pCallbackListener, pData);"); sw.WriteLine("\t\t"); sw.WriteLine("\t\tswitch (dwMessageId) {"); foreach (Method m in cls.MethodList) { if (typeof(Subscribe).IsInstanceOfType(m)) { Subscribe subscribe = m as Subscribe; sw.WriteLine("\t\tcase {0}:", GetMethodEnumName(entity, cls, subscribe)); sw.WriteLine("\t\t\tif (Error) {"); sw.WriteLine("\t\t\t\t{0} Msg;", GetInfoStructName(entity, cls, subscribe.Message)); sw.WriteLine("\t\t\t\tOnMessage(Error, Msg, pData);"); sw.WriteLine("\t\t\t} else {"); sw.WriteLine("\t\t\t\t{0} Msg;", GetInfoStructName(entity, cls, subscribe.Message)); sw.WriteLine("\t\t\t\tSpBuffer2Object(Buf, Msg);"); sw.WriteLine("\t\t\t\tOnMessage(Error, Msg, pData);"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tbreak;"); } } sw.WriteLine("\t\tdefault:"); sw.WriteLine("\t\t\tassert(0);"); sw.WriteLine("\t\t\tbreak;"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\t"); sw.WriteLine("\t\t"); sw.WriteLine("\t}"); sw.WriteLine(); } bool HasSubscribe(EntityClass cls) { foreach (Method m in cls.MethodList) { if (typeof(Subscribe).IsInstanceOfType(m)) return true; } return false; } void WriteClientConstructor(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\texplicit {0}(CEntityBase *pEntity) : m_pEntityBase(pEntity), m_bSysManaged(false) {{}}", GetClientClassName(entity, cls)); sw.WriteLine(); } void WriteOperatorContext(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\t{0}* operator () (const linkContext &curLink) ", GetClientClassName(entity, cls)); sw.WriteLine("\t{"); sw.WriteLine("\t\tm_context = curLink;"); sw.WriteLine("\t\treturn this;"); sw.WriteLine("\t}"); sw.WriteLine(); } void WriteClientDestructor(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("protected:"); sw.WriteLine("\tvirtual ~{0}()", GetClientClassName(entity, cls)); sw.WriteLine("\t{"); sw.WriteLine("\t\t/// override by user"); sw.WriteLine("\t}"); sw.WriteLine("public:"); sw.WriteLine(); } void WriteClientConnect(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine("\tvoid OnConnectSucceed()"); sw.WriteLine("\t{"); sw.WriteLine("\t\tbSessionClosed = false;"); sw.WriteLine("\t}"); sw.WriteLine("\tvoid OnClose(ErrorCodeEnum)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tbSessionClosed = true;"); sw.WriteLine("\t}"); sw.WriteLine("\tbool QuerySessionClosed()"); sw.WriteLine("\t{"); sw.WriteLine("\t\treturn bSessionClosed;"); sw.WriteLine("\t}"); sw.WriteLine("\tErrorCodeEnum Connect(CSmartPointer &spAsyncWait)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer pFunc = m_pEntityBase->GetFunction();"); sw.WriteLine("\t\tErrorCodeEnum Error = pFunc->ConnectRemoteEntity(this, \"{0}\", \"{1}\", spAsyncWait);", entity.Name, cls.Name); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\tm_bSysManaged = true;"); sw.WriteLine("\t\t\tbSessionClosed = false;"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine("\tErrorCodeEnum Connect()"); sw.WriteLine("\t{"); sw.WriteLine("\t\tCSmartPointer spAsyncWait;"); sw.WriteLine("\t\tErrorCodeEnum Error = Connect(spAsyncWait);"); sw.WriteLine("\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\tError = spAsyncWait->WaitAnswer();"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn Error;"); sw.WriteLine("\t}"); sw.WriteLine(); } string GetClientClassName(Entity entity, EntityClass cls) { return string.Format("{0}_ClientBase", cls.Name); } void WriteSafeDelete(StreamWriter sw, Entity entity, EntityClass cls) { sw.WriteLine(""); sw.WriteLine("\tbool SafeDelete()"); sw.WriteLine("\t{"); sw.WriteLine("\t\tif (!m_bSysManaged) {"); sw.WriteLine("\t\t\tdelete this;"); sw.WriteLine("\t\t}"); sw.WriteLine("\t\treturn m_bSysManaged;"); sw.WriteLine("\t}"); sw.WriteLine(""); } void WriteClassClient(StreamWriter sw, Entity entity, EntityClass cls) { string clsname = GetClientClassName(entity, cls); bool bHasSub = HasSubscribe(cls); if (bHasSub) sw.WriteLine("class {0} : public CClientSessionBase, public ICallbackListener {{ ", clsname); else sw.WriteLine("class {0} : public CClientSessionBase {{", clsname); sw.WriteLine("public:"); WriteClientConstructor(sw, entity, cls); WriteOperatorContext(sw, entity, cls); WriteClientDestructor(sw, entity, cls); WriteClientConnect(sw, entity, cls); foreach (Method m in cls.MethodList) { if (typeof(Oneway).IsInstanceOfType(m)) { WriteClientOneway(sw, entity, cls, m as Oneway); } else if (typeof(Twoway).IsInstanceOfType(m)) { WriteClientTwoway(sw, entity, cls, m as Twoway); } else if (typeof(Subscribe).IsInstanceOfType(m)) { WriteClientSubscribe(sw, entity, cls, m as Subscribe); } else { throw new Exception("unknown"); } } WriteSafeDelete(sw, entity, cls); if (bHasSub) { WriteOnAnswer(sw, entity, cls); } sw.WriteLine("protected:"); sw.WriteLine("\tbool m_bSysManaged;"); sw.WriteLine("\tCEntityBase *m_pEntityBase;"); sw.WriteLine("\tlinkContext m_context;"); sw.WriteLine("\tbool bSessionClosed;"); sw.WriteLine("};"); } void GenerateClient(string deffilename, string file, Entity entity) { string file_name = System.IO.Path.GetFileName(file); using (StreamWriter sw = new StreamWriter(file, false, Encoding.GetEncoding("gb2312"))) { string guard_marco = string.Format("__{0}", file_name.Replace('.', '_').ToUpper()); sw.WriteLine(); sw.WriteLine("#ifndef " + guard_marco); sw.WriteLine("#define " + guard_marco); sw.WriteLine(); sw.WriteLine("#pragma once"); sw.WriteLine(); sw.WriteLine("// This code is generated by spgen tool!"); sw.WriteLine(); sw.WriteLine("#include \"{0}\"", deffilename); sw.WriteLine(); sw.WriteLine("namespace {0} {{", entity.Name); foreach (EntityClass cls in entity.ClassList) { WriteClassClient(sw, entity, cls); sw.WriteLine(); sw.WriteLine("///////////////////////////"); sw.WriteLine(); } sw.WriteLine("}} // namespace {0}", entity.Name); sw.WriteLine(string.Format("#endif // {0}", guard_marco)); } } string GetMsgDefName(EntityMsg msg) { return string.Format("eMsg_{0}", msg.Name); } string GetMsgSigDefName(EntityMsg msg) { return string.Format("eMsgSig_{0}", msg.Name); } void WriteMsgDef(StreamWriter sw, Entity entity) { int i = 0; foreach (EntityMsg msg in entity.MsgList) { WriteLineDefine(sw, entity, GetMsgDefName(msg), i.ToString()); i++; } sw.WriteLine(); foreach (EntityMsg msg in entity.MsgList) { WriteLineDefine(sw, entity, GetMsgSigDefName(msg), msg.Signature.ToString()); } sw.WriteLine(); } #if false void WriteMsgReceiverBase(StreamWriter sw, Entity entity) { sw.WriteLine(); sw.WriteLine("struct ReceiverBase : public IBroadcastListener {"); foreach (EntityMsg msg in entity.MsgList) { sw.WriteLine("\tvirtual void Handle_{0}({0} &Event) = 0;", msg.Name); } sw.WriteLine("\tvirtual void OnBroadcastEvent(const char *pszEntityName,DWORD dwMessageId, DWORD dwMessageSignature,CAutoBuffer Buffer)"); sw.WriteLine("\t{"); sw.WriteLine("\t\tswitch(dwMessageId) {"); foreach (EntityMsg msg in entity.MsgList) { sw.WriteLine("\t\tcase {0}:", GetMsgDefName(msg)); sw.WriteLine("\t\t\t{"); sw.WriteLine("\t\t\t\tif (dwMessageSignature == {0}) {{", GetMsgSigDefName(msg)); sw.WriteLine("\t\t\t\t\t{0} Event;", msg.Name); sw.WriteLine("\t\t\t\t\tErrorCodeEnum Error = SpBuffer2Object<{0}>(Buffer, Event);", msg.Name); sw.WriteLine("\t\t\t\t\tif (Error == Error_Succeed) {"); sw.WriteLine("\t\t\t\t\t\tHandle_{0}(Event);", msg.Name); sw.WriteLine("\t\t\t\t\t}"); sw.WriteLine("\t\t\t\t} else {"); sw.WriteLine("\t\t\t\t\tLOG_TRACE(\"sig mismatch, %d\", dwMessageId);"); sw.WriteLine("\t\t\t\t}"); sw.WriteLine("\t\t\t}"); sw.WriteLine("\t\t\tbreak;"); } sw.WriteLine("\t\tdefault:"); sw.WriteLine("\t\t\tLOG_TRACE(\"ignore event! %d\", dwMessageId);"); sw.WriteLine("\t\t}"); sw.WriteLine("\t}"); sw.WriteLine("};"); sw.WriteLine(); } #endif void GenerateMsg(string msgfile, Entity entity) { string file_name = System.IO.Path.GetFileName(msgfile); using (StreamWriter sw = new StreamWriter(msgfile, false, Encoding.GetEncoding("gb2312"))) { string guard_marco = string.Format("__{0}", file_name.Replace('.', '_').ToUpper()); sw.WriteLine(); sw.WriteLine("#ifndef " + guard_marco); sw.WriteLine("#define " + guard_marco); sw.WriteLine(); sw.WriteLine("#pragma once"); sw.WriteLine(); sw.WriteLine("// This code is generated by spgen tool!"); sw.WriteLine(); sw.WriteLine("#include \"SpHelper.h\""); sw.WriteLine(); sw.WriteLine("namespace {0} {{", entity.Name); WriteMsgDef(sw, entity); foreach (EntityMsg msg in entity.MsgList) { WriteStruct(sw, msg.Name, msg.InfoParamList); sw.WriteLine(); sw.WriteLine("///////////////////////////"); sw.WriteLine(); } sw.WriteLine("}} // namespace {0}", entity.Name); sw.WriteLine(string.Format("#endif // {0}", guard_marco)); } } } }