version: 20180713

This commit is contained in:
Super Zheng 2018-07-27 12:33:14 +08:00
parent 3c4c8533da
commit deaeeb550b
35 changed files with 14819 additions and 0 deletions

52
CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 2.6)
project(tars2node)
set(CMAKE_VERBOSE_MAKEFILE off)
# version
set(TARS_VERSION "1.1.0")
set(PARSER_VERSION "${TARS_VERSION}")
set(GENERATOR_VERSION "20180713")
# namespace
set(IDL_NAMESPACE Tars)
string(TOLOWER ${IDL_NAMESPACE} TC_NAMESPACE)
set(GRAMMAR_NAME Grammar)
# idl
set(RPC_MODULE_PATH "@tars/rpc")
set(STREAM_MODULE_PATH "@tars/stream")
set(IDL_TYPE "Tars")
set(PROTOCOL_NAME "Tup")
# flag
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O2 -Wall -Wno-sign-compare -Wno-unused-result")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O2 -Wall")
# define
add_definitions(-DTARS_VERSION="${TARS_VERSION}")
add_definitions(-DPARSER_VERSION="${PARSER_VERSION}")
add_definitions(-DGENERATOR_VERSION="${GENERATOR_VERSION}")
add_definitions(-DTC_NAMESPACE=${TC_NAMESPACE})
add_definitions(-DIDL_NAMESPACE=${IDL_NAMESPACE})
add_definitions(-DGRAMMAR_NAME=${GRAMMAR_NAME})
add_definitions(-DRPC_MODULE_PATH="${RPC_MODULE_PATH}")
add_definitions(-DSTREAM_MODULE_PATH="${STREAM_MODULE_PATH}")
add_definitions(-DEXECUTE_FILENAME="${PROJECT_NAME}")
add_definitions(-DIDL_TYPE="${IDL_TYPE}")
add_definitions(-DPROTOCOL_NAME="${PROTOCOL_NAME}")
# include
include_directories(${PROJECT_SOURCE_DIR}/third_partly/dirent/include)
include_directories(${PROJECT_SOURCE_DIR}/third_partly/tarsgrammar)
include_directories(${PROJECT_SOURCE_DIR}/third_partly/tarsparse)
include_directories(${PROJECT_SOURCE_DIR}/third_partly/util/include)
include_directories(${PROJECT_SOURCE_DIR}/include)
# source
aux_source_directory(${PROJECT_SOURCE_DIR}/third_partly/tarsgrammar DIR_SRCS)
aux_source_directory(${PROJECT_SOURCE_DIR}/third_partly/tarsparse DIR_SRCS)
aux_source_directory(${PROJECT_SOURCE_DIR}/third_partly/util/src DIR_SRCS)
aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS)
add_executable(${PROJECT_NAME} ${DIR_SRCS})

40
README.md Normal file
View File

@ -0,0 +1,40 @@
# Tars2Node
`tars2node` 可以将 Tars IDL 定义文件转换为 JavaScript 语言所使用的版本,结合 [@tars/stream](https://www.npmjs.com/package/@tars/stream) 模块执行编解码操作。
如您有 Tars RPC 需求可结合 [@tars/rpc](https://www.npmjs.com/package/@tars/rpc) 模块进行调用。
## 用法
直接使用 build 目录中的 `tars2node` 预编译程序即可Linux 平台)。
```bash
tars2node [OPTIONS] tarsfile
```
## 选项
> Options:
> --version print tars2node version
> --rpc-path=[DIRECTORY] specify the path of rpc module.
> --stream-path=[DIRECTORY[] specify the path of stream module.
> --allow-reserved-namespace allow you to use reserved word as a namespace.
> --dir=DIRECTORY generate source file to DIRECTORY.
> --relative use current path.
> --tarsBase=DIRECTORY where to search tars files.
> --r generate source all tars files.
> --r-minimal minimize the dependent members.
> --r-reserved list of names(split by ",") that should be keeped.
> --client just for client side source file.
> --server just for server side source file.
> --dts generate d.ts file.
> --use-string-represent use string represent long type.
> --string-binary-encoding get string raw bytes <BinBuffer>.
> --optimize=[0|s] support "s" to reduce code size, default is 0.
## 从源码编译
1. 安装对应平台的 build-essential
2. 安装 [CMake](https://cmake.org/)
3. 在源码 build 目录下执行 `cmake ../ && make`

BIN
build/tars2node Executable file

Binary file not shown.

273
include/code_generator.h Normal file
View File

@ -0,0 +1,273 @@
/**
* 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.
*/
#ifndef _CODEGENERATOR_H
#define _CODEGENERATOR_H
#include "parse.h"
#include "util/tc_file.h"
#include "util/tc_encoder.h"
#include <set>
#ifndef TAB
#define TAB g_parse->getTab()
#endif
#ifndef INC_TAB
#define INC_TAB g_parse->incTab()
#endif
#ifndef DEL_TAB
#define DEL_TAB g_parse->delTab()
#endif
#define TO_LOWER_STRING(str) TC_Common::lower(str)
#define DEFINE_STRING(str) string(CSTR(str))
#define CSTR(str) #str
#define IDL_NAMESPACE_STR DEFINE_STRING(IDL_NAMESPACE)
#define GET_CONST_GRAMMAR_PTR_V(name, ptr) \
ptr->getConst##name##Ptr()
#define GET_CONST_GRAMMAR_PTR_BASE(name, ptr) \
GET_CONST_GRAMMAR_PTR_V(name, ptr)
#define GET_CONST_GRAMMAR_PTR(ptr) \
GET_CONST_GRAMMAR_PTR_BASE(GRAMMAR_NAME, ptr)
#define CONST_GRAMMAR_V(name, val) \
Const##name::val
#define CONST_GRAMMAR_BASE(name, val) \
CONST_GRAMMAR_V(name, val)
#define CONST_GRAMMAR(val) \
CONST_GRAMMAR_BASE(GRAMMAR_NAME, val)
#define PROTOCOL_V(space, protocol, type) \
space + "Stream." + protocol + "." + TC_Common::upper(protocol) + "_" + type
#define PROTOCOL_SIMPLE PROTOCOL_V(IDL_NAMESPACE_STR, PROTOCOL_NAME, "SIMPLE")
#define PROTOCOL_COMPLEX PROTOCOL_V(IDL_NAMESPACE_STR, PROTOCOL_NAME, "COMPLEX")
#define PROTOCOL_VAR TO_LOWER_STRING(PROTOCOL_NAME)
using namespace TC_NAMESPACE;
class CodeGenerator
{
public:
CodeGenerator()
: uiNameIndex(0),
_sRpcPath(RPC_MODULE_PATH),
_sStreamPath(STREAM_MODULE_PATH),
_sToPath("./"),
_bClient(false),
_bServer(false),
_bRecursive(false),
_bUseSpecialPath(false),
_bUseStringRepresent(false),
_bStringBinaryEncoding(false),
_bMinimalMembers(false),
_bDTS(false),
_iOptimizeLevel(O0) {}
void createFile(const string& file, const bool bEntry = true);
void setRpcPath(const string& sPath) { _sRpcPath = sPath; }
void setStreamPath(const string& sPath) { _sStreamPath = sPath; }
void setEnableClient(bool bEnable) { _bClient = bEnable; }
void setEnableServer(bool bEnable) { _bServer = bEnable; }
void setTargetPath(const string& sPath) { _sToPath = sPath + "/"; }
void setRecursive(bool bEnable) { _bRecursive = bEnable; }
void setUseSpecialPath(bool bEnable) { _bUseSpecialPath = bEnable; }
void setUseStringRepresent(bool bEnable) { _bUseStringRepresent = bEnable; }
void setStringBinaryEncoding(bool bEnable) { _bStringBinaryEncoding = bEnable; }
void setMinimalMembers(bool bEnable) { _bMinimalMembers = bEnable; }
void setDependent(set<string>& deps) { _depMembers = deps; }
void setEnableDTS(bool bEnable) { _bDTS = bEnable; }
void setOptimize(int iLevel) { _iOptimizeLevel = iLevel; }
enum OPTIMIZE_LEVEL {O0 = 0, Os};
private:
struct ImportFileType
{
enum TYPE_T {EN_ENUM = 10000, EN_ENUM_VALUE, EN_STRUCT};
int iType;
string sNamespace;
string sTypeName;
string sName;
};
struct ImportFile
{
string sFile;
string sModule;
map<string, ImportFileType> mapVars;
};
uint32_t uiNameIndex;
map<string, ImportFile> _mapFiles;
set<string> _depMembers;
void scan(const string & sFile, bool bNotPrefix);
string makeName();
string findName(const string & sNamespace, const string & sName);
private:
string toFunctionName(const TypeIdPtr & pPtr, const string &sAction);
string getDataType(const TypePtr& pPtr);
string getClassName(const TypePtr& pPtr);
string getDtsType(const TypePtr &pPtr, const bool bStream = true);
string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace);
string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace, const bool bGlobal);
private:
string generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert);
string generateJS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream);
string generateJS(const EnumPtr &pPtr, const string &sNamespace);
string generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert);
bool generateJS(const ContextPtr &pPtr);
private:
string generateJSProxy(const NamespacePtr &nPtr, bool &bNeedRpc, bool &bNeedStream);
string generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr);
string generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr);
bool generateJSProxy(const ContextPtr &pPtr);
private:
string generateJSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert);
string generatePing(const NamespacePtr &nPtr, const InterfacePtr &pPtr);
string generateAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr);
string generateDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr);
string generateJSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr);
string generateJSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr);
bool generateJSServer(const ContextPtr &pPtr);
private:
string generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr);
string generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr);
string generateJSServerImp(const ContextPtr &cPtr, const NamespacePtr &nPtr);
void generateJSServerImp(const ContextPtr &cPtr);
private:
string generateDTS(const StructPtr &pPtr, const string &sNamespace);
string generateDTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream);
string generateDTS(const EnumPtr &pPtr, const string &sNamespace);
string generateDTS(const NamespacePtr &pPtr, bool &bNeedStream);
string generateDTS(const NamespacePtr &pPtr, const string &sContent);
void generateDTS(const ContextPtr &cPtr);
private:
string generateDTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc);
string generateDTSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr);
void generateDTSServer(const ContextPtr &cPtr);
private:
string generateDTSProxyInfo();
string generateDTSProxy(const InterfacePtr &pPtr);
string generateDTSProxy(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc);
void generateDTSProxy(const ContextPtr &pPtr);
private:
void makeUTF8File(const string & sFileName, const string & sFileContent);
bool isSimple(const TypePtr & pPtr) const;
bool isBinBuffer(const TypePtr & pPtr) const;
bool isRawOrString(const TypePtr & pPtr) const;
bool isDependent(const string & sNamespace, const string & sName) const;
string getRealFileInfo(const string & sPath);
string printHeaderRemark(const string & sTypeName);
private:
string _sRpcPath;
string _sStreamPath;
string _sToPath;
bool _bClient;
bool _bServer;
bool _bRecursive;
bool _bUseSpecialPath;
bool _bUseStringRepresent;
bool _bStringBinaryEncoding;
bool _bMinimalMembers;
bool _bEntry;
string _sIdlFile;
bool _bDTS;
int _iOptimizeLevel;
};
#endif

90
src/code_generator.cpp Normal file
View File

@ -0,0 +1,90 @@
/**
* 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 "code_generator.h"
string CodeGenerator::printHeaderRemark(const string &sTypeName)
{
ostringstream s;
s << "// **********************************************************************" << endl;
s << "// Parsed By " << IDL_NAMESPACE_STR << "Parser(" << PARSER_VERSION << "), Generated By " << EXECUTE_FILENAME << "(" << GENERATOR_VERSION << ")" << endl;
s << "// " << IDL_NAMESPACE_STR << "Parser Maintained By <" << TC_Common::upper(IDL_NAMESPACE_STR) << "> and " << EXECUTE_FILENAME << " Maintained By <superzheng>" << endl;
s << "// Generated from \"" << TC_File::extractFileName(_sIdlFile) << "\" by " <<
(_bEntry ? sTypeName : (_bMinimalMembers ? "Minimal" : "Relation")) << " Mode" << endl;
s << "// **********************************************************************" << endl;
s << endl;
s << "/* eslint-disable */" << endl;
s << endl;
return s.str();
}
void CodeGenerator::createFile(const string &file, const bool bEntry)
{
_sIdlFile = getRealFileInfo(file);
_bEntry = bEntry;
g_parse->parse(_sIdlFile);
vector<ContextPtr> contexts = g_parse->getContexts();
for(size_t i = 0; i < contexts.size(); i++)
{
if (_sIdlFile == contexts[i]->getFileName())
{
scan(_sIdlFile, true); //分析枚举值、结构体所在的文件
if (!_bClient && !_bServer)
{
generateJS(contexts[i]); //生成当前文件的编解码文件
if(_bDTS) generateDTS(contexts[i]); //生成 typescript 描述文件
}
if (_bClient)
{
if(!generateJSProxy(contexts[i])) return; //生成当前文件的客户端代理类文件
if(_bDTS) generateDTSProxy(contexts[i]); //生成客户端 typescript 描述文件
}
if (_bServer)
{
if(!generateJSServer(contexts[i])) return; //生成当前文件的服务端代理类文件
if(_bDTS) generateDTSServer(contexts[i]); //生成服务端 typescript 描述文件
generateJSServerImp(contexts[i]); //生成当前文件的服务端实现类文件
}
vector<string> files = contexts[i]->getIncludes();
for (size_t ii = 0; _bRecursive && ii < files.size(); ii++)
{
CodeGenerator node;
node.setRpcPath(_sRpcPath);
node.setStreamPath(_sStreamPath);
node.setTargetPath(_sToPath);
node.setRecursive(_bRecursive);
node.setUseSpecialPath(_bUseSpecialPath);
node.setUseStringRepresent(_bUseStringRepresent);
node.setStringBinaryEncoding(_bStringBinaryEncoding);
node.setMinimalMembers(_bMinimalMembers);
node.setDependent(_depMembers);
node.setEnableDTS(_bDTS);
node.createFile(files[ii], false);
}
}
}
}

38
src/file_util.cpp Normal file
View File

@ -0,0 +1,38 @@
/**
* 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 "code_generator.h"
void CodeGenerator::makeUTF8File(const string& sFileName, const string& sFileContent)
{
try {
char header[3] = {(char)(0xef), (char)(0xbb), (char)(0xbf)};
string sData(header, 3);
sData += TC_Encoder::gbk2utf8(sFileContent);
TC_File::save2file(sFileName, sData.c_str());
} catch (...) {
cout << "Convert GBK to UTF8 failed, current encoding is GBK.";
TC_File::save2file(sFileName, sFileContent.c_str());
}
}
string CodeGenerator::getRealFileInfo(const string& sPath)
{
return TC_File::extractFilePath(sPath) + TC_File::excludeFileExt(TC_File::extractFileName(sPath)) + "." + TC_Common::lower(IDL_TYPE);
}

398
src/gen_js.cpp Normal file
View File

@ -0,0 +1,398 @@
/**
* 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 "code_generator.h"
string CodeGenerator::generateJS(const EnumPtr &pPtr, const string &sNamespace)
{
ostringstream s;
s << TAB << sNamespace << "." << pPtr->getId() << " = {" << endl;
INC_TAB;
//成员变量
int nenum = -1;
bool bDependent = false;
vector<TypeIdPtr>& member = pPtr->getAllMemberPtr();
for (size_t i = 0; i < member.size(); i++)
{
bDependent |= isDependent(sNamespace, member[i]->getId());
if (member[i]->hasDefault())
{
nenum = TC_Common::strto<int>(member[i]->def());
}
else
{
nenum++;
}
s << TAB << "\"" << member[i]->getId() << "\" : " << TC_Common::tostr(nenum) << "," << endl;
}
s << TAB << "\"_classname\" : \"" << sNamespace << "." << pPtr->getId() << "\"" << endl;
DEL_TAB;
s << TAB << "};" << endl;
//函数
s << TAB << sNamespace << "." << pPtr->getId() << "._write = function(os, tag, val) { return os.writeInt32(tag, val); };" << endl;
s << TAB << sNamespace << "." << pPtr->getId() << "._read = function(is, tag, def) { return is.readInt32(tag, true, def); };" << endl;
if (!_bMinimalMembers || _bEntry || bDependent || isDependent(sNamespace, pPtr->getId())) {
return s.str();
} else {
return "";
}
}
string CodeGenerator::generateJS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream)
{
if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getTypeIdPtr()->getId()))
{
return "";
}
ostringstream s;
if (_bStringBinaryEncoding && GET_CONST_GRAMMAR_PTR(pPtr)->t == CONST_GRAMMAR(STRING))
{
bNeedStream = true;
}
s << TAB << sNamespace << "." << pPtr->getTypeIdPtr()->getId() << " = " << getDefault(pPtr->getTypeIdPtr(), GET_CONST_GRAMMAR_PTR(pPtr)->v, sNamespace, false) << ";" << endl;
return s.str();
}
string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert)
{
if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId()))
{
return "";
}
ostringstream s;
vector<TypeIdPtr>& member = pPtr->getAllMemberPtr();
s << TAB << sNamespace << "." << pPtr->getId() << " = function() {"<< endl;
INC_TAB;
for (size_t i = 0; i < member.size(); i++)
{
s << TAB << "this." << member[i]->getId() << " = " << getDefault(member[i], member[i]->def(), sNamespace) << ";" << endl;
}
{
s << TAB << "this._classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl;
}
DEL_TAB;
s << TAB << "};" << endl;
s << TAB << sNamespace << "." << pPtr->getId() << "._classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl;
string sProto = TC_Common::replace(pPtr->getSid(), "::", ".");
s << TAB << sProto << "._write = function (os, tag, value) { os.writeStruct(tag, value); };" << endl;
s << TAB << sProto << "._read = function (is, tag, def) { return is.readStruct(tag, true, def); };" << endl;
//_readFrom
s << TAB << sNamespace << "." << pPtr->getId() << "._readFrom = function (is) {" << endl;
INC_TAB;
s << TAB << "var tmp = new " << sNamespace << "." << pPtr->getId() << ";" << endl;
for (size_t i = 0; i < member.size(); i++)
{
string sFuncName = toFunctionName(member[i], "read");
s << TAB << "tmp." << member[i]->getId() << " = is." << sFuncName << "(" << member[i]->getTag()
<< ", " << (member[i]->isRequire()?"true":"false") << ", ";
if (isSimple(member[i]->getTypePtr()))
{
s << getDefault(member[i], member[i]->def(), sNamespace)
<< (isRawOrString(member[i]->getTypePtr()) ? ", 1" : "");
}
else
{
s << getDataType(member[i]->getTypePtr());
}
s << ");" << endl;
}
s << TAB << "return tmp;" << endl;
DEL_TAB;
s << TAB << "};" << endl;
//_writeTo
s << TAB << sNamespace << "." << pPtr->getId() << ".prototype._writeTo = function (os) {" << endl;
INC_TAB;
for (size_t i = 0; i < member.size(); i++)
{
string sFuncName = toFunctionName(member[i], "write");
s << TAB << "os." << sFuncName << "(" << member[i]->getTag() << ", this." << member[i]->getId()
<< (isRawOrString(member[i]->getTypePtr()) ? ", 1" : "") << ");" << endl;
}
DEL_TAB;
s << TAB << "};" << endl;
/*
* Size Optimize:
* Remove <mutil_map> support.
* Remove toBinBuffer, readFromObject, toObject, new, create members.
*/
if (_iOptimizeLevel == Os)
{
return s.str();
}
//_equal
vector<string> key = pPtr->getKey();
s << TAB << sNamespace << "." << pPtr->getId() << ".prototype._equal = function (" << (key.size() > 0 ? "anItem" : "") << ") {" << endl;
INC_TAB;
if (key.size() > 0)
{
s << TAB << "return ";
for (size_t i = 0; i < key.size(); i++)
{
for (size_t ii =0; ii < member.size(); ii++)
{
if (key[i] != member[ii]->getId())
{
continue;
}
if (isSimple(member[i]->getTypePtr()))
{
s << (i==0?"":TAB + TAB) << "this." << key[i] << " === " << "anItem." << key[i];
}
else
{
s << (i==0?"":TAB + TAB) << "this._equal(" << "anItem)";
}
}
if (i != key.size() - 1)
{
s << " && " << endl;
}
}
s << ";" << endl;
}
else
{
bNeedAssert = true;
s << TAB << "assert.fail(\"this structure not define key operation\");" << endl;
}
DEL_TAB;
s << TAB << "};" << endl;
//_genKey
s << TAB << sNamespace << "." << pPtr->getId() << ".prototype._genKey = function () {" << endl;
INC_TAB;
s << TAB << "if (!this._proto_struct_name_) {" << endl;
INC_TAB;
s << TAB << "this._proto_struct_name_ = \"STRUCT\" + Math.random();" << endl;
DEL_TAB;
s << TAB << "}" << endl;
s << TAB << "return this._proto_struct_name_;" << endl;
DEL_TAB;
s << TAB << "};" << endl;
//toObject
s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.toObject = function() { "<< endl;
INC_TAB;
s << TAB << "return {" << endl;
for (size_t i = 0; i < member.size(); i++)
{
INC_TAB;
if (i > 0 && i < member.size()) {
s << "," << endl;
}
if (isSimple(member[i]->getTypePtr())) {
s << TAB << "\"" << member[i]->getId() << "\" : this." << member[i]->getId();
}
else {
s << TAB << "\"" << member[i]->getId() << "\" : this." << member[i]->getId() << ".toObject()";
}
DEL_TAB;
}
s << endl;
s << TAB << "};" << endl;
DEL_TAB;
s << TAB << "};" << endl;
//readFromJson
s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.readFromObject = function(json) { "<< endl;
INC_TAB;
for (size_t i = 0; i < member.size(); i++)
{
if (isSimple(member[i]->getTypePtr())) {
s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << ");" << endl;
} else {
s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << "));" << endl;
}
}
DEL_TAB;
s << TAB << "};" << endl;
//toBinBuffer
s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.toBinBuffer = function () {" << endl;
INC_TAB;
s << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
s << TAB << "this._writeTo(os);" << endl;
s << TAB << "return os.getBinBuffer();" << endl;
DEL_TAB;
s << TAB << "};" << endl;
//new
s << TAB << sNamespace << "." << pPtr->getId() << ".new = function () {" << endl;
INC_TAB;
s << TAB << "return new " << sNamespace << "." << pPtr->getId() << "();" << endl;
DEL_TAB;
s << TAB << "};" << endl;
//create
s << TAB << sNamespace << "." << pPtr->getId() << ".create = function (is) {" << endl;
INC_TAB;
s << TAB << "return " << sNamespace << "." << pPtr->getId() << "._readFrom(is);" << endl;
DEL_TAB;
s << TAB << "};" << endl;
return s.str();
}
string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert)
{
ostringstream sstr;
vector<StructPtr> ss(pPtr->getAllStructPtr());
for (size_t last = 0; last != ss.size() && ss.size() != 0;)
{
last = ss.size();
for (vector<StructPtr>::iterator iter=ss.begin(); iter!=ss.end();)
{
string str = generateJS(*iter, pPtr->getId(), bNeedAssert);
if (!str.empty()) {
sstr << str << endl;
iter = ss.erase(iter);
} else {
iter++;
}
}
}
ostringstream cstr;
vector<ConstPtr> &cs = pPtr->getAllConstPtr();
for (size_t i = 0; i < cs.size(); i++)
{
cstr << generateJS(cs[i], pPtr->getId(), bNeedStream);
}
ostringstream estr;
vector<EnumPtr> & es = pPtr->getAllEnumPtr();
for (size_t i = 0; i < es.size(); i++)
{
estr << generateJS(es[i], pPtr->getId());
}
ostringstream str;
if (!estr.str().empty()) str << estr.str() << endl;
if (!cstr.str().empty()) str << cstr.str() << endl;
if (!sstr.str().empty())
{
bNeedStream = true;
str << sstr.str() << endl;
}
return str.str();
}
bool CodeGenerator::generateJS(const ContextPtr &pPtr)
{
vector<NamespacePtr> namespaces = pPtr->getNamespaces();
ostringstream istr;
set<string> setNamespace;
for(size_t i = 0; i < namespaces.size(); i++)
{
if (setNamespace.count(namespaces[i]->getId()) == 0)
{
istr << TAB << "var " << namespaces[i]->getId() << " = " << namespaces[i]->getId() << " || {};" << endl;
istr << TAB << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl << endl;
setNamespace.insert(namespaces[i]->getId());
}
}
//先生成编解码体
ostringstream estr;
bool bNeedAssert = false;
bool bNeedStream = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
estr << generateJS(namespaces[i], bNeedStream, bNeedAssert);
}
if (estr.str().empty())
{
return false;
}
//再生成导入模块
ostringstream ostr;
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
if (it->second.sModule.empty()) continue;
if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl;
}
//生成文件内容
ostringstream sstr;
sstr << printHeaderRemark("Structure");
sstr << "\"use strict\";" << endl << endl;
if (bNeedAssert)
{
sstr << "var assert = require(\"assert\");" << endl;
}
if (bNeedStream)
{
sstr << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl;
}
sstr << ostr.str() << endl;
sstr << istr.str();
sstr << estr.str() << endl;
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + IDL_TYPE + ".js";
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, sstr.str());
return true;
}

