/** * Tencent is pleased to support the open source community by making Tars available. * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ #include "tars2oc.h" #include "util/tc_md5.h" #include "util/tc_file.h" #include "util/tc_common.h" #include #define TAB g_parse->getTab() #define INC_TAB g_parse->incTab() #define DEL_TAB g_parse->delTab() ////////////////////////////////////////////////////////////////////////////////// string Tars2OC::toClassName(const TypePtr &pPtr) const { string s; BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) { switch (bPtr->kind()) { case Builtin::KindBool: s = "bool"; break; case Builtin::KindByte: s = "char"; break; case Builtin::KindShort: s = "short"; break; case Builtin::KindInt: s = "int32"; break; case Builtin::KindLong: s = "int64"; break; case Builtin::KindFloat: s = "float"; break; case Builtin::KindDouble: s = "double"; break; case Builtin::KindString: s = "string"; break; default: assert(false); break; } return s; } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); if (vPtr) return tostrVector(vPtr); MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) return tostrMap(mPtr); StructPtr sPtr = StructPtr::dynamicCast(pPtr); if (sPtr) return tostrStruct(sPtr); EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if (ePtr) return tostrEnum(ePtr); if (!pPtr) return "void"; assert(false); return ""; } string Tars2OC::toAddtionalClassName(const TypePtr &pPtr) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) { string s = ""; switch (bPtr->kind()) { case Builtin::KindBool: case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: case Builtin::KindFloat: case Builtin::KindDouble: { s = "ONSNumber"; break; } case Builtin::KindString: { s = "ONSString"; break; } default: assert(false); break; } return s; } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); if (vPtr) { string s = ""; if (toClassName(vPtr) == "list") { s = "ONSData"; } else { s = "V" + toAddtionalClassName(vPtr->getTypePtr()); } return s; } MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) { string sKey = toAddtionalClassName(mPtr->getLeftTypePtr()); string sValue = toAddtionalClassName(mPtr->getRightTypePtr()); ostringstream osKeyLen; { int iLen = sKey.length(); assert(iLen <= 99 && iLen >=0); char sLen[3]; snprintf(&sLen[0],3,"%.2d",iLen); osKeyLen <getSid(), "::", ""); } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if (ePtr) { return "ONSNumber"; } if (!pPtr) return "void"; assert(false); return ""; } /*******************************BuiltinPtr********************************/ string Tars2OC::tostr(const TypePtr &pPtr) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) return tostrBuiltin(bPtr); VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); if (vPtr) { if (toClassName(vPtr) == "list") { return "NSData*"; } else { ostringstream s; s << "NSArray<" << (isNumberType(vPtr->getTypePtr()) ? "NSNumber*" : tostr(vPtr->getTypePtr())) << ">*"; return s.str(); } } MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) { ostringstream s; s << "NSDictionary<" << (isNumberType(mPtr->getLeftTypePtr()) ? "NSNumber*" : tostr(mPtr->getLeftTypePtr())) << ", " << (isNumberType(mPtr->getRightTypePtr()) ? "NSNumber*" : tostr(mPtr->getRightTypePtr())) << ">*"; return s.str(); } StructPtr sPtr = StructPtr::dynamicCast(pPtr); if (sPtr) return tostrStruct(sPtr)+ "*"; EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if (ePtr) return tostrEnum(ePtr); if (!pPtr) return "void"; assert(false); return ""; } bool Tars2OC::isNumberType(const TypePtr &pPtr) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); bool ret = false; if (bPtr) { switch (bPtr->kind()) { case Builtin::KindBool: case Builtin::KindByte: case Builtin::KindShort: case Builtin::KindInt: case Builtin::KindLong: case Builtin::KindFloat: case Builtin::KindDouble: { ret = true; break; } default: ret = false; break; } } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if (ePtr) { ret = true; } return ret; } string Tars2OC::tostrBuiltin(const BuiltinPtr &pPtr) const { string s; switch (pPtr->kind()) { case Builtin::KindBool: s = "TarsBool"; break; case Builtin::KindByte: s = "TarsInt8"; break; case Builtin::KindShort: s = (pPtr->isUnsigned()?"TarsUInt8":"TarsInt16"); break; case Builtin::KindInt: s = (pPtr->isUnsigned()?"TarsUInt16":"TarsInt32"); break; case Builtin::KindLong: s = (pPtr->isUnsigned()?"TarsUInt32":"TarsInt64"); break; case Builtin::KindFloat: s = "TarsFloat"; break; case Builtin::KindDouble: s = "TarsDouble"; break; case Builtin::KindString: s = "NSString*"; break; default: assert(false); break; } return s; } /*******************************VectorPtr********************************/ string Tars2OC::tostrVector(const VectorPtr &pPtr) const { string s = string("list<") + toClassName(pPtr->getTypePtr()); if (MapPtr::dynamicCast(pPtr->getTypePtr()) || VectorPtr::dynamicCast(pPtr->getTypePtr())) { s += " >"; } else { s += ">"; } return s; } /*******************************MapPtr********************************/ string Tars2OC::tostrMap(const MapPtr &pPtr) const { string s = string("map<") + toClassName(pPtr->getLeftTypePtr()) + "," + toClassName(pPtr->getRightTypePtr()); if (MapPtr::dynamicCast(pPtr->getRightTypePtr()) || VectorPtr::dynamicCast(pPtr->getRightTypePtr())) { s += " >"; } else { s += ">"; } return s; } string Tars2OC::getReqOptionType(const TypeIdPtr &pPtr) const { return (pPtr->isRequire())?"r":"o"; } string Tars2OC::toTarsV2Procstr(const TypeIdPtr &pPtr) const { ostringstream s; BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); if (bPtr) { // s << "JV2_PROP_NM(" << getReqOptionType(pPtr) << "," << pPtr->getTag() <<","<< pPtr->getId() << ")"; } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr()); if (vPtr) { //vector if (toClassName(vPtr) == "list") { s << "JV2_PROP_NM(" << getReqOptionType(pPtr) << "," << pPtr->getTag() << "," << pPtr->getId() << ")"; } else { s << "JV2_PROP_EX(" << getReqOptionType(pPtr) << "," << pPtr->getTag()<< "," <getId()<< "," <getTypePtr()); if (mPtr) { s << "JV2_PROP_EX(" << getReqOptionType(pPtr) << "," << pPtr->getTag()<< "," <getId()<< "," << toAddtionalClassName(mPtr) << ")"; } StructPtr sPtr = StructPtr::dynamicCast(pPtr->getTypePtr()); if (sPtr) { s << "JV2_PROP_NM(" << getReqOptionType(pPtr) << "," << pPtr->getTag() <<","<< pPtr->getId() << ")"; } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); if (ePtr) { s << "JV2_PROP_NM(" << getReqOptionType(pPtr) << "," << pPtr->getTag() <<","<< pPtr->getId() << ")"; } return s.str(); } /*******************************StructPtr********************************/ string Tars2OC::tostrStruct(const StructPtr &pPtr) const { vector vStr = TC_Common::sepstr(pPtr->getSid(), "::"); if(vStr.size() >= 2) { string sNamespace = getNamePrix(vStr[0]); return sNamespace + vStr[1]; } return TC_Common::replace(pPtr->getSid(), "::", ""); } ///////////////////////////////////////////////////////////////////// string Tars2OC::tostrEnum(const EnumPtr &pPtr) const { vector vStr = TC_Common::sepstr(pPtr->getSid(), "::"); if(vStr.size() >= 2) { string sNamespace = getNamePrix(vStr[0]); return sNamespace + vStr[1]; } return TC_Common::replace(pPtr->getSid(), "::", ""); } void Tars2OC::toIncludeName(const TypePtr &pPtr,map& mReference) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) { return ; } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); if (vPtr) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); if (!bPtr) { toIncludeName(vPtr->getTypePtr(),mReference); } } MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(mPtr->getLeftTypePtr()); if (!bPtr)//not builin type { toIncludeName(mPtr->getLeftTypePtr(),mReference); } BuiltinPtr _bPtr = BuiltinPtr::dynamicCast(mPtr->getRightTypePtr()); if (!_bPtr) { toIncludeName(mPtr->getRightTypePtr(),mReference); } } StructPtr sPtr = StructPtr::dynamicCast(pPtr); if (sPtr) { mReference[tostrStruct(sPtr)] = EM_STRUCT_TYPE; } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if (ePtr) { mReference[tostrEnum(ePtr)] = EM_ENUM_TYPE; } } map Tars2OC::getReferences(const StructPtr &pPtr, const string& namespaceId) const { map mTemp; vector& vMember = pPtr->getAllMemberPtr(); for (size_t j = 0; j < vMember.size(); j++) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(vMember[j]->getTypePtr()); if (bPtr) { continue; } VectorPtr vPtr = VectorPtr::dynamicCast(vMember[j]->getTypePtr()); if (vPtr) { //vector if (toClassName(vPtr) == "list") { continue; } else { toIncludeName(vPtr,mTemp); } } MapPtr mPtr = MapPtr::dynamicCast(vMember[j]->getTypePtr()); if (mPtr) { toIncludeName(mPtr,mTemp); } StructPtr sPtr = StructPtr::dynamicCast(vMember[j]->getTypePtr()); if (sPtr) { mTemp[tostrStruct(sPtr)] = EM_STRUCT_TYPE; } EnumPtr ePtr = EnumPtr::dynamicCast(vMember[j]->getTypePtr()); if (ePtr) { mTemp[tostrEnum(ePtr)] = EM_ENUM_TYPE; } } return mTemp; } bool Tars2OC::IsRetainType(const TypePtr &pPtr) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if((bPtr && bPtr->kind() != Builtin::KindString) || ePtr) { return false; } else { return true; } } string Tars2OC::getNamePrix(const string& sTarsNS) const { string sNameSpace = ""; if(m_bNeedNS) { if(!m_sNamespace.empty()) { return m_sNamespace; } else { return sTarsNS; } } else { return sNameSpace; } } string Tars2OC::getPropertyName(const string& sId) const { return "JV2_PROP(" + sId + ")"; } string Tars2OC::getSetterName(const string& sId) const { if(!sId.empty()) { return "set" + TC_Common::upper(sId.substr(0,1)) + sId.substr(1) + ":"; } else { return sId; } } /////////////////////////////////////////////////////////////////////// string Tars2OC::generateH(const StructPtr &pPtr, const string& namespaceId) const { ostringstream s; string sStructName = getNamePrix(namespaceId) + pPtr->getId(); string fileH = m_sBaseDir + "/" + sStructName + ".h"; s << g_parse->printHeaderRemark(); s << "#import \"TarsObjectV2.h\"" << endl; map mTemp = getReferences(pPtr); for(map::iterator it = mTemp.begin();it != mTemp.end();it++) { s << "#import \"" << it->first <<".h\""<& vMember = pPtr->getAllMemberPtr(); for (size_t j = 0; j < vMember.size(); j++) { string sPropType = IsRetainType(vMember[j]->getTypePtr())?"retain":"assign"; s << "@property (nonatomic, "<getId() << "," << getSetterName(vMember[j]->getId()) <<")) "; s << tostr(vMember[j]->getTypePtr()) << " " << toTarsV2Procstr(vMember[j]) <<";"<& vMember) const { ostringstream s; s << "- (id)init" <getTypePtr()); if(bPtr) { if(bPtr->kind() == Builtin::KindBool) { string sBool = (vMember[j]->def() == "true")?"YES":"NO"; s <getId()) << " = " << sBool << ";" << endl; } else if(bPtr->kind() == Builtin::KindString) { string tmp = tars::TC_Common::replace(vMember[j]->def(), "\"", "\\\""); if(!tmp.empty()) { s <getId()) << " = @\"" << tmp << "\";" << endl; } else { s <getId()) << " = DefaultTarsString;" << endl; } } else if((vMember[j]->def() != "0")) { s <getId()) << " = " << vMember[j]->def() << ";" << endl; } } if(vMember[j]->isRequire() && IsRetainType(vMember[j]->getTypePtr())) { VectorPtr vPtr = VectorPtr::dynamicCast(vMember[j]->getTypePtr()); if (vPtr) { if (toClassName(vPtr) == "list") { s <getId()) << " = DefaultTarsData;" << endl; } else { s <getId()) << " = DefaultTarsArray;" << endl; } } MapPtr mPtr = MapPtr::dynamicCast(vMember[j]->getTypePtr()); if (mPtr) { s <getId()) << " = DefaultTarsDictionary;" << endl; } StructPtr sPtr = StructPtr::dynamicCast(vMember[j]->getTypePtr()); if (sPtr) { s <getId()) << " = ["<& vMember) const { ostringstream s; s << "- (void)dealloc" <getTypePtr())) { s <getId()) << " = nil;" <& vMember) const { ostringstream s; s <getSid(), "::", ".")<< "\";" <getSid(), "::", ""); s << TAB << "if (self == [" << sStructName << " class]) {" << endl; INC_TAB; map mTemp = getReferences(pPtr); for(map::iterator it = mTemp.begin();it != mTemp.end();it++) { if(it->second == EM_STRUCT_TYPE) { s << TAB << "[" << it->first <<" initialize];"<< endl; } } s << TAB <<"[super initialize];" <getId(); string fileH = m_sBaseDir + FILE_SEP + sEnumPrefix + ".m"; s << g_parse->printHeaderRemark(); s << "#import \"TarsObjectV2.h\"" << endl; s << "#import \"" <& member = pPtr->getAllMemberPtr(); for(size_t i = 0; i < member.size(); i++) { string sMem = sEnumPrefix + "_" + member[i]->getId(); s << TAB << "case " << sMem << ": return "<< "@\"" << sMem << "\";" << endl; } s << TAB << "default: return @\"\";" << endl; DEL_TAB; s << TAB << "}" << endl; DEL_TAB; s << TAB << "}" << endl; s << endl; s << "+ (" << sEnumPrefix << ")stoe:(NSString *)s" << endl; s << "{" << endl; INC_TAB; for(size_t i = 0; i < member.size(); i++) { string sMem = sEnumPrefix + "_" + member[i]->getId(); s << TAB << "if(isTarsEnumStringEqual(s, @\"" << sMem << "\")) return " << sMem <<";"<getId(); ostringstream s; string fileM = m_sBaseDir + FILE_SEP + sStructName + ".m"; s << g_parse->printHeaderRemark(); vector& member = pPtr->getAllMemberPtr(); //////////////////////////////////////////////////////////// s << "#import \"" <getAllNamespacePtr().size(); i++) { s << generateH(pPtr->getAllNamespacePtr()[i]) << endl; s << endl; } return s.str(); } /******************************EnumPtr***************************************/ string Tars2OC::generateH(const EnumPtr &pPtr, const string& namespaceId) const { ostringstream s; string sEnumPrefix = getNamePrix(namespaceId) + pPtr->getId(); string fileH = m_sBaseDir + FILE_SEP + sEnumPrefix + ".h"; s << g_parse->printHeaderRemark(); s << "#import \"TarsObjectV2.h\"" << endl; s << endl; s << "enum {"<& member = pPtr->getAllMemberPtr(); for (size_t i = 0; i < member.size(); i++) { s << TAB << sEnumPrefix << "_" << member[i]->getId(); if (member[i]->hasDefault()) { s << " = " << member[i]->def(); } s << (i==member.size()-1 ? "" : ",") << endl; } DEL_TAB; s <<"};" << endl; s <<"#define "<&ss = pPtr->getAllStructPtr(); vector&es = pPtr->getAllEnumPtr(); for (size_t i = 0; i < es.size(); i++) { generateH(es[i], pPtr->getId()); generateM(es[i], pPtr->getId()); } for (size_t i = 0; i < ss.size(); i++) { generateH(ss[i], pPtr->getId()); generateM(ss[i], pPtr->getId()); } return ""; } /******************************Tars2OC***************************************/ void Tars2OC::generate(const ContextPtr &pPtr) const { vector namespaces = pPtr->getNamespaces(); for (size_t i = 0; i < namespaces.size(); i++) { generate(namespaces[i]); } } void Tars2OC::createFile(const string &file) { std::vector contexts = g_parse->getContexts(); for (size_t i = 0; i < contexts.size(); i++) { if (file == contexts[i]->getFileName()) { generate(contexts[i]); } } }