diff --git a/.gitignore b/.gitignore deleted file mode 100644 index c6127b38c1aa25968a88db3940604d41529e4cf5..0000000000000000000000000000000000000000 --- a/.gitignore +++ /dev/null @@ -1,52 +0,0 @@ -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..8db18b5e6005cdb816950181391951ce0214fe2d --- /dev/null +++ b/README.en.md @@ -0,0 +1,151 @@ +[中文](README.md) || [English](README.en.md) +# XEngine_APIService +This repository has a development and master branch. If you want to use it, please use the master branch + +## Introduction +c c++ 接口服务器 +c c++ interface api service +This is an api interface for information query service,At present, the information search service on the market need to charge, and our information search service is free and open source. +This service mainly uses HTTP/V1.1 to implement various interface services +This is a general information query service that does not contain any language attributes +The purpose of development and implementation based on libXEngine is a cross-platform network storage service + +## Software feature +1. support json and string stream methods to return the content of the query +2. support ip address location information query(IPV4 and IPV6) +3. support ID verification and information query +4. support phone number information query +5. Weather forecast (planned) +6. Lunar calendar conversion (planning) +7. News headlines (planned) +8. Standard height and weight (planned) +9. Zodiac Constellation (planned) +10. Password generator (planned) +11. World Time Zones (planned) +12. Oil price inquiry (planned) +13. Administrative zip code (planned) +14. Bank card verification (planned) +15. Exchange rate calculation (planned) +16. QR code generation (planned) +17. Simplified and Traditional Conversion (planned) +18. Oil price inquiry (planned) +19. Twenty-four solar terms (planned) +20. Xinhua Dictionary (planned) + +## install + +#### Requirements +support system above windows 7sp1 and linux(ubuntu20.04,centos8) +XEngine need V7.30 or above + +#### Windows +use vs open and complie +You need to configure the environment in the following way, otherwise you may need to set the library directory in the project yourself + +##### XEngine +download xengine through git.read xengine project readme file to configure your env + +#### Linux +Linux use Makefile to complie +supproted ubuntu x64 or centos x64 + +##### complie +execute command in XEngine_Source path +make complie +make FLAGS=InstallAll install +make FLAGS=CleanAll clear + +#### use + +1. Switch to the MASTER branch +2. download code +3. complie +4. install +5. uncompress /XEngine_Release/XEngine_DBFile/ipdata.rar into current dir +6. run + +## directory struct +- XEngine_Docment docment directory +- XEngine_Release install directory +- XEngine_Source code directory +- XEngine_APPClient client code dir + +## now task + + +## other problems +You can refer to the document under the docment directory. It contains API protocol and service description. + +## Test Service +Address:app.xyry.org,Port:5501 +#### example +phone information query +api:http://app.xyry.org:5501/api?function=phonequery¶ms1=13699439999¶ms2=0 +```json +{ + "code":0, + "data":{ + "nAreaCode":28, + "nPhoneNumber":13699439999, + "nZipCode":610000, + "tszCity":"成都", + "tszProvincer":"四川" + }, + "msg":"success" +} +``` +ip address information +api;http://app.xyry.org:5501/api?function=ipquery¶ms1=1.29.164.255¶ms2=0 +```json +{ + "code":0, + "data":{ + "tszIPAddr":"1.29.164.255", + "tszIPAddress":"内蒙古通辽市霍林郭勒市", + "tszIPCity":"通辽市", + "tszIPCountry":"中国", + "tszIPCounty":"霍林郭勒市", + "tszIPEnd":"1.29.164.255", + "tszIPISP":"联通", + "tszIPProvince":"内蒙古", + "tszIPStart":"1.29.164.0", + "tszIPTime":"2021-11-03 07:33:50" + }, + "msg":"success" +} +``` +id information query +api;http://app.xyry.org:5501/api?function=idquery¶ms1=511025198800000000¶ms2=0 +```json +{ + "code":0, + "data":{ + "nBirthDay":00, + "nBirthMonth":00, + "nBirthYear":1988, + "nCheck":2, + "nPoliceID":87, + "nSex":1, + "tszCity":"内江市", + "tszCounty":"资中县", + "tszIDNumber":"511025198800000000", + "tszProvincer":"四川省" + }, + "msg":"success" +} +``` + +## Participate in contribution +I hope you will submit more code to participate in the contribution + +1. Fork this code +2. Create new Feat_xxx branch +3. Submit the code +4. New Pull Request + +## Follow us +If you think this software is helpful to you, please give us a START + +## post issues + +if you have eny quest.post issues... \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b301e213b9dacaec71e0ee4e4680ec22aee0619e --- /dev/null +++ b/README.md @@ -0,0 +1,150 @@ +[中文](README.md) || [English](README.en.md) +# XEngine_APIService +本仓库有开发和主分支,如果要使用,请使用master分支下的代码 + +## 介绍 +c c++ 接口服务器 +c c++ interface api service +这是一个信息查询的API接口服务,目前市面上的信息查询服务都需要收费,而我们这个信息查询服务属于免费开源的. +这个服务主要使用HTTP/V1.1实现各种接口服务. +这是一个不包含任何语言属性的通用信息查询服务. +基于libXEngine开发并实现的一套简洁高性能跨平台接口服务 + +## 软件特性 +1. 支持JSON和字符串流方式返回查询的内容 +2. 支持IP地址位置信息查询(IPV4和IPV6) +3. 支持身份证校验与信息查询 +4. 支持手机号信息归属查询 +5. 天气预报(计划中) +6. 农历公历转换(计划中) +7. 新闻头条(计划中) +8. 标准身高体重(计划中) +9. 生肖星座(计划中) +10. 密码生成器(计划中) +11. 世界时区(计划中) +12. 油价查询(计划中) +13. 行政邮编(计划中) +14. 银行卡验证(计划中) +15. 汇率计算(计划中) +16. 二维码生成(计划中) +17. 简繁转换(计划中) +18. 油价查询(计划中) +19. 二十四节气(计划中) +20. 新华词典(计划中) + +## 安装教程 + +#### 版本需求 +支持WINDOWS 7SP1和LINUX(UBUNT20.04,CENTOS8)以上系统 +XEngine版本需要V7.30或者以上版本 + +#### Windows +使用VS打开并且编译 +你需要按照下面的方式配置环境,不然你可能需要自己在项目中设置库目录 + +##### XEngine环境 +XEngine通过GIT下载,参考XEngine项目的readme配置环境 + +#### Linux +Linux使用Makefile编译 +UBUNTU20.04 x64或者CENTOS8 x64均可 + +##### 编译命令 +在XEngine_Source目录下执行命令 +make 编译 +make FLAGS=InstallAll 安装库程序 +make FLAGS=CleanAll 清理编译 + +#### 使用说明 + +1. 切换到MASTER分支 +2. 下载代码 +3. 编译 +4. 安装 +5. 解压/XEngine_Release/XEngine_DBFile/ipdata.rar 到当前目录 +6. 运行 + +## 目录结构 +- XEngine_Docment 文档目录结构 +- XEngine_Release 安装目录结构 +- XEngine_Source 源代目录结构 +- XEngine_APPClient 客户端演示代码 + +## 当前任务 + + +## 其他问题 +你可以参考docment目录下的文档.里面包含了API协议和服务说明. + +## 测试服务器 +地址:app.xyry.org,端口:5501 +#### 测试接口示例 +手机信息查询 +接口:http://app.xyry.org:5501/api?function=phonequery¶ms1=13699439999¶ms2=0 +```json +{ + "code":0, + "data":{ + "nAreaCode":28, + "nPhoneNumber":13699439999, + "nZipCode":610000, + "tszCity":"成都", + "tszProvincer":"四川" + }, + "msg":"success" +} +``` +IP地址查询 +接口;http://app.xyry.org:5501/api?function=ipquery¶ms1=1.29.164.255¶ms2=0 +```json +{ + "code":0, + "data":{ + "tszIPAddr":"1.29.164.255", + "tszIPAddress":"内蒙古通辽市霍林郭勒市", + "tszIPCity":"通辽市", + "tszIPCountry":"中国", + "tszIPCounty":"霍林郭勒市", + "tszIPEnd":"1.29.164.255", + "tszIPISP":"联通", + "tszIPProvince":"内蒙古", + "tszIPStart":"1.29.164.0", + "tszIPTime":"2021-11-03 07:33:50" + }, + "msg":"success" +} +``` +身份证查询 +接口;http://app.xyry.org:5501/api?function=idquery¶ms1=511025198800000000¶ms2=0 +```json +{ + "code":0, + "data":{ + "nBirthDay":00, + "nBirthMonth":00, + "nBirthYear":1988, + "nCheck":2, + "nPoliceID":87, + "nSex":1, + "tszCity":"内江市", + "tszCounty":"资中县", + "tszIDNumber":"511025198800000000", + "tszProvincer":"四川省" + }, + "msg":"success" +} +``` +## 参与贡献 +希望大家多多提交代码参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request + +## 关注我们 +如果你觉得这个软件对你有帮助,请你给我们一个START吧 + +## 提交问题 + +如果你有问题或者发现程序有BUG和意见,可以在issues中提交 \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.cpp b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df82eeee9982b43c3eebb3fad864f346dc925446 --- /dev/null +++ b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.cpp @@ -0,0 +1,46 @@ +#ifdef _MSC_BUILD +#include +#include +#pragma comment(lib,"Ws2_32") +#pragma comment(lib,"XEngine_BaseLib/XEngine_BaseLib") +#pragma comment(lib,"XEngine_NetHelp/NetHelp_APIHelp") +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//需要优先配置XEngine +//WINDOWS支持VS2022 x64 debug 编译调试 +//linux使用下面的命令编译 +//g++ -std=c++17 -Wall -g APPClient_IDExample.cpp -o APPClient_IDExample.exe -L /usr/local/lib/XEngine_Release/XEngine_BaseLib -L /usr/local/lib/XEngine_Release/XEngine_NetHelp -lXEngine_BaseLib -lNetHelp_APIHelp + +int main() +{ +#ifdef _MSC_BUILD + WSADATA st_WSAData; + WSAStartup(MAKEWORD(2, 2), &st_WSAData); +#endif + int nLen = 0; + TCHAR* ptszMsgBuffer = NULL; + LPCTSTR lpszUrl = _T("http://127.0.0.1:5501/api?function=idquery¶ms1=511025191101018792¶ms2=0"); + + if (!APIHelp_HttpRequest_Get(lpszUrl, &ptszMsgBuffer, &nLen)) + { + printf("发送投递失败!\n"); + return 0; + } + printf("接受到数据,大小:%d,内容:%s\n", nLen, ptszMsgBuffer); + BaseLib_OperatorMemory_FreeCStyle((XPPMEM)&ptszMsgBuffer); + +#ifdef _MSC_BUILD + WSACleanup(); +#endif + return 0; +} \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..e5890726903200a889c94aca68480b41d7504a26 --- /dev/null +++ b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {355b24d9-9049-4086-a35a-596eedba0a9c} + APPClientIDExample + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj.filters b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..fb6393893669d2263c8b178a67630b03243b8444 --- /dev/null +++ b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj.user b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_APPClient/APPClient_IDExample/APPClient_IDExample.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.cpp b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a09148c0c7a982f2475d01dd78ee92a4b3f2779 --- /dev/null +++ b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.cpp @@ -0,0 +1,46 @@ +#ifdef _MSC_BUILD +#include +#include +#pragma comment(lib,"Ws2_32") +#pragma comment(lib,"XEngine_BaseLib/XEngine_BaseLib") +#pragma comment(lib,"XEngine_NetHelp/NetHelp_APIHelp") +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//需要优先配置XEngine +//WINDOWS支持VS2022 x64 debug 编译调试 +//linux使用下面的命令编译 +//g++ -std=c++17 -Wall -g APPClient_IPExample.cpp -o APPClient_IPExample.exe -L /usr/local/lib/XEngine_Release/XEngine_BaseLib -L /usr/local/lib/XEngine_Release/XEngine_NetHelp -lXEngine_BaseLib -lNetHelp_APIHelp + +int main() +{ +#ifdef _MSC_BUILD + WSADATA st_WSAData; + WSAStartup(MAKEWORD(2, 2), &st_WSAData); +#endif + int nLen = 0; + TCHAR* ptszMsgBuffer = NULL; + LPCTSTR lpszUrl = _T("http://127.0.0.1:5501/api?function=ipquery¶ms1=1.29.164.255¶ms2=0"); + + if (!APIHelp_HttpRequest_Get(lpszUrl, &ptszMsgBuffer, &nLen)) + { + printf("发送投递失败!\n"); + return 0; + } + printf("接受到数据,大小:%d,内容:%s\n", nLen, ptszMsgBuffer); + BaseLib_OperatorMemory_FreeCStyle((XPPMEM)&ptszMsgBuffer); + +#ifdef _MSC_BUILD + WSACleanup(); +#endif + return 0; +} \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..a1ab432f3db647204012b5629afcaf81d5e59c15 --- /dev/null +++ b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {2b0e660c-be55-40c0-baa2-729abe4eda4e} + APPClientIPExample + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj.filters b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..8599f987e2daa3ff25b985f690aff86bde091b41 --- /dev/null +++ b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj.user b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_APPClient/APPClient_IPExample/APPClient_IPExample.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.cpp b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1b1631a34801303f8877d2d1320da41287fd773 --- /dev/null +++ b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.cpp @@ -0,0 +1,46 @@ +#ifdef _MSC_BUILD +#include +#include +#pragma comment(lib,"Ws2_32") +#pragma comment(lib,"XEngine_BaseLib/XEngine_BaseLib") +#pragma comment(lib,"XEngine_NetHelp/NetHelp_APIHelp") +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//需要优先配置XEngine +//WINDOWS支持VS2022 x64 debug 编译调试 +//linux使用下面的命令编译 +//g++ -std=c++17 -Wall -g APPClient_PhoneExample.cpp -o APPClient_PhoneExample.exe -L /usr/local/lib/XEngine_Release/XEngine_BaseLib -L /usr/local/lib/XEngine_Release/XEngine_NetHelp -lXEngine_BaseLib -lNetHelp_APIHelp + +int main() +{ +#ifdef _MSC_BUILD + WSADATA st_WSAData; + WSAStartup(MAKEWORD(2, 2), &st_WSAData); +#endif + int nLen = 0; + TCHAR* ptszMsgBuffer = NULL; + LPCTSTR lpszUrl = _T("http://127.0.0.1:5501/api?function=phonequery¶ms1=13699438888¶ms2=0"); + + if (!APIHelp_HttpRequest_Get(lpszUrl, &ptszMsgBuffer, &nLen)) + { + printf("发送投递失败!\n"); + return 0; + } + printf("接受到数据,大小:%d,内容:%s\n", nLen, ptszMsgBuffer); + BaseLib_OperatorMemory_FreeCStyle((XPPMEM)&ptszMsgBuffer); + +#ifdef _MSC_BUILD + WSACleanup(); +#endif + return 0; +} \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..90d451823c51935941f042b7a62a05fac0fd5424 --- /dev/null +++ b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {2ea578aa-4f40-48e1-87bc-9a04295c9a34} + APPClientPhoneExample + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj.filters b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..fabd8647d23ae5f25bbbe90d36f1d29a1e965cbe --- /dev/null +++ b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj.user b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_APPClient/APPClient_PhoneExample/APPClient_PhoneExample.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_APPClient/XEngine_APPClient.sln b/XEngine_APPClient/XEngine_APPClient.sln new file mode 100644 index 0000000000000000000000000000000000000000..061878276dc261640ff07b8e1d7b63255b9debc0 --- /dev/null +++ b/XEngine_APPClient/XEngine_APPClient.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APPClient_IPExample", "APPClient_IPExample\APPClient_IPExample.vcxproj", "{2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APPClient_IDExample", "APPClient_IDExample\APPClient_IDExample.vcxproj", "{355B24D9-9049-4086-A35A-596EEDBA0A9C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APPClient_PhoneExample", "APPClient_PhoneExample\APPClient_PhoneExample.vcxproj", "{2EA578AA-4F40-48E1-87BC-9A04295C9A34}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Debug|x64.ActiveCfg = Debug|x64 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Debug|x64.Build.0 = Debug|x64 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Debug|x86.ActiveCfg = Debug|Win32 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Debug|x86.Build.0 = Debug|Win32 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Release|x64.ActiveCfg = Release|x64 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Release|x64.Build.0 = Release|x64 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Release|x86.ActiveCfg = Release|Win32 + {2B0E660C-BE55-40C0-BAA2-729ABE4EDA4E}.Release|x86.Build.0 = Release|Win32 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Debug|x64.ActiveCfg = Debug|x64 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Debug|x64.Build.0 = Debug|x64 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Debug|x86.ActiveCfg = Debug|Win32 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Debug|x86.Build.0 = Debug|Win32 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Release|x64.ActiveCfg = Release|x64 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Release|x64.Build.0 = Release|x64 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Release|x86.ActiveCfg = Release|Win32 + {355B24D9-9049-4086-A35A-596EEDBA0A9C}.Release|x86.Build.0 = Release|Win32 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Debug|x64.ActiveCfg = Debug|x64 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Debug|x64.Build.0 = Debug|x64 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Debug|x86.ActiveCfg = Debug|Win32 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Debug|x86.Build.0 = Debug|Win32 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Release|x64.ActiveCfg = Release|x64 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Release|x64.Build.0 = Release|x64 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Release|x86.ActiveCfg = Release|Win32 + {2EA578AA-4F40-48E1-87BC-9A04295C9A34}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CC8142BD-8426-4A48-94DD-7560D3BA8C15} + EndGlobalSection +EndGlobal diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx new file mode 100644 index 0000000000000000000000000000000000000000..e1d5f98e85276bed3d7ed29b506509dd91072e39 Binary files /dev/null and b/XEngine_Docment/Docment_en.docx differ diff --git a/XEngine_Docment/Docment_zh.docx b/XEngine_Docment/Docment_zh.docx new file mode 100644 index 0000000000000000000000000000000000000000..e1501ede52ec3d1e10e5b8dfb190cb65ed3915af Binary files /dev/null and b/XEngine_Docment/Docment_zh.docx differ diff --git a/XEngine_Release/XEngine_Config/HttpCode.types b/XEngine_Release/XEngine_Config/HttpCode.types new file mode 100644 index 0000000000000000000000000000000000000000..09c6a20ec617edcd3f3ac8f737c0b4e7ad96c11c --- /dev/null +++ b/XEngine_Release/XEngine_Config/HttpCode.types @@ -0,0 +1,61 @@ +//CodeMessage +100:HTTP/1.1 100 Continue +101:HTTP/1.1 101 Switching Protocols +102:HTTP/1.1 102 Processing +//CodeSuccess +200:HTTP/1.1 200 OK +201:HTTP/1.1 201 Created +202:HTTP/1.1 202 Accepted +203:HTTP/1.1 203 Non-Authoritative Information +204:HTTP/1.1 204 No Content +205:HTTP/1.1 205 Reset Content +206:HTTP/1.1 206 Partial Content +//CodeRedirect +300:HTTP/1.1 300 Multiple Choices +301:HTTP/1.1 301 Moved Permanently +302:HTTP/1.1 302 Move temporarily +303:HTTP/1.1 303 See Other +304:HTTP/1.1 304 Not Modified +305:HTTP/1.1 305 Use Proxy +306:HTTP/1.1 306 Switch Proxy +//CodeRequestFail +400:HTTP/1.1 400 Bad Request +401:HTTP/1.1 401 Payment Required +402:HTTP/1.1 402 Unauthorized +403:HTTP/1.1 403 Forbidden +404:HTTP/1.1 404 Not Found +405:HTTP/1.1 405 Method Not Allowed +406:HTTP/1.1 406 Not Acceptable +407:HTTP/1.1 407 Proxy Authentication Required +408:HTTP/1.1 408 Request Timeout +409:HTTP/1.1 409 Conflict +410:HTTP/1.1 410 Gone +411:HTTP/1.1 411 Length Required +412:HTTP/1.1 412 Precondition Failed +413:HTTP/1.1 413 Request Entity Too Large +414:HTTP/1.1 414 Request-URI Too Long +415:HTTP/1.1 415 Unsupported Media Type +416:HTTP/1.1 416 Requested Range Not Satisfiable +417:HTTP/1.1 417 Expectation Failed +421:HTTP/1.1 421 too many connections +422:HTTP/1.1 422 Unprocessable Entity +423:HTTP/1.1 423 Locked +424:HTTP/1.1 424 Failed Dependency +425:HTTP/1.1 425 Unordered Collection +426:HTTP/1.1 426 Upgrade Required +449:HTTP/1.1 449 Retry With +451:HTTP/1.1 451 Unavailable For Legal Reasons +//CodeServerFail +500:HTTP/1.1 500 Internal Server Error +501:HTTP/1.1 501 Not Implemented +502:HTTP/1.1 502 Bad Gateway +503:HTTP/1.1 503 Service Unavailable +504:HTTP/1.1 504 Gateway Timeout +505:HTTP/1.1 505 HTTP Version Not Supported +506:HTTP/1.1 506 Variant Also Negotiates +507:HTTP/1.1 507 Insufficient Storage +508:HTTP/1.1 509 Bandwidth Limit Exceeded +600:HTTP/1.1 600 Unparseable Response Headers +//CodeUser +1001:HTTP/1.1 1001 XEngine Auth Ok +1002:HTTP/1.1 1002 XEngine Auth Failed \ No newline at end of file diff --git a/XEngine_Release/XEngine_Config/HttpMime.types b/XEngine_Release/XEngine_Config/HttpMime.types new file mode 100644 index 0000000000000000000000000000000000000000..aef066d89918e1c9f496848be7cbd737dc27bae3 --- /dev/null +++ b/XEngine_Release/XEngine_Config/HttpMime.types @@ -0,0 +1,86 @@ +text/html html htm shtml +text/css css +text/xml xml +image/gif gif +image/jpeg jpeg jpg +application/javascript js +application/atom+xml atom +application/rss+xml rss + +text/mathml mml +text/plain txt +text/vnd.sun.j2me.app-descriptor jad +text/vnd.wap.wml wml +text/x-component htc + +image/png png +image/tiff tif tiff +image/vnd.wap.wbmp wbmp +image/x-icon ico +image/x-jng jng +image/x-ms-bmp bmp +image/svg+xml svg svgz +image/webp webp + +application/font-woff woff +application/java-archive jar war ear +application/json json +application/mac-binhex40 hqx +application/msword doc +application/pdf pdf +application/postscript ps eps ai +application/rtf rtf +application/vnd.apple.mpegurl m3u8 +application/vnd.ms-excel xls +application/vnd.ms-fontobject eot +application/vnd.ms-powerpoint ppt +application/vnd.wap.wmlc wmlc +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/x-7z-compressed 7z +application/x-cocoa cco +application/x-java-archive-diff jardiff +application/x-java-jnlp-file jnlp +application/x-makeself run +application/x-perl pl pm +application/x-pilot prc pdb +application/x-rar-compressed rar +application/x-redhat-package-manager rpm +application/x-sea sea +application/x-shockwave-flash swf +application/x-stuffit sit +application/x-tcl tcl tk +application/x-x509-ca-cert der pem crt +application/x-xpinstall xpi +application/xhtml+xml xhtml +application/xspf+xml xspf +application/zip zip + +application/octet-stream bin exe dll +application/octet-stream deb +application/octet-stream dmg +application/octet-stream iso img +application/octet-stream msi msp msm + +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx + +audio/midi mid midi kar +audio/mpeg mp3 +audio/ogg ogg +audio/x-m4a m4a +audio/x-realaudio ra + +video/3gpp 3gpp 3gp +video/mp2t ts +video/mp4 mp4 +video/mpeg mpeg mpg +video/quicktime mov +video/webm webm +video/x-flv flv +video/x-m4v m4v +video/x-mng mng +video/x-ms-asf asx asf +video/x-ms-wmv wmv +video/x-msvideo avi diff --git a/XEngine_Release/XEngine_Config/XEngine_Config.json b/XEngine_Release/XEngine_Config/XEngine_Config.json new file mode 100644 index 0000000000000000000000000000000000000000..90dd94d4cdf9fd76c134efa8c2397747ee6de72a --- /dev/null +++ b/XEngine_Release/XEngine_Config/XEngine_Config.json @@ -0,0 +1,28 @@ +{ + "tszIPAddr":"192.168.1.8", + "bDeamon":0, + "nHttpPort":5501, + "XMax":{ + "nMaxClient":10000, + "nMaxQueue":10000, + "nIOThread":2, + "nHttpThread":2 + }, + "XTime":{ + "nTimeCheck":3, + "nHttpTimeOut":5 + }, + "XLog":{ + "MaxSize":1024000, + "MaxCount":10, + "LogLeave":32 + }, + "XDatabase":{ + "tszIPData":"./XEngine_DBFile/ipdata.db", + "tszIDData":"./XEngine_DBFile/regionsid.db", + "tszPhoneData":"./XEngine_DBFile/phone.dat" + }, + "XVer":[ + "1.0.0.1001 Build20220311" + ] +} \ No newline at end of file diff --git a/XEngine_Release/XEngine_DBFile/ipdata.rar b/XEngine_Release/XEngine_DBFile/ipdata.rar new file mode 100644 index 0000000000000000000000000000000000000000..615c239965bdbd0f76241824fb1499db2974a951 Binary files /dev/null and b/XEngine_Release/XEngine_DBFile/ipdata.rar differ diff --git a/XEngine_Release/XEngine_DBFile/phone.dat b/XEngine_Release/XEngine_DBFile/phone.dat new file mode 100644 index 0000000000000000000000000000000000000000..34bcab7fba2282eddbf95b59d88b39a41ffbb401 Binary files /dev/null and b/XEngine_Release/XEngine_DBFile/phone.dat differ diff --git a/XEngine_Release/XEngine_DBFile/regionsid.db b/XEngine_Release/XEngine_DBFile/regionsid.db new file mode 100644 index 0000000000000000000000000000000000000000..935968d66006d02e684de9ce6744c05b43cdbffc Binary files /dev/null and b/XEngine_Release/XEngine_DBFile/regionsid.db differ diff --git a/XEngine_Release/XEngine_Log/.gitignore b/XEngine_Release/XEngine_Log/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/XEngine_Source/Makefile b/XEngine_Source/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6b6255b0f3e7cce4cfe6487adc574bf4081f65ff --- /dev/null +++ b/XEngine_Source/Makefile @@ -0,0 +1,44 @@ +RELEASE = 0 +UNICODE = 0 +#编译的选项参数 +FLAGS = RELEASE=$(RELEASE) + +#要编译的模块 +THIRDPART_MODULE_JSONCPP = ./XEngine_ThirdPart/jsoncpp + +MODULE_CONFIGURE_PATH = ./XEngine_ModuleConfigure +MODULE_DATABASE_PATH = ./XEngine_ModuleDatabase +MODULE_PROTOCOL_PATH = ./XEngine_ModuleProtocol +MODULE_HELP_PATH = ./XEngine_ModuleHelp +APP_CENTER_PATH = ./XEngine_ServiceApp/XEngine_CenterApp +APP_HTTP_PATH = ./XEngine_ServiceApp/XEngine_HttpApp + +XENGINE_MODULES = libjsoncpp.so \ + libXEngine_ModuleConfigure.so libXEngine_ModuleDatabase.so libXEngine_ModuleProtocol.so libXEngine_ModuleHelp.so \ + XEngine_HttpApp.exe + +.PHONY:MakeAll +MakeAll:$(XENGINE_MODULES) + +libjsoncpp.so: + make -C $(THIRDPART_MODULE_JSONCPP) $(FLAGS) + +libXEngine_ModuleConfigure.so: + make -C $(MODULE_CONFIGURE_PATH) $(FLAGS) +libXEngine_ModuleDatabase.so: + make -C $(MODULE_DATABASE_PATH) $(FLAGS) +libXEngine_ModuleProtocol.so: + make -C $(MODULE_PROTOCOL_PATH) $(FLAGS) +libXEngine_ModuleHelp.so: + make -C $(MODULE_HELP_PATH) $(FLAGS) + +XEngine_HttpApp.exe: + make -C $(APP_HTTP_PATH) $(FLAGS) + +SetFlags_Install: + export FLAGS=InstallAll +InstallAll:SetFlags_Install $(NETENGINE_LIB) + +SetFlags_Clean: + export FLAGS=CleanAll +CleanAll:SetFlags_Clean $(NETENGINE_LIB) diff --git a/XEngine_Source/VSClean.bat b/XEngine_Source/VSClean.bat new file mode 100644 index 0000000000000000000000000000000000000000..bf8eca312f152fb046525e2cb0588095fec84b08 --- /dev/null +++ b/XEngine_Source/VSClean.bat @@ -0,0 +1,10 @@ +@echo Off +del /s /a *.ncb *.so *.o *.db +FOR /R . %%d IN (.) DO rd /s /q "%%d\Debug" 2>nul +FOR /R . %%d IN (.) DO rd /s /q "%%d\Release" 2>nul +FOR /R . %%d IN (.) DO rd /s /q "%%d\x64" 2>nul +FOR /R . %%d IN (.) DO rd /s /q "%%d\Debug" 2>nul +FOR /R . %%d IN (.) DO rd /s /q "%%d\ipch" 2>nul + +rem If the Properties directory is empty, remove it +FOR /R . %%d in (.) do rd /q "%%d\Properties" 2> nul diff --git a/XEngine_Source/VSCopy-Debug.bat b/XEngine_Source/VSCopy-Debug.bat new file mode 100644 index 0000000000000000000000000000000000000000..7b4e91977e048f252bb0a68bf7094a5f3a853ba5 --- /dev/null +++ b/XEngine_Source/VSCopy-Debug.bat @@ -0,0 +1,11 @@ +copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_BaseLib.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_Algorithm.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_Core.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_ManagePool.dll" "./" + +copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_SystemApi.dll" "./" + +copy /y "D:\XEngine\XEngine_SourceCode\Debug\HelpComponents_DataBase.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\HelpComponents_Packets.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\HelpComponents_XLog.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\RfcComponents_HttpServer.dll" "./" \ No newline at end of file diff --git a/XEngine_Source/VSCopy-x64.bat b/XEngine_Source/VSCopy-x64.bat new file mode 100644 index 0000000000000000000000000000000000000000..49e5eb83bc8dae0a2b4507f22984f9e2f2623274 --- /dev/null +++ b/XEngine_Source/VSCopy-x64.bat @@ -0,0 +1,20 @@ +copy /y "%XEngine_Lib64%\XEngine_BaseLib\XEngine_BaseLib.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_BaseLib\XEngine_Algorithm.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_Core\XEngine_Core.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_Core\XEngine_ManagePool.dll" "./" + +copy /y "%XEngine_Lib64%\XEngine_SystemSdk\XEngine_SystemApi.dll" "./" + +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\HelpComponents_DataBase.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\HelpComponents_Packets.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\HelpComponents_XLog.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_RfcComponents\RfcComponents_HttpServer.dll" "./" + +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\bson-1.0.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\mongoc-1.0.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\libmariadb.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\libpq.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\sqlite3.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_HelpComponents\zlib1.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_LibEx\libcrypto-1_1.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_LibEx\libssl-1_1.dll" "./" \ No newline at end of file diff --git a/XEngine_Source/VSCopy-x86.bat b/XEngine_Source/VSCopy-x86.bat new file mode 100644 index 0000000000000000000000000000000000000000..c319a8b9ad973b61d15235d1122e24165c94af07 --- /dev/null +++ b/XEngine_Source/VSCopy-x86.bat @@ -0,0 +1,20 @@ +copy /y "%XEngine_Lib32%\XEngine_BaseLib\XEngine_BaseLib.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_BaseLib\XEngine_Algorithm.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_Core\XEngine_Core.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_Core\XEngine_ManagePool.dll" "./" + +copy /y "%XEngine_Lib32%\XEngine_SystemSdk\XEngine_SystemApi.dll" "./" + +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\HelpComponents_DataBase.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\HelpComponents_Packets.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\HelpComponents_XLog.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_RfcComponents\RfcComponents_HttpServer.dll" "./" + +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\bson-1.0.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\mongoc-1.0.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\libmariadb.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\libpq.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\sqlite3.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_HelpComponents\zlib1.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_LibEx\libcrypto-1_1.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_LibEx\libssl-1_1.dll" "./" \ No newline at end of file diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln new file mode 100644 index 0000000000000000000000000000000000000000..25b7e45dc5e347a556a9edcf2c2c62eb5ff433b4 --- /dev/null +++ b/XEngine_Source/XEngine.sln @@ -0,0 +1,94 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_ModuleConfigure", "XEngine_ModuleConfigure\XEngine_ModuleConfigure.vcxproj", "{F54F152C-594F-4465-A44E-2DB915B39760}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XEngine_UserHdr", "XEngine_UserHdr", "{9E4F2158-9AC1-4C19-A3F7-375A9DBCF856}" + ProjectSection(SolutionItems) = preProject + XEngine_UserProtocol.h = XEngine_UserProtocol.h + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XEngine_ServiceApp", "XEngine_ServiceApp", "{79A9A569-7DA8-4D9D-AD34-D11115199EA1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_HttpApp", "XEngine_ServiceApp\XEngine_HttpApp\XEngine_HttpApp.vcxproj", "{E756B7D2-D40D-4106-9C14-1D90F20A712E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XEngine_ThirdPart", "XEngine_ThirdPart", "{1F64BA84-8754-4FD3-87F8-9102F124EBC1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsoncpp", "XEngine_ThirdPart\jsoncpp\jsoncpp.vcxproj", "{F1736B3F-03A2-4FC7-B045-A12BA8D724FB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_ModuleDatabase", "XEngine_ModuleDatabase\XEngine_ModuleDatabase.vcxproj", "{140AD4A9-4918-4345-B352-507C345AEBE0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_ModuleProtocol", "XEngine_ModuleProtocol\XEngine_ModuleProtocol.vcxproj", "{6C935BE1-77E3-4719-A7A6-C76ABAFEE010}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_ModuleHelp", "XEngine_ModuleHelp\XEngine_ModuleHelp.vcxproj", "{6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F54F152C-594F-4465-A44E-2DB915B39760}.Debug|x64.ActiveCfg = Debug|x64 + {F54F152C-594F-4465-A44E-2DB915B39760}.Debug|x64.Build.0 = Debug|x64 + {F54F152C-594F-4465-A44E-2DB915B39760}.Debug|x86.ActiveCfg = Debug|Win32 + {F54F152C-594F-4465-A44E-2DB915B39760}.Debug|x86.Build.0 = Debug|Win32 + {F54F152C-594F-4465-A44E-2DB915B39760}.Release|x64.ActiveCfg = Release|x64 + {F54F152C-594F-4465-A44E-2DB915B39760}.Release|x64.Build.0 = Release|x64 + {F54F152C-594F-4465-A44E-2DB915B39760}.Release|x86.ActiveCfg = Release|Win32 + {F54F152C-594F-4465-A44E-2DB915B39760}.Release|x86.Build.0 = Release|Win32 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Debug|x64.ActiveCfg = Debug|x64 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Debug|x64.Build.0 = Debug|x64 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Debug|x86.ActiveCfg = Debug|Win32 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Debug|x86.Build.0 = Debug|Win32 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Release|x64.ActiveCfg = Release|x64 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Release|x64.Build.0 = Release|x64 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Release|x86.ActiveCfg = Release|Win32 + {E756B7D2-D40D-4106-9C14-1D90F20A712E}.Release|x86.Build.0 = Release|Win32 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Debug|x64.ActiveCfg = Debug|x64 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Debug|x64.Build.0 = Debug|x64 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Debug|x86.ActiveCfg = Debug|Win32 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Debug|x86.Build.0 = Debug|Win32 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Release|x64.ActiveCfg = Release|x64 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Release|x64.Build.0 = Release|x64 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Release|x86.ActiveCfg = Release|Win32 + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}.Release|x86.Build.0 = Release|Win32 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Debug|x64.ActiveCfg = Debug|x64 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Debug|x64.Build.0 = Debug|x64 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Debug|x86.ActiveCfg = Debug|Win32 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Debug|x86.Build.0 = Debug|Win32 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Release|x64.ActiveCfg = Release|x64 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Release|x64.Build.0 = Release|x64 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Release|x86.ActiveCfg = Release|Win32 + {140AD4A9-4918-4345-B352-507C345AEBE0}.Release|x86.Build.0 = Release|Win32 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Debug|x64.ActiveCfg = Debug|x64 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Debug|x64.Build.0 = Debug|x64 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Debug|x86.ActiveCfg = Debug|Win32 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Debug|x86.Build.0 = Debug|Win32 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Release|x64.ActiveCfg = Release|x64 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Release|x64.Build.0 = Release|x64 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Release|x86.ActiveCfg = Release|Win32 + {6C935BE1-77E3-4719-A7A6-C76ABAFEE010}.Release|x86.Build.0 = Release|Win32 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Debug|x64.ActiveCfg = Debug|x64 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Debug|x64.Build.0 = Debug|x64 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Debug|x86.ActiveCfg = Debug|Win32 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Debug|x86.Build.0 = Debug|Win32 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Release|x64.ActiveCfg = Release|x64 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Release|x64.Build.0 = Release|x64 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Release|x86.ActiveCfg = Release|Win32 + {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {E756B7D2-D40D-4106-9C14-1D90F20A712E} = {79A9A569-7DA8-4D9D-AD34-D11115199EA1} + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {1F64BA84-8754-4FD3-87F8-9102F124EBC1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9B202F91-A601-429E-BB0F-880DDEE096FE} + EndGlobalSection +EndGlobal diff --git a/XEngine_Source/XEngine_ModuleConfigure/Makefile b/XEngine_Source/XEngine_ModuleConfigure/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..7bca8c178490640166f26598b9cf35db8cb561e2 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/Makefile @@ -0,0 +1,45 @@ +CC = g++ -Wall -std=c++17 -fPIC +RELEASE = 0 +UNICODE = 0 +INCLUDE = -I ./ -I ../XEngine_ThirdPart/jsoncpp +LOADBIN = -L ../XEngine_ThirdPart/jsoncpp +LIB = -ljsoncpp +LIBEX = -static-libgcc -lrt -ldl -lpthread +LOADSO = -Wl,-rpath=./,--disable-new-dtags +LIBINCLUDE = ModuleConfigure_Json.o pch.o + +ifeq ($(RELEASE),1) +FLAGS = -c -O2 +DEBUG = +else +FLAGS = -c -lc_p +DEBUG = -g -pg +endif + +ifeq ($(UNICODE),1) +UNICODE = -D _UNICODE +else +UNICODE = +endif + + +all:$(LIBINCLUDE) + $(CC) $(DEBUG) $(LIBINCLUDE) -o libXEngine_ModuleConfigure.so -shared -fPIC $(LOADBIN) $(LIB) $(LIBEX) $(LOADSO) + +ModuleConfigure_Json.o:./ModuleConfigure_Json/ModuleConfigure_Json.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleConfigure_Json/ModuleConfigure_Json.cpp + +pch.o:./pch.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./pch.cpp + + +InstallAll:InstallSo +InstallSo:./libXEngine_ModuleConfigure.so + cp ./libXEngine_ModuleConfigure.so ../../XEngine_Release/libXEngine_ModuleConfigure.so + + +CleanAll:CleanObj CleanMk +CleanObj: + rm *.o +CleanMk: + rm *.so diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h new file mode 100644 index 0000000000000000000000000000000000000000..9255ff73e6d2fa483196cc72bfafc28ace1a2ad8 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h @@ -0,0 +1,78 @@ +#pragma once +/******************************************************************** +// Created: 2021/12/02 16:09:03 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfig_Define.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure +// File Base: ModuleConfig_Define +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 配置模块导出定义 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +// 导出的数据结构 +////////////////////////////////////////////////////////////////////////// +typedef struct tag_XEngine_ServiceConfig +{ + TCHAR tszIPAddr[128]; //本机IP地址,根据需要配置 + BOOL bDeamon; //是否以守护进程启动,LINUX有效 + int nHttpPort; //HTTP服务端口 + int nCenterPort; //业务端口 + struct + { + int nMaxClient; //最大客户端个数 + int nMaxQueue; //最大队列个数 + int nIOThread; //网络IO线程数 + int nHTTPThread; //HTTP任务处理线程数 + int nCenterThread; //业务任务处理线程数 + }st_XMax; + struct + { + int nTimeCheck; //检测次数 + int nHTTPTimeOut; //HTTP超时时间 + int nCenterTimeOut; //业务超时时间 + }st_XTime; //次数*时间=超时 + struct + { + int nMaxSize; //最大日志大小 + int nMaxCount; //最大日志个数 + int nLogLeave; //日志等级 + }st_XLog; + struct + { + TCHAR tszIPData[MAX_PATH]; //IP数据库地址 + TCHAR tszIDData[MAX_PATH]; //ID数据库地址 + TCHAR tszPhoneData[MAX_PATH]; //电话号码数据库地址 + }st_XDBInfo; + struct + { + list* pStl_ListVer; + }st_XVer; +}XENGINE_SERVICECONFIG; +////////////////////////////////////////////////////////////////////////// +// 导出函数定义 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleConfigure_GetLastError(int* pInt_ErrorCode = NULL); +/************************************************************************/ +/* 文件配置读取 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleConfigure_Json_File +函数功能:读取JSON配置文件 + 参数.一:lpszConfigFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要读取的配置文件 + 参数.二:pSt_ServerConfig + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出服务配置信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleConfigure_Json_File(LPCTSTR lpszConfigFile, XENGINE_SERVICECONFIG* pSt_ServerConfig); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h new file mode 100644 index 0000000000000000000000000000000000000000..5918ceecec8810290c4f4952448a96b4e58cfe9f --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h @@ -0,0 +1,20 @@ +#pragma once +/******************************************************************** +// Created: 2021/12/02 16:15:47 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfig_Error.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure +// File Base: ModuleConfig_Error +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 配置模块导出错误 +// History: +*********************************************************************/ +#define ERROR_MODULE_CONFIGURE_JSON_PARAMENT 0xA0001 //参数错误 +#define ERROR_MODULE_CONFIGURE_JSON_OPENFILE 0xA0002 //打开文件失败 +#define ERROR_MODULE_CONFIGURE_JSON_PARSE 0xA0003 //解析JSON失败 +#define ERROR_MODULE_CONFIGURE_JSON_XMAX 0xA0004 //读取XMAX配置失败 +#define ERROR_MODULE_CONFIGURE_JSON_XTIME 0xA0005 //读取XTIME配置失败 +#define ERROR_MODULE_CONFIGURE_JSON_XLOG 0xA0006 //读取XLOG配置失败 +#define ERROR_MODULE_CONFIGURE_JSON_XDB 0xA0007 //数据库配置错误 +#define ERROR_MODULE_CONFIGURE_JSON_XVER 0xA0008 //版本配置文件读取错误 \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34b1bcda9a38bc9de964e058ad8d06c982f58009 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp @@ -0,0 +1,145 @@ +#include "pch.h" +#include "ModuleConfigure_Json.h" +/******************************************************************** +// Created: 2021/12/02 16:14:11 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfigure_Json\ModuleConfigure_Json.cpp +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfigure_Json +// File Base: ModuleConfigure_Json +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: JSON配置读写实现 +// History: +*********************************************************************/ +CModuleConfigure_Json::CModuleConfigure_Json() +{ + +} +CModuleConfigure_Json::~CModuleConfigure_Json() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公用函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleConfigure_Json_File +函数功能:读取JSON配置文件 + 参数.一:lpszConfigFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要读取的配置文件 + 参数.二:pSt_ServerConfig + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出服务配置信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleConfigure_Json::ModuleConfigure_Json_File(LPCTSTR lpszConfigFile, XENGINE_SERVICECONFIG* pSt_ServerConfig) +{ + Config_IsErrorOccur = FALSE; + + if ((NULL == lpszConfigFile) || (NULL == pSt_ServerConfig)) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_PARAMENT; + return FALSE; + } + Json::Value st_JsonRoot; + JSONCPP_STRING st_JsonError; + Json::CharReaderBuilder st_JsonBuilder; + //读取配置文件所有内容到缓冲区 + FILE* pSt_File = _tfopen(lpszConfigFile, _T("rb")); + if (NULL == pSt_File) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_OPENFILE; + return FALSE; + } + size_t nCount = 0; + TCHAR tszMsgBuffer[4096]; + while (1) + { + size_t nRet = fread(tszMsgBuffer + nCount, 1, 2048, pSt_File); + if (nRet <= 0) + { + break; + } + nCount += nRet; + } + fclose(pSt_File); + //开始解析配置文件 + std::unique_ptr const pSt_JsonReader(st_JsonBuilder.newCharReader()); + if (!pSt_JsonReader->parse(tszMsgBuffer, tszMsgBuffer + nCount, &st_JsonRoot, &st_JsonError)) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_PARSE; + return FALSE; + } + _tcscpy(pSt_ServerConfig->tszIPAddr, st_JsonRoot["tszIPAddr"].asCString()); + pSt_ServerConfig->bDeamon = st_JsonRoot["bDeamon"].asInt(); + pSt_ServerConfig->nHttpPort = st_JsonRoot["nHttpPort"].asInt(); + + if (st_JsonRoot["XMax"].empty() || (4 != st_JsonRoot["XMax"].size())) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_XMAX; + return FALSE; + } + Json::Value st_JsonXMax = st_JsonRoot["XMax"]; + pSt_ServerConfig->st_XMax.nMaxClient = st_JsonXMax["nMaxClient"].asInt(); + pSt_ServerConfig->st_XMax.nMaxQueue = st_JsonXMax["nMaxQueue"].asInt(); + pSt_ServerConfig->st_XMax.nIOThread = st_JsonXMax["nIOThread"].asInt(); + pSt_ServerConfig->st_XMax.nHTTPThread = st_JsonXMax["nHttpThread"].asInt(); + + if (st_JsonRoot["XTime"].empty() || (2 != st_JsonRoot["XTime"].size())) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_XTIME; + return FALSE; + } + Json::Value st_JsonXTime = st_JsonRoot["XTime"]; + pSt_ServerConfig->st_XTime.nTimeCheck = st_JsonXTime["nTimeCheck"].asInt(); + pSt_ServerConfig->st_XTime.nHTTPTimeOut = st_JsonXTime["nHttpTimeOut"].asInt(); + + if (st_JsonRoot["XLog"].empty() || (3 != st_JsonRoot["XLog"].size())) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_XLOG; + return FALSE; + } + Json::Value st_JsonXLog = st_JsonRoot["XLog"]; + pSt_ServerConfig->st_XLog.nMaxSize = st_JsonXLog["MaxSize"].asInt(); + pSt_ServerConfig->st_XLog.nMaxCount = st_JsonXLog["MaxCount"].asInt(); + pSt_ServerConfig->st_XLog.nLogLeave = st_JsonXLog["LogLeave"].asInt(); + + if (st_JsonRoot["XDatabase"].empty() || (3 != st_JsonRoot["XDatabase"].size())) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_XDB; + return FALSE; + } + Json::Value st_JsonXDB = st_JsonRoot["XDatabase"]; + _tcscpy(pSt_ServerConfig->st_XDBInfo.tszIPData, st_JsonXDB["tszIPData"].asCString()); + _tcscpy(pSt_ServerConfig->st_XDBInfo.tszIDData, st_JsonXDB["tszIDData"].asCString()); + _tcscpy(pSt_ServerConfig->st_XDBInfo.tszPhoneData, st_JsonXDB["tszPhoneData"].asCString()); + + if (st_JsonRoot["XVer"].empty()) + { + Config_IsErrorOccur = TRUE; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_XVER; + return FALSE; + } + pSt_ServerConfig->st_XVer.pStl_ListVer = new list; + Json::Value st_JsonXVer = st_JsonRoot["XVer"]; + for (unsigned int i = 0; i < st_JsonXVer.size(); i++) + { + pSt_ServerConfig->st_XVer.pStl_ListVer->push_back(st_JsonXVer[i].asCString()); + } + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.h b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.h new file mode 100644 index 0000000000000000000000000000000000000000..7ff49474b6cf2a6cc69fec7cb2a5de586d2663c1 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.h @@ -0,0 +1,23 @@ +#pragma once +/******************************************************************** +// Created: 2021/12/02 16:08:16 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfigure_Json\ModuleConfigure_Json.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfigure_Json +// File Base: ModuleConfigure_Json +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: JSON配置文件读写 +// History: +*********************************************************************/ + +class CModuleConfigure_Json +{ +public: + CModuleConfigure_Json(); + ~CModuleConfigure_Json(); +public: + BOOL ModuleConfigure_Json_File(LPCTSTR lpszConfigFile, XENGINE_SERVICECONFIG* pSt_ServerConfig); +protected: +private: +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.def b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.def new file mode 100644 index 0000000000000000000000000000000000000000..6255e0732a407007cd9b07dd0cd643911336e33c --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.def @@ -0,0 +1,6 @@ +LIBRARY + +EXPORTS + ModuleConfigure_GetLastError + + ModuleConfigure_Json_File \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..6d632fab0c5ff68cb28399781a80e77797d8a930 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj @@ -0,0 +1,193 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {f54f152c-594f-4465-a44e-2db915b39760} + XEngineModuleConfigure + 10.0 + + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + false + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + true + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + + + false + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + + Level3 + true + WIN32;_DEBUG;XENGINEMODULECONFIGURE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + 4819 + + + Windows + true + false + XEngine_ModuleConfigure.def + + + + + Level3 + true + true + true + WIN32;NDEBUG;XENGINEMODULECONFIGURE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + MultiThreaded + 4819 + + + Windows + true + true + true + false + XEngine_ModuleConfigure.def + + + + + Level3 + true + _DEBUG;XENGINEMODULECONFIGURE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + 4819 + + + Windows + true + false + XEngine_ModuleConfigure.def + + + + + Level3 + true + true + true + NDEBUG;XENGINEMODULECONFIGURE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + MultiThreaded + 4819 + + + Windows + true + true + true + false + XEngine_ModuleConfigure.def + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj.filters b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..a8d85e7d07a8c6741f9666e2a63ffbe98e2a20bb --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {49ae8b29-d807-47ec-907b-b4e5c91e1f62} + + + {865425d8-f7eb-4fb9-bcd1-8bb631209b4e} + + + + + 头文件 + + + 头文件 + + + 头文件\ModuleConfigure_Json + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件\ModuleConfigure_Json + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj.user b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/XEngine_ModuleConfigure.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/dllmain.cpp b/XEngine_Source/XEngine_ModuleConfigure/dllmain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..daed8c8f7ac50ca1466016a0529648d18125a7e7 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/XEngine_Source/XEngine_ModuleConfigure/framework.h b/XEngine_Source/XEngine_ModuleConfigure/framework.h new file mode 100644 index 0000000000000000000000000000000000000000..80cbbc9b06a9b0141f92ee19eceaed71328caff4 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/XEngine_Source/XEngine_ModuleConfigure/pch.cpp b/XEngine_Source/XEngine_ModuleConfigure/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a4bfa52f983d913c273b1411618b0678a76c588 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/pch.cpp @@ -0,0 +1,35 @@ +#include "pch.h" +#include "ModuleConfigure_Json/ModuleConfigure_Json.h" +/******************************************************************** +// Created: 2021/12/02 16:20:26 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\pch.cpp +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure +// File Base: pch +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出函数实现 +// History: +*********************************************************************/ +BOOL Config_IsErrorOccur = FALSE; +DWORD Config_dwErrorCode = 0; +////////////////////////////////////////////////////////////////////// +CModuleConfigure_Json m_ConfigJson; +////////////////////////////////////////////////////////////////////// +// 导出函数定义 +////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleConfigure_GetLastError(int* pInt_ErrorCode) +{ + if (pInt_ErrorCode != NULL) + { + *pInt_ErrorCode = errno; + } + return Config_dwErrorCode; +} +/************************************************************************/ +/* 配置文件读取 */ +/************************************************************************/ +extern "C" BOOL ModuleConfigure_Json_File(LPCTSTR lpszConfigFile, XENGINE_SERVICECONFIG * pSt_ServerConfig) +{ + return m_ConfigJson.ModuleConfigure_Json_File(lpszConfigFile, pSt_ServerConfig); +} diff --git a/XEngine_Source/XEngine_ModuleConfigure/pch.h b/XEngine_Source/XEngine_ModuleConfigure/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..477c82889c83e2c4245d8d1d9585a3299ae800c5 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleConfigure/pch.h @@ -0,0 +1,56 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +#ifdef _MSC_BUILD +// 添加要在此处预编译的标头 +#include "framework.h" +#include +#endif +#endif //PCH_H +#include +#include +#include +#include +#include +#include +#include +using namespace std; +#include +#include +#include "ModuleConfig_Define.h" +#include "ModuleConfig_Error.h" +/******************************************************************** +// Created: 2021/12/02 16:07:58 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\pch.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure +// File Base: pch +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 公用头文件 +// History: +*********************************************************************/ +extern BOOL Config_IsErrorOccur; +extern DWORD Config_dwErrorCode; + +#ifdef _MSC_BUILD +#ifdef _DEBUG +#ifdef _WIN64 +#pragma comment(lib,"../x64/Debug/jsoncpp") +#else +#pragma comment(lib,"../Debug/jsoncpp") +#endif +#else +#ifdef _WIN64 +#pragma comment(lib,"../x64/Release/jsoncpp") +#else +#pragma comment(lib,"../Release/jsoncpp") +#endif +#endif +#endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/Makefile b/XEngine_Source/XEngine_ModuleDatabase/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f599cecc59886197013f2c6c47f57b86416ef622 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/Makefile @@ -0,0 +1,49 @@ +CC = g++ -Wall -std=c++17 -fPIC +RELEASE = 0 +UNICODE = 0 +INCLUDE = -I ./ +LOADBIN = -L /usr/local/lib/XEngine_Release/XEngine_HelpComponents +LIB = -lHelpComponents_DataBase +LIBEX = -static-libgcc -lrt -ldl -lpthread +LOADSO = -Wl,-rpath=./,--disable-new-dtags +LIBINCLUDE = ModuleDatabase_IDCard.o ModuleDatabase_IPInfo.o ModuleDatabase_Phone.o pch.o + +ifeq ($(RELEASE),1) +FLAGS = -c -O2 +DEBUG = +else +FLAGS = -c -lc_p +DEBUG = -g -pg +endif + +ifeq ($(UNICODE),1) +UNICODE = -D _UNICODE +else +UNICODE = +endif + + +all:$(LIBINCLUDE) + $(CC) $(DEBUG) $(LIBINCLUDE) -o libXEngine_ModuleDatabase.so -shared -fPIC $(LOADBIN) $(LIB) $(LIBEX) $(LOADSO) + +ModuleDatabase_IDCard.o:./ModuleDatabase_IDCard/ModuleDatabase_IDCard.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleDatabase_IDCard/ModuleDatabase_IDCard.cpp +ModuleDatabase_IPInfo.o:./ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.cpp +ModuleDatabase_Phone.o:./ModuleDatabase_Phone/ModuleDatabase_Phone.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleDatabase_Phone/ModuleDatabase_Phone.cpp + +pch.o:./pch.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./pch.cpp + + +InstallAll:InstallSo +InstallSo:./libXEngine_ModuleDatabase.so + cp ./libXEngine_ModuleDatabase.so ../../XEngine_Release/libXEngine_ModuleDatabase.so + + +CleanAll:CleanObj CleanMk +CleanObj: + rm *.o +CleanMk: + rm *.so \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDB_Define.h b/XEngine_Source/XEngine_ModuleDatabase/ModuleDB_Define.h new file mode 100644 index 0000000000000000000000000000000000000000..f4bed51ea6e6697dbc39e4695c528edee072a6cf --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDB_Define.h @@ -0,0 +1,170 @@ +#pragma once +/******************************************************************** +// Created: 2022/02/28 10:16:15 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase\ModuleDB_Define.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase +// File Base: ModuleDB_Define +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 数据库操作导出 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +/// 导出的函数 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleDB_GetLastError(int *pInt_SysError = NULL); +/************************************************************************/ +/* 导出的IP地址操作函数 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_Init +函数功能:初始化SQLITE文件系统 + 参数.一:lpszSQLFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要操作的SQL文件 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IPInfo_Init(LPCTSTR lpszSQLFile); +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_Destory +函数功能:销毁 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IPInfo_Destory(); +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_IPV4Query +函数功能:查询文件信息 + 参数.一:pSt_IPAddrInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出IP地址信息结构 + 参数.二:lpszIPAddr + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要查询的IPV4 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IPInfo_IPV4Query(XENGINE_IPADDRINFO* pSt_IPAddrInfo, LPCTSTR lpszIPAddr); +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_IPV6Query +函数功能:查询IPV6地址信息 + 参数.一:pSt_IPAddrInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出IP地址信息结构 + 参数.二:lpszIPAddr + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要查询的地址 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IPInfo_IPV6Query(XENGINE_IPADDRINFO* pSt_IPAddrInfo, LPCTSTR lpszIPAddr); +/************************************************************************/ +/* 导出的身份证地址操作函数 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleDatabase_IDCard_Init +函数功能:初始化SQLITE文件系统 + 参数.一:lpszSQLFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要操作的SQL文件 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IDCard_Init(LPCTSTR lpszSQLFile); +/******************************************************************** +函数名称:ModuleDatabase_IDCard_Destory +函数功能:销毁 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IDCard_Destory(); +/******************************************************************** +函数名称:ModuleDatabase_IDCard_QueryRegion +函数功能:查询身份证位置信息 + 参数.一:pSt_IDRegion + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出查询到的位置信息 + 参数.二:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要查询的信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_IDCard_QueryRegion(XENGINE_IDREGION * pSt_IDRegion, XENGINE_IDCARDINFO * pSt_IDInfo); +/************************************************************************/ +/* 导出的电话号码信息函数 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleDatabase_Phone_Init +函数功能:初始化电话信息查询数据库 + 参数.一:lpszSQLFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要操作的SQL文件 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_Phone_Init(LPCTSTR lpszSQLFile); +/******************************************************************** +函数名称:ModuleDatabase_Phone_Destory +函数功能:销毁 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_Phone_Destory(); +/******************************************************************** +函数名称:ModuleDatabase_Phone_Query +函数功能:查询电话号码信息 + 参数.一:lpszPhoneNumber + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要查询的电话号码 + 参数.二:pSt_PhoneInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出电话信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleDatabase_Phone_Query(LPCTSTR lpszPhoneNumber, XENGINE_PHONEINFO * pSt_PhoneInfo); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDB_Error.h b/XEngine_Source/XEngine_ModuleDatabase/ModuleDB_Error.h new file mode 100644 index 0000000000000000000000000000000000000000..26443ab798e0915e78dfb7e5e54df655b2dd64a7 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDB_Error.h @@ -0,0 +1,28 @@ +#pragma once +/******************************************************************** +// Created: 2022/02/28 10:16:35 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase\ModuleDB_Error.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase +// File Base: ModuleDB_Error +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 数据库错误导出 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +// 导出的IP数据库错误 +////////////////////////////////////////////////////////////////////////// +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_IPINFO_PARAMENT 0xB0001 //初始化失败.参数错误 +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_IPINFO_NOTFOUND 0xB0002 //没有找到 +////////////////////////////////////////////////////////////////////////// +// 导出的身份证数据库错误 +////////////////////////////////////////////////////////////////////////// +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_PARAMENT 0xB1001 //初始化失败.参数错误 +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_NOTFOUND 0xB1002 //没有找到 +////////////////////////////////////////////////////////////////////////// +// 导出的电话数据库错误 +////////////////////////////////////////////////////////////////////////// +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_PARAMENT 0xB2001 //初始化失败.参数错误 +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_MALLOC 0xB2002 //申请内存失败 +#define ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_NOTFOUND 0xB1002 //没有找到 \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IDCard/ModuleDatabase_IDCard.cpp b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IDCard/ModuleDatabase_IDCard.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5f7fb28aafe3925a2e1ed5aba62795c8bce4769 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IDCard/ModuleDatabase_IDCard.cpp @@ -0,0 +1,249 @@ +#include "pch.h" +#include "ModuleDatabase_IDCard.h" +/******************************************************************** +// Created: 2022/03/04 14:24:12 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IDCard\ModuleDatabase_IDCard.cpp +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IDCard +// File Base: ModuleDatabase_IDCard +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 身份证信息数据库操作 +// History: +*********************************************************************/ +CModuleDatabase_IDCard::CModuleDatabase_IDCard() +{ +} +CModuleDatabase_IDCard::~CModuleDatabase_IDCard() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公有函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleDatabase_IDCard_Init +函数功能:初始化SQLITE文件系统 + 参数.一:lpszSQLFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要操作的SQL文件 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IDCard::ModuleDatabase_IDCard_Init(LPCTSTR lpszSQLFile) +{ + DBModule_IsErrorOccur = FALSE; + //打开数据库 + if (!DataBase_SQLite_Open(&xhSQL, lpszSQLFile)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IDCard_Destory +函数功能:销毁 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IDCard::ModuleDatabase_IDCard_Destory() +{ + DBModule_IsErrorOccur = FALSE; + + DataBase_SQLite_Close(xhSQL); + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IDCard_QueryRegion +函数功能:查询身份证位置信息 + 参数.一:pSt_IDRegion + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出查询到的位置信息 + 参数.二:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要查询的信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IDCard::ModuleDatabase_IDCard_QueryRegion(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo) +{ + DBModule_IsErrorOccur = FALSE; + + ModuleDatabase_IDCard_QueryProvincer(pSt_IDRegion, pSt_IDInfo); + ModuleDatabase_IDCard_QueryCity(pSt_IDRegion, pSt_IDInfo); + ModuleDatabase_IDCard_QueryCounty(pSt_IDRegion, pSt_IDInfo); + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IDCard_QueryProvincer +函数功能:查询省份信息 + 参数.一:pSt_IDRegion + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出所属省份 + 参数.二:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要查询的信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IDCard::ModuleDatabase_IDCard_QueryProvincer(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo) +{ + DBModule_IsErrorOccur = FALSE; + + if ((NULL == pSt_IDRegion) || (NULL == pSt_IDInfo)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_PARAMENT; + return FALSE; + } + //查询 + int nLine = 0; + int nRow = 0; + TCHAR** pptszResult; + TCHAR tszSQLStatement[1024]; + + memset(tszSQLStatement, '\0', sizeof(tszSQLStatement)); + _stprintf(tszSQLStatement, _T("SELECT * FROM `regionsid` WHERE code = '%02d0000'"), pSt_IDInfo->nIDProvince); + if (!DataBase_SQLite_GetTable(xhSQL, tszSQLStatement, &pptszResult, &nLine, &nRow)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + if (nLine <= 0) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_IDRegion->tszProvincer, pptszResult[nRow + 1]); + + DataBase_SQLite_FreeTable(pptszResult); + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IDCard_QueryCity +函数功能:查询市信息 + 参数.一:pSt_IDRegion + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出所属市 + 参数.二:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要查询的信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IDCard::ModuleDatabase_IDCard_QueryCity(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo) +{ + DBModule_IsErrorOccur = FALSE; + + if ((NULL == pSt_IDRegion) || (NULL == pSt_IDInfo)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_PARAMENT; + return FALSE; + } + //查询 + int nLine = 0; + int nRow = 0; + TCHAR** pptszResult; + TCHAR tszSQLStatement[1024]; + + memset(tszSQLStatement, '\0', sizeof(tszSQLStatement)); + _stprintf(tszSQLStatement, _T("SELECT * FROM `regionsid` WHERE code = '%02d%02d00'"), pSt_IDInfo->nIDProvince, pSt_IDInfo->nIDCity); + if (!DataBase_SQLite_GetTable(xhSQL, tszSQLStatement, &pptszResult, &nLine, &nRow)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + if (nLine <= 0) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_IDRegion->tszCity, pptszResult[nRow + 1]); + + DataBase_SQLite_FreeTable(pptszResult); + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IDCard_QueryCounty +函数功能:查询县区信息 + 参数.一:pSt_IDRegion + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出所属县区 + 参数.二:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要查询的信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IDCard::ModuleDatabase_IDCard_QueryCounty(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo) +{ + DBModule_IsErrorOccur = FALSE; + + if ((NULL == pSt_IDRegion) || (NULL == pSt_IDInfo)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_PARAMENT; + return FALSE; + } + //查询 + int nLine = 0; + int nRow = 0; + TCHAR** pptszResult; + TCHAR tszSQLStatement[1024]; + + memset(tszSQLStatement, '\0', sizeof(tszSQLStatement)); + _stprintf(tszSQLStatement, _T("SELECT * FROM `regionsid` WHERE code = '%02d%02d%02d'"), pSt_IDInfo->nIDProvince, pSt_IDInfo->nIDCity, pSt_IDInfo->nIDCounty); + if (!DataBase_SQLite_GetTable(xhSQL, tszSQLStatement, &pptszResult, &nLine, &nRow)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + if (nLine <= 0) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IDCARD_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_IDRegion->tszCounty, pptszResult[nRow + 1]); + + DataBase_SQLite_FreeTable(pptszResult); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IDCard/ModuleDatabase_IDCard.h b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IDCard/ModuleDatabase_IDCard.h new file mode 100644 index 0000000000000000000000000000000000000000..5838256bfb18e5ff6a8e4d870a70413953b7486c --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IDCard/ModuleDatabase_IDCard.h @@ -0,0 +1,30 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/04 14:23:55 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IDCard\ModuleDatabase_IDCard.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IDCard +// File Base: ModuleDatabase_IDCard +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 身份证信息数据库操作 +// History: +*********************************************************************/ + + +class CModuleDatabase_IDCard +{ +public: + CModuleDatabase_IDCard(); + ~CModuleDatabase_IDCard(); +public: + BOOL ModuleDatabase_IDCard_Init(LPCTSTR lpszSQLFile); + BOOL ModuleDatabase_IDCard_Destory(); + BOOL ModuleDatabase_IDCard_QueryRegion(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo); +protected: + BOOL ModuleDatabase_IDCard_QueryProvincer(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo); + BOOL ModuleDatabase_IDCard_QueryCity(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo); + BOOL ModuleDatabase_IDCard_QueryCounty(XENGINE_IDREGION* pSt_IDRegion, XENGINE_IDCARDINFO* pSt_IDInfo); +private: + XHDATA xhSQL; +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.cpp b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..583d89d2e4a68d39752d72488cf90c0b0fa4236a --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.cpp @@ -0,0 +1,200 @@ +#include "pch.h" +#include "ModuleDatabase_IPInfo.h" +/******************************************************************** +// Created: 2022/03/04 14:24:57 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IPInfo\ModuleDatabase_IPInfo.cpp +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IPInfo +// File Base: ModuleDatabase_IPInfo +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: IP数据库信息操作 +// History: +*********************************************************************/ +CModuleDatabase_IPInfo::CModuleDatabase_IPInfo() +{ +} +CModuleDatabase_IPInfo::~CModuleDatabase_IPInfo() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公有函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_Init +函数功能:初始化SQLITE文件系统 + 参数.一:lpszSQLFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要操作的SQL文件 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IPInfo::ModuleDatabase_IPInfo_Init(LPCTSTR lpszSQLFile) +{ + DBModule_IsErrorOccur = FALSE; + //打开数据库 + if (!DataBase_SQLite_Open(&xhSQL, lpszSQLFile)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_Destory +函数功能:销毁 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IPInfo::ModuleDatabase_IPInfo_Destory() +{ + DBModule_IsErrorOccur = FALSE; + + DataBase_SQLite_Close(xhSQL); + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_IPV4Query +函数功能:查询IPV4地址信息 + 参数.一:pSt_IPAddrInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出IP地址信息结构 + 参数.二:lpszIPAddr + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要查询的IPV4 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IPInfo::ModuleDatabase_IPInfo_IPV4Query(XENGINE_IPADDRINFO* pSt_IPAddrInfo, LPCTSTR lpszIPAddr) +{ + DBModule_IsErrorOccur = FALSE; + + if ((NULL == pSt_IPAddrInfo) && (NULL == lpszIPAddr)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IPINFO_PARAMENT; + return FALSE; + } + //查询 + int nLine = 0; + int nRow = 0; + TCHAR** pptszResult; + TCHAR tszSQLStatement[1024]; + struct in_addr st_Addr; + + memset(tszSQLStatement, '\0', sizeof(tszSQLStatement)); + memset(&st_Addr, '\0', sizeof(struct in_addr)); + + inet_pton(AF_INET, lpszIPAddr, &st_Addr); + + _stprintf(tszSQLStatement, _T("SELECT * FROM `iprange_info` WHERE '%u' BETWEEN ip_start_num AND ip_end_num"), htonl(st_Addr.s_addr)); + if (!DataBase_SQLite_GetTable(xhSQL, tszSQLStatement, &pptszResult, &nLine, &nRow)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + if (nLine <= 0) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IPINFO_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_IPAddrInfo->tszIPStart, pptszResult[nRow + 1]); + _tcscpy(pSt_IPAddrInfo->tszIPEnd, pptszResult[nRow + 3]); + _tcscpy(pSt_IPAddrInfo->tszIPAddr, lpszIPAddr); + _tcscpy(pSt_IPAddrInfo->tszIPCountry, pptszResult[nRow + 5]); + _tcscpy(pSt_IPAddrInfo->tszIPProvince, pptszResult[nRow + 6]); + _tcscpy(pSt_IPAddrInfo->tszIPCity, pptszResult[nRow + 7]); + _tcscpy(pSt_IPAddrInfo->tszIPCounty, pptszResult[nRow + 8]); + _tcscpy(pSt_IPAddrInfo->tszIPAddress, pptszResult[nRow + 9]); + _tcscpy(pSt_IPAddrInfo->tszIPISP, pptszResult[nRow + 10]); + _tcscpy(pSt_IPAddrInfo->tszIPTime, pptszResult[nRow + 11]); + + DataBase_SQLite_FreeTable(pptszResult); + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_IPInfo_IPV6Query +函数功能:查询IPV6地址信息 + 参数.一:pSt_IPAddrInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出IP地址信息结构 + 参数.二:lpszIPAddr + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要查询的地址 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_IPInfo::ModuleDatabase_IPInfo_IPV6Query(XENGINE_IPADDRINFO* pSt_IPAddrInfo, LPCTSTR lpszIPAddr) +{ + DBModule_IsErrorOccur = FALSE; + + if ((NULL == pSt_IPAddrInfo) && (NULL == lpszIPAddr)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IPINFO_PARAMENT; + return FALSE; + } + //查询 + int nLine = 0; + int nRow = 0; + TCHAR** pptszResult; + TCHAR tszSQLStatement[1024]; + TCHAR tszIPV6Addr[128]; + XENGINE_LIBADDR st_LibAddr; + + memset(tszSQLStatement, '\0', sizeof(tszSQLStatement)); + memset(tszIPV6Addr, '\0', sizeof(tszIPV6Addr)); + memset(&st_LibAddr, '\0', sizeof(XENGINE_LIBADDR)); + + BaseLib_OperatorIPAddr_IsIPV6Addr(lpszIPAddr, &st_LibAddr); + BaseLib_OperatorIPAddr_ExpIPV6Addr(&st_LibAddr, tszIPV6Addr, TRUE, FALSE); + + _stprintf(tszSQLStatement, _T("SELECT * FROM `ipv6_range_info` WHERE X'%s' BETWEEN ip_start_num AND ip_end_num"), tszIPV6Addr); + if (!DataBase_SQLite_GetTable(xhSQL, tszSQLStatement, &pptszResult, &nLine, &nRow)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = DataBase_GetLastError(); + return FALSE; + } + if (nLine <= 0) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_IPINFO_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_IPAddrInfo->tszIPStart, pptszResult[nRow + 1]); + _tcscpy(pSt_IPAddrInfo->tszIPEnd, pptszResult[nRow + 3]); + _tcscpy(pSt_IPAddrInfo->tszIPAddr, lpszIPAddr); + _tcscpy(pSt_IPAddrInfo->tszIPCountry, pptszResult[nRow + 5]); + _tcscpy(pSt_IPAddrInfo->tszIPProvince, pptszResult[nRow + 6]); + _tcscpy(pSt_IPAddrInfo->tszIPCity, pptszResult[nRow + 7]); + _tcscpy(pSt_IPAddrInfo->tszIPCounty, pptszResult[nRow + 8]); + _tcscpy(pSt_IPAddrInfo->tszIPAddress, pptszResult[nRow + 9]); + _tcscpy(pSt_IPAddrInfo->tszIPISP, pptszResult[nRow + 10]); + _tcscpy(pSt_IPAddrInfo->tszIPTime, pptszResult[nRow + 11]); + + DataBase_SQLite_FreeTable(pptszResult); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.h b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..d59d2d2c9079860bc4f7632d5e3f0d8fdb3a96e4 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.h @@ -0,0 +1,27 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/04 14:24:30 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IPInfo\ModuleDatabase_IPInfo.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_IPInfo +// File Base: ModuleDatabase_IPInfo +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: IP数据库信息操作 +// History: +*********************************************************************/ + + +class CModuleDatabase_IPInfo +{ +public: + CModuleDatabase_IPInfo(); + ~CModuleDatabase_IPInfo(); +public: + BOOL ModuleDatabase_IPInfo_Init(LPCTSTR lpszSQLFile); + BOOL ModuleDatabase_IPInfo_Destory(); + BOOL ModuleDatabase_IPInfo_IPV4Query(XENGINE_IPADDRINFO* pSt_IPAddrInfo, LPCTSTR lpszIPAddr); + BOOL ModuleDatabase_IPInfo_IPV6Query(XENGINE_IPADDRINFO* pSt_IPAddrInfo, LPCTSTR lpszIPAddr); +private: + XHDATA xhSQL; +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_Phone/ModuleDatabase_Phone.cpp b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_Phone/ModuleDatabase_Phone.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ebecde5c67566d955272738f2801be8a4588869 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_Phone/ModuleDatabase_Phone.cpp @@ -0,0 +1,255 @@ +#include "pch.h" +#include "ModuleDatabase_Phone.h" +/******************************************************************** +// Created: 2022/03/09 10:31:44 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_Phone\ModuleDatabase_Phone.cpp +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_Phone +// File Base: ModuleDatabase_Phone +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 移动电话查询 +// History: +*********************************************************************/ +CModuleDatabase_Phone::CModuleDatabase_Phone() +{ +} +CModuleDatabase_Phone::~CModuleDatabase_Phone() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公有函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleDatabase_Phone_Init +函数功能:初始化电话信息查询数据库 + 参数.一:lpszSQLFile + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要操作的SQL文件 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_Phone::ModuleDatabase_Phone_Init(LPCTSTR lpszSQLFile) +{ + DBModule_IsErrorOccur = FALSE; + + if (NULL == lpszSQLFile) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_PARAMENT; + return FALSE; + } + //打开数据库 + FILE* pSt_File = _tfopen(lpszSQLFile, _T("rb")); + if (NULL == pSt_File) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_NOTFOUND; + return FALSE; + } + //申请内存 + ptszMsgBuffer = (TCHAR*)malloc(XENGINE_APISERVICE_DATABASE_PHONE_BUFFER_SIZE); + if (NULL == ptszMsgBuffer) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_MALLOC; + return FALSE; + } + memset(ptszMsgBuffer, '\0', XENGINE_APISERVICE_DATABASE_PHONE_BUFFER_SIZE); + //读取内容 + while (TRUE) + { + int nRet = fread(ptszMsgBuffer + nFLen, 1, 2048, pSt_File); + if (nRet <= 0) + { + break; + } + nFLen += nRet; + } + fclose(pSt_File); + memcpy(&st_PhoneHdr, ptszMsgBuffer, sizeof(XENGINE_DBPHONEHDR)); + nCount = (nFLen - st_PhoneHdr.nOffset) / XENGINE_APISERVICE_DATABASE_PHONE_INDEX_LEN; + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_Phone_Destory +函数功能:销毁 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_Phone::ModuleDatabase_Phone_Destory() +{ + DBModule_IsErrorOccur = FALSE; + + free(ptszMsgBuffer); + ptszMsgBuffer = NULL; + return TRUE; +} +/******************************************************************** +函数名称:ModuleDatabase_Phone_Query +函数功能:查询电话号码信息 + 参数.一:lpszPhoneNumber + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要查询的电话号码 + 参数.二:pSt_PhoneInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出电话信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_Phone::ModuleDatabase_Phone_Query(LPCTSTR lpszPhoneNumber, XENGINE_PHONEINFO* pSt_PhoneInfo) +{ + DBModule_IsErrorOccur = FALSE; + + if ((NULL == lpszPhoneNumber) || (NULL == pSt_PhoneInfo)) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_PARAMENT; + return FALSE; + } + size_t nPLen = _tcslen(lpszPhoneNumber); + size_t nPhone = 0; + //不能超过7 + if (nPLen > 7) + { + TCHAR tszPhone[64]; + memset(tszPhone, '\0', sizeof(tszPhone)); + + memcpy(tszPhone, lpszPhoneNumber, 7); + nPhone = _ttoi(tszPhone); + } + else + { + nPhone = _ttoi(lpszPhoneNumber); + } + + size_t nLeft = 0; + size_t nRight = nCount; + while (nLeft <= nRight) + { + //二分查找 + size_t nMiddle = (nLeft + nRight) / 2; + size_t nCurrentPos = st_PhoneHdr.nOffset + nMiddle * XENGINE_APISERVICE_DATABASE_PHONE_INDEX_LEN; + if (nCurrentPos >= nFLen) + { + break; + } + XENGINE_DBPHONERECORD st_DBRecord; + memset(&st_DBRecord, '\0', sizeof(XENGINE_DBPHONERECORD)); + + memcpy(&st_DBRecord, ptszMsgBuffer + nCurrentPos, XENGINE_APISERVICE_DATABASE_PHONE_INDEX_LEN); + if (st_DBRecord.nPhone > nPhone) + { + nRight = nMiddle - 1; + } + else if (st_DBRecord.nPhone < nPhone) + { + nLeft = nMiddle + 1; + } + else + { + int i = 0; + while (TRUE) + { + if (ptszMsgBuffer[i + st_DBRecord.nOffset] == '\0') + { + break; + } + i++; + } + pSt_PhoneInfo->enPhoneType = (ENUM_XENGINE_APISERVICE_PHONE_TYPE)st_DBRecord.byType; + //转换数据 + if (!ModuleDatabase_Phone_Convert(ptszMsgBuffer + st_DBRecord.nOffset, i, pSt_PhoneInfo)) + { + return FALSE; + } + break; + } + } + return TRUE; +} +////////////////////////////////////////////////////////////////////////// +// 保护函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleDatabase_Phone_Convert +函数功能:转换数据格式到指定数据结构 + 参数.一:lpszPhoneInfo + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要转换的信息 + 参数.二:nMsgLen + In/Out:In + 类型:整数型 + 可空:N + 意思:输入查找大小 + 参数.三:pSt_PhoneInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输出转换后的信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleDatabase_Phone::ModuleDatabase_Phone_Convert(LPCTSTR lpszPhoneInfo, int nMsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo) +{ + DBModule_IsErrorOccur = FALSE; + + TCHAR tszMsgBuffer[128]; + memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); + memcpy(tszMsgBuffer, lpszPhoneInfo, nMsgLen); + //省 + TCHAR* ptszTokStr = _tcstok(tszMsgBuffer, _T("|")); + if (NULL == ptszTokStr) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_PhoneInfo->tszProvincer, ptszTokStr); + //市区 + ptszTokStr = _tcstok(NULL, _T("|")); + if (NULL == ptszTokStr) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_NOTFOUND; + return FALSE; + } + _tcscpy(pSt_PhoneInfo->tszCity, ptszTokStr); + //邮编 + ptszTokStr = _tcstok(NULL, _T("|")); + if (NULL == ptszTokStr) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_NOTFOUND; + return FALSE; + } + pSt_PhoneInfo->nZipCode = _ttoi(ptszTokStr); + //区号 + ptszTokStr = _tcstok(NULL, _T("|")); + if (NULL == ptszTokStr) + { + DBModule_IsErrorOccur = TRUE; + DBModule_dwErrorCode = ERROR_XENGINE_IPADDR_MODULE_DATABASE_PHONE_NOTFOUND; + return FALSE; + } + pSt_PhoneInfo->nAreaCode = _ttoi(ptszTokStr); + + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_Phone/ModuleDatabase_Phone.h b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_Phone/ModuleDatabase_Phone.h new file mode 100644 index 0000000000000000000000000000000000000000..d5b8f01e4a6cb58f2ccabf6b4597ada8eb0af566 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/ModuleDatabase_Phone/ModuleDatabase_Phone.h @@ -0,0 +1,46 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/09 10:30:46 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_Phone\ModuleDatabase_Phone.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleDatabase\ModuleDatabase_Phone +// File Base: ModuleDatabase_Phone +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 电话信息查询 +// History: +*********************************************************************/ +#define XENGINE_APISERVICE_DATABASE_PHONE_BUFFER_SIZE 1024 * 1024 * 10 +#define XENGINE_APISERVICE_DATABASE_PHONE_INDEX_LEN 9 + +typedef struct +{ + BYTE byVersion[4]; + unsigned int nOffset; +}XENGINE_DBPHONEHDR; + +typedef struct +{ + unsigned int nPhone; + unsigned int nOffset; + BYTE byType; +}XENGINE_DBPHONERECORD; + +class CModuleDatabase_Phone +{ +public: + CModuleDatabase_Phone(); + ~CModuleDatabase_Phone(); +public: + BOOL ModuleDatabase_Phone_Init(LPCTSTR lpszSQLFile); + BOOL ModuleDatabase_Phone_Destory(); + BOOL ModuleDatabase_Phone_Query(LPCTSTR lpszPhoneNumber, XENGINE_PHONEINFO* pSt_PhoneInfo); +protected: + BOOL ModuleDatabase_Phone_Convert(LPCTSTR lpszPhoneInfo, int nMsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo); +private: + XENGINE_DBPHONEHDR st_PhoneHdr; +private: + size_t nFLen = 0; + size_t nCount = 0; + TCHAR* ptszMsgBuffer; +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.def b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.def new file mode 100644 index 0000000000000000000000000000000000000000..c1734eed5292d1fb4b284b351a6020547dbb7d6a --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.def @@ -0,0 +1,17 @@ +LIBRARY + +EXPORTS + ModuleDB_GetLastError + + ModuleDatabase_IPInfo_Init + ModuleDatabase_IPInfo_Destory + ModuleDatabase_IPInfo_IPV4Query + ModuleDatabase_IPInfo_IPV6Query + + ModuleDatabase_IDCard_Init + ModuleDatabase_IDCard_Destory + ModuleDatabase_IDCard_QueryRegion + + ModuleDatabase_Phone_Init + ModuleDatabase_Phone_Destory + ModuleDatabase_Phone_Query \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..d2e0d7c07b97040e4a9f78f9487e3f724bdcc4cc --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj @@ -0,0 +1,192 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {140ad4a9-4918-4345-b352-507c345aebe0} + XEngineModuleDatabase + 10.0 + + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + false + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + false + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + + Level3 + true + WIN32;_DEBUG;XENGINEMODULEDATABASE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + XEngine_ModuleDatabase.def + + + + + Level3 + true + true + true + WIN32;NDEBUG;XENGINEMODULEDATABASE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + XEngine_ModuleDatabase.def + + + + + Level3 + true + _DEBUG;XENGINEMODULEDATABASE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + XEngine_ModuleDatabase.def + + + + + Level3 + true + true + true + NDEBUG;XENGINEMODULEDATABASE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + XEngine_ModuleDatabase.def + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj.filters b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..c6c9cd4fd737b0614bbe5b3b8c01d89726b95370 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {266f0adf-8526-49bb-9e70-84ba7e12ad0c} + + + {e9607c40-79f5-4867-862b-fedb12e965c0} + + + {03852075-f646-4a9d-92c9-774dfc0128f1} + + + {6b278ea0-4508-4d95-bd66-45093876c078} + + + {7cff7f4e-9be6-4728-8d7e-465e87a7b9ea} + + + {213c5e28-4b0f-4314-9d6f-cbc412594ca4} + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件\ModuleDatabase_IDCard + + + 头文件\ModuleDatabase_IPInfo + + + 头文件\ModuleDatabase_Phone + + + + + 源文件 + + + 源文件 + + + 源文件\ModuleDatabase_IDCard + + + 源文件\ModuleDatabase_IPInfo + + + 源文件\ModuleDatabase_Phone + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj.user b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/XEngine_ModuleDatabase.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/dllmain.cpp b/XEngine_Source/XEngine_ModuleDatabase/dllmain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..daed8c8f7ac50ca1466016a0529648d18125a7e7 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/XEngine_Source/XEngine_ModuleDatabase/framework.h b/XEngine_Source/XEngine_ModuleDatabase/framework.h new file mode 100644 index 0000000000000000000000000000000000000000..80cbbc9b06a9b0141f92ee19eceaed71328caff4 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/XEngine_Source/XEngine_ModuleDatabase/pch.cpp b/XEngine_Source/XEngine_ModuleDatabase/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ef1ea05b8e5f8149e1ab72ae5415db5d0b6009d --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/pch.cpp @@ -0,0 +1,81 @@ +#include "pch.h" +#include "ModuleDatabase_IDCard/ModuleDatabase_IDCard.h" +#include "ModuleDatabase_IPInfo/ModuleDatabase_IPInfo.h" +#include "ModuleDatabase_Phone/ModuleDatabase_Phone.h" +/******************************************************************** +// Created: 2022/02/28 13:26:15 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase\pch.cpp +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase +// File Base: pch +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出函数实现 +// History: +*********************************************************************/ +DWORD DBModule_IsErrorOccur = FALSE; +BOOL DBModule_dwErrorCode = 0; +////////////////////////////////////////////////////////////////////////// +CModuleDatabase_IPInfo m_IPAddr; +CModuleDatabase_IDCard m_IDCard; +CModuleDatabase_Phone m_Phone; +////////////////////////////////////////////////////////////////////////// +/// 导出的函数 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleDB_GetLastError(int* pInt_SysError) +{ + if (NULL != pInt_SysError) + { + *pInt_SysError = errno; + } + return DBModule_dwErrorCode; +} +/************************************************************************/ +/* 导出的IP地址操作函数 */ +/************************************************************************/ +extern "C" BOOL ModuleDatabase_IPInfo_Init(LPCTSTR lpszSQLFile) +{ + return m_IPAddr.ModuleDatabase_IPInfo_Init(lpszSQLFile); +} +extern "C" BOOL ModuleDatabase_IPInfo_Destory() +{ + return m_IPAddr.ModuleDatabase_IPInfo_Destory(); +} +extern "C" BOOL ModuleDatabase_IPInfo_IPV4Query(XENGINE_IPADDRINFO * pSt_IPAddrInfo, LPCTSTR lpszIPAddr) +{ + return m_IPAddr.ModuleDatabase_IPInfo_IPV4Query(pSt_IPAddrInfo, lpszIPAddr); +} +extern "C" BOOL ModuleDatabase_IPInfo_IPV6Query(XENGINE_IPADDRINFO * pSt_IPAddrInfo, LPCTSTR lpszIPAddr) +{ + return m_IPAddr.ModuleDatabase_IPInfo_IPV6Query(pSt_IPAddrInfo, lpszIPAddr); +} +/************************************************************************/ +/* 导出的身份证地址操作函数 */ +/************************************************************************/ +extern "C" BOOL ModuleDatabase_IDCard_Init(LPCTSTR lpszSQLFile) +{ + return m_IDCard.ModuleDatabase_IDCard_Init(lpszSQLFile); +} +extern "C" BOOL ModuleDatabase_IDCard_Destory() +{ + return m_IDCard.ModuleDatabase_IDCard_Destory(); +} +extern "C" BOOL ModuleDatabase_IDCard_QueryRegion(XENGINE_IDREGION * pSt_IDRegion, XENGINE_IDCARDINFO * pSt_IDInfo) +{ + return m_IDCard.ModuleDatabase_IDCard_QueryRegion(pSt_IDRegion, pSt_IDInfo); +} +/************************************************************************/ +/* 导出的电话号码信息函数 */ +/************************************************************************/ +extern "C" BOOL ModuleDatabase_Phone_Init(LPCTSTR lpszSQLFile) +{ + return m_Phone.ModuleDatabase_Phone_Init(lpszSQLFile); +} +extern "C" BOOL ModuleDatabase_Phone_Destory() +{ + return m_Phone.ModuleDatabase_Phone_Destory(); +} +extern "C" BOOL ModuleDatabase_Phone_Query(LPCTSTR lpszPhoneNumber, XENGINE_PHONEINFO * pSt_PhoneInfo) +{ + return m_Phone.ModuleDatabase_Phone_Query(lpszPhoneNumber, pSt_PhoneInfo); +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleDatabase/pch.h b/XEngine_Source/XEngine_ModuleDatabase/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..b9b7143af94690b69b231dca46c17972f63125a7 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleDatabase/pch.h @@ -0,0 +1,53 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +#ifdef _MSC_BUILD +// 添加要在此处预编译的标头 +#include "framework.h" +#include +#include +#else +#include +#endif +#endif //PCH_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../XEngine_UserProtocol.h" +#include "ModuleDB_Define.h" +#include "ModuleDB_Error.h" +/******************************************************************** +// Created: 2022/02/28 10:16:47 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase\pch.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleDatabase +// File Base: pch +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: +// History: +*********************************************************************/ +extern DWORD DBModule_IsErrorOccur; +extern BOOL DBModule_dwErrorCode; + +#ifdef _MSC_BUILD +#pragma comment(lib,"Ws2_32") +#pragma comment(lib,"XEngine_BaseLib/XEngine_BaseLib") +#pragma comment(lib,"XEngine_HelpComponents/HelpComponents_DataBase") +#endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/Makefile b/XEngine_Source/XEngine_ModuleHelp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9c65f63f4dd002d4066838e32f2d110ba9965d02 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/Makefile @@ -0,0 +1,45 @@ +CC = g++ -Wall -std=c++17 -fPIC +RELEASE = 0 +UNICODE = 0 +INCLUDE = -I ./ +LOADBIN = +LIB = +LIBEX = -static-libgcc -lrt -ldl -lpthread +LOADSO = -Wl,-rpath=./,--disable-new-dtags +LIBINCLUDE = ModuleHelp_IDCard.o pch.o + +ifeq ($(RELEASE),1) +FLAGS = -c -O2 +DEBUG = +else +FLAGS = -c -lc_p +DEBUG = -g -pg +endif + +ifeq ($(UNICODE),1) +UNICODE = -D _UNICODE +else +UNICODE = +endif + + +all:$(LIBINCLUDE) + $(CC) $(DEBUG) $(LIBINCLUDE) -o libXEngine_ModuleHelp.so -shared -fPIC $(LOADBIN) $(LIB) $(LIBEX) $(LOADSO) + +ModuleHelp_IDCard.o:./ModuleHelp_IDCard/ModuleHelp_IDCard.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleHelp_IDCard/ModuleHelp_IDCard.cpp + +pch.o:./pch.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./pch.cpp + + +InstallAll:InstallSo +InstallSo:./libXEngine_ModuleHelp.so + cp ./libXEngine_ModuleHelp.so ../../XEngine_Release/libXEngine_ModuleHelp.so + + +CleanAll:CleanObj CleanMk +CleanObj: + rm *.o +CleanMk: + rm *.so \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_Define.h b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_Define.h new file mode 100644 index 0000000000000000000000000000000000000000..b654b7470583b887a705a377e187733a60e6f112 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_Define.h @@ -0,0 +1,47 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/04 13:37:09 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_Define.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp +// File Base: ModuleHelp_Define +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出帮助模块定义 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +/// 导出的函数 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleHelp_GetLastError(int *pInt_SysError = NULL); +/************************************************************************/ +/* 导出的身份证帮助函数 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleHelp_IDCard_CheckBirth +函数功能:检查身份证号生日 + 参数.一:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要检查的身份结构 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleHelp_IDCard_CheckBirth(XENGINE_IDCARDINFO* pSt_IDInfo); +/******************************************************************** +函数名称:ModuleHelp_IDCard_CheckBirth +函数功能:检查身份证的校验码是否正确 + 参数.一:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要检查的身份结构 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleHelp_IDCard_CheckSum(XENGINE_IDCARDINFO* pSt_IDInfo); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_Error.h b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_Error.h new file mode 100644 index 0000000000000000000000000000000000000000..de982e64bb4d0d82a9bb9d8715b9d040c08ea817 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_Error.h @@ -0,0 +1,18 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/04 13:33:35 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_Error.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp +// File Base: ModuleHelp_Error +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出的错误 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +// 导出的身份证错误 +////////////////////////////////////////////////////////////////////////// +#define ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_PARAMENT 0xD0001 //参数错误 +#define ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_FMT 0xD0002 //格式错误 +#define ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_SUM 0xD0003 //校验码错误 \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_IDCard/ModuleHelp_IDCard.cpp b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_IDCard/ModuleHelp_IDCard.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5fc306e87464a86a4d20c03f0e8a2554440e84f --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_IDCard/ModuleHelp_IDCard.cpp @@ -0,0 +1,111 @@ +#include "pch.h" +#include "ModuleHelp_IDCard.h" +/******************************************************************** +// Created: 2022/03/03 13:59:47 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_IDCard\ModuleHelp_IDCard.cpp +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_IDCard +// File Base: ModuleHelp_IDCard +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 身份证处理 +// History: +*********************************************************************/ +CModuleHelp_IDCard::CModuleHelp_IDCard() +{ +} +CModuleHelp_IDCard::~CModuleHelp_IDCard() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公有函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleHelp_IDCard_CheckBirth +函数功能:检查身份证号生日 + 参数.一:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要检查的身份结构 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleHelp_IDCard::ModuleHelp_IDCard_CheckBirth(XENGINE_IDCARDINFO *pSt_IDInfo) +{ + ModuleHelp_IsErrorOccur = FALSE; + + if (NULL == pSt_IDInfo) + { + ModuleHelp_IsErrorOccur = TRUE; + ModuleHelp_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_PARAMENT; + return FALSE; + } + if (pSt_IDInfo->nBirthYear < 1949 || pSt_IDInfo->nBirthYear > 2999) + { + ModuleHelp_IsErrorOccur = TRUE; + ModuleHelp_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_FMT; + return FALSE; + } + if (pSt_IDInfo->nBirthMonth < 1 || pSt_IDInfo->nBirthMonth > 12) + { + ModuleHelp_IsErrorOccur = TRUE; + ModuleHelp_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_FMT; + return FALSE; + } + if (pSt_IDInfo->nBirthDay < 1 || pSt_IDInfo->nBirthDay > 31) + { + ModuleHelp_IsErrorOccur = TRUE; + ModuleHelp_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_FMT; + return FALSE; + } + return TRUE; +} +/******************************************************************** +函数名称:ModuleHelp_IDCard_CheckBirth +函数功能:检查身份证的校验码是否正确 + 参数.一:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要检查的身份结构 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleHelp_IDCard::ModuleHelp_IDCard_CheckSum(XENGINE_IDCARDINFO* pSt_IDInfo) +{ + ModuleHelp_IsErrorOccur = FALSE; + + if (NULL == pSt_IDInfo) + { + ModuleHelp_IsErrorOccur = TRUE; + ModuleHelp_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_PARAMENT; + return FALSE; + } + int nCheck = 0; + int nIDArray[18]; + const int nFactor[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; //加权因子 + const int nTable[] = { 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 }; //校验值对应表 + //转换字符为整数 + for (int i = 0; i < 18; i++) + { + nIDArray[i] = pSt_IDInfo->tszIDNumber[i] - 48; + } + //计算校验码 + for (int i = 0; i < 17; i++) + { + nCheck += nIDArray[i] * nFactor[i]; + } + if ((nIDArray[17] != nTable[nCheck % 11]) && (pSt_IDInfo->nCheck != 'x' || nTable[nCheck % 11] != 2)) + { + ModuleHelp_IsErrorOccur = TRUE; + ModuleHelp_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_HELP_IDCARD_SUM; + return FALSE; + } + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_IDCard/ModuleHelp_IDCard.h b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_IDCard/ModuleHelp_IDCard.h new file mode 100644 index 0000000000000000000000000000000000000000..a06d7c3115cb6e40882e7520a332484e063f3288 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/ModuleHelp_IDCard/ModuleHelp_IDCard.h @@ -0,0 +1,24 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/03 13:59:35 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_IDCard\ModuleHelp_IDCard.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_IDCard +// File Base: ModuleHelp_IDCard +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 身份证处理 +// History: +*********************************************************************/ + + +class CModuleHelp_IDCard +{ +public: + CModuleHelp_IDCard(); + ~CModuleHelp_IDCard(); +public: + BOOL ModuleHelp_IDCard_CheckBirth(XENGINE_IDCARDINFO* pSt_IDInfo); + BOOL ModuleHelp_IDCard_CheckSum(XENGINE_IDCARDINFO* pSt_IDInfo); +private: +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.def b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.def new file mode 100644 index 0000000000000000000000000000000000000000..4739c418cde77b456317ffb7e42b268dc9d10481 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.def @@ -0,0 +1,7 @@ +LIBRARY + +EXPORTS + ModuleHelp_GetLastError + + ModuleHelp_IDCard_CheckBirth + ModuleHelp_IDCard_CheckSum \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..bdc42615d432f2a3189b80968bf221805c6c048f --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {6d0fcb40-d544-4ab2-a239-2febc4b98f6d} + XEngineModuleHelp + 10.0 + + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(XEngine_Include);$(IncludePath) + + + false + $(XEngine_Include);$(IncludePath) + + + true + $(XEngine_Include);$(IncludePath) + + + false + $(XEngine_Include);$(IncludePath) + + + + Level3 + true + WIN32;_DEBUG;XENGINEMODULEHELP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + XEngine_ModuleHelp.def + + + + + Level3 + true + true + true + WIN32;NDEBUG;XENGINEMODULEHELP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + XEngine_ModuleHelp.def + + + + + Level3 + true + _DEBUG;XENGINEMODULEHELP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + XEngine_ModuleHelp.def + + + + + Level3 + true + true + true + NDEBUG;XENGINEMODULEHELP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + XEngine_ModuleHelp.def + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj.filters b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..b40f5fbe9baceaa951c2d43b9c2ac0a1ae950eb6 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {6513688b-b2b5-4446-9744-a0467baa83f9} + + + {e4739b45-7ee9-486e-9bb7-a2d299bf5d47} + + + + + 头文件 + + + 头文件 + + + 头文件\ModuleHelp_IDCard + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件\ModuleHelp_IDCard + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj.user b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/XEngine_ModuleHelp.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/dllmain.cpp b/XEngine_Source/XEngine_ModuleHelp/dllmain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..daed8c8f7ac50ca1466016a0529648d18125a7e7 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/XEngine_Source/XEngine_ModuleHelp/framework.h b/XEngine_Source/XEngine_ModuleHelp/framework.h new file mode 100644 index 0000000000000000000000000000000000000000..80cbbc9b06a9b0141f92ee19eceaed71328caff4 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/XEngine_Source/XEngine_ModuleHelp/pch.cpp b/XEngine_Source/XEngine_ModuleHelp/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0a253cf2df0f20907150ca8e2400b5ee4a57c7f --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/pch.cpp @@ -0,0 +1,39 @@ +#include "pch.h" +#include "ModuleHelp_IDCard/ModuleHelp_IDCard.h" +/******************************************************************** +// Created: 2022/03/04 13:37:38 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\pch.cpp +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp +// File Base: pch +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出函数实现 +// History: +*********************************************************************/ +BOOL ModuleHelp_IsErrorOccur = FALSE; +DWORD ModuleHelp_dwErrorCode = 0; +////////////////////////////////////////////////////////////////////////// +CModuleHelp_IDCard m_IDCard; +////////////////////////////////////////////////////////////////////////// +/// 导出的函数 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleHelp_GetLastError(int* pInt_SysError) +{ + if (NULL != pInt_SysError) + { + *pInt_SysError = errno; + } + return ModuleHelp_dwErrorCode; +} +/************************************************************************/ +/* 导出的身份证帮助函数 */ +/************************************************************************/ +extern "C" BOOL ModuleHelp_IDCard_CheckBirth(XENGINE_IDCARDINFO * pSt_IDInfo) +{ + return m_IDCard.ModuleHelp_IDCard_CheckBirth(pSt_IDInfo); +} +extern "C" BOOL ModuleHelp_IDCard_CheckSum(XENGINE_IDCARDINFO * pSt_IDInfo) +{ + return m_IDCard.ModuleHelp_IDCard_CheckSum(pSt_IDInfo); +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleHelp/pch.h b/XEngine_Source/XEngine_ModuleHelp/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..65870ce32bf72b35cee1f58196cfe2ffcdb09a14 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleHelp/pch.h @@ -0,0 +1,34 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +#ifdef _MSC_BUILD +// 添加要在此处预编译的标头 +#include "framework.h" +#endif +#endif //PCH_H +#include +#include +#include +#include +#include "../XEngine_UserProtocol.h" +#include "ModuleHelp_Define.h" +#include "ModuleHelp_Error.h" +/******************************************************************** +// Created: 2022/03/03 14:01:50 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp\pch.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleHelp +// File Base: pch +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 公用头文件 +// History: +*********************************************************************/ +extern BOOL ModuleHelp_IsErrorOccur; +extern DWORD ModuleHelp_dwErrorCode; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/Makefile b/XEngine_Source/XEngine_ModuleProtocol/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ac684ade0d12102f0d7ff4f178b83d1dfad23bbf --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/Makefile @@ -0,0 +1,47 @@ +CC = g++ -Wall -std=c++17 -fPIC +RELEASE = 0 +UNICODE = 0 +INCLUDE = -I ./ -I ../XEngine_ThirdPart/jsoncpp +LOADBIN = -L ../XEngine_ThirdPart/jsoncpp +LIB = -ljsoncpp +LIBEX = -static-libgcc -lrt -ldl -lpthread +LOADSO = -Wl,-rpath=./,--disable-new-dtags +LIBINCLUDE = ModuleProtocol_Packet.o ModuleProtocol_Parse.o pch.o + +ifeq ($(RELEASE),1) +FLAGS = -c -O2 +DEBUG = +else +FLAGS = -c -lc_p +DEBUG = -g -pg +endif + +ifeq ($(UNICODE),1) +UNICODE = -D _UNICODE +else +UNICODE = +endif + + +all:$(LIBINCLUDE) + $(CC) $(DEBUG) $(LIBINCLUDE) -o libXEngine_ModuleProtocol.so -shared -fPIC $(LOADBIN) $(LIB) $(LIBEX) $(LOADSO) + +ModuleProtocol_Packet.o:./ModuleProtocol_Packet/ModuleProtocol_Packet.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleProtocol_Packet/ModuleProtocol_Packet.cpp +ModuleProtocol_Parse.o:./ModuleProtocol_Parse/ModuleProtocol_Parse.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./ModuleProtocol_Parse/ModuleProtocol_Parse.cpp + +pch.o:./pch.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) ./pch.cpp + + +InstallAll:InstallSo +InstallSo:./libXEngine_ModuleProtocol.so + cp ./libXEngine_ModuleProtocol.so ../../XEngine_Release/libXEngine_ModuleProtocol.so + + +CleanAll:CleanObj CleanMk +CleanObj: + rm *.o +CleanMk: + rm *.so \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h new file mode 100644 index 0000000000000000000000000000000000000000..aa74b44f07631331927d717e0c2792221673705c --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h @@ -0,0 +1,240 @@ +#pragma once +/******************************************************************** +// Created: 2022/02/28 14:21:45 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Define.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol +// File Base: ModuleProtocol_Define +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出协议模块定义 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +/// 导出的函数 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleProtocol_GetLastError(int *pInt_SysError = NULL); +/************************************************************************/ +/* 导出的协议打包函数 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleProtocol_Packet_IPQuery +函数功能:IP地址查询打包协议 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IPAddrInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要操作的IP地址信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 + 参数.五:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:Y + 意思:输入操作结果 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_IPQuery(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO * pSt_IPAddrInfo, int nCode = 0, LPCTSTR lpszMsgBuffer = NULL); +/******************************************************************** +函数名称:ModuleProtocol_Packet_IPQuery2 +函数功能:IP查询打包函数另一种方式 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IPAddrInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要操作的IP地址信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_IPQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO* pSt_IPAddrInfo, int nCode = 0); +/******************************************************************** +函数名称:ModuleProtocol_Packet_IDQuery +函数功能:ID查询打包为JSON的封包函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的ID信息 + 参数.四:pSt_IDRegion + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入ID地址信息 + 参数.五:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 + 参数.六:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:Y + 意思:输入操作结果 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_IDQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO* pSt_IDInfo, XENGINE_IDREGION* pSt_IDRegion, int nCode = 0, LPCTSTR lpszMsgBuffer = NULL); +/******************************************************************** +函数名称:ModuleProtocol_Packet_IDQuery2 +函数功能:ID查询打包为字符串流函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的ID信息 + 参数.四:pSt_IDRegion + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入ID地址信息 + 参数.五:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_IDQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO* pSt_IDInfo, XENGINE_IDREGION* pSt_IDRegion, int nCode = 0); +/******************************************************************** +函数名称:ModuleProtocol_Packet_PhoneQuery +函数功能:电话信息查询打包为JSON的封包函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_PhoneInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 + 参数.五:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:Y + 意思:输入操作结果 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_PhoneQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo, int nCode = 0, LPCTSTR lpszMsgBuffer = NULL); +/******************************************************************** +函数名称:ModuleProtocol_Packet_PhoneQuery2 +函数功能:电话查询打包为字符串流函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_PhoneInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_PhoneQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo, int nCode = 0); +/************************************************************************/ +/* 导出的协议解析函数 */ +/************************************************************************/ +/******************************************************************** +函数名称:ModuleProtocol_Parse_IDCard +函数功能:ID身份证号码解析 + 参数.一:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要解析的身份证 + 参数.二:pSt_IDInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出ID身份证编码信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" BOOL ModuleProtocol_Parse_IDCard(LPCTSTR lpszMsgBuffer, XENGINE_IDCARDINFO* pSt_IDInfo); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Error.h b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Error.h new file mode 100644 index 0000000000000000000000000000000000000000..7db2d72ced53de4b2a63e31f70416df03a89295d --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Error.h @@ -0,0 +1,22 @@ +#pragma once +/******************************************************************** +// Created: 2022/02/28 14:21:56 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Error.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol +// File Base: ModuleProtocol_Error +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出协议模块错误 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +// 导出的打包错误 +////////////////////////////////////////////////////////////////////////// +#define ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT 0xC0001 //初始化失败.参数错误 +////////////////////////////////////////////////////////////////////////// +// 导出的解析错误 +////////////////////////////////////////////////////////////////////////// +#define ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PARSE_PARAMENT 0xC0001 //初始化失败.参数错误 +#define ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PARSE_LEN 0xC0002 //长度错误 +#define ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PARSE_FMT 0xC0003 //格式错误 \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Packet/ModuleProtocol_Packet.cpp b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Packet/ModuleProtocol_Packet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63a8eb8437e1c710fc3eee595ffb8f3973f94cb5 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Packet/ModuleProtocol_Packet.cpp @@ -0,0 +1,407 @@ +#include "pch.h" +#include "ModuleProtocol_Packet.h" +/******************************************************************** +// Created: 2022/02/28 14:10:32 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Packet\ModuleProtocol_Packet.cpp +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Packet +// File Base: ModuleProtocol_Packet +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 协议打包类 +// History: +*********************************************************************/ +CModuleProtocol_Packet::CModuleProtocol_Packet() +{ +} +CModuleProtocol_Packet::~CModuleProtocol_Packet() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公有函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleProtocol_Packet_IPQuery +函数功能:IP地址查询打包协议 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IPAddrInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要操作的IP地址信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 + 参数.五:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:Y + 意思:输入操作结果 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Packet::ModuleProtocol_Packet_IPQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO* pSt_IPAddrInfo, int nCode /* = 0 */, LPCTSTR lpszMsgBuffer /* = NULL */) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen) || (NULL == pSt_IPAddrInfo)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT; + return FALSE; + } + Json::Value st_JsonRoot; + Json::Value st_JsonObject; + Json::StreamWriterBuilder st_JsonBuilder; + + if (0 == nCode) + { + st_JsonObject["tszIPAddr"] = pSt_IPAddrInfo->tszIPAddr; + st_JsonObject["tszIPStart"] = pSt_IPAddrInfo->tszIPStart; + st_JsonObject["tszIPEnd"] = pSt_IPAddrInfo->tszIPEnd; + st_JsonObject["tszIPCountry"] = pSt_IPAddrInfo->tszIPCountry; + st_JsonObject["tszIPProvince"] = pSt_IPAddrInfo->tszIPProvince; + st_JsonObject["tszIPCity"] = pSt_IPAddrInfo->tszIPCity; + st_JsonObject["tszIPCounty"] = pSt_IPAddrInfo->tszIPCounty; + st_JsonObject["tszIPAddress"] = pSt_IPAddrInfo->tszIPAddress; + st_JsonObject["tszIPISP"] = pSt_IPAddrInfo->tszIPISP; + st_JsonObject["tszIPTime"] = pSt_IPAddrInfo->tszIPTime; + } + + st_JsonRoot["code"] = nCode; + if (NULL == lpszMsgBuffer) + { + st_JsonRoot["msg"] = "success"; + } + else + { + st_JsonRoot["msg"] = lpszMsgBuffer; + } + st_JsonRoot["data"] = st_JsonObject; + st_JsonBuilder["emitUTF8"] = true; + + *pInt_MsgLen = Json::writeString(st_JsonBuilder, st_JsonRoot).length(); + memcpy(ptszMsgBuffer, Json::writeString(st_JsonBuilder, st_JsonRoot).c_str(), *pInt_MsgLen); + return TRUE; +} +/******************************************************************** +函数名称:ModuleProtocol_Packet_IPQuery2 +函数功能:IP查询打包函数另一种方式 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IPAddrInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要操作的IP地址信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Packet::ModuleProtocol_Packet_IPQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO* pSt_IPAddrInfo, int nCode /* = 0 */) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen) || (NULL == pSt_IPAddrInfo)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT; + return FALSE; + } + *pInt_MsgLen = _stprintf(ptszMsgBuffer, "%d\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s\r\n" + "%s", nCode, pSt_IPAddrInfo->tszIPAddr, pSt_IPAddrInfo->tszIPStart, pSt_IPAddrInfo->tszIPEnd, pSt_IPAddrInfo->tszIPCountry, pSt_IPAddrInfo->tszIPProvince, pSt_IPAddrInfo->tszIPCity, pSt_IPAddrInfo->tszIPCounty, pSt_IPAddrInfo->tszIPAddress, pSt_IPAddrInfo->tszIPISP, pSt_IPAddrInfo->tszIPTime); + return TRUE; +} +/******************************************************************** +函数名称:ModuleProtocol_Packet_IDQuery +函数功能:ID查询打包为JSON的封包函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的ID信息 + 参数.四:pSt_IDRegion + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入ID地址信息 + 参数.五:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 + 参数.六:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:Y + 意思:输入操作结果 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Packet::ModuleProtocol_Packet_IDQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO* pSt_IDInfo, XENGINE_IDREGION* pSt_IDRegion, int nCode /* = 0 */, LPCTSTR lpszMsgBuffer /* = NULL */) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT; + return FALSE; + } + Json::Value st_JsonRoot; + Json::Value st_JsonObject; + Json::StreamWriterBuilder st_JsonBuilder; + + if (0 == nCode) + { + st_JsonObject["tszIDNumber"] = pSt_IDInfo->tszIDNumber; + st_JsonObject["nBirthYear"] = pSt_IDInfo->nBirthYear; + st_JsonObject["nBirthMonth"] = pSt_IDInfo->nBirthMonth; + st_JsonObject["nBirthDay"] = pSt_IDInfo->nBirthDay; + st_JsonObject["nPoliceID"] = pSt_IDInfo->nPoliceID; + st_JsonObject["nSex"] = pSt_IDInfo->nSex / 2 == 0 ? 0 : 1; + st_JsonObject["nCheck"] = pSt_IDInfo->nCheck; + + st_JsonObject["tszProvincer"] = pSt_IDRegion->tszProvincer; + st_JsonObject["tszCity"] = pSt_IDRegion->tszCity; + st_JsonObject["tszCounty"] = pSt_IDRegion->tszCounty; + } + + st_JsonRoot["code"] = nCode; + if (NULL == lpszMsgBuffer) + { + st_JsonRoot["msg"] = "success"; + } + else + { + st_JsonRoot["msg"] = lpszMsgBuffer; + } + st_JsonRoot["data"] = st_JsonObject; + st_JsonBuilder["emitUTF8"] = true; + + *pInt_MsgLen = Json::writeString(st_JsonBuilder, st_JsonRoot).length(); + memcpy(ptszMsgBuffer, Json::writeString(st_JsonBuilder, st_JsonRoot).c_str(), *pInt_MsgLen); + return TRUE; +} +/******************************************************************** +函数名称:ModuleProtocol_Packet_IDQuery2 +函数功能:ID查询打包为字符串流函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_IDInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的ID信息 + 参数.四:pSt_IDRegion + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入ID地址信息 + 参数.五:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Packet::ModuleProtocol_Packet_IDQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO* pSt_IDInfo, XENGINE_IDREGION* pSt_IDRegion, int nCode /* = 0 */) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT; + return FALSE; + } + *pInt_MsgLen = _stprintf(ptszMsgBuffer, "%d\r\n" + "%s\r\n" + "%d\r\n" + "%d\r\n" + "%d\r\n" + "%d\r\n" + "%d\r\n" + "%s\r\n" + "%s\r\n" + "%s", nCode, pSt_IDInfo->tszIDNumber, pSt_IDInfo->nBirthYear, pSt_IDInfo->nBirthMonth, pSt_IDInfo->nBirthDay, pSt_IDInfo->nPoliceID, pSt_IDInfo->nSex / 2 == 0 ? 0 : 1, pSt_IDRegion->tszProvincer, pSt_IDRegion->tszCity, pSt_IDRegion->tszCounty); + return TRUE; +} +/******************************************************************** +函数名称:ModuleProtocol_Packet_PhoneQuery +函数功能:电话信息查询打包为JSON的封包函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_PhoneInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 + 参数.五:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:Y + 意思:输入操作结果 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Packet::ModuleProtocol_Packet_PhoneQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo, int nCode /* = 0 */, LPCTSTR lpszMsgBuffer /* = NULL */) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT; + return FALSE; + } + Json::Value st_JsonRoot; + Json::Value st_JsonObject; + Json::StreamWriterBuilder st_JsonBuilder; + + if (0 == nCode) + { + st_JsonObject["nPhoneNumber"] = (Json::Value::Int64)pSt_PhoneInfo->nPhoneNumber; + st_JsonObject["tszProvincer"] = pSt_PhoneInfo->tszProvincer; + st_JsonObject["tszCity"] = pSt_PhoneInfo->tszCity; + st_JsonObject["nZipCode"] = pSt_PhoneInfo->nZipCode; + st_JsonObject["nAreaCode"] = pSt_PhoneInfo->nAreaCode; + } + + st_JsonRoot["code"] = nCode; + if (NULL == lpszMsgBuffer) + { + st_JsonRoot["msg"] = "success"; + } + else + { + st_JsonRoot["msg"] = lpszMsgBuffer; + } + st_JsonRoot["data"] = st_JsonObject; + st_JsonBuilder["emitUTF8"] = true; + + *pInt_MsgLen = Json::writeString(st_JsonBuilder, st_JsonRoot).length(); + memcpy(ptszMsgBuffer, Json::writeString(st_JsonBuilder, st_JsonRoot).c_str(), *pInt_MsgLen); + return TRUE; +} +/******************************************************************** +函数名称:ModuleProtocol_Packet_PhoneQuery2 +函数功能:电话查询打包为字符串流函数 + 参数.一:ptszMsgBuffer + In/Out:Out + 类型:字符指针 + 可空:N + 意思:输出打包的数据信息 + 参数.二:pInt_MsgLen + In/Out:Out + 类型:整数型指针 + 可空:N + 意思:输出打包大小 + 参数.三:pSt_PhoneInfo + In/Out:In + 类型:数据结构指针 + 可空:N + 意思:输入要打包的信息 + 参数.四:nCode + In/Out:In + 类型:整数型 + 可空:Y + 意思:输入返回的值 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Packet::ModuleProtocol_Packet_PhoneQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo, int nCode /* = 0 */) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PACKET_PARAMENT; + return FALSE; + } + *pInt_MsgLen = _stprintf(ptszMsgBuffer, "%d\r\n" + "%lld\r\n" + "%s\r\n" + "%s\r\n" + "%d\r\n" + "%d", nCode, pSt_PhoneInfo->nPhoneNumber, pSt_PhoneInfo->tszProvincer, pSt_PhoneInfo->tszCity, pSt_PhoneInfo->nZipCode, pSt_PhoneInfo->nAreaCode); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Packet/ModuleProtocol_Packet.h b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Packet/ModuleProtocol_Packet.h new file mode 100644 index 0000000000000000000000000000000000000000..24899da8c7037010c3d5301f6264f9c0f2164b0e --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Packet/ModuleProtocol_Packet.h @@ -0,0 +1,28 @@ +#pragma once +/******************************************************************** +// Created: 2022/02/28 14:10:28 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Packet\ModuleProtocol_Packet.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Packet +// File Base: ModuleProtocol_Packet +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 协议打包类 +// History: +*********************************************************************/ + + +class CModuleProtocol_Packet +{ +public: + CModuleProtocol_Packet(); + ~CModuleProtocol_Packet(); +public: + BOOL ModuleProtocol_Packet_IPQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO* pSt_IPAddrInfo, int nCode = 0, LPCTSTR lpszMsgBuffer = NULL); + BOOL ModuleProtocol_Packet_IPQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO* pSt_IPAddrInfo, int nCode = 0); + BOOL ModuleProtocol_Packet_IDQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO* pSt_IDInfo, XENGINE_IDREGION* pSt_IDRegion, int nCode = 0, LPCTSTR lpszMsgBuffer = NULL); + BOOL ModuleProtocol_Packet_IDQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO* pSt_IDInfo, XENGINE_IDREGION* pSt_IDRegion, int nCode = 0); + BOOL ModuleProtocol_Packet_PhoneQuery(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo, int nCode = 0, LPCTSTR lpszMsgBuffer = NULL); + BOOL ModuleProtocol_Packet_PhoneQuery2(TCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO* pSt_PhoneInfo, int nCode = 0); +private: +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14712f60f57cca14ff9dc56f71aeda7c755929fc --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp @@ -0,0 +1,117 @@ +#include "pch.h" +#include "ModuleProtocol_Parse.h" +/******************************************************************** +// Created: 2022/03/03 11:10:04 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Parse\ModuleProtocol_Parse.cpp +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Parse +// File Base: ModuleProtocol_Parse +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 协议解析类 +// History: +*********************************************************************/ +CModuleProtocol_Parse::CModuleProtocol_Parse() +{ +} +CModuleProtocol_Parse::~CModuleProtocol_Parse() +{ + +} +////////////////////////////////////////////////////////////////////////// +// 公有函数 +////////////////////////////////////////////////////////////////////////// +/******************************************************************** +函数名称:ModuleProtocol_Parse_IDCard +函数功能:ID身份证号码解析 + 参数.一:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要解析的身份证 + 参数.二:pSt_IDInfo + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出ID身份证编码信息 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +BOOL CModuleProtocol_Parse::ModuleProtocol_Parse_IDCard(LPCTSTR lpszMsgBuffer, XENGINE_IDCARDINFO* pSt_IDInfo) +{ + ModuleProtocol_IsErrorOccur = FALSE; + + if ((NULL == lpszMsgBuffer) || (NULL == pSt_IDInfo)) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PARSE_PARAMENT; + return FALSE; + } + if (_tcslen(lpszMsgBuffer) != 18) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PARSE_LEN; + return FALSE; + } + int nPos = 0; + TCHAR tszTmpBuffer[16]; + //是否是身份证号码 + for (int i = 0; i < 17; i++) + { + if (!isdigit(lpszMsgBuffer[i])) + { + ModuleProtocol_IsErrorOccur = TRUE; + ModuleProtocol_dwErrorCode = ERROR_XENGINE_APISERVICE_MODULE_PROTOCOL_PARSE_FMT; + return FALSE; + } + } + _tcscpy(pSt_IDInfo->tszIDNumber, lpszMsgBuffer); + //提取行政区域 + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 2); + pSt_IDInfo->nIDProvince = _ttoi(tszTmpBuffer); + nPos += 2; + + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 2); + pSt_IDInfo->nIDCity = _ttoi(tszTmpBuffer); + nPos += 2; + + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 2); + pSt_IDInfo->nIDCounty = _ttoi(tszTmpBuffer); + nPos += 2; + //提取生日 + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 4); + pSt_IDInfo->nBirthYear = _ttoi(tszTmpBuffer); + nPos += 4; + + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 2); + pSt_IDInfo->nBirthMonth = _ttoi(tszTmpBuffer); + nPos += 2; + + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 2); + pSt_IDInfo->nBirthDay = _ttoi(tszTmpBuffer); + nPos += 2; + //提取派出所编码 + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 2); + pSt_IDInfo->nPoliceID = _ttoi(tszTmpBuffer); + nPos += 2; + //提取性别 + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 1); + pSt_IDInfo->nSex = _ttoi(tszTmpBuffer); + nPos += 1; + //提取校验码 + memset(tszTmpBuffer, '\0', sizeof(tszTmpBuffer)); + memcpy(tszTmpBuffer, lpszMsgBuffer + nPos, 1); + pSt_IDInfo->nCheck = _ttoi(tszTmpBuffer); + nPos += 1; + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h new file mode 100644 index 0000000000000000000000000000000000000000..f643774e03bd011e3182646d4a97e92bb6c1b7f9 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h @@ -0,0 +1,23 @@ +#pragma once +/******************************************************************** +// Created: 2022/03/03 11:09:16 +// File Name: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Parse\ModuleProtocol_Parse.h +// File Path: D:\XEngine_APIService\XEngine_Source\XEngine_ModuleProtocol\ModuleProtocol_Parse +// File Base: ModuleProtocol_Parse +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 协议解析类 +// History: +*********************************************************************/ + + +class CModuleProtocol_Parse +{ +public: + CModuleProtocol_Parse(); + ~CModuleProtocol_Parse(); +public: + BOOL ModuleProtocol_Parse_IDCard(LPCTSTR lpszMsgBuffer, XENGINE_IDCARDINFO* pSt_IDInfo); +private: +}; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def new file mode 100644 index 0000000000000000000000000000000000000000..d0ed386d6fa015800042f19eb932a1ffc6854d63 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def @@ -0,0 +1,13 @@ +LIBRARY + +EXPORTS + ModuleProtocol_GetLastError + + ModuleProtocol_Packet_IPQuery + ModuleProtocol_Packet_IPQuery2 + ModuleProtocol_Packet_IDQuery + ModuleProtocol_Packet_IDQuery2 + ModuleProtocol_Packet_PhoneQuery + ModuleProtocol_Packet_PhoneQuery2 + + ModuleProtocol_Parse_IDCard \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..d4c5a308e27d7d7a55db0020add206f531f748e6 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {6c935be1-77e3-4719-a7a6-c76abafee010} + XEngineModuleProtocol + 10.0 + + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + DynamicLibrary + true + v143 + MultiByte + + + DynamicLibrary + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + false + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + true + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + false + $(XEngine_Include);../XEngine_ThirdPart/jsoncpp;$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + + Level3 + true + WIN32;_DEBUG;XENGINEMODULEPROTOCOL_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + XEngine_ModuleProtocol.def + + + + + Level3 + true + true + true + WIN32;NDEBUG;XENGINEMODULEPROTOCOL_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + XEngine_ModuleProtocol.def + + + + + Level3 + true + _DEBUG;XENGINEMODULEPROTOCOL_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + XEngine_ModuleProtocol.def + + + + + Level3 + true + true + true + NDEBUG;XENGINEMODULEPROTOCOL_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + XEngine_ModuleProtocol.def + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj.filters b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..b76ef79dff7ef06c62a5d11ab7bd40845bd09f06 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj.filters @@ -0,0 +1,68 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {563fda1d-114e-4795-9060-ea9ac18b64e9} + + + {3d2dc46b-019d-43ad-bfd8-b3144ca2f46a} + + + {5b37f3a0-0993-4293-a5c0-badce4297f59} + + + {7c173485-3304-428f-aeb2-f66f5900b793} + + + + + 头文件 + + + 头文件 + + + 头文件\ModuleProtocol_Packet + + + 头文件 + + + 头文件 + + + 头文件\ModuleProtocol_Parse + + + + + 源文件 + + + 源文件 + + + 源文件\ModuleProtocol_Packet + + + 源文件\ModuleProtocol_Parse + + + + + 源文件 + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj.user b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/dllmain.cpp b/XEngine_Source/XEngine_ModuleProtocol/dllmain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..daed8c8f7ac50ca1466016a0529648d18125a7e7 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/XEngine_Source/XEngine_ModuleProtocol/framework.h b/XEngine_Source/XEngine_ModuleProtocol/framework.h new file mode 100644 index 0000000000000000000000000000000000000000..80cbbc9b06a9b0141f92ee19eceaed71328caff4 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/XEngine_Source/XEngine_ModuleProtocol/pch.cpp b/XEngine_Source/XEngine_ModuleProtocol/pch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4587368b164da7903d7eedc8c58ff642a6cc236a --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/pch.cpp @@ -0,0 +1,64 @@ +#include "pch.h" +#include "ModuleProtocol_Packet/ModuleProtocol_Packet.h" +#include "ModuleProtocol_Parse/ModuleProtocol_Parse.h" +/******************************************************************** +// Created: 2022/02/28 14:23:53 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\pch.cpp +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol +// File Base: pch +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 导出协议模块实现 +// History: +*********************************************************************/ +BOOL ModuleProtocol_IsErrorOccur = FALSE; +DWORD ModuleProtocol_dwErrorCode = 0; +////////////////////////////////////////////////////////////////////////// +CModuleProtocol_Packet m_ProtocolPacket; +CModuleProtocol_Parse m_ProtocolParse; +////////////////////////////////////////////////////////////////////////// +/// 导出的函数 +////////////////////////////////////////////////////////////////////////// +extern "C" DWORD ModuleProtocol_GetLastError(int* pInt_SysError) +{ + if (NULL != pInt_SysError) + { + *pInt_SysError = errno; + } + return ModuleProtocol_dwErrorCode; +} +/************************************************************************/ +/* 导出的协议打包函数 */ +/************************************************************************/ +extern "C" BOOL ModuleProtocol_Packet_IPQuery(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO * pSt_IPAddrInfo, int nCode, LPCTSTR lpszMsgBuffer) +{ + return m_ProtocolPacket.ModuleProtocol_Packet_IPQuery(ptszMsgBuffer, pInt_MsgLen, pSt_IPAddrInfo, nCode, lpszMsgBuffer); +} +extern "C" BOOL ModuleProtocol_Packet_IPQuery2(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IPADDRINFO * pSt_IPAddrInfo, int nCode) +{ + return m_ProtocolPacket.ModuleProtocol_Packet_IPQuery2(ptszMsgBuffer, pInt_MsgLen, pSt_IPAddrInfo, nCode); +} +extern "C" BOOL ModuleProtocol_Packet_IDQuery(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO * pSt_IDInfo, XENGINE_IDREGION * pSt_IDRegion, int nCode, LPCTSTR lpszMsgBuffer) +{ + return m_ProtocolPacket.ModuleProtocol_Packet_IDQuery(ptszMsgBuffer, pInt_MsgLen, pSt_IDInfo, pSt_IDRegion, nCode, lpszMsgBuffer); +} +extern "C" BOOL ModuleProtocol_Packet_IDQuery2(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_IDCARDINFO * pSt_IDInfo, XENGINE_IDREGION * pSt_IDRegion, int nCode) +{ + return m_ProtocolPacket.ModuleProtocol_Packet_IDQuery2(ptszMsgBuffer, pInt_MsgLen, pSt_IDInfo, pSt_IDRegion, nCode); +} +extern "C" BOOL ModuleProtocol_Packet_PhoneQuery(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO * pSt_PhoneInfo, int nCode, LPCTSTR lpszMsgBuffer) +{ + return m_ProtocolPacket.ModuleProtocol_Packet_PhoneQuery(ptszMsgBuffer, pInt_MsgLen, pSt_PhoneInfo, nCode, lpszMsgBuffer); +} +extern "C" BOOL ModuleProtocol_Packet_PhoneQuery2(TCHAR * ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PHONEINFO * pSt_PhoneInfo, int nCode) +{ + return m_ProtocolPacket.ModuleProtocol_Packet_PhoneQuery2(ptszMsgBuffer, pInt_MsgLen, pSt_PhoneInfo, nCode); +} +/************************************************************************/ +/* 导出的协议解析函数 */ +/************************************************************************/ +extern "C" BOOL ModuleProtocol_Parse_IDCard(LPCTSTR lpszMsgBuffer, XENGINE_IDCARDINFO * pSt_IDInfo) +{ + return m_ProtocolParse.ModuleProtocol_Parse_IDCard(lpszMsgBuffer, pSt_IDInfo); +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/pch.h b/XEngine_Source/XEngine_ModuleProtocol/pch.h new file mode 100644 index 0000000000000000000000000000000000000000..96ac564785c03cb6567fba86ddddb88aeb0e85f3 --- /dev/null +++ b/XEngine_Source/XEngine_ModuleProtocol/pch.h @@ -0,0 +1,55 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +#ifdef _MSC_BUILD +// 添加要在此处预编译的标头 +#include "framework.h" +#include +#endif +#endif //PCH_H +#include +#include +#include +#include +#include +#include +#include +#include +#include "../XEngine_UserProtocol.h" +#include "ModuleProtocol_Define.h" +#include "ModuleProtocol_Error.h" +/******************************************************************** +// Created: 2022/02/28 14:11:33 +// File Name: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol\pch.h +// File Path: D:\XEngine_IPInfo\XEngine_Source\XEngine_ModuleProtocol +// File Base: pch +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 公用头文件 +// History: +*********************************************************************/ +extern BOOL ModuleProtocol_IsErrorOccur; +extern DWORD ModuleProtocol_dwErrorCode; + +#ifdef _MSC_BUILD +#ifdef _DEBUG +#ifdef _WIN64 +#pragma comment(lib,"../x64/Debug/jsoncpp") +#else +#pragma comment(lib,"../Debug/jsoncpp") +#endif +#else +#ifdef _WIN64 +#pragma comment(lib,"../x64/Release/jsoncpp") +#else +#pragma comment(lib,"../Release/jsoncpp") +#endif +#endif +#endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/Makefile b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b54676c0336fbed08b533d213eacd14de13e3f15 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/Makefile @@ -0,0 +1,54 @@ +CC = g++ -Wall +RELEASE = 0 +UNICODE = 0 +LOADBIN = -L /usr/local/lib/XEngine_Release/XEngine_BaseLib -L /usr/local/lib/XEngine_Release/XEngine_Core -L /usr/local/lib/XEngine_Release/XEngine_HelpComponents -L /usr/local/lib/XEngine_Release/XEngine_RfcComponents -L ../../XEngine_ThirdPart/jsoncpp -L ../../XEngine_ModuleConfigure -L ../../XEngine_ModuleDatabase -L ../../XEngine_ModuleProtocol -L ../../XEngine_ModuleHelp +LIB = -lXEngine_BaseLib -lXEngine_Algorithm -lXEngine_Core -lXEngine_ManagePool -lHelpComponents_XLog -lRfcComponents_HttpServer -ljsoncpp -lXEngine_ModuleConfigure -lXEngine_ModuleDatabase -lXEngine_ModuleProtocol -lXEngine_ModuleHelp +LIBEX = -static-libgcc -ldl -lrt -lpthread +LOADSO = -Wl,-rpath=./,--disable-new-dtags +LIBINCLUDE = XEngine_Configure.o XEngine_Network.o XEngine_HTTPTask.o HTTPTask_IPInfo.o HTTPTask_IDCard.o HTTPTask_Phone.o XEngine_HttpApp.o + +ifeq ($(RELEASE),1) +FLAGS = -c -O2 +DEBUG = +else +FLAGS = -c -lc_p +DEBUG = -g -pg +endif + +ifeq ($(UNICODE),1) +UNICODE = -D _UNICODE +else +UNICODE = +endif + +all:$(LIBINCLUDE) + $(CC) $(DEBUG) $(LIBINCLUDE) -o XEngine_HttpApp $(LOADBIN) $(LIB) $(LIBEX) $(LOADSO) + +XEngine_Configure.o:./XEngine_Configure.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_Configure.cpp +XEngine_Network.o:./XEngine_Network.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_Network.cpp +XEngine_HTTPTask.o:./XEngine_HTTPTask.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_HTTPTask.cpp + +HTTPTask_IPInfo.o:./XEngine_HTTPTask/HTTPTask_IPInfo.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_HTTPTask/HTTPTask_IPInfo.cpp +HTTPTask_IDCard.o:./XEngine_HTTPTask/HTTPTask_IDCard.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_HTTPTask/HTTPTask_IDCard.cpp +HTTPTask_Phone.o:./XEngine_HTTPTask/HTTPTask_Phone.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_HTTPTask/HTTPTask_Phone.cpp + +XEngine_HttpApp.o:./XEngine_HttpApp.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) ./XEngine_HttpApp.cpp + + +InstallAll:InstallApp +InstallApp:./XEngine_HttpApp + cp -f ./XEngine_HttpApp ../../../XEngine_Release/XEngine_HttpApp + +CleanAll:CleanObj CleanMk +CleanObj: + rm *.o +CleanMk: + rm XEngine_HttpApp + diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Configure.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Configure.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e30435034e13cfe73fa97302fc9cd376cbbf4b64 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Configure.cpp @@ -0,0 +1,46 @@ +#include "XEngine_Hdr.h" +/******************************************************************** +// Created: 2022/01/20 14:40:45 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_Configure.cpp +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_Configure +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 配置文件操作代码 +// History: +*********************************************************************/ +BOOL XEngine_Configure_Parament(int argc, char** argv, XENGINE_SERVICECONFIG* pSt_Configure) +{ + LPCTSTR lpszConfigFile = _T("./XEngine_Config/XEngine_Config.json"); + + if (!ModuleConfigure_Json_File(lpszConfigFile, pSt_Configure)) + { + printf("解析配置文件失败,ModuleConfigure_Json_File:%lX\n", ModuleConfigure_GetLastError()); + return FALSE; + } + + for (int i = 0; i < argc; i++) + { + if ((0 == _tcscmp("-h", argv[i])) || (0 == _tcscmp("-H", argv[i]))) + { + XEngine_Configure_Help(); + return FALSE; + } + else if (0 == _tcscmp("-d", argv[i])) + { + pSt_Configure->bDeamon = _ttoi(argv[i + 1]); + } + } + + return TRUE; +} + +void XEngine_Configure_Help() +{ + printf(_T("--------------------------启动参数帮助开始--------------------------\n")); + printf(_T("网络消息队列服务启动参数:程序 参数 参数值,参数是区分大小写的。如果不指定将会加载默认的ini配置文件里面的参数\n")); + printf(_T("-h or -H:启动参数帮助提示信息\n")); + printf(_T("-d:1 启用守护进程,2不启用\n")); + printf(_T("--------------------------启动参数帮助结束--------------------------\n")); +} diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Configure.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Configure.h new file mode 100644 index 0000000000000000000000000000000000000000..e5c853da5d1c569081ac2d3dc3adbd3eb199bf46 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Configure.h @@ -0,0 +1,14 @@ +#pragma once +/******************************************************************** +// Created: 2022/01/20 14:40:37 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_Configure.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_Configure +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 配置文件操作代码 +// History: +*********************************************************************/ +BOOL XEngine_Configure_Parament(int argc, char** argv, XENGINE_SERVICECONFIG* pSt_Configure); +void XEngine_Configure_Help(); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1b9ca2f03e8fb1c69ca8f72f23ea20a9fc5b2f3 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask.cpp @@ -0,0 +1,196 @@ +#include "XEngine_Hdr.h" +/******************************************************************** +// Created: 2022/01/20 14:44:17 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_HTTPTask.cpp +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_HTTPTask +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: HTTP任务处理代码 +// History: +*********************************************************************/ +XHTHREAD CALLBACK XEngine_HTTPTask_Thread(LPVOID lParam) +{ + //任务池是编号1开始的. + int nThreadPos = *(int*)lParam; + nThreadPos++; + + while (bIsRun) + { + //等待编号1的任务池触发一个组完包的事件 + if (!RfcComponents_HttpServer_EventWaitEx(xhHTTPPacket, nThreadPos)) + { + continue; + } + int nListCount = 0; + RFCCOMPONENTS_HTTP_PKTCLIENT** ppSst_ListAddr; + //获得编号1的所有待处理任务的客户端列表(也就是客户端发送过来的数据已经组好了一个包,需要我们处理) + RfcComponents_HttpServer_GetPoolEx(xhHTTPPacket, nThreadPos, &ppSst_ListAddr, &nListCount); + //先循环客户端 + for (int i = 0; i < nListCount; i++) + { + //再循环客户端拥有的任务个数 + for (int j = 0; j < ppSst_ListAddr[i]->nPktCount; j++) + { + int nMsgLen = 0; //客户端发送的数据大小,不包括头 + CHAR* ptszMsgBuffer = NULL; //客户端发送的数据 + RFCCOMPONENTS_HTTP_REQPARAM st_HTTPReqparam; //客户端的请求参数 + + memset(&st_HTTPReqparam, '\0', sizeof(RFCCOMPONENTS_HTTP_REQPARAM)); + //得到一个指定客户端的完整数据包 + if (!RfcComponents_HttpServer_GetMemoryEx(xhHTTPPacket, ppSst_ListAddr[i]->tszClientAddr, &ptszMsgBuffer, &nMsgLen, &st_HTTPReqparam)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("HTTP客户端:%s,获取数据包失败,错误:%lX"), ppSst_ListAddr[i]->tszClientAddr, HttpServer_GetLastError()); + continue; + } + //在另外一个函数里面处理数据 + XEngine_HTTPTask_Handle(&st_HTTPReqparam, ppSst_ListAddr[i]->tszClientAddr, ptszMsgBuffer, nMsgLen); + //释放内存 + BaseLib_OperatorMemory_FreeCStyle((VOID**)&ptszMsgBuffer); + } + } + BaseLib_OperatorMemory_Free((XPPPMEM)&ppSst_ListAddr, nListCount); + } + return 0; +} +BOOL XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCTSTR lpszClientAddr, LPCTSTR lpszRVBuffer, int nRVLen) +{ + int nMsgLen = 4096; + //LPCTSTR lpszMethodPost = _T("POST"); + LPCTSTR lpszMethodGet = _T("GET"); + TCHAR tszMsgBuffer[4096]; + RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam; //发送给客户端的参数 + + memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); + memset(&st_HDRParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM)); + + st_HDRParam.nHttpCode = 200; //HTTP CODE码 + st_HDRParam.bIsClose = TRUE; //收到回复后就关闭 + if (0 == _tcsnicmp(lpszMethodGet, pSt_HTTPParam->tszHttpMethod, _tcslen(lpszMethodGet))) + { + TCHAR** pptszList; + TCHAR tszUrlName[128]; + int nListCount = 0; + + memset(tszUrlName, '\0', sizeof(tszUrlName)); + //得到URL参数个数 + RfcComponents_HttpHelp_GetParament(pSt_HTTPParam->tszHttpUri, &pptszList, &nListCount, tszUrlName); + if (nListCount < 3) + { + st_HDRParam.nHttpCode = 404; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送的URL请求参数不正确:%s"), lpszClientAddr, pSt_HTTPParam->tszHttpUri); + return FALSE; + } + TCHAR tszKey[128]; + TCHAR tszValue[128]; + LPCTSTR lpszFuncName = _T("api"); + LPCTSTR lpszParamFunc1 = _T("function"); + LPCTSTR lpszParamFunc2 = _T("params1"); + LPCTSTR lpszParamValue1 = _T("ipquery"); + LPCTSTR lpszParamValue2 = _T("idquery"); + LPCTSTR lpszParamValue3 = _T("phonequery"); + + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszValue, '\0', sizeof(tszValue)); + + if (0 != _tcsnicmp(lpszFuncName, tszUrlName, _tcslen(lpszFuncName))) + { + st_HDRParam.nHttpCode = 404; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送的URL请求参数不正确:%s"), lpszClientAddr, pSt_HTTPParam->tszHttpUri); + return FALSE; + } + //获得函数名 + BaseLib_OperatorString_GetKeyValue(pptszList[0], "=", tszKey, tszValue); + if (0 != _tcsnicmp(lpszParamFunc1, tszKey, _tcslen(lpszParamFunc1))) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送的URL请求参数不正确:%s"), lpszClientAddr, pSt_HTTPParam->tszHttpUri); + return FALSE; + } + //是不是ip查询 + if (0 == _tcsnicmp(lpszParamValue1, tszValue, _tcslen(lpszParamValue1))) + { + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszValue, '\0', sizeof(tszValue)); + BaseLib_OperatorString_GetKeyValue(pptszList[1], "=", tszKey, tszValue); + if (0 != _tcsnicmp(lpszParamFunc2, tszKey, _tcslen(lpszParamFunc2))) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送的URL请求参数不正确:%s"), lpszClientAddr, pSt_HTTPParam->tszHttpUri); + return FALSE; + } + TCHAR tszGetType[64]; + + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszGetType, '\0', sizeof(tszGetType)); + + BaseLib_OperatorString_GetKeyValue(pptszList[2], "=", tszKey, tszGetType); + XEngine_HTTPTask_IPInfo(lpszClientAddr, tszValue, _ttoi(tszGetType)); + } + else if (0 == _tcsnicmp(lpszParamValue2, tszValue, _tcslen(lpszParamValue2))) + { + //是不是身份证查询 + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszValue, '\0', sizeof(tszValue)); + BaseLib_OperatorString_GetKeyValue(pptszList[1], "=", tszKey, tszValue); + if (0 != _tcsnicmp(lpszParamFunc2, tszKey, _tcslen(lpszParamFunc2))) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送的URL请求参数不正确:%s"), lpszClientAddr, pSt_HTTPParam->tszHttpUri); + return FALSE; + } + TCHAR tszGetType[64]; + + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszGetType, '\0', sizeof(tszGetType)); + + BaseLib_OperatorString_GetKeyValue(pptszList[2], "=", tszKey, tszGetType); + XEngine_HTTPTask_IDCard(lpszClientAddr, tszValue, _ttoi(tszGetType)); + } + else if (0 == _tcsnicmp(lpszParamValue3, tszValue, _tcslen(lpszParamValue3))) + { + //是不是身份证查询 + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszValue, '\0', sizeof(tszValue)); + BaseLib_OperatorString_GetKeyValue(pptszList[1], "=", tszKey, tszValue); + if (0 != _tcsnicmp(lpszParamFunc2, tszKey, _tcslen(lpszParamFunc2))) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送的URL请求参数不正确:%s"), lpszClientAddr, pSt_HTTPParam->tszHttpUri); + return FALSE; + } + TCHAR tszGetType[64]; + + memset(tszKey, '\0', sizeof(tszKey)); + memset(tszGetType, '\0', sizeof(tszGetType)); + + BaseLib_OperatorString_GetKeyValue(pptszList[2], "=", tszKey, tszGetType); + XEngine_HTTPTask_PhoneInfo(lpszClientAddr, tszValue, _ttoi(tszGetType)); + } + BaseLib_OperatorMemory_Free((XPPPMEM)&pptszList, nListCount); + } + else + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _T("HTTP客户端:%s,协议错误"), lpszClientAddr); + } + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask.h new file mode 100644 index 0000000000000000000000000000000000000000..d9c49156ba82f24586f2beecb0a0b4fd3f885640 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask.h @@ -0,0 +1,16 @@ +#pragma once +/******************************************************************** +// Created: 2022/01/20 14:42:44 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_HTTPTask.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_HTTPTask +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: HTTP任务处理代码 +// History: +*********************************************************************/ +//任务处理池,用来获取一个完整包 +XHTHREAD CALLBACK XEngine_HTTPTask_Thread(LPVOID lParam); +//任务处理相关函数,处理包的内容 +BOOL XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCTSTR lpszClientAddr, LPCTSTR lpszRVBuffer, int nRVLen); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IDCard.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IDCard.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3536e24ace720cb8f84f9fefc84ebea26b0f7676 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IDCard.cpp @@ -0,0 +1,60 @@ +#include "../XEngine_Hdr.h" + +BOOL XEngine_HTTPTask_IDCard(LPCTSTR lpszClientAddr, LPCTSTR lpszMsgBuffer, int nType) +{ + int nMsgLen = 4096; + int nPktLen = 4096; + TCHAR tszMsgBuffer[4096]; + TCHAR tszPktBuffer[4096]; + XENGINE_IDREGION st_IDRegion; + XENGINE_IDCARDINFO st_IDCardInfo; + RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam; //发送给客户端的参数 + + memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); + memset(tszPktBuffer, '\0', sizeof(tszPktBuffer)); + memset(&st_IDRegion, '\0', sizeof(XENGINE_IDREGION)); + memset(&st_IDCardInfo, '\0', sizeof(XENGINE_IDCARDINFO)); + memset(&st_HDRParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM)); + + st_HDRParam.nHttpCode = 200; //HTTP CODE码 + st_HDRParam.bIsClose = TRUE; //收到回复后就关闭 + + if (!ModuleProtocol_Parse_IDCard(lpszMsgBuffer, &st_IDCardInfo)) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,请求的身份证编号不正确:%s"), lpszClientAddr, lpszMsgBuffer); + return FALSE; + } + //验证身份证是否正确 + if (!ModuleHelp_IDCard_CheckBirth(&st_IDCardInfo)) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,请求的身份证验证生日失败:%s"), lpszClientAddr, lpszMsgBuffer); + return FALSE; + } + if (!ModuleHelp_IDCard_CheckSum(&st_IDCardInfo)) + { + st_HDRParam.nHttpCode = 406; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,请求的身份证验证校验码失败:%s"), lpszClientAddr, lpszMsgBuffer); + return FALSE; + } + ModuleDatabase_IDCard_QueryRegion(&st_IDRegion, &st_IDCardInfo); + if (0 == nType) + { + ModuleProtocol_Packet_IDQuery(tszPktBuffer, &nPktLen, &st_IDCardInfo, &st_IDRegion); + } + else + { + ModuleProtocol_Packet_IDQuery2(tszPktBuffer, &nPktLen, &st_IDCardInfo, &st_IDRegion); + } + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam, tszPktBuffer, nPktLen); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,请求身份证号码验证与信息查询成功,号码:%s"), lpszClientAddr, lpszMsgBuffer); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IDCard.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IDCard.h new file mode 100644 index 0000000000000000000000000000000000000000..ba0cbecf93baab1f07da3dd79f14c4845f62a9e3 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IDCard.h @@ -0,0 +1,3 @@ +#pragma once + +BOOL XEngine_HTTPTask_IDCard(LPCTSTR lpszClientAddr, LPCTSTR lpszMsgBuffer, int nType); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IPInfo.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IPInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e92aaa6c681d0318d0e7d0ebb78f58943350dee --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IPInfo.cpp @@ -0,0 +1,59 @@ +#include "../XEngine_Hdr.h" + + +BOOL XEngine_HTTPTask_IPInfo(LPCTSTR lpszClientAddr, LPCTSTR lpszIPAddr, int nType) +{ + int nMsgLen = 4096; + int nPktLen = 4096; + TCHAR tszMsgBuffer[4096]; + TCHAR tszPktBuffer[4096]; + XENGINE_IPADDRINFO st_IPAddrInfo; + RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam; //发送给客户端的参数 + + memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); + memset(tszPktBuffer, '\0', sizeof(tszPktBuffer)); + memset(&st_IPAddrInfo, '\0', sizeof(XENGINE_IPADDRINFO)); + memset(&st_HDRParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM)); + + st_HDRParam.nHttpCode = 200; //HTTP CODE码 + st_HDRParam.bIsClose = TRUE; //收到回复后就关闭 + int nIPVer = 0; + BaseLib_OperatorIPAddr_GetIPVer(lpszIPAddr, &nIPVer); + + if (AF_INET == nIPVer) + { + if (!ModuleDatabase_IPInfo_IPV4Query(&st_IPAddrInfo, lpszIPAddr)) + { + st_HDRParam.nHttpCode = 404; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,请求的IP地址不正确:%s"), lpszClientAddr, lpszIPAddr); + return FALSE; + } + } + else + { + if (!ModuleDatabase_IPInfo_IPV6Query(&st_IPAddrInfo, lpszIPAddr)) + { + st_HDRParam.nHttpCode = 404; + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,请求的IP地址不正确:%s"), lpszClientAddr, lpszIPAddr); + return FALSE; + } + } + //通过此函数来打包成我们要发送的数据,就是打包成一条标准的HTTP协议 + if (0 == nType) + { + ModuleProtocol_Packet_IPQuery(tszPktBuffer, &nPktLen, &st_IPAddrInfo); + } + else + { + ModuleProtocol_Packet_IPQuery2(tszPktBuffer, &nPktLen, &st_IPAddrInfo); + } + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam, tszPktBuffer, nPktLen); + //打包完毕后才能发送给客户端 + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送IP地址信息获取请求给服务器,查询地址:%s"), lpszClientAddr, lpszIPAddr); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IPInfo.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IPInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..127cdbd77a54fe6117d80f90fff1c250da6bd734 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_IPInfo.h @@ -0,0 +1,3 @@ +#pragma once + +BOOL XEngine_HTTPTask_IPInfo(LPCTSTR lpszClientAddr, LPCTSTR lpszIPAddr, int nType); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_Phone.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_Phone.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8eee18a34836e9336d9d4be4e97472118407c64f --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_Phone.cpp @@ -0,0 +1,36 @@ +#include "../XEngine_Hdr.h" + + +BOOL XEngine_HTTPTask_PhoneInfo(LPCTSTR lpszClientAddr, LPCTSTR lpszPhoneNumber, int nType) +{ + int nMsgLen = 4096; + int nPktLen = 4096; + TCHAR tszMsgBuffer[4096]; + TCHAR tszPktBuffer[4096]; + XENGINE_PHONEINFO st_PhoneInfo; + RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam; //发送给客户端的参数 + + memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); + memset(tszPktBuffer, '\0', sizeof(tszPktBuffer)); + memset(&st_PhoneInfo, '\0', sizeof(XENGINE_PHONEINFO)); + memset(&st_HDRParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM)); + + st_HDRParam.nHttpCode = 200; //HTTP CODE码 + st_HDRParam.bIsClose = TRUE; //收到回复后就关闭 + + st_PhoneInfo.nPhoneNumber = _ttoi64(lpszPhoneNumber); + ModuleDatabase_Phone_Query(lpszPhoneNumber, &st_PhoneInfo); + //打包发送 + if (0 == nType) + { + ModuleProtocol_Packet_PhoneQuery(tszPktBuffer, &nPktLen, &st_PhoneInfo); + } + else + { + ModuleProtocol_Packet_PhoneQuery2(tszPktBuffer, &nPktLen, &st_PhoneInfo); + } + RfcComponents_HttpServer_SendMsgEx(xhHTTPPacket, tszMsgBuffer, &nMsgLen, &st_HDRParam, tszPktBuffer, nPktLen); + XEngine_Network_Send(lpszClientAddr, tszMsgBuffer, nMsgLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,发送电话信息获取请求给服务器,查询号码:%s"), lpszClientAddr, lpszPhoneNumber); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_Phone.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_Phone.h new file mode 100644 index 0000000000000000000000000000000000000000..9a25ff53b11b703f1e6ee7a018b3bd762b8e0a04 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HTTPTask/HTTPTask_Phone.h @@ -0,0 +1,3 @@ +#pragma once + +BOOL XEngine_HTTPTask_PhoneInfo(LPCTSTR lpszClientAddr, LPCTSTR lpszPhoneNumber, int nType); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Hdr.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Hdr.h new file mode 100644 index 0000000000000000000000000000000000000000..c0e9800a0c22dd2b0a813e2f0b259c6c9808682d --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Hdr.h @@ -0,0 +1,108 @@ +#pragma once +//加载系统头文件 +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WINDOWS +#include +#include +#else +#include +#include +#include +#include +#endif +using namespace std; +//加载XEngine头文件 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//加载项目相关头文件 +#include "../../XEngine_UserProtocol.h" +#include "../../XEngine_ModuleConfigure/ModuleConfig_Define.h" +#include "../../XEngine_ModuleConfigure/ModuleConfig_Error.h" +#include "../../XEngine_ModuleDatabase/ModuleDB_Define.h" +#include "../../XEngine_ModuleDatabase/ModuleDB_Error.h" +#include "../../XEngine_ModuleProtocol/ModuleProtocol_Define.h" +#include "../../XEngine_ModuleProtocol/ModuleProtocol_Error.h" +#include "../../XEngine_ModuleHelp/ModuleHelp_Define.h" +#include "../../XEngine_ModuleHelp/ModuleHelp_Error.h" +//加载自己的头文件 +#include "XEngine_Configure.h" +#include "XEngine_Network.h" +#include "XEngine_HTTPTask.h" +#include "XEngine_HTTPTask/HTTPTask_IPInfo.h" +#include "XEngine_HTTPTask/HTTPTask_IDCard.h" +#include "XEngine_HTTPTask/HTTPTask_Phone.h" +/******************************************************************** +// Created: 2022/01/20 14:42:06 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_Hdr.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_Hdr +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 公用头文件 +// History: +*********************************************************************/ +extern BOOL bIsRun; +extern XLOG xhLog; +//HTTP服务器 +extern XNETHANDLE xhHTTPSocket; +extern XNETHANDLE xhHTTPHeart; +extern XNETHANDLE xhHTTPPool; +extern XHANDLE xhHTTPPacket; +//配置文件 +extern XENGINE_SERVICECONFIG st_ServiceConfig; + +//连接库 +#ifdef _WINDOWS +#ifdef _WIN64 +#ifdef _DEBUG +#pragma comment(lib,"../../x64/Debug/XEngine_ModuleConfigure.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_ModuleDatabase.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_ModuleProtocol.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_ModuleHelp.lib") +#else +#pragma comment(lib,"../../x64/Release/XEngine_ModuleConfigure.lib") +#pragma comment(lib,"../../x64/Release/XEngine_ModuleDatabase.lib") +#pragma comment(lib,"../../x64/Release/XEngine_ModuleProtocol.lib") +#pragma comment(lib,"../../x64/Release/XEngine_ModuleHelp.lib") +#endif +#else +#ifdef _DEBUG +#pragma comment(lib,"../../Debug/XEngine_ModuleConfigure.lib") +#pragma comment(lib,"../../Debug/XEngine_ModuleDatabase.lib") +#pragma comment(lib,"../../Debug/XEngine_ModuleProtocol.lib") +#pragma comment(lib,"../../Debug/XEngine_ModuleHelp.lib") +#else +#pragma comment(lib,"../../Release/XEngine_ModuleConfigure.lib") +#pragma comment(lib,"../../Release/XEngine_ModuleDatabase.lib") +#pragma comment(lib,"../../Release/XEngine_ModuleProtocol.lib") +#pragma comment(lib,"../../Release/XEngine_ModuleHelp.lib") +#endif +#endif +#pragma comment(lib,"XEngine_BaseLib/XEngine_BaseLib.lib") +#pragma comment(lib,"XEngine_Core/XEngine_Core.lib") +#pragma comment(lib,"XEngine_Core/XEngine_ManagePool.lib") +#pragma comment(lib,"XEngine_HelpComponents/HelpComponents_XLog.lib") +#pragma comment(lib,"XEngine_RfcComponents/RfcComponents_HttpServer.lib") +#pragma comment(lib,"Ws2_32.lib") +#endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cb9defd729de1c8df866ad72da8132df8e5bc5f --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.cpp @@ -0,0 +1,222 @@ +#include "XEngine_Hdr.h" +/******************************************************************** +// Created: 2022/01/20 14:43:07 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_HttpApp.cpp +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_HttpApp +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 主要入口函数 +// History: +*********************************************************************/ +BOOL bIsRun = FALSE; +XLOG xhLog = NULL; +//HTTP服务器 +XNETHANDLE xhHTTPSocket = 0; +XNETHANDLE xhHTTPHeart = 0; +XNETHANDLE xhHTTPPool = 0; +XHANDLE xhHTTPPacket = NULL; +//配置文件 +XENGINE_SERVICECONFIG st_ServiceConfig; + +void ServiceApp_Stop(int signo) +{ + if (bIsRun) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _T("服务器退出...")); + bIsRun = FALSE; + //销毁HTTP资源 + NetCore_TCPXCore_DestroyEx(xhHTTPSocket); + SocketOpt_HeartBeat_DestoryEx(xhHTTPHeart); + RfcComponents_HttpServer_DestroyEx(xhHTTPPacket); + ManagePool_Thread_NQDestroy(xhHTTPPool); + //销毁数据库 + ModuleDatabase_IPInfo_Destory(); + ModuleDatabase_IDCard_Destory(); + ModuleDatabase_Phone_Destory(); + //销毁日志资源 + HelpComponents_XLog_Destroy(xhLog); + } +#ifdef _WINDOWS + WSACleanup(); +#endif + exit(0); +} +//LINUX守护进程 +static int ServiceApp_Deamon() +{ +#ifndef _WINDOWS + pid_t nPID = 0; + int nStatus = 0; + nPID = fork(); + if (nPID > 0) + { + exit(0); + } + + close(2); + while (1) + { + nPID = fork(); + if (nPID < 0) + { + exit(1); + } + if (nPID == 0) + { + return 0; + } + waitpid(nPID, &nStatus, 0); + sleep(1); + } +#endif + return 0; +} + +int main(int argc, char** argv) +{ +#ifdef _WINDOWS + WSADATA st_WSAData; + WSAStartup(MAKEWORD(2, 2), &st_WSAData); +#endif + bIsRun = TRUE; + LPCTSTR lpszHTTPMime = _T("./XEngine_Config/HttpMime.types"); + LPCTSTR lpszHTTPCode = _T("./XEngine_Config/HttpCode.types"); + LPCTSTR lpszLogFile = _T("./XEngine_Log/XEngine_HttpApp.Log"); + HELPCOMPONENTS_XLOG_CONFIGURE st_XLogConfig; + THREADPOOL_PARAMENT** ppSt_ListHTTPParam; + + memset(&st_XLogConfig, '\0', sizeof(HELPCOMPONENTS_XLOG_CONFIGURE)); + memset(&st_ServiceConfig, '\0', sizeof(XENGINE_SERVICECONFIG)); + + st_XLogConfig.XLog_MaxBackupFile = 10; + st_XLogConfig.XLog_MaxSize = 1024000; + _tcscpy(st_XLogConfig.tszFileName, lpszLogFile); + //初始化参数 + if (!XEngine_Configure_Parament(argc, argv, &st_ServiceConfig)) + { + return -1; + } + //判断是否以守护进程启动 + if (st_ServiceConfig.bDeamon) + { + ServiceApp_Deamon(); + } + //初始日志 + xhLog = HelpComponents_XLog_Init(HELPCOMPONENTS_XLOG_OUTTYPE_STD | HELPCOMPONENTS_XLOG_OUTTYPE_FILE, &st_XLogConfig); + if (NULL == xhLog) + { + printf("启动服务中,启动日志失败,错误:%lX", XLog_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + //设置日志打印级别 + HelpComponents_XLog_SetLogPriority(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化日志系统成功")); + + signal(SIGINT, ServiceApp_Stop); + signal(SIGTERM, ServiceApp_Stop); + signal(SIGABRT, ServiceApp_Stop); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化信号量成功")); + //初始化数据库 + if (!ModuleDatabase_IPInfo_Init(st_ServiceConfig.st_XDBInfo.tszIPData)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,初始化IP数据库失败,错误:%lX"), ModuleDB_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化IP数据库成功,地址:%s"), st_ServiceConfig.st_XDBInfo.tszIPData); + if (!ModuleDatabase_IDCard_Init(st_ServiceConfig.st_XDBInfo.tszIDData)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,初始化ID数据库失败,错误:%lX"), ModuleDB_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化ID数据库成功,地址:%s"), st_ServiceConfig.st_XDBInfo.tszIDData); + if (!ModuleDatabase_Phone_Init(st_ServiceConfig.st_XDBInfo.tszPhoneData)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,初始化电话数据库失败,错误:%lX"), ModuleDB_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化电话数据库成功,地址:%s"), st_ServiceConfig.st_XDBInfo.tszPhoneData); + //启动HTTP服务相关代码 + if (st_ServiceConfig.nHttpPort > 0) + { + //HTTP包处理器 + xhHTTPPacket = RfcComponents_HttpServer_InitEx(lpszHTTPCode, lpszHTTPMime, st_ServiceConfig.st_XMax.nHTTPThread); + if (NULL == xhHTTPPacket) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,初始化HTTP组包失败,错误:%lX"), HttpServer_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化HTTP组包成功,IO线程个数:%d"), st_ServiceConfig.st_XMax.nHTTPThread); + //启动心跳 + if (st_ServiceConfig.st_XTime.nHTTPTimeOut > 0) + { + if (!SocketOpt_HeartBeat_InitEx(&xhHTTPHeart, st_ServiceConfig.st_XTime.nHTTPTimeOut, st_ServiceConfig.st_XTime.nTimeCheck, Network_Callback_HTTPHeart)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,初始化HTTP心跳服务失败,错误:%lX"), NetCore_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,初始化HTTP心跳服务成功,句柄:%llu,时间:%d,次数:%d"), xhHTTPHeart, st_ServiceConfig.st_XTime.nHTTPTimeOut, st_ServiceConfig.st_XTime.nTimeCheck); + } + else + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _T("启动服务中,HTTP心跳服务被设置为不启用")); + } + //网络 + if (!NetCore_TCPXCore_StartEx(&xhHTTPSocket, st_ServiceConfig.nHttpPort, st_ServiceConfig.st_XMax.nMaxClient, st_ServiceConfig.st_XMax.nIOThread)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,启动HTTP网络服务器失败,错误:%lX"), NetCore_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,启动HTTP网络服务器成功,HTTP端口:%d,IO:%d"), st_ServiceConfig.nHttpPort, st_ServiceConfig.st_XMax.nIOThread); + NetCore_TCPXCore_RegisterCallBackEx(xhHTTPSocket, Network_Callback_HTTPLogin, Network_Callback_HTTPRecv, Network_Callback_HTTPLeave); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,注册HTTP网络事件成功")); + //HTTP任务池 + BaseLib_OperatorMemory_Malloc((XPPPMEM)&ppSt_ListHTTPParam, st_ServiceConfig.st_XMax.nHTTPThread, sizeof(THREADPOOL_PARAMENT)); + for (int i = 0; i < st_ServiceConfig.st_XMax.nHTTPThread; i++) + { + int* pInt_Pos = new int; + + *pInt_Pos = i; + ppSt_ListHTTPParam[i]->lParam = pInt_Pos; + ppSt_ListHTTPParam[i]->fpCall_ThreadsTask = XEngine_HTTPTask_Thread; + } + if (!ManagePool_Thread_NQCreate(&xhHTTPPool, &ppSt_ListHTTPParam, st_ServiceConfig.st_XMax.nHTTPThread)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("启动服务中,启动HTTP线程池服务失败,错误:%lX"), ManagePool_GetLastError()); + goto XENGINE_SERVICEAPP_EXIT; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("启动服务中,启动HTTP线程池服务成功,启动个数:%d"), st_ServiceConfig.st_XMax.nHTTPThread); + } + else + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _T("启动服务中,HTTP消息服务没有被启用")); + } + + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("所有服务成功启动,服务运行中,发行版本次数:%d,当前版本:%s。。。"), st_ServiceConfig.st_XVer.pStl_ListVer->size(), st_ServiceConfig.st_XVer.pStl_ListVer->front().c_str()); + while (bIsRun) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } +XENGINE_SERVICEAPP_EXIT: + if (bIsRun) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("有服务启动失败,服务器退出...")); + bIsRun = FALSE; + //销毁HTTP资源 + NetCore_TCPXCore_DestroyEx(xhHTTPSocket); + SocketOpt_HeartBeat_DestoryEx(xhHTTPHeart); + RfcComponents_HttpServer_DestroyEx(xhHTTPPacket); + ManagePool_Thread_NQDestroy(xhHTTPPool); + //销毁数据库 + ModuleDatabase_IPInfo_Destory(); + ModuleDatabase_IDCard_Destory(); + ModuleDatabase_Phone_Destory(); + //销毁日志资源 + HelpComponents_XLog_Destroy(xhLog); + } +#ifdef _WINDOWS + WSACleanup(); +#endif + return 0; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..213b906b16d6661e27d480ff2219c7d7e5c0aa7b --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {e756b7d2-d40d-4106-9c14-1d90f20a712e} + XEngineHttpApp + 10.0 + + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + false + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib32);$(LibraryPath) + + + true + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + false + $(XEngine_Include);$(IncludePath) + $(XEngine_Lib64);$(LibraryPath) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + 4819 + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + 4819 + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + 4819 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + 4819 + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj.filters b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..969942236765df38454110083f7ca3433df5f3de --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {9bf2e74a-551b-4d8d-ad34-ccd13e64e985} + + + {a205153f-6995-49dc-ae5f-cd2bc0d31549} + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件\XEngine_HTTPTask + + + 源文件\XEngine_HTTPTask + + + 源文件\XEngine_HTTPTask + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件\XEngine_HTTPTask + + + 头文件\XEngine_HTTPTask + + + 头文件\XEngine_HTTPTask + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj.user b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_HttpApp.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Network.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Network.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1a3a69e4ea2fed7cf8540f823e3fc1a1342bcec --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Network.cpp @@ -0,0 +1,65 @@ +#include "XEngine_Hdr.h" +/******************************************************************** +// Created: 2022/01/20 14:44:40 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_Network.cpp +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_Network +// File Ext: cpp +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 网络IO相关代码 +// History: +*********************************************************************/ +//////////////////////////////////////////////////////////////////////////下面是HTTP网络IO相关代码处理函数 +BOOL __stdcall Network_Callback_HTTPLogin(LPCTSTR lpszClientAddr, SOCKET hSocket, LPVOID lParam) +{ + SocketOpt_HeartBeat_InsertAddrEx(xhHTTPHeart, lpszClientAddr); + RfcComponents_HttpServer_CreateClientEx(xhHTTPPacket, lpszClientAddr, 0); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,连接到服务器"), lpszClientAddr); + return TRUE; +} +void __stdcall Network_Callback_HTTPRecv(LPCTSTR lpszClientAddr, SOCKET hSocket, LPCTSTR lpszRecvMsg, int nMsgLen, LPVOID lParam) +{ + if (!RfcComponents_HttpServer_InserQueueEx(xhHTTPPacket, lpszClientAddr, lpszRecvMsg, nMsgLen)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("HTTP客户端:%s,投递HTTP数据包到消息队列失败,错误:%lX"), lpszClientAddr, HttpServer_GetLastError()); + return; + } + SocketOpt_HeartBeat_ActiveAddrEx(xhHTTPHeart, lpszClientAddr); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_DEBUG, _T("HTTP客户端:%s,投递数据包到组包队列成功,大小:%d"), lpszClientAddr, nMsgLen); +} +void __stdcall Network_Callback_HTTPLeave(LPCTSTR lpszClientAddr, SOCKET hSocket, LPVOID lParam) +{ + XEngine_Network_Close(lpszClientAddr, FALSE); +} +void __stdcall Network_Callback_HTTPHeart(LPCTSTR lpszClientAddr, SOCKET hSocket, int nStatus, LPVOID lParam) +{ + XEngine_Network_Close(lpszClientAddr, TRUE); +} +//////////////////////////////////////////////////////////////////////////网络IO关闭操作 +void XEngine_Network_Close(LPCTSTR lpszClientAddr, BOOL bHeart) +{ + if (bHeart) + { + NetCore_TCPXCore_CloseForClientEx(xhHTTPSocket, lpszClientAddr); + } + else + { + SocketOpt_HeartBeat_DeleteAddrEx(xhHTTPHeart, lpszClientAddr); + } + RfcComponents_HttpServer_CloseClinetEx(xhHTTPPacket, lpszClientAddr); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _T("HTTP客户端:%s,离开服务器"), lpszClientAddr); +} +////////////////////////////////////////////////////////////////////////// +BOOL XEngine_Network_Send(LPCTSTR lpszClientAddr, LPCTSTR lpszMsgBuffer, int nMsgLen) +{ + //发送数据给指定客户端 + if (!NetCore_TCPXCore_SendEx(xhHTTPSocket, lpszClientAddr, lpszMsgBuffer, nMsgLen)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _T("HTTP客户端:%s,发送数据失败,错误:%lX"), lpszClientAddr, NetCore_GetLastError()); + return FALSE; + } + //发送成功激活一次心跳 + SocketOpt_HeartBeat_ActiveAddrEx(xhHTTPHeart, lpszClientAddr); + return TRUE; +} \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Network.h b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Network.h new file mode 100644 index 0000000000000000000000000000000000000000..f0ee920165c50e6faf858c16a513393b088fcfd9 --- /dev/null +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_HttpApp/XEngine_Network.h @@ -0,0 +1,20 @@ +#pragma once +/******************************************************************** +// Created: 2022/01/20 14:42:55 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp\XEngine_Network.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ServiceApp\XEngine_HttpApp +// File Base: XEngine_Network +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 网络IO相关代码 +// History: +*********************************************************************/ +//HTTP相关 +BOOL __stdcall Network_Callback_HTTPLogin(LPCTSTR lpszClientAddr, SOCKET hSocket, LPVOID lParam); +void __stdcall Network_Callback_HTTPRecv(LPCTSTR lpszClientAddr, SOCKET hSocket, LPCTSTR lpszRecvMsg, int nMsgLen, LPVOID lParam); +void __stdcall Network_Callback_HTTPLeave(LPCTSTR lpszClientAddr, SOCKET hSocket, LPVOID lParam); +void __stdcall Network_Callback_HTTPHeart(LPCTSTR lpszClientAddr, SOCKET hSocket, int nStatus, LPVOID lParam); +//关闭与发送 +void XEngine_Network_Close(LPCTSTR lpszClientAddr, BOOL bHeart); +BOOL XEngine_Network_Send(LPCTSTR lpszClientAddr, LPCTSTR lpszMsgBuffer, int nMsgLen); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/Makefile b/XEngine_Source/XEngine_ThirdPart/jsoncpp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..30dbd85ab2df273f2653cfe72e063176644ad6a8 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/Makefile @@ -0,0 +1,46 @@ +CC = g++ -Wall -std=c++17 -fPIC +RELEASE = 0 +UNICODE = 0 +INCLUDE = -I ./ +FILECENTOS = /etc/redhat-release +LOADBIN = +LIB = +LIBEX = -static-libgcc -lrt -ldl -lpthread +LOADSO = -Wl,-rpath= +LIBINCLUDE = json_reader.o json_value.o json_writer.o + +ifeq ($(RELEASE),1) +FLAGS = -c -O2 +DEBUG = +else +FLAGS = -c -lc_p +DEBUG = -g -pg +endif + +ifeq ($(UNICODE),1) +UNICODE = -D _UNICODE +else +UNICODE = +endif + +all:$(LIBINCLUDE) + $(CC) $(DEBUG) $(LIBINCLUDE) -o libjsoncpp.so -shared -fPIC $(LOADBIN) $(LIB) $(LIBEX) $(LOADSO) + +json_reader.o:json_reader.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) json_reader.cpp +json_value.o:json_value.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) json_value.cpp +json_writer.o:json_writer.cpp + $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(INCLUDE) json_writer.cpp + +InstallAll:InstallSo +InstallSo:./libjsoncpp.so + cp ./libjsoncpp.so ../../../XEngine_Release/libjsoncpp.so + + + +CleanAll:CleanObj CleanMk +CleanObj: + rm *.o +CleanMk: + rm *.so diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/allocator.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..d669dda90baefec39e320a09c7d9005bc1a2e81e --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/allocator.h @@ -0,0 +1,88 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_ALLOCATOR_H_INCLUDED +#define JSON_ALLOCATOR_H_INCLUDED + +#include +#include + +#pragma pack(push, 8) + +namespace Json { +template class SecureAllocator { +public: + // Type definitions + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + /** + * Allocate memory for N items using the standard allocator. + */ + pointer allocate(size_type n) { + // allocate using "global operator new" + return static_cast(::operator new(n * sizeof(T))); + } + + /** + * Release memory which was allocated for N items at pointer P. + * + * The memory block is filled with zeroes before being released. + */ + void deallocate(pointer p, size_type n) { + // memset_s is used because memset may be optimized away by the compiler + memset_s(p, n * sizeof(T), 0, n * sizeof(T)); + // free using "global operator delete" + ::operator delete(p); + } + + /** + * Construct an item in-place at pointer P. + */ + template void construct(pointer p, Args&&... args) { + // construct using "placement new" and "perfect forwarding" + ::new (static_cast(p)) T(std::forward(args)...); + } + + size_type max_size() const { return size_t(-1) / sizeof(T); } + + pointer address(reference x) const { return std::addressof(x); } + + const_pointer address(const_reference x) const { return std::addressof(x); } + + /** + * Destroy an item in-place at pointer P. + */ + void destroy(pointer p) { + // destroy using "explicit destructor" + p->~T(); + } + + // Boilerplate + SecureAllocator() {} + template SecureAllocator(const SecureAllocator&) {} + template struct rebind { using other = SecureAllocator; }; +}; + +template +bool operator==(const SecureAllocator&, const SecureAllocator&) { + return true; +} + +template +bool operator!=(const SecureAllocator&, const SecureAllocator&) { + return false; +} + +} // namespace Json + +#pragma pack(pop) + +#endif // JSON_ALLOCATOR_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/assertions.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/assertions.h new file mode 100644 index 0000000000000000000000000000000000000000..0a0120d6db8c0dd783d6209807163fc0b436bd9d --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/assertions.h @@ -0,0 +1,61 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_ASSERTIONS_H_INCLUDED +#define JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +/** It should not be possible for a maliciously designed file to + * cause an abort() or seg-fault, so these macros are used only + * for pre-condition violations and internal logic errors. + */ +#if JSON_USE_EXCEPTION + +// @todo <= add detail about condition in exception +#define JSON_ASSERT(condition) \ + do { \ + if (!(condition)) { \ + Json::throwLogicError("assert json failed"); \ + } \ + } while (0) + +#define JSON_FAIL_MESSAGE(message) \ + do { \ + OStringStream oss; \ + oss << message; \ + Json::throwLogicError(oss.str()); \ + abort(); \ + } while (0) + +#else // JSON_USE_EXCEPTION + +#define JSON_ASSERT(condition) assert(condition) + +// The call to assert() will show the failure message in debug builds. In +// release builds we abort, for a core-dump or debugger. +#define JSON_FAIL_MESSAGE(message) \ + { \ + OStringStream oss; \ + oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + do { \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } \ + } while (0) + +#endif // JSON_ASSERTIONS_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/config.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/config.h new file mode 100644 index 0000000000000000000000000000000000000000..81d7969c21498da7453b02cf8fba2cb08c39b227 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/config.h @@ -0,0 +1,150 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED +#include +#include +#include +#include +#include +#include +#include +#include + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +// Temporary, tracked for removal with issue #982. +#ifndef JSON_USE_NULLREF +#define JSON_USE_NULLREF 1 +#endif + +/// If defined, indicates that the source file is amalgamated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgamated header. +// #define JSON_IS_AMALGAMATION + +// Export macros for DLL visibility +#if defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllexport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#elif defined(__GNUC__) || defined(__clang__) +#define JSON_API __attribute__((visibility("default"))) +#endif // if defined(_MSC_VER) + +#elif defined(JSON_DLL) +#if defined(_MSC_VER) || defined(__MINGW32__) +#define JSON_API __declspec(dllimport) +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#endif // if defined(_MSC_VER) +#endif // ifdef JSON_DLL_BUILD + +#if !defined(JSON_API) +#define JSON_API +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 +#error \ + "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +// As recommended at +// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 +extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...); +#define jsoncpp_snprintf msvc_pre1900_c99_snprintf +#else +#define jsoncpp_snprintf std::snprintf +#endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. +// C++11 should be used directly in JSONCPP. +#define JSONCPP_OVERRIDE override + +#ifdef __clang__ +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif +#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates + // MSVC) +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif // __clang__ || __GNUC__ || _MSC_VER + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif + +#if !defined(JSON_IS_AMALGAMATION) + +#include "allocator.h" +#include "version.h" + +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { +using Int = int; +using UInt = unsigned int; +#if defined(JSON_NO_INT64) +using LargestInt = int; +using LargestUInt = unsigned int; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +using Int64 = __int64; +using UInt64 = unsigned __int64; +#else // if defined(_MSC_VER) // Other platforms, use long long +using Int64 = int64_t; +using UInt64 = uint64_t; +#endif // if defined(_MSC_VER) +using LargestInt = Int64; +using LargestUInt = UInt64; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) + +template +using Allocator = + typename std::conditional, + std::allocator>::type; +using String = std::basic_string, Allocator>; +using IStringStream = + std::basic_istringstream; +using OStringStream = + std::basic_ostringstream; +using IStream = std::istream; +using OStream = std::ostream; +} // namespace Json + +// Legacy names (formerly macros). +using JSONCPP_STRING = Json::String; +using JSONCPP_ISTRINGSTREAM = Json::IStringStream; +using JSONCPP_OSTRINGSTREAM = Json::OStringStream; +using JSONCPP_ISTREAM = Json::IStream; +using JSONCPP_OSTREAM = Json::OStream; + +#endif // JSON_CONFIG_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/forwards.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/forwards.h new file mode 100644 index 0000000000000000000000000000000000000000..733b9d68f91121d80097eccee7bc0856c60304c1 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/forwards.h @@ -0,0 +1,43 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class StreamWriter; +class StreamWriterBuilder; +class Writer; +class FastWriter; +class StyledWriter; +class StyledStreamWriter; + +// reader.h +class Reader; +class CharReader; +class CharReaderBuilder; + +// json_features.h +class Features; + +// value.h +using ArrayIndex = unsigned int; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/json.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/json.h new file mode 100644 index 0000000000000000000000000000000000000000..c6a9bbddd3fe9b930d170c32aa2a26f7eba115a2 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/json.h @@ -0,0 +1,15 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_JSON_H_INCLUDED +#define JSON_JSON_H_INCLUDED + +#include "config.h" +#include "json_features.h" +#include "reader.h" +#include "value.h" +#include "writer.h" + +#endif // JSON_JSON_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/json_features.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/json_features.h new file mode 100644 index 0000000000000000000000000000000000000000..6d881b80bbad1dc431c8d66bc16231bd511801e6 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/json_features.h @@ -0,0 +1,61 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FEATURES_H_INCLUDED +#define JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_{true}; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_{false}; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_{false}; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_{false}; +}; + +} // namespace Json + +#pragma pack(pop) + +#endif // JSON_FEATURES_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/reader.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/reader.h new file mode 100644 index 0000000000000000000000000000000000000000..775037e750c6ed1779ce8cd8dae87e26ca97d327 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/reader.h @@ -0,0 +1,405 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_READER_H_INCLUDED +#define JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +/** \brief Unserialize a JSON document into a + * Value. + * + * \deprecated Use CharReader and CharReaderBuilder. + */ + +class JSON_API Reader { +public: + using Char = char; + using Location = const Char*; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + */ + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + String message; + }; + + /** \brief Constructs a Reader allowing all features for parsing. + * \deprecated Use CharReader and CharReaderBuilder. + */ + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set for parsing. + * \deprecated Use CharReader and CharReaderBuilder. + */ + Reader(const Features& features); + + /** \brief Read a Value from a JSON + * document. + * + * \param document UTF-8 encoded string containing the document + * to read. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool parse(const std::string& document, Value& root, + bool collectComments = true); + + /** \brief Read a Value from a JSON + * document. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded + * string of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string + * of the document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + bool parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments = true); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse(IStream& is, Value& root, bool collectComments = true); + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") + String getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed + * document. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. + */ + String getFormattedErrorMessages() const; + + /** \brief Returns a vector of structured errors encountered while parsing. + * + * \return A (possibly empty) vector of StructuredError objects. Currently + * only one error can be returned, but the caller should tolerate multiple + * errors. This can occur if the parser recovers from a non-fatal parse + * error and then encounters additional errors. + */ + std::vector getStructuredErrors() const; + + /** \brief Add a semantic error message. + * + * \param value JSON Value location associated with the error + * \param message The error message. + * \return \c true if the error was successfully added, \c false if the Value + * offset exceeds the document size. + */ + bool pushError(const Value& value, const String& message); + + /** \brief Add a semantic error message with extra context. + * + * \param value JSON Value location associated with the error + * \param message The error message. + * \param extra Additional JSON Value location to contextualize the error + * \return \c true if the error was successfully added, \c false if either + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const String& message, const Value& extra); + + /** \brief Return whether there are any errors. + * + * \return \c true if there are no errors to report \c false if errors have + * occurred. + */ + bool good() const; + +private: + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + String message_; + Location extra_; + }; + + using Errors = std::deque; + + bool readToken(Token& token); + void skipSpaces(); + bool match(const Char* pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, String& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static bool containsNewLine(Location begin, Location end); + static String normalizeEOL(Location begin, Location end); + + using Nodes = std::stack; + Nodes nodes_; + Errors errors_; + String document_; + Location begin_{}; + Location end_{}; + Location current_{}; + Location lastValueEnd_{}; + Value* lastValue_{}; + String commentsBefore_; + Features features_; + bool collectComments_{}; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() = default; + /** \brief Read a Value from a JSON + * document. The document must be a UTF-8 encoded string containing the + * document to read. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string + * of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + * document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it was + * successfully parsed. + * \param[out] errs Formatted error messages (if not NULL) a user + * friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + * error occurred. + */ + virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) = 0; + + class JSON_API Factory { + public: + virtual ~Factory() = default; + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + * + * Usage: + * \code + * using namespace Json; + * CharReaderBuilder builder; + * builder["collectComments"] = false; + * Value value; + * String errs; + * bool ok = parseFromStream(builder, std::cin, &value, &errs); + * \endcode + */ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + * These are case-sensitive. + * Available settings (case-sensitive): + * - `"collectComments": false or true` + * - true to collect comment and allow writing them back during + * serialization, false to discard comments. This parameter is ignored + * if allowComments is false. + * - `"allowComments": false or true` + * - true if comments are allowed. + * - `"allowTrailingCommas": false or true` + * - true if trailing commas in objects and arrays are allowed. + * - `"strictRoot": false or true` + * - true if root must be either an array or an object value + * - `"allowDroppedNullPlaceholders": false or true` + * - true if dropped null placeholders are allowed. (See + * StreamWriterBuilder.) + * - `"allowNumericKeys": false or true` + * - true if numeric object keys are allowed. + * - `"allowSingleQuotes": false or true` + * - true if '' are allowed for strings (both keys and values) + * - `"stackLimit": integer` + * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an + * exception. + * - This is a security issue (seg-faults caused by deeply nested JSON), so + * the default is low. + * - `"failIfExtra": false or true` + * - If true, `parse()` returns false when extra non-whitespace trails the + * JSON value in the input string. + * - `"rejectDupKeys": false or true` + * - If true, `parse()` returns false when a key is duplicated within an + * object. + * - `"allowSpecialFloats": false or true` + * - If true, special float values (NaNs and infinities) are allowed and + * their values are lossfree restorable. + * - `"skipBom": false or true` + * - If true, if the input starts with the Unicode byte order mark (BOM), + * it is skipped. + * + * You can examine 'settings_` yourself to see the defaults. You can also + * write and read them just like any JSON Value. + * \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + ~CharReaderBuilder() override; + + CharReader* newCharReader() const override; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](const String& key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); +}; + +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root, + String* errs); + +/** \brief Read from 'sin' into 'root'. + * + * Always keep comments from the input JSON. + * + * This can be used to read a file into a particular sub-object. + * For example: + * \code + * Json::Value root; + * cin >> root["dir"]["file"]; + * cout << root; + * \endcode + * Result: + * \verbatim + * { + * "dir": { + * "file": { + * // The input stream JSON would be nested here. + * } + * } + * } + * \endverbatim + * \throw std::exception on parse error. + * \see Json::operator<<() + */ +JSON_API IStream& operator>>(IStream&, Value&); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_READER_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/value.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/value.h new file mode 100644 index 0000000000000000000000000000000000000000..d24ca53484c857a86612d451f9e80e91d044105c --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/value.h @@ -0,0 +1,935 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_H_INCLUDED +#define JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +// Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +#if defined(_MSC_VER) && _MSC_VER == 1800 +#define JSONCPP_NORETURN __declspec(noreturn) +#else +#define JSONCPP_NORETURN [[noreturn]] +#endif +#endif + +// Support for '= delete' with template declarations was a late addition +// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2 +// even though these declare themselves to be c++11 compilers. +#if !defined(JSONCPP_TEMPLATE_DELETE) +#if defined(__clang__) && defined(__apple_build_version__) +#if __apple_build_version__ <= 8000042 +#define JSONCPP_TEMPLATE_DELETE +#endif +#elif defined(__clang__) +#if __clang_major__ == 3 && __clang_minor__ <= 8 +#define JSONCPP_TEMPLATE_DELETE +#endif +#endif +#if !defined(JSONCPP_TEMPLATE_DELETE) +#define JSONCPP_TEMPLATE_DELETE = delete +#endif +#endif + +#include +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251 4275) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +#if JSON_USE_EXCEPTION +/** Base class for all exceptions we throw. + * + * We use nothing but these internally. Of course, STL can throw others. + */ +class JSON_API Exception : public std::exception { +public: + Exception(String msg); + ~Exception() noexcept override; + char const* what() const noexcept override; + +protected: + String msg_; +}; + +/** Exceptions which the user cannot easily avoid. + * + * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input + * + * \remark derived from Json::Exception + */ +class JSON_API RuntimeError : public Exception { +public: + RuntimeError(String const& msg); +}; + +/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. + * + * These are precondition-violations (user bugs) and internal errors (our bugs). + * + * \remark derived from Json::Exception + */ +class JSON_API LogicError : public Exception { +public: + LogicError(String const& msg); +}; +#endif + +/// used internally +JSONCPP_NORETURN void throwRuntimeError(String const& msg); +/// used internally +JSONCPP_NORETURN void throwLogicError(String const& msg); + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignment takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : c_str_(czstring) {} + + operator const char*() const { return c_str_; } + + const char* c_str() const { return c_str_; } + +private: + const char* c_str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * Values of an #objectValue or #arrayValue can be accessed using operator[]() + * methods. + * Non-const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resized and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtain default value in the case the + * required element does not exist. + * + * It is possible to iterate over the list of member keys of an object using + * the getMemberNames() method. + * + * \note #Value string-length fit in size_t, but keys must be < 2^30. + * (The reason is an implementation detail.) A #CharReader will raise an + * exception if a bound is exceeded to avoid security holes in your app, + * but the Value API does *not* check bounds. That is the responsibility + * of the caller. + */ +class JSON_API Value { + friend class ValueIteratorBase; + +public: + using Members = std::vector; + using iterator = ValueIterator; + using const_iterator = ValueConstIterator; + using UInt = Json::UInt; + using Int = Json::Int; +#if defined(JSON_HAS_INT64) + using UInt64 = Json::UInt64; + using Int64 = Json::Int64; +#endif // defined(JSON_HAS_INT64) + using LargestInt = Json::LargestInt; + using LargestUInt = Json::LargestUInt; + using ArrayIndex = Json::ArrayIndex; + + // Required for boost integration, e. g. BOOST_TEST + using value_type = std::string; + +#if JSON_USE_NULLREF + // Binary compatibility kludges, do not use. + static const Value& null; + static const Value& nullRef; +#endif + + // null and nullRef are deprecated, use this instead. + static Value const& nullSingleton(); + + /// Minimum signed integer value that can be stored in a Json::Value. + static constexpr LargestInt minLargestInt = + LargestInt(~(LargestUInt(-1) / 2)); + /// Maximum signed integer value that can be stored in a Json::Value. + static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2); + /// Maximum unsigned integer value that can be stored in a Json::Value. + static constexpr LargestUInt maxLargestUInt = LargestUInt(-1); + + /// Minimum signed int value that can be stored in a Json::Value. + static constexpr Int minInt = Int(~(UInt(-1) / 2)); + /// Maximum signed int value that can be stored in a Json::Value. + static constexpr Int maxInt = Int(UInt(-1) / 2); + /// Maximum unsigned int value that can be stored in a Json::Value. + static constexpr UInt maxUInt = UInt(-1); + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2)); + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2); + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static constexpr UInt64 maxUInt64 = UInt64(-1); +#endif // defined(JSON_HAS_INT64) + /// Default precision for real value for string representation. + static constexpr UInt defaultRealPrecision = 17; + // The constant is hard-coded because some compiler have trouble + // converting Value::maxUInt64 to a double correctly (AIX/xlC). + // Assumes that UInt64 is a 64 bits integer. + static constexpr double maxUInt64AsDouble = 18446744073709551615.0; +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else +private: +#endif +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + class CZString { + public: + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; + CZString(ArrayIndex index); + CZString(char const* str, unsigned length, DuplicationPolicy allocate); + CZString(CZString const& other); + CZString(CZString&& other) noexcept; + ~CZString(); + CZString& operator=(const CZString& other); + CZString& operator=(CZString&& other) noexcept; + + bool operator<(CZString const& other) const; + bool operator==(CZString const& other) const; + ArrayIndex index() const; + // const char* c_str() const; ///< \deprecated + char const* data() const; + unsigned length() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + + struct StringStorage { + unsigned policy_ : 2; + unsigned length_ : 30; // 1GB max + }; + + char const* cstr_; // actually, a prefixed string, unless policy is noDup + union { + ArrayIndex index_; + StringStorage storage_; + }; + }; + +public: + typedef std::map ObjectValues; +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** + * \brief Create a default Value of the given type. + * + * This is a very useful constructor. + * To create an empty array, pass arrayValue. + * To create an empty object, pass objectValue. + * Another Value can then be set to this one by assignment. + * This is useful since clear() and resize() will not alter types. + * + * Examples: + * \code + * Json::Value null_value; // null + * Json::Value arr_value(Json::arrayValue); // [] + * Json::Value obj_value(Json::objectValue); // {} + * \endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) + Value(const char* begin, const char* end); ///< Copy all, incl zeroes. + /** + * \brief Constructs a value from a static string. + * + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to + * this constructor. + * + * \note This works only for null-terminated strings. (We cannot change the + * size of this class, so we have nowhere to store the length, which might be + * computed later for various operations.) + * + * Example of usage: + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode + */ + Value(const StaticString& value); + Value(const String& value); + Value(bool value); + Value(std::nullptr_t ptr) = delete; + Value(const Value& other); + Value(Value&& other) noexcept; + ~Value(); + + /// \note Overwrite existing comments. To preserve comments, use + /// #swapPayload(). + Value& operator=(const Value& other); + Value& operator=(Value&& other) noexcept; + + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + /// copy everything. + void copy(const Value& other); + /// copy values but leave comments and source offsets in place. + void copyPayload(const Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; ///< Embedded zeroes could cause you trouble! +#if JSONCPP_USING_SECURE_MEMORY + unsigned getCStringLength() const; // Allows you to understand the length of + // the CString +#endif + String asString() const; ///< Embedded zeroes are possible. + /** Get raw char* of string-value. + * \return false if !string. (Seg-fault if str or end are NULL.) + */ + bool getString(char const** begin, char const** end) const; + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + /// The `as` and `is` member function templates and specializations. + template T as() const JSONCPP_TEMPLATE_DELETE; + template bool is() const JSONCPP_TEMPLATE_DELETE; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return !isNull() + explicit operator bool() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to newSize elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex newSize); + + //@{ + /// Access an array element (zero based index). If the array contains less + /// than index element, then null value are inserted in the array so that + /// its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + Value& operator[](int index); + //@} + + //@{ + /// Access an array element (zero based index). + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + const Value& operator[](int index) const; + //@} + + /// If the array contains at least index+1 elements, returns the element + /// value, otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + Value& append(Value&& value); + + /// \brief Insert value in array at specific index + bool insert(ArrayIndex index, const Value& newValue); + bool insert(ArrayIndex index, Value&& newValue); + + /// Access an object value by name, create a null member if it does not exist. + /// \note Because of our implementation, keys are limited to 2^30 -1 chars. + /// Exceeding that will cause an exception. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + /// \param key may contain embedded nulls. + Value& operator[](const String& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + /// \param key may contain embedded nulls. + const Value& operator[](const String& key) const; + /** \brief Access an object value by name, create a null member if it does not + * exist. + * + * If the object has no entry for that name, then the member name used to + * store the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \note key may contain embedded nulls. + Value get(const char* begin, const char* end, + const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \param key may contain embedded nulls. + Value get(const String& key, const Value& defaultValue) const; + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of object-mutators. + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. + Value* demand(char const* begin, char const* end); + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + void removeMember(const char* key); + /// Same as removeMember(const char*) + /// \param key may contain embedded nulls. + void removeMember(const String& key); + /// Same as removeMember(const char* begin, const char* end, Value* removed), + /// but 'key' is null-terminated. + bool removeMember(const char* key, Value* removed); + /** \brief Remove the named map member. + * + * Update 'removed' iff removed. + * \param key may contain embedded nulls. + * \return true iff removed (no exceptions) + */ + bool removeMember(String const& key, Value* removed); + /// Same as removeMember(String const& key, Value* removed) + bool removeMember(const char* begin, const char* end, Value* removed); + /** \brief Remove the indexed array element. + * + * O(n) expensive operations. + * Update 'removed' iff removed. + * \return true if removed (no exceptions) + */ + bool removeIndex(ArrayIndex index, Value* removed); + + /// Return true if the object has a member named key. + /// \note 'key' must be null-terminated. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + /// \param key may contain embedded nulls. + bool isMember(const String& key) const; + /// Same as isMember(String const& key)const + bool isMember(const char* begin, const char* end) const; + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + /// \deprecated Always pass len. + JSONCPP_DEPRECATED("Use setComment(String const&) instead.") + void setComment(const char* comment, CommentPlacement placement) { + setComment(String(comment, strlen(comment)), placement); + } + /// Comments must be //... or /* ... */ + void setComment(const char* comment, size_t len, CommentPlacement placement) { + setComment(String(comment, len), placement); + } + /// Comments must be //... or /* ... */ + void setComment(String comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + String getComment(CommentPlacement placement) const; + + String toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(ptrdiff_t start); + void setOffsetLimit(ptrdiff_t limit); + ptrdiff_t getOffsetStart() const; + ptrdiff_t getOffsetLimit() const; + +private: + void setType(ValueType v) { + bits_.value_type_ = static_cast(v); + } + bool isAllocated() const { return bits_.allocated_; } + void setIsAllocated(bool v) { bits_.allocated_ = v; } + + void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); + + Value& resolveReference(const char* key); + Value& resolveReference(const char* key, const char* end); + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; // if allocated_, ptr to { unsigned, char[] }. + ObjectValues* map_; + } value_; + + struct { + // Really a ValueType, but types should agree for bitfield packing. + unsigned int value_type_ : 8; + // Unless allocated_, string_ must be null-terminated. + unsigned int allocated_ : 1; + } bits_; + + class Comments { + public: + Comments() = default; + Comments(const Comments& that); + Comments(Comments&& that) noexcept; + Comments& operator=(const Comments& that); + Comments& operator=(Comments&& that) noexcept; + bool has(CommentPlacement slot) const; + String get(CommentPlacement slot) const; + void set(CommentPlacement slot, String comment); + + private: + using Array = std::array; + std::unique_ptr ptr_; + }; + Comments comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + ptrdiff_t start_; + ptrdiff_t limit_; +}; + +template <> inline bool Value::as() const { return asBool(); } +template <> inline bool Value::is() const { return isBool(); } + +template <> inline Int Value::as() const { return asInt(); } +template <> inline bool Value::is() const { return isInt(); } + +template <> inline UInt Value::as() const { return asUInt(); } +template <> inline bool Value::is() const { return isUInt(); } + +#if defined(JSON_HAS_INT64) +template <> inline Int64 Value::as() const { return asInt64(); } +template <> inline bool Value::is() const { return isInt64(); } + +template <> inline UInt64 Value::as() const { return asUInt64(); } +template <> inline bool Value::is() const { return isUInt64(); } +#endif + +template <> inline double Value::as() const { return asDouble(); } +template <> inline bool Value::is() const { return isDouble(); } + +template <> inline String Value::as() const { return asString(); } +template <> inline bool Value::is() const { return isString(); } + +/// These `as` specializations are type conversions, and do not have a +/// corresponding `is`. +template <> inline float Value::as() const { return asFloat(); } +template <> inline const char* Value::as() const { + return asCString(); +} + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(String key); + +private: + enum Kind { kindNone = 0, kindIndex, kindKey }; + String key_; + ArrayIndex index_{}; + Kind kind_{kindNone}; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provided as parameter + */ +class JSON_API Path { +public: + Path(const String& path, const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + using InArgs = std::vector; + using Args = std::vector; + + void makePath(const String& path, const InArgs& in); + void addPathInArg(const String& path, const InArgs& in, + InArgs::const_iterator& itInArg, PathArgument::Kind kind); + static void invalidPath(const String& path, int location); + + Args args_; +}; + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + using iterator_category = std::bidirectional_iterator_tag; + using size_t = unsigned int; + using difference_type = int; + using SelfType = ValueIteratorBase; + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return other.computeDistance(*this); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value, or -1 if it is not an + /// arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value, or "" if it is not an + /// objectValue. + /// \note Avoid `c_str()` on result, as embedded zeroes are possible. + String name() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + /// \deprecated This cannot be used for UTF-8 strings, since there can be + /// embedded nulls. + JSONCPP_DEPRECATED("Use `key = name();` instead.") + char const* memberName() const; + /// Return the member name of the referenced Value, or NULL if it is not an + /// objectValue. + /// \note Better version than memberName(). Allows embedded nulls. + char const* memberName(char const** end) const; + +protected: + /*! Internal utility functions to assist with implementing + * other iterator functions. The const and non-const versions + * of the "deref" protected methods expose the protected + * current_ member variable in a way that can often be + * optimized away by the compiler. + */ + const Value& deref() const; + Value& deref(); + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_{true}; + +public: + // For some reason, BORLAND needs these at the end, rather + // than earlier. No idea why. + ValueIteratorBase(); + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + using value_type = const Value; + // typedef unsigned int size_t; + // typedef int difference_type; + using reference = const Value&; + using pointer = const Value*; + using SelfType = ValueConstIterator; + + ValueConstIterator(); + ValueConstIterator(ValueIterator const& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + using value_type = Value; + using size_t = unsigned int; + using difference_type = int; + using reference = Value&; + using pointer = Value*; + using SelfType = ValueIterator; + + ValueIterator(); + explicit ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: + /*! \internal Use by Value to create an iterator. + */ + explicit ValueIterator(const Value::ObjectValues::iterator& current); + +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + /*! The return value of non-const iterators can be + * changed, so the these functions are not const + * because the returned references/pointers can be used + * to change state of the base class. + */ + reference operator*() const { return const_cast(deref()); } + pointer operator->() const { return const_cast(&deref()); } +}; + +inline void swap(Value& a, Value& b) { a.swap(b); } + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/version.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/version.h new file mode 100644 index 0000000000000000000000000000000000000000..99a27fa5daaec41e7459db8babb9ba37db34eeb6 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/version.h @@ -0,0 +1,28 @@ +#ifndef JSON_VERSION_H_INCLUDED +#define JSON_VERSION_H_INCLUDED + +// Note: version must be updated in three places when doing a release. This +// annoying process ensures that amalgamate, CMake, and meson all report the +// correct version. +// 1. /meson.build +// 2. /include/json/version.h +// 3. /CMakeLists.txt +// IMPORTANT: also update the SOVERSION!! + +#define JSONCPP_VERSION_STRING "1.9.5" +#define JSONCPP_VERSION_MAJOR 1 +#define JSONCPP_VERSION_MINOR 9 +#define JSONCPP_VERSION_PATCH 5 +#define JSONCPP_VERSION_QUALIFIER +#define JSONCPP_VERSION_HEXA \ + ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ + (JSONCPP_VERSION_PATCH << 8)) + +#ifdef JSONCPP_USING_SECURE_MEMORY +#undef JSONCPP_USING_SECURE_MEMORY +#endif +#define JSONCPP_USING_SECURE_MEMORY 0 +// If non-zero, the library zeroes any memory that it has allocated before +// it frees its memory. + +#endif // JSON_VERSION_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/writer.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/writer.h new file mode 100644 index 0000000000000000000000000000000000000000..acf7c35f17ebcc5671a097247d5a483c0ef12a82 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json/writer.h @@ -0,0 +1,369 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#pragma pack(push, 8) + +namespace Json { + +class Value; + +/** + * + * Usage: + * \code + * using namespace Json; + * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) + * { std::unique_ptr const writer( factory.newStreamWriter()); + * writer->write(value, &std::cout); + * std::cout << std::endl; // add lf and flush + * } + * \endcode + */ +class JSON_API StreamWriter { +protected: + OStream* sout_; // not owned; will not delete +public: + StreamWriter(); + virtual ~StreamWriter(); + /** Write Value into document as configured in sub-class. + * Do not take ownership of sout, but maintain a reference during function. + * \pre sout != NULL + * \return zero on success (For now, we always return zero, so check the + * stream instead.) \throw std::exception possibly, depending on + * configuration + */ + virtual int write(Value const& root, OStream* sout) = 0; + + /** \brief A simple abstract factory. + */ + class JSON_API Factory { + public: + virtual ~Factory(); + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const = 0; + }; // Factory +}; // StreamWriter + +/** \brief Write into stringstream, then return string, for convenience. + * A StreamWriter will be created from the factory, used, and then deleted. + */ +String JSON_API writeString(StreamWriter::Factory const& factory, + Value const& root); + +/** \brief Build a StreamWriter implementation. + +* Usage: +* \code +* using namespace Json; +* Value value = ...; +* StreamWriterBuilder builder; +* builder["commentStyle"] = "None"; +* builder["indentation"] = " "; // or whatever you like +* std::unique_ptr writer( +* builder.newStreamWriter()); +* writer->write(value, &std::cout); +* std::cout << std::endl; // add lf and flush +* \endcode +*/ +class JSON_API StreamWriterBuilder : public StreamWriter::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + * Available settings (case-sensitive): + * - "commentStyle": "None" or "All" + * - "indentation": "". + * - Setting this to an empty string also omits newline characters. + * - "enableYAMLCompatibility": false or true + * - slightly change the whitespace around colons + * - "dropNullPlaceholders": false or true + * - Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + * - "useSpecialFloats": false or true + * - If true, outputs non-finite floating point values in the following way: + * NaN values as "NaN", positive infinity as "Infinity", and negative + * infinity as "-Infinity". + * - "precision": int + * - Number of precision digits for formatting of real values. + * - "precisionType": "significant"(default) or "decimal" + * - Type of precision for formatting of real values. + * - "emitUTF8": false or true + * - If true, outputs raw UTF8 strings instead of escaping them. + + * You can examine 'settings_` yourself + * to see the defaults. You can also write and read them just like any + * JSON Value. + * \sa setDefaults() + */ + Json::Value settings_; + + StreamWriterBuilder(); + ~StreamWriterBuilder() override; + + /** + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + StreamWriter* newStreamWriter() const override; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + /** A simple way to update a specific setting. + */ + Value& operator[](const String& key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults + */ + static void setDefaults(Json::Value* settings); +}; + +/** \brief Abstract class for writers. + * \deprecated Use StreamWriter. (And really, this is an implementation detail.) + */ +class JSON_API Writer { +public: + virtual ~Writer(); + + virtual String write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON format + *without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' + *consumption, + * but may be useful to support feature such as RPC where bandwidth is limited. + * \sa Reader, Value + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSON_API FastWriter + : public Writer { +public: + FastWriter(); + ~FastWriter() override = default; + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + String write(const Value& root) override; + +private: + void writeValue(const Value& value); + + String document_; + bool yamlCompatibilityEnabled_{false}; + bool dropNullPlaceholders_{false}; + bool omitEndingLineFeed_{false}; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSON_API + StyledWriter : public Writer { +public: + StyledWriter(); + ~StyledWriter() override = default; + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + String write(const Value& root) override; + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); + void writeIndent(); + void writeWithIndent(const String& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); + + using ChildValues = std::vector; + + ChildValues childValues_; + String document_; + String indentString_; + unsigned int rightMargin_{74}; + unsigned int indentSize_{3}; + bool addChildValues_{false}; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSON_API + StyledStreamWriter { +public: + /** + * \param indentation Each level will be indented by this amount extra. + */ + StyledStreamWriter(String indentation = "\t"); + ~StyledStreamWriter() = default; + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(OStream& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); + void writeIndent(); + void writeWithIndent(const String& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); + + using ChildValues = std::vector; + + ChildValues childValues_; + OStream* document_; + String indentString_; + unsigned int rightMargin_{74}; + String indentation_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(JSON_HAS_INT64) +String JSON_API valueToString(Int value); +String JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +String JSON_API valueToString(LargestInt value); +String JSON_API valueToString(LargestUInt value); +String JSON_API valueToString( + double value, unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); +String JSON_API valueToString(bool value); +String JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API OStream& operator<<(OStream&, const Value& root); + +} // namespace Json + +#pragma pack(pop) + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_reader.cpp b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02f4b2f25afe228b508364ec8f1ca1db76f1bacc --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_reader.cpp @@ -0,0 +1,1992 @@ +// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors +// Copyright (C) 2016 InfoTeCS JSC. All rights reserved. +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#if __cplusplus >= 201103L + +#if !defined(sscanf) +#define sscanf std::sscanf +#endif + +#endif //__cplusplus + +#if defined(_MSC_VER) +#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#endif //_MSC_VER + +#if defined(_MSC_VER) +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile +// time to change the stack limit +#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) +#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 +#endif + +static size_t const stackLimit_g = + JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() + +namespace Json { + +#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) +using CharReaderPtr = std::unique_ptr; +#else +using CharReaderPtr = std::auto_ptr; +#endif + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() = default; + +Features Features::all() { return {}; } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + features.allowDroppedNullPlaceholders_ = false; + features.allowNumericKeys_ = false; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { + return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() : features_(Features::all()) {} + +Reader::Reader(const Features& features) : features_(features) {} + +bool Reader::parse(const std::string& document, Value& root, + bool collectComments) { + document_.assign(document.begin(), document.end()); + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& is, Value& root, bool collectComments) { + // std::istream_iterator begin(is); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since String is reference-counted, this at least does not + // create an extra copy. + String doc(std::istreambuf_iterator(is), {}); + return parse(doc.data(), doc.data() + doc.size(), root, collectComments); +} + +bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + // readValue() may call itself only if it calls readObject() or ReadArray(). + // These methods execute nodes_.push() just before and nodes_.pop)() just + // after calling readValue(). parse() executes one nodes_.push(), so > instead + // of >=. + if (nodes_.size() > stackLimit_g) + throwRuntimeError("Exceeded stackLimit in readValue()."); + + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenFalse: { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNull: { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return ok; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(const Char* pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { + String normalized; + normalized.reserve(static_cast(end - begin)); + Reader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void Reader::addComment(Location begin, Location end, + CommentPlacement placement) { + assert(collectComments_); + const String& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != nullptr); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool Reader::readCStyleComment() { + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void Reader::readNumber() { + Location p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : '\0'; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } +} + +bool Reader::readString() { + Char c = '\0'; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& token) { + Token tokenName; + String name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name.clear(); + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); +} + +bool Reader::readArray(Token& token) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + skipSpaces(); + if (current_ != end_ && *current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token currentToken; + // Accept Comment after last item in the array. + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); + } + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); + } + if (currentToken.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + auto digit(static_cast(c - '0')); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative && value == maxIntegerValue) + decoded = Value::minLargestInt; + else if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + String buffer(token.start_, token.end_); + IStringStream is(buffer); + if (!(is >> value)) + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + String decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeString(Token& token, String& decoded) { + decoded.reserve(static_cast(token.end_ - token.start_ - 2)); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, Location& current, + Location end, unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, current); + if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, + unsigned int& ret_unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", token, + current); + int unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, current); + } + ret_unicode = static_cast(unicode); + return true; +} + +bool Reader::addError(const String& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + size_t const errorCount = errors_.size(); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +String Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +// Deprecated. Preserved for backward compatibility +String Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +String Reader::getFormattedErrorMessages() const { + String formattedMessage; + for (const auto& error : errors_) { + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector Reader::getStructuredErrors() const { + std::vector allErrors; + for (const auto& error : errors_) { + Reader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool Reader::pushError(const Value& value, const String& message) { + ptrdiff_t const length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = nullptr; + errors_.push_back(info); + return true; +} + +bool Reader::pushError(const Value& value, const String& message, + const Value& extra) { + ptrdiff_t const length = end_ - begin_; + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool Reader::good() const { return errors_.empty(); } + +// Originally copied from the Features class (now deprecated), used internally +// for features implementation. +class OurFeatures { +public: + static OurFeatures all(); + bool allowComments_; + bool allowTrailingCommas_; + bool strictRoot_; + bool allowDroppedNullPlaceholders_; + bool allowNumericKeys_; + bool allowSingleQuotes_; + bool failIfExtra_; + bool rejectDupKeys_; + bool allowSpecialFloats_; + bool skipBom_; + size_t stackLimit_; +}; // OurFeatures + +OurFeatures OurFeatures::all() { return {}; } + +// Implementation of class Reader +// //////////////////////////////// + +// Originally copied from the Reader class (now deprecated), used internally +// for implementing JSON reading. +class OurReader { +public: + using Char = char; + using Location = const Char*; + struct StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + String message; + }; + + explicit OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments = true); + String getFormattedErrorMessages() const; + std::vector getStructuredErrors() const; + +private: + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl + + enum TokenType { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenNaN, + tokenPosInf, + tokenNegInf, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo { + public: + Token token_; + String message_; + Location extra_; + }; + + using Errors = std::deque; + + bool readToken(Token& token); + void skipSpaces(); + void skipBom(bool skipBom); + bool match(const Char* pattern, int patternLength); + bool readComment(); + bool readCStyleComment(bool* containsNewLineResult); + bool readCppStyleComment(); + bool readString(); + bool readStringSingleQuote(); + bool readNumber(bool checkInf); + bool readValue(); + bool readObject(Token& token); + bool readArray(Token& token); + bool decodeNumber(Token& token); + bool decodeNumber(Token& token, Value& decoded); + bool decodeString(Token& token); + bool decodeString(Token& token, String& decoded); + bool decodeDouble(Token& token); + bool decodeDouble(Token& token, Value& decoded); + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, + unsigned int& unicode); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); + bool recoverFromError(TokenType skipUntilToken); + bool addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken); + void skipUntilSpace(); + Value& currentValue(); + Char getNextChar(); + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; + void addComment(Location begin, Location end, CommentPlacement placement); + void skipCommentTokens(Token& token); + + static String normalizeEOL(Location begin, Location end); + static bool containsNewLine(Location begin, Location end); + + using Nodes = std::stack; + + Nodes nodes_{}; + Errors errors_{}; + String document_{}; + Location begin_ = nullptr; + Location end_ = nullptr; + Location current_ = nullptr; + Location lastValueEnd_ = nullptr; + Value* lastValue_ = nullptr; + bool lastValueHasAComment_ = false; + String commentsBefore_{}; + + OurFeatures const features_; + bool collectComments_ = false; +}; // OurReader + +// complete copy of Read impl, for OurReader + +bool OurReader::containsNewLine(OurReader::Location begin, + OurReader::Location end) { + return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); +} + +OurReader::OurReader(OurFeatures const& features) : features_(features) {} + +bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; + commentsBefore_.clear(); + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + // skip byte order mark if it exists at the beginning of the UTF-8 text. + skipBom(features_.skipBom_); + bool successful = readValue(); + nodes_.pop(); + Token token; + skipCommentTokens(token); + if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) { + addError("Extra non-whitespace after JSON value.", token); + return false; + } + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool OurReader::readValue() { + // To preserve the old behaviour we cast size_t to int. + if (nodes_.size() > features_.stackLimit_) + throwRuntimeError("Exceeded stackLimit in readValue()."); + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_.clear(); + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenFalse: { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNull: { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNaN: { + Value v(std::numeric_limits::quiet_NaN()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenPosInf: { + Value v(std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenNegInf: { + Value v(-std::numeric_limits::infinity()); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // else, fall through ... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValueHasAComment_ = false; + lastValue_ = ¤tValue(); + } + + return successful; +} + +void OurReader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool OurReader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + } else { + // If we don't allow single quotes, this is a failure case. + ok = false; + } + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token.type_ = tokenNumber; + readNumber(false); + break; + case '-': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenNegInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; + case '+': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenPosInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case 'N': + if (features_.allowSpecialFloats_) { + token.type_ = tokenNaN; + ok = match("aN", 2); + } else { + ok = false; + } + break; + case 'I': + if (features_.allowSpecialFloats_) { + token.type_ = tokenPosInf; + ok = match("nfinity", 7); + } else { + ok = false; + } + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return ok; +} + +void OurReader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +void OurReader::skipBom(bool skipBom) { + // The default behavior is to skip BOM. + if (skipBom) { + if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) { + begin_ += 3; + current_ = begin_; + } + } +} + +bool OurReader::match(const Char* pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool OurReader::readComment() { + const Location commentBegin = current_ - 1; + const Char c = getNextChar(); + bool successful = false; + bool cStyleWithEmbeddedNewline = false; + + const bool isCStyleComment = (c == '*'); + const bool isCppStyleComment = (c == '/'); + if (isCStyleComment) { + successful = readCStyleComment(&cStyleWithEmbeddedNewline); + } else if (isCppStyleComment) { + successful = readCppStyleComment(); + } + + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + + if (!lastValueHasAComment_) { + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (isCppStyleComment || !cStyleWithEmbeddedNewline) { + placement = commentAfterOnSameLine; + lastValueHasAComment_ = true; + } + } + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +String OurReader::normalizeEOL(OurReader::Location begin, + OurReader::Location end) { + String normalized; + normalized.reserve(static_cast(end - begin)); + OurReader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void OurReader::addComment(Location begin, Location end, + CommentPlacement placement) { + assert(collectComments_); + const String& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != nullptr); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool OurReader::readCStyleComment(bool* containsNewLineResult) { + *containsNewLineResult = false; + + while ((current_ + 1) < end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + if (c == '\n') + *containsNewLineResult = true; + } + + return getNextChar() == '/'; +} + +bool OurReader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +bool OurReader::readNumber(bool checkInf) { + Location p = current_; + if (checkInf && p != end_ && *p == 'I') { + current_ = ++p; + return false; + } + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : '\0'; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : '\0'; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : '\0'; + } + return true; +} +bool OurReader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool OurReader::readStringSingleQuote() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '\'') + break; + } + return c == '\''; +} + +bool OurReader::readObject(Token& token) { + Token tokenName; + String name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && + (name.empty() || + features_.allowTrailingCommas_)) // empty object or trailing comma + return true; + name.clear(); + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + if (name.length() >= (1U << 30)) + throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + String msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover(msg, tokenName, tokenObjectEnd); + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); +} + +bool OurReader::readArray(Token& token) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(token.start_ - begin_); + int index = 0; + for (;;) { + skipSpaces(); + if (current_ != end_ && *current_ == ']' && + (index == 0 || + (features_.allowTrailingCommas_ && + !features_.allowDroppedNullPlaceholders_))) // empty array or trailing + // comma + { + Token endArray; + readToken(endArray); + return true; + } + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token currentToken; + // Accept Comment after last item in the array. + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); + } + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); + } + if (currentToken.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool OurReader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + const bool isNegative = *current == '-'; + if (isNegative) { + ++current; + } + + // We assume we can represent the largest and smallest integer types as + // unsigned integers with separate sign. This is only true if they can fit + // into an unsigned integer. + static_assert(Value::maxLargestInt <= Value::maxLargestUInt, + "Int must be smaller than UInt"); + + // We need to convert minLargestInt into a positive number. The easiest way + // to do this conversion is to assume our "threshold" value of minLargestInt + // divided by 10 can fit in maxLargestInt when absolute valued. This should + // be a safe assumption. + static_assert(Value::minLargestInt <= -Value::maxLargestInt, + "The absolute value of minLargestInt must be greater than or " + "equal to maxLargestInt"); + static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, + "The absolute value of minLargestInt must be only 1 magnitude " + "larger than maxLargest Int"); + + static constexpr Value::LargestUInt positive_threshold = + Value::maxLargestUInt / 10; + static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10; + + // For the negative values, we have to be more careful. Since typically + // -Value::minLargestInt will cause an overflow, we first divide by 10 and + // then take the inverse. This assumes that minLargestInt is only a single + // power of 10 different in magnitude, which we check above. For the last + // digit, we take the modulus before negating for the same reason. + static constexpr auto negative_threshold = + Value::LargestUInt(-(Value::minLargestInt / 10)); + static constexpr auto negative_last_digit = + Value::UInt(-(Value::minLargestInt % 10)); + + const Value::LargestUInt threshold = + isNegative ? negative_threshold : positive_threshold; + const Value::UInt max_last_digit = + isNegative ? negative_last_digit : positive_last_digit; + + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + + const auto digit(static_cast(c - '0')); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, meaing value == threshold, + // b) this is the last digit, or + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > max_last_digit) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + + if (isNegative) { + // We use the same magnitude assumption here, just in case. + const auto last_digit = static_cast(value % 10); + decoded = -Value::LargestInt(value / 10) * 10 - last_digit; + } else if (value <= Value::LargestUInt(Value::maxLargestInt)) { + decoded = Value::LargestInt(value); + } else { + decoded = value; + } + + return true; +} + +bool OurReader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + const String buffer(token.start_, token.end_); + IStringStream is(buffer); + if (!(is >> value)) { + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); + } + decoded = value; + return true; +} + +bool OurReader::decodeString(Token& token) { + String decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeString(Token& token, String& decoded) { + decoded.reserve(static_cast(token.end_ - token.start_ - 2)); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current, + Location end, unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, current); + if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, current); + } + return true; +} + +bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, + unsigned int& ret_unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", token, + current); + int unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, current); + } + ret_unicode = static_cast(unicode); + return true; +} + +bool OurReader::addError(const String& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool OurReader::recoverFromError(TokenType skipUntilToken) { + size_t errorCount = errors_.size(); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool OurReader::addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& OurReader::currentValue() { return *(nodes_.top()); } + +OurReader::Char OurReader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void OurReader::getLocationLineAndColumn(Location location, int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +String OurReader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; + jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + return buffer; +} + +String OurReader::getFormattedErrorMessages() const { + String formattedMessage; + for (const auto& error : errors_) { + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector OurReader::getStructuredErrors() const { + std::vector allErrors; + for (const auto& error : errors_) { + OurReader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +class OurCharReader : public CharReader { + bool const collectComments_; + OurReader reader_; + +public: + OurCharReader(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) override { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; + } +}; + +CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } +CharReaderBuilder::~CharReaderBuilder() = default; +CharReader* CharReaderBuilder::newCharReader() const { + bool collectComments = settings_["collectComments"].asBool(); + OurFeatures features = OurFeatures::all(); + features.allowComments_ = settings_["allowComments"].asBool(); + features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool(); + features.strictRoot_ = settings_["strictRoot"].asBool(); + features.allowDroppedNullPlaceholders_ = + settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); + + // Stack limit is always a size_t, so we get this as an unsigned int + // regardless of it we have 64-bit integer support enabled. + features.stackLimit_ = static_cast(settings_["stackLimit"].asUInt()); + features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); + features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); + features.skipBom_ = settings_["skipBom"].asBool(); + return new OurCharReader(collectComments, features); +} + +bool CharReaderBuilder::validate(Json::Value* invalid) const { + static const auto& valid_keys = *new std::set{ + "collectComments", + "allowComments", + "allowTrailingCommas", + "strictRoot", + "allowDroppedNullPlaceholders", + "allowNumericKeys", + "allowSingleQuotes", + "stackLimit", + "failIfExtra", + "rejectDupKeys", + "allowSpecialFloats", + "skipBom", + }; + for (auto si = settings_.begin(); si != settings_.end(); ++si) { + auto key = si.name(); + if (valid_keys.count(key)) + continue; + if (invalid) + (*invalid)[key] = *si; + else + return false; + } + return invalid ? invalid->empty() : true; +} + +Value& CharReaderBuilder::operator[](const String& key) { + return settings_[key]; +} +// static +void CharReaderBuilder::strictMode(Json::Value* settings) { + //! [CharReaderBuilderStrictMode] + (*settings)["allowComments"] = false; + (*settings)["allowTrailingCommas"] = false; + (*settings)["strictRoot"] = true; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = true; + (*settings)["allowSpecialFloats"] = false; + (*settings)["skipBom"] = true; + //! [CharReaderBuilderStrictMode] +} +// static +void CharReaderBuilder::setDefaults(Json::Value* settings) { + //! [CharReaderBuilderDefaults] + (*settings)["collectComments"] = true; + (*settings)["allowComments"] = true; + (*settings)["allowTrailingCommas"] = true; + (*settings)["strictRoot"] = false; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = false; + (*settings)["rejectDupKeys"] = false; + (*settings)["allowSpecialFloats"] = false; + (*settings)["skipBom"] = true; + //! [CharReaderBuilderDefaults] +} + +////////////////////////////////// +// global functions + +bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root, + String* errs) { + OStringStream ssin; + ssin << sin.rdbuf(); + String doc = ssin.str(); + char const* begin = doc.data(); + char const* end = begin + doc.size(); + // Note that we do not actually need a null-terminator. + CharReaderPtr const reader(fact.newCharReader()); + return reader->parse(begin, end, root, errs); +} + +IStream& operator>>(IStream& sin, Value& root) { + CharReaderBuilder b; + String errs; + bool ok = parseFromStream(b, sin, &root, &errs); + if (!ok) { + throwRuntimeError(errs); + } + return sin; +} + +} // namespace Json diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_tool.h b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_tool.h new file mode 100644 index 0000000000000000000000000000000000000000..3d34f2e203f8bf7874ec3ae885fa85100bef8969 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_tool.h @@ -0,0 +1,138 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include +#endif + +// Also support old flag NO_LOCALE_SUPPORT +#ifdef NO_LOCALE_SUPPORT +#define JSONCPP_NO_LOCALE_SUPPORT +#endif + +#ifndef JSONCPP_NO_LOCALE_SUPPORT +#include +#endif + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { +static inline char getDecimalPoint() { +#ifdef JSONCPP_NO_LOCALE_SUPPORT + return '\0'; +#else + struct lconv* lc = localeconv(); + return lc ? *(lc->decimal_point) : '\0'; +#endif +} + +/// Converts a unicode code-point to UTF-8. +static inline String codePointToUTF8(unsigned int cp) { + String result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +using UIntToStringBuffer = char[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned integer to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = static_cast(value % 10U + static_cast('0')); + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +template Iter fixNumericLocale(Iter begin, Iter end) { + for (; begin != end; ++begin) { + if (*begin == ',') { + *begin = '.'; + } + } + return begin; +} + +template void fixNumericLocaleInput(Iter begin, Iter end) { + char decimalPoint = getDecimalPoint(); + if (decimalPoint == '\0' || decimalPoint == '.') { + return; + } + for (; begin != end; ++begin) { + if (*begin == '.') { + *begin = decimalPoint; + } + } +} + +/** + * Return iterator that would be the new end of the range [begin,end), if we + * were to delete zeros in the end of string, but not the last zero before '.'. + */ +template +Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) { + for (; begin != end; --end) { + if (*(end - 1) != '0') { + return end; + } + // Don't delete the last zero before the decimal point. + if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') { + if (precision) { + return end; + } + return end - 2; + } + } + return end; +} + +} // namespace Json + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_value.cpp b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_value.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c99b5b40c9a26a56a43c2de9f22eb0a5620416e4 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_value.cpp @@ -0,0 +1,1634 @@ +// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include + +// Provide implementation equivalent of std::snprintf for older _MSC compilers +#if defined(_MSC_VER) && _MSC_VER < 1900 +#include +static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size, + const char* format, va_list ap) { + int count = -1; + if (size != 0) + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + return count; +} + +int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...) { + va_list ap; + va_start(ap, format); + const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + return count; +} +#endif + +// Disable warning C4702 : unreachable code +#if defined(_MSC_VER) +#pragma warning(disable : 4702) +#endif + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { +template +static std::unique_ptr cloneUnique(const std::unique_ptr& p) { + std::unique_ptr r; + if (p) { + r = std::unique_ptr(new T(*p)); + } + return r; +} + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +#define ALIGNAS(byte_alignment) +#endif + +// static +Value const& Value::nullSingleton() { + static Value const nullStatic; + return nullStatic; +} + +#if JSON_USE_NULLREF +// for backwards compatibility, we'll leave these global references around, but +// DO NOT use them in JSONCPP library code any more! +// static +Value const& Value::null = Value::nullSingleton(); + +// static +Value const& Value::nullRef = Value::nullSingleton(); +#endif + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + // The casts can lose precision, but we are looking only for + // an approximate range. Might fail on edge cases though. ~cdunn + return d >= static_cast(min) && d <= static_cast(max); +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + + static_cast(Int64(value & 1)); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, size_t length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= static_cast(Value::maxInt)) + length = Value::maxInt - 1; + + auto newString = static_cast(malloc(length + 1)); + if (newString == nullptr) { + throwRuntimeError("in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + } + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/* Record the length as a prefix. + */ +static inline char* duplicateAndPrefixStringValue(const char* value, + unsigned int length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + JSON_ASSERT_MESSAGE(length <= static_cast(Value::maxInt) - + sizeof(unsigned) - 1U, + "in Json::Value::duplicateAndPrefixStringValue(): " + "length too big for prefixing"); + size_t actualLength = sizeof(length) + length + 1; + auto newString = static_cast(malloc(actualLength)); + if (newString == nullptr) { + throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); + } + *reinterpret_cast(newString) = length; + memcpy(newString + sizeof(unsigned), value, length); + newString[actualLength - 1U] = + 0; // to avoid buffer over-run accidents by users later + return newString; +} +inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, + unsigned* length, char const** value) { + if (!isPrefixed) { + *length = static_cast(strlen(prefixed)); + *value = prefixed; + } else { + *length = *reinterpret_cast(prefixed); + *value = prefixed + sizeof(unsigned); + } +} +/** Free the string duplicated by + * duplicateStringValue()/duplicateAndPrefixStringValue(). + */ +#if JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { + unsigned length = 0; + char const* valueDecoded; + decodePrefixedString(true, value, &length, &valueDecoded); + size_t const size = sizeof(unsigned) + length + 1U; + memset(value, 0, size); + free(value); +} +static inline void releaseStringValue(char* value, unsigned length) { + // length==0 => we allocated the strings memory + size_t size = (length == 0) ? strlen(value) : length; + memset(value, 0, size); + free(value); +} +#else // !JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { free(value); } +static inline void releaseStringValue(char* value, unsigned) { free(value); } +#endif // JSONCPP_USING_SECURE_MEMORY + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +#if JSON_USE_EXCEPTION +Exception::Exception(String msg) : msg_(std::move(msg)) {} +Exception::~Exception() noexcept = default; +char const* Exception::what() const noexcept { return msg_.c_str(); } +RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} +LogicError::LogicError(String const& msg) : Exception(msg) {} +JSONCPP_NORETURN void throwRuntimeError(String const& msg) { + throw RuntimeError(msg); +} +JSONCPP_NORETURN void throwLogicError(String const& msg) { + throw LogicError(msg); +} +#else // !JSON_USE_EXCEPTION +JSONCPP_NORETURN void throwRuntimeError(String const& msg) { + std::cerr << msg << std::endl; + abort(); +} +JSONCPP_NORETURN void throwLogicError(String const& msg) { + std::cerr << msg << std::endl; + abort(); +} +#endif + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +// Notes: policy_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {} + +Value::CZString::CZString(char const* str, unsigned length, + DuplicationPolicy allocate) + : cstr_(str) { + // allocate != duplicate + storage_.policy_ = allocate & 0x3; + storage_.length_ = length & 0x3FFFFFFF; +} + +Value::CZString::CZString(const CZString& other) { + cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_); + storage_.policy_ = + static_cast( + other.cstr_ + ? (static_cast(other.storage_.policy_) == + noDuplication + ? noDuplication + : duplicate) + : static_cast(other.storage_.policy_)) & + 3U; + storage_.length_ = other.storage_.length_; +} + +Value::CZString::CZString(CZString&& other) noexcept + : cstr_(other.cstr_), index_(other.index_) { + other.cstr_ = nullptr; +} + +Value::CZString::~CZString() { + if (cstr_ && storage_.policy_ == duplicate) { + releaseStringValue(const_cast(cstr_), + storage_.length_ + 1U); // +1 for null terminating + // character for sake of + // completeness but not actually + // necessary + } +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(const CZString& other) { + cstr_ = other.cstr_; + index_ = other.index_; + return *this; +} + +Value::CZString& Value::CZString::operator=(CZString&& other) noexcept { + cstr_ = other.cstr_; + index_ = other.index_; + other.cstr_ = nullptr; + return *this; +} + +bool Value::CZString::operator<(const CZString& other) const { + if (!cstr_) + return index_ < other.index_; + // return strcmp(cstr_, other.cstr_) < 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this->cstr_ && other.cstr_); + int comp = memcmp(this->cstr_, other.cstr_, min_len); + if (comp < 0) + return true; + if (comp > 0) + return false; + return (this_len < other_len); +} + +bool Value::CZString::operator==(const CZString& other) const { + if (!cstr_) + return index_ == other.index_; + // return strcmp(cstr_, other.cstr_) == 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + if (this_len != other_len) + return false; + JSON_ASSERT(this->cstr_ && other.cstr_); + int comp = memcmp(this->cstr_, other.cstr_, this_len); + return comp == 0; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +// const char* Value::CZString::c_str() const { return cstr_; } +const char* Value::CZString::data() const { return cstr_; } +unsigned Value::CZString::length() const { return storage_.length_; } +bool Value::CZString::isStaticString() const { + return storage_.policy_ == noDuplication; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType type) { + static char const emptyString[] = ""; + initBasic(type); + switch (type) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + // allocated_ == false, so this is safe. + value_.string_ = const_cast(static_cast(emptyString)); + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; +} + +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; +} +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; +} +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; +} + +Value::Value(const char* value) { + initBasic(stringValue, true); + JSON_ASSERT_MESSAGE(value != nullptr, + "Null Value Passed to Value Constructor"); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast(strlen(value))); +} + +Value::Value(const char* begin, const char* end) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(begin, static_cast(end - begin)); +} + +Value::Value(const String& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue( + value.data(), static_cast(value.length())); +} + +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); +} + +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; +} + +Value::Value(const Value& other) { + dupPayload(other); + dupMeta(other); +} + +Value::Value(Value&& other) noexcept { + initBasic(nullValue); + swap(other); +} + +Value::~Value() { + releasePayload(); + value_.uint_ = 0; +} + +Value& Value::operator=(const Value& other) { + Value(other).swap(*this); + return *this; +} + +Value& Value::operator=(Value&& other) noexcept { + other.swap(*this); + return *this; +} + +void Value::swapPayload(Value& other) { + std::swap(bits_, other.bits_); + std::swap(value_, other.value_); +} + +void Value::copyPayload(const Value& other) { + releasePayload(); + dupPayload(other); +} + +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); +} + +void Value::copy(const Value& other) { + copyPayload(other); + dupMeta(other); +} + +ValueType Value::type() const { + return static_cast(bits_.value_type_); +} + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type() - other.type(); + if (typeDelta) + return typeDelta < 0; + switch (type()) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: { + if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { + return other.value_.string_ != nullptr; + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, + &other_str); + unsigned min_len = std::min(this_len, other_len); + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, min_len); + if (comp < 0) + return true; + if (comp > 0) + return false; + return (this_len < other_len); + } + case arrayValue: + case objectValue: { + auto thisSize = value_.map_->size(); + auto otherSize = other.value_.map_->size(); + if (thisSize != otherSize) + return thisSize < otherSize; + return (*value_.map_) < (*other.value_.map_); + } + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + if (type() != other.type()) + return false; + switch (type()) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: { + if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { + return (value_.string_ == other.value_.string_); + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, + &other_str); + if (this_len != other_len) + return false; + JSON_ASSERT(this_str && other_str); + int comp = memcmp(this_str, other_str, this_len); + return comp == 0; + } + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type() == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == nullptr) + return nullptr; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + return this_str; +} + +#if JSONCPP_USING_SECURE_MEMORY +unsigned Value::getCStringLength() const { + JSON_ASSERT_MESSAGE(type() == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + return this_len; +} +#endif + +bool Value::getString(char const** begin, char const** end) const { + if (type() != stringValue) + return false; + if (value_.string_ == nullptr) + return false; + unsigned length; + decodePrefixedString(this->isAllocated(), this->value_.string_, &length, + begin); + *end = *begin + length; + return true; +} + +String Value::asString() const { + switch (type()) { + case nullValue: + return ""; + case stringValue: { + if (value_.string_ == nullptr) + return ""; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + return String(this_str, this_len); + } + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +Value::Int Value::asInt() const { + switch (type()) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type()) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type()) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type()) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type()) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type()) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + // This can fail (silently?) if the value is bigger than MAX_FLOAT. + return static_cast(integerToDouble(value_.uint_)); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0F : 0.0F; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type()) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ != 0; + case uintValue: + return value_.uint_ != 0; + case realValue: { + // According to JavaScript language zero or NaN is regarded as false + const auto value_classification = std::fpclassify(value_.real_); + return value_classification != FP_ZERO && value_classification != FP_NAN; + } + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type() == booleanValue && !value_.bool_) || + (type() == stringValue && asString().empty()) || + (type() == arrayValue && value_.map_->empty()) || + (type() == objectValue && value_.map_->empty()) || + type() == nullValue; + case intValue: + return isInt() || + (type() == realValue && InRange(value_.real_, minInt, maxInt)) || + type() == booleanValue || type() == nullValue; + case uintValue: + return isUInt() || + (type() == realValue && InRange(value_.real_, 0, maxUInt)) || + type() == booleanValue || type() == nullValue; + case realValue: + return isNumeric() || type() == booleanValue || type() == nullValue; + case booleanValue: + return isNumeric() || type() == booleanValue || type() == nullValue; + case stringValue: + return isNumeric() || type() == booleanValue || type() == stringValue || + type() == nullValue; + case arrayValue: + return type() == arrayValue || type() == nullValue; + case objectValue: + return type() == objectValue || type() == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0U; + return false; +} + +Value::operator bool() const { return !isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || + type() == objectValue, + "in Json::Value::clear(): requires complex value"); + start_ = 0; + limit_ = 0; + switch (type()) { + case arrayValue: + case objectValue: + value_.map_->clear(); + break; + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type() == nullValue) + *this = Value(arrayValue); + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + for (ArrayIndex i = oldSize; i < newSize; ++i) + (*this)[i]; + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + JSON_ASSERT(size() == newSize); + } +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type() == nullValue) + *this = Value(arrayValue); + CZString key(index); + auto it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type() == nullValue) + return nullSingleton(); + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return nullSingleton(); + return (*it).second; +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +void Value::initBasic(ValueType type, bool allocated) { + setType(type); + setIsAllocated(allocated); + comments_ = Comments{}; + start_ = 0; + limit_ = 0; +} + +void Value::dupPayload(const Value& other) { + setType(other.type()); + setIsAllocated(false); + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.isAllocated()) { + unsigned len; + char const* str; + decodePrefixedString(other.isAllocated(), other.value_.string_, &len, + &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + setIsAllocated(true); + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::releasePayload() { + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (isAllocated()) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::dupMeta(const Value& other) { + comments_ = other.comments_; + start_ = other.start_; + limit_ = other.limit_; +} + +// Access an object value by name, create a null member if it does not exist. +// @pre Type of '*this' is object or null. +// @param key is null-terminated. +Value& Value::resolveReference(const char* key) { + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type() == nullValue) + *this = Value(objectValue); + CZString actualKey(key, static_cast(strlen(key)), + CZString::noDuplication); // NOTE! + auto it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +// @param key is not null-terminated. +Value& Value::resolveReference(char const* key, char const* end) { + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == objectValue, + "in Json::Value::resolveReference(key, end): requires objectValue"); + if (type() == nullValue) + *this = Value(objectValue); + CZString actualKey(key, static_cast(end - key), + CZString::duplicateOnCopy); + auto it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullSingleton()); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &nullSingleton() ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +Value const* Value::find(char const* begin, char const* end) const { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::find(begin, end): requires " + "objectValue or nullValue"); + if (type() == nullValue) + return nullptr; + CZString actualKey(begin, static_cast(end - begin), + CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return nullptr; + return &(*it).second; +} +Value* Value::demand(char const* begin, char const* end) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::demand(begin, end): requires " + "objectValue or nullValue"); + return &resolveReference(begin, end); +} +const Value& Value::operator[](const char* key) const { + Value const* found = find(key, key + strlen(key)); + if (!found) + return nullSingleton(); + return *found; +} +Value const& Value::operator[](const String& key) const { + Value const* found = find(key.data(), key.data() + key.length()); + if (!found) + return nullSingleton(); + return *found; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, key + strlen(key)); +} + +Value& Value::operator[](const String& key) { + return resolveReference(key.data(), key.data() + key.length()); +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key.c_str()); +} + +Value& Value::append(const Value& value) { return append(Value(value)); } + +Value& Value::append(Value&& value) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::append: requires arrayValue"); + if (type() == nullValue) { + *this = Value(arrayValue); + } + return this->value_.map_->emplace(size(), std::move(value)).first->second; +} + +bool Value::insert(ArrayIndex index, const Value& newValue) { + return insert(index, Value(newValue)); +} + +bool Value::insert(ArrayIndex index, Value&& newValue) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::insert: requires arrayValue"); + ArrayIndex length = size(); + if (index > length) { + return false; + } + for (ArrayIndex i = length; i > index; i--) { + (*this)[i] = std::move((*this)[i - 1]); + } + (*this)[index] = std::move(newValue); + return true; +} + +Value Value::get(char const* begin, char const* end, + Value const& defaultValue) const { + Value const* found = find(begin, end); + return !found ? defaultValue : *found; +} +Value Value::get(char const* key, Value const& defaultValue) const { + return get(key, key + strlen(key), defaultValue); +} +Value Value::get(String const& key, Value const& defaultValue) const { + return get(key.data(), key.data() + key.length(), defaultValue); +} + +bool Value::removeMember(const char* begin, const char* end, Value* removed) { + if (type() != objectValue) { + return false; + } + CZString actualKey(begin, static_cast(end - begin), + CZString::noDuplication); + auto it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return false; + if (removed) + *removed = std::move(it->second); + value_.map_->erase(it); + return true; +} +bool Value::removeMember(const char* key, Value* removed) { + return removeMember(key, key + strlen(key), removed); +} +bool Value::removeMember(String const& key, Value* removed) { + return removeMember(key.data(), key.data() + key.length(), removed); +} +void Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type() == nullValue) + return; + + CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); + value_.map_->erase(actualKey); +} +void Value::removeMember(const String& key) { removeMember(key.c_str()); } + +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type() != arrayValue) { + return false; + } + CZString key(index); + auto it = value_.map_->find(key); + if (it == value_.map_->end()) { + return false; + } + if (removed) + *removed = it->second; + ArrayIndex oldSize = size(); + // shift left all items left, into the place of the "removed" + for (ArrayIndex i = index; i < (oldSize - 1); ++i) { + CZString keey(i); + (*value_.map_)[keey] = (*this)[i + 1]; + } + // erase the last one ("leftover") + CZString keyLast(oldSize - 1); + auto itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); + return true; +} + +bool Value::isMember(char const* begin, char const* end) const { + Value const* value = find(begin, end); + return nullptr != value; +} +bool Value::isMember(char const* key) const { + return isMember(key, key + strlen(key)); +} +bool Value::isMember(String const& key) const { + return isMember(key.data(), key.data() + key.length()); +} + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type() == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) { + members.push_back(String((*it).first.data(), (*it).first.length())); + } + return members; +} + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type() == nullValue; } + +bool Value::isBool() const { return type() == booleanValue; } + +bool Value::isInt() const { + switch (type()) { + case intValue: +#if defined(JSON_HAS_INT64) + return value_.int_ >= minInt && value_.int_ <= maxInt; +#else + return true; +#endif + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type()) { + case intValue: +#if defined(JSON_HAS_INT64) + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); +#else + return value_.int_ >= 0; +#endif + case uintValue: +#if defined(JSON_HAS_INT64) + return value_.uint_ <= maxUInt; +#else + return true; +#endif + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type()) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type()) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { + switch (type()) { + case intValue: + case uintValue: + return true; + case realValue: +#if defined(JSON_HAS_INT64) + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); +#else + return value_.real_ >= minInt && value_.real_ <= maxUInt && + IsIntegral(value_.real_); +#endif // JSON_HAS_INT64 + default: + break; + } + return false; +} + +bool Value::isDouble() const { + return type() == intValue || type() == uintValue || type() == realValue; +} + +bool Value::isNumeric() const { return isDouble(); } + +bool Value::isString() const { return type() == stringValue; } + +bool Value::isArray() const { return type() == arrayValue; } + +bool Value::isObject() const { return type() == objectValue; } + +Value::Comments::Comments(const Comments& that) + : ptr_{cloneUnique(that.ptr_)} {} + +Value::Comments::Comments(Comments&& that) noexcept + : ptr_{std::move(that.ptr_)} {} + +Value::Comments& Value::Comments::operator=(const Comments& that) { + ptr_ = cloneUnique(that.ptr_); + return *this; +} + +Value::Comments& Value::Comments::operator=(Comments&& that) noexcept { + ptr_ = std::move(that.ptr_); + return *this; +} + +bool Value::Comments::has(CommentPlacement slot) const { + return ptr_ && !(*ptr_)[slot].empty(); +} + +String Value::Comments::get(CommentPlacement slot) const { + if (!ptr_) + return {}; + return (*ptr_)[slot]; +} + +void Value::Comments::set(CommentPlacement slot, String comment) { + if (slot >= CommentPlacement::numberOfCommentPlacement) + return; + if (!ptr_) + ptr_ = std::unique_ptr(new Array()); + (*ptr_)[slot] = std::move(comment); +} + +void Value::setComment(String comment, CommentPlacement placement) { + if (!comment.empty() && (comment.back() == '\n')) { + // Always discard trailing newline, to aid indentation. + comment.pop_back(); + } + JSON_ASSERT(!comment.empty()); + JSON_ASSERT_MESSAGE( + comment[0] == '\0' || comment[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + comments_.set(placement, std::move(comment)); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_.has(placement); +} + +String Value::getComment(CommentPlacement placement) const { + return comments_.get(placement); +} + +void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } + +void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } + +ptrdiff_t Value::getOffsetStart() const { return start_; } + +ptrdiff_t Value::getOffsetLimit() const { return limit_; } + +String Value::toStyledString() const { + StreamWriterBuilder builder; + + String out = this->hasComment(commentBefore) ? "\n" : ""; + out += Json::writeString(builder, *this); + out += '\n'; + + return out; +} + +Value::const_iterator Value::begin() const { + switch (type()) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; + default: + break; + } + return {}; +} + +Value::const_iterator Value::end() const { + switch (type()) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; + default: + break; + } + return {}; +} + +Value::iterator Value::begin() { + switch (type()) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type()) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() = default; + +PathArgument::PathArgument(ArrayIndex index) + : index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {} + +PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2, + const PathArgument& a3, const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.reserve(5); + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const String& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + auto itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *++current != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.' || *current == ']') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(String(beginName, current)); + } + } +} + +void Path::addPathInArg(const String& /*path*/, const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg++); + } +} + +void Path::invalidPath(const String& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (const auto& arg : args_) { + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... ) + return Value::nullSingleton(); + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + return Value::nullSingleton(); + } + node = &((*node)[arg.key_]); + if (node == &Value::nullSingleton()) { + // Error: unable to resolve path (object has no member named '' at + // position...) + return Value::nullSingleton(); + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (const auto& arg : args_) { + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::nullSingleton()) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (const auto& arg : args_) { + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_valueiterator.inl b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_valueiterator.inl new file mode 100644 index 0000000000000000000000000000000000000000..d6128b8edf091d57ca6e86af77069ddb9f098bc9 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_valueiterator.inl @@ -0,0 +1,156 @@ +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() : current_() {} + +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} + +Value& ValueIteratorBase::deref() { return current_->second; } +const Value& ValueIteratorBase::deref() const { return current_->second; } + +void ValueIteratorBase::increment() { ++current_; } + +void ValueIteratorBase::decrement() { --current_; } + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +} + +void ValueIteratorBase::copy(const SelfType& other) { + current_ = other.current_; + isNull_ = other.isNull_; +} + +Value ValueIteratorBase::key() const { + const Value::CZString czstring = (*current_).first; + if (czstring.data()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.data())); + return Value(czstring.data(), czstring.data() + czstring.length()); + } + return Value(czstring.index()); +} + +UInt ValueIteratorBase::index() const { + const Value::CZString czstring = (*current_).first; + if (!czstring.data()) + return czstring.index(); + return Value::UInt(-1); +} + +String ValueIteratorBase::name() const { + char const* keey; + char const* end; + keey = memberName(&end); + if (!keey) + return String(); + return String(keey, end); +} + +char const* ValueIteratorBase::memberName() const { + const char* cname = (*current_).first.data(); + return cname ? cname : ""; +} + +char const* ValueIteratorBase::memberName(char const** end) const { + const char* cname = (*current_).first.data(); + if (!cname) { + *end = nullptr; + return nullptr; + } + *end = cname + (*current_).first.length(); + return cname; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() = default; + +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueConstIterator::ValueConstIterator(ValueIterator const& other) + : ValueIteratorBase(other) {} + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() = default; + +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) { + throwRuntimeError("ConstIterator to Iterator should never be allowed."); +} + +ValueIterator::ValueIterator(const ValueIterator& other) = default; + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_writer.cpp b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..855f3a87e48fd80703cbc22546622ee40178da98 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/json_writer.cpp @@ -0,0 +1,1259 @@ +// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include + +#if !defined(isnan) +#define isnan std::isnan +#endif + +#if !defined(isfinite) +#define isfinite std::isfinite +#endif + +#else +#include +#include + +#if defined(_MSC_VER) +#if !defined(isnan) +#include +#define isnan _isnan +#endif + +#if !defined(isfinite) +#include +#define isfinite _finite +#endif + +#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES + +#endif //_MSC_VER + +#if defined(__sun) && defined(__SVR4) // Solaris +#if !defined(isfinite) +#include +#define isfinite finite +#endif +#endif + +#if defined(__hpux) +#if !defined(isfinite) +#if defined(__ia64) && !defined(finite) +#define isfinite(x) \ + ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) +#endif +#endif +#endif + +#if !defined(isnan) +// IEEE standard states that NaN values will not compare to themselves +#define isnan(x) ((x) != (x)) +#endif + +#if !defined(__APPLE__) +#if !defined(isfinite) +#define isfinite finite +#endif +#endif +#endif + +#if defined(_MSC_VER) +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) +using StreamWriterPtr = std::unique_ptr; +#else +using StreamWriterPtr = std::auto_ptr; +#endif + +String valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + if (value == Value::minLargestInt) { + uintToString(LargestUInt(Value::maxLargestInt) + 1, current); + *--current = '-'; + } else if (value < 0) { + uintToString(LargestUInt(-value), current); + *--current = '-'; + } else { + uintToString(LargestUInt(value), current); + } + assert(current >= buffer); + return current; +} + +String valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +String valueToString(Int value) { return valueToString(LargestInt(value)); } + +String valueToString(UInt value) { return valueToString(LargestUInt(value)); } + +#endif // # if defined(JSON_HAS_INT64) + +namespace { +String valueToString(double value, bool useSpecialFloats, + unsigned int precision, PrecisionType precisionType) { + // Print into the buffer. We need not request the alternative representation + // that always has a decimal point because JSON doesn't distinguish the + // concepts of reals and integers. + if (!isfinite(value)) { + static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"}, + {"null", "-1e+9999", "1e+9999"}}; + return reps[useSpecialFloats ? 0 : 1] + [isnan(value) ? 0 : (value < 0) ? 1 : 2]; + } + + String buffer(size_t(36), '\0'); + while (true) { + int len = jsoncpp_snprintf( + &*buffer.begin(), buffer.size(), + (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", + precision, value); + assert(len >= 0); + auto wouldPrint = static_cast(len); + if (wouldPrint >= buffer.size()) { + buffer.resize(wouldPrint + 1); + continue; + } + buffer.resize(wouldPrint); + break; + } + + buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); + + // try to ensure we preserve the fact that this was given to us as a double on + // input + if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { + buffer += ".0"; + } + + // strip the zero padding from the right + if (precisionType == PrecisionType::decimalPlaces) { + buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision), + buffer.end()); + } + + return buffer; +} +} // namespace + +String valueToString(double value, unsigned int precision, + PrecisionType precisionType) { + return valueToString(value, false, precision, precisionType); +} + +String valueToString(bool value) { return value ? "true" : "false"; } + +static bool doesAnyCharRequireEscaping(char const* s, size_t n) { + assert(s || !n); + + return std::any_of(s, s + n, [](unsigned char c) { + return c == '\\' || c == '"' || c < 0x20 || c > 0x7F; + }); +} + +static unsigned int utf8ToCodepoint(const char*& s, const char* e) { + const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; + + unsigned int firstByte = static_cast(*s); + + if (firstByte < 0x80) + return firstByte; + + if (firstByte < 0xE0) { + if (e - s < 2) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = + ((firstByte & 0x1F) << 6) | (static_cast(s[1]) & 0x3F); + s += 1; + // oversized encoded characters are invalid + return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF0) { + if (e - s < 3) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x0F) << 12) | + ((static_cast(s[1]) & 0x3F) << 6) | + (static_cast(s[2]) & 0x3F); + s += 2; + // surrogates aren't valid codepoints itself + // shouldn't be UTF-8 encoded + if (calculated >= 0xD800 && calculated <= 0xDFFF) + return REPLACEMENT_CHARACTER; + // oversized encoded characters are invalid + return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF8) { + if (e - s < 4) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x07) << 18) | + ((static_cast(s[1]) & 0x3F) << 12) | + ((static_cast(s[2]) & 0x3F) << 6) | + (static_cast(s[3]) & 0x3F); + s += 3; + // oversized encoded characters are invalid + return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; + } + + return REPLACEMENT_CHARACTER; +} + +static const char hex2[] = "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + +static String toHex16Bit(unsigned int x) { + const unsigned int hi = (x >> 8) & 0xff; + const unsigned int lo = x & 0xff; + String result(4, ' '); + result[0] = hex2[2 * hi]; + result[1] = hex2[2 * hi + 1]; + result[2] = hex2[2 * lo]; + result[3] = hex2[2 * lo + 1]; + return result; +} + +static void appendRaw(String& result, unsigned ch) { + result += static_cast(ch); +} + +static void appendHex(String& result, unsigned ch) { + result.append("\\u").append(toHex16Bit(ch)); +} + +static String valueToQuotedStringN(const char* value, size_t length, + bool emitUTF8 = false) { + if (value == nullptr) + return ""; + + if (!doesAnyCharRequireEscaping(value, length)) + return String("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to String is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL + String result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + char const* end = value + length; + for (const char* c = value; c != end; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something.) + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + if (codepoint < 0x20) { + appendHex(result, codepoint); + } else { + appendRaw(result, codepoint); + } + } else { + unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c` + if (codepoint < 0x20) { + appendHex(result, codepoint); + } else if (codepoint < 0x80) { + appendRaw(result, codepoint); + } else if (codepoint < 0x10000) { + // Basic Multilingual Plane + appendHex(result, codepoint); + } else { + // Extended Unicode. Encode 20 bits as a surrogate pair. + codepoint -= 0x10000; + appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff)); + appendHex(result, 0xdc00 + (codepoint & 0x3ff)); + } + } + } break; + } + } + result += "\""; + return result; +} + +String valueToQuotedString(const char* value) { + return valueToQuotedStringN(value, strlen(value)); +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() = default; + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + + = default; + +void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } + +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } + +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } + +String FastWriter::write(const Value& root) { + document_.clear(); + writeValue(root); + if (!omitEndingLineFeed_) + document_ += '\n'; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + document_ += valueToQuotedStringN(str, static_cast(end - str)); + break; + } + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + ArrayIndex size = value.size(); + for (ArrayIndex index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); + } + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (auto it = members.begin(); it != members.end(); ++it) { + const String& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedStringN(name.data(), name.length()); + document_ += yamlCompatibilityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() = default; + +String StyledWriter::write(const Value& root) { + document_.clear(); + addChildValues_ = false; + indentString_.clear(); + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += '\n'; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + auto it = members.begin(); + for (;;) { + const String& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + size_t size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultilineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + ArrayIndex index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (size_t index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultilineArray(const Value& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + !childValue.empty()); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const String& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const String& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); } + +void StyledWriter::unindent() { + assert(indentString_.size() >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += '\n'; + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + document_ += *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + writeIndent(); + ++iter; + } + + // Comments are stripped of trailing newlines, so add one here + document_ += '\n'; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + document_ += '\n'; + document_ += root.getComment(commentAfter); + document_ += '\n'; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(String indentation) + : document_(nullptr), indentation_(std::move(indentation)), + addChildValues_(), indented_(false) {} + +void StyledStreamWriter::write(OStream& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_.clear(); + indented_ = true; + writeCommentBeforeValue(root); + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = nullptr; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: { + // Is NULL possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast(end - str))); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + auto it = members.begin(); + for (;;) { + const String& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultilineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultilineArray(const Value& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + !childValue.empty()); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const String& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const String& value) { + if (!indented_) + writeIndent(); + *document_ << value; + indented_ = false; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *document_ << *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would include newline + *document_ << indentString_; + ++iter; + } + indented_ = false; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << ' ' << root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *document_ << root.getComment(commentAfter); + } + indented_ = false; +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +////////////////////////// +// BuiltStyledStreamWriter + +/// Scoped enums are not available until C++11. +struct CommentStyle { + /// Decide whether to write comments. + enum Enum { + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. + }; +}; + +struct BuiltStyledStreamWriter : public StreamWriter { + BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs, + String colonSymbol, String nullSymbol, + String endingLineFeedSymbol, bool useSpecialFloats, + bool emitUTF8, unsigned int precision, + PrecisionType precisionType); + int write(Value const& root, OStream* sout) override; + +private: + void writeValue(Value const& value); + void writeArrayValue(Value const& value); + bool isMultilineArray(Value const& value); + void pushValue(String const& value); + void writeIndent(); + void writeWithIndent(String const& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(Value const& root); + void writeCommentAfterValueOnSameLine(Value const& root); + static bool hasCommentForValue(const Value& value); + + using ChildValues = std::vector; + + ChildValues childValues_; + String indentString_; + unsigned int rightMargin_; + String indentation_; + CommentStyle::Enum cs_; + String colonSymbol_; + String nullSymbol_; + String endingLineFeedSymbol_; + bool addChildValues_ : 1; + bool indented_ : 1; + bool useSpecialFloats_ : 1; + bool emitUTF8_ : 1; + unsigned int precision_; + PrecisionType precisionType_; +}; +BuiltStyledStreamWriter::BuiltStyledStreamWriter( + String indentation, CommentStyle::Enum cs, String colonSymbol, + String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats, + bool emitUTF8, unsigned int precision, PrecisionType precisionType) + : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs), + colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)), + endingLineFeedSymbol_(std::move(endingLineFeedSymbol)), + addChildValues_(false), indented_(false), + useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8), + precision_(precision), precisionType_(precisionType) {} +int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) { + sout_ = sout; + addChildValues_ = false; + indented_ = true; + indentString_.clear(); + writeCommentBeforeValue(root); + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *sout_ << endingLineFeedSymbol_; + sout_ = nullptr; + return 0; +} +void BuiltStyledStreamWriter::writeValue(Value const& value) { + switch (value.type()) { + case nullValue: + pushValue(nullSymbol_); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, + precisionType_)); + break; + case stringValue: { + // Is NULL is possible for value.string_? No. + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) + pushValue( + valueToQuotedStringN(str, static_cast(end - str), emitUTF8_)); + else + pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + auto it = members.begin(); + for (;;) { + String const& name = *it; + Value const& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent( + valueToQuotedStringN(name.data(), name.length(), emitUTF8_)); + *sout_ << colonSymbol_; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); + if (isMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + Value const& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) + writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *sout_ << "["; + if (!indentation_.empty()) + *sout_ << " "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *sout_ << ((!indentation_.empty()) ? ", " : ","); + *sout_ << childValues_[index]; + } + if (!indentation_.empty()) + *sout_ << " "; + *sout_ << "]"; + } + } +} + +bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { + ArrayIndex const size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { + Value const& childValue = value[index]; + isMultiLine = ((childValue.isArray() || childValue.isObject()) && + !childValue.empty()); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (ArrayIndex index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += static_cast(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void BuiltStyledStreamWriter::pushValue(String const& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *sout_ << value; +} + +void BuiltStyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + + if (!indentation_.empty()) { + // In this case, drop newlines too. + *sout_ << '\n' << indentString_; + } +} + +void BuiltStyledStreamWriter::writeWithIndent(String const& value) { + if (!indented_) + writeIndent(); + *sout_ << value; + indented_ = false; +} + +void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } + +void BuiltStyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { + if (cs_ == CommentStyle::None) + return; + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *sout_ << *iter; + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would write extra newline + *sout_ << indentString_; + ++iter; + } + indented_ = false; +} + +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( + Value const& root) { + if (cs_ == CommentStyle::None) + return; + if (root.hasComment(commentAfterOnSameLine)) + *sout_ << " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *sout_ << root.getComment(commentAfter); + } +} + +// static +bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +/////////////// +// StreamWriter + +StreamWriter::StreamWriter() : sout_(nullptr) {} +StreamWriter::~StreamWriter() = default; +StreamWriter::Factory::~Factory() = default; +StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } +StreamWriterBuilder::~StreamWriterBuilder() = default; +StreamWriter* StreamWriterBuilder::newStreamWriter() const { + const String indentation = settings_["indentation"].asString(); + const String cs_str = settings_["commentStyle"].asString(); + const String pt_str = settings_["precisionType"].asString(); + const bool eyc = settings_["enableYAMLCompatibility"].asBool(); + const bool dnp = settings_["dropNullPlaceholders"].asBool(); + const bool usf = settings_["useSpecialFloats"].asBool(); + const bool emitUTF8 = settings_["emitUTF8"].asBool(); + unsigned int pre = settings_["precision"].asUInt(); + CommentStyle::Enum cs = CommentStyle::All; + if (cs_str == "All") { + cs = CommentStyle::All; + } else if (cs_str == "None") { + cs = CommentStyle::None; + } else { + throwRuntimeError("commentStyle must be 'All' or 'None'"); + } + PrecisionType precisionType(significantDigits); + if (pt_str == "significant") { + precisionType = PrecisionType::significantDigits; + } else if (pt_str == "decimal") { + precisionType = PrecisionType::decimalPlaces; + } else { + throwRuntimeError("precisionType must be 'significant' or 'decimal'"); + } + String colonSymbol = " : "; + if (eyc) { + colonSymbol = ": "; + } else if (indentation.empty()) { + colonSymbol = ":"; + } + String nullSymbol = "null"; + if (dnp) { + nullSymbol.clear(); + } + if (pre > 17) + pre = 17; + String endingLineFeedSymbol; + return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, + endingLineFeedSymbol, usf, emitUTF8, pre, + precisionType); +} + +bool StreamWriterBuilder::validate(Json::Value* invalid) const { + static const auto& valid_keys = *new std::set{ + "indentation", + "commentStyle", + "enableYAMLCompatibility", + "dropNullPlaceholders", + "useSpecialFloats", + "emitUTF8", + "precision", + "precisionType", + }; + for (auto si = settings_.begin(); si != settings_.end(); ++si) { + auto key = si.name(); + if (valid_keys.count(key)) + continue; + if (invalid) + (*invalid)[key] = *si; + else + return false; + } + return invalid ? invalid->empty() : true; +} + +Value& StreamWriterBuilder::operator[](const String& key) { + return settings_[key]; +} +// static +void StreamWriterBuilder::setDefaults(Json::Value* settings) { + //! [StreamWriterBuilderDefaults] + (*settings)["commentStyle"] = "All"; + (*settings)["indentation"] = "\t"; + (*settings)["enableYAMLCompatibility"] = false; + (*settings)["dropNullPlaceholders"] = false; + (*settings)["useSpecialFloats"] = false; + (*settings)["emitUTF8"] = false; + (*settings)["precision"] = 17; + (*settings)["precisionType"] = "significant"; + //! [StreamWriterBuilderDefaults] +} + +String writeString(StreamWriter::Factory const& factory, Value const& root) { + OStringStream sout; + StreamWriterPtr const writer(factory.newStreamWriter()); + writer->write(root, &sout); + return sout.str(); +} + +OStream& operator<<(OStream& sout, Value const& root) { + StreamWriterBuilder builder; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout; +} + +} // namespace Json diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj b/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..e170cfca56eef3355078f0c1215430594b4dbe18 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {f1736b3f-03a2-4fc7-b045-a12ba8d724fb} + jsoncpp + 10.0 + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + ./;$(IncludePath) + + + false + ./;$(IncludePath) + + + true + ./;$(IncludePath) + + + false + ./;$(IncludePath) + + + + Level3 + true + WIN32;_DEBUG;JSONCPP_EXPORTS;_WINDOWS;_USRDLL;JSON_DLL_BUILD;%(PreprocessorDefinitions) + true + NotUsing + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;JSONCPP_EXPORTS;_WINDOWS;_USRDLL;JSON_DLL_BUILD;%(PreprocessorDefinitions) + true + NotUsing + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _DEBUG;JSONCPP_EXPORTS;_WINDOWS;_USRDLL;JSON_DLL_BUILD;%(PreprocessorDefinitions) + true + NotUsing + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;JSONCPP_EXPORTS;_WINDOWS;_USRDLL;JSON_DLL_BUILD;%(PreprocessorDefinitions) + true + NotUsing + pch.h + + + Windows + true + true + true + false + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj.filters b/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..ccf99d75cf91d9e4a65f54c08416b7e68053fab6 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj.filters @@ -0,0 +1,63 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {b702a2a0-b1a3-486d-b83e-23cb806e5158} + + + + + 源文件 + + + 源文件 + + + 源文件 + + + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + 头文件\json + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj.user b/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/XEngine_Source/XEngine_ThirdPart/jsoncpp/jsoncpp.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/XEngine_Source/XEngine_UserProtocol.h b/XEngine_Source/XEngine_UserProtocol.h new file mode 100644 index 0000000000000000000000000000000000000000..9cc27fa2c510a1a9137a245d22b00164bf5f6a1f --- /dev/null +++ b/XEngine_Source/XEngine_UserProtocol.h @@ -0,0 +1,86 @@ +#pragma once +/******************************************************************** +// Created: 2021/12/03 14:16:27 +// File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_UserProtocol.h +// File Path: D:\XEngine_ServiceApp\XEngine_Source +// File Base: XEngine_UserProtocol +// File Ext: h +// Project: XEngine(网络通信引擎) +// Author: qyt +// Purpose: 用户自定义协议头 +// History: +*********************************************************************/ +////////////////////////////////////////////////////////////////////////// +// 主协议定义;unOperatorType +////////////////////////////////////////////////////////////////////////// +typedef enum +{ + //用户消息 + ENUM_XENGINE_COMMUNICATION_PROTOCOL_TYPE_MSG = ENUM_XENGINE_COMMUNICATION_PROTOCOL_TYPE_USER + 1 +}ENUM_XENGINE_COMMUNICATION_PROTOCOL_TYPE_CUSTOM; +typedef enum +{ + ENUM_XENGINE_APISERVICE_PHONE_TYPE_UNKNOWN = 0, // 未知,查找失败 + ENUM_XENGINE_APISERVICE_PHONE_TYPE_CMCC, // 中国移动 + ENUM_XENGINE_APISERVICE_PHONE_TYPE_CUCC, // 中国联通 + ENUM_XENGINE_APISERVICE_PHONE_TYPE_CTCC, // 中国电信 + ENUM_XENGINE_APISERVICE_PHONE_TYPE_CTCC_V, // 电信虚拟运营商 + ENUM_XENGINE_APISERVICE_PHONE_TYPE_CUCC_V, // 联通虚拟运营商 + ENUM_XENGINE_APISERVICE_PHONE_TYPE_CMCC_V // 移动虚拟运营商 +}ENUM_XENGINE_APISERVICE_PHONE_TYPE; +////////////////////////////////////////////////////////////////////////// +// 子协议定义:unOperatorCode +////////////////////////////////////////////////////////////////////////// +#define XENGINE_COMMUNICATION_PROTOCOL_OPERATOR_CODE_MSG_TEXTREQ 0x0001 //发送消息 +#define XENGINE_COMMUNICATION_PROTOCOL_OPERATOR_CODE_MSG_TEXTREP 0x0002 //回复消息 +/////////////////////////////////////////////////////////////////////////// +// 导出的数据结构 +/////////////////////////////////////////////////////////////////////////// +#pragma pack(push) +#pragma pack(1) +//IP地址信息 +typedef struct +{ + TCHAR tszIPStart[128]; + TCHAR tszIPEnd[128]; + TCHAR tszIPAddr[128]; //IP地址 + TCHAR tszIPCountry[128]; //国家/地区 + TCHAR tszIPProvince[128]; //省/自治区 + TCHAR tszIPCity[128]; //市 + TCHAR tszIPCounty[128]; //县 + TCHAR tszIPAddress[128]; //详细地址 + TCHAR tszIPISP[128]; //运营商 + TCHAR tszIPTime[128]; //数据库日期 +}XENGINE_IPADDRINFO; +//身份证校验 +typedef struct +{ + TCHAR tszIDNumber[20]; + WORD nIDProvince; //省/自治区/直辖市 + WORD nIDCity; //市/区 + WORD nIDCounty; //县 + WORD nBirthYear; //出生年 + WORD nBirthMonth; //出生月 + WORD nBirthDay; //出生日 + WORD nPoliceID; //派出所编码 + WORD nSex; //性别 + WORD nCheck; //校验码 +}XENGINE_IDCARDINFO; +//行政区域 +typedef struct +{ + TCHAR tszProvincer[64]; //省/自治区/直辖市 + TCHAR tszCity[64]; //市/区 + TCHAR tszCounty[64]; //县 +}XENGINE_IDREGION; +//行政区域 +typedef struct +{ + TCHAR tszProvincer[64]; //省/自治区/直辖市 + TCHAR tszCity[64]; //市/区 + __int64x nPhoneNumber; //电话号码 + int nZipCode; //邮编 + int nAreaCode; //区号 + ENUM_XENGINE_APISERVICE_PHONE_TYPE enPhoneType; //电话号码类型 +}XENGINE_PHONEINFO; +#pragma pack(pop) \ No newline at end of file