239
src/gen_js_dts.cpp Normal file
View File

@ -0,0 +1,239 @@
/**
* 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 "code_generator.h"
string CodeGenerator::generateDTS(const EnumPtr &pPtr, const string &sNamespace)
{
ostringstream s;
INC_TAB;
s << TAB << "enum " << pPtr->getId() << " {" << endl;
INC_TAB;
//成员变量
int nenum = -1;
bool bDependent = false;
vector<TypeIdPtr>& member = pPtr->getAllMemberPtr();
for (size_t i = 0; i < member.size(); i++)
{
bDependent |= isDependent(sNamespace, member[i]->getId());
if (member[i]->hasDefault())
{
nenum = TC_Common::strto<int>(member[i]->def());
}
else
{
nenum++;
}
s << TAB << "\"" << member[i]->getId() << "\" = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl;
}
DEL_TAB;
s << TAB << "}" << endl;
DEL_TAB;
if (!_bMinimalMembers || _bEntry || bDependent || isDependent(sNamespace, pPtr->getId())) {
return s.str();
} else {
return "";
}
}
string CodeGenerator::generateDTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream)
{
if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getTypeIdPtr()->getId()))
{
return "";
}
ostringstream s;
if (_bStringBinaryEncoding && GET_CONST_GRAMMAR_PTR(pPtr)->t == CONST_GRAMMAR(STRING))
{
bNeedStream = true;
}
INC_TAB;
s << TAB << "const " << pPtr->getTypeIdPtr()->getId() << ":"
<< getDtsType(pPtr->getTypeIdPtr()->getTypePtr()) << ";"
<< endl;
DEL_TAB;
return s.str();
}
string CodeGenerator::generateDTS(const StructPtr &pPtr, const string &sNamespace)
{
if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId()))
{
return "";
}
string sStructName = pPtr->getId() + "$OBJ";
vector<TypeIdPtr> &member = pPtr->getAllMemberPtr();
ostringstream s;
INC_TAB;
s << TAB << "class " << pPtr->getId() << " {" << endl;
INC_TAB;
for (size_t i = 0; i < member.size(); i++)
{
s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << getDtsType(member[i]->getTypePtr()) << ";" << endl;
}
if (member.size() > 0)
{
s << endl;
}
/*
* Size Optimize:
* Remove <mutil_map> support.
* Remove toBinBuffer, readFromObject, toObject, new, create members.
*/
if (_iOptimizeLevel != Os)
{
s << TAB << "toObject(): " << sStructName << ";" << endl;
s << TAB << "readFromObject(json: " << sStructName << "): void;" << endl;
s << TAB << "toBinBuffer(): " << IDL_NAMESPACE_STR << "Stream.BinBuffer;" << endl;
s << TAB << "static new(): " << pPtr->getId() << ";" << endl;
s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream): " << pPtr->getId() << ";" << endl;
}
DEL_TAB;
s << TAB << "}" << endl;
s << TAB << "interface " << sStructName << " {" << endl;
INC_TAB;
for (size_t i = 0; i < member.size(); i++)
{
const string &sType = getDtsType(member[i]->getTypePtr(), false);
if (!sType.empty())
{
s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << sType << ";" << endl;
}
}
DEL_TAB;
s << TAB << "}" << endl;
DEL_TAB;
return s.str();
}
string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream)
{
//结构
ostringstream sstr;
vector<StructPtr> ss(pPtr->getAllStructPtr());
for (size_t last = 0; last != ss.size() && ss.size() != 0;)
{
last = ss.size();
for (vector<StructPtr>::iterator iter=ss.begin(); iter!=ss.end();)
{
string str = generateDTS(*iter, pPtr->getId());
if (!str.empty())
{
sstr << str << endl;
iter = ss.erase(iter);
}
else
{
iter++;
}
}
}
//常量
ostringstream cstr;
vector<ConstPtr> &cs = pPtr->getAllConstPtr();
for (size_t i = 0; i < cs.size(); i++)
{
cstr << generateDTS(cs[i], pPtr->getId(), bNeedStream);
}
//枚举
ostringstream estr;
vector<EnumPtr> &es = pPtr->getAllEnumPtr();
for (size_t i = 0; i < es.size(); i++)
{
estr << generateDTS(es[i], pPtr->getId());
}
ostringstream kstr;
if (!estr.str().empty()) kstr << estr.str() << endl;
if (!cstr.str().empty()) kstr << cstr.str() << endl;
if (!sstr.str().empty())
{
bNeedStream = true;
kstr << sstr.str();
}
return kstr.str();
}
string CodeGenerator::generateDTS(const NamespacePtr &pPtr, const string &sContent)
{
ostringstream str;
if (!sContent.empty())
{
str << "export declare namespace " << pPtr->getId() << " {" << endl;
str << sContent;
str << "}" << endl << endl;
}
return str.str();
}
void CodeGenerator::generateDTS(const ContextPtr &pPtr)
{
vector<NamespacePtr> namespaces = pPtr->getNamespaces();
//先生成编解码体
ostringstream estr;
bool bNeedStream = false;
for (size_t i = 0; i < namespaces.size(); i++)
{
estr << generateDTS(namespaces[i], generateDTS(namespaces[i], bNeedStream));
}
if (estr.str().empty())
{
return;
}
//再生成导入模块
ostringstream ostr;
if (bNeedStream)
{
ostr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl;
}
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
if (it->second.sModule.empty()) continue;
if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl;
}
//生成文件内容
ostringstream sstr;
sstr << printHeaderRemark("Structure");
sstr << ostr.str() << endl;
sstr << estr.str() << endl;
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + IDL_TYPE + ".d.ts";
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, sstr.str());
}

549
src/gen_proxy.cpp Normal file
View File

