a
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# 忽略所有的本地配置文件
|
||||
local_config.h
|
||||
|
||||
# 忽略所有的二进制可执行文件
|
||||
**/bin/*
|
||||
**/Debug/*
|
||||
**/build/*
|
||||
|
||||
# 忽略所有的日志文件
|
||||
**/logs/*
|
||||
|
||||
# 忽略所有的IDE配置目录
|
||||
**/.vs/*
|
||||
**/.vs/*
|
||||
**/.idea/*
|
||||
**/.svn/*
|
||||
|
||||
# 忽略所有的依赖管理文件和目录
|
||||
**/deps/*
|
||||
**/vcpkg/*
|
||||
|
||||
# 忽略所有的文档和示例文件
|
||||
doc/
|
||||
examples/
|
||||
|
||||
# 忽略所有的外部库文件和文档
|
||||
**/external/*
|
||||
|
||||
# 忽略所有的测试结果文件
|
||||
test_results/
|
||||
|
||||
# 忽略所有的版本控制文件
|
||||
.git/
|
||||
|
||||
# 忽略所有的系统文件和可执行文件
|
||||
.DS_Store
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31729.503
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GeomativeSDK", "GeomativeSDK\GeomativeSDK.vcxproj", "{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Examples", "Examples\Examples.vcxproj", "{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}"
|
||||
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
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Debug|x64.Build.0 = Debug|x64
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Debug|x86.Build.0 = Debug|Win32
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Release|x64.ActiveCfg = Release|x64
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Release|x64.Build.0 = Release|x64
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{80D50A7B-9C5A-4EA5-B9D8-0C224A9B3BBC}.Release|x86.Build.0 = Release|Win32
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Debug|x64.Build.0 = Debug|x64
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Debug|x86.Build.0 = Debug|Win32
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Release|x64.ActiveCfg = Release|x64
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Release|x64.Build.0 = Release|x64
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{ED8FC65E-83ED-4344-9FF0-551A025BEAFD}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A8477F66-70A5-4F9C-B8AB-C6FC6262B43A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{80d50a7b-9c5a-4ea5-b9d8-0c224a9b3bbc}</ProjectGuid>
|
||||
<RootNamespace>GeomativeSDK</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>GeomativeSDK</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir);$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)\libs;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir);$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)\libs;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;GEOMATIVESDK_EXPORTS;_WINDOWS;_USRDLL;_HAS_STD_BYTE=0;_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;GEOMATIVESDK_EXPORTS;_WINDOWS;_USRDLL;_HAS_STD_BYTE=0;_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;GEOMATIVESDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;GEOMATIVESDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="app_config.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="ini_doc.h" />
|
||||
<ClInclude Include="nanolog.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="geo_meta_helper.h" />
|
||||
<ClInclude Include="post_helper.h" />
|
||||
<ClInclude Include="project.h" />
|
||||
<ClInclude Include="util_helper.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\json\json_reader.cpp" />
|
||||
<ClCompile Include="..\json\json_value.cpp" />
|
||||
<ClCompile Include="..\json\json_writer.cpp" />
|
||||
<ClCompile Include="app_config.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="geo_meta_helper.cpp" />
|
||||
<ClCompile Include="ini_doc.cpp" />
|
||||
<ClCompile Include="nanolog.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="post_helper.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="geo_meta_helper.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="post_helper.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="project.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nanolog.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util_helper.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="app_config.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ini_doc.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="post_helper.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="nanolog.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="app_config.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ini_doc.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="geo_meta_helper.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\json\json_reader.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\json\json_value.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\json\json_writer.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -0,0 +1,67 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "app_config.h"
|
||||
#include "ini_doc.h"
|
||||
#include "util_helper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
AppConfig::AppConfig() {
|
||||
LoadConfigIni();
|
||||
Init();
|
||||
}
|
||||
|
||||
AppConfig* AppConfig::Instance() {
|
||||
static AppConfig* instance = new AppConfig();
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*
|
||||
×Ô¶¯²éÕÒ²»´æÔÚµÄkey
|
||||
*/
|
||||
void AppConfig::AutomaticSaveProjectPath(string path) {
|
||||
for (int i = 1; i < 100; i++) {
|
||||
string key = UtilHelper::StringFormat("PATH%02d", i);
|
||||
if (m_doc.IsKeyExist(PROJECT_SEC_NAME, key))
|
||||
continue;
|
||||
|
||||
SetProfile(PROJECT_SEC_NAME, key, path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AppConfig::SetProfile(string secName, string key, string word) {
|
||||
m_doc.setString(PROJECT_SEC_NAME, key, word);
|
||||
m_doc.save();
|
||||
}
|
||||
|
||||
void AppConfig::GetProfile(string secName, string key, string &word) {
|
||||
if(m_doc.IsKeyExist(secName,key))
|
||||
word = m_doc.getString(PROJECT_SEC_NAME, key, word);
|
||||
}
|
||||
|
||||
void AppConfig::DelProfile(string secName, string word) {
|
||||
IniDoc::KeyMap map = m_doc.getSection(secName);
|
||||
string key;
|
||||
|
||||
for (auto it = map.begin(); it != map.end(); it++) {
|
||||
if (it->second.compare(word) == 0) {
|
||||
key = it->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (key.size() > 0) {
|
||||
m_doc.delKey(secName, key);
|
||||
m_doc.save();
|
||||
}
|
||||
}
|
||||
|
||||
void AppConfig::LoadConfigIni(void) {
|
||||
string dir = UtilHelper::LaunchPath();
|
||||
|
||||
bool ret = m_doc.load(dir.append("\\GeomativeSDKConfig.ini"));
|
||||
if (!ret) {
|
||||
cout << "can't find GeomativeSDKConfig.ini,please check" << endl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include "ini_doc.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class AppConfig
|
||||
{
|
||||
private:
|
||||
AppConfig();
|
||||
|
||||
public:
|
||||
const std::string PROJECT_SEC_NAME = "Project";
|
||||
const std::string NETSETTING_SEC_NAME = "NetworkSetting";
|
||||
const std::string DEVNETSETTING_SEC_NAME = "DevNetworkSetting";
|
||||
const std::string LOGIN_SEC_NAME = "Login";
|
||||
const std::string SYSTEM_SEC_NAME = "SystemConfig";
|
||||
|
||||
public:
|
||||
static AppConfig* Instance();
|
||||
void SetProfile(string secName,string key,string word);
|
||||
void GetProfile(string secName, string key, string &word);
|
||||
void DelProfile(string secName, string word);
|
||||
void AutomaticSaveProjectPath(string path);
|
||||
|
||||
private:
|
||||
void LoadConfigIni(void);
|
||||
IniDoc m_doc;
|
||||
|
||||
private:
|
||||
string DataServerIp;
|
||||
string DataServerPort;
|
||||
string WebServerIP;
|
||||
string WebServerPort;
|
||||
|
||||
public:
|
||||
string DataServerUrl;
|
||||
string WebServerUrl;
|
||||
|
||||
private:
|
||||
bool isNum(string str)
|
||||
{
|
||||
stringstream sin(str);
|
||||
double d;
|
||||
char c;
|
||||
|
||||
if (!(sin >> d))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sin >> c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
void Init()
|
||||
{
|
||||
long sel = 0;
|
||||
sel = m_doc.getInteger("EnvSelect", "ChooseEnv", sel);
|
||||
|
||||
string sectionName = (sel == 1) ? DEVNETSETTING_SEC_NAME:NETSETTING_SEC_NAME;
|
||||
DataServerIp.clear();
|
||||
DataServerIp = m_doc.getString(sectionName, "DataServerIp", DataServerIp);
|
||||
DataServerPort.clear();
|
||||
DataServerPort = m_doc.getString(sectionName, "DataServerPort", DataServerPort);
|
||||
WebServerIP.clear();
|
||||
WebServerIP = m_doc.getString(sectionName, "WebServerIP", WebServerIP);
|
||||
WebServerPort.clear();
|
||||
WebServerPort = m_doc.getString(sectionName, "WebServerPort", WebServerPort);
|
||||
|
||||
if (isNum(DataServerPort)){
|
||||
DataServerUrl = DataServerIp + ":" + DataServerPort;
|
||||
}
|
||||
else{
|
||||
DataServerUrl = DataServerIp + "/" + DataServerPort;
|
||||
}
|
||||
|
||||
if (isNum(WebServerPort)) {
|
||||
WebServerUrl = WebServerIP + ":" + WebServerPort;
|
||||
}
|
||||
else {
|
||||
WebServerUrl = WebServerIP + "/" + WebServerPort;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||
// Windows 头文件
|
||||
#include <windows.h>
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "geo_meta_helper.h"
|
||||
#include "json/json.h"
|
||||
#include "util_helper.h"
|
||||
#include "app_config.h"
|
||||
#include "post_helper.h"
|
||||
|
||||
static PostHelper post_helper;
|
||||
|
||||
bool GeoMetaHelper::Login(const std::string& name, const std::string& password) {
|
||||
if (!post_helper.PostLogin(name, password)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = GeoMetaCode::success;
|
||||
return IsOK();
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::RefreshToken() {
|
||||
if (!post_helper.RefreshToken()) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = GeoMetaCode::success;
|
||||
return IsOK();
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::GetProjectList(GeoMetaSceneId scene_id, std::vector<ProjectInfo>& project_list) {
|
||||
Json::Value res;
|
||||
if (!post_helper.Get(AppConfig::Instance()->DataServerUrl + "/business/project/page?sceneId=" + std::to_string(static_cast<std::int32_t>(scene_id)), res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
const auto& list = res["data"]["list"];
|
||||
for (std::uint32_t j = 0; j < list.size(); j++) {
|
||||
project_list.push_back(ProjectInfo(UtilHelper::U2G(list[j]["projectName"].asString().c_str()), std::atoll(list[j]["projectId"].asString().c_str())));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::GetGsList(ProjectId id, std::vector<GsInfo>& gs_list) {
|
||||
Json::Value res;
|
||||
if (!post_helper.Get(AppConfig::Instance()->DataServerUrl + "/business/project/" + std::to_string(id) + "/gsObject", res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
const auto& list = res["data"];
|
||||
for (std::uint32_t i = 0; i < list.size(); i++) {
|
||||
gs_list.emplace_back(UtilHelper::U2G(list[i]["name"].asString().c_str()), list[i]["id"].asInt64());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::GetTmList(GsId gs_id, ComponentId component_id, std::vector<TmInfo>& tm_list) {
|
||||
Json::Value res;
|
||||
if (!post_helper.Get(AppConfig::Instance()->DataServerUrl + "/business/project/gs-object/tm-list?gsObjectId=" + std::to_string(gs_id) + "&componentId=" + std::to_string(component_id), res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
const auto& list = res["data"]["paramConfigRows"];
|
||||
for (std::uint32_t i = 0; i < list.size(); i++)
|
||||
tm_list.emplace_back(UtilHelper::U2G(list[i]["name"].asString().c_str()), std::atoll(list[i]["tmObjectId"].asString().c_str()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::CreateProject(const GeoMetaSceneId scene_id, const std::string& project_name, Properties& properties, ProjectId& project_id) {
|
||||
Json::Value args, res;
|
||||
const auto& property_names = { "" };
|
||||
for (const auto& name : property_names)
|
||||
args[name] = properties[name];
|
||||
args["sceneId"] = static_cast<std::uint64_t>(scene_id);
|
||||
args["projectName"] = project_name;
|
||||
if (!post_helper.Post(AppConfig::Instance()->DataServerUrl + "/business/project/create", args, res)) {
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
project_id = res["data"]["projectId"].asUInt64();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::CreateGs(const ProjectId project_id, const std::string& gs_name, Properties& properties, GsId& gs_id) {
|
||||
Json::Value args, res;
|
||||
const auto& property_names = { ""};
|
||||
for (const auto& name : property_names)
|
||||
args[name] = properties[name];
|
||||
args["name"] = gs_name;
|
||||
args["projectId"] = project_id;
|
||||
if (!post_helper.Post(AppConfig::Instance()->DataServerUrl + "/business/project/gsObject/base/add", args, res)) {
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
gs_id = res["data"]["gsObjectId"].asUInt64();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::CreateTm(const GsId gs_id, const ComponentId component_id, Properties& properties, TmId& tm_id) {
|
||||
Json::Value config_data, args, res;
|
||||
const auto& property_names = { "name", "remark", "weather", "operator" };
|
||||
for (const auto& name : property_names)
|
||||
config_data[name] = properties[name];
|
||||
args["componentId"] = component_id;
|
||||
args["gsObjectId"] = gs_id;
|
||||
args["configData"] = config_data;
|
||||
if (!post_helper.Post(AppConfig::Instance()->DataServerUrl + "/business/project/gs-object/tm-add", args, res)) {
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
tm_id = res["data"]["tmObjectId"].asUInt64();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::UploadFile(const std::string& file_path, const GeoMetaSceneId& scene_id, const GsId gs_id, const TmId& tm_id) {
|
||||
Json::Value args, res, item;
|
||||
const auto& file_name = std::filesystem::path(file_path).filename().string();
|
||||
args["path"] = file_name;
|
||||
if (!post_helper.Post(AppConfig::Instance()->DataServerUrl + "/common/file/upload", args, file_path, res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
res.clear();
|
||||
args.clear();
|
||||
args["gsObjectId"] = gs_id;
|
||||
args["tmObjectId"] = tm_id;
|
||||
args["datasetTypeId"] = 24;
|
||||
item["fileName"] = std::filesystem::path(file_path).filename().string();
|
||||
item["fileUrl"] = res["data"]["url"];
|
||||
args["dataList"].append(item);
|
||||
|
||||
Json::StreamWriterBuilder builder;
|
||||
const std::string strSavePost = Json::writeString(builder, args);
|
||||
if (!post_helper.Post(AppConfig::Instance()->DataServerUrl + "/business/tool/node_earthquake", args, res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
return IsOK();
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::DownloadFile(const TmId& tm_id, const std::string& dest_path) {
|
||||
Json::Value res;
|
||||
if (!post_helper.Get(AppConfig::Instance()->DataServerUrl + "/business/node/earthquake/listAllNeFile/" + std::to_string(tm_id), res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
if (res["data"].size() == 0)
|
||||
return true;
|
||||
|
||||
for (unsigned int i = 0; i < res["data"].size(); i++) {
|
||||
if (!post_helper.Get(res["data"][i]["fileUrl"].asString(), std::filesystem::path(dest_path) / res["data"][i]["fileName"].asString())) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::GetData(const GsId gs_id, const ComponentId component_id, const DatasetId dataset_id, std::string& data) {
|
||||
Json::Value res;
|
||||
if (post_helper.Get(AppConfig::Instance()->DataServerUrl + "/business/project/gs-object/dataset-list?gsObjectId=" + std::to_string(gs_id) + "&componentId=" + std::to_string(component_id), res)) {
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
if (!IsOK())
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 0; i < res["datasetTree"].size(); i++) {
|
||||
if (res["datasetTree"][i]["id"].asInt64() == dataset_id) {
|
||||
data = res["datasetTree"][i]["data"].asString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
error_code_ = GeoMetaCode::resource_not_found;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeoMetaHelper::SetData(const GsId gs_id, const TmId tm_id, const ComponentId component_id, const DatasetId dataset_id, const std::string& data) {
|
||||
Json::Value args, res;
|
||||
args["gsObjectId"] = gs_id;
|
||||
args["tmObjectId"] = tm_id;
|
||||
args["tmDatasetTypeId"] = 0;
|
||||
args["tmDatasetId"] = dataset_id;
|
||||
args["data"] = data;
|
||||
if (post_helper.Post(AppConfig::Instance()->DataServerUrl + "/business/project/tm/dataset/save", args, res)) {
|
||||
error_code_ = GeoMetaCode::system_failure;
|
||||
return false;
|
||||
}
|
||||
error_code_ = static_cast<GeoMetaCode>(res["code"].asInt());
|
||||
return IsOK();
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
typedef std::int64_t ProjectId;
|
||||
typedef std::int64_t GsId;
|
||||
typedef std::int64_t TmId;
|
||||
typedef std::int64_t ComponentId;
|
||||
typedef std::int64_t DatasetId;
|
||||
typedef std::map<std::string, std::string> Properties;
|
||||
|
||||
struct TmInfo
|
||||
{
|
||||
public:
|
||||
TmInfo(const std::string name, const TmId id = 0) :id_(id), name_(name) {}
|
||||
|
||||
public:
|
||||
TmId id_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
struct GsInfo
|
||||
{
|
||||
public:
|
||||
GsInfo(const std::string name, const GsId id = 0) :id_(id), name_(name) {}
|
||||
|
||||
public:
|
||||
GsId id_;
|
||||
std::string name_;
|
||||
std::vector<TmInfo> tm_list_;
|
||||
};
|
||||
|
||||
struct ProjectInfo
|
||||
{
|
||||
public:
|
||||
ProjectInfo(const std::string name, const ProjectId id = 0) :id_(id), name_(name) {}
|
||||
|
||||
public:
|
||||
ProjectId id_;
|
||||
std::string name_;
|
||||
std::vector<GsInfo> gs_list_;
|
||||
};
|
||||
|
||||
#ifdef GEOMATIVESDK_EXPORTS
|
||||
class __declspec(dllexport) GeoMetaHelper {
|
||||
#else
|
||||
class __declspec(dllimport) GeoMetaHelper {
|
||||
#endif
|
||||
public:
|
||||
GeoMetaHelper() :error_code_(GeoMetaCode::success) {};
|
||||
~GeoMetaHelper() = default;
|
||||
|
||||
public:
|
||||
enum class GeoMetaCode {
|
||||
success = 200,
|
||||
|
||||
system_failure = -1,
|
||||
resource_not_found = -2
|
||||
};
|
||||
|
||||
enum class GeoMetaSceneId {
|
||||
scene_id_seis = 30
|
||||
};
|
||||
|
||||
enum class GeoMetaComponentId {
|
||||
component_id_ert = 18,
|
||||
component_id_seis = 19
|
||||
};
|
||||
|
||||
public:
|
||||
GeoMetaCode ErrorCode() {
|
||||
return error_code_;
|
||||
}
|
||||
|
||||
bool Login(const std::string& name, const std::string& password);
|
||||
bool RefreshToken();
|
||||
bool GetProjectList(const GeoMetaSceneId scene_id, std::vector<ProjectInfo>& project_list);
|
||||
bool GetGsList(const ProjectId project_id, std::vector<GsInfo>& gs_list);
|
||||
bool GetTmList(const GsId gs_id, const ComponentId component_id, std::vector<TmInfo>& tm_list);
|
||||
bool CreateProject(const GeoMetaSceneId scene_id, const std::string& project_name, Properties& properties, ProjectId& project_id);
|
||||
bool CreateGs(const ProjectId project_id, const std::string& gs_name, Properties& properties, GsId& gs_id);
|
||||
bool CreateTm(const GsId gs_id, const ComponentId component_id, Properties& properties, TmId& tm_id);
|
||||
bool UploadFile(const std::string& file_path, const GeoMetaSceneId& scene_id, const GsId gs_id, const TmId& tm_id);
|
||||
bool DownloadFile(const TmId& tm_id, const std::string& dest_path);
|
||||
bool GetData(const GsId gs_id, const ComponentId component_id, const DatasetId dataset_id, std::string& data);
|
||||
bool SetData(const GsId gs_id, const TmId tm_id, const ComponentId component_id, const DatasetId dataset_id, const std::string& data);
|
||||
|
||||
protected:
|
||||
bool IsOK() {
|
||||
return error_code_ == GeoMetaCode::code_200;
|
||||
}
|
||||
|
||||
private:
|
||||
GeoMetaCode error_code_;
|
||||
};
|
||||
@@ -0,0 +1,425 @@
|
||||
#include <fstream>
|
||||
#include <strstream>
|
||||
#include "ini_doc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char IniDoc::left_tag = '[';
|
||||
const char IniDoc::right_tag = ']';
|
||||
const char IniDoc::equal = '=';
|
||||
const char IniDoc::cr = '\r';
|
||||
const char IniDoc::new_line = '\n';
|
||||
const char* IniDoc::empty_str = "";
|
||||
const int IniDoc::BUFFER_LEN = 255;
|
||||
|
||||
const IniDoc::KeyMap IniDoc::ms_emptySection;
|
||||
|
||||
IniDoc::IniDoc() : m_modified(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
IniDoc::IniDoc(const std::string& file_name) : m_modified(false)
|
||||
{
|
||||
load(file_name);
|
||||
}
|
||||
|
||||
IniDoc::~IniDoc()
|
||||
{
|
||||
if (m_modified)
|
||||
save();
|
||||
}
|
||||
|
||||
void IniDoc::saveBeforeLoad()
|
||||
{
|
||||
if (m_modified)
|
||||
save();
|
||||
|
||||
m_file_name.resize(0);
|
||||
|
||||
m_map.clear();
|
||||
|
||||
m_modified = false;
|
||||
}
|
||||
|
||||
const char* IniDoc::key_value(const std::string& section, const std::string& key)
|
||||
{
|
||||
SectionIterator itSection = m_map.find(section);
|
||||
if (m_map.end() != itSection)
|
||||
{
|
||||
KeyIterator itKey = itSection->second.find(key);
|
||||
if (itKey != itSection->second.end())
|
||||
return itKey->second.c_str();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IniDoc::load(const std::string& file_name)
|
||||
{
|
||||
saveBeforeLoad();
|
||||
|
||||
ifstream file(file_name);
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
file.seekg(0, ios::end);
|
||||
long len = file.tellg();
|
||||
if (len < 0)
|
||||
return false;
|
||||
|
||||
|
||||
char* buffer = new char[len + 1];
|
||||
if (0 == buffer)
|
||||
return false;
|
||||
|
||||
|
||||
file.seekg(0, ios::beg);
|
||||
file.read(buffer, len);
|
||||
|
||||
buffer[len = file.gcount()] = 0;
|
||||
|
||||
loadString(buffer);
|
||||
m_file_name = file_name;
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IniDoc::loadString(const std::string& str)
|
||||
{
|
||||
saveBeforeLoad();
|
||||
|
||||
unsigned long length = str.size();
|
||||
|
||||
if (str.size() == 0)
|
||||
return false;
|
||||
|
||||
enum project_status
|
||||
{
|
||||
after_left_tag,
|
||||
after_section_name,
|
||||
after_section_name_ws,
|
||||
after_key_name,
|
||||
after_key_name_ws,
|
||||
after_equal,
|
||||
start
|
||||
};
|
||||
|
||||
string section; // 当前 section.
|
||||
string key; // 当前 key.
|
||||
project_status sta = start; // 解析状态.
|
||||
const char* p = str.c_str(); // 当前解析字符串的位置.
|
||||
const char* beg = p; // 当前元素的开始.
|
||||
const char* last_ws = p; // 最后一个空格字符.
|
||||
|
||||
for (; length; ++p, --length)
|
||||
{
|
||||
if (new_line == *p)
|
||||
{
|
||||
if (after_equal == sta)
|
||||
{
|
||||
if (cr == *(p - 1))
|
||||
--p;
|
||||
|
||||
m_map[section][key] = string(beg, p - beg);
|
||||
|
||||
if (cr == *p)
|
||||
++p;
|
||||
}
|
||||
sta = start;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (sta)
|
||||
{
|
||||
case after_left_tag:
|
||||
if (right_tag == *p)
|
||||
{
|
||||
sta = start;
|
||||
section = empty_str; // empty section name.
|
||||
}
|
||||
else if (!isspace((unsigned char)*p))
|
||||
{
|
||||
sta = after_section_name;
|
||||
beg = p;
|
||||
}
|
||||
break;
|
||||
case after_section_name:
|
||||
if (right_tag == *p)
|
||||
{
|
||||
sta = start;
|
||||
section = string(beg, p - beg);
|
||||
}
|
||||
else if (isspace((unsigned char)*p))
|
||||
{
|
||||
sta = after_section_name_ws;
|
||||
last_ws = p;
|
||||
}
|
||||
break;
|
||||
case after_section_name_ws:
|
||||
if (right_tag == *p)
|
||||
{
|
||||
sta = start;
|
||||
section = string(beg, last_ws - beg);
|
||||
}
|
||||
else if (!isspace((unsigned char)*p))
|
||||
{
|
||||
sta = after_section_name;
|
||||
}
|
||||
break;
|
||||
case after_key_name:
|
||||
if (equal == *p)
|
||||
{
|
||||
sta = after_equal;
|
||||
key = string(beg, p - beg);
|
||||
beg = p + 1;
|
||||
}
|
||||
else if (isspace((unsigned char)*p))
|
||||
{
|
||||
sta = after_key_name_ws;
|
||||
last_ws = p;
|
||||
}
|
||||
break;
|
||||
case after_key_name_ws:
|
||||
if (equal == *p)
|
||||
{
|
||||
sta = after_equal;
|
||||
key = string(beg, last_ws - beg);
|
||||
beg = p + 1;
|
||||
}
|
||||
else if (!isspace((unsigned char)*p))
|
||||
{
|
||||
sta = after_key_name;
|
||||
}
|
||||
break;
|
||||
case start:
|
||||
if (left_tag == *p)
|
||||
{
|
||||
sta = after_left_tag;
|
||||
}
|
||||
else if (equal == *p)
|
||||
{
|
||||
key = empty_str; // an empty key.
|
||||
sta = after_equal;
|
||||
beg = p + 1;
|
||||
}
|
||||
else if (!isspace((unsigned char)*p))
|
||||
{
|
||||
sta = after_key_name;
|
||||
beg = p;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (after_equal == sta)
|
||||
m_map[section][key] = string(beg, p - beg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IniDoc::save()
|
||||
{
|
||||
if (0 == m_file_name.c_str() || 0 == m_file_name[0])
|
||||
return false; // file name invalid
|
||||
|
||||
ofstream file(m_file_name.c_str());
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
for (SectionMap::iterator itApp = m_map.begin(); itApp != m_map.end(); ++itApp)
|
||||
{
|
||||
file << left_tag << itApp->first << right_tag << endl;
|
||||
|
||||
for (KeyMap::iterator itKey = itApp->second.begin(); itKey != itApp->second.end(); ++itKey)
|
||||
file << itKey->first << equal << itKey->second << endl;
|
||||
|
||||
file << endl;
|
||||
}
|
||||
m_modified = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IniDoc::saveAs(const std::string& file_name)
|
||||
{
|
||||
string old_file_name = m_file_name;
|
||||
m_file_name = file_name;
|
||||
|
||||
if (save())
|
||||
return true;
|
||||
|
||||
m_file_name = old_file_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
long IniDoc::getInteger(const std::string& section, const std::string& key, long def_val)
|
||||
{
|
||||
istrstream(key_value(section, key)) >> def_val;
|
||||
return def_val;
|
||||
}
|
||||
|
||||
float IniDoc::getFloat(const std::string& section, const std::string& key, float def_val)
|
||||
{
|
||||
istrstream(key_value(section, key)) >> def_val;
|
||||
return def_val;
|
||||
}
|
||||
|
||||
long IniDoc::getStruct(const std::string& section, const std::string& key_, void* buffer, long size)
|
||||
{
|
||||
std::string key = key_value(section, key_);
|
||||
|
||||
if (key.size() == 0)
|
||||
return 0;
|
||||
|
||||
const char* p = key.c_str();
|
||||
char* dst = (char*)buffer;
|
||||
long read_len = 0;
|
||||
char value;
|
||||
|
||||
while (*p && read_len < size)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
value = *p - '0';
|
||||
break;
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
value = *p - 'a' + 10;
|
||||
break;
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
value = *p - 'A' + 10;
|
||||
break;
|
||||
default:
|
||||
return read_len;
|
||||
}
|
||||
|
||||
|
||||
if (0 == (p - key.c_str()) % 2)
|
||||
*(dst + read_len) = value << 4;
|
||||
else
|
||||
*(dst + read_len) = (*(dst + read_len) & 0xf0) + value;
|
||||
|
||||
|
||||
if (0 == (++p - key.c_str()) % 2)
|
||||
++read_len;
|
||||
}
|
||||
|
||||
return read_len;
|
||||
}
|
||||
|
||||
long IniDoc::getString(const std::string& section, const std::string& key_, const std::string& def_val, std::string& dst_str)
|
||||
{
|
||||
std::string key = key_value(section, key_);
|
||||
dst_str = key.length() ? key : def_val;
|
||||
return dst_str.length();
|
||||
}
|
||||
|
||||
bool IniDoc::IsKeyExist(const std::string& section,string key)
|
||||
{
|
||||
SectionIterator itSection = m_map.find(section);
|
||||
if (m_map.end() != itSection)
|
||||
{
|
||||
KeyIterator itKey = itSection->second.find(key);
|
||||
if (itKey != itSection->second.end())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string IniDoc::getString(const std::string& section, const std::string& key_, const std::string& def_val)
|
||||
{
|
||||
const char* pKey = key_value(section, key_);
|
||||
std::string key = !pKey ? "" : std::string(pKey);
|
||||
if (key.length() == 0)
|
||||
key = def_val;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void IniDoc::setInteger(const std::string& section, const std::string& key, long value)
|
||||
{
|
||||
char buffer[BUFFER_LEN + 1];
|
||||
ostrstream ostr(buffer, BUFFER_LEN);
|
||||
ostr << value;
|
||||
buffer[ostr.pcount()] = 0;
|
||||
setString(section, key, buffer);
|
||||
}
|
||||
|
||||
void IniDoc::setFloat(const std::string& section, const std::string& key, float value)
|
||||
{
|
||||
char buffer[BUFFER_LEN + 1];
|
||||
ostrstream ostr(buffer, BUFFER_LEN);
|
||||
ostr << value;
|
||||
buffer[ostr.pcount()] = 0;
|
||||
setString(section, key, buffer);
|
||||
}
|
||||
|
||||
inline char bin2hex(char bin)
|
||||
{
|
||||
return bin < 10 ? bin + '0' : bin - 10 + 'A';
|
||||
}
|
||||
|
||||
void IniDoc::setStruct(const std::string& section, const std::string& key, const void* buffer, long size)
|
||||
{
|
||||
char* dst = new char[size * 2 + 1];
|
||||
if (dst)
|
||||
{
|
||||
const char* src = (const char*)buffer;
|
||||
long i = 0;
|
||||
for (i = 0; i < size; ++i)
|
||||
{
|
||||
dst[i << 1] = bin2hex((src[i] >> 4) & 0x0f);
|
||||
dst[(i << 1) + 1] = bin2hex(src[i] & 0x0f);
|
||||
}
|
||||
|
||||
dst[i << 1] = 0;
|
||||
setString(section, key, dst);
|
||||
|
||||
delete[] dst;
|
||||
}
|
||||
}
|
||||
|
||||
void IniDoc::setString(const std::string& section, const std::string& key, const std::string& value)
|
||||
{
|
||||
m_map[section][key] = value;
|
||||
m_modified = true;
|
||||
}
|
||||
|
||||
bool IniDoc::delSection(const std::string& section)
|
||||
{
|
||||
SectionIterator itSection = m_map.find(section);
|
||||
if (m_map.end() != itSection)
|
||||
{
|
||||
m_map.erase(itSection);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IniDoc::delKey(const std::string& section, const std::string& key)
|
||||
{
|
||||
SectionIterator itSection = m_map.find(section);
|
||||
if (m_map.end() != itSection)
|
||||
{
|
||||
KeyIterator itKey = itSection->second.find(key);
|
||||
if (itKey != itSection->second.end())
|
||||
{
|
||||
itSection->second.erase(itKey);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const IniDoc::KeyMap& IniDoc::getSection(const std::string& section) const
|
||||
{
|
||||
SectionMap::const_iterator itApp = m_map.find(section);
|
||||
return m_map.end() == itApp ? ms_emptySection : itApp->second;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
|
||||
class IniDoc
|
||||
{
|
||||
public:
|
||||
struct IgnoreCaseLT
|
||||
{
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const
|
||||
{
|
||||
return strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef std::map<std::string, std::string, IgnoreCaseLT> KeyMap;
|
||||
typedef std::map<std::string, KeyMap, IgnoreCaseLT> SectionMap;
|
||||
typedef KeyMap::iterator KeyIterator;
|
||||
typedef SectionMap::iterator SectionIterator;
|
||||
|
||||
public:
|
||||
// 默认的构造函数和析构函数
|
||||
IniDoc();
|
||||
~IniDoc();
|
||||
|
||||
// 构造函数 - 加载文件
|
||||
IniDoc(const std::string& file_name);
|
||||
|
||||
// 加载一个ini文件, 如果之前的文件被修改, 那么之前的ini文件将会被保持。
|
||||
bool load(const std::string& file_name);
|
||||
|
||||
// 从字符串中作为ini文件加载
|
||||
bool loadString(const std::string& str);
|
||||
|
||||
// 保持到加载ini位置
|
||||
bool save();
|
||||
|
||||
// 另存为一个和加载路径不一样的文件中
|
||||
bool saveAs(const std::string& file_name);
|
||||
|
||||
// 返回ini是否被修改, 或者他最后一次操作是保存
|
||||
bool isModified() const { return m_modified; }
|
||||
|
||||
public: // high level member function.
|
||||
|
||||
// 下面的成员函数是从Section中获得一些值
|
||||
long getInteger(const std::string& section, const std::string& key, long def_val);
|
||||
float getFloat(const std::string& section, const std::string& key, float def_val);
|
||||
long getStruct(const std::string& section, const std::string& key, void* buffer, long size);
|
||||
long getString(const std::string& section, const std::string& key, const std::string& def_val, std::string& buffer);
|
||||
const std::string getString(const std::string& section, const std::string& key, const std::string& def_val);
|
||||
|
||||
void setInteger(const std::string& section, const std::string& key, long value);
|
||||
void setFloat(const std::string& section, const std::string& key, float value);
|
||||
void setStruct(const std::string& section, const std::string& key, const void* buffer, long size);
|
||||
void setString(const std::string& section, const std::string& key, const std::string& value);
|
||||
|
||||
public:
|
||||
bool delSection(const std::string& section);
|
||||
bool delKey(const std::string& section, const std::string& key);
|
||||
|
||||
public:
|
||||
// 返回一个section的map键值对
|
||||
const KeyMap& getSection(const std::string& section) const;
|
||||
|
||||
// 返回整个ini的Sections
|
||||
const SectionMap& getIni() const { return m_map; }
|
||||
|
||||
bool IsKeyExist(const std::string& section,std::string key);
|
||||
|
||||
private:
|
||||
void saveBeforeLoad();
|
||||
const char* key_value(const std::string& section, const std::string& key);
|
||||
|
||||
private:
|
||||
// 禁止复制构造函数和赋值操作符。
|
||||
IniDoc(const IniDoc& copy);
|
||||
IniDoc& operator=(const IniDoc& rhs);
|
||||
|
||||
private:
|
||||
static const KeyMap ms_emptySection;
|
||||
static const char left_tag;
|
||||
static const char right_tag;
|
||||
static const char equal;
|
||||
static const char cr;
|
||||
static const char new_line;
|
||||
static const char* empty_str;
|
||||
static const int BUFFER_LEN;
|
||||
|
||||
SectionMap m_map;
|
||||
std::string m_file_name;
|
||||
bool m_modified;
|
||||
|
||||
public:
|
||||
SectionMap& get_map() {
|
||||
return m_map;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
|
||||
#include "nanolog.h"
|
||||
|
||||
namespace nanolog {
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#define COMBINE_PATH(path,name) (path + "\\" + name)
|
||||
#include <io.h>
|
||||
std::vector<std::string> get_all_files_in_dir(std::string dir_path)
|
||||
{
|
||||
std::vector<std::string> retV;
|
||||
std::string p;
|
||||
intptr_t hFile = 0;
|
||||
struct _finddata_t fileinfo;
|
||||
|
||||
if ((hFile = _findfirst(p.assign(dir_path).append("\\*").c_str(), &fileinfo)) != -1)
|
||||
{
|
||||
do{
|
||||
if ((fileinfo.attrib & _A_ARCH))
|
||||
{
|
||||
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
|
||||
{
|
||||
retV.push_back(fileinfo.name);
|
||||
}
|
||||
}
|
||||
} while (_findnext(hFile, &fileinfo) == 0);
|
||||
_findclose(hFile);
|
||||
}
|
||||
|
||||
return retV;
|
||||
}
|
||||
|
||||
int remove_file(const char* pathname)
|
||||
{
|
||||
return remove(pathname);
|
||||
}
|
||||
|
||||
#include <Windows.h>
|
||||
int create_dir(const char* path)
|
||||
{
|
||||
int ret;
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
if (_access(path,0) == 0)
|
||||
return 0;
|
||||
ret = CreateDirectoryA(path,nullptr);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define COMBINE_PATH(path,name) (path + "/" + name)
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
std::vector<std::string> get_all_files_in_dir(std::string dir_path)
|
||||
{
|
||||
DIR *pDir;
|
||||
struct dirent *ent;
|
||||
std::vector<std::string> retV;
|
||||
|
||||
pDir = opendir(dir_path.c_str());
|
||||
while((ent = readdir(pDir)) != NULL)
|
||||
{
|
||||
if(ent->d_type & DT_DIR){
|
||||
//ignore
|
||||
}
|
||||
else{
|
||||
retV.emplace_back(ent->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
return retV;
|
||||
}
|
||||
#include <stdio.h>
|
||||
int remove_file(const char* pathname)
|
||||
{
|
||||
return remove(pathname);
|
||||
}
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
//#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
int create_dir(const char* path)
|
||||
{
|
||||
int ret;
|
||||
if(path == NULL)
|
||||
return -1;
|
||||
if(access(path,F_OK) >= 0)
|
||||
return 0;
|
||||
ret = mkdir(path,0777);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::atomic <unsigned int> loglevel;
|
||||
std::unique_ptr <NanoLogger> nanologger;
|
||||
std::atomic < NanoLogger * > atomic_nanologger;
|
||||
std::atomic<bool> flush_to_console;
|
||||
|
||||
void Logger::initialize(GuaranteedLogger gl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num)
|
||||
{
|
||||
create_dir(log_directory.c_str());
|
||||
nanologger.reset(new NanoLogger(gl, log_directory, log_file_name, log_file_roll_size_mb, file_num));
|
||||
atomic_nanologger.store(nanologger.get(), std::memory_order_seq_cst);
|
||||
}
|
||||
|
||||
void Logger::initialize(NonGuaranteedLogger ngl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num)
|
||||
{
|
||||
nanologger.reset(new NanoLogger(ngl, log_directory, log_file_name, log_file_roll_size_mb, file_num));
|
||||
atomic_nanologger.store(nanologger.get(), std::memory_order_seq_cst);
|
||||
}
|
||||
|
||||
void Logger::set_log_level(LogLevel level)
|
||||
{
|
||||
loglevel.store(static_cast<unsigned int>(level), std::memory_order_release);
|
||||
}
|
||||
|
||||
void Logger::set_flush_to_console(bool v)
|
||||
{
|
||||
flush_to_console.store(v);
|
||||
}
|
||||
|
||||
bool Logger::is_logged(LogLevel level)
|
||||
{
|
||||
return static_cast<unsigned int>(level) >= loglevel.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
bool Logger::operator==(NanoLogLine & logline)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
// nothing to do
|
||||
#else
|
||||
if (flush_to_console) {
|
||||
std::ostringstream ostm{};
|
||||
logline.stringify(ostm);
|
||||
std::cout << ostm.str();
|
||||
}
|
||||
#endif
|
||||
atomic_nanologger.load(std::memory_order_acquire)->add(std::move(logline));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,965 @@
|
||||
|
||||
#ifndef __NANOLOG_H
|
||||
#define __NANOLOG_H
|
||||
|
||||
#pragma warning( disable : 4996 )
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
#include <cstring>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <atomic>
|
||||
#include <queue>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace nanolog
|
||||
{
|
||||
#if defined max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
extern std::vector<std::string> get_all_files_in_dir(std::string dir_path);
|
||||
extern int remove_file(const char* pathname);
|
||||
extern int create_dir(const char* path);
|
||||
|
||||
#define YEAR (1900)
|
||||
#define MONTH (1)
|
||||
#define CCT (+8)
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#define COMBINE_PATH(path,name) (path + "\\" + name)
|
||||
#else
|
||||
#define COMBINE_PATH(path,name) (path + "/" + name)
|
||||
#endif
|
||||
|
||||
class NanologBase
|
||||
{
|
||||
public:
|
||||
/* Returns microseconds since epoch */
|
||||
static uint64_t timestamp_now()
|
||||
{
|
||||
// return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
static std::string get_datetime(uint64_t timestamp)
|
||||
{
|
||||
char miliseconds[4];
|
||||
sprintf(miliseconds, "%03llu", timestamp % 1000);
|
||||
std::time_t time_t = timestamp / 1000;
|
||||
tm* gmtime = std::localtime(&time_t);
|
||||
|
||||
std::ostringstream ostr;
|
||||
if(nullptr == gmtime)
|
||||
{
|
||||
ostr<< miliseconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
char datetime[32];
|
||||
//sprintf(datetime, "%d%02d%02d%02d%02d%02d", gmtime->tm_year+YEAR, gmtime->tm_mon+MONTH,
|
||||
// gmtime->tm_mday, gmtime->tm_hour + CCT, gmtime->tm_min, gmtime->tm_sec);
|
||||
sprintf(datetime, "%d%02d%02d", gmtime->tm_year+YEAR, gmtime->tm_mon+MONTH, gmtime->tm_mday);
|
||||
ostr<< datetime;
|
||||
}
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
/* I want [2016-10-13 00:01:23.528514] */
|
||||
static void format_timestamp(std::ostream & os, uint64_t timestamp)
|
||||
{
|
||||
// The next 3 lines do not work on MSVC!
|
||||
// auto duration = std::chrono::microseconds(timestamp);
|
||||
// std::chrono::high_resolution_clock::time_point time_point(duration);
|
||||
// std::time_t time_t = std::chrono::high_resolution_clock::to_time_t(time_point);
|
||||
char miliseconds[7];
|
||||
sprintf(miliseconds, "%03llu", timestamp % 1000);
|
||||
std::time_t time_t = timestamp / 1000;
|
||||
tm* gmtime = localtime(&time_t);
|
||||
|
||||
if(nullptr == gmtime)
|
||||
{
|
||||
os << '[' << miliseconds << ']';
|
||||
}
|
||||
else
|
||||
{
|
||||
char datetime[32];
|
||||
sprintf(datetime, "%d-%02d-%02d %02d:%02d:%02d", gmtime->tm_year+YEAR, gmtime->tm_mon+MONTH,
|
||||
gmtime->tm_mday, gmtime->tm_hour, gmtime->tm_min, gmtime->tm_sec);
|
||||
os << '['<< datetime<< "."<< miliseconds << ']';
|
||||
}
|
||||
}
|
||||
|
||||
static std::thread::id this_thread_id()
|
||||
{
|
||||
//static thread_local const std::thread::id id = std::this_thread::get_id();
|
||||
std::thread::id id = std::this_thread::get_id();
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
enum class LogLevel : uint8_t { INFO, WARN, CRIT };
|
||||
|
||||
class NanoLogLine
|
||||
{
|
||||
public:
|
||||
template < typename T, typename Tuple >
|
||||
struct TupleIndex;
|
||||
|
||||
template < typename T,typename ... Types >
|
||||
struct TupleIndex < T, std::tuple < T, Types... > >
|
||||
{
|
||||
static constexpr const std::size_t value = 0;
|
||||
};
|
||||
|
||||
template < typename T, typename U, typename ... Types >
|
||||
struct TupleIndex < T, std::tuple < U, Types... > >
|
||||
{
|
||||
static constexpr const std::size_t value = 1 + TupleIndex < T, std::tuple < Types... > >::value;
|
||||
};
|
||||
|
||||
struct string_literal_t
|
||||
{
|
||||
explicit string_literal_t(char const * s) : m_s(s) {}
|
||||
char const * m_s;
|
||||
};
|
||||
typedef std::tuple < char, uint32_t, uint64_t, int32_t, int64_t, double, NanoLogLine::string_literal_t, char * > SupportedTypes;
|
||||
|
||||
NanoLogLine(LogLevel level, char const * file, char const * function, uint32_t line)
|
||||
: m_bytes_used(0)
|
||||
, m_buffer_size(sizeof(m_stack_buffer))
|
||||
{
|
||||
encode < uint64_t >(NanologBase::timestamp_now());
|
||||
encode < std::thread::id >(NanologBase::this_thread_id());
|
||||
encode < string_literal_t >(string_literal_t(file));
|
||||
encode < string_literal_t >(string_literal_t(function));
|
||||
encode < uint32_t >(line);
|
||||
encode < LogLevel >(level);
|
||||
}
|
||||
~NanoLogLine() = default;
|
||||
|
||||
NanoLogLine(NanoLogLine &&) = default;
|
||||
NanoLogLine& operator=(NanoLogLine &&) = default;
|
||||
|
||||
void stringify(std::ostream & os)
|
||||
{
|
||||
char * b = !m_heap_buffer ? m_stack_buffer : m_heap_buffer.get();
|
||||
char const * const end = b + m_bytes_used;
|
||||
uint64_t timestamp = *reinterpret_cast < uint64_t * >(b); b += sizeof(uint64_t);
|
||||
std::thread::id threadid = *reinterpret_cast < std::thread::id * >(b); b += sizeof(std::thread::id);
|
||||
string_literal_t file = *reinterpret_cast < string_literal_t * >(b); b += sizeof(string_literal_t);
|
||||
string_literal_t function = *reinterpret_cast < string_literal_t * >(b); b += sizeof(string_literal_t);
|
||||
uint32_t line = *reinterpret_cast < uint32_t * >(b); b += sizeof(uint32_t);
|
||||
LogLevel loglevel = *reinterpret_cast < LogLevel * >(b); b += sizeof(LogLevel);
|
||||
|
||||
NanologBase::format_timestamp(os, timestamp);
|
||||
|
||||
os << '[' << to_string(loglevel) << ']'
|
||||
<< '[' << threadid << ']'
|
||||
<< '[' << file.m_s << ':' << function.m_s << ':' << line << "] ";
|
||||
|
||||
stringify(os, b, end);
|
||||
|
||||
os << std::endl;
|
||||
|
||||
if (loglevel >= LogLevel::CRIT)
|
||||
os.flush();
|
||||
}
|
||||
|
||||
NanoLogLine& operator<<(char arg)
|
||||
{
|
||||
encode < char >(arg, TupleIndex < char, SupportedTypes >::value);
|
||||
return *this;
|
||||
}
|
||||
NanoLogLine& operator<<(int32_t arg)
|
||||
{
|
||||
encode < int32_t >(arg, TupleIndex < int32_t, SupportedTypes >::value);
|
||||
return *this;
|
||||
}
|
||||
NanoLogLine& operator<<(uint32_t arg)
|
||||
{
|
||||
encode < uint32_t >(arg, TupleIndex < uint32_t, SupportedTypes >::value);
|
||||
return *this;
|
||||
}
|
||||
NanoLogLine& operator<<(int64_t arg)
|
||||
{
|
||||
encode < int64_t >(arg, TupleIndex < int64_t, SupportedTypes >::value);
|
||||
return *this;
|
||||
}
|
||||
NanoLogLine& operator<<(uint64_t arg)
|
||||
{
|
||||
encode < uint64_t >(arg, TupleIndex < uint64_t, SupportedTypes >::value);
|
||||
return *this;
|
||||
}
|
||||
NanoLogLine& operator<<(double arg)
|
||||
{
|
||||
encode < double >(arg, TupleIndex < double, SupportedTypes >::value);
|
||||
return *this;
|
||||
}
|
||||
NanoLogLine& operator<<(std::string const & arg)
|
||||
{
|
||||
encode_c_string(arg.c_str(), arg.length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < size_t N >
|
||||
NanoLogLine& operator<<(const char (&arg)[N])
|
||||
{
|
||||
encode(string_literal_t(arg));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename Arg >
|
||||
typename std::enable_if < std::is_same < Arg, char const * >::value, NanoLogLine& >::type
|
||||
operator<<(Arg const & arg)
|
||||
{
|
||||
encode(arg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename Arg >
|
||||
typename std::enable_if < std::is_same < Arg, char * >::value, NanoLogLine& >::type
|
||||
operator<<(Arg const & arg)
|
||||
{
|
||||
encode(arg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
char const * to_string(LogLevel loglevel)
|
||||
{
|
||||
switch (loglevel)
|
||||
{
|
||||
case LogLevel::INFO:
|
||||
return "INFO";
|
||||
case LogLevel::WARN:
|
||||
return "WARN";
|
||||
case LogLevel::CRIT:
|
||||
return "CRIT";
|
||||
}
|
||||
return "XXXX";
|
||||
}
|
||||
|
||||
char * buffer()
|
||||
{
|
||||
return !m_heap_buffer ? &m_stack_buffer[m_bytes_used] : &(m_heap_buffer.get())[m_bytes_used];
|
||||
}
|
||||
|
||||
template < typename Arg >
|
||||
void encode(Arg arg)
|
||||
{
|
||||
*reinterpret_cast<Arg*>(buffer()) = arg;
|
||||
m_bytes_used += sizeof(Arg);
|
||||
}
|
||||
|
||||
template < typename Arg >
|
||||
void encode(Arg arg, uint8_t type_id)
|
||||
{
|
||||
resize_buffer_if_needed(sizeof(Arg) + sizeof(uint8_t));
|
||||
encode < uint8_t >(type_id);
|
||||
encode < Arg >(arg);
|
||||
}
|
||||
|
||||
void encode(char * arg)
|
||||
{
|
||||
if (arg != nullptr)
|
||||
encode_c_string(arg, strlen(arg));
|
||||
}
|
||||
void encode(char const * arg)
|
||||
{
|
||||
if (arg != nullptr)
|
||||
encode_c_string(arg, strlen(arg));
|
||||
}
|
||||
void encode(string_literal_t arg)
|
||||
{
|
||||
encode < string_literal_t >(arg, TupleIndex < string_literal_t, SupportedTypes >::value);
|
||||
}
|
||||
void encode_c_string(char const * arg, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
resize_buffer_if_needed(1 + length + 1);
|
||||
char * b = buffer();
|
||||
auto type_id = TupleIndex < char *, SupportedTypes >::value;
|
||||
*reinterpret_cast<uint8_t*>(b++) = static_cast<uint8_t>(type_id);
|
||||
memcpy(b, arg, length + 1);
|
||||
m_bytes_used += 1 + length + 1;
|
||||
}
|
||||
|
||||
void resize_buffer_if_needed(size_t additional_bytes)
|
||||
{
|
||||
size_t const required_size = m_bytes_used + additional_bytes;
|
||||
|
||||
if (required_size <= m_buffer_size)
|
||||
return;
|
||||
|
||||
if (!m_heap_buffer)
|
||||
{
|
||||
m_buffer_size = std::max(static_cast<size_t>(512), required_size);
|
||||
m_heap_buffer.reset(new char[m_buffer_size]);
|
||||
memcpy(m_heap_buffer.get(), m_stack_buffer, m_bytes_used);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer_size = std::max(static_cast<size_t>(2 * m_buffer_size), required_size);
|
||||
std::unique_ptr < char [] > new_heap_buffer(new char[m_buffer_size]);
|
||||
memcpy(new_heap_buffer.get(), m_heap_buffer.get(), m_bytes_used);
|
||||
m_heap_buffer.swap(new_heap_buffer);
|
||||
}
|
||||
}
|
||||
void stringify(std::ostream & os, char * start, char const * const end)
|
||||
{
|
||||
if (start == end)
|
||||
return;
|
||||
|
||||
int type_id = static_cast < int >(*start); start++;
|
||||
|
||||
switch (type_id)
|
||||
{
|
||||
case 0:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<0, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 1:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<1, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 2:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<2, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 3:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<3, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 4:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<4, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 5:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<5, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 6:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<6, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
case 7:
|
||||
stringify(os, decode(os, start, static_cast<std::tuple_element<7, SupportedTypes>::type*>(nullptr)), end);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename Arg >
|
||||
char * decode(std::ostream & os, char * b, Arg * dummy)
|
||||
{
|
||||
Arg arg = *reinterpret_cast < Arg * >(b);
|
||||
os << arg;
|
||||
return b + sizeof(Arg);
|
||||
}
|
||||
|
||||
char * decode(std::ostream & os, char * b, NanoLogLine::string_literal_t * dummy)
|
||||
{
|
||||
NanoLogLine::string_literal_t s = *reinterpret_cast < NanoLogLine::string_literal_t * >(b);
|
||||
os << s.m_s;
|
||||
return b + sizeof(NanoLogLine::string_literal_t);
|
||||
}
|
||||
|
||||
char * decode(std::ostream & os, char * b, char ** dummy)
|
||||
{
|
||||
while (*b != '\0')
|
||||
{
|
||||
os << *b;
|
||||
++b;
|
||||
}
|
||||
return ++b;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_bytes_used;
|
||||
size_t m_buffer_size;
|
||||
std::unique_ptr < char [] > m_heap_buffer;
|
||||
char m_stack_buffer[256 - 2 * sizeof(size_t) - sizeof(decltype(m_heap_buffer)) - 8 /* Reserved */];
|
||||
};
|
||||
|
||||
struct BufferBase
|
||||
{
|
||||
virtual ~BufferBase() = default;
|
||||
virtual void push(NanoLogLine && logline) = 0;
|
||||
virtual bool try_pop(NanoLogLine & logline) = 0;
|
||||
};
|
||||
|
||||
class SpinLock
|
||||
{
|
||||
public:
|
||||
SpinLock(std::atomic_flag & flag) : m_flag(flag)
|
||||
{
|
||||
while (m_flag.test_and_set(std::memory_order_acquire));
|
||||
}
|
||||
|
||||
~SpinLock()
|
||||
{
|
||||
m_flag.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic_flag & m_flag;
|
||||
};
|
||||
|
||||
/* Multi Producer Single Consumer Ring Buffer */
|
||||
class RingBuffer : public BufferBase
|
||||
{
|
||||
public:
|
||||
struct alignas(64) Item
|
||||
{
|
||||
Item()
|
||||
: written(0)
|
||||
, logline(LogLevel::INFO, nullptr, nullptr, 0)
|
||||
{
|
||||
}
|
||||
|
||||
std::atomic_flag flag = ATOMIC_FLAG_INIT;
|
||||
char written;
|
||||
char padding[256 - sizeof(std::atomic_flag) - sizeof(char) - sizeof(NanoLogLine)];
|
||||
NanoLogLine logline;
|
||||
};
|
||||
|
||||
RingBuffer(size_t const size)
|
||||
: m_size(size)
|
||||
, m_ring(static_cast<Item*>(std::malloc(size * sizeof(Item))))
|
||||
, m_write_index(0)
|
||||
, m_read_index(0)
|
||||
{
|
||||
for (size_t i = 0; i < m_size; ++i)
|
||||
{
|
||||
new (&m_ring[i]) Item();
|
||||
}
|
||||
static_assert(sizeof(Item) == 256, "Unexpected size != 256");
|
||||
}
|
||||
|
||||
~RingBuffer()
|
||||
{
|
||||
for (size_t i = 0; i < m_size; ++i)
|
||||
{
|
||||
m_ring[i].~Item();
|
||||
}
|
||||
std::free(m_ring);
|
||||
}
|
||||
|
||||
void push(NanoLogLine && logline) override
|
||||
{
|
||||
unsigned int write_index = m_write_index.fetch_add(1, std::memory_order_relaxed) % m_size;
|
||||
Item & item = m_ring[write_index];
|
||||
SpinLock spinlock(item.flag);
|
||||
item.logline = std::move(logline);
|
||||
item.written = 1;
|
||||
}
|
||||
|
||||
bool try_pop(NanoLogLine & logline) override
|
||||
{
|
||||
Item & item = m_ring[m_read_index % m_size];
|
||||
SpinLock spinlock(item.flag);
|
||||
if (item.written == 1)
|
||||
{
|
||||
logline = std::move(item.logline);
|
||||
item.written = 0;
|
||||
++m_read_index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RingBuffer(RingBuffer const &) = delete;
|
||||
RingBuffer& operator=(RingBuffer const &) = delete;
|
||||
|
||||
private:
|
||||
size_t const m_size;
|
||||
Item * m_ring;
|
||||
std::atomic < unsigned int > m_write_index;
|
||||
char pad[64];
|
||||
unsigned int m_read_index;
|
||||
};
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
struct Item
|
||||
{
|
||||
Item(NanoLogLine && nanologline) : logline(std::move(nanologline)) {}
|
||||
char padding[256 - sizeof(NanoLogLine)];
|
||||
NanoLogLine logline;
|
||||
};
|
||||
|
||||
static constexpr const size_t size = 32768; // 8MB. Helps reduce memory fragmentation
|
||||
|
||||
Buffer() : m_buffer(static_cast<Item*>(std::malloc(size * sizeof(Item))))
|
||||
{
|
||||
for (size_t i = 0; i <= size; ++i)
|
||||
{
|
||||
m_write_state[i].store(0, std::memory_order_relaxed);
|
||||
}
|
||||
static_assert(sizeof(Item) == 256, "Unexpected size != 256");
|
||||
}
|
||||
|
||||
~Buffer()
|
||||
{
|
||||
unsigned int write_count = m_write_state[size].load();
|
||||
for (size_t i = 0; i < write_count; ++i)
|
||||
{
|
||||
m_buffer[i].~Item();
|
||||
}
|
||||
std::free(m_buffer);
|
||||
}
|
||||
|
||||
// Returns true if we need to switch to next buffer
|
||||
bool push(NanoLogLine && logline, unsigned int const write_index)
|
||||
{
|
||||
new (&m_buffer[write_index]) Item(std::move(logline));
|
||||
m_write_state[write_index].store(1, std::memory_order_release);
|
||||
return m_write_state[size].fetch_add(1, std::memory_order_acquire) + 1 == size;
|
||||
}
|
||||
|
||||
bool try_pop(NanoLogLine & logline, unsigned int const read_index)
|
||||
{
|
||||
if (m_write_state[read_index].load(std::memory_order_acquire))
|
||||
{
|
||||
Item & item = m_buffer[read_index];
|
||||
logline = std::move(item.logline);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Buffer(Buffer const &) = delete;
|
||||
Buffer& operator=(Buffer const &) = delete;
|
||||
|
||||
private:
|
||||
Item * m_buffer;
|
||||
std::atomic < unsigned int > m_write_state[size + 1];
|
||||
};
|
||||
|
||||
class QueueBuffer : public BufferBase
|
||||
{
|
||||
public:
|
||||
QueueBuffer(QueueBuffer const &) = delete;
|
||||
QueueBuffer& operator=(QueueBuffer const &) = delete;
|
||||
|
||||
QueueBuffer() : m_current_read_buffer{nullptr}
|
||||
, m_write_index(0)
|
||||
, m_read_index(0)
|
||||
{
|
||||
setup_next_write_buffer();
|
||||
}
|
||||
|
||||
void push(NanoLogLine && logline) override
|
||||
{
|
||||
unsigned int write_index = m_write_index.fetch_add(1, std::memory_order_relaxed);
|
||||
if (write_index < Buffer::size)
|
||||
{
|
||||
if (m_current_write_buffer.load(std::memory_order_acquire)->push(std::move(logline), write_index))
|
||||
{
|
||||
setup_next_write_buffer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (m_write_index.load(std::memory_order_acquire) >= Buffer::size);
|
||||
push(std::move(logline));
|
||||
}
|
||||
}
|
||||
|
||||
bool try_pop(NanoLogLine & logline) override
|
||||
{
|
||||
if (m_current_read_buffer == nullptr)
|
||||
m_current_read_buffer = get_next_read_buffer();
|
||||
|
||||
Buffer* read_buffer = m_current_read_buffer;
|
||||
|
||||
if (read_buffer == nullptr)
|
||||
return false;
|
||||
|
||||
if (read_buffer->try_pop(logline, m_read_index))
|
||||
{
|
||||
m_read_index++;
|
||||
if (m_read_index == Buffer::size)
|
||||
{
|
||||
m_read_index = 0;
|
||||
m_current_read_buffer = nullptr;
|
||||
SpinLock spinlock(m_flag);
|
||||
m_buffers.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void setup_next_write_buffer()
|
||||
{
|
||||
std::unique_ptr < Buffer > next_write_buffer(new Buffer());
|
||||
m_current_write_buffer.store(next_write_buffer.get(), std::memory_order_release);
|
||||
SpinLock spinlock(m_flag);
|
||||
m_buffers.push(std::move(next_write_buffer));
|
||||
m_write_index.store(0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
Buffer * get_next_read_buffer()
|
||||
{
|
||||
SpinLock spinlock(m_flag);
|
||||
return m_buffers.empty() ? nullptr : m_buffers.front().get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::queue < std::unique_ptr < Buffer > > m_buffers;
|
||||
std::atomic < Buffer * > m_current_write_buffer;
|
||||
Buffer * m_current_read_buffer;
|
||||
std::atomic < unsigned int > m_write_index;
|
||||
unsigned int m_read_index;
|
||||
std::atomic_flag m_flag = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
|
||||
class FileWriter
|
||||
{
|
||||
public:
|
||||
struct sfile_data
|
||||
{
|
||||
int64_t date = 0LL;
|
||||
int64_t index = 0LL;
|
||||
|
||||
bool operator > (const sfile_data& right) const
|
||||
{
|
||||
if(date > right.date)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(date < right.date)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return index > right.index;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator == (const sfile_data& right) const
|
||||
{
|
||||
return (date == right.date) && (index == right.index);
|
||||
}
|
||||
};
|
||||
|
||||
FileWriter(std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num)
|
||||
: m_log_file_roll_size_bytes(log_file_roll_size_mb * 1024 * 1024)
|
||||
, m_log_directory(log_directory)
|
||||
, m_name(log_directory + "/" + log_file_name)
|
||||
, m_filenum(file_num)
|
||||
, m_first_create(true)
|
||||
{
|
||||
//roll_file();
|
||||
init_fileset();
|
||||
create_file();
|
||||
}
|
||||
|
||||
void write(NanoLogLine & logline)
|
||||
{
|
||||
auto pos = m_os->tellp();
|
||||
logline.stringify(*m_os);
|
||||
m_bytes_written += m_os->tellp() - pos;
|
||||
if (m_bytes_written > m_log_file_roll_size_bytes)
|
||||
{
|
||||
roll_file();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void init_fileset()
|
||||
{
|
||||
auto files = get_all_files_in_dir(m_log_directory);
|
||||
for(auto& p : files)
|
||||
{
|
||||
insert(COMBINE_PATH(m_log_directory,p));
|
||||
}
|
||||
}
|
||||
|
||||
void insert(sfile_data file_data)
|
||||
{
|
||||
if(file_data.date <= 0LL || file_data.index < 0LL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_file_value_set.insert(file_data);
|
||||
}
|
||||
|
||||
void insert(const std::string& filename)
|
||||
{
|
||||
sfile_data file_data = filename_to_file_data(filename);
|
||||
if(file_data.date <= 0LL || file_data.index < 0LL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_file_value_set.insert(file_data);
|
||||
}
|
||||
|
||||
sfile_data filename_to_file_data(const std::string& filename){
|
||||
sfile_data file_data;
|
||||
size_t pos1 = filename.find_first_of("_");
|
||||
if (pos1 == std::string::npos)
|
||||
{
|
||||
return file_data;
|
||||
}
|
||||
size_t pos2 = filename.find_last_of("_");
|
||||
if (pos2 == std::string::npos)
|
||||
{
|
||||
return file_data;
|
||||
}
|
||||
std::string str_date = filename.substr(pos1 + 1, pos2 - pos1);
|
||||
file_data.date = atoll(str_date.c_str());
|
||||
std::string str_index = filename.substr(pos2 + 1);
|
||||
file_data.index = atoll(str_index.c_str());
|
||||
return file_data;
|
||||
}
|
||||
|
||||
std::string get_logfilename()
|
||||
{
|
||||
std::string log_file_name = "_";
|
||||
std::string date_time = NanologBase::get_datetime(NanologBase::timestamp_now());
|
||||
log_file_name.append(date_time);
|
||||
log_file_name.append("_");
|
||||
log_file_name.append(std::to_string(++m_file_number));
|
||||
return log_file_name;
|
||||
}
|
||||
|
||||
void create_file()
|
||||
{
|
||||
if(m_first_create){
|
||||
sfile_data file_data_max;
|
||||
if(!m_file_value_set.empty())
|
||||
{
|
||||
file_data_max = *(m_file_value_set.begin());
|
||||
}
|
||||
sfile_data cur_file_data = filename_to_file_data(get_logfilename());
|
||||
if(file_data_max > cur_file_data ||
|
||||
file_data_max == cur_file_data)
|
||||
{
|
||||
cur_file_data.index = file_data_max.index;
|
||||
}
|
||||
const std::string logfile_type = ".txt";
|
||||
std::string file_path = m_name + file_data_to_filename(cur_file_data) + logfile_type;
|
||||
m_os.reset(new std::ofstream());
|
||||
m_os->open(file_path, std::ofstream::out | std::ofstream::app);
|
||||
insert(cur_file_data);
|
||||
init_file_number(cur_file_data);
|
||||
m_first_create = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string logfile_type = ".txt";
|
||||
std::string logfile_suffix = get_logfilename();
|
||||
std::string file_path = m_name + logfile_suffix + logfile_type;
|
||||
m_os.reset(new std::ofstream());
|
||||
m_os->open(file_path, std::ofstream::out | std::ofstream::app);
|
||||
insert(logfile_suffix);
|
||||
}
|
||||
|
||||
delete_exceed_file();
|
||||
}
|
||||
|
||||
void init_file_number(const sfile_data& cur_file_data){
|
||||
m_file_number = cur_file_data.index;
|
||||
}
|
||||
|
||||
void delete_exceed_file(){
|
||||
if(m_filenum > 0 && m_file_value_set.size() > m_filenum)
|
||||
{
|
||||
int num = 0;
|
||||
auto it_set = m_file_value_set.begin();
|
||||
while(it_set != m_file_value_set.end())
|
||||
{
|
||||
if(num >= m_filenum)
|
||||
{
|
||||
const std::string logfile_type = ".txt";
|
||||
std::string filename = m_name + file_data_to_filename(*it_set) + logfile_type;
|
||||
try{
|
||||
remove_file(filename.c_str());
|
||||
}
|
||||
catch(const std::exception& excep)
|
||||
{
|
||||
|
||||
}
|
||||
m_file_value_set.erase(it_set++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++num;
|
||||
++it_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void roll_file()
|
||||
{
|
||||
if (m_os)
|
||||
{
|
||||
m_os->flush();
|
||||
m_os->close();
|
||||
}
|
||||
|
||||
m_bytes_written = 0;
|
||||
create_file();
|
||||
}
|
||||
|
||||
std::string file_data_to_filename(const sfile_data& cur_file_data)
|
||||
{
|
||||
std::string filename = "_";
|
||||
filename += std::to_string(cur_file_data.date);
|
||||
filename += "_";
|
||||
filename += std::to_string(cur_file_data.index);
|
||||
return filename;
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t m_file_number = 0;
|
||||
std::streamoff m_bytes_written = 0;
|
||||
uint32_t const m_log_file_roll_size_bytes;
|
||||
std::string const m_log_directory;
|
||||
std::string const m_name;
|
||||
int m_filenum;
|
||||
bool m_first_create;
|
||||
std::unique_ptr < std::ofstream > m_os;
|
||||
std::set<sfile_data, std::greater<sfile_data> > m_file_value_set;
|
||||
};
|
||||
|
||||
/*
|
||||
* Non guaranteed logging. Uses a ring buffer to hold log lines.
|
||||
* When the ring gets full, the previous log line in the slot will be dropped.
|
||||
* Does not block producer even if the ring buffer is full.
|
||||
* ring_buffer_size_mb - LogLines are pushed into a mpsc ring buffer whose size
|
||||
* is determined by this parameter. Since each LogLine is 256 bytes,
|
||||
* ring_buffer_size = ring_buffer_size_mb * 1024 * 1024 / 256
|
||||
*/
|
||||
struct NonGuaranteedLogger
|
||||
{
|
||||
NonGuaranteedLogger(uint32_t ring_buffer_size_mb_) : ring_buffer_size_mb(ring_buffer_size_mb_) {}
|
||||
uint32_t ring_buffer_size_mb;
|
||||
};
|
||||
|
||||
/*
|
||||
* Provides a guarantee log lines will not be dropped.
|
||||
*/
|
||||
struct GuaranteedLogger
|
||||
{
|
||||
};
|
||||
|
||||
class NanoLogger
|
||||
{
|
||||
public:
|
||||
NanoLogger(NonGuaranteedLogger ngl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num)
|
||||
: m_state(State::INIT)
|
||||
, m_buffer_base(new RingBuffer(std::max(1u, ngl.ring_buffer_size_mb) * 1024 * 4))
|
||||
, m_file_writer(log_directory, log_file_name, std::max(1u, log_file_roll_size_mb), file_num)
|
||||
, m_thread(&NanoLogger::pop, this)
|
||||
{
|
||||
m_state.store(State::READY, std::memory_order_release);
|
||||
}
|
||||
|
||||
NanoLogger(GuaranteedLogger gl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num)
|
||||
: m_state(State::INIT)
|
||||
, m_buffer_base(new QueueBuffer())
|
||||
, m_file_writer(log_directory, log_file_name, std::max(1u, log_file_roll_size_mb), file_num)
|
||||
, m_thread(&NanoLogger::pop, this)
|
||||
{
|
||||
m_state.store(State::READY, std::memory_order_release);
|
||||
}
|
||||
|
||||
~NanoLogger()
|
||||
{
|
||||
m_state.store(State::SHUTDOWN);
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
void add(NanoLogLine && logline)
|
||||
{
|
||||
m_buffer_base->push(std::move(logline));
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
// Wait for constructor to complete and pull all stores done there to this thread / core.
|
||||
while (m_state.load(std::memory_order_acquire) == State::INIT)
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
||||
|
||||
NanoLogLine logline(LogLevel::INFO, nullptr, nullptr, 0);
|
||||
|
||||
while (m_state.load() == State::READY)
|
||||
{
|
||||
if (m_buffer_base->try_pop(logline))
|
||||
m_file_writer.write(logline);
|
||||
else
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
||||
}
|
||||
|
||||
// Pop and log all remaining entries
|
||||
while (m_buffer_base->try_pop(logline))
|
||||
{
|
||||
m_file_writer.write(logline);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum class State
|
||||
{
|
||||
INIT,
|
||||
READY,
|
||||
SHUTDOWN
|
||||
};
|
||||
|
||||
std::atomic < State > m_state;
|
||||
std::unique_ptr < BufferBase > m_buffer_base;
|
||||
FileWriter m_file_writer;
|
||||
std::thread m_thread;
|
||||
};
|
||||
|
||||
//std::atomic <unsigned int> loglevel;
|
||||
//std::unique_ptr <NanoLogger> nanologger;
|
||||
//std::atomic < NanoLogger * > atomic_nanologger;
|
||||
//std::atomic<bool> flush_to_console;
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
static void initialize(GuaranteedLogger gl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num);
|
||||
static void initialize(NonGuaranteedLogger ngl, std::string const & log_directory, std::string const & log_file_name, uint32_t log_file_roll_size_mb, int file_num);
|
||||
static void set_log_level(LogLevel level);
|
||||
static void set_flush_to_console(bool v);
|
||||
|
||||
public:
|
||||
static bool is_logged(LogLevel level);
|
||||
bool operator==(NanoLogLine & logline);
|
||||
};
|
||||
} // namespace nanolog
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FILE_NAME(x) strrchr(x,'\\')?strrchr(x,'\\')+1:x
|
||||
#else
|
||||
#define FILE_NAME(x) x
|
||||
#endif
|
||||
|
||||
#if defined (NDEBUG)
|
||||
#define NANO_LOG(LEVEL) ::nanolog::Logger() == ::nanolog::NanoLogLine(LEVEL, "", __func__, __LINE__)
|
||||
#else
|
||||
#define NANO_LOG(LEVEL) ::nanolog::Logger() == ::nanolog::NanoLogLine(LEVEL, FILE_NAME(__FILE__), __func__, __LINE__)
|
||||
#endif
|
||||
|
||||
#define LOG_INFO nanolog::Logger::is_logged(nanolog::LogLevel::INFO) && NANO_LOG(nanolog::LogLevel::INFO)
|
||||
#define LOG_WARN nanolog::Logger::is_logged(nanolog::LogLevel::WARN) && NANO_LOG(nanolog::LogLevel::WARN)
|
||||
#define LOG_CRIT nanolog::Logger::is_logged(nanolog::LogLevel::CRIT) && NANO_LOG(nanolog::LogLevel::CRIT)
|
||||
@@ -0,0 +1,5 @@
|
||||
// pch.cpp: 与预编译标头对应的源文件
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// 当使用预编译的头时,需要使用此源文件,编译才能成功。
|
||||
@@ -0,0 +1,13 @@
|
||||
// pch.h: 这是预编译标头文件。
|
||||
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
|
||||
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
|
||||
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
|
||||
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// 添加要在此处预编译的标头
|
||||
#include "framework.h"
|
||||
|
||||
#endif //PCH_H
|
||||
@@ -0,0 +1,345 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
|
||||
#include "post_helper.h"
|
||||
#include "util_helper.h"
|
||||
#include "app_config.h"
|
||||
#include "nanolog.h"
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#pragma comment(lib, "libcurl.lib")
|
||||
|
||||
static size_t ret_data(void* buffer, size_t size, size_t nmemb, void* userp)
|
||||
{
|
||||
string* ststr = (string*)userp;
|
||||
ststr->append((char*)buffer, size * nmemb);
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
size_t write_callback(char* ptr, size_t size, size_t nmemb, void* userdata)
|
||||
{
|
||||
FILE* fp = static_cast<FILE*>(userdata);
|
||||
if (!fp) return 0;
|
||||
|
||||
size_t length = fwrite(ptr, size, nmemb, fp);
|
||||
if (length != nmemb) {
|
||||
return length;
|
||||
}
|
||||
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
bool PostHelper::PostLogin(const std::string& name, const std::string& passwd)
|
||||
{
|
||||
string strRes;
|
||||
struct curl_slist* chunk = NULL;
|
||||
|
||||
//设置url
|
||||
string strUrl = AppConfig::Instance()->DataServerUrl + "/business/system/auth/login";
|
||||
curl_easy_setopt(curl_, CURLOPT_URL, strUrl.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //忽略服务器验证
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_HEADER, TRUE);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ret_data);
|
||||
|
||||
struct curl_slist* headers = NULL;
|
||||
headers = curl_slist_append(headers, "Content-Type:application/json;charset=utf-8");
|
||||
curl_easy_setopt(curl_, CURLOPT_POST, 1);
|
||||
|
||||
Json::Value root;
|
||||
root["username"] = name;
|
||||
root["password"] = passwd;
|
||||
Json::StreamWriterBuilder builder;
|
||||
const std::string strLoginPost = Json::writeString(builder, root);
|
||||
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, strLoginPost.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 2);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &strRes);
|
||||
|
||||
// 执行一次URL请求
|
||||
CURLcode res = curl_easy_perform(curl_);
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (!strRes.empty())
|
||||
{
|
||||
strRes = strRes.substr(strRes.find('{'), strRes.size() - 1);
|
||||
|
||||
bool res;
|
||||
JSONCPP_STRING errs;
|
||||
Json::Value root;
|
||||
Json::CharReaderBuilder readerBuilder;
|
||||
|
||||
std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
|
||||
res = jsonReader->parse(strRes.c_str(), strRes.c_str() + strRes.length(), &root, &errs);
|
||||
if (!res || !errs.empty()) {
|
||||
std::cout << "parseJson err. " << errs << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (root["code"].asInt() == 200) {
|
||||
token_ = root["data"]["accessToken"].asString();
|
||||
refresh_token_ = root["data"]["refreshToken"].asString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PostHelper::RefreshToken() {
|
||||
std::lock_guard guard(mutex_);
|
||||
string strRes;
|
||||
|
||||
//设置url
|
||||
string strUrl = AppConfig::Instance()->DataServerUrl + "/business/system/auth/refresh-token";
|
||||
curl_easy_setopt(curl_, CURLOPT_URL, strUrl.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //忽略服务器验证
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_HEADER, TRUE);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ret_data);
|
||||
|
||||
struct curl_slist* headers = NULL;
|
||||
string headerToken = "GeomativeAuthorization:" + token_;
|
||||
headers = curl_slist_append(headers, headerToken.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_POST, 1);
|
||||
|
||||
struct curl_httppost* formpost = NULL;
|
||||
struct curl_httppost* lastptr = NULL;
|
||||
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "refreshToken", CURLFORM_COPYCONTENTS, PostHelper::refresh_token_.c_str(), CURLFORM_END);
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPPOST, formpost);
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 2);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &strRes);
|
||||
|
||||
// 执行一次URL请求
|
||||
CURLcode res = curl_easy_perform(curl_);
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (!strRes.empty())
|
||||
{
|
||||
strRes = strRes.substr(strRes.find('{'), strRes.size() - 1);
|
||||
|
||||
bool res;
|
||||
JSONCPP_STRING errs;
|
||||
Json::Value root;
|
||||
Json::CharReaderBuilder readerBuilder;
|
||||
|
||||
std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
|
||||
res = jsonReader->parse(strRes.c_str(), strRes.c_str() + strRes.length(), &root, &errs);
|
||||
if (!res || !errs.empty()) {
|
||||
std::cout << "parseJson err. " << errs << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (root["code"].asInt() == 200) {
|
||||
token_ = root["data"]["accessToken"].asString();
|
||||
refresh_token_ = root["data"]["refreshToken"].asString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PostHelper::Get(const std::string& url, Json::Value& res) {
|
||||
std::lock_guard guard(mutex_);
|
||||
|
||||
std::string strRes;
|
||||
|
||||
//设置url
|
||||
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //忽略服务器验证
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_HEADER, TRUE);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ret_data);
|
||||
|
||||
struct curl_slist* headers = NULL;
|
||||
headers = curl_slist_append(headers, "Content-Type:application/json;charset=utf-8");
|
||||
string headerToken = "GeomativeAuthorization:" + token_;
|
||||
headers = curl_slist_append(headers, headerToken.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPGET, 1L);
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 10);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &strRes);
|
||||
|
||||
// 执行一次URL请求
|
||||
curl_easy_perform(curl_);
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (!strRes.empty())
|
||||
{
|
||||
if (strRes.find('{') == string::npos)
|
||||
return false;
|
||||
strRes = strRes.substr(strRes.find('{'), strRes.size() - 1);
|
||||
|
||||
JSONCPP_STRING errs;
|
||||
Json::CharReaderBuilder readerBuilder;
|
||||
std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
|
||||
if (!jsonReader->parse(strRes.c_str(), strRes.c_str() + strRes.length(), &res, &errs) || !errs.empty()) {
|
||||
std::cout << "parseJson err. " << errs << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PostHelper::Get(const std::string& url, const std::filesystem::path& file_path) {
|
||||
std::lock_guard guard(mutex_);
|
||||
|
||||
FILE* fp = fopen(file_path.string().c_str(), "wb");
|
||||
if (!fp) return false;
|
||||
|
||||
//设置url
|
||||
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //忽略服务器验证
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_HEADER, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
|
||||
struct curl_slist* headers = NULL;
|
||||
string headerToken = "GeomativeAuthorization:" + token_;
|
||||
headers = curl_slist_append(headers, headerToken.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPGET, 1L);
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 10);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, fp);
|
||||
|
||||
// 执行一次URL请求
|
||||
CURLcode res = curl_easy_perform(curl_);
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (fp) fclose(fp);
|
||||
return res == CURLE_OK;
|
||||
}
|
||||
|
||||
bool PostHelper::Post(const std::string& url, const Json::Value& arg, Json::Value& res)
|
||||
{
|
||||
std::lock_guard guard(mutex_);
|
||||
|
||||
string strRes;
|
||||
|
||||
//设置url
|
||||
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //忽略服务器验证
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_HEADER, TRUE);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ret_data);
|
||||
|
||||
struct curl_slist* headers = NULL;
|
||||
headers = curl_slist_append(headers, "Expect:");
|
||||
headers = curl_slist_append(headers, "Content-Type:application/json;charset=utf-8");
|
||||
if (!token_.empty()) {
|
||||
string headerToken = "GeomativeAuthorization:" + token_;
|
||||
headers = curl_slist_append(headers, headerToken.c_str());
|
||||
}
|
||||
|
||||
//struct curl_httppost* formpost = NULL;
|
||||
//struct curl_httppost* lastptr = NULL;
|
||||
//for (auto it = arg.begin(); it != arg.end(); it++) {
|
||||
// Json::StreamWriterBuilder builder;
|
||||
// std::string& content = it->type() < Json::ValueType::arrayValue ? it->asString() : Json::writeString(builder, *it);
|
||||
// curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, it.name().c_str(), CURLFORM_COPYCONTENTS, content.c_str(), CURLFORM_END);
|
||||
//}
|
||||
//curl_easy_setopt(curl_, CURLOPT_HTTPPOST, formpost);
|
||||
|
||||
Json::StreamWriterBuilder builder;
|
||||
const std::string strLoginPost = Json::writeString(builder, arg);
|
||||
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, strLoginPost.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 2);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &strRes);
|
||||
|
||||
// 执行一次URL请求
|
||||
CURLcode res1 = curl_easy_perform(curl_);
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (!strRes.empty())
|
||||
{
|
||||
strRes = strRes.substr(strRes.find('{'), strRes.size() - 1);
|
||||
|
||||
JSONCPP_STRING errs;
|
||||
Json::CharReaderBuilder readerBuilder;
|
||||
std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
|
||||
if (!jsonReader->parse(strRes.c_str(), strRes.c_str() + strRes.length(), &res, &errs) || !errs.empty()) {
|
||||
std::cout << "parseJson err. " << errs << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PostHelper::Post(const std::string& url, const Json::Value& arg, const std::string& filePath, Json::Value& res) {
|
||||
string strRes;
|
||||
|
||||
//设置url
|
||||
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, false); //忽略服务器验证
|
||||
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_easy_setopt(curl_, CURLOPT_HEADER, TRUE);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ret_data);
|
||||
|
||||
struct curl_slist* headers = NULL;
|
||||
string headerToken = "GeomativeAuthorization:" + token_;
|
||||
headers = curl_slist_append(headers, headerToken.c_str());
|
||||
|
||||
struct curl_httppost* formpost = NULL;
|
||||
struct curl_httppost* lastptr = NULL;
|
||||
for (auto& it = arg.begin(); it != arg.end(); it++) {
|
||||
Json::StreamWriterBuilder builder;
|
||||
std::string& content = it->type() < Json::ValueType::arrayValue ? it->asString() : Json::writeString(builder, *it);
|
||||
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, it.name().c_str(), CURLFORM_COPYCONTENTS, content.c_str(), CURLFORM_END);
|
||||
}
|
||||
if (!filePath.empty()) {
|
||||
auto fileName = filePath.substr(filePath.find_last_of('\\') + 1, filePath.length());
|
||||
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "file", CURLFORM_FILENAME, fileName.c_str(), CURLFORM_FILE, filePath.c_str(), CURLFORM_END);
|
||||
}
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPPOST, formpost);
|
||||
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 10);
|
||||
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &strRes);
|
||||
|
||||
// 执行一次URL请求
|
||||
curl_easy_perform(curl_);
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (!strRes.empty())
|
||||
{
|
||||
strRes = strRes.substr(strRes.find('{'), strRes.size() - 1);
|
||||
|
||||
JSONCPP_STRING errs;
|
||||
Json::CharReaderBuilder readerBuilder;
|
||||
std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
|
||||
if (!jsonReader->parse(strRes.c_str(), strRes.c_str() + strRes.length(), &res, &errs) || !errs.empty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PostHelper::init_curl() {
|
||||
curl_ = curl_easy_init();
|
||||
}
|
||||
|
||||
void PostHelper::exit_curl() {
|
||||
if (nullptr != curl_) {
|
||||
curl_easy_cleanup(curl_);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
|
||||
#include "json/json.h"
|
||||
#include "curl/curl.h"
|
||||
|
||||
class PostHelper
|
||||
{
|
||||
public:
|
||||
PostHelper() {
|
||||
init_curl();
|
||||
}
|
||||
|
||||
~PostHelper() {
|
||||
exit_curl();
|
||||
}
|
||||
|
||||
public:
|
||||
bool PostLogin(const std::string& name, const std::string& passwd);
|
||||
bool RefreshToken();
|
||||
|
||||
bool Get(const std::string& api, Json::Value& res);
|
||||
bool Get(const std::string& url, const std::filesystem::path& file_path);
|
||||
bool Post(const std::string& api, const Json::Value& arg, Json::Value& res);
|
||||
bool Post(const std::string& api, const Json::Value& arg, const std::string& filePath, Json::Value& res);
|
||||
|
||||
protected:
|
||||
void init_curl();
|
||||
void exit_curl();
|
||||
|
||||
private:
|
||||
CURL* curl_;
|
||||
std::string token_, refresh_token_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
class UtilHelper {
|
||||
|
||||
public:
|
||||
static std::string StringFormat(const char* format, ...)
|
||||
{
|
||||
#if 1 // 最大长度限制:1024 - 1
|
||||
char buff[1024] = { 0 };
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsprintf_s(buff, sizeof(buff), format, args);
|
||||
va_end(args);
|
||||
|
||||
std::string str(buff);
|
||||
return str;
|
||||
#else // 无长度限制
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int count = vsnprintf(NULL, 0, format, args); // 使用vsnprintf:warning C4996; 使用vsnprintf_s:无法自动计算长度
|
||||
va_end(args);
|
||||
|
||||
va_start(args, format);
|
||||
char* buff = (char*)malloc(count * sizeof(wchar_t));
|
||||
vsnprintf(buff, count, format, args);
|
||||
va_end(args);
|
||||
|
||||
std::string str(buff, count);
|
||||
free(buff);
|
||||
return str;
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string LaunchPath()
|
||||
{
|
||||
CHAR tszModule[MAX_PATH + 1] = { 0 };
|
||||
::GetModuleFileNameA(NULL, tszModule, MAX_PATH); /* 获取结果为应用程序全路径名称 */
|
||||
std::string filepath(tszModule);
|
||||
std::string dir = filepath.substr(0, filepath.find_last_of(L'\\'));
|
||||
return dir;
|
||||
}
|
||||
|
||||
//UTF-8到GB2312的转换
|
||||
static char* U2G(const char* utf8)
|
||||
{
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
||||
wchar_t* wstr = new wchar_t[len + 1];
|
||||
memset(wstr, 0, len + 1);
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
|
||||
len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||
char* str = new char[len + 1];
|
||||
memset(str, 0, len + 1);
|
||||
WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
|
||||
if (wstr) delete[] wstr;
|
||||
return str;
|
||||
}
|
||||
|
||||
//GB2312到UTF-8的转换
|
||||
static char* G2U(const char* gb2312)
|
||||
{
|
||||
int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
|
||||
wchar_t* wstr = new wchar_t[len + 1];
|
||||
memset(wstr, 0, len + 1);
|
||||
MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||
char* str = new char[len + 1];
|
||||
memset(str, 0, len + 1);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
|
||||
if (wstr) delete[] wstr;
|
||||
return str;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
# GeomativeSDK
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
pkginclude_HEADERS = \
|
||||
curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
|
||||
typecheck-gcc.h system.h
|
||||
|
||||
pkgincludedir= $(includedir)/curl
|
||||
|
||||
checksrc:
|
||||
@@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS)
|
||||
|
||||
if CURLDEBUG
|
||||
# for debug builds, we scan the sources on all regular make invokes
|
||||
all-local: checksrc
|
||||
endif
|
||||
@@ -0,0 +1,686 @@
|
||||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = include/curl
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \
|
||||
$(top_srcdir)/m4/curl-compilers.m4 \
|
||||
$(top_srcdir)/m4/curl-confopts.m4 \
|
||||
$(top_srcdir)/m4/curl-functions.m4 \
|
||||
$(top_srcdir)/m4/curl-openssl.m4 \
|
||||
$(top_srcdir)/m4/curl-override.m4 \
|
||||
$(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/xc-am-iface.m4 \
|
||||
$(top_srcdir)/m4/xc-cc-check.m4 \
|
||||
$(top_srcdir)/m4/xc-lt-iface.m4 \
|
||||
$(top_srcdir)/m4/xc-translit.m4 \
|
||||
$(top_srcdir)/m4/xc-val-flgs.m4 \
|
||||
$(top_srcdir)/m4/zz40-xc-ovr.m4 \
|
||||
$(top_srcdir)/m4/zz50-xc-ovr.m4 \
|
||||
$(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \
|
||||
$(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/lib/curl_config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(pkgincludedir)"
|
||||
HEADERS = $(pkginclude_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
pkgincludedir = $(includedir)/curl
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@
|
||||
CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
|
||||
CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
|
||||
CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
|
||||
CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
|
||||
CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
|
||||
CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
|
||||
CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@
|
||||
CURLVERSION = @CURLVERSION@
|
||||
CURL_CA_BUNDLE = @CURL_CA_BUNDLE@
|
||||
CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@
|
||||
CURL_DISABLE_DICT = @CURL_DISABLE_DICT@
|
||||
CURL_DISABLE_FILE = @CURL_DISABLE_FILE@
|
||||
CURL_DISABLE_FTP = @CURL_DISABLE_FTP@
|
||||
CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@
|
||||
CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@
|
||||
CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@
|
||||
CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@
|
||||
CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@
|
||||
CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@
|
||||
CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@
|
||||
CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@
|
||||
CURL_DISABLE_SMB = @CURL_DISABLE_SMB@
|
||||
CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@
|
||||
CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@
|
||||
CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@
|
||||
CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@
|
||||
CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@
|
||||
CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GCOV = @GCOV@
|
||||
GENHTML = @GENHTML@
|
||||
GREP = @GREP@
|
||||
HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@
|
||||
HAVE_LDAP_SSL = @HAVE_LDAP_SSL@
|
||||
HAVE_LIBZ = @HAVE_LIBZ@
|
||||
HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@
|
||||
IDN_ENABLED = @IDN_ENABLED@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
IPV6_ENABLED = @IPV6_ENABLED@
|
||||
LCOV = @LCOV@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@
|
||||
LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@
|
||||
LIBMETALINK_LIBS = @LIBMETALINK_LIBS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MANOPT = @MANOPT@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
NROFF = @NROFF@
|
||||
NSS_LIBS = @NSS_LIBS@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PERL = @PERL@
|
||||
PKGADD_NAME = @PKGADD_NAME@
|
||||
PKGADD_PKG = @PKGADD_PKG@
|
||||
PKGADD_VENDOR = @PKGADD_VENDOR@
|
||||
PKGCONFIG = @PKGCONFIG@
|
||||
RANDOM_FILE = @RANDOM_FILE@
|
||||
RANLIB = @RANLIB@
|
||||
REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL_ENABLED = @SSL_ENABLED@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STRIP = @STRIP@
|
||||
SUPPORT_FEATURES = @SUPPORT_FEATURES@
|
||||
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
|
||||
USE_ARES = @USE_ARES@
|
||||
USE_AXTLS = @USE_AXTLS@
|
||||
USE_CYASSL = @USE_CYASSL@
|
||||
USE_DARWINSSL = @USE_DARWINSSL@
|
||||
USE_GNUTLS = @USE_GNUTLS@
|
||||
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
|
||||
USE_LIBRTMP = @USE_LIBRTMP@
|
||||
USE_LIBSSH2 = @USE_LIBSSH2@
|
||||
USE_MBEDTLS = @USE_MBEDTLS@
|
||||
USE_NGHTTP2 = @USE_NGHTTP2@
|
||||
USE_NSS = @USE_NSS@
|
||||
USE_OPENLDAP = @USE_OPENLDAP@
|
||||
USE_POLARSSL = @USE_POLARSSL@
|
||||
USE_SCHANNEL = @USE_SCHANNEL@
|
||||
USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
|
||||
USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
|
||||
VERSION = @VERSION@
|
||||
VERSIONNUM = @VERSIONNUM@
|
||||
ZLIB_LIBS = @ZLIB_LIBS@
|
||||
ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
libext = @libext@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
pkginclude_HEADERS = \
|
||||
curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
|
||||
typecheck-gcc.h system.h
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/curl/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign include/curl/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-pkgincludeHEADERS: $(pkginclude_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
|
||||
$(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
|
||||
done
|
||||
|
||||
uninstall-pkgincludeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
|
||||
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||
dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
@CURLDEBUG_FALSE@all-local:
|
||||
all-am: Makefile $(HEADERS) all-local
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(pkgincludedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-pkgincludeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-pkgincludeHEADERS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \
|
||||
clean-generic clean-libtool cscopelist-am ctags ctags-am \
|
||||
distclean distclean-generic distclean-libtool distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-pkgincludeHEADERS \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am uninstall-pkgincludeHEADERS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
checksrc:
|
||||
@@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS)
|
||||
|
||||
# for debug builds, we scan the sources on all regular make invokes
|
||||
@CURLDEBUG_TRUE@all-local: checksrc
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
#ifndef __CURL_CURLVER_H
|
||||
#define __CURL_CURLVER_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* This header file contains nothing but libcurl version info, generated by
|
||||
a script at release-time. This was made its own header file in 7.11.2 */
|
||||
|
||||
/* This is the global package copyright */
|
||||
#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, <daniel@haxx.se>."
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.55.1"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 55
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
always follow this syntax:
|
||||
|
||||
0xXXYYZZ
|
||||
|
||||
Where XX, YY and ZZ are the main version, release and patch numbers in
|
||||
hexadecimal (using 8 bits each). All three numbers are always represented
|
||||
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
|
||||
appears as "0x090b07".
|
||||
|
||||
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
|
||||
Note: This define is the full hex number and _does not_ use the
|
||||
CURL_VERSION_BITS() macro since curl's own configure script greps for it
|
||||
and needs it to contain the full number.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x073701
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
* timestamp is not stored in git, as the timestamp is properly set in the
|
||||
* tarballs by the maketgz script.
|
||||
*
|
||||
* The format of the date follows this template:
|
||||
*
|
||||
* "2007-11-23"
|
||||
*/
|
||||
#define LIBCURL_TIMESTAMP "2017-08-14"
|
||||
|
||||
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) \
|
||||
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef __CURL_EASY_H
|
||||
#define __CURL_EASY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
CURL_EXTERN CURL *curl_easy_init(void);
|
||||
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
|
||||
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
|
||||
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_getinfo()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Request internal information from the curl session with this function. The
|
||||
* third argument MUST be a pointer to a long, a pointer to a char * or a
|
||||
* pointer to a double (as the documentation describes elsewhere). The data
|
||||
* pointed to will be filled in accordingly and can be relied upon only if the
|
||||
* function returns CURLE_OK. This function is intended to get used *AFTER* a
|
||||
* performed transfer, all results from this function are undefined until the
|
||||
* transfer is completed.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
|
||||
|
||||
|
||||
/*
|
||||
* NAME curl_easy_duphandle()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Creates a new curl session handle with the same options set for the handle
|
||||
* passed in. Duplicating a handle could only be a matter of cloning data and
|
||||
* options, internal state info and things like persistent connections cannot
|
||||
* be transferred. It is useful in multithreaded applications when you can run
|
||||
* curl_easy_duphandle() for each new thread to avoid a series of identical
|
||||
* curl_easy_setopt() invokes in every thread.
|
||||
*/
|
||||
CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_reset()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Re-initializes a CURL handle to the default values. This puts back the
|
||||
* handle to the same state as it was in when it was just created.
|
||||
*
|
||||
* It does keep: live connections, the Session ID cache, the DNS cache and the
|
||||
* cookies.
|
||||
*/
|
||||
CURL_EXTERN void curl_easy_reset(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_recv()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Receives data from the connected socket. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
|
||||
size_t *n);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_send()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Sends data over the connected socket. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
|
||||
size_t buflen, size_t *n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,439 @@
|
||||
#ifndef __CURL_MULTI_H
|
||||
#define __CURL_MULTI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
/*
|
||||
This is an "external" header file. Don't give away any internals here!
|
||||
|
||||
GOALS
|
||||
|
||||
o Enable a "pull" interface. The application that uses libcurl decides where
|
||||
and when to ask libcurl to get/send data.
|
||||
|
||||
o Enable multiple simultaneous transfers in the same thread without making it
|
||||
complicated for the application.
|
||||
|
||||
o Enable the application to select() on its own file descriptors and curl's
|
||||
file descriptors simultaneous easily.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header file should not really need to include "curl.h" since curl.h
|
||||
* itself includes this file and we expect user applications to do #include
|
||||
* <curl/curl.h> without the need for especially including multi.h.
|
||||
*
|
||||
* For some reason we added this include here at one point, and rather than to
|
||||
* break existing (wrongly written) libcurl applications, we leave it as-is
|
||||
* but with this warning attached.
|
||||
*/
|
||||
#include "curl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
|
||||
typedef struct Curl_multi CURLM;
|
||||
#else
|
||||
typedef void CURLM;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
|
||||
curl_multi_socket*() soon */
|
||||
CURLM_OK,
|
||||
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
||||
attempted to get added - again */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
/* just to make code nicer when using curl_multi_socket() you can now check
|
||||
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
|
||||
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
|
||||
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
|
||||
|
||||
/* bitmask bits for CURLMOPT_PIPELINING */
|
||||
#define CURLPIPE_NOTHING 0L
|
||||
#define CURLPIPE_HTTP1 1L
|
||||
#define CURLPIPE_MULTIPLEX 2L
|
||||
|
||||
typedef enum {
|
||||
CURLMSG_NONE, /* first, not used */
|
||||
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
|
||||
the CURLcode of the transfer */
|
||||
CURLMSG_LAST /* last, not used */
|
||||
} CURLMSG;
|
||||
|
||||
struct CURLMsg {
|
||||
CURLMSG msg; /* what this message means */
|
||||
CURL *easy_handle; /* the handle it concerns */
|
||||
union {
|
||||
void *whatever; /* message-specific data */
|
||||
CURLcode result; /* return code for transfer */
|
||||
} data;
|
||||
};
|
||||
typedef struct CURLMsg CURLMsg;
|
||||
|
||||
/* Based on poll(2) structure and values.
|
||||
* We don't use pollfd and POLL* constants explicitly
|
||||
* to cover platforms without poll(). */
|
||||
#define CURL_WAIT_POLLIN 0x0001
|
||||
#define CURL_WAIT_POLLPRI 0x0002
|
||||
#define CURL_WAIT_POLLOUT 0x0004
|
||||
|
||||
struct curl_waitfd {
|
||||
curl_socket_t fd;
|
||||
short events;
|
||||
short revents; /* not supported yet */
|
||||
};
|
||||
|
||||
/*
|
||||
* Name: curl_multi_init()
|
||||
*
|
||||
* Desc: inititalize multi-style curl usage
|
||||
*
|
||||
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
|
||||
*/
|
||||
CURL_EXTERN CURLM *curl_multi_init(void);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_add_handle()
|
||||
*
|
||||
* Desc: add a standard curl handle to the multi stack
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_remove_handle()
|
||||
*
|
||||
* Desc: removes a curl handle from the multi stack again
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_fdset()
|
||||
*
|
||||
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
|
||||
* poll() on. We want curl_multi_perform() called as soon as one of
|
||||
* them are ready.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_wait()
|
||||
*
|
||||
* Desc: Poll on all fds within a CURLM set as well as any
|
||||
* additional fds passed to the function.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
struct curl_waitfd extra_fds[],
|
||||
unsigned int extra_nfds,
|
||||
int timeout_ms,
|
||||
int *ret);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_perform()
|
||||
*
|
||||
* Desc: When the app thinks there's data available for curl it calls this
|
||||
* function to read/write whatever there is right now. This returns
|
||||
* as soon as the reads and writes are done. This function does not
|
||||
* require that there actually is data available for reading or that
|
||||
* data can be written, it can be called just in case. It returns
|
||||
* the number of handles that still transfer data in the second
|
||||
* argument's integer-pointer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
|
||||
* returns errors etc regarding the whole multi stack. There might
|
||||
* still have occurred problems on invidual transfers even when this
|
||||
* returns OK.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_cleanup()
|
||||
*
|
||||
* Desc: Cleans up and removes a whole multi stack. It does not free or
|
||||
* touch any individual easy handles in any way. We need to define
|
||||
* in what state those handles will be if this function is called
|
||||
* in the middle of a transfer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_info_read()
|
||||
*
|
||||
* Desc: Ask the multi handle if there's any messages/informationals from
|
||||
* the individual transfers. Messages include informationals such as
|
||||
* error code from the transfer or just the fact that a transfer is
|
||||
* completed. More details on these should be written down as well.
|
||||
*
|
||||
* Repeated calls to this function will return a new struct each
|
||||
* time, until a special "end of msgs" struct is returned as a signal
|
||||
* that there is no more to get at this point.
|
||||
*
|
||||
* The data the returned pointer points to will not survive calling
|
||||
* curl_multi_cleanup().
|
||||
*
|
||||
* The 'CURLMsg' struct is meant to be very simple and only contain
|
||||
* very basic information. If more involved information is wanted,
|
||||
* we will provide the particular "transfer handle" in that struct
|
||||
* and that should/could/would be used in subsequent
|
||||
* curl_easy_getinfo() calls (or similar). The point being that we
|
||||
* must never expose complex structs to applications, as then we'll
|
||||
* undoubtably get backwards compatibility problems in the future.
|
||||
*
|
||||
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
|
||||
* of structs. It also writes the number of messages left in the
|
||||
* queue (after this read) in the integer the second argument points
|
||||
* to.
|
||||
*/
|
||||
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
|
||||
int *msgs_in_queue);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_strerror()
|
||||
*
|
||||
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
|
||||
* value into the equivalent human readable error string. This is
|
||||
* useful for printing meaningful error messages.
|
||||
*
|
||||
* Returns: A pointer to a zero-terminated error message.
|
||||
*/
|
||||
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_socket() and
|
||||
* curl_multi_socket_all()
|
||||
*
|
||||
* Desc: An alternative version of curl_multi_perform() that allows the
|
||||
* application to pass in one of the file descriptors that have been
|
||||
* detected to have "action" on them and let libcurl perform.
|
||||
* See man page for details.
|
||||
*/
|
||||
#define CURL_POLL_NONE 0
|
||||
#define CURL_POLL_IN 1
|
||||
#define CURL_POLL_OUT 2
|
||||
#define CURL_POLL_INOUT 3
|
||||
#define CURL_POLL_REMOVE 4
|
||||
|
||||
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
|
||||
|
||||
#define CURL_CSELECT_IN 0x01
|
||||
#define CURL_CSELECT_OUT 0x02
|
||||
#define CURL_CSELECT_ERR 0x04
|
||||
|
||||
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
void *userp, /* private callback
|
||||
pointer */
|
||||
void *socketp); /* private socket
|
||||
pointer */
|
||||
/*
|
||||
* Name: curl_multi_timer_callback
|
||||
*
|
||||
* Desc: Called by libcurl whenever the library detects a change in the
|
||||
* maximum number of milliseconds the app is allowed to wait before
|
||||
* curl_multi_socket() or curl_multi_perform() must be called
|
||||
* (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: The callback should return zero.
|
||||
*/
|
||||
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
|
||||
long timeout_ms, /* see above */
|
||||
void *userp); /* private callback
|
||||
pointer */
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
|
||||
curl_socket_t s,
|
||||
int ev_bitmask,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
|
||||
/* This macro below was added in 7.16.3 to push users who recompile to use
|
||||
the new curl_multi_socket_action() instead of the old curl_multi_socket()
|
||||
*/
|
||||
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
*
|
||||
* Desc: Returns the maximum number of milliseconds the app is allowed to
|
||||
* wait before curl_multi_socket() or curl_multi_perform() must be
|
||||
* called (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
long *milliseconds);
|
||||
|
||||
#undef CINIT /* re-using the same name as in curl.h */
|
||||
|
||||
#ifdef CURL_ISOCPP
|
||||
#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
|
||||
#else
|
||||
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
|
||||
#define LONG CURLOPTTYPE_LONG
|
||||
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
|
||||
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
|
||||
#define OFF_T CURLOPTTYPE_OFF_T
|
||||
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* This is the socket callback function pointer */
|
||||
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
|
||||
|
||||
/* This is the argument passed to the socket callback */
|
||||
CINIT(SOCKETDATA, OBJECTPOINT, 2),
|
||||
|
||||
/* set to 1 to enable pipelining for this multi handle */
|
||||
CINIT(PIPELINING, LONG, 3),
|
||||
|
||||
/* This is the timer callback function pointer */
|
||||
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
|
||||
|
||||
/* This is the argument passed to the timer callback */
|
||||
CINIT(TIMERDATA, OBJECTPOINT, 5),
|
||||
|
||||
/* maximum number of entries in the connection cache */
|
||||
CINIT(MAXCONNECTS, LONG, 6),
|
||||
|
||||
/* maximum number of (pipelining) connections to one host */
|
||||
CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
|
||||
|
||||
/* maximum number of requests in a pipeline */
|
||||
CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
|
||||
|
||||
/* a connection with a content-length longer than this
|
||||
will not be considered for pipelining */
|
||||
CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
|
||||
|
||||
/* a connection with a chunk length longer than this
|
||||
will not be considered for pipelining */
|
||||
CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
|
||||
|
||||
/* a list of site names(+port) that are blacklisted from
|
||||
pipelining */
|
||||
CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
|
||||
|
||||
/* a list of server types that are blacklisted from
|
||||
pipelining */
|
||||
CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
|
||||
|
||||
/* maximum number of open connections in total */
|
||||
CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
|
||||
|
||||
/* This is the server push callback function pointer */
|
||||
CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
|
||||
|
||||
/* This is the argument passed to the server push callback */
|
||||
CINIT(PUSHDATA, OBJECTPOINT, 15),
|
||||
|
||||
CURLMOPT_LASTENTRY /* the last unused */
|
||||
} CURLMoption;
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_setopt()
|
||||
*
|
||||
* Desc: Sets options for the multi handle.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURLMoption option, ...);
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_assign()
|
||||
*
|
||||
* Desc: This function sets an association in the multi handle between the
|
||||
* given socket and a private pointer of the application. This is
|
||||
* (only) useful for curl_multi_socket uses.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
|
||||
curl_socket_t sockfd, void *sockp);
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_push_callback
|
||||
*
|
||||
* Desc: This callback gets called when a new stream is being pushed by the
|
||||
* server. It approves or denies the new stream.
|
||||
*
|
||||
* Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
|
||||
*/
|
||||
#define CURL_PUSH_OK 0
|
||||
#define CURL_PUSH_DENY 1
|
||||
|
||||
struct curl_pushheaders; /* forward declaration only */
|
||||
|
||||
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
|
||||
size_t num);
|
||||
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
|
||||
const char *name);
|
||||
|
||||
typedef int (*curl_push_callback)(CURL *parent,
|
||||
CURL *easy,
|
||||
size_t num_headers,
|
||||
struct curl_pushheaders *headers,
|
||||
void *userp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef __STDC_HEADERS_H
|
||||
#define __STDC_HEADERS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
size_t fread(void *, size_t, size_t, FILE *);
|
||||
size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
|
||||
int strcasecmp(const char *, const char *);
|
||||
int strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
#endif /* __STDC_HEADERS_H */
|
||||
@@ -0,0 +1,547 @@
|
||||
#ifndef __CURL_SYSTEM_H
|
||||
#define __CURL_SYSTEM_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Try to keep one section per platform, compiler and architecture, otherwise,
|
||||
* if an existing section is reused for a different one and later on the
|
||||
* original is adjusted, probably the piggybacking one can be adversely
|
||||
* changed.
|
||||
*
|
||||
* In order to differentiate between platforms/compilers/architectures use
|
||||
* only compiler built in predefined preprocessor symbols.
|
||||
*
|
||||
* curl_off_t
|
||||
* ----------
|
||||
*
|
||||
* For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
|
||||
* wide signed integral data type. The width of this data type must remain
|
||||
* constant and independent of any possible large file support settings.
|
||||
*
|
||||
* As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
|
||||
* wide signed integral data type if there is no 64-bit type.
|
||||
*
|
||||
* As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
|
||||
* only be violated if off_t is the only 64-bit data type available and the
|
||||
* size of off_t is independent of large file support settings. Keep your
|
||||
* build on the safe side avoiding an off_t gating. If you have a 64-bit
|
||||
* off_t then take for sure that another 64-bit data type exists, dig deeper
|
||||
* and you will find it.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__DJGPP__) || defined(__GO32__)
|
||||
# if defined(__DJGPP__) && (__DJGPP__ > 1)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__SALFORDC__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
# if (__BORLANDC__ < 0x520)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__TURBOC__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__WATCOMC__)
|
||||
# if defined(__386__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__POCC__)
|
||||
# if (__POCC__ < 280)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# elif defined(_MSC_VER)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__LCC__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# if defined(__EABI__) /* Treat all ARM compilers equally */
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__CW32__)
|
||||
# pragma longlong on
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__VC32__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__MWERKS__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(_WIN32_WCE)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__MINGW32__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_WS2TCPIP_H 1
|
||||
|
||||
#elif defined(__VMS)
|
||||
# if defined(__VAX)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__OS400__)
|
||||
# if defined(__ILEC400__)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(__MVS__)
|
||||
# if defined(__IBMC__) || defined(__IBMCPP__)
|
||||
# if defined(_ILP32)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# elif defined(_LP64)
|
||||
# define CURL_SIZEOF_LONG 8
|
||||
# endif
|
||||
# if defined(_LONG_LONG)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(__370__)
|
||||
# if defined(__IBMC__) || defined(__IBMCPP__)
|
||||
# if defined(_ILP32)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# elif defined(_LP64)
|
||||
# define CURL_SIZEOF_LONG 8
|
||||
# endif
|
||||
# if defined(_LONG_LONG)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(TPF)
|
||||
# define CURL_SIZEOF_LONG 8
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
#elif defined(__TINYC__) /* also known as tcc */
|
||||
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
|
||||
# if !defined(__LP64) && (defined(__ILP32) || \
|
||||
defined(__i386) || defined(__sparcv8))
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__LP64) || \
|
||||
defined(__amd64) || defined(__sparcv9)
|
||||
# define CURL_SIZEOF_LONG 8
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP MSVC THE PENULTIMATE ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP GENERIC GCC THE LAST ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
# if !defined(__LP64__) && (defined(__ILP32__) || \
|
||||
defined(__i386__) || defined(__powerpc__) || defined(__arm__) || \
|
||||
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
|
||||
defined(__XTENSA__) || (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4))
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__LP64__) || \
|
||||
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
|
||||
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8)
|
||||
# define CURL_SIZEOF_LONG 8
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SIZEOF_CURL_OFF_T 8
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#else
|
||||
/* generic "safe guess" on old 32 bit style */
|
||||
# define CURL_SIZEOF_LONG 4
|
||||
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
# define CURL_SIZEOF_CURL_OFF_T 4
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
|
||||
/* ws2tcpip.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_WS2TCPIP_H
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
|
||||
/* sys/types.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
|
||||
/* sys/socket.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* Data type definition of curl_socklen_t. */
|
||||
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
|
||||
#endif
|
||||
|
||||
/* Data type definition of curl_off_t. */
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
|
||||
* these to be visible and exported by the external libcurl interface API,
|
||||
* while also making them visible to the library internals, simply including
|
||||
* curl_setup.h, without actually needing to include curl.h internally.
|
||||
* If some day this section would grow big enough, all this should be moved
|
||||
* to its own header file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Figure out if we can use the ## preprocessor operator, which is supported
|
||||
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
|
||||
* or __cplusplus so we need to carefully check for them too.
|
||||
*/
|
||||
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
|
||||
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
|
||||
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
|
||||
defined(__ILEC400__)
|
||||
/* This compiler is believed to have an ISO compatible preprocessor */
|
||||
#define CURL_ISOCPP
|
||||
#else
|
||||
/* This compiler is believed NOT to have an ISO compatible preprocessor */
|
||||
#undef CURL_ISOCPP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
|
||||
*/
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
|
||||
# define __CURL_OFF_T_C_HLPR2(x) x
|
||||
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
|
||||
#else
|
||||
# ifdef CURL_ISOCPP
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
|
||||
# else
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
|
||||
# endif
|
||||
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_SYSTEM_H */
|
||||
@@ -0,0 +1,677 @@
|
||||
#ifndef __CURL_TYPECHECK_GCC_H
|
||||
#define __CURL_TYPECHECK_GCC_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* wraps curl_easy_setopt() with typechecking */
|
||||
|
||||
/* To add a new kind of warning, add an
|
||||
* if(_curl_is_sometype_option(_curl_opt))
|
||||
* if(!_curl_is_sometype(value))
|
||||
* _curl_easy_setopt_err_sometype();
|
||||
* block and define _curl_is_sometype_option, _curl_is_sometype and
|
||||
* _curl_easy_setopt_err_sometype below
|
||||
*
|
||||
* NOTE: We use two nested 'if' statements here instead of the && operator, in
|
||||
* order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
|
||||
* when compiling with -Wlogical-op.
|
||||
*
|
||||
* To add an option that uses the same type as an existing option, you'll just
|
||||
* need to extend the appropriate _curl_*_option macro
|
||||
*/
|
||||
#define curl_easy_setopt(handle, option, value) \
|
||||
__extension__ ({ \
|
||||
__typeof__(option) _curl_opt = option; \
|
||||
if(__builtin_constant_p(_curl_opt)) { \
|
||||
if(_curl_is_long_option(_curl_opt)) \
|
||||
if(!_curl_is_long(value)) \
|
||||
_curl_easy_setopt_err_long(); \
|
||||
if(_curl_is_off_t_option(_curl_opt)) \
|
||||
if(!_curl_is_off_t(value)) \
|
||||
_curl_easy_setopt_err_curl_off_t(); \
|
||||
if(_curl_is_string_option(_curl_opt)) \
|
||||
if(!_curl_is_string(value)) \
|
||||
_curl_easy_setopt_err_string(); \
|
||||
if(_curl_is_write_cb_option(_curl_opt)) \
|
||||
if(!_curl_is_write_cb(value)) \
|
||||
_curl_easy_setopt_err_write_callback(); \
|
||||
if((_curl_opt) == CURLOPT_READFUNCTION) \
|
||||
if(!_curl_is_read_cb(value)) \
|
||||
_curl_easy_setopt_err_read_cb(); \
|
||||
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
|
||||
if(!_curl_is_ioctl_cb(value)) \
|
||||
_curl_easy_setopt_err_ioctl_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
|
||||
if(!_curl_is_sockopt_cb(value)) \
|
||||
_curl_easy_setopt_err_sockopt_cb(); \
|
||||
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
|
||||
if(!_curl_is_opensocket_cb(value)) \
|
||||
_curl_easy_setopt_err_opensocket_cb(); \
|
||||
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
|
||||
if(!_curl_is_progress_cb(value)) \
|
||||
_curl_easy_setopt_err_progress_cb(); \
|
||||
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
|
||||
if(!_curl_is_debug_cb(value)) \
|
||||
_curl_easy_setopt_err_debug_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
|
||||
if(!_curl_is_ssl_ctx_cb(value)) \
|
||||
_curl_easy_setopt_err_ssl_ctx_cb(); \
|
||||
if(_curl_is_conv_cb_option(_curl_opt)) \
|
||||
if(!_curl_is_conv_cb(value)) \
|
||||
_curl_easy_setopt_err_conv_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
|
||||
if(!_curl_is_seek_cb(value)) \
|
||||
_curl_easy_setopt_err_seek_cb(); \
|
||||
if(_curl_is_cb_data_option(_curl_opt)) \
|
||||
if(!_curl_is_cb_data(value)) \
|
||||
_curl_easy_setopt_err_cb_data(); \
|
||||
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
|
||||
if(!_curl_is_error_buffer(value)) \
|
||||
_curl_easy_setopt_err_error_buffer(); \
|
||||
if((_curl_opt) == CURLOPT_STDERR) \
|
||||
if(!_curl_is_FILE(value)) \
|
||||
_curl_easy_setopt_err_FILE(); \
|
||||
if(_curl_is_postfields_option(_curl_opt)) \
|
||||
if(!_curl_is_postfields(value)) \
|
||||
_curl_easy_setopt_err_postfields(); \
|
||||
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
||||
if(!_curl_is_arr((value), struct curl_httppost)) \
|
||||
_curl_easy_setopt_err_curl_httpost(); \
|
||||
if(_curl_is_slist_option(_curl_opt)) \
|
||||
if(!_curl_is_arr((value), struct curl_slist)) \
|
||||
_curl_easy_setopt_err_curl_slist(); \
|
||||
if((_curl_opt) == CURLOPT_SHARE) \
|
||||
if(!_curl_is_ptr((value), CURLSH)) \
|
||||
_curl_easy_setopt_err_CURLSH(); \
|
||||
} \
|
||||
curl_easy_setopt(handle, _curl_opt, value); \
|
||||
})
|
||||
|
||||
/* wraps curl_easy_getinfo() with typechecking */
|
||||
/* FIXME: don't allow const pointers */
|
||||
#define curl_easy_getinfo(handle, info, arg) \
|
||||
__extension__ ({ \
|
||||
__typeof__(info) _curl_info = info; \
|
||||
if(__builtin_constant_p(_curl_info)) { \
|
||||
if(_curl_is_string_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), char *)) \
|
||||
_curl_easy_getinfo_err_string(); \
|
||||
if(_curl_is_long_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), long)) \
|
||||
_curl_easy_getinfo_err_long(); \
|
||||
if(_curl_is_double_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), double)) \
|
||||
_curl_easy_getinfo_err_double(); \
|
||||
if(_curl_is_slist_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_slist *)) \
|
||||
_curl_easy_getinfo_err_curl_slist(); \
|
||||
if(_curl_is_tlssessioninfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
|
||||
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
|
||||
if(_curl_is_certinfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_certinfo *)) \
|
||||
_curl_easy_getinfo_err_curl_certinfo(); \
|
||||
if(_curl_is_socket_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_socket_t)) \
|
||||
_curl_easy_getinfo_err_curl_socket(); \
|
||||
if(_curl_is_off_t_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_off_t)) \
|
||||
_curl_easy_getinfo_err_curl_off_t(); \
|
||||
} \
|
||||
curl_easy_getinfo(handle, _curl_info, arg); \
|
||||
})
|
||||
|
||||
/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
|
||||
* for now just make sure that the functions are called with three
|
||||
* arguments
|
||||
*/
|
||||
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
|
||||
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
|
||||
|
||||
|
||||
/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
|
||||
* functions */
|
||||
|
||||
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
|
||||
#define _CURL_WARNING(id, message) \
|
||||
static void __attribute__((__warning__(message))) \
|
||||
__attribute__((__unused__)) __attribute__((__noinline__)) \
|
||||
id(void) { __asm__(""); }
|
||||
|
||||
_CURL_WARNING(_curl_easy_setopt_err_long,
|
||||
"curl_easy_setopt expects a long argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
|
||||
"curl_easy_setopt expects a curl_off_t argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_string,
|
||||
"curl_easy_setopt expects a "
|
||||
"string ('char *' or char[]) argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
|
||||
"curl_easy_setopt expects a curl_write_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
|
||||
"curl_easy_setopt expects a curl_read_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
|
||||
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
|
||||
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_opensocket_callback argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
|
||||
"curl_easy_setopt expects a curl_progress_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
|
||||
"curl_easy_setopt expects a curl_debug_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
|
||||
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
|
||||
"curl_easy_setopt expects a curl_conv_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
|
||||
"curl_easy_setopt expects a curl_seek_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_cb_data,
|
||||
"curl_easy_setopt expects a "
|
||||
"private data pointer as argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
|
||||
"curl_easy_setopt expects a "
|
||||
"char buffer of CURL_ERROR_SIZE as argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_FILE,
|
||||
"curl_easy_setopt expects a 'FILE *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_postfields,
|
||||
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
|
||||
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
|
||||
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
|
||||
"curl_easy_setopt expects a CURLSH* argument for this option")
|
||||
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_string,
|
||||
"curl_easy_getinfo expects a pointer to 'char *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_long,
|
||||
"curl_easy_getinfo expects a pointer to long for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_double,
|
||||
"curl_easy_getinfo expects a pointer to double for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_tlssessioninfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_certinfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
|
||||
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
"curl_easy_getinfo expects a pointer to curl_off_t for this info")
|
||||
|
||||
/* groups of curl_easy_setops options that take the same type of argument */
|
||||
|
||||
/* To add a new option to one of the groups, just add
|
||||
* (option) == CURLOPT_SOMETHING
|
||||
* to the or-expression. If the option takes a long or curl_off_t, you don't
|
||||
* have to do anything
|
||||
*/
|
||||
|
||||
/* evaluates to true if option takes a long argument */
|
||||
#define _curl_is_long_option(option) \
|
||||
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
|
||||
|
||||
#define _curl_is_off_t_option(option) \
|
||||
((option) > CURLOPTTYPE_OFF_T)
|
||||
|
||||
/* evaluates to true if option takes a char* argument */
|
||||
#define _curl_is_string_option(option) \
|
||||
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
|
||||
(option) == CURLOPT_ACCEPT_ENCODING || \
|
||||
(option) == CURLOPT_CAINFO || \
|
||||
(option) == CURLOPT_CAPATH || \
|
||||
(option) == CURLOPT_COOKIE || \
|
||||
(option) == CURLOPT_COOKIEFILE || \
|
||||
(option) == CURLOPT_COOKIEJAR || \
|
||||
(option) == CURLOPT_COOKIELIST || \
|
||||
(option) == CURLOPT_CRLFILE || \
|
||||
(option) == CURLOPT_CUSTOMREQUEST || \
|
||||
(option) == CURLOPT_DEFAULT_PROTOCOL || \
|
||||
(option) == CURLOPT_DNS_INTERFACE || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP4 || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP6 || \
|
||||
(option) == CURLOPT_DNS_SERVERS || \
|
||||
(option) == CURLOPT_EGDSOCKET || \
|
||||
(option) == CURLOPT_FTPPORT || \
|
||||
(option) == CURLOPT_FTP_ACCOUNT || \
|
||||
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
|
||||
(option) == CURLOPT_INTERFACE || \
|
||||
(option) == CURLOPT_ISSUERCERT || \
|
||||
(option) == CURLOPT_KEYPASSWD || \
|
||||
(option) == CURLOPT_KRBLEVEL || \
|
||||
(option) == CURLOPT_LOGIN_OPTIONS || \
|
||||
(option) == CURLOPT_MAIL_AUTH || \
|
||||
(option) == CURLOPT_MAIL_FROM || \
|
||||
(option) == CURLOPT_NETRC_FILE || \
|
||||
(option) == CURLOPT_NOPROXY || \
|
||||
(option) == CURLOPT_PASSWORD || \
|
||||
(option) == CURLOPT_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PRE_PROXY || \
|
||||
(option) == CURLOPT_PROXY || \
|
||||
(option) == CURLOPT_PROXYPASSWORD || \
|
||||
(option) == CURLOPT_PROXYUSERNAME || \
|
||||
(option) == CURLOPT_PROXYUSERPWD || \
|
||||
(option) == CURLOPT_PROXY_CAINFO || \
|
||||
(option) == CURLOPT_PROXY_CAPATH || \
|
||||
(option) == CURLOPT_PROXY_CRLFILE || \
|
||||
(option) == CURLOPT_PROXY_KEYPASSWD || \
|
||||
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PROXY_SERVICE_NAME || \
|
||||
(option) == CURLOPT_PROXY_SSLCERT || \
|
||||
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSLKEY || \
|
||||
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_RANDOM_FILE || \
|
||||
(option) == CURLOPT_RANGE || \
|
||||
(option) == CURLOPT_REFERER || \
|
||||
(option) == CURLOPT_RTSP_SESSION_ID || \
|
||||
(option) == CURLOPT_RTSP_STREAM_URI || \
|
||||
(option) == CURLOPT_RTSP_TRANSPORT || \
|
||||
(option) == CURLOPT_SERVICE_NAME || \
|
||||
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
|
||||
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
|
||||
(option) == CURLOPT_SSH_KNOWNHOSTS || \
|
||||
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
|
||||
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
|
||||
(option) == CURLOPT_SSLCERT || \
|
||||
(option) == CURLOPT_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_SSLENGINE || \
|
||||
(option) == CURLOPT_SSLKEY || \
|
||||
(option) == CURLOPT_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_UNIX_SOCKET_PATH || \
|
||||
(option) == CURLOPT_URL || \
|
||||
(option) == CURLOPT_USERAGENT || \
|
||||
(option) == CURLOPT_USERNAME || \
|
||||
(option) == CURLOPT_USERPWD || \
|
||||
(option) == CURLOPT_XOAUTH2_BEARER || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
#define _curl_is_write_cb_option(option) \
|
||||
((option) == CURLOPT_HEADERFUNCTION || \
|
||||
(option) == CURLOPT_WRITEFUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a curl_conv_callback argument */
|
||||
#define _curl_is_conv_cb_option(option) \
|
||||
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a data argument to pass to a callback */
|
||||
#define _curl_is_cb_data_option(option) \
|
||||
((option) == CURLOPT_CHUNK_DATA || \
|
||||
(option) == CURLOPT_CLOSESOCKETDATA || \
|
||||
(option) == CURLOPT_DEBUGDATA || \
|
||||
(option) == CURLOPT_FNMATCH_DATA || \
|
||||
(option) == CURLOPT_HEADERDATA || \
|
||||
(option) == CURLOPT_INTERLEAVEDATA || \
|
||||
(option) == CURLOPT_IOCTLDATA || \
|
||||
(option) == CURLOPT_OPENSOCKETDATA || \
|
||||
(option) == CURLOPT_PRIVATE || \
|
||||
(option) == CURLOPT_PROGRESSDATA || \
|
||||
(option) == CURLOPT_READDATA || \
|
||||
(option) == CURLOPT_SEEKDATA || \
|
||||
(option) == CURLOPT_SOCKOPTDATA || \
|
||||
(option) == CURLOPT_SSH_KEYDATA || \
|
||||
(option) == CURLOPT_SSL_CTX_DATA || \
|
||||
(option) == CURLOPT_WRITEDATA || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a POST data argument (void* or char*) */
|
||||
#define _curl_is_postfields_option(option) \
|
||||
((option) == CURLOPT_POSTFIELDS || \
|
||||
(option) == CURLOPT_COPYPOSTFIELDS || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a struct curl_slist * argument */
|
||||
#define _curl_is_slist_option(option) \
|
||||
((option) == CURLOPT_HTTP200ALIASES || \
|
||||
(option) == CURLOPT_HTTPHEADER || \
|
||||
(option) == CURLOPT_MAIL_RCPT || \
|
||||
(option) == CURLOPT_POSTQUOTE || \
|
||||
(option) == CURLOPT_PREQUOTE || \
|
||||
(option) == CURLOPT_PROXYHEADER || \
|
||||
(option) == CURLOPT_QUOTE || \
|
||||
(option) == CURLOPT_RESOLVE || \
|
||||
(option) == CURLOPT_TELNETOPTIONS || \
|
||||
0)
|
||||
|
||||
/* groups of curl_easy_getinfo infos that take the same type of argument */
|
||||
|
||||
/* evaluates to true if info expects a pointer to char * argument */
|
||||
#define _curl_is_string_info(info) \
|
||||
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
|
||||
|
||||
/* evaluates to true if info expects a pointer to long argument */
|
||||
#define _curl_is_long_info(info) \
|
||||
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
|
||||
|
||||
/* evaluates to true if info expects a pointer to double argument */
|
||||
#define _curl_is_double_info(info) \
|
||||
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
|
||||
|
||||
/* true if info expects a pointer to struct curl_slist * argument */
|
||||
#define _curl_is_slist_info(info) \
|
||||
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
|
||||
|
||||
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
|
||||
#define _curl_is_tlssessioninfo_info(info) \
|
||||
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
|
||||
|
||||
/* true if info expects a pointer to struct curl_certinfo * argument */
|
||||
#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
|
||||
|
||||
/* true if info expects a pointer to struct curl_socket_t argument */
|
||||
#define _curl_is_socket_info(info) \
|
||||
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
|
||||
|
||||
/* true if info expects a pointer to curl_off_t argument */
|
||||
#define _curl_is_off_t_info(info) \
|
||||
(CURLINFO_OFF_T < (info))
|
||||
|
||||
|
||||
/* typecheck helpers -- check whether given expression has requested type*/
|
||||
|
||||
/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
|
||||
* otherwise define a new macro. Search for __builtin_types_compatible_p
|
||||
* in the GCC manual.
|
||||
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
|
||||
* the actual expression passed to the curl_easy_setopt macro. This
|
||||
* means that you can only apply the sizeof and __typeof__ operators, no
|
||||
* == or whatsoever.
|
||||
*/
|
||||
|
||||
/* XXX: should evaluate to true iff expr is a pointer */
|
||||
#define _curl_is_any_ptr(expr) \
|
||||
(sizeof(expr) == sizeof(void *))
|
||||
|
||||
/* evaluates to true if expr is NULL */
|
||||
/* XXX: must not evaluate expr, so this check is not accurate */
|
||||
#define _curl_is_NULL(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
|
||||
|
||||
/* evaluates to true if expr is type*, const type* or NULL */
|
||||
#define _curl_is_ptr(expr, type) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), const type *))
|
||||
|
||||
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
|
||||
#define _curl_is_arr(expr, type) \
|
||||
(_curl_is_ptr((expr), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type []))
|
||||
|
||||
/* evaluates to true if expr is a string */
|
||||
#define _curl_is_string(expr) \
|
||||
(_curl_is_arr((expr), char) || \
|
||||
_curl_is_arr((expr), signed char) || \
|
||||
_curl_is_arr((expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is a long (no matter the signedness)
|
||||
* XXX: for now, int is also accepted (and therefore short and char, which
|
||||
* are promoted to int when passed to a variadic function) */
|
||||
#define _curl_is_long(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed char) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is of type curl_off_t */
|
||||
#define _curl_is_off_t(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
|
||||
|
||||
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
|
||||
/* XXX: also check size of an char[] array? */
|
||||
#define _curl_is_error_buffer(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char[]))
|
||||
|
||||
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
|
||||
#if 0
|
||||
#define _curl_is_cb_data(expr) \
|
||||
(_curl_is_ptr((expr), void) || \
|
||||
_curl_is_ptr((expr), FILE))
|
||||
#else /* be less strict */
|
||||
#define _curl_is_cb_data(expr) \
|
||||
_curl_is_any_ptr(expr)
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type FILE* */
|
||||
#define _curl_is_FILE(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
|
||||
|
||||
/* evaluates to true if expr can be passed as POST data (void* or char*) */
|
||||
#define _curl_is_postfields(expr) \
|
||||
(_curl_is_ptr((expr), void) || \
|
||||
_curl_is_arr((expr), char))
|
||||
|
||||
/* FIXME: the whole callback checking is messy...
|
||||
* The idea is to tolerate char vs. void and const vs. not const
|
||||
* pointers in arguments at least
|
||||
*/
|
||||
/* helper: __builtin_types_compatible_p distinguishes between functions and
|
||||
* function pointers, hide it */
|
||||
#define _curl_callback_compatible(func, type) \
|
||||
(__builtin_types_compatible_p(__typeof__(func), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(func) *, type))
|
||||
|
||||
/* evaluates to true if expr is of type curl_read_callback or "similar" */
|
||||
#define _curl_is_read_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fread) *) || \
|
||||
_curl_callback_compatible((expr), curl_read_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback6))
|
||||
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_write_callback or "similar" */
|
||||
#define _curl_is_write_cb(expr) \
|
||||
(_curl_is_read_cb(expr) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fwrite) *) || \
|
||||
_curl_callback_compatible((expr), curl_write_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback6))
|
||||
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
|
||||
#define _curl_is_ioctl_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_ioctl_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback4))
|
||||
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
|
||||
#define _curl_is_sockopt_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_sockopt_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback2))
|
||||
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
|
||||
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
|
||||
curlsocktype);
|
||||
|
||||
/* evaluates to true if expr is of type curl_opensocket_callback or
|
||||
"similar" */
|
||||
#define _curl_is_opensocket_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_opensocket_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback4))
|
||||
typedef curl_socket_t (*_curl_opensocket_callback1)
|
||||
(void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback2)
|
||||
(void *, curlsocktype, const struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback3)
|
||||
(const void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback4)
|
||||
(const void *, curlsocktype, const struct curl_sockaddr *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
|
||||
#define _curl_is_progress_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_progress_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback2))
|
||||
typedef int (*_curl_progress_callback1)(void *,
|
||||
double, double, double, double);
|
||||
typedef int (*_curl_progress_callback2)(const void *,
|
||||
double, double, double, double);
|
||||
|
||||
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
|
||||
#define _curl_is_debug_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_debug_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback8))
|
||||
typedef int (*_curl_debug_callback1) (CURL *,
|
||||
curl_infotype, char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback2) (CURL *,
|
||||
curl_infotype, char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback3) (CURL *,
|
||||
curl_infotype, const char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback4) (CURL *,
|
||||
curl_infotype, const char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback5) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback6) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback7) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback8) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
|
||||
/* this is getting even messier... */
|
||||
#define _curl_is_ssl_ctx_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
|
||||
const void *);
|
||||
#ifdef HEADER_SSL_H
|
||||
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
|
||||
* this will of course break if we're included before OpenSSL headers...
|
||||
*/
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
|
||||
const void *);
|
||||
#else
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
|
||||
#define _curl_is_conv_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_conv_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback4))
|
||||
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
|
||||
|
||||
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
|
||||
#define _curl_is_seek_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_seek_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback2))
|
||||
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
|
||||
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
|
||||
|
||||
|
||||
#endif /* __CURL_TYPECHECK_GCC_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 <cstring>
|
||||
#include <memory>
|
||||
|
||||
#pragma pack(push, 8)
|
||||
|
||||
namespace Json {
|
||||
template <typename T> 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<pointer>(::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 <typename... Args> void construct(pointer p, Args&&... args) {
|
||||
// construct using "placement new" and "perfect forwarding"
|
||||
::new (static_cast<void*>(p)) T(std::forward<Args>(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 <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||
template <typename U> struct rebind { using other = SecureAllocator<U>; };
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // JSON_ALLOCATOR_H_INCLUDED
|
||||
@@ -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 <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
#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
|
||||
@@ -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 <cstddef>
|
||||
#include <cstdint>
|
||||
#include <istream>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
// 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 <typename T>
|
||||
using Allocator =
|
||||
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
||||
std::allocator<T>>::type;
|
||||
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
||||
using IStringStream =
|
||||
std::basic_istringstream<String::value_type, String::traits_type,
|
||||
String::allocator_type>;
|
||||
using OStringStream =
|
||||
std::basic_ostringstream<String::value_type, String::traits_type,
|
||||
String::allocator_type>;
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
// 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 "config.h"
|
||||
#endif
|
||||
|
||||
// Also support old flag NO_LOCALE_SUPPORT
|
||||
#ifdef NO_LOCALE_SUPPORT
|
||||
#define JSONCPP_NO_LOCALE_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifndef JSONCPP_NO_LOCALE_SUPPORT
|
||||
#include <clocale>
|
||||
#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<char>(cp);
|
||||
} else if (cp <= 0x7FF) {
|
||||
result.resize(2);
|
||||
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
||||
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
||||
} else if (cp <= 0xFFFF) {
|
||||
result.resize(3);
|
||||
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
||||
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
|
||||
} else if (cp <= 0x10FFFF) {
|
||||
result.resize(4);
|
||||
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
||||
result[0] = static_cast<char>(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<char>(value % 10U + static_cast<unsigned>('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 <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
|
||||
for (; begin != end; ++begin) {
|
||||
if (*begin == ',') {
|
||||
*begin = '.';
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
template <typename Iter> 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 <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) {
|
||||
for (; begin != end; --end) {
|
||||
if (*(end - 1) != '0') {
|
||||
return end;
|
||||
}
|
||||
// Don't delete the last zero before the decimal point.
|
||||
if (begin != (end - 1) && *(end - 2) == '.') {
|
||||
return end;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,403 @@
|
||||
// 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 <deque>
|
||||
#include <iosfwd>
|
||||
#include <istream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
// Disable warning C4251: <data member>: <type> 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 <a HREF="http://www.json.org">JSON</a> document into a
|
||||
* Value.
|
||||
*
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
|
||||
class JSONCPP_DEPRECATED(
|
||||
"Use CharReader and CharReaderBuilder instead.") 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.
|
||||
*/
|
||||
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
|
||||
Reader();
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
||||
*/
|
||||
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
|
||||
Reader(const Features& features);
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||
* 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 <a HREF="http://www.json.org">JSON</a>
|
||||
* 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<StructuredError> 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<ErrorInfo>;
|
||||
|
||||
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<Value*>;
|
||||
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 <a HREF="http://www.json.org">JSON</a>
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
@@ -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 <array>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Disable warning C4251: <data member>: <type> 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)
|
||||
|
||||
/** \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 <a HREF="http://www.json.org">JSON</a> 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<String>;
|
||||
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<CZString, Value> 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<T>` and `is<T>` member function templates and specializations.
|
||||
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
|
||||
template <typename T> 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<unsigned char>(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<String, numberOfCommentPlacement>;
|
||||
std::unique_ptr<Array> 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<bool>() const { return asBool(); }
|
||||
template <> inline bool Value::is<bool>() const { return isBool(); }
|
||||
|
||||
template <> inline Int Value::as<Int>() const { return asInt(); }
|
||||
template <> inline bool Value::is<Int>() const { return isInt(); }
|
||||
|
||||
template <> inline UInt Value::as<UInt>() const { return asUInt(); }
|
||||
template <> inline bool Value::is<UInt>() const { return isUInt(); }
|
||||
|
||||
#if defined(JSON_HAS_INT64)
|
||||
template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
|
||||
template <> inline bool Value::is<Int64>() const { return isInt64(); }
|
||||
|
||||
template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
|
||||
template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
|
||||
#endif
|
||||
|
||||
template <> inline double Value::as<double>() const { return asDouble(); }
|
||||
template <> inline bool Value::is<double>() const { return isDouble(); }
|
||||
|
||||
template <> inline String Value::as<String>() const { return asString(); }
|
||||
template <> inline bool Value::is<String>() const { return isString(); }
|
||||
|
||||
/// These `as` specializations are type conversions, and do not have a
|
||||
/// corresponding `is`.
|
||||
template <> inline float Value::as<float>() const { return asFloat(); }
|
||||
template <> inline const char* Value::as<const char*>() 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<const PathArgument*>;
|
||||
using Args = std::vector<PathArgument>;
|
||||
|
||||
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*() { return deref(); }
|
||||
pointer operator->() { return &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
|
||||
@@ -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.4"
|
||||
#define JSONCPP_VERSION_MAJOR 1
|
||||
#define JSONCPP_VERSION_MINOR 9
|
||||
#define JSONCPP_VERSION_PATCH 4
|
||||
#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
|
||||
@@ -0,0 +1,367 @@
|
||||
// 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 <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Disable warning C4251: <data member>: <type> 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<StreamWriter> 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<Json::StreamWriter> 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": "<anything>".
|
||||
* - 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.
|
||||
|
||||
* 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 JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
|
||||
public:
|
||||
virtual ~Writer();
|
||||
|
||||
virtual String write(const Value& root) = 0;
|
||||
};
|
||||
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> 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 JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") 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 <a HREF="http://www.json.org">JSON</a> 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 JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
||||
StyledWriter : public Writer {
|
||||
public:
|
||||
StyledWriter();
|
||||
~StyledWriter() override = default;
|
||||
|
||||
public: // overridden from Writer
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> 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<String>;
|
||||
|
||||
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 <a HREF="http://www.json.org">JSON</a> 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 JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") 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 <a HREF="http://www.json.org">JSON</a> 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<String>;
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user