mirror of
https://github.com/tars-node/tars2node.git
synced 2024-03-22 13:10:56 +08:00
version: 20180713
This commit is contained in:
parent
3c4c8533da
commit
deaeeb550b
52
CMakeLists.txt
Normal file
52
CMakeLists.txt
Normal 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
40
README.md
Normal 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
BIN
build/tars2node
Executable file
Binary file not shown.
273
include/code_generator.h
Normal file
273
include/code_generator.h
Normal 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
90
src/code_generator.cpp
Normal 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
38
src/file_util.cpp
Normal 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
398
src/gen_js.cpp
Normal 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
239
src/gen_js_dts.cpp
Normal 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
549
src/gen_proxy.cpp
Normal 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
208
src/gen_proxy_dts.cpp
Normal 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
381
src/gen_server.cpp
Normal 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
149
src/gen_server_dts.cpp
Normal 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
123
src/gen_server_imp.cpp
Normal 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
175
src/idl_scan.cpp
Normal 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
440
src/idl_util.cpp
Normal 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
198
src/main.cpp
Normal 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;
|
||||
}
|
2261
third_partly/tarsgrammar/tars.lex.cpp
Normal file
2261
third_partly/tarsgrammar/tars.lex.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3083
third_partly/tarsgrammar/tars.tab.cpp
Normal file
3083
third_partly/tarsgrammar/tars.tab.cpp
Normal file
File diff suppressed because it is too large
Load Diff
94
third_partly/tarsgrammar/tars.tab.hpp
Normal file
94
third_partly/tarsgrammar/tars.tab.hpp
Normal 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 */
|
339
third_partly/tarsparse/element.cpp
Normal file
339
third_partly/tarsparse/element.cpp
Normal 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");
|
||||
}
|
||||
|
||||
|
861
third_partly/tarsparse/element.h
Normal file
861
third_partly/tarsparse/element.h
Normal 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
|
||||
|
||||
|
603
third_partly/tarsparse/parse.cpp
Normal file
603
third_partly/tarsparse/parse.cpp
Normal 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();
|
||||
}
|
||||
|
||||
|
368
third_partly/tarsparse/parse.h
Normal file
368
third_partly/tarsparse/parse.h
Normal 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
|
||||
|
||||
|
199
third_partly/util/include/util/tc_atomic.h
Normal file
199
third_partly/util/include/util/tc_atomic.h
Normal 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
|
508
third_partly/util/include/util/tc_autoptr.h
Normal file
508
third_partly/util/include/util/tc_autoptr.h
Normal 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
|
785
third_partly/util/include/util/tc_common.h
Normal file
785
third_partly/util/include/util/tc_common.h
Normal 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
|
||||
|
143
third_partly/util/include/util/tc_encoder.h
Normal file
143
third_partly/util/include/util/tc_encoder.h
Normal 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之间的相互转码函数,通过静态函数提供.
|
||||
*
|
||||
* 1:GBK ==> UTF8的转换
|
||||
*
|
||||
* 2:UTF8 ==> 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
|
||||
|
||||
|
94
third_partly/util/include/util/tc_ex.h
Normal file
94
third_partly/util/include/util/tc_ex.h
Normal 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
|
||||
|
289
third_partly/util/include/util/tc_file.h
Normal file
289
third_partly/util/include/util/tc_file.h
Normal 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
|
111
third_partly/util/include/util/tc_option.h
Normal file
111
third_partly/util/include/util/tc_option.h
Normal 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 存在返回true,否则返回false
|
||||
*/
|
||||
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,
|
||||
* def,参数按照顺序在vector中
|
||||
* @return vector<string> 顺序存放参数的vector
|
||||
*/
|
||||
vector<string>& getSingle();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief 解析字符串,取出标识和其对应的参数值,
|
||||
* 对型如--name=value 的字符串进行解析,取出name和vaue
|
||||
* @param s 要解析的字符串
|
||||
*/
|
||||
void parse(const string &s);
|
||||
|
||||
protected:
|
||||
/**
|
||||
*存放标识和其对应参数的对应关系,例如:对于--name=value,存放name和value
|
||||
*/
|
||||
map<string, string> _mParam;
|
||||
|
||||
/**
|
||||
*存放普通参数的vetor
|
||||
*/
|
||||
vector<string> _vSingle;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
757
third_partly/util/src/tc_common.cpp
Normal file
757
third_partly/util/src/tc_common.cpp
Normal 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];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
310
third_partly/util/src/tc_encoder.cpp
Normal file
310
third_partly/util/src/tc_encoder.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
62
third_partly/util/src/tc_ex.cpp
Normal file
62
third_partly/util/src/tc_ex.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
514
third_partly/util/src/tc_file.cpp
Normal file
514
third_partly/util/src/tc_file.cpp
Normal 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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
85
third_partly/util/src/tc_option.cpp
Normal file
85
third_partly/util/src/tc_option.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user