@ -0,0 +1,549 @@
/**
* 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 "code_generator.h"
#define INVOKE_RETURN(protocol, prefix, params) \
str << TAB << "return this._worker." << TC_Common::lower(protocol) << "_invoke(\"" << oPtr->getId() << "\", "; \
str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "E"; \
str << "(" << sParams << params << "), arguments[arguments.length - 1], "; \
str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF" << ").then("; \
str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "D, "; \
str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER);" << endl;
#define PROTOCOL_PARAMS (sParams.empty() ? "" : ", ") << "version"
struct SortOperation
{
bool operator()(const OperationPtr &o1, const OperationPtr &o2)
{
return o1->getId() < o2->getId();
}
};
string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
{
ostringstream str;
vector<ParamDeclPtr> & vParamDecl = oPtr->getAllParamDeclPtr();
bool bHasParamOut = false;
string sParams = "";
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (vParamDecl[i]->isOut())
{
continue;
}
sParams += (sParams.empty()?"":", ") + vParamDecl[i]->getTypeIdPtr()->getId();
}
//SETP01 生成函数声明Interface = IF
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF = {" << endl;
INC_TAB;
str << TAB << "\"name\" : \"" << oPtr->getId() << "\"," << endl;
str << TAB << "\"return\" : \"" << getClassName(oPtr->getReturnPtr()->getTypePtr()) << "\"," << endl;
str << TAB << "\"arguments\" : [";
for (size_t i = 0; i < vParamDecl.size(); i++)
{
str << (i > 0 ? ", {" : "{") << endl;
INC_TAB;
str << TAB << "\"name\" : \"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"," << endl;
str << TAB << "\"class\" : \"" << getClassName(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << "\"," << endl;
if (vParamDecl[i]->isOut())
{
bHasParamOut = true;
str << TAB << "\"direction\" : \"out\"" << endl;
}
else
{
str << TAB << "\"direction\" : \"in\"" << endl;
}
DEL_TAB;
str << TAB << "}";
}
str << "]" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//SETP02 生成 IDL 编码接口IDL Encoder = IE
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IE = function (" << sParams << ") {" << endl;
INC_TAB;
str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (vParamDecl[i]->isOut()) continue;
str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "("
<< (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId()
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl;
// 写入 Dependent 列表
getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
}
str << TAB << "return os.getBinBuffer();" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//STEP03 生成 IDL 解码函数IDL Decoder = ID
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ID = function (data) {" << endl;
INC_TAB;
str << TAB << "try {" << endl;
INC_TAB;
if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut)
{
str << TAB << "var is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(data.response.sBuffer);" << endl;
}
str << TAB << "return {" << endl;
INC_TAB;
str << TAB << "\"request\" : data.request," << endl;
str << TAB << "\"response\" : {" << endl;
INC_TAB;
str << TAB << "\"costtime\" : data.request.costtime";
if (oPtr->getReturnPtr()->getTypePtr())
{
str << "," << endl;
str << TAB << "\"return\""
<< " : is." << toFunctionName(oPtr->getReturnPtr(), "read") << "(0, true, ";
if (isSimple(oPtr->getReturnPtr()->getTypePtr()))
{
str << getDefault(oPtr->getReturnPtr(), oPtr->getReturnPtr()->def(), nPtr->getId())
<< (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "");
}
else
{
str << getDataType(oPtr->getReturnPtr()->getTypePtr());
}
str << ")";
}
if (bHasParamOut)
{
str << "," << endl;
str << TAB << "\"arguments\" : {" << endl;
INC_TAB;
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (!vParamDecl[i]->isOut()) continue;
str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""
<< " : is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "(" << (i + 1) << ", true, ";
if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
{
str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId())
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "");
}
else
{
str << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
}
str << ")";
if (i == vParamDecl.size() - 1)
{
str << endl;
}
else
{
str << "," << endl;
}
}
DEL_TAB;
str << TAB << "}";
}
str << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl;
DEL_TAB;
str << TAB << "} catch (e) {" << endl;
INC_TAB;
str << TAB << "throw {" << endl;
INC_TAB;
str << TAB << "\"request\" : data.request," << endl;
str << TAB << "\"response\" : {" << endl;
INC_TAB;
str << TAB << "\"costtime\" : data.request.costtime," << endl;
str << TAB << "\"error\" : {" << endl;
INC_TAB;
str << TAB << "\"code\" : " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR," << endl;
str << TAB << "\"message\" : e.message" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//SETP04 生成 Protocol 编码接口Protocol Encoder = PE
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PE = function ("
<< sParams << (sParams.empty() ? "" : ", ") << "__$PROTOCOL$VERSION) {" << endl;
INC_TAB;
str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = __$PROTOCOL$VERSION;" << endl;
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (vParamDecl[i]->isOut()) continue;
str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\""
<< vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId()
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl;
// 写入 Dependent 列表
getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
}
str << TAB << "return " << PROTOCOL_VAR << ";" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
// STEP05 生成 Protocol 解码函数Protocol Decoder = PD
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PD = function (data) {" << endl;
INC_TAB;
str << TAB << "try {" << endl;
INC_TAB;
if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) {
str << TAB << "var " << PROTOCOL_VAR << " = data.response." << PROTOCOL_VAR << ";" << endl;
}
str << TAB << "return {" << endl;
INC_TAB;
str << TAB << "\"request\" : data.request," << endl;
str << TAB << "\"response\" : {" << endl;
INC_TAB;
str << TAB << "\"costtime\" : data.request.costtime";
if (oPtr->getReturnPtr()->getTypePtr())
{
str << "," << endl;
str << TAB << "\"return\" : " << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "read") << "(\"\"";
if (!isSimple(oPtr->getReturnPtr()->getTypePtr()) && !isBinBuffer(oPtr->getReturnPtr()->getTypePtr()))
{
str << ", " << getDataType(oPtr->getReturnPtr()->getTypePtr());
}
str << ", " << getDefault(oPtr->getReturnPtr(), "", nPtr->getId(), true)
<< (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "");
str << ")";
}
if (bHasParamOut)
{
str << "," << endl;
str << TAB << "\"arguments\" : {" << endl;
INC_TAB;
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (!vParamDecl[i]->isOut()) continue;
str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\" : "
<< PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read")
<< "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"";
if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
{
str << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
}
str << ")";
if (i == vParamDecl.size() - 1)
{
str << endl;
}
else
{
str << "," << endl;
}
}
DEL_TAB;
str << TAB << "}";
}
str << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl;
DEL_TAB;
str << TAB << "} catch (e) {" << endl;
INC_TAB;
str << TAB << "throw {" << endl;
INC_TAB;
str << TAB << "\"request\" : data.request," << endl;
str << TAB << "\"response\" : {" << endl;
INC_TAB;
str << TAB << "\"costtime\" : data.request.costtime," << endl;
str << TAB << "\"error\" : {" << endl;
INC_TAB;
str << TAB << "\"code\" : " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR," << endl;
str << TAB << "\"message\" : e.message" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//STEP03 生成框架调用错误处理函数Error Response = ER
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER = function (data) {" << endl;
INC_TAB;
str << TAB << "throw {" << endl;
INC_TAB;
str << TAB << "\"request\" : data.request," << endl;
str << TAB << "\"response\" : {" << endl;
INC_TAB;
str << TAB << "\"costtime\" : data.request.costtime," << endl;
str << TAB << "\"error\" : data.error" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//SETP04 生成函数接口
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy.prototype." << oPtr->getId() << " = function ("
<< sParams << ") {" << endl;
INC_TAB;
str << TAB << "var version = this._worker.version;" << endl;
str << TAB << "if (version === " << PROTOCOL_SIMPLE << " || version === " << PROTOCOL_COMPLEX << ") {" << endl;
INC_TAB;
INVOKE_RETURN(PROTOCOL_VAR, "P", PROTOCOL_PARAMS);
DEL_TAB;
str << TAB << "} else {" << endl;
INC_TAB;
INVOKE_RETURN(IDL_NAMESPACE_STR, "I", "");
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl;
//SETP05 绑定函数声明
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy." << oPtr->getId() << " = "
<< "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF;" << endl;
return str.str();
}
string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr)
{
ostringstream str;
vector<OperationPtr> & vOperation = pPtr->getAllOperationPtr();
sort(vOperation.begin(), vOperation.end(), SortOperation());
for (size_t i = 0; i < vOperation.size(); i++)
{
str << generateJSProxy(nPtr, pPtr, vOperation[i]) << endl;
}
return str.str();
}
string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, bool &bNeedRpc, bool &bNeedStream)
{
ostringstream str;
vector<InterfacePtr> & is = nPtr->getAllInterfacePtr();
for (size_t i = 0; i < is.size(); i++)
{
str << generateJSProxy(nPtr, is[i]) << endl;
}
if (is.size() != 0)
{
bNeedRpc = true;
bNeedStream = true;
}
return str.str();
}
bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr)
{
vector<NamespacePtr> namespaces = cPtr->getNamespaces();
ostringstream istr;
set<string> setNamespace;
for(size_t i = 0; i < namespaces.size(); i++)
{
if (setNamespace.count(namespaces[i]->getId()) == 0)
{
istr << TAB << "var " << namespaces[i]->getId() << " = " << namespaces[i]->getId() << " || {};" << endl;
istr << TAB << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl << endl;
setNamespace.insert(namespaces[i]->getId());
}
}
set<string> setInterface;
for(size_t i = 0; i < namespaces.size(); i++)
{
vector<InterfacePtr> & is = namespaces[i]->getAllInterfacePtr();
for (size_t ii = 0; ii < is.size(); ii++)
{
if (setInterface.count(namespaces[i]->getId() + "::" + is[ii]->getId()) != 0)
{
continue;
}
setInterface.insert(namespaces[i]->getId() + "::" + is[ii]->getId());
istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy = function () {" << endl;
INC_TAB;
istr << TAB << "this._name = undefined;" << endl;
istr << TAB << "this._worker = undefined;" << endl;
DEL_TAB;
istr << TAB << "};" << endl << endl;
istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.setTimeout = function (iTimeout) {" << endl;
INC_TAB;
istr << TAB << "this._worker.timeout = iTimeout;" << endl;
DEL_TAB;
istr << TAB << "};" << endl << endl;
istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.getTimeout = function () {" << endl;
INC_TAB;
istr << TAB << "return this._worker.timeout;" << endl;
DEL_TAB;
istr << TAB << "};" << endl << endl;
istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.setVersion = function (iVersion) {" << endl;
INC_TAB;
istr << TAB << "this._worker.version = iVersion;" << endl;
DEL_TAB;
istr << TAB << "};" << endl << endl;
istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.getVersion = function () {" << endl;
INC_TAB;
istr << TAB << "return this._worker.version;" << endl;
DEL_TAB;
istr << TAB << "};" << endl << endl;
}
}
//先生成编解码 + 代理类
ostringstream estr;
bool bNeedAssert = false;
bool bNeedStream = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
estr << generateJS(namespaces[i], bNeedStream, bNeedAssert);
}
bool bNeedRpc = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
estr << generateJSProxy(namespaces[i], bNeedRpc, bNeedStream);
}
if (estr.str().empty())
{
return false;
}
//再生成导入模块
ostringstream ostr;
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
if (it->second.sModule.empty()) continue;
if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl;
}
//生成文件内容
ostringstream sstr;
sstr << printHeaderRemark("Client");
sstr << "\"use strict\";" << endl << endl;
if (bNeedAssert)
{
sstr << "var assert = require(\"assert\");" << endl;
}
if (bNeedStream)
{
sstr << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl;
}
if (bNeedRpc)
{
sstr << "var " << IDL_NAMESPACE_STR << "Error = require(\"" << _sRpcPath << "\").error;" << endl;
}
sstr << ostr.str() << endl;
sstr << istr.str() << endl;
sstr << estr.str() << endl;
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Proxy.js";
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, sstr.str());
return true;
}
#undef INVOKE_RETURN
#undef PROTOCOL_PARAMS

208
src/gen_proxy_dts.cpp Normal file
View File

@ -0,0 +1,208 @@
/**
* 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 "code_generator.h"
string CodeGenerator::generateDTSProxyInfo()
{
ostringstream str;
INC_TAB;
// Argument
str << TAB << "interface SharedArgumentInfo {" << endl;
INC_TAB;
str << TAB << "name: string;" << endl;
str << TAB << "class: string;" << endl;
str << TAB << "direction: 'in' | 'out';" << endl;
DEL_TAB;
str << TAB << "}" << endl;
// Function
str << TAB << "interface SharedFunctionInfo {" << endl;
INC_TAB;
str << TAB << "name: string;" << endl;
str << TAB << "return: string;" << endl;
str << TAB << "arguments: SharedArgumentInfo[];" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
return str.str();
}
string CodeGenerator::generateDTSProxy(const InterfacePtr &pPtr)
{
vector<OperationPtr> &vOperation = pPtr->getAllOperationPtr();
ostringstream str;
//class
INC_TAB;
str << TAB << "class " << pPtr->getId() << "Proxy {" << endl;
INC_TAB;
str << TAB << "setTimeout(iTimeout: number): void;" << endl;
str << TAB << "getTimeout(): number;" << endl;
str << TAB << "setVersion(iVersion: number): void;" << endl;
str << TAB << "getVersion(): number;" << endl;
for (size_t i = 0; i < vOperation.size(); i++)
{
OperationPtr &oPtr = vOperation[i];
str << TAB << oPtr->getId() << "(";
vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
for (size_t j = 0; j < vParamDecl.size(); j++)
{
if(vParamDecl[j]->isOut())
{
continue;
}
str << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
str << ", ";
}
str << "property?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty): Promise<" << pPtr->getId() << "$" << oPtr->getId() << "$DE>;" << endl;
str << TAB << "static " << oPtr->getId() << ": SharedFunctionInfo;" << endl;
}
DEL_TAB;
str << TAB << "}" << endl;
//interface
for (size_t i = 0; i < vOperation.size(); i++)
{
OperationPtr &oPtr = vOperation[i];
str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$DE {" << endl;
INC_TAB;
str << TAB << "request: object;" << endl;
str << TAB << "response: {" << endl;
INC_TAB;
str << TAB << "costtime: number;" << endl;
if (oPtr->getReturnPtr()->getTypePtr())
{
str << TAB << "return: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()) << ";" << endl;
}
else
{
str << TAB << "return: void;" << endl;
}
vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
bool hasArgs = false;
for (size_t j = 0; j < vParamDecl.size(); j++)
{
if(vParamDecl[j]->isOut()) {
hasArgs = true;
break;
}
}
if(hasArgs)
{
str << TAB << "arguments: {" << endl;
INC_TAB;
for (size_t j = 0; j < vParamDecl.size(); j++)
{
if(!vParamDecl[j]->isOut()) {
continue;
}
str << TAB << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) << ";" << endl;
}
DEL_TAB;
str << TAB << "}" << endl;
}
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "}" << endl;
}
DEL_TAB;
return str.str();
}
string CodeGenerator::generateDTSProxy(const NamespacePtr &nPtr, bool &bNeedStream, bool &bNeedRpc)
{
ostringstream str;
vector<InterfacePtr> &is = nPtr->getAllInterfacePtr();
if (is.size() > 0)
{
bNeedStream = true;
bNeedRpc = true;
str << generateDTSProxyInfo() << endl;
}
for (size_t i = 0; i < is.size(); i++)
{
str << generateDTSProxy(is[i]) << endl;
}
return str.str();
}
void CodeGenerator::generateDTSProxy(const ContextPtr &cPtr)
{
vector<NamespacePtr> namespaces = cPtr->getNamespaces();
//先生成编解码 + 代理类
ostringstream estr;
bool bNeedStream = false;
bool bNeedRpc = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
ostringstream kstr;
kstr << generateDTS(namespaces[i], bNeedStream);
kstr << generateDTSProxy(namespaces[i], bNeedStream, bNeedRpc);
estr << generateDTS(namespaces[i], kstr.str());
}
if (estr.str().empty())
{
return;
}
//再生成导入模块
ostringstream ostr;
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
if (it->second.sModule.empty()) continue;
if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl;
}
//生成文件内容
ostringstream sstr;
sstr << printHeaderRemark("Client");
if (bNeedStream)
{
sstr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl;
}
if (bNeedRpc)
{
sstr << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl;
}
sstr << ostr.str() << endl;
sstr << estr.str() << endl;
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Proxy.d.ts";
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, sstr.str());
}

381
src/gen_server.cpp Normal file
View File

@ -0,0 +1,381 @@
/**
* 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 "code_generator.h"
string CodeGenerator::generatePing(const NamespacePtr &nPtr, const InterfacePtr &pPtr)
{
ostringstream str;
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping$RE = function (_ret) {" << endl;
INC_TAB;
str << TAB << "if (this.getRequestVersion() === " << PROTOCOL_SIMPLE << " || this.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl;
INC_TAB;
str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl;
str << TAB << PROTOCOL_VAR << ".writeInt32(\"\", _ret);" << endl << endl;
str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl;
DEL_TAB;
str << TAB << "} else {" << endl;
INC_TAB;
str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
str << TAB << "os.writeInt32(0, _ret);" << endl << endl;
str << TAB << "this.doResponse(os.getBinBuffer());" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.__" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping = function (current) {" << endl;
INC_TAB;
str << TAB << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping$RE.call(current, 0);" << endl << endl;
str << TAB << "return " << IDL_NAMESPACE_STR << "Error.SUCCESS;" << endl;
DEL_TAB;
str << TAB << "};" << endl;
return str.str();
}
string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
{
ostringstream str;
string sParams = "";
if (oPtr->getReturnPtr()->getTypePtr())
{
sParams += "_ret";
// 写入 Dependent 列表
getDataType(oPtr->getReturnPtr()->getTypePtr());
}
vector<ParamDeclPtr> & vParamDecl = oPtr->getAllParamDeclPtr();
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (!vParamDecl[i]->isOut()) continue;
sParams += (sParams.empty()?"":", ") + vParamDecl[i]->getTypeIdPtr()->getId();
}
str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$RE = function (" << sParams << ") {" << endl;
INC_TAB;
if (sParams.empty())
{
str << TAB << "this.doResponse(new " << IDL_NAMESPACE_STR << "Stream.BinBuffer());" << endl;
DEL_TAB;
str << TAB << "};" << endl;
return str.str();
}
str << TAB << "if (this.getRequestVersion() === " << PROTOCOL_SIMPLE << " || this.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl;
INC_TAB;
str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl;
if (oPtr->getReturnPtr()->getTypePtr())
{
str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret"
<< (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl;
}
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (!vParamDecl[i]->isOut()) continue;
str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\""
<< vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId()
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl;
}
str << endl;
str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl;
DEL_TAB;
str << TAB << "} else {" << endl;
INC_TAB;
str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
if (oPtr->getReturnPtr()->getTypePtr())
{
str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret"
<< (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl;
}
for (size_t i = 0; i < vParamDecl.size(); i++)
{
if (!vParamDecl[i]->isOut()) continue;
str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "("
<< (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId()
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl;
}
str << endl;
str << TAB << "this.doResponse(os.getBinBuffer());" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl;
return str.str();
}
string CodeGenerator::generateDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
{
ostringstream str;
vector<ParamDeclPtr> & vParamDecl = oPtr->getAllParamDeclPtr();
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.__" << oPtr->getId() << " = function (current" << (vParamDecl.size() != 0 ? ", binBuffer" : "") << ") {" << endl;
INC_TAB;
ostringstream dstr;
for (size_t i = 0; i < vParamDecl.size(); i++)
{
dstr << TAB << "var " << vParamDecl[i]->getTypeIdPtr()->getId() << " = null;" << endl;
}
if (vParamDecl.size() != 0)
{
dstr << endl;
}
dstr << TAB << "if (current.getRequestVersion() === " << PROTOCOL_SIMPLE << " || current.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl;
INC_TAB;
dstr << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
dstr << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = current.getRequestVersion();" << endl;
dstr << TAB << PROTOCOL_VAR << ".decode(binBuffer);" << endl;
for (size_t i = 0; i < vParamDecl.size(); i++)
{
dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
<< " = " << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read")
<< "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"";
if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
{
dstr << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
}
if (vParamDecl[i]->isOut())
{
dstr << ", " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true)
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "");
}
dstr << ");" << endl;
}
DEL_TAB;
dstr << TAB << "} else {" << endl;
INC_TAB;
dstr << TAB << "var is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(binBuffer);" << endl;
string sParams = "";
for (size_t i = 0; i < vParamDecl.size(); i++)
{
sParams += ", " + vParamDecl[i]->getTypeIdPtr()->getId();
dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
<< " = is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "("
<< (i + 1) << ", " << (vParamDecl[i]->isOut() ? "false" : "true") << ", ";
if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
{
dstr << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId())
<< (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "");
}
else
{
dstr << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
}
dstr << ");" << endl;
}
DEL_TAB;
dstr << TAB << "}" << endl << endl;
if (!sParams.empty())
{
str << dstr.str();
}
str << TAB << "current.sendResponse = __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$RE;" << endl << endl;
str << TAB << "this." << oPtr->getId() << "(current" << sParams << ");" << endl << endl;
str << TAB << "return " << IDL_NAMESPACE_STR << "Error.SUCCESS;" << endl;
DEL_TAB;
str << TAB << "};" << endl;
return str.str();
}
string CodeGenerator::generateJSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
{
ostringstream str;
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype." << oPtr->getId() << " = function () {" << endl;
INC_TAB;
str << TAB << "assert.fail(\"" << oPtr->getId() << " function not implemented\");" << endl;
DEL_TAB;
str << TAB << "};" << endl;
return str.str();
}
string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr)
{
ostringstream str;
vector<OperationPtr> & vOperation = pPtr->getAllOperationPtr();
//生成类
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp = function () { " << endl;
INC_TAB;
str << TAB << "this._name = undefined;" << endl;
str << TAB << "this._worker = undefined;" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//生成初始化函数
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.initialize = function () {};" << endl << endl;
//生成分发函数
str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.onDispatch = function (current, funcName, binBuffer) { " << endl;
INC_TAB;
str << TAB << "if (\"__\" + funcName in this) {" << endl;
INC_TAB;
str << TAB << "return this[\"__\" + funcName](current, binBuffer);" << endl;
DEL_TAB;
str << TAB << "} else {" << endl;
INC_TAB;
str << TAB << "return " << IDL_NAMESPACE_STR << "Error.SERVER.FUNC_NOT_FOUND;" << endl;
DEL_TAB;
str << TAB << "}" << endl;
DEL_TAB;
str << TAB << "};" << endl << endl;
//生成 PING 方法
str << generatePing(nPtr, pPtr) << endl;
//生成接口函数
for (size_t i = 0; i < vOperation.size(); i++)
{
str << generateJSServer(nPtr, pPtr, vOperation[i]) << endl;
str << generateAsync(nPtr, pPtr, vOperation[i]) << endl;
str << generateDispatch(nPtr, pPtr, vOperation[i]) << endl;
}
str << endl;
return str.str();
}
string CodeGenerator::generateJSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert)
{
ostringstream str;
vector<InterfacePtr> & is = pPtr->getAllInterfacePtr();
for (size_t i = 0; i < is.size(); i++)
{
str << generateJSServer(is[i], pPtr) << endl;
}
if (is.size() != 0)
{
bNeedRpc = true;
bNeedStream = true;
bNeedAssert = true;
}
return str.str();
}
bool CodeGenerator::generateJSServer(const ContextPtr &pPtr)
{
vector<NamespacePtr> namespaces = pPtr->getNamespaces();
ostringstream istr;
set<string> setNamespace;
for(size_t i = 0; i < namespaces.size(); i++)
{
if (setNamespace.count(namespaces[i]->getId()) == 0)
{
istr << TAB << "var " << namespaces[i]->getId() << " = " << namespaces[i]->getId() << " || {};" << endl;
istr << TAB << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl << endl;
setNamespace.insert(namespaces[i]->getId());
}
}
//生成编解码 + 服务类
ostringstream estr;
bool bNeedAssert = false;
bool bNeedStream = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
estr << generateJS(namespaces[i], bNeedStream, bNeedAssert);
}
bool bNeedRpc = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
estr << generateJSServer(namespaces[i], bNeedStream, bNeedRpc, bNeedAssert) << endl;
}
if (estr.str().empty())
{
return false;
}
//再生成导入模块
ostringstream ostr;
if (bNeedAssert)
{
ostr << TAB << "var assert = require(\"assert\");" << endl;
}
if (bNeedStream)
{
ostr << TAB << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl;
}
if (bNeedRpc)
{
ostr << TAB << "var " << IDL_NAMESPACE_STR << "Error = require(\"" << _sRpcPath << "\").error;" << endl;
}
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
if (it->second.sModule.empty()) continue;
if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
ostr << TAB << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl;
}
ostringstream str;
str << printHeaderRemark("Server");
str << "\"use strict\";" << endl << endl;
str << ostr.str() << endl;
str << istr.str();
str << estr.str() << endl;
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + ".js";
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, str.str());
return true;
}

149
src/gen_server_dts.cpp Normal file
View File

@ -0,0 +1,149 @@
/**
* 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 "code_generator.h"
string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr)
{
vector<OperationPtr> &vOperation = pPtr->getAllOperationPtr();
ostringstream str;
//class
INC_TAB;
str << TAB << "class " << pPtr->getId() << "Imp {" << endl;
INC_TAB;
str << TAB << "initialize(): Promise<any> | void;" << endl;
str << TAB << "protected onDispatch(current: " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current, funcName: string, binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer): number" << endl;
for (size_t i = 0; i < vOperation.size(); i++)
{
OperationPtr &oPtr = vOperation[i];
str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "$" << oPtr->getId() << "$CUR";
vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
for (size_t j = 0; j < vParamDecl.size(); j++)
{
str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
}
str << "): void;" << endl;
}
DEL_TAB;
str << TAB << "}" << endl;
//interface
for (size_t i = 0; i < vOperation.size(); i++)
{
OperationPtr &oPtr = vOperation[i];
str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$CUR extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <<endl;
INC_TAB;
str << TAB;
if (oPtr->getReturnPtr()->getTypePtr())
{
str << "sendResponse(ret: " << getDtsType(oPtr->getReturnPtr()->getTypePtr());
vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
for (size_t j = 0; j < vParamDecl.size(); j++)
{
if(!vParamDecl[j]->isOut()) {
continue;
}
str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ;
}
str << "): void;" << endl;
}
else
{
str << "sendResponse(): void;" << endl;
}
DEL_TAB;
str << TAB << "}" << endl;
}
DEL_TAB;
return str.str();
}
string CodeGenerator::generateDTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc)
{
vector<InterfacePtr> &is = pPtr->getAllInterfacePtr();
ostringstream str;
for (size_t i = 0; i < is.size(); i++)
{
str << generateDTSServer(pPtr, is[i]) << endl;
}
if (is.size() != 0)
{
bNeedRpc = true;
bNeedStream = true;
}
return str.str();
}
void CodeGenerator::generateDTSServer(const ContextPtr &pPtr)
{
vector<NamespacePtr> namespaces = pPtr->getNamespaces();
//生成编解码 + 服务类
ostringstream estr;
bool bNeedStream = false;
bool bNeedRpc = false;
for(size_t i = 0; i < namespaces.size(); i++)
{
ostringstream kstr;
kstr << generateDTS(namespaces[i], bNeedStream);
kstr << generateDTSServer(namespaces[i], bNeedStream, bNeedRpc);
estr << generateDTS(namespaces[i], kstr.str());
}
if(estr.str().empty())
{
return;
}
//再生成导入模块
ostringstream ostr;
if (bNeedStream)
{
ostr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl;
}
if (bNeedRpc)
{
ostr << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl;
}
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
if (it->second.sModule.empty()) continue;
if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl;
}
ostringstream str;
str << printHeaderRemark("Server");
str << ostr.str() << endl;
str << estr.str() << endl;
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + ".d.ts";
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, str.str());
}

123
src/gen_server_imp.cpp Normal file
View File

@ -0,0 +1,123 @@
/**
* 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 "code_generator.h"
string CodeGenerator::generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
{
ostringstream str;
str << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype." << oPtr->getId() << " = function (current";
vector<ParamDeclPtr> & vParamDecl = oPtr->getAllParamDeclPtr();
for (size_t i = 0; i < vParamDecl.size(); i++)
{
str << ", " << vParamDecl[i]->getTypeIdPtr()->getId();
}
str << ") {" << endl;
INC_TAB;
str << TAB << "//TODO::" << endl;
DEL_TAB;
str << "};" << endl << endl;
return str.str();
}
string CodeGenerator::generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr)
{
ostringstream str;
vector<OperationPtr> & vOperation = pPtr->getAllOperationPtr();
for (size_t i = 0; i < vOperation.size(); i++)
{
str << generateJSServerImp(nPtr, pPtr, vOperation[i]);
}
return str.str();
}
string CodeGenerator::generateJSServerImp(const ContextPtr &cPtr, const NamespacePtr &nPtr)
{
ostringstream str;
vector<InterfacePtr> & is = nPtr->getAllInterfacePtr();
for (size_t i = 0; i < is.size(); i++)
{
str << generateJSServerImp(nPtr, is[i]) << endl;
}
return str.str();
}
void CodeGenerator::generateJSServerImp(const ContextPtr &cPtr)
{
string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Imp.js";
if (TC_File::isFileExist(sFileName))
{
return ;
}
ostringstream str;
str << printHeaderRemark("Imp");
str << "\"use strict\";" << endl << endl;
vector<NamespacePtr> namespaces = cPtr->getNamespaces();
set<string> setNamespace;
for(size_t i = 0; i < namespaces.size(); i++)
{
if (setNamespace.count(namespaces[i]->getId()) != 0)
{
continue;
}
setNamespace.insert(namespaces[i]->getId());
str << "var " << namespaces[i]->getId() << " = require(\"./"
<< TC_File::excludeFileExt(TC_File::extractFileName(cPtr->getFileName())) << ".js\")."
<< namespaces[i]->getId() << ";" << endl;
str << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl;
}
str << endl;
set<string> setInterface;
for(size_t i = 0; i < namespaces.size(); i++)
{
vector<InterfacePtr> & is = namespaces[i]->getAllInterfacePtr();
for (size_t ii = 0; ii < is.size(); ii++)
{
if (setInterface.count(namespaces[i]->getId() + "::" + is[ii]->getId()) != 0)
{
continue;
}
setInterface.insert(namespaces[i]->getId() + "::" + is[ii]->getId());
str << namespaces[i]->getId() << "." << is[ii]->getId() << "Imp.prototype.initialize = function () {" << endl;
INC_TAB;
str << TAB << "//TODO::" << endl;
DEL_TAB;
str << "};" << endl << endl;
}
}
for(size_t i = 0; i < namespaces.size(); i++)
{
str << generateJSServerImp(cPtr, namespaces[i]);
}
TC_File::makeDirRecursive(_sToPath, 0755);
makeUTF8File(sFileName, str.str());
}

175
src/idl_scan.cpp Normal file
View File

@ -0,0 +1,175 @@
/**
* 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 "code_generator.h"
string CodeGenerator::makeName()
{
int iHigh = uiNameIndex/26;
int iLow = uiNameIndex%26;
uiNameIndex++;
ostringstream s;
s << "_" << TC_Common::upper(IDL_NAMESPACE_STR) << "_MODULE_";
if (iHigh != 0)
{
s << string(1, (char)(iHigh + 65)) << string(1, (char)(iLow + 65));
}
else
{
s << string(1, (char)(iLow + 65));
}
s << "_";
return s.str();
}
bool CodeGenerator::isDependent(const string& sNamespace, const string& sName) const
{
return _depMembers.find(sNamespace + "::" + sName) != _depMembers.end();
}
string CodeGenerator::findName(const string& sNamespace, const string& sName)
{
#ifdef DUMP_FIND_NAME
cout << "FINDNAME BEGIN:" << sNamespace << "|" << sName << endl;
#endif
for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
{
#ifdef DUMP_FIND_NAME
for (map<string, ImportFileType>::iterator demo = it->second.mapVars.begin(); demo != it->second.mapVars.end(); demo++)
{
cout << "FINDNAME:" << it->second.sModule << "|" << demo->first << "|" << demo->second.sNamespace << "|" << demo->second.sName << endl;
}
#endif
map<string, ImportFileType>::iterator inIter = it->second.mapVars.find(sNamespace + "::" + sName);
if (inIter == it->second.mapVars.end())
{
continue;
}
#ifdef DUMP_FIND_NAME
cout << "DEPMEMBER:" << it->first << "|" << inIter->second.sNamespace << "::" << inIter->second.sName << endl;
#endif
_depMembers.insert(inIter->second.sNamespace + "::" + inIter->second.sName);
switch (inIter->second.iType)
{
case ImportFileType::EN_ENUM : // [[fallthrough]]
case ImportFileType::EN_STRUCT :
{
return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sName;
}
case ImportFileType::EN_ENUM_VALUE :
{
return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sTypeName + "." + inIter->second.sName;
}
default :
{
return it->second.sModule;
}
}
}
return "";
}
void CodeGenerator::scan(const string& sFile, bool bNotPrefix)
{
if (_mapFiles.find(sFile) != _mapFiles.end())
{
return ;
}
string sIdlFile = getRealFileInfo(sFile);
g_parse->parse(sIdlFile);
vector<ContextPtr> contexts = g_parse->getContexts();
for(size_t i = 0; i < contexts.size(); i++)
{
if (sIdlFile == contexts[i]->getFileName())
{
ImportFile item;
item.sFile = "./" + TC_File::excludeFileExt(TC_File::extractFileName(sFile)) + IDL_TYPE + ".js";
item.sModule = bNotPrefix?"":makeName();
vector<NamespacePtr> namespaces = contexts[i]->getNamespaces();
for (size_t ii = 0; ii < namespaces.size(); ii++)
{
string sNamespace = namespaces[ii]->getId();
vector<StructPtr> & ss = namespaces[ii]->getAllStructPtr();
for (size_t iii = 0; iii < ss.size(); iii++)
{
vector<string> vecNames = TC_Common::sepstr<string>(ss[iii]->getSid(), "::");
ImportFileType temp;
temp.iType = ImportFileType::EN_STRUCT;
temp.sNamespace = sNamespace;
temp.sName = vecNames[1];
item.mapVars.insert(make_pair(temp.sNamespace + "::" + temp.sName, temp));
}
vector<EnumPtr> & es = namespaces[ii]->getAllEnumPtr();
for (size_t iii = 0; iii < es.size(); iii++)
{
vector<string> vecNames = TC_Common::sepstr<string>(es[iii]->getSid(), "::");
ImportFileType temp;
temp.iType = ImportFileType::EN_ENUM;
temp.sNamespace = sNamespace;
temp.sName = vecNames[1];
item.mapVars.insert(make_pair(temp.sNamespace + "::" + temp.sName, temp));
vector<TypeIdPtr> & eMember = es[iii]->getAllMemberPtr();
for (size_t iiii = 0; iiii < eMember.size(); iiii++)
{
ImportFileType temp;
temp.iType = ImportFileType::EN_ENUM_VALUE;
temp.sNamespace = sNamespace;
temp.sTypeName = vecNames[1];
temp.sName = eMember[iiii]->getId();
#ifdef DUMP_FIND_NAME
cout << "GET::::" << temp.sNamespace << "|" << temp.sName << endl;
#endif
item.mapVars.insert(make_pair(temp.sNamespace + "::" + temp.sName, temp));
}
}
}
_mapFiles.insert(make_pair(sFile, item));
vector<string> vecFiles = contexts[i]->getIncludes();
for (size_t ii = 0; ii < vecFiles.size(); ii++)
{
string sFileName = TC_File::extractFilePath(vecFiles[ii]) + TC_File::excludeFileExt(TC_File::extractFileName(vecFiles[ii])) + "." + TC_Common::lower(IDL_TYPE);
scan(sFileName, false);
}
}
}
}

440
src/idl_util.cpp Normal file
View File

@ -0,0 +1,440 @@
/**
* 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 "code_generator.h"
string CodeGenerator::toFunctionName(const TypeIdPtr& pPtr, const string& sAction)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
if (bPtr)
{
switch (bPtr->kind())
{
case Builtin::KindBool : return sAction + "Boolean";
case Builtin::KindString : return sAction + "String";
case Builtin::KindByte : return sAction + "Int8";
case Builtin::KindShort : return sAction + (bPtr->isUnsigned() ? "UInt8" : "Int16");
case Builtin::KindInt : return sAction + (bPtr->isUnsigned() ? "UInt16" : "Int32");
case Builtin::KindLong : return sAction + (bPtr->isUnsigned() ? "UInt32" : "Int64");
case Builtin::KindFloat : return sAction + "Float";
case Builtin::KindDouble : return sAction + "Double";
default : assert(false);
}
}
VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr());
if (vPtr)
{
BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
if (vbPtr && vbPtr->kind() == Builtin::KindByte)
{
return sAction + "Bytes";
}
return sAction + "List";
}
StructPtr sPtr = StructPtr::dynamicCast(pPtr->getTypePtr());
if (sPtr)
{
return sAction + "Struct";
}
EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr());
if (ePtr)
{
return sAction + "Int32";
}
MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr());
if (mPtr)
{
return sAction + "Map";
}
return "";
}
bool CodeGenerator::isRawOrString(const TypePtr& pPtr) const
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
if (bPtr)
{
if (_bUseStringRepresent && bPtr->kind() == Builtin::KindLong)
{
return true;
}
if (_bStringBinaryEncoding && bPtr->kind() == Builtin::KindString)
{
return true;
}
}
return false;
}
string CodeGenerator::getClassName(const TypePtr& pPtr)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
if (bPtr)
{
switch (bPtr->kind())
{
case Builtin::KindBool : return "bool";
case Builtin::KindString : return "string";
case Builtin::KindByte : return "char";
case Builtin::KindShort : return "short";
case Builtin::KindInt : return "int32";
case Builtin::KindLong : return "int64";
case Builtin::KindFloat : return "float";
case Builtin::KindDouble : return "double";
default : assert(false);
}
}
VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
if (vPtr)
{
return "list(" + getDataType(vPtr->getTypePtr()) + ")";
}
StructPtr sPtr = StructPtr::dynamicCast(pPtr);
if (sPtr)
{
vector<string> vecNames = TC_Common::sepstr<string>(sPtr->getSid(), "::");
assert(vecNames.size() == 2);
return findName(vecNames[0], vecNames[1]);
}
MapPtr mPtr = MapPtr::dynamicCast(pPtr);
if (mPtr)
{
return "map(" + getClassName(mPtr->getLeftTypePtr()) + ", " + getClassName(mPtr->getRightTypePtr()) + ")";
}
EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
if (ePtr)
{
return "int32";
}
return "void";
}
string CodeGenerator::getDataType(const TypePtr& pPtr)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
if (bPtr)
{
switch (bPtr->kind())
{
case Builtin::KindBool : return IDL_NAMESPACE_STR + "Stream.Boolean";
case Builtin::KindString : return IDL_NAMESPACE_STR + "Stream.String";
case Builtin::KindByte : return IDL_NAMESPACE_STR + "Stream.Int8";
case Builtin::KindShort : return IDL_NAMESPACE_STR + "Stream.Int16";
case Builtin::KindInt : return IDL_NAMESPACE_STR + "Stream.Int32";
case Builtin::KindLong : return IDL_NAMESPACE_STR + "Stream.Int64";
case Builtin::KindFloat : return IDL_NAMESPACE_STR + "Stream.Float";
case Builtin::KindDouble : return IDL_NAMESPACE_STR + "Stream.Double";
default : assert(false);
}
}
VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
if (vPtr)
{
BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
if (vbPtr && vbPtr->kind() == Builtin::KindByte)
{
return IDL_NAMESPACE_STR + "Stream.BinBuffer";
}
return IDL_NAMESPACE_STR + "Stream.List(" + getDataType(vPtr->getTypePtr()) + (isRawOrString(vPtr->getTypePtr()) ? ", 1" : "") + ")";
}
StructPtr sPtr = StructPtr::dynamicCast(pPtr);
if (sPtr)
{
vector<string> vecNames = TC_Common::sepstr<string>(sPtr->getSid(), "::");
assert(vecNames.size() == 2);
return findName(vecNames[0], vecNames[1]);
}
MapPtr mPtr = MapPtr::dynamicCast(pPtr);
if (mPtr)
{
bool bLeft = isRawOrString(mPtr->getLeftTypePtr());
bool bRight = isRawOrString(mPtr->getRightTypePtr());
if (!bRight && !bLeft) {
return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ")";
} else if (bRight && bLeft) {
return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1, 1)";
} else if (bRight) {
return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 0, 1)";
} else if (bLeft) {
return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1)";
} else {
assert(false);
}
}
EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
if (ePtr)
{
vector<string> vecNames = TC_Common::sepstr<string>(ePtr->getSid(), "::");
assert(vecNames.size() == 2);
return findName(vecNames[0], vecNames[1]);
}
assert(false);
return "";
}
string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
if (bPtr)
{
switch (bPtr->kind())
{
case Builtin::KindBool : return "boolean";
case Builtin::KindString : return _bStringBinaryEncoding ? (bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer") : "string";
case Builtin::KindByte : return "number";
case Builtin::KindShort : return "number";
case Builtin::KindInt : return "number";
case Builtin::KindLong : return _bUseStringRepresent ? "string" : "number";
case Builtin::KindFloat : return "number";
case Builtin::KindDouble : return "number";
default : assert(false);
}
}
VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
if (vPtr)
{
BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
if (vbPtr && vbPtr->kind() == Builtin::KindByte)
{
return bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer";
}
return (bStream ? (IDL_NAMESPACE_STR + "Stream.List") : "Array") + string("<") + getDtsType(vPtr->getTypePtr(), bStream) + string(">");
}
StructPtr sPtr = StructPtr::dynamicCast(pPtr);
if (sPtr)
{
vector<string> vecNames = TC_Common::sepstr<string>(sPtr->getSid(), "::");
assert(vecNames.size() == 2);
return findName(vecNames[0], vecNames[1]) + (bStream ? "" : "$OBJ");
}
MapPtr mPtr = MapPtr::dynamicCast(pPtr);
if (mPtr)
{
if (bStream)
{
return IDL_NAMESPACE_STR + "Stream.Map<" + getDtsType(mPtr->getLeftTypePtr(), bStream) + ", " + getDtsType(mPtr->getRightTypePtr(), bStream) + ">";
}
else
{
const string& sLeftType = getDtsType(mPtr->getLeftTypePtr(), bStream);
if (sLeftType == "number" || sLeftType == "string")
{
return "{[key: " + getDtsType(mPtr->getLeftTypePtr(), bStream) + "]: " + getDtsType(mPtr->getRightTypePtr(), bStream) + "}";
}
else if (isSimple(mPtr->getLeftTypePtr()) && sLeftType != "Buffer")
{
return "object";
}
else
{
return "";
}
}
}
EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
if (ePtr)
{
vector<string> vecNames = TC_Common::sepstr<string>(ePtr->getSid(), "::");
assert(vecNames.size() == 2);
return findName(vecNames[0], vecNames[1]);
}
assert(false);
return "";
}
bool CodeGenerator::isSimple(const TypePtr & pPtr) const
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
if (bPtr)
{
return true;
}
EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
if (ePtr)
{
return true;
}
return false;
}
bool CodeGenerator::isBinBuffer(const TypePtr & pPtr) const
{
VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
if (vPtr)
{
BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
if (vbPtr && vbPtr->kind() == Builtin::KindByte)
{
return true;
}
}
return false;
}
string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace)
{
return getDefault(pPtr, sDefault, sNamespace, true);
}
string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace, const bool bGlobal)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
if (bPtr)
{
switch (bPtr->kind())
{
case Builtin::KindBool :
return sDefault.empty() ? "false" : sDefault;
case Builtin::KindString :
{
if (_bStringBinaryEncoding)
{
return IDL_NAMESPACE_STR + "Stream.BinBuffer.from(\"" + TC_Common::replace(sDefault, "\"", "\\\"") + "\").toNodeBufferUnSafe()";
}
else
{
return "\"" + TC_Common::replace(sDefault, "\"", "\\\"") + "\"";
}
}
case Builtin::KindByte : // [[fallthrough]]
case Builtin::KindShort : // [[fallthrough]]
case Builtin::KindInt : // [[fallthrough]]
case Builtin::KindLong :
{
string sTemp = TC_Common::trim(sDefault);
if (sTemp.empty())
{
sTemp = "0";
}
else
{
if (TC_Common::tostr(TC_Common::strto<long>(sTemp)) != sTemp)
{
//有可能是枚举值,在枚举值中查找
vector<string> vecNames = TC_Common::sepstr<string>(sDefault, "::");
if (vecNames.size() == 2)
{
sTemp = findName(vecNames[0], vecNames[1]);
}
else
{
sTemp = findName(sNamespace, sDefault);
}
}
}
if (sTemp.empty())
{
sTemp = "0";
}
if (_bUseStringRepresent)
{
if (bPtr->kind() == Builtin::KindLong)
{
sTemp = "\"" + sTemp + "\"";
}
}
return sTemp;
}
case Builtin::KindFloat : // [[fallthrough]]
case Builtin::KindDouble :
return sDefault.empty()?"0.0":sDefault;
default :
assert(false);
}
}
EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr());
if (ePtr)
{
if (sDefault.empty())
{
vector<TypeIdPtr>& eMember = ePtr->getAllMemberPtr();
if (eMember.size() > 0)
{
vector<string> vecNames = TC_Common::sepstr<string>(ePtr->getSid(), "::");
string sModule = findName(vecNames[0], eMember[0]->getId());
return sModule;
}
}
if (!TC_Common::isdigit(sDefault))
{
string s1 = sNamespace;
string s2 = sDefault;
string::size_type index = sDefault.find("::");
if (index != string::npos)
{
s1 = sDefault.substr(0, index);
s2 = sDefault.substr(index + 2);
}
string sModule = findName(s1, s2);
assert(!sModule.empty());
return sModule;
}
return sDefault;
}
if (bGlobal)
{
return "new " + getDataType(pPtr->getTypePtr());
}
return sDefault;
}

198
src/main.cpp Normal file
View File

@ -0,0 +1,198 @@
/**
* 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 "util/tc_option.h"
#include "code_generator.h"
void version()
{
cout << "v" << GENERATOR_VERSION << endl;
}
void usage()
{
cout << "Version : " << GENERATOR_VERSION << endl;
cout << "Usage : " << EXECUTE_FILENAME << " [OPTION] " << "*." << TC_Common::lower(IDL_TYPE) << " file" << endl;
cout << " --version print " << EXECUTE_FILENAME << " version" << endl;
cout << " --rpc-path=[DIRECTORY] specify the path of rpc module." << endl;
cout << " --stream-path=[DIRECTORY] specify the path of stream module." << endl;
cout << " --allow-reserved-namespace allow you to use reserved word as a namespace." << endl;
cout << " --dir=DIRECTORY generate source file to DIRECTORY." << endl;
cout << " --relative use current path." << endl;
cout << " --base=DIRECTORY where to search " << IDL_TYPE << " files." << endl;
cout << " --r generate source all " << IDL_TYPE << " files." << endl;
cout << " --r-minimal minimize the dependent members." << endl;
cout << " --r-reserved list of names(split by \",\") that should be keeped." << endl;
cout << " --client just for client side source file." << endl;
cout << " --server just for server side source file." << endl;
cout << " --dts generate d.ts file." << endl;
cout << " --use-string-represent use string represent long type." << endl;
cout << " --string-binary-encoding get string raw bytes <BinBuffer>." << endl;
cout << " --optimize=[0|s] support \"s\" to reduce code size, default is 0." << endl;
cout << endl;
cout << EXECUTE_FILENAME << " support type: boolean char short int long float double list map" << endl;
exit(0);
}
void check(vector<string> &vFiles)
{
for(size_t i = 0; i < vFiles.size(); i++)
{
string ext = TC_File::extractFileExt(vFiles[i]);
if(ext == TC_Common::lower(IDL_TYPE))
{
if(!TC_File::isFileExist(vFiles[i]))
{
cerr << "file '" << vFiles[i] << "' not exists" << endl;
usage();
exit(0);
}
}
else
{
cerr << "only support "<< TC_Common::lower(IDL_TYPE) << " file." << endl;
usage();
exit(0);
}
}
}
int main(int argc, char* argv[])
{
if(argc < 2)
{
usage();
}
try
{
TC_Option option;
option.decode(argc, argv);
vector<string> vFiles = option.getSingle();
check(vFiles);
if (option.hasParam("version"))
{
version();
return 0;
}
if(option.hasParam("help"))
{
usage();
return 0;
}
if(option.hasParam("base"))
{
if (::chdir(option.getValue("base").c_str()) != 0) {
return -1;
}
}
#define ALLOW_USE_RESERVED_NAMESPACE_V(name, keeped) \
g_parse->set##name(keeped);
#define ALLOW_USE_RESERVED_NAMESPACE_BASE(name, keeped) \
ALLOW_USE_RESERVED_NAMESPACE_V(name, keeped)
#define ALLOW_USE_RESERVED_NAMESPACE(keeped) \
ALLOW_USE_RESERVED_NAMESPACE_BASE(IDL_NAMESPACE, keeped)
ALLOW_USE_RESERVED_NAMESPACE(option.hasParam("allow-reserved-namespace"));
#undef ALLOW_USE_RESERVED_NAMESPACE
#undef ALLOW_USE_RESERVED_NAMESPACE_BASE
#undef ALLOW_USE_RESERVED_NAMESPACE_V
g_parse->setUseCurrentPath(option.hasParam("relative"));
CodeGenerator generator;
generator.setRpcPath(option.hasParam("rpc-path")?option.getValue("rpc-path"):RPC_MODULE_PATH);
generator.setStreamPath(option.hasParam("stream-path")?option.getValue("stream-path"):STREAM_MODULE_PATH);
generator.setEnableClient(option.hasParam("client"));
generator.setEnableServer(option.hasParam("server"));
generator.setTargetPath(option.hasParam("dir")?option.getValue("dir"):"./");
generator.setUseSpecialPath(option.hasParam("relative"));
generator.setUseStringRepresent(option.hasParam("use-string-represent"));
generator.setStringBinaryEncoding(option.hasParam("string-binary-encoding"));
generator.setEnableDTS(option.hasParam("dts"));
if (option.hasParam("optimize"))
{
string level = TC_Common::lower(option.getValue("optimize"));
if (level == "s")
{
generator.setOptimize(CodeGenerator::Os);
}
else
{
generator.setOptimize(CodeGenerator::O0);
}
}
bool _bRecursive = option.hasParam("r");
bool _bMinimalMembers = option.hasParam("r-minimal");
if (option.hasParam("r-reserved"))
{
set<string> vMembers;
vector<string> vReserved = TC_Common::sepstr<string>(option.getValue("r-reserved"), ",");
for (size_t i = 0; i < vReserved.size(); i++)
{
if (vReserved[i].empty())
{
continue;
}
if (TC_Common::sepstr<string>(vReserved[i], "::").size() == 2)
{
vMembers.insert(TC_Common::trim(vReserved[i]));
} else {
cerr << "reserved member must be match <Module>::<Member> pattern" << endl;
return 0;
}
}
if (vMembers.size() > 0)
{
_bMinimalMembers = true;
generator.setDependent(vMembers);
}
}
if (!_bRecursive && _bMinimalMembers)
{
cerr << "Missing --r flag" << endl;
return 0;
}
generator.setRecursive(_bRecursive);
generator.setMinimalMembers(_bMinimalMembers);
for (size_t i = 0; i < vFiles.size(); i++)
{
generator.createFile(vFiles[i], true);
}
}
catch(exception& e)
{
cerr<<e.what()<<endl;
}
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_TARS_TAB_HPP_INCLUDED
# define YY_YY_TARS_TAB_HPP_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 1
#endif
#if YYDEBUG
extern int yydebug;
#endif
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
TARS_VOID = 258,
TARS_STRUCT = 259,
TARS_BOOL = 260,
TARS_BYTE = 261,
TARS_SHORT = 262,
TARS_INT = 263,
TARS_DOUBLE = 264,
TARS_FLOAT = 265,
TARS_LONG = 266,
TARS_STRING = 267,
TARS_VECTOR = 268,
TARS_MAP = 269,
TARS_NAMESPACE = 270,
TARS_INTERFACE = 271,
TARS_IDENTIFIER = 272,
TARS_OUT = 273,
TARS_OP = 274,
TARS_KEY = 275,
TARS_ROUTE_KEY = 276,
TARS_REQUIRE = 277,
TARS_OPTIONAL = 278,
TARS_CONST_INTEGER = 279,
TARS_CONST_FLOAT = 280,
TARS_FALSE = 281,
TARS_TRUE = 282,
TARS_STRING_LITERAL = 283,
TARS_SCOPE_DELIMITER = 284,
TARS_CONST = 285,
TARS_ENUM = 286,
TARS_UNSIGNED = 287,
BAD_CHAR = 288
};
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;
int yyparse (void);
#endif /* !YY_YY_TARS_TAB_HPP_INCLUDED */

View File

@ -0,0 +1,339 @@
/**
* 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 "element.h"
#include <iostream>
#include <cassert>
#include "parse.h"
#include "util/tc_file.h"
#include "util/tc_common.h"
/*************************************************************************************************/
const char* Builtin::builtinTable[] =
{
"void",
"bool",
"byte",
"short",
"int",
"long",
"float",
"double",
"string",
"vector",
"map"
};
Builtin::Builtin(Kind kind,bool isUnsigned = false) : _kind(kind),_isUnsigned(isUnsigned)
{
}
Builtin::Kind Builtin::kind() const
{
return _kind;
}
bool Builtin::isSimple() const
{
switch(_kind)
{
case Builtin::KindBool:
case Builtin::KindByte:
case Builtin::KindShort:
case Builtin::KindInt:
case Builtin::KindLong:
case Builtin::KindFloat:
case Builtin::KindDouble:
return true;
default:
return false;
}
return true;
}
string Builtin::def() const
{
switch(_kind)
{
case Builtin::KindBool:
return "true";
case Builtin::KindByte:
case Builtin::KindShort:
case Builtin::KindInt:
case Builtin::KindLong:
case Builtin::KindFloat:
case Builtin::KindDouble:
return "0";
case Builtin::KindString:
return "";
default:
assert(false);
}
return "";
}
/*************************************************************************************************/
Vector::Vector(const TypePtr& ptr) : _ptr(ptr)
{
}
/*************************************************************************************************/
Map::Map(const TypePtr& pleft, const TypePtr& pright): _pleft(pleft), _pright(pright)
{
}
/*************************************************************************************************/
TypeId::TypeId(const TypePtr& ptr, const string&id)
: _ptr(ptr)
, _id(id)
, _bRequire(true)
, _tag(0)
, _bHasDefault(false)
, _size(0)
, _array(false)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr);
if(bPtr)
{
_bHasDefault = true;
_default = bPtr->def();
}
}
void TypeId::setRequire(int tag)
{
_bRequire = true;
_tag = tag;
}
void TypeId::setDefault(const string &def)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr);
EnumPtr ePtr = EnumPtr::dynamicCast(_ptr);
assert(bPtr || ePtr);
_bHasDefault = true;
_default = def;
}
void TypeId::disableDefault()
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr);
assert(bPtr);
_bHasDefault = false;
}
void TypeId::setOptional(int tag)
{
_bRequire = false;
_tag = tag;
}
/*************************************************************************************************/
NamespacePtr Container::createNamespace(const string &id)
{
NamespacePtr np = NamespacePtr::dynamicCast(this);
if(np)
{
g_parse->error("namespace can't be nested!");
}
_ns.push_back(new Namespace(id));
g_parse->currentContextPtr()->addNamespacePtr(_ns.back());
return _ns.back();
}
/*************************************************************************************************/
ParamDeclPtr Operation::createParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k)
{
_itag++;
if(_itag > 255)
{
g_parse->error("operation '" + _id + "' can't have more than 255 paramters!");
}
if(typeIdPtr->getId() == getId())
{
g_parse->error("paramters name '" + _id + "' conflicts with operation name!");
}
typeIdPtr->setRequire(_itag);
_ps.push_back(new ParamDecl(typeIdPtr, v, k));
return _ps.back();
}
/*************************************************************************************************/
OperationPtr Interface::createOperation(const string &id, const TypePtr &typePtr)
{
for(size_t i = 0; i < _ops.size(); i++)
{
if(_ops[i]->getId() == id)
{
g_parse->error("operation '" + id + "' exists in interface '" + _id + "'");
return NULL;
}
}
_ops.push_back(new Operation(id, typePtr));
return _ops.back();
}
/*************************************************************************************************/
InterfacePtr Namespace::createInterface(const string &id)
{
for(size_t i = 0; i < _is.size(); i++)
{
if(_is[i]->getId() == id)
{
g_parse->error("interface '" + id + "' exists in namespace '" + _id + "'");
return NULL;
}
}
if(id == _id)
{
g_parse->error("interface '" + id + "' must not be same with namespace '" + _id + "'");
return NULL;
}
_is.push_back(new Interface(id));
return _is.back();
}
StructPtr Namespace::createStruct(const string& id)
{
g_parse->checkConflict(_id + "::" + id);
_ss.push_back(new Struct(id, _id + "::" + id));
g_parse->addStructPtr(_ss.back());
return _ss.back();
}
EnumPtr Namespace::createEnum(const string &id)
{
g_parse->checkConflict(_id + "::" + id);
_es.push_back(new Enum(id, _id + "::" + id));
g_parse->addEnumPtr(_es.back());
return _es.back();
}
ConstPtr Namespace::createConst(TypeIdPtr &pPtr, ConstGrammarPtr &cPtr)
{
for(size_t i = 0; i < _cs.size(); i++)
{
if(_cs[i]->getTypeIdPtr()->getId() == pPtr->getId())
{
g_parse->error("const type '" + pPtr->getId() + "' exists in namespace '" + _id + "'");
return NULL;
}
}
g_parse->checkConstValue(pPtr, cPtr->t);
_cs.push_back(new Const(pPtr, cPtr));
return _cs.back();
}
/*************************************************************************************************/
void Struct::addTypeId(const TypeIdPtr &typeIdPtr)
{
StructPtr sp = StructPtr::dynamicCast(typeIdPtr->getTypePtr());
if(sp)
{
if(sp->getSid() == getSid())
{
g_parse->error("struct can't take self as member data");
}
}
for(size_t i = 0; i < _members.size(); i++)
{
if(_members[i]->getId() == typeIdPtr->getId())
{
g_parse->error("data member '" + typeIdPtr->getId() + "' duplicate definition");
}
if(_members[i]->getTag() == typeIdPtr->getTag())
{
g_parse->error("data member '" + typeIdPtr->getId() + "' has equal tag with '" + _members[i]->getId() + "'");
}
if(_members[i]->getTag() > typeIdPtr->getTag())
{
_members.insert(_members.begin() + i, typeIdPtr);
return;
}
}
_members.push_back(typeIdPtr);
}
void Struct::addKey(const string &member)
{
size_t i;
for(i = 0; i < _members.size(); i++)
{
if(_members[i]->getId() == member)
{
break;
}
}
if(i == _members.size())
{
g_parse->error("key member '" + member + "' is not struct member");
}
_key.push_back(member);
}
/***********************************************************************************/
void Enum::addMember(const TypeIdPtr &typeIdPtr)
{
for(size_t i = 0; i < _members.size(); i++)
{
if(_members[i]->getId() == typeIdPtr->getId())
{
g_parse->error("enum member '" + typeIdPtr->getId() + "' duplicate definition");
}
}
_members.push_back(typeIdPtr);
}
/***********************************************************************************/
void Context::addInclude(const string &incl)
{
if(incl == _filename)
{
g_parse->error("can't include self");
}
_includes.push_back(tars::TC_File::excludeFileExt(incl) + ".h");
}

View File

@ -0,0 +1,861 @@
/**
* 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.
*/
#ifndef _ELEMENT_H
#define _ELEMENT_H
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <map>
#include <stack>
#include <sstream>
#include "errno.h"
#include "util/tc_autoptr.h"
using namespace std;
void yyerror(char const *msg);
/**
*
*/
class GrammarBase : virtual public tars::TC_HandleBase
{
public:
virtual ~GrammarBase(){};
};
typedef tars::TC_AutoPtr<GrammarBase> GrammarBasePtr;
/**
*
*/
class StringGrammar : public GrammarBase
{
public:
StringGrammar() { }
string v;
};
typedef tars::TC_AutoPtr<StringGrammar> StringGrammarPtr;
/**
*
*/
class IntergerGrammar : public GrammarBase
{
public:
IntergerGrammar():v(0) { }
long long v;
};
typedef tars::TC_AutoPtr<IntergerGrammar> IntergerGrammarPtr;
/**
*
*/
class FloatGrammar : public GrammarBase
{
public:
FloatGrammar():v(0.0f) { }
double v;
};
typedef tars::TC_AutoPtr<FloatGrammar> FloatGrammarPtr;
/**
* bool类型
*/
class BoolGrammar : public GrammarBase
{
public:
BoolGrammar():v(false) { }
bool v;
};
typedef tars::TC_AutoPtr<BoolGrammar> BoolGrammarPtr;
/**
*
*/
class ConstGrammar : public GrammarBase
{
public:
ConstGrammar():t(VALUE) { }
enum
{
VALUE,
STRING,
BOOL,
ENUM
};
int t;
string v;
};
typedef tars::TC_AutoPtr<ConstGrammar> ConstGrammarPtr;
///////////////////////////////////////////////
/**
*
*/
class Type : virtual public GrammarBase
{
public:
/**
*
* @param Type
*/
Type():_size(0),_array(false),_pointer(false){};
//是否简单类型
virtual bool isSimple() const { return false;}
//是否数组类型
virtual bool isArray() const { return _array;}
virtual void setArray(int size) {_array = true;_size = size;}
virtual int getSize() const {return _size;};
//是否指针类型
virtual bool isPointer() const { return _pointer;}
virtual void setPointer(bool b) {_pointer = b;}
public:
int _size;
bool _array;
bool _pointer;
};
typedef tars::TC_AutoPtr<Type> TypePtr;
/**
*
*/
class Builtin : public Type
{
public:
enum Kind
{
KindVoid,
KindBool,
KindByte,
KindShort,
KindInt,
KindLong,
KindFloat,
KindDouble,
KindString,
KindVector,
KindMap
};
/**
*
* @param kind
*/
Builtin(Kind kind,bool isUnsigned);
/**
*
*
* @return Kind
*/
Kind kind() const;
/**
*
*
* @return bool
*/
bool isSimple() const;
/**
* unsined类型
*
* @return bool
*/
bool isUnsigned() const {return _isUnsigned;}
/**
* unsined类型
*
* @return bool
*/
void setUnsigned(bool isUnsigned = false) {_isUnsigned = isUnsigned;}
/**
*
*
* @return string
*/
string def() const;
/**
*
*/
static const char* builtinTable[];
protected:
Kind _kind;
bool _isUnsigned;
};
typedef tars::TC_AutoPtr<Builtin> BuiltinPtr;
/**
* Vector类型
*/
class Vector : public Type
{
public:
/**
*
* @param ptr
*/
Vector(const TypePtr& ptr);
/**
*
*
* @return TypePtr&
*/
TypePtr& getTypePtr() {return _ptr;}
protected:
TypePtr _ptr;
};
typedef tars::TC_AutoPtr<Vector> VectorPtr;
/**
* Map类型
*/
class Map : public Type
{
public:
/**
*
* @param pleft
* @param pright
*/
Map(const TypePtr& pleft, const TypePtr& pright);
/**
*
*
* @return TypePtr&
*/
TypePtr& getLeftTypePtr() {return _pleft;}
/**
*
*
* @return TypePtr&
*/
TypePtr& getRightTypePtr() {return _pright;}
protected:
TypePtr _pleft;
TypePtr _pright;
};
typedef tars::TC_AutoPtr<Map> MapPtr;
/**
*
*/
class TypeId : public GrammarBase
{
public:
/**
*
* @param ptr
* @param id
*/
TypeId(const TypePtr& ptr, const string& id);
/**
*
*
* @return string
*/
string getId() const { return _id; }
/**
*
*
* @return Type*
*/
TypePtr& getTypePtr() { return _ptr;}
/**
*
*
* @return bool
*/
bool isRequire() const { return _bRequire; }
/**
*
* @param tag
*/
void setRequire(int tag);
/**
*
*
*/
void setDefault(const string &def);
/**
*
*
*/
void disableDefault();
/**
*
* @param tag
*/
void setOptional(int tag);
/**
* tag标识
*/
int getTag() const { return _tag; }
/**
*
*
* @return string
*/
string def() const { return _default; }
/**
*
*
* @return bool
*/
bool hasDefault() const { return _bHasDefault; }
protected:
TypePtr _ptr;
string _id;
bool _bRequire;
int _tag;
bool _bHasDefault;
string _default;
public:
int _size;
bool _array;
};
typedef tars::TC_AutoPtr<TypeId> TypeIdPtr;
////////////////////////////////////////////////////
//
class Namespace;
typedef tars::TC_AutoPtr<Namespace> NamespacePtr;
/**
* ,
*/
class Container : virtual public GrammarBase
{
public:
/**
*
* @param id
*/
Container(const string &id) : _id(id)
{
}
/**
*
* @param id
*
* @return NamespacePtr
*/
NamespacePtr createNamespace(const string &id);
/**
* ID
*
* @return string
*/
string getId() const { return _id;}
/**
*
*
* @return vector<NamespacePtr>&
*/
vector<NamespacePtr> &getAllNamespacePtr() { return _ns; }
protected:
string _id;
vector<NamespacePtr> _ns;
};
typedef tars::TC_AutoPtr<Container> ContainerPtr;
////////////////////////////////////////////////////
//
class Const : public GrammarBase
{
public:
/**
*
* @param tPtr
* @param cPtr
*/
Const(TypeIdPtr &tPtr, ConstGrammarPtr &cPtr) : _tPtr(tPtr), _cPtr(cPtr)
{
}
/**
*
*
* @return TypePtr&
*/
TypeIdPtr &getTypeIdPtr() { return _tPtr; }
/**
*
*
* @return ConstGrammarPtr
*/
ConstGrammarPtr getConstGrammarPtr() { return _cPtr; }
protected:
TypeIdPtr _tPtr;
ConstGrammarPtr _cPtr;
};
typedef tars::TC_AutoPtr<Const> ConstPtr;
/////////////////////////////////////////////////////////
//
class Enum : virtual public Container, virtual public Type
{
public:
Enum(const string &id, const string &sid) : Container(id), _sid(sid)
{
}
/**
*
* @param ptid
*/
void addMember(const TypeIdPtr &ptr);
/**
*
*
* @return vector<TypeIdPtr>&
*/
vector<TypeIdPtr>& getAllMemberPtr() {return _members;}
/**
*
*
* @return string
*/
string getSid() const { return _sid; }
/**
*
*
* @return bool
*/
virtual bool isSimple() const { return true; }
protected:
/**
*
*/
vector<TypeIdPtr> _members;
/**
*
*/
string _sid;
};
typedef tars::TC_AutoPtr<Enum> EnumPtr;
////////////////////////////////////////////////////
//
/**
*
*/
class Struct : virtual public Container, virtual public Type
{
public:
/**
*
* @param id
*/
Struct(const string& id, const string &sid) : Container(id), _sid(sid)
{
}
/**
*
* @param ptid
*/
void addTypeId(const TypeIdPtr &ptr);
/**
*
*
* @return vector<TypeIdPtr>&
*/
vector<TypeIdPtr>& getAllMemberPtr() {return _members;}
/**
*
*
* @return string
*/
string getSid() const { return _sid; }
/**
* memeber
* @param member
*/
void addKey(const string &member);
vector<string> getKey() { return _key; }
protected:
vector<TypeIdPtr> _members;
vector<string> _key;
string _sid;
};
typedef tars::TC_AutoPtr<Struct> StructPtr;
////////////////////////////////////////////////////
//
/**
*
*/
class ParamDecl : public GrammarBase
{
public:
/**
*
* @param typeIdPtr
* @param v
*/
ParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k)
: _typeIdPtr(typeIdPtr), _v(v), _k(k)
{
}
/**
*
*
* @return TypeIdPtr&
*/
TypeIdPtr& getTypeIdPtr() { return _typeIdPtr; }
/**
*
*
* @return bool
*/
bool isOut() const { return _v; }
/**
*
*
* @return bool
*/
bool isRouteKey() const { return _k; }
protected:
TypeIdPtr _typeIdPtr;
bool _v;
bool _k;
};
typedef tars::TC_AutoPtr<ParamDecl> ParamDeclPtr;
///////////////////////////////////////////////////////
//
/**
*
*/
class Operation : public Container
{
public:
/**
*
* @param id
* @param typePtr
*/
Operation(const string &id, const TypePtr &typePtr) : Container(id), _itag(0)
{
_retPtr = new TypeId(typePtr, "_ret");
_retPtr->setRequire(_itag);
}
/**
*
* @param typeIdPtr
* @param v
* @param k
*
* @return ParamDeclPtr
*/
ParamDeclPtr createParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k);
/**
*
*
* @return TypePtr&
*/
TypeIdPtr &getReturnPtr() { return _retPtr; }
/**
*
*
* @return vector<ParamDeclPtr>&
*/
vector<ParamDeclPtr> &getAllParamDeclPtr() { return _ps; }
protected:
int _itag;
TypeIdPtr _retPtr;
vector<ParamDeclPtr> _ps;
};
typedef tars::TC_AutoPtr<Operation> OperationPtr;
///////////////////////////////////////////////////////
//
/**
*
*/
class Interface : public Container
{
public:
/**
*
* @param id
*/
Interface(const string &id) : Container(id)
{
}
/**
*
* @param id
* @param typePtr
*
* @return OperationPtr
*/
OperationPtr createOperation(const string &id, const TypePtr &typePtr);
/**
*
*
* @return vector<OperationPtr>&
*/
vector<OperationPtr> &getAllOperationPtr() { return _ops; }
protected:
vector<OperationPtr> _ops;
};
typedef tars::TC_AutoPtr<Interface> InterfacePtr;
/////////////////////////////////////////////////////////
//
/**
*
*/
class Namespace : public Container
{
public:
/**
*
* @param id
*/
Namespace(const string &id) : Container(id)
{
}
/**
*
* @param id
*
* @return InterfacePtr
*/
InterfacePtr createInterface(const string &id);
/**
*
* @param id
*
* @return StructPtr
*/
StructPtr createStruct(const string& id);
/**
*
* @param id
*
* @return EnumPtr
*/
EnumPtr createEnum(const string &id);
/**
*
* @param pPtr
* @param cPtr
*
* @return ConstPtr
*/
ConstPtr createConst(TypeIdPtr &pPtr, ConstGrammarPtr &cPtr);
/**
*
*
* @return bool
*/
bool hasInterface() const { return !_is.empty(); }
/**
*
*
* @return vector<InterfacePtr>&
*/
vector<InterfacePtr> &getAllInterfacePtr() { return _is; }
/**
*
*
* @return vector<StructPtr>&
*/
vector<StructPtr> &getAllStructPtr() { return _ss; }
/**
*
*
* @return vector<EnumPtr>&
*/
vector<EnumPtr> &getAllEnumPtr() { return _es; }
/**
*
*
* @return vector<ConstPtr>&
*/
vector<ConstPtr> &getAllConstPtr() { return _cs; }
protected:
vector<InterfacePtr> _is;
vector<StructPtr> _ss;
vector<EnumPtr> _es;
vector<ConstPtr> _cs;
};
/////////////////////////////////////////////////////////////////
/**
*
*/
class Context : public tars::TC_HandleBase
{
public:
/**
*
*/
Context(const string &file) : _currline(1), _filename(file)
{
}
/**
*
*/
void nextLine() { _currline++; }
/**
*
*
* @return size_t
*/
size_t getCurrLine() { return _currline; }
/**
*
*
* @return string
*/
string getFileName() { return _filename; }
/**
* include的文件
* @param incl
*/
void addInclude(const string &incl);
/**
*
* @param c
*/
void addNamespacePtr(const NamespacePtr &c)
{
_namespaces.push_back(c);
}
/**
* includes的文件
*
* @return vector<string>
*/
vector<string> getIncludes() { return _includes; }
/**
*
*
* @return vector<NamespacePtr>
*/
vector<NamespacePtr> getNamespaces() { return _namespaces; }
protected:
size_t _currline;
string _filename;
vector<string> _includes;
vector<NamespacePtr> _namespaces;
};
typedef tars::TC_AutoPtr<Context> ContextPtr;
#endif

View File

@ -0,0 +1,603 @@
/**
* 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 "parse.h"
#include "tars.tab.hpp"
#include <errno.h>
#include <fstream>
#include <string.h>
#include "util/tc_common.h"
#include "util/tc_file.h"
TarsParsePtr g_parse = new TarsParse();
void yyerror(char const *msg)
{
g_parse->error(msg);
}
TarsParse::TarsParse()
{
_bWithTars = false;
_bUseCurrentPath = false;
_itab = 0;
_bUseCurrentPathFirst = false;
initScanner();
}
void TarsParse::setTars(bool bWithTars)
{
_bWithTars = bWithTars;
}
void TarsParse::setHeader(const string &sHeader)
{
_sHeader = sHeader;
}
void TarsParse::setCurrentPriority(bool bFlag)
{
_bUseCurrentPathFirst = bFlag;
}
string TarsParse::getHeader()
{
if(_sHeader.empty())
return _sHeader;
return _sHeader + "/";
}
void TarsParse::clear()
{
while(!_contexts.empty()) _contexts.pop();
while(!_contains.empty()) _contains.pop();
_vcontexts.clear();
_structs.clear();
_enums.clear();
_namespaces.clear();
}
void TarsParse::parse(const string& sFileName)
{
if (_bUseCurrentPath)
{
std::string sTemp = sFileName;
bool isExist = tars::TC_File::isFileExist(sFileName);
if (!isExist)
{
sTemp = tars::TC_File::extractFileName(sFileName);
}
clear();
_contains.push(new Container(""));
if(!(yyin = fopen(sTemp.c_str(), "r")))
{
error("open file '" + sFileName + "(" + sTemp + ")" + "' error :" + string(strerror(errno)));
}
pushFile(sFileName);
yyparse();
return ;
}
if (_bUseCurrentPathFirst)
{
std::string sTemp = tars::TC_File::extractFileName(sFileName);
bool isExist = tars::TC_File::isFileExist(sTemp);
if (!isExist)
{
sTemp = sFileName;
}
clear();
_contains.push(new Container(""));
if(!(yyin = fopen(sTemp.c_str(), "r")))
{
error("open file '" + sFileName + "(" + sTemp + ")" + "' error :" + string(strerror(errno)));
}
pushFile(sFileName);
yyparse();
return ;
}
{
clear();
_contains.push(new Container(""));
if(!(yyin = fopen(sFileName.c_str(), "r")))
{
error("open file '" + sFileName + "' error :" + string(strerror(errno)));
}
pushFile(sFileName);
yyparse();
}
}
void TarsParse::pushFile(const string &file)
{
ContextPtr c = new Context(file);
_contexts.push(c);
_vcontexts.push_back(c);
}
ContextPtr TarsParse::popFile()
{
ContextPtr c = _contexts.top();
_contexts.pop();
return c;
}
bool TarsParse::getFilePath(const string &s, string &file)
{
if (_bUseCurrentPath)
{
if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"')
{
error("#include need \"FILENAME\"");
}
file = s.substr(1, s.length() - 2);
std::string sTemp = file;
bool isExist = tars::TC_File::isFileExist(file);
if (!isExist)
{
file = tars::TC_File::extractFileName(file);
}
for(size_t i = 0; i < _vcontexts.size(); i++)
{
if(_vcontexts[i]->getFileName() == file)
{
return false;
}
}
return true;
}
if(_bUseCurrentPathFirst)
{
if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"')
{
error("#include need \"FILENAME\"");
}
file = s.substr(1, s.length() - 2);
std::string sTemp = tars::TC_File::extractFileName(file);
bool isExist = tars::TC_File::isFileExist(sTemp);
if (isExist)
{
file = sTemp;
}
for(size_t i = 0; i < _vcontexts.size(); i++)
{
if(_vcontexts[i]->getFileName() == file)
{
return false;
}
}
return true;
}
if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"')
{
error("#include need \"FILENAME\"");
}
file = s.substr(1, s.length() - 2);
if (!tars::TC_File::isFileExist(file))
{
for (size_t i = 0; i < _vIncludePath.size(); i++)
{
if (tars::TC_File::isFileExist(_vIncludePath[i] + "/" + file))
{
file = _vIncludePath[i] + "/" + file;
break;
}
}
}
for(size_t i = 0; i < _vcontexts.size(); i++)
{
if(_vcontexts[i]->getFileName() == file)
{
return false;
}
}
return true;
}
string TarsParse::getCurrFileName()
{
return _contexts.top()->getFileName();
}
void TarsParse::nextLine()
{
_contexts.top()->nextLine();
}
ContextPtr TarsParse::currentContextPtr()
{
return _contexts.top();
}
void TarsParse::error(const string &msg)
{
cerr << _contexts.top()->getFileName() << ": " << _contexts.top()->getCurrLine() << ": error: " << msg << endl;
exit(-1);
}
int TarsParse::checkKeyword(const string& s)
{
std::map<std::string, int>::const_iterator it = _keywordMap.find(s);
if(it != _keywordMap.end())
{
return it->second;
}
if(!_bWithTars)
{
string sPrefix = "tars";
//不能以tars开头
if((s.length() >= sPrefix.length()) && (s.substr(0, sPrefix.length()) == sPrefix))
{
error("identifier can't start with 'tars'");
}
}
return TARS_IDENTIFIER;
}
void TarsParse::initScanner()
{
_keywordMap["void"] = TARS_VOID;
_keywordMap["struct"] = TARS_STRUCT;
_keywordMap["bool"] = TARS_BOOL;
_keywordMap["byte"] = TARS_BYTE;
_keywordMap["short"] = TARS_SHORT;
_keywordMap["int"] = TARS_INT;
_keywordMap["double"] = TARS_DOUBLE;
_keywordMap["float"] = TARS_FLOAT;
_keywordMap["long"] = TARS_LONG;
_keywordMap["string"] = TARS_STRING;
_keywordMap["vector"] = TARS_VECTOR;
_keywordMap["map"] = TARS_MAP;
_keywordMap["key"] = TARS_KEY;
_keywordMap["routekey"] = TARS_ROUTE_KEY;
_keywordMap["module"] = TARS_NAMESPACE;
_keywordMap["interface"]= TARS_INTERFACE;
_keywordMap["out"] = TARS_OUT;
_keywordMap["require"] = TARS_REQUIRE;
_keywordMap["optional"] = TARS_OPTIONAL;
_keywordMap["false"] = TARS_FALSE;
_keywordMap["true"] = TARS_TRUE;
_keywordMap["enum"] = TARS_ENUM;
_keywordMap["const"] = TARS_CONST;
_keywordMap["unsigned"] = TARS_UNSIGNED;
}
string TarsParse::getTab()
{
ostringstream s;
for(int i = 0; i < _itab; i++)
{
s << " ";
}
return s.str();
}
BuiltinPtr TarsParse::createBuiltin(Builtin::Kind kind,bool isUnsigned)
{
return new Builtin(kind,isUnsigned);
}
VectorPtr TarsParse::createVector(const TypePtr &ptr)
{
return new Vector(ptr);
}
MapPtr TarsParse::createMap(const TypePtr &pleft, const TypePtr &pright)
{
return new Map(pleft, pright);
}
void TarsParse::addNamespacePtr(const NamespacePtr &nPtr)
{
_namespaces.push_back(nPtr);
}
NamespacePtr TarsParse::findNamespace(const string &id)
{
for(size_t i = 0; i < _namespaces.size(); i++)
{
if(_namespaces[i]->getId() == id)
{
return _namespaces[i];
}
}
return NULL;
}
NamespacePtr TarsParse::currentNamespace()
{
return _namespaces.back();
}
void TarsParse::addStructPtr(const StructPtr &sPtr)
{
_structs.push_back(sPtr);
}
void TarsParse::addEnumPtr(const EnumPtr &ePtr)
{
_enums.push_back(ePtr);
}
StructPtr TarsParse::findStruct(const string &sid)
{
string ssid = sid;
//在当前namespace中查找
NamespacePtr np = currentNamespace();
if(ssid.find("::") == string::npos)
{
ssid = np->getId() + "::" + ssid;
}
for(size_t i = 0; i < _structs.size(); i++)
{
if(_structs[i]->getSid() == ssid)
{
return _structs[i];
}
}
return NULL;
}
EnumPtr TarsParse::findEnum(const string &sid)
{
string ssid = sid;
//在当前namespace中查找
NamespacePtr np = currentNamespace();
if(ssid.find("::") == string::npos)
{
ssid = np->getId() + "::" + sid;
}
for(size_t i = 0; i < _enums.size(); i++)
{
if(_enums[i]->getSid() == ssid)
{
return _enums[i];
}
}
return NULL;
}
bool TarsParse::checkEnum(const string &idName)
{
for(size_t i = 0; i < _enums.size(); i++)
{
vector<TypeIdPtr> & list = _enums[i]->getAllMemberPtr();
for (size_t j = 0; j < list.size(); j++)
{
if (list[j]->getId() == idName)
{
return true;
}
}
}
return false;
}
void TarsParse::checkConflict(const string &sid)
{
//是否和枚举重名
if(findEnum(sid))
{
error("conflicts with enum '" + sid + "'");
}
//是否和结构重名
if(findStruct(sid))
{
error("conflicts with struct '" + sid + "'");
}
}
TypePtr TarsParse::findUserType(const string &sid)
{
StructPtr sPtr = findStruct(sid);
if(sPtr) return sPtr;
EnumPtr ePtr = findEnum(sid);
if(ePtr) return ePtr;
return NULL;
}
ContainerPtr TarsParse::currentContainer()
{
return _contains.top();
}
void TarsParse::pushContainer(const ContainerPtr &c)
{
_contains.push(c);
NamespacePtr np = NamespacePtr::dynamicCast(c);
if(np)
{
addNamespacePtr(np);
}
}
ContainerPtr TarsParse::popContainer()
{
ContainerPtr c = _contains.top();
_contains.pop();
return c;
}
void TarsParse::checkTag(int i)
{
if(i >= 256)
{
error("struct memeber tag can't beyond 256");
}
if(i < 0)
{
error("struct memeber tag can't less then 0");
}
}
void TarsParse::checkSize(int i)
{
if(i >= 1024*1024)
{
error("struct memeber size can't beyond 1M");
}
if(i < 1)
{
error("struct memeber size can't less than 1");
}
}
void TarsParse::checkArrayVaid(TypePtr &tPtr,int size)
{
checkSize(size);
//只有string/vector可以为array类型
//vector不可以嵌套array类型 例如不允许vector<string:8>:2;
VectorPtr vPtr = VectorPtr::dynamicCast(tPtr);
if(vPtr )
{
if(vPtr->getTypePtr()->isArray())
{
error("fixed array type can not be nested");
}
return;
}
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(tPtr);
if(bPtr && bPtr->kind()== Builtin::KindString)
{
return;
}
error("only string or vector can use fix array");
}
void TarsParse::checkPointerVaid(TypePtr &tPtr)
{
//必须为vector<Byte>类型
VectorPtr vPtr = VectorPtr::dynamicCast(tPtr);
if(vPtr)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
if( bPtr && bPtr->kind()== Builtin::KindByte)
return;
}
error("only 'byte *' can be pointer type");
}
void TarsParse::checkConstValue(TypeIdPtr &tPtr, int c)
{
//只有内建类型才能有缺省值
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(tPtr->getTypePtr());
EnumPtr ePtr = EnumPtr::dynamicCast(tPtr->getTypePtr());
if(!bPtr && !ePtr)
{
error("only base/enum type can have default value");
}
if (ePtr)
{
if (c != ConstGrammar::VALUE && c != ConstGrammar::ENUM)
{
error("default value of enum only be int or enum_type");
}
return ;
}
int b = bPtr->kind();
if(c == ConstGrammar::VALUE)
{
if(b == Builtin::KindBool)
{
error("default value of bool can only be true or false");
}
if(b == Builtin::KindString)
{
error("default value of string can only be \"string\"");
}
}
else if(c == ConstGrammar::BOOL)
{
if(b != Builtin::KindBool)
{
error("only bool type can be true or false");
}
}
else if(c == ConstGrammar::STRING)
{
if(b != Builtin::KindString)
{
error("only string type can be \"string\"");
}
}
}
string TarsParse::printHeaderRemark()
{
ostringstream s;
s << "// **********************************************************************" << endl;
s << "// This file was generated by a TARS parser!" << endl;
s << "// TARS version " << TARS_VERSION << "." << endl;
s << "// **********************************************************************" << endl;
s << endl;
return s.str();
}

View File

@ -0,0 +1,368 @@
/**
* 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.
*/
#ifndef __TARS_PARSE_H_
#define __TARS_PARSE_H_
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <map>
#include <stack>
#include <sstream>
#include <sys/types.h>
#include <sys/stat.h>
#include "element.h"
#include "util/tc_common.h"
#include "util/tc_autoptr.h"
using namespace std;
/**
* Tars文件解析类
*
*/
class TarsParse : public tars::TC_HandleBase
{
public:
/**
*
*/
TarsParse();
/**
* tars开头的标识
* @param bWithTars
*/
void setTars(bool bWithTars);
/**
*
* @param sHeader
*/
void setHeader(const string &sHeader);
/**
* 使tars文件
* @param bWithTars
*/
void setCurrentPriority(bool bFlag);
/**
*
*/
string getHeader();
/**
*
* @param sFileName
*/
void parse(const string &sFileName);
/**
*
* @param msg
*/
void error(const string &msg);
/**
*
* @param s
*
* @return int
*/
int checkKeyword(const string &s);
/**
*
*/
void nextLine();
/**
*
*
* @return string
*/
string getCurrFileName();
/**
* tab
*
* @return string
*/
string getTab();
/**
* tab数
*/
void incTab() { _itab++; }
/**
* tab数
*/
void delTab() { _itab--; }
/**
*
* @param file
*/
void pushFile(const string &file);
/**
*
*/
ContextPtr popFile();
/**
*
*
* @return std::vector<ContextPtr>
*/
std::vector<ContextPtr> getContexts() { return _vcontexts; }
/**
*
*
* @return ContainerPtr
*/
ContainerPtr currentContainer();
/**
* push容器
* @param c
*/
void pushContainer(const ContainerPtr &c);
/**
*
*
* @return ContextPtr
*/
ContextPtr currentContextPtr();
/**
*
*
* @return ContainerPtr
*/
ContainerPtr popContainer();
/**
* Builtin元素
* @param kind
*
* @return BuiltinPtr
*/
BuiltinPtr createBuiltin(Builtin::Kind kind,bool isUnsigned = false);
/**
* Vector元素
* @param ptr
*
* @return VectorPtr
*/
VectorPtr createVector(const TypePtr &ptr);
/**
* Map元素
* @param pleft
* @param pright
*
* @return MapPtr
*/
MapPtr createMap(const TypePtr &pleft, const TypePtr &pright);
/**
*
* @param sPtr
*/
void addStructPtr(const StructPtr &sPtr);
/**
*
* @param id
*
* @return StructPtr
*/
StructPtr findStruct(const string &sid);
/**
*
* @param ePtr
*/
void addEnumPtr(const EnumPtr &ePtr);
/**
*
* @param id
*
* @return EnumPtr
*/
EnumPtr findEnum(const string &sid);
/**
*
* @param id
*/
void checkConflict(const string &sid);
/**
*
* @param sid
*
* @return TypePtr
*/
TypePtr findUserType(const string &sid);
/**
*
* @param id
*
* @return NamespacePtr
*/
NamespacePtr findNamespace(const string &id);
/**
*
*
* @return NamespacePtr
*/
NamespacePtr currentNamespace();
/**
* tag的合法性
* @param i
*/
void checkTag(int i);
/**
* szie的合法性
* @param i
*/
void checkSize(int i);
/**
* array的合法性
* @param i
*/
void checkArrayVaid(TypePtr &tPtr,int size);
/**
* pointer的合法性
* @param i
*/
void checkPointerVaid(TypePtr &tPtr);
/**
*
* @param c
* @param b
*/
void checkConstValue(TypeIdPtr &tPtr, int b);
/**
*
* @param s
*
* @return string
*/
bool getFilePath(const string &s, string &file);
void setKeyStruct(const StructPtr& key)
{
_key = key;
}
StructPtr getKeyStruct()
{
return _key;
}
/**
*
*/
string printHeaderRemark();
/**
*
*/
bool checkEnum(const string &idName);
/**
* include的tars文件全部从当前文件搜寻
*/
void setUseCurrentPath(const bool & bEnable) { _bUseCurrentPath = bEnable; }
/**
* tars文件时,include路径
*/
void addIncludePath(const string &include)
{
vector<string> v = tars::TC_Common::sepstr<string>(include, "; ,", false);
_vIncludePath.insert(_vIncludePath.end(), v.begin(), v.end());
}
protected:
/**
*
* @param nPtr
*/
void addNamespacePtr(const NamespacePtr &nPtr);
/**
*
*/
void initScanner();
/**
*
*/
void clear();
protected:
bool _bWithTars;
std::map<std::string, int> _keywordMap;
int _itab;
StructPtr _key;
std::stack<ContextPtr> _contexts;
std::stack<ContainerPtr> _contains;
std::vector<ContextPtr> _vcontexts;
std::vector<StructPtr> _structs;
std::vector<EnumPtr> _enums;
std::vector<NamespacePtr> _namespaces;
string _sHeader;
bool _bUseCurrentPath;
bool _bUseCurrentPathFirst;
std::vector<string> _vIncludePath;
};
extern int yyparse();
extern int yylex();
extern FILE *yyin, *yyout;
typedef tars::TC_AutoPtr<TarsParse> TarsParsePtr;
extern TarsParsePtr g_parse;
#endif

View File

@ -0,0 +1,199 @@
/**
* 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.
*/
#ifndef __TC_ATOMIC_H
#define __TC_ATOMIC_H
#include <stdint.h>
namespace tars
{
/////////////////////////////////////////////////
/**
* @file tc_atomic.h
* @brief .
*/
__BEGIN_DECLS
#define TARS_LOCK "lock ; "
typedef struct { volatile int counter; } tars_atomic_t;
#define tars_atomic_read(v) ((v)->counter)
#define tars_atomic_set(v,i) (((v)->counter) = (i))
__END_DECLS
/**
* @brief ,int做原子操作
*/
class TC_Atomic
{
public:
/**
*
*/
typedef int atomic_type;
/**
* @brief ,0
*/
TC_Atomic(atomic_type at = 0)
{
set(at);
}
TC_Atomic& operator++()
{
inc();
return *this;
}
TC_Atomic& operator--()
{
dec();
return *this;
}
operator atomic_type() const
{
return get();
}
TC_Atomic& operator+=(atomic_type n)
{
add(n);
return *this;
}
TC_Atomic& operator-=(atomic_type n)
{
sub(n);
return *this;
}
TC_Atomic& operator=(atomic_type n)
{
set(n);
return *this;
}
/**
* @brief
*
* @return int
*/
atomic_type get() const { return _value.counter; }
/**
* @brief
* @param i
*
* @return int
*/
atomic_type add(atomic_type i) { return add_and_return(i); }
/**
* @brief
* @param i
*
* @return int
*/
atomic_type sub(atomic_type i) { return add_and_return(-i); }
/**
* @brief 1
*
* @return int
*/
atomic_type inc() { return add(1); }
/**
* @brief 1
*/
atomic_type dec() { return sub(1); }
/**
* @brief 1
*
* @return void
*/
void inc_fast()
{
__asm__ __volatile__(
TARS_LOCK "incl %0"
:"=m" (_value.counter)
:"m" (_value.counter));
}
/**
* @brief 1
* Atomically decrements @_value by 1 and returns true if the
* result is 0, or false for all other
*/
bool dec_and_test()
{
unsigned char c;
__asm__ __volatile__(
TARS_LOCK "decl %0; sete %1"
:"=m" (_value.counter), "=qm" (c)
:"m" (_value.counter) : "memory");
return c != 0;
}
/**
* @brief
*/
atomic_type set(atomic_type i)
{
_value.counter = i;
return i;
}
protected:
/**
* @brief
*/
int add_and_return(int i)
{
/* Modern 486+ processor */
int __i = i;
__asm__ __volatile__(
TARS_LOCK "xaddl %0, %1;"
:"=r"(i)
:"m"(_value.counter), "0"(i));
return i + __i;
}
protected:
/**
*
*/
tars_atomic_t _value;
};
}
#endif

View File

@ -0,0 +1,508 @@
/**
* 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.
*/
#ifndef __TC_AUTOPTR_H
#define __TC_AUTOPTR_H
#include "util/tc_atomic.h"
#include "util/tc_ex.h"
namespace tars
{
///////////////////////////////////////////////////////
/**
* @file tc_autoptr.h
* @brief (, ).
*/
//////////////////////////////////////////////////////
/**
* @brief
*/
struct TC_AutoPtrNull_Exception : public TC_Exception
{
TC_AutoPtrNull_Exception(const string &buffer) : TC_Exception(buffer){};
~TC_AutoPtrNull_Exception() throw(){};
};
/**
* @brief .
*
*
*
* TC_Atomic实现
*/
template<class T>
class TC_HandleBaseT
{
public:
/** 原子计数类型*/
typedef T atomic_type;
/**
* @brief .
*
* @return TC_HandleBase&
*/
TC_HandleBaseT& operator=(const TC_HandleBaseT&)
{
return *this;
}
/**
* @brief
*/
void incRef() { _atomic.inc_fast(); }
/**
* @brief , ==0, ,
*/
void decRef()
{
if(_atomic.dec_and_test() && !_bNoDelete)
{
_bNoDelete = true;
delete this;
}
}
/**
* @brief .
*
* @return int
*/
int getRef() const { return _atomic.get(); }
/**
* @brief .
*
* @param b ,true or false
*/
void setNoDelete(bool b) { _bNoDelete = b; }
protected:
/**
* @brief
*/
TC_HandleBaseT() : _atomic(0), _bNoDelete(false)
{
}
/**
* @brief
*/
TC_HandleBaseT(const TC_HandleBaseT&) : _atomic(0), _bNoDelete(false)
{
}
/**
* @brief
*/
virtual ~TC_HandleBaseT()
{
}
protected:
/**
*
*/
atomic_type _atomic;
/**
*
*/
bool _bNoDelete;
};
template<>
inline void TC_HandleBaseT<int>::incRef()
{
//__sync_fetch_and_add(&_atomic,1);
++_atomic;
}
template<>
inline void TC_HandleBaseT<int>::decRef()
{
//int c = __sync_fetch_and_sub(&_atomic, 1);
//if(c == 1 && !_bNoDelete)
if(--_atomic == 0 && !_bNoDelete)
{
_bNoDelete = true;
delete this;
}
}
template<>
inline int TC_HandleBaseT<int>::getRef() const
{
//return __sync_fetch_and_sub(const_cast<volatile int*>(&_atomic), 0);
return _atomic;
}
typedef TC_HandleBaseT<TC_Atomic> TC_HandleBase;
/**
* @brief .
*
* ,线.
*
*
*
* .
*
* template<typename T> T必须继承于TC_HandleBase
*/
template<typename T>
class TC_AutoPtr
{
public:
/**
*
*/
typedef T element_type;
/**
* @brief , +1.
*
* @param p
*/
TC_AutoPtr(T* p = 0)
{
_ptr = p;
if(_ptr)
{
_ptr->incRef();
}
}
/**
* @brief r的原生指针初始化, +1.
*
* @param Y
* @param r
*/
template<typename Y>
TC_AutoPtr(const TC_AutoPtr<Y>& r)
{
_ptr = r._ptr;
if(_ptr)
{
_ptr->incRef();
}
}
/**
* @brief , +1.
*
* @param r
*/
TC_AutoPtr(const TC_AutoPtr& r)
{
_ptr = r._ptr;
if(_ptr)
{
_ptr->incRef();
}
}
/**
* @brief
*/
~TC_AutoPtr()
{
if(_ptr)
{
_ptr->decRef();
}
}
/**
* @brief , .
*
* @param p
* @return TC_AutoPtr&
*/
TC_AutoPtr& operator=(T* p)
{
if(_ptr != p)
{
if(p)
{
p->incRef();
}
T* ptr = _ptr;
_ptr = p;
if(ptr)
{
ptr->decRef();
}
}
return *this;
}
/**
* @brief , .
*
* @param Y
* @param r
* @return TC_AutoPtr&
*/
template<typename Y>
TC_AutoPtr& operator=(const TC_AutoPtr<Y>& r)
{
if(_ptr != r._ptr)
{
if(r._ptr)
{
r._ptr->incRef();
}
T* ptr = _ptr;
_ptr = r._ptr;
if(ptr)
{
ptr->decRef();
}
}
return *this;
}
/**
* @brief , .
*
* @param r
* @return TC_AutoPtr&
*/
TC_AutoPtr& operator=(const TC_AutoPtr& r)
{
if(_ptr != r._ptr)
{
if(r._ptr)
{
r._ptr->incRef();
}
T* ptr = _ptr;
_ptr = r._ptr;
if(ptr)
{
ptr->decRef();
}
}
return *this;
}
/**
* @brief .
*
* @param Y
* @param r
* @return TC_AutoPtr
*/
template<class Y>
static TC_AutoPtr dynamicCast(const TC_AutoPtr<Y>& r)
{
return TC_AutoPtr(dynamic_cast<T*>(r._ptr));
}
/**
* @brief .
*
* @param Y
* @param p
* @return TC_AutoPtr
*/
template<class Y>
static TC_AutoPtr dynamicCast(Y* p)
{
return TC_AutoPtr(dynamic_cast<T*>(p));
}
/**
* @brief .
*
* @return T*
*/
T* get() const
{
return _ptr;
}
/**
* @brief .
*
* @return T*
*/
T* operator->() const
{
if(!_ptr)
{
throwNullHandleException();
}
return _ptr;
}
/**
* @brief .
*
* @return T&
*/
T& operator*() const
{
if(!_ptr)
{
throwNullHandleException();
}
return *_ptr;
}
/**
* @brief .
*
* @return bool
*/
operator bool() const
{
return _ptr ? true : false;
}
/**
* @brief .
*
* @param other
*/
void swap(TC_AutoPtr& other)
{
std::swap(_ptr, other._ptr);
}
protected:
/**
* @brief
*/
void throwNullHandleException() const;
public:
T* _ptr;
};
/**
* @brief .
*
* @param T
* @param file
* @param line
*/
template<typename T> inline void
TC_AutoPtr<T>::throwNullHandleException() const
{
throw TC_AutoPtrNull_Exception("autoptr null handle error");
}
/**
* @brief ==.
*
* @param T
* @param U
* @param lhs
* @param rhs
*
* @return bool
*/
template<typename T, typename U>
inline bool operator==(const TC_AutoPtr<T>& lhs, const TC_AutoPtr<U>& rhs)
{
T* l = lhs.get();
U* r = rhs.get();
if(l && r)
{
return *l == *r;
}
else
{
return !l && !r;
}
}
/**
* @brief .
*
* @param T
* @param U
* @param lhs
* @param rhs
*
* @return bool
*/
template<typename T, typename U>
inline bool operator!=(const TC_AutoPtr<T>& lhs, const TC_AutoPtr<U>& rhs)
{
T* l = lhs.get();
U* r = rhs.get();
if(l && r)
{
return *l != *r;
}
else
{
return l || r;
}
}
/**
* @brief , map等容器中.
*
* @param T
* @param U
* @param lhs
* @param rhs
*
* @return bool
*/
template<typename T, typename U>
inline bool operator<(const TC_AutoPtr<T>& lhs, const TC_AutoPtr<U>& rhs)
{
T* l = lhs.get();
U* r = rhs.get();
if(l && r)
{
return *l < *r;
}
else
{
return !l && r;
}
}
}
#endif

View File

@ -0,0 +1,785 @@
/**
* 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.
*/
#ifndef __TC_COMMON_H
#define __TC_COMMON_H
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <cassert>
#include <cstdio>
#include <string>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <algorithm>
#include <map>
#include <stack>
#include <vector>
using namespace std;
namespace tars
{
/////////////////////////////////////////////////
/**
* @file tc_common.h
* @brief ,, .
*
*/
/////////////////////////////////////////////////
/**
* @brief 使.
*
* :
*
* Trim类函数,,
*
* ,,,,
*
* ,Ip匹配函数,
*/
class TC_Common
{
public:
/**
* @brief .
*
* @param sStr
* @param s
* @param bChar true, s中每个字符; false, s字符串
* @return string
*/
static string trim(const string &sStr, const string &s = " \r\n\t", bool bChar = true);
/**
* @brief .
*
* @param sStr
* @param s
* @param bChar true, s中每个字符; false, s字符串
* @return string
*/
static string trimleft(const string &sStr, const string &s = " \r\n\t", bool bChar = true);
/**
* @brief .
*
* @param sStr
* @param s
* @param bChar true, s中每个字符; false, s字符串
* @return string
*/
static string trimright(const string &sStr, const string &s = " \r\n\t", bool bChar = true);
/**
* @brief .
*
* @param sString
* @return string
*/
static string lower(const string &sString);
/**
* @brief .
*
* @param sString
* @return string
*/
static string upper(const string &sString);
/**
* @brief .
*
* @param sString
* @return bool
*/
static bool isdigit(const string &sInput);
/**
* @brief .
*
* @param sString
* @param sFormat
* @param stTm
* @return 0: , -1:
*/
static int str2tm(const string &sString, const string &sFormat, struct tm &stTm);
/**
* @brief GMT格式的时间转化为时间结构
*
* eg.Sat, 06 Feb 2010 09:29:29 GMT, %a, %d %b %Y %H:%M:%S GMT
*
* mktime换成time_t, mktime(&stTm)
*
* - timezone换成本地的秒(time(NULL)) timezone是系统的 ,
*
* extern long timezone;
*
* @param sString GMT格式的时间
* @param stTm
* @return 0: , -1:
*/
static int strgmt2tm(const string &sString, struct tm &stTm);
/**
* @brief .
*
* @param stTm
* @param sFormat
* @return string
*/
static string tm2str(const struct tm &stTm, const string &sFormat = "%Y%m%d%H%M%S");
/**
* @brief .
*
* @param t
* @param sFormat
* @return string
*/
static string tm2str(const time_t &t, const string &sFormat = "%Y%m%d%H%M%S");
/**
* @brief
* @param sFormat
* @return string
*/
static string now2str(const string &sFormat = "%Y%m%d%H%M%S");
/**
* @brief GMT字符串GMT格式:Fri, 12 Jan 2001 18:18:18 GMT
* @param stTm
* @return string GMT格式的时间字符串
*/
static string tm2GMTstr(const struct tm &stTm);
/**
* @brief GMT字符串GMT格式:Fri, 12 Jan 2001 18:18:18 GMT
* @param stTm
* @return string GMT格式的时间字符串
*/
static string tm2GMTstr(const time_t &t);
/**
* @brief GMT字符串GMT格式:Fri, 12 Jan 2001 18:18:18 GMT
* @return string GMT格式的时间字符串
*/
static string now2GMTstr();
/**
* @brief ()(%Y%m%d).
*
* @return string (%Y%m%d)
*/
static string nowdate2str();
/**
* @brief ()(%H%M%S).
*
* @return string (%H%M%S)
*/
static string nowtime2str();
/**
* @brief .
*
* @return int64_t
*/
static int64_t now2ms();
/**
* @brief .
*
* @return int64_t
*/
static int64_t now2us();
/**
* @brief T型T是数值类型, str为空,T为0.
*
* @param sStr
* @return T T型类型
*/
template<typename T>
static T strto(const string &sStr);
/**
* @brief T型.
*
* @param sStr
* @param sDefault
* @return T T类型
*/
template<typename T>
static T strto(const string &sStr, const string &sDefault);
/**
* @brief ,,vector里
*
* : |a|b||c|
*
* withEmpty=true时, |:"","a", "b", "", "c", ""
*
* withEmpty=false时, |:"a", "b", "c"
*
* T类型为int等数值类型, "", 0
*
* @param sStr
* @param sSep ()
* @param withEmpty true代表空的也算一个元素, false时空的过滤
* @return vector
*/
template<typename T>
static vector<T> sepstr(const string &sStr, const string &sSep, bool withEmpty = false);
/**
* @brief T型转换成字符串T能够使用ostream对象用<<,
* @param t
* @return
*/
template<typename T>
static string tostr(const T &t);
/**
* @brief vector转换成string.
*
* @param t vector型的数据
* @return
*/
template<typename T>
static string tostr(const vector<T> &t);
/**
* @brief map输出为字符串.
*
* @param map<K, V, D, A> map对象
* @return string
*/
template<typename K, typename V, typename D, typename A>
static string tostr(const map<K, V, D, A> &t);
/**
* @brief map输出为字符串.
*
* @param multimap<K, V, D, A> map对象
* @return
*/
template<typename K, typename V, typename D, typename A>
static string tostr(const multimap<K, V, D, A> &t);
/**
* @brief pair map等关系容器可以直接用tostr来输出
* @param pair<F, S> pair对象
* @return
*/
template<typename F, typename S>
static string tostr(const pair<F, S> &itPair);
/**
* @brief container .
*
* @param iFirst
* @param iLast
* @param sSep
* @return
*/
template <typename InputIter>
static string tostr(InputIter iFirst, InputIter iLast, const string &sSep = "|");
/**
* @brief .
*
* @param buf buffer
* @param len buffer长度
* @param sSep
* @param lines , 0
* @return
*/
static string bin2str(const void *buf, size_t len, const string &sSep = "", size_t lines = 0);
/**
* @brief .
*
* @param sBinData
* @param sSep
* @param lines , 0
* @return
*/
static string bin2str(const string &sBinData, const string &sSep = "", size_t lines = 0);
/**
* @brief .
*
* @param psAsciiData
* @param sBinData
* @param iBinSize
* @return 0
*/
static int str2bin(const char *psAsciiData, unsigned char *sBinData, int iBinSize);
/**
* @brief .
*
* @param sBinData
* @param sSep
* @param lines , 0
* @return
*/
static string str2bin(const string &sBinData, const string &sSep = "", size_t lines = 0);
/**
* @brief .
*
* @param sString
* @param sSrc
* @param sDest
* @return string
*/
static string replace(const string &sString, const string &sSrc, const string &sDest);
/**
* @brief .
*
* @param sString
* @param mSrcDest map<,>
* @return string
*/
static string replace(const string &sString, const map<string,string>& mSrcDest);
/**
* @brief .pat中*
* s为空, false pat为空, true
* @param s
* @param pat *ip地址
* @return
*/
static bool matchPeriod(const string& s, const string& pat);
/**
* @brief ..
*
* @param s
* @param pat vector中的每个元素都是带*ip地址
* @return
*/
static bool matchPeriod(const string& s, const vector<string>& pat);
/**
* @brief .
*
* @param n
* @return true代表是素数false表示非素数
*/
static bool isPrimeNumber(size_t n);
/**
* @brief daemon
*/
static void daemon();
/**
* @brief
*/
static void ignorePipe();
/**
* @brief string类型转成一个字节 .
*
* @param sWhat
* @return char
*/
static char x2c(const string &sWhat);
/**
* @brief K, M, G两种 : 1K, 3M, 4G, 4.5M, 2.3G
* @param s
* @param iDefaultSize ,
* @return
*/
static size_t toSize(const string &s, size_t iDefaultSize);
/**
* @brief 16
* @param p
* @param len
*/
static void getRandomHexChars(char* p, unsigned int len);
};
namespace p
{
template<typename D>
struct strto1
{
D operator()(const string &sStr)
{
string s = "0";
if(!sStr.empty())
{
s = sStr;
}
istringstream sBuffer(s);
D t;
sBuffer >> t;
return t;
}
};
template<>
struct strto1<char>
{
char operator()(const string &sStr)
{
if(!sStr.empty())
{
return sStr[0];
}
return 0;
}
};
template<>
struct strto1<short>
{
short operator()(const string &sStr)
{
if(!sStr.empty())
{
return atoi(sStr.c_str());
}
return 0;
}
};
template<>
struct strto1<unsigned short>
{
unsigned short operator()(const string &sStr)
{
if(!sStr.empty())
{
return strtoul(sStr.c_str(), NULL, 10);
}
return 0;
}
};
template<>
struct strto1<int>
{
int operator()(const string &sStr)
{
if(!sStr.empty())
{
return atoi(sStr.c_str());
}
return 0;
}
};
template<>
struct strto1<unsigned int>
{
unsigned int operator()(const string &sStr)
{
if(!sStr.empty())
{
return strtoul(sStr.c_str(), NULL, 10);
}
return 0;
}
};
template<>
struct strto1<long>
{
long operator()(const string &sStr)
{
if(!sStr.empty())
{
return atol(sStr.c_str());
}
return 0;
}
};
template<>
struct strto1<long long>
{
long long operator()(const string &sStr)
{
if(!sStr.empty())
{
return atoll(sStr.c_str());
}
return 0;
}
};
template<>
struct strto1<unsigned long>
{
unsigned long operator()(const string &sStr)
{
if(!sStr.empty())
{
return strtoul(sStr.c_str(), NULL, 10);
}
return 0;
}
};
template<>
struct strto1<float>
{
float operator()(const string &sStr)
{
if(!sStr.empty())
{
return atof(sStr.c_str());
}
return 0;
}
};
template<>
struct strto1<double>
{
double operator()(const string &sStr)
{
if(!sStr.empty())
{
return atof(sStr.c_str());
}
return 0;
}
};
template<typename D>
struct strto2
{
D operator()(const string &sStr)
{
istringstream sBuffer(sStr);
D t;
sBuffer >> t;
return t;
}
};
template<>
struct strto2<string>
{
string operator()(const string &sStr)
{
return sStr;
}
};
}
template<typename T>
T TC_Common::strto(const string &sStr)
{
using strto_type = typename std::conditional<std::is_arithmetic<T>::value, p::strto1<T>, p::strto2<T>>::type;
return strto_type()(sStr);
}
template<typename T>
T TC_Common::strto(const string &sStr, const string &sDefault)
{
string s;
if(!sStr.empty())
{
s = sStr;
}
else
{
s = sDefault;
}
return strto<T>(s);
}
template<typename T>
vector<T> TC_Common::sepstr(const string &sStr, const string &sSep, bool withEmpty)
{
vector<T> vt;
string::size_type pos = 0;
string::size_type pos1 = 0;
while(true)
{
string s;
pos1 = sStr.find_first_of(sSep, pos);
if(pos1 == string::npos)
{
if(pos + 1 <= sStr.length())
{
s = sStr.substr(pos);
}
}
else if(pos1 == pos)
{
s = "";
}
else
{
s = sStr.substr(pos, pos1 - pos);
pos = pos1;
}
if(withEmpty)
{
vt.push_back(strto<T>(s));
}
else
{
if(!s.empty())
{
T tmp = strto<T>(s);
vt.push_back(tmp);
}
}
if(pos1 == string::npos)
{
break;
}
pos++;
}
return vt;
}
template<typename T>
string TC_Common::tostr(const T &t)
{
ostringstream sBuffer;
sBuffer << t;
return sBuffer.str();
}
template<typename T>
string TC_Common::tostr(const vector<T> &t)
{
string s;
for(size_t i = 0; i < t.size(); i++)
{
s += tostr(t[i]);
s += " ";
}
return s;
}
template<typename K, typename V, typename D, typename A>
string TC_Common::tostr(const map<K, V, D, A> &t)
{
string sBuffer;
typename map<K, V, D, A>::const_iterator it = t.begin();
while(it != t.end())
{
sBuffer += " [";
sBuffer += tostr(it->first);
sBuffer += "]=[";
sBuffer += tostr(it->second);
sBuffer += "] ";
++it;
}
return sBuffer;
}
template<typename K, typename V, typename D, typename A>
string TC_Common::tostr(const multimap<K, V, D, A> &t)
{
string sBuffer;
typename multimap<K, V, D, A>::const_iterator it = t.begin();
while(it != t.end())
{
sBuffer += " [";
sBuffer += tostr(it->first);
sBuffer += "]=[";
sBuffer += tostr(it->second);
sBuffer += "] ";
++it;
}
return sBuffer;
}
template<typename F, typename S>
string TC_Common::tostr(const pair<F, S> &itPair)
{
string sBuffer;
sBuffer += "[";
sBuffer += tostr(itPair.first);
sBuffer += "]=[";
sBuffer += tostr(itPair.second);
sBuffer += "]";
return sBuffer;
}
template <typename InputIter>
string TC_Common::tostr(InputIter iFirst, InputIter iLast, const string &sSep)
{
string sBuffer;
InputIter it = iFirst;
while(it != iLast)
{
sBuffer += tostr(*it);
++it;
if(it != iLast)
{
sBuffer += sSep;
}
else
{
break;
}
}
return sBuffer;
}
}
#endif

View File

@ -0,0 +1,143 @@
/**
* 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.
*/
#ifndef __TC_ENCODER_H_
#define __TC_ENCODER_H_
#include <vector>
#include "util/tc_ex.h"
namespace tars
{
/////////////////////////////////////////////////
/**
* @file tc_encoder.h
* @brief
*
*
*/
/////////////////////////////////////////////////
/**
* @brief
*/
struct TC_Encoder_Exception : public TC_Exception
{
TC_Encoder_Exception(const string &buffer) : TC_Exception(buffer){};
TC_Encoder_Exception(const string &buffer, int err) : TC_Exception(buffer, err){};
~TC_Encoder_Exception() throw(){};
};
/**
* @brief .
*
* Gbk到utf8之间的相互转码函数.
*
* 1GBK ==> UTF8的转换
*
* 2UTF8 ==> GBK的转换
*/
class TC_Encoder
{
public:
/**
* @brief gbk utf8.
*
* @param sOut buffer
* @param iMaxOutLen buffer最大的长度/sOut的长度
* @param sIn buffer
* @param iInLen buffer长度
* @throws TC_Encoder_Exception
* @return
*/
static void gbk2utf8(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen);
/**
* @brief gbk utf8.
*
* @param sIn buffer*
* @throws TC_Encoder_Exception
* @return utf8编码
*/
static string gbk2utf8(const string &sIn);
/**
* @brief gbk utf8.
*
* @param sIn buffer
* @param vtStr gbk的vector
* @throws TC_Encoder_Exception
* @return
*/
static void gbk2utf8(const string &sIn, vector<string> &vtStr);
/**
* @brief utf8 gbk.
*
* @param sOut buffer
* @param iMaxOutLen buffer最大的长度/sOut的长度
* @param sIn buffer
* @param iInLen buffer长度
* @throws TC_Encoder_Exception
* @return
*/
static void utf82gbk(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen);
/**
* @brief utf8 gbk.
*
* @param sIn buffer
* @throws TC_Encoder_Exception
* @return gbk编码
*/
static string utf82gbk(const string &sIn);
/**
* @brief string的\n替换掉,
*
* :\n \r\0; \r转换为\,
*
* string记录在一行bin-log的地方;
* @param str
* @param f
* @param t
* @param u
* @return str
*/
static string transTo(const string& str, char f = '\n', char t = '\r', char u = '\0');
/**
* @brief , transTo
*
* :\r\0 \n\r\r还原为,
*
* string记录在一行bin-log的地方
* @param str (transTo后得到的字符串)
* @param f
* @param t
* @param u
* @return str
*/
static string transFrom(const string& str, char f = '\n', char t = '\r', char u = '\0');
};
}
#endif

View File

@ -0,0 +1,94 @@
/**
* 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.
*/
#ifndef __TC_EX_H
#define __TC_EX_H
#include <stdexcept>
using namespace std;
namespace tars
{
/////////////////////////////////////////////////
/**
* @file tc_ex.h
* @brief
*/
/////////////////////////////////////////////////
/**
* @brief .
*/
class TC_Exception : public exception
{
public:
/**
* @brief errno的构造函数
*
*
*
* @param buffer
*/
explicit TC_Exception(const string &buffer);
/**
* @brief ,errno的构造函数
*
*
*
* @param buffer
* @param err , strerror获取错误信息
*/
TC_Exception(const string &buffer, int err);
/**
* @brief
*/
virtual ~TC_Exception() throw();
/**
* @brief .
*
* @return const char*
*/
virtual const char* what() const throw();
/**
* @brief
*
* @return 0
*/
int getErrCode() { return _code; }
private:
void getBacktrace();
private:
/**
*
*/
string _buffer;
/**
*
*/
int _code;
};
}
#endif

View File

@ -0,0 +1,289 @@
/**
* 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.
*/
#ifndef __TC_FILE_H_
#define __TC_FILE_H_
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
#include "util/tc_ex.h"
#include "util/tc_common.h"
namespace tars
{
/////////////////////////////////////////////////
/**
* @file tc_file.h
* @brief .
*
*/
/////////////////////////////////////////////////
/**
* @brief .
*
*/
struct TC_File_Exception : public TC_Exception
{
TC_File_Exception(const string &buffer) : TC_Exception(buffer){};
TC_File_Exception(const string &buffer, int err) : TC_Exception(buffer, err){};
~TC_File_Exception() throw(){};
};
/**
* @brief .
*
*/
class TC_File
{
public:
/**
* @brief , , -1.
*
* @param sFullFileName ()
* @return ofstream::pos_type类型文件大小
*/
static ifstream::pos_type getFileSize(const string &sFullFileName);
/**
* @brief , '/'.
*
* @param sFullFileName ()
* @return ture是绝对路径false代表非绝对路径
*/
static bool isAbsolute(const string &sFullFileName);
/**
* @brief .
* ,
* @param sFullFileName
* @param iFileType , S_IFREG
* @return true代表存在fals代表不存在
*/
static bool isFileExist(const string &sFullFileName, mode_t iFileType = S_IFREG);
/**
* @brief .
* : ,
* @param sFullFileName
* @param iFileType , S_IFREG
* @return true-fals-
*/
static bool isFileExistEx(const string &sFullFileName, mode_t iFileType = S_IFREG);
/**
* @brief , , ./.
*
* @param path
* @return
*/
static string simplifyDirectory(const string& path);
/**
* @brief , , .
*
* @param sFullPath
* @param iFlag , S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP| S_IXGRP | S_IROTH | S_IXOTH
* @return bool true- false-
*/
static bool makeDir(const string &sDirectoryPath, mode_t iFlag = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
/**
*@brief , , .
*
* @param sFullPath
* @param iFlag , S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
* @return true-false-
*/
static bool makeDirRecursive(const string &sDirectoryPath, mode_t iFlag = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
/**
* @brief .
*
* @param sFullFileName
* @param canExecutable true表示可执行, false代表不可之行
* @return 0,
*/
static int setExecutable(const string &sFullFileName, bool canExecutable);
/**
* @brief .
*
* @param sFullFileName
* @return true-, false-
*/
static bool canExecutable(const string &sFullFileName);
/**
* @brief .
*
* @param sFullFileName
* @param bRecursive
* @return 0-errno查看失败的原因
*/
static int removeFile(const string &sFullFileName, bool bRecursive);
/**
* @brief string
* ,
* @param sFullFileName
* @return
*/
static string load2str(const string &sFullFileName);
/**
* @brief vector<char>
* ,
* @param sFullFileName
*/
static void load2str(const string &sFullFileName, vector<char> &buffer);
/**
* @brief .
*
* @param sFullFileName
* @param sFileData
* @return
*/
static void save2file(const string &sFullFileName, const string &sFileData);
/**
* @brief .
*
* @param sFullFileName
* @param sFileData
* @param length
* @return 0-,-1-
*/
static int save2file(const string &sFullFileName, const char *sFileData, size_t length);
/**
* @brief .
*
* @return string
*/
static string getExePath();
/**
* @brief
*:/usr/local/temp.gif获取temp.gif
*@param sFullFileName
*@return string
*/
static string extractFileName(const string &sFullFileName);
/**
* @brief .
*
* 1: "/usr/local/temp.gif" "/usr/local/"
* 2: "temp.gif" "./"
* @param sFullFileName
* @return
*/
static string extractFilePath(const string &sFullFileName);
/**
* @brief .
*
* 1: "/usr/local/temp.gif" "gif"
* 2: "temp.gif" "gif"
*@param sFullFileName
*@return
*/
static string extractFileExt(const string &sFullFileName);
/**
* @brief ,.
* 1: "/usr/local/temp.gif" "/usr/local/temp"
* 2: "temp.gif" "temp"
* @param sFullFileName
* @return
*/
static string excludeFileExt(const string &sFullFileName);
/**
* @brief
*
* , =?1:
* 1"/usr/temp.gif" "jpg" "/usr/temp.jpg"
* 2: "/usr/local/temp" "jpg" "/usr/local/temp.jpg"
* @param sFullFileName
* @param sExt
* @return
*/
static string replaceFileExt(const string &sFullFileName, const string &sExt);
/**
* @brief url中获取完全文件名.
*
* http://外,第一个'/'后面的所有字符
* 1:http://www.qq.com/tmp/temp.gif 获取tmp/temp.gif
* 2:www.qq.com/tmp/temp.gif tmp/temp.gif
* 3:/tmp/temp.gif tmp/temp.gif
* @param sUrl url字符串
* @return
*/
static string extractUrlFilePath(const string &sUrl);
/**
* @brief .
*
* @return 1-, 0-
*/
typedef int (*FILE_SELECT)(const dirent *);
/**
* @brief .
*
* @param sFilePath
* @param vtMatchFiles
* @param f ,NULL表示所有文件都获取
* @param iMaxSize ,iMaxSize <=0,
* @return
*/
static size_t scanDir(const string &sFilePath, vector<string> &vtMatchFiles, FILE_SELECT f = NULL, int iMaxSize = 0);
/**
* @brief , .
*
* @param path
* @param files
* @param bRecursive
*
**/
static void listDirectory(const string &path, vector<string> &files, bool bRecursive);
/**
* @brief .
* sExistFile复制到sNewFile
* @param sExistFile
* @param sNewFile
* @param bRemove sNewFile再copy Textfile busy导致复制失败
* @return
*/
static void copyFile(const string &sExistFile, const string &sNewFile,bool bRemove = false);
};
}
#endif // TC_FILE_H

View File

@ -0,0 +1,111 @@
/**
* 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.
*/
#ifndef __TC_OPTION_H
#define __TC_OPTION_H
#include <map>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
namespace tars
{
/////////////////////////////////////////////////
/**
* @file tc_option.h
* @brief .
*
*/
/////////////////////////////////////////////////
/**
* @brief
*
* : ./main.exe --name=value --with abc def
*/
class TC_Option
{
public:
/**
* @brief
*/
TC_Option(){};
/**
* @brief .
*
* @param argc
* @param argv
*
*/
void decode(int argc, char *argv[]);
/**
* @brief --.
*
* @param sName
* @return bool truefalse
*/
bool hasParam(const string &sName);
/**
* @brief -- ,
* ""
* @param sName
* @return string
*/
string getValue(const string &sName);
/**
* @brief --.
*
* @return map<string,string> map类型的标识和参数值的对应关系
*/
map<string, string>& getMulti();
/**
* @brief , abc,
* defvector中
* @return vector<string> vector
*/
vector<string>& getSingle();
protected:
/**
* @brief
* --name=value name和vaue
* @param s
*/
void parse(const string &s);
protected:
/**
*--name=valuename和value
*/
map<string, string> _mParam;
/**
*vetor
*/
vector<string> _vSingle;
};
}
#endif

View File

@ -0,0 +1,757 @@
/**
* 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 "util/tc_common.h"
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#include <cmath>
namespace tars
{
template <>
string TC_Common::tostr<bool>(const bool &t)
{
char buf[2];
buf[0] = t ? '1' : '0';
buf[1] = '\0';
return string(buf);
}
template <>
string TC_Common::tostr<char>(const char &t)
{
char buf[2];
snprintf(buf, 2, "%c", t);
return string(buf);
}
template <>
string TC_Common::tostr<unsigned char>(const unsigned char &t)
{
char buf[2];
snprintf(buf, 2, "%c", t);
return string(buf);
}
template <>
string TC_Common::tostr<short>(const short &t)
{
char buf[16];
snprintf(buf, 16, "%d", t);
return string(buf);
}
template <>
string TC_Common::tostr<unsigned short>(const unsigned short &t)
{
char buf[16];
snprintf(buf, 16, "%u", t);
return string(buf);
}
template <>
string TC_Common::tostr<int>(const int &t)
{
char buf[16];
snprintf(buf, 16, "%d", t);
return string(buf);
}
template <>
string TC_Common::tostr<unsigned int>(const unsigned int &t)
{
char buf[16];
snprintf(buf, 16, "%u", t);
return string(buf);
}
template <>
string TC_Common::tostr<long>(const long &t)
{
char buf[32];
snprintf(buf, 32, "%ld", t);
return string(buf);
}
template <>
string TC_Common::tostr<long long>(const long long &t)
{
char buf[32];
snprintf(buf, 32, "%lld", t);
return string(buf);
}
template <>
string TC_Common::tostr<unsigned long>(const unsigned long &t)
{
char buf[32];
snprintf(buf, 32, "%lu", t);
return string(buf);
}
template <>
string TC_Common::tostr<float>(const float &t)
{
char buf[32];
snprintf(buf, 32, "%.5f", t);
string s(buf);
//去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1
bool bFlag = false;
int pos = int(s.size() - 1);
for(; pos > 0; --pos)
{
if(s[pos] == '0')
{
bFlag = true;
if(s[pos-1] == '.')
{
//-2为了去掉"."号
pos -= 2;
break;
}
}
else
{
break;
}
}
if(bFlag)
s = s.substr(0, pos+1);
return s;
}
template <>
string TC_Common::tostr<double>(const double &t)
{
char buf[32];
snprintf(buf, 32, "%.5f", t);
string s(buf);
//去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1
bool bFlag = false;
int pos = int(s.size() - 1);
for(; pos > 0; --pos)
{
if(s[pos] == '0')
{
bFlag = true;
if(s[pos-1] == '.')
{
//-2为了去掉"."号
pos -= 2;
break;
}
}
else
{
break;
}
}
if(bFlag)
s = s.substr(0, pos+1);
return s;
}
template <>
string TC_Common::tostr<long double>(const long double &t)
{
char buf[32];
snprintf(buf, 32, "%Lf", t);
string s(buf);
//去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1
bool bFlag = false;
int pos = int(s.size() - 1);
for(; pos > 0; --pos)
{
if(s[pos] == '0')
{
bFlag = true;
if(s[pos-1] == '.')
{
//-2为了去掉"."号
pos -= 2;
break;
}
}
else
{
break;
}
}
if(bFlag)
s = s.substr(0, pos+1);
return s;
}
template <>
string TC_Common::tostr<std::string>(const std::string &t)
{
return t;
}
string TC_Common::trim(const string &sStr, const string &s, bool bChar)
{
if(sStr.empty())
{
return sStr;
}
/**
* s相同的字符串去掉
*/
if(!bChar)
{
return trimright(trimleft(sStr, s, false), s, false);
}
return trimright(trimleft(sStr, s, true), s, true);
}
string TC_Common::trimleft(const string &sStr, const string &s, bool bChar)
{
if(sStr.empty())
{
return sStr;
}
/**
* sStr左边的字符串s
*/
if(!bChar)
{
if(sStr.length() < s.length())
{
return sStr;
}
if(sStr.compare(0, s.length(), s) == 0)
{
return sStr.substr(s.length());
}
return sStr;
}
/**
* sStr左边的 s中的字符
*/
string::size_type pos = 0;
while(pos < sStr.length())
{
if(s.find_first_of(sStr[pos]) == string::npos)
{
break;
}
pos++;
}
if(pos == 0) return sStr;
return sStr.substr(pos);
}
string TC_Common::trimright(const string &sStr, const string &s, bool bChar)
{
if(sStr.empty())
{
return sStr;
}
/**
* sStr右边的字符串s
*/
if(!bChar)
{
if(sStr.length() < s.length())
{
return sStr;
}
if(sStr.compare(sStr.length() - s.length(), s.length(), s) == 0)
{
return sStr.substr(0, sStr.length() - s.length());
}
return sStr;
}
/**
* sStr右边的 s中的字符
*/
string::size_type pos = sStr.length();
while(pos != 0)
{
if(s.find_first_of(sStr[pos-1]) == string::npos)
{
break;
}
pos--;
}
if(pos == sStr.length()) return sStr;
return sStr.substr(0, pos);
}
string TC_Common::lower(const string &s)
{
string sString = s;
for (string::iterator iter = sString.begin(); iter != sString.end(); ++iter)
{
*iter = tolower(*iter);
}
return sString;
}
string TC_Common::upper(const string &s)
{
string sString = s;
for (string::iterator iter = sString.begin(); iter != sString.end(); ++iter)
{
*iter = toupper(*iter);
}
return sString;
}
bool TC_Common::isdigit(const string &sInput)
{
string::const_iterator iter = sInput.begin();
if(sInput.empty())
{
return false;
}
while(iter != sInput.end())
{
if (!::isdigit(*iter))
{
return false;
}
++iter;
}
return true;
}
int TC_Common::str2tm(const string &sString, const string &sFormat, struct tm &stTm)
{
char *p = strptime(sString.c_str(), sFormat.c_str(), &stTm);
return (p != NULL) ? 0 : -1;
}
int TC_Common::strgmt2tm(const string &sString, struct tm &stTm)
{
return str2tm(sString, "%a, %d %b %Y %H:%M:%S GMT", stTm);
}
string TC_Common::tm2str(const struct tm &stTm, const string &sFormat)
{
char sTimeString[255] = "\0";
strftime(sTimeString, sizeof(sTimeString), sFormat.c_str(), &stTm);
return string(sTimeString);
}
string TC_Common::tm2str(const time_t &t, const string &sFormat)
{
struct tm tt;
localtime_r(&t, &tt);
return tm2str(tt, sFormat);
}
string TC_Common::now2str(const string &sFormat)
{
time_t t = time(NULL);
return tm2str(t, sFormat.c_str());
}
string TC_Common::now2GMTstr()
{
time_t t = time(NULL);
return tm2GMTstr(t);
}
string TC_Common::tm2GMTstr(const time_t &t)
{
struct tm tt;
gmtime_r(&t, &tt);
return tm2str(tt, "%a, %d %b %Y %H:%M:%S GMT");
}
string TC_Common::tm2GMTstr(const struct tm &stTm)
{
return tm2str(stTm, "%a, %d %b %Y %H:%M:%S GMT");
}
string TC_Common::nowdate2str()
{
return now2str("%Y%m%d");
}
string TC_Common::nowtime2str()
{
return now2str("%H%M%S");
}
int64_t TC_Common::now2ms()
{
struct timeval tv;
gettimeofday(&tv, 0);
return tv.tv_sec * (int64_t)1000 + tv.tv_usec/1000;
}
int64_t TC_Common::now2us()
{
struct timeval tv;
gettimeofday(&tv, 0);
return tv.tv_sec * (int64_t)1000000 + tv.tv_usec;
}
//参照phorix的优化
static char c_b2s[256][4]={"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f","20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f","30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f","40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f","50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f","60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f","70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f","80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f","90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f","a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af","b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf","c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf","d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df","e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef","f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff"};
string TC_Common::bin2str(const void *buf, size_t len, const string &sSep, size_t lines)
{
if(buf == NULL || len <=0 )
{
return "";
}
string sOut;
const unsigned char *p = (const unsigned char *) buf;
for (size_t i = 0; i < len; ++i, ++p)
{
sOut += c_b2s[*p][0];
sOut += c_b2s[*p][1];
sOut += sSep;
//换行
if ((lines != 0) && ((i+1) % lines == 0))
{
sOut += "\n";
}
}
return sOut;
}
string TC_Common::bin2str(const string &sBinData, const string &sSep, size_t lines)
{
return bin2str((const void *)sBinData.data(), sBinData.length(), sSep, lines);
}
int TC_Common::str2bin(const char *psAsciiData, unsigned char *sBinData, int iBinSize)
{
int iAsciiLength = strlen(psAsciiData);
int iRealLength = (iAsciiLength/2 > iBinSize)?iBinSize:(iAsciiLength/2);
for (int i = 0 ; i < iRealLength ; i++)
{
sBinData[i] = x2c(psAsciiData + i*2);
}
return iRealLength;
}
string TC_Common::str2bin(const string &sString, const string &sSep, size_t lines)
{
const char *psAsciiData = sString.c_str();
int iAsciiLength = sString.length();
string sBinData;
for (int i = 0 ; i < iAsciiLength ; i++)
{
sBinData += x2c(psAsciiData + i);
i++;
i += sSep.length(); //过滤掉分隔符
if (lines != 0 && sBinData.length()%lines == 0)
{
i++; //过滤掉回车
}
}
return sBinData;
}
char TC_Common::x2c(const string &sWhat)
{
register char digit;
if(sWhat.length() < 2)
{
return '\0';
}
digit = (sWhat[0] >= 'A' ? ((sWhat[0] & 0xdf) - 'A')+10 : (sWhat[0] - '0'));
digit *= 16;
digit += (sWhat[1] >= 'A' ? ((sWhat[1] & 0xdf) - 'A')+10 : (sWhat[1] - '0'));
return(digit);
}
string TC_Common::replace(const string &sString, const string &sSrc, const string &sDest)
{
if(sSrc.empty())
{
return sString;
}
string sBuf = sString;
string::size_type pos = 0;
while( (pos = sBuf.find(sSrc, pos)) != string::npos)
{
sBuf.replace(pos, sSrc.length(), sDest);
pos += sDest.length();
}
return sBuf;
}
string TC_Common::replace(const string &sString, const map<string,string>& mSrcDest)
{
if(sString.empty())
{
return sString;
}
string tmp = sString;
map<string,string>::const_iterator it = mSrcDest.begin();
while(it != mSrcDest.end())
{
string::size_type pos = 0;
while((pos = tmp.find(it->first, pos)) != string::npos)
{
tmp.replace(pos, it->first.length(), it->second);
pos += it->second.length();
}
++it;
}
return tmp;
}
bool TC_Common::matchPeriod(const string& s, const string& pat)
{
if(s.empty())
{
return false;
}
if(pat.empty())
{
return true;
}
if(pat.find('*') == string::npos)
{
return s == pat;
}
string::size_type sIndex = 0;
string::size_type patIndex = 0;
do
{
if(pat[patIndex] == '*')
{
if(s[sIndex] == '.')
{
return false;
}
while(sIndex < s.size() && s[sIndex] != '.')
{
++sIndex;
}
patIndex++;
}
else
{
if(pat[patIndex] != s[sIndex])
{
return false;
}
++sIndex;
++patIndex;
}
}
while(sIndex < s.size() && patIndex < pat.size());
return sIndex == s.size() && patIndex == pat.size();
}
bool TC_Common::matchPeriod(const string& s, const vector<string>& pat)
{
for(size_t i = 0; i < pat.size(); i++)
{
if(TC_Common::matchPeriod(s,pat[i]))
{
return true;
}
}
return false;
}
void TC_Common::daemon()
{
pid_t pid;
if ((pid = fork()) != 0)
{
exit(0);
}
setsid();
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
signal(SIGTERM, SIG_IGN);
ignorePipe();
if((pid = fork()) != 0)
{
//父进程结束,变成daemon
exit(0);
}
umask(0);
// chdir("/");
}
void TC_Common::ignorePipe()
{
struct sigaction sig;
memset(&sig,0,sizeof(struct sigaction));
sig.sa_handler = SIG_IGN;
sig.sa_flags = 0;
sigemptyset(&sig.sa_mask);
sigaction(SIGPIPE,&sig,NULL);
}
bool TC_Common::isPrimeNumber(size_t n)
{
size_t nn = (size_t)sqrt((double)n);
for(size_t i = 2; i < nn;i++)
{
if(n % i == 0)
{
return false;
}
}
return true;
}
size_t TC_Common::toSize(const string &s, size_t iDefaultSize)
{
if (s.empty())
{
return iDefaultSize;
}
char c = s[s.length()-1];
if(c != 'K' && c != 'M' && c != 'G' && TC_Common::trim(s) == TC_Common::tostr(TC_Common::strto<size_t>(s)))
{
//没有后缀, 且转换是正确的
return (size_t)(TC_Common::strto<size_t>(s));
}
else if(c == 'K' || c == 'M' || c == 'G')
{
if (s.length() == 1)
{
return iDefaultSize;
}
float n = TC_Common::strto<float>(s.substr(0, s.length()-1));
if(TC_Common::trim(s.substr(0, s.length()-1)) != TC_Common::tostr(n))
{
return iDefaultSize;
}
if(c == 'K')
{
return (size_t)(n * 1024);
}
if(c == 'M')
{
return (size_t)(n * 1024*1024);
}
if(c == 'G')
{
return (size_t)(n * 1024 * 1024 * 1024);
}
}
return iDefaultSize;
}
// Generate the randome string, a SHA1-sized random number
void TC_Common::getRandomHexChars(char* p, unsigned int len)
{
const char* const chars = "0123456789abcdef";
FILE *fp = fopen("/dev/urandom","r");
if (!fp || fread(p,len,1,fp) == 0)
{
for (unsigned int j = 0; j < len; j++)
p[j] ^= rand();
}
if (fp) fclose(fp);
for (unsigned int j = 0; j < len; j++)
p[j] = chars[p[j] & 0x0F];
}
}

View File

@ -0,0 +1,310 @@
/**
* 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 <iconv.h>
#include <errno.h>
#include <string.h>
#include "util/tc_encoder.h"
namespace tars
{
void TC_Encoder::gbk2utf8(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen)
{
char * pIn = (char*)sIn;
char * pEnd = pIn+iInLen;
char * pOut = sOut;
size_t iLeftLen;
size_t iGbkLen;
iconv_t cd;
if (iInLen > iMaxOutLen)
{
throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iInLen > iMaxOutLen error : ", errno);
}
cd = iconv_open("UTF-8","GBK");
if (cd == (iconv_t)-1)
{
throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error : ", errno);
}
iLeftLen = iMaxOutLen;
while(pIn < pEnd)
{
if((unsigned char)(*pIn)==0x80)
{
//注意GBK的0x80转换为UTF-8时为E2 82 AC
*pOut = 0xe2; pOut++; iLeftLen--;
*pOut = 0x82; pOut++; iLeftLen--;
*pOut = 0xac; pOut++; iLeftLen--;
pIn++;
}
else if((unsigned char)(*pIn)<0x80)
{
//单字节(GBK: 0x00-0x7F)
*pOut = *pIn;
pIn++;pOut++;iLeftLen--;
}
else
{
//双字节
iGbkLen=2;
int iRet=iconv(cd, &pIn, (size_t *)&iGbkLen, (char **)&pOut, (size_t *)&iLeftLen);
if(iRet < 0)
{
*pOut = ' '; //转换不了替换为空格
pIn+=2; pOut++; iLeftLen--;
}
}
}
iconv_close(cd);
sOut[iMaxOutLen - iLeftLen] = '\0';
iMaxOutLen = iMaxOutLen - iLeftLen;
}
string TC_Encoder::gbk2utf8(const string &sIn)
{
iconv_t cd;
cd = iconv_open("UTF-8","GBK");
if (cd == (iconv_t)-1)
{
throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error", errno);
}
string sOut;
for(string::size_type pos = 0; pos < sIn.length(); ++pos)
{
if((unsigned char)sIn[pos] == 0x80)
{
//注意GBK的0x80转换为UTF-8时为E2 82 AC
sOut += 0xe2;
sOut += 0x82;
sOut += 0xac;
}
else if((unsigned char)sIn[pos] < 0x80)
{
//单字节(GBK: 0x00-0x7F)
sOut += sIn[pos];
}
else
{
//双字节
size_t sizeGbkLen = 2;
char pIn[128] = "\0";
strncpy(pIn, sIn.c_str() + pos, sizeGbkLen);
char *p = pIn;
size_t sizeLeftLen = 128;
char pOut[128] = "\0";
char *o = pOut;
int iRet = iconv(cd, &p, &sizeGbkLen, (char **)&o, &sizeLeftLen);
if(iRet < 0)
{
//转换不了, 暂时替换为空格
sOut += ' ';
}
else
{
sOut += pOut;
}
++pos;
}
}
iconv_close(cd);
return sOut;
}
void TC_Encoder::gbk2utf8(const string &sIn, vector<string> &vtStr)
{
iconv_t cd;
cd = iconv_open("UTF-8","GBK");
if (cd == (iconv_t)-1)
{
throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error", errno);
}
vtStr.clear();
for(string::size_type pos = 0; pos < sIn.length(); ++pos)
{
string sOut;
if((unsigned char)sIn[pos] == 0x80)
{
//注意GBK的0x80转换为UTF-8时为E2 82 AC
sOut += 0xe2;
sOut += 0x82;
sOut += 0xac;
}
else if((unsigned char)sIn[pos] < 0x80)
{
//单字节(GBK: 0x00-0x7F)
sOut += sIn[pos];
}
else
{
//双字节
size_t iGbkLen = 2;
char pIn[128] = "\0";
strncpy(pIn, sIn.c_str() + pos, iGbkLen);
char *p = pIn;
size_t iLeftLen = 128;
char pOut[128] = "\0";
char *o = pOut;
int iRet = iconv(cd, &p, (size_t *)&iGbkLen, (char **)&o, (size_t *)&iLeftLen);
if(iRet < 0)
{
//转换不了, 暂时替换为空格
sOut += ' ';
}
else
{
sOut += pOut;
}
++pos;
}
vtStr.push_back(sOut);
}
iconv_close(cd);
}
void TC_Encoder::utf82gbk(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen)
{
iconv_t cd;
cd = iconv_open("GBK","UTF-8");
if (cd == (iconv_t)-1)
{
throw TC_Encoder_Exception("[TC_Encoder::utf82gbk] iconv_open error", errno);
}
char * pIn = (char*)sIn;
size_t sizeLeftLen = iMaxOutLen;
size_t sizeInLen = iInLen;
char* pOut = sOut;
size_t ret = iconv(cd, &pIn, &sizeInLen, (char **)&sOut, &sizeLeftLen);
if (ret == (size_t) - 1)
{
iMaxOutLen = 0;
iconv_close(cd);
throw TC_Encoder_Exception("[TC_Encoder::utf82gbk] iconv error", errno);
return;
}
iconv_close(cd);
pOut[iMaxOutLen - (int)sizeLeftLen] = '\0';
iMaxOutLen = iMaxOutLen - (int)sizeLeftLen;
}
string TC_Encoder::utf82gbk(const string &sIn)
{
if(sIn.length() == 0)
{
return "";
}
string sOut;
int iLen = sIn.length() * 2 + 1;
char *pOut = new char[iLen];
try
{
utf82gbk(pOut, iLen, sIn.c_str(), sIn.length());
}
catch (TC_Encoder_Exception& e)
{
delete[] pOut;
throw e;
}
sOut.assign(pOut, iLen);
delete[] pOut;
return sOut;
}
/**
* \n -> \r\0
* \r -> \r\r
*/
string TC_Encoder::transTo(const string& str, char f /*='\n'*/, char t /*= '\r'*/, char u /*= '\0'*/)
{
string ret = str;
for (size_t i = 0; i < ret.length(); ++i)
{
if (ret[i] == f)
{
ret[i] = t;
ret.insert(++i, 1, u);
}
else if (ret[i] == t)
{
ret.insert(++i, 1, t);
}
}
return ret;
}
/**
* \r\0 -> \n
* \r\r -> \r
*/
string TC_Encoder::transFrom(const string& str, char f /*= '\n'*/, char t /*= '\r'*/, char u /*= '\0'*/)
{
string ret = "";
for (string::const_iterator it = str.begin()
; it != str.end()
; ++it)
{
ret.append(1, *it);
if (*it == t)
{
if (*(++it) == u)
{
*ret.rbegin() = f;
}
}
}
return ret;
}
}

View File

@ -0,0 +1,62 @@
/**
* 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 "util/tc_ex.h"
#include <execinfo.h>
#include <string.h>
#include <stdlib.h>
#include <cerrno>
namespace tars
{
TC_Exception::TC_Exception(const string &buffer)
:_buffer(buffer), _code(0)
{
// getBacktrace();
}
TC_Exception::TC_Exception(const string &buffer, int err)
{
_buffer = buffer + " :" + strerror(err);
_code = err;
// getBacktrace();
}
TC_Exception::~TC_Exception() throw()
{
}
const char* TC_Exception::what() const throw()
{
return _buffer.c_str();
}
void TC_Exception::getBacktrace()
{
void * array[64];
int nSize = backtrace(array, 64);
char ** symbols = backtrace_symbols(array, nSize);
for (int i = 0; i < nSize; i++)
{
_buffer += symbols[i];
_buffer += "\n";
}
free(symbols);
}
}

View File

@ -0,0 +1,514 @@
/**
* 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 "util/tc_file.h"
#include <string.h>
namespace tars
{
ifstream::pos_type TC_File::getFileSize(const string &sFullFileName)
{
ifstream ifs(sFullFileName.c_str());
ifs.seekg(0, ios_base::end);
return ifs.tellg();
}
bool TC_File::isAbsolute(const string &sFullFileName)
{
if(sFullFileName.empty())
{
return false;
}
unsigned i = 0;
while(isspace(sFullFileName[i]))
{
++i;
}
return sFullFileName[i] == '/';
}
bool TC_File::isFileExist(const string &sFullFileName, mode_t iFileType)
{
struct stat f_stat;
if (lstat(sFullFileName.c_str(), &f_stat) == -1)
{
return false;
}
if (!(f_stat.st_mode & iFileType))
{
return false;
}
return true;
}
bool TC_File::isFileExistEx(const string &sFullFileName, mode_t iFileType)
{
struct stat f_stat;
if (stat(sFullFileName.c_str(), &f_stat) == -1)
{
return false;
}
if (!(f_stat.st_mode & iFileType))
{
return false;
}
return true;
}
bool TC_File::makeDir(const string &sDirectoryPath, mode_t iFlag)
{
int iRetCode = mkdir(sDirectoryPath.c_str(), iFlag);
if(iRetCode < 0 && errno == EEXIST)
{
return isFileExistEx(sDirectoryPath, S_IFDIR);
}
return iRetCode == 0;
}
bool TC_File::makeDirRecursive(const string &sDirectoryPath, mode_t iFlag)
{
string simple = simplifyDirectory(sDirectoryPath);
string::size_type pos = 0;
for(; pos != string::npos; )
{
pos = simple.find("/", pos + 1);
string s;
if(pos == string::npos)
{
s = simple.substr(0, simple.size());
return makeDir(s.c_str(), iFlag);
}
else
{
s = simple.substr(0, pos);
if(!makeDir(s.c_str(), iFlag)) return false;
}
}
return true;
}
int TC_File::setExecutable(const string &sFullFileName, bool canExecutable)
{
struct stat f_stat;
if (stat(sFullFileName.c_str(), &f_stat) == -1)
{
return -1;
}
return chmod(sFullFileName.c_str(), canExecutable ? f_stat.st_mode | S_IXUSR : f_stat.st_mode & ~S_IXUSR);
}
bool TC_File::canExecutable(const string &sFullFileName)
{
struct stat f_stat;
if (stat(sFullFileName.c_str(), &f_stat) == -1)
{
return false;
}
return f_stat.st_mode & S_IXUSR;
}
int TC_File::removeFile(const string &sFullFileName, bool bRecursive)
{
string path = simplifyDirectory(sFullFileName);
if(isFileExist(path, S_IFDIR))
{
if(bRecursive)
{
vector<string> files;
listDirectory(path, files, false);
for(size_t i = 0; i < files.size(); i++)
{
removeFile(files[i], bRecursive);
}
if(path != "/")
{
if(::rmdir(path.c_str()) == -1)
{
return -1;
}
return 0;
}
}
else
{
if(::rmdir(path.c_str()) == -1)
{
return -1;
}
}
}
else
{
if(::remove(path.c_str()) == -1)
{
return -1;
}
}
return 0;
}
string TC_File::simplifyDirectory(const string& path)
{
string result = path;
string::size_type pos;
pos = 0;
while((pos = result.find("//", pos)) != string::npos)
{
result.erase(pos, 1);
}
pos = 0;
while((pos = result.find("/./", pos)) != string::npos)
{
result.erase(pos, 2);
}
while(result.substr(0, 4) == "/../")
{
result.erase(0, 3);
}
if(result == "/.")
{
return result.substr(0, result.size() - 1);
}
if(result.size() >= 2 && result.substr(result.size() - 2, 2) == "/.")
{
result.erase(result.size() - 2, 2);
}
if(result == "/")
{
return result;
}
if(result.size() >= 1 && result[result.size() - 1] == '/')
{
result.erase(result.size() - 1);
}
if(result == "/..")
{
result = "/";
}
return result;
}
string TC_File::load2str(const string &sFullFileName)
{
FILE* fp = fopen(sFullFileName.data(), "rb");
if (!fp)
return "";
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
string s(size, '\0');
fread((void*)s.data(), size, 1, fp);
fclose(fp);
return s;
}
void TC_File::load2str(const string &sFullFileName, vector<char> &buffer)
{
buffer.clear();
FILE* fp = fopen(sFullFileName.data(), "rb");
if (!fp)
return;
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
buffer.resize(size);
fread((void*)&buffer[0], size, 1, fp);
fclose(fp);
}
void TC_File::save2file(const string &sFullFileName, const string &sFileData)
{
ofstream ofs((sFullFileName).c_str());
ofs << sFileData;
ofs.close();
}
int TC_File::save2file(const string &sFullFileName, const char *sFileData, size_t length)
{
FILE *fp = fopen(sFullFileName.c_str(), "wb");
if(fp == NULL)
{
return -1;
}
size_t ret = fwrite((void*)sFileData, 1, length, fp);
fclose(fp);
if(ret == length)
{
return 0;
}
return -1;
}
string TC_File::getExePath()
{
string proc = "/proc/self/exe";
char buf[2048] = "\0";
int bufsize = sizeof(buf)/sizeof(char);
int count = readlink(proc.c_str(), buf,bufsize);
if ( count < 0 )
{
throw TC_File_Exception("[TC_File::getExePath] could not get exe path error", errno);
}
count = (count>=bufsize)?(bufsize-1):count;
buf[count] = '\0';
return buf;
}
string TC_File::extractFileName(const string &sFullFileName)
{
if(sFullFileName.length() <= 0)
{
return "";
}
string::size_type pos = sFullFileName.rfind('/');
if(pos == string::npos)
{
return sFullFileName;
}
return sFullFileName.substr(pos + 1);
}
string TC_File::extractFilePath(const string &sFullFileName)
{
if(sFullFileName.length() <= 0)
{
return "./";
}
string::size_type pos = 0;
for(pos = sFullFileName.length(); pos != 0 ; --pos)
{
if(sFullFileName[pos-1] == '/')
{
return sFullFileName.substr(0, pos);
}
}
return "./";
}
string TC_File::extractFileExt(const string &sFullFileName)
{
string::size_type pos;
if ((pos = sFullFileName.rfind('.')) == string::npos)
{
return string("");
}
return sFullFileName.substr(pos+1);
}
string TC_File::excludeFileExt(const string &sFullFileName)
{
string::size_type pos;
if ((pos = sFullFileName.rfind('.')) == string::npos)
{
return sFullFileName;
}
return sFullFileName.substr(0, pos);
}
string TC_File::replaceFileExt(const string &sFullFileName, const string &sExt)
{
return excludeFileExt(sFullFileName) + "." + sExt;
}
string TC_File::extractUrlFilePath(const string &sUrl)
{
string sLowerUrl = TC_Common::lower(sUrl);
string::size_type pos = sLowerUrl.find("http://");
if(pos == 0)
{
pos += strlen("http://");
}
else if(pos == string::npos)
{
pos = 0;
}
for( ; pos < sUrl.length(); ++pos)
{
if(sUrl[pos] == '/')
{
if(pos < sUrl.length() - 1)
{
pos++;
break;
}
else
{
return "";
}
}
}
if(pos == string::npos || pos == sUrl.length())
{
pos = 0;
}
return sUrl.substr(pos);
}
size_t TC_File::scanDir(const string &sFilePath, vector<string> &vtMatchFiles, FILE_SELECT f, int iMaxSize )
{
vtMatchFiles.clear();
struct dirent **namelist;
int n = scandir(sFilePath.c_str(), &namelist, f, alphasort);
if (n < 0)
{
return 0;
}
else
{
while(n-- )
{
if(iMaxSize > 0 && vtMatchFiles.size() >= (size_t)iMaxSize )
{
free(namelist[n]);
break;
}
else
{
vtMatchFiles.push_back(namelist[n]->d_name);
free(namelist[n]);
}
}
free(namelist);
}
return vtMatchFiles.size();
}
void TC_File::listDirectory(const string &path, vector<string> &files, bool bRecursive)
{
vector<string> tf;
scanDir(path, tf, 0, 0);
for(size_t i = 0; i < tf.size(); i++)
{
if(tf[i] == "." || tf[i] == "..")
continue;
string s = path + "/" + tf[i];
if(isFileExist(s, S_IFDIR))
{
files.push_back(simplifyDirectory(s));
if(bRecursive)
{
listDirectory(s, files, bRecursive);
}
}
else
{
files.push_back(simplifyDirectory(s));
}
}
}
void TC_File::copyFile(const string &sExistFile, const string &sNewFile,bool bRemove)
{
if(TC_File::isFileExist(sExistFile, S_IFDIR))
{
TC_File::makeDir(sNewFile);
vector<string> tf;
TC_File::scanDir(sExistFile,tf, 0, 0);
for(size_t i = 0; i <tf.size(); i++)
{
if(tf[i] == "." || tf[i] == "..")
continue;
string s = sExistFile + "/" + tf[i];
string d = sNewFile + "/" + tf[i];
copyFile(s, d,bRemove);
}
}
else
{
if(bRemove) std::remove(sNewFile.c_str());
std::ifstream fin(sExistFile.c_str());
if(!fin)
{
throw TC_File_Exception("[TC_File::copyFile] error: "+sExistFile, errno);
}
std::ofstream fout(sNewFile.c_str());
if(!fout )
{
throw TC_File_Exception("[TC_File::copyFile] error: "+sNewFile, errno);
}
struct stat f_stat;
if (stat(sExistFile.c_str(), &f_stat) == -1)
{
throw TC_File_Exception("[TC_File::copyFile] error: "+sExistFile, errno);
}
chmod(sNewFile.c_str(),f_stat.st_mode);
fout<<fin.rdbuf();
fin.close();
fout.close();
}
}
}

View File

@ -0,0 +1,85 @@
/**
* 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 "util/tc_option.h"
#include "util/tc_common.h"
namespace tars
{
void TC_Option::decode(int argc, char *argv[])
{
_mParam.clear();
vector<string> v;
for(int i = 1; i < argc; i++)
{
v.push_back(argv[i]);
}
for(size_t i = 0; i < v.size(); i++)
{
if(v[i].length() > 2 && v[i].substr(0,2) == "--")
{
parse(v[i]);
}
else
{
_vSingle.push_back(v[i]);
}
}
}
void TC_Option::parse(const string &s)
{
string::size_type pos = s.find('=');
if( pos != string::npos)
{
_mParam[s.substr(2, pos-2)] = s.substr(pos+1);
}
else
{
_mParam[s.substr(2, pos-2)] = "";
}
}
string TC_Option::getValue(const string &sName)
{
if(_mParam.find(sName) != _mParam.end())
{
return _mParam[sName];
}
return "";
}
bool TC_Option::hasParam(const string &sName)
{
return _mParam.find(sName) != _mParam.end();
}
vector<string>& TC_Option::getSingle()
{
return _vSingle;
}
map<string, string>& TC_Option::getMulti()
{
return _mParam;
}
}