20 Commits

Author SHA1 Message Date
269412b371 增加实例:将hp-socket通讯框架集中到UI 2026-02-26 10:12:15 +08:00
78fa2665b0 新增示例 2026-02-25 22:24:40 +08:00
cf51900c96 26-2-25 在用版本备份 2026-02-25 21:35:10 +08:00
6aa522f3e2 26-2-20 源码备份 2026-02-20 15:02:30 +08:00
c5d109e9be 备份 2026-02-20 12:18:52 +08:00
睿 安
ab7ee978e7 优化tableView单元格绘制超出的bug 2026-01-29 20:24:18 +08:00
睿 安
e22a779dda 优化前备份 2026-01-29 19:39:12 +08:00
睿 安
dcdbf051d0 优化tableView控件横向拖动滑块的显示 2026-01-29 10:43:25 +08:00
睿 安
bcb56200c1 优化textBox控件多行手动换行时,调整显示区域的问题 2026-01-29 09:58:13 +08:00
睿 安
0811c0eabb 添加ComboBox的xml实现 2026-01-29 09:45:03 +08:00
睿 安
415d9ab518 优化单元格进入编辑状态后,能跟随区域移动 2026-01-29 00:23:46 +08:00
睿 安
76be13001f 修改和新增单元格内容的对齐方式 2026-01-28 23:21:04 +08:00
睿 安
814f42120c 优化编辑框控件的多行编辑和显示;
优化表格控件单元格的多行编辑和显示效果
2026-01-28 22:27:21 +08:00
睿 安
4fe4749826 表格新增右键单击回调函数 2026-01-28 17:15:41 +08:00
睿 安
2ff880c267 新增:单元格编辑完成回调;单击第一列选中整行 2026-01-28 16:51:51 +08:00
睿 安
abcfc78596 新增tavleView控件,初步可用 2026-01-28 15:00:12 +08:00
睿 安
bcbf890ebd 新增表格控件前的备份 2026-01-27 17:45:50 +08:00
睿 安
9fe2fe5874 text控件:新增光标后插入;新增可控边界 2026-01-27 14:45:32 +08:00
睿 安
1be1ecbbf2 使用双窗口 2026-01-26 18:36:55 +08:00
睿 安
37e7d278bd 备份 2026-01-25 23:46:14 +08:00
599 changed files with 178932 additions and 166 deletions

View File

@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"mcp__ide__getDiagnostics"
]
}
}

63
.gitattributes vendored
View File

@@ -1,63 +0,0 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

23
.gitignore vendored
View File

@@ -1,3 +1,20 @@
build/*
build64/*
demo/*
################################################################################
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
################################################################################
ThirdParty/
_temp/
_bin/
.vs/
/build
/build_x64
/example
/demo
/lib
/.vs
/.vscode
*.db
*.gitignore
*.gitattributes
*.exe
*.pdb

View File

@@ -9,20 +9,31 @@ EzUI 是一个基于原生 Win32 消息机制和 Direct2D 的 C++ 桌面 UI 框
## 构建命令
```bash
build.bat # 构建 32 位版本
build64.bat # 构建 64 位版本
# 生成 Visual Studio 项目(推荐)
cmake -S . -B build_x86 -A Win32 # 32位 VS 项目
cmake -S . -B build_x64 -A x64 # 64位 VS 项目
# 或使用现有的批处理脚本
build_x86.bat # 生成 32 位项目并打开
build_x64.bat # 生成 64 位项目并打开
```
或使用 CMake 直接构建:
CMake 构建:
```bash
cmake -B build
cmake --build build
```
静态库/动态库切换:
```bash
cmake -B build -DBUILD_SHARED_LIBS=ON # 动态库
cmake -B build -DBUILD_SHARED_LIBS=OFF # 静态库(默认)
```
## 核心架构
### 窗口类型 (继承层次)
- `Window` - 经典边框窗口
- `Window` - 经典边框窗口
- `BorderlessWindow` - 无边框带阴影窗口
- `LayeredWindow` - 分层透明窗口,支持异形
- `PopupWindow` - 失焦自动关闭的弹出窗口
@@ -32,7 +43,13 @@ cmake --build build
- 基础控件:`Label`, `Button`, `TextBox`, `PictureBox`
- 选择控件:`CheckBox`, `RadioButton`, `ComboBox`
- 布局容器:`HLayout`, `VLayout`, `HListView`, `VListView`, `TileListView`, `TabLayout`
- 功能控件:`ScrollBar`, `Menu`, `NotifyIcon`, `ProgressBar`
- 功能控件:`ScrollBar`, `Menu`, `NotifyIcon`, `ProgressBar`, `TreeView`, `Spacer`, `TableView`, `IFrame`
### 布局系统
- **尺寸优先级**:比例尺寸 (`SetRateWidth/Height`) > 绝对尺寸 (`SetFixedSize`) > 控件内容大小
- **自动布局**`SetAutoWidth/Height` 让控件根据内容自动调整大小
- **停靠布局**`SetDockStyle` 支持 Fill/Vertical/Horizontal 停靠
- **布局状态**`TryPendLayout`/`ResumeLayout` 批量添加控件后统一布局
### 样式与渲染
- `UIManager` - UI 样式与资源管理,支持 XML 布局加载
@@ -41,7 +58,35 @@ cmake --build build
- `RenderTypes` - 颜色、对齐方式等绘图类型
### 事件系统
支持事件冒泡机制,可实现事件捕获与穿透。Debug 模式下按 F11 可查看布局信息和控件边界。
- 支持事件冒泡机制,可实现事件捕获与穿透
- `NotifyFlags` 控制控件哪些事件需要通知窗口
- `Event` 枚举定义所有事件类型,支持位运算组合
- Debug 模式下按 F11 可查看布局信息和控件边界
### 线程模型
- UI 线程:`Application::Run` 启动消息循环
- 跨线程调用:`BeginInvoke`(异步)/ `Invoke`(同步)
- 全局隐藏窗口 `__EzUI_MessageWnd` 用于线程通讯
### 动画系统
- `Animation` 类支持类似 Qt 的过渡动画
- 可用于控件属性(位置、大小、透明度等)的平滑过渡
### 资源管理
- 控件树内存由父控件自动管理:`Attach`/`Detach`
- 图片资源通过 `PtrManager` 自动释放
- XML 布局加载后由 `UIManager` 管理生命周期
- `ResPackage.exe` 工具用于打包资源文件
## Demo 示例
Demo 位于 `demo/` 目录:
- `helloWorld` - 基础 HelloWorld 示例
- `QQ` - 仿 QQ 登录界面
- `kugou` - 仿酷狗音乐播放器(需要 VLC 解码库)
Demo 新版位于 `demoEx/` 目录:
- `Adminstor` - 用户管理 界面示例
## 开发约定
@@ -49,3 +94,5 @@ cmake --build build
- 源文件位于 `sources/` 目录
- 一切皆控件,纯代码组合 UI
- 使用 CSS 驱动视觉,结构与样式分离
- 中文注释,中文沟通
- 每次编码完毕无需编译,让用户自行编译验证

View File

@@ -44,4 +44,7 @@ function(add_resource_package TARGET_NAME INPUT_DIR OUTPUT_FILE)
endfunction()
#添加子项目
#add_subdirectory(./demo) # 暂时注释掉,只编译库
option(BUILD_DEMO "Build demo projects" ON)
if(BUILD_DEMO)
add_subdirectory(./demo)
endif()

4
build_x64.bat Normal file
View File

@@ -0,0 +1,4 @@
chcp 65001
@echo off
cmake -S . -B build_x64 -A x64 -DBUILD_EZUI=OFF
pause

4
build_x86.bat Normal file
View File

@@ -0,0 +1,4 @@
chcp 65001
@echo off
cmake -S . -B build_x86 -A Win32 -DBUILD_EZUI=OFF
pause

95
demo/CMakeLists.txt Normal file
View File

@@ -0,0 +1,95 @@
cmake_minimum_required(VERSION 3.0...9.0)
#gui库的包含目录位置
set(include ../include)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH_NAME "x64")
else()
set(ARCH_NAME "x86")
endif()
#一个简单的helloworld
project(helloWorld)
file(GLOB src helloWorld/*.*)
add_executable(helloWorld WIN32 ${src})
target_include_directories(helloWorld PRIVATE ${include})
target_link_libraries(helloWorld PRIVATE EzUI)
set_property(TARGET helloWorld PROPERTY FOLDER "demo")
#资源打包器
project(ResPackage)
file(GLOB src ./ResPackage/*.*)
add_executable(ResPackage WIN32 ${src} )
target_include_directories(ResPackage PRIVATE ${include})
target_link_libraries(ResPackage PRIVATE EzUI)
set_property(TARGET ResPackage PROPERTY FOLDER "demo")
#仿QQ登录界面
project(QQ)
#主程序
file(GLOB src CONFIGURE_DEPENDS
"./QQ/*.h"
"./QQ/*.hpp"
"./QQ/*.c"
"./QQ/*.cpp"
"./QQ/*.rc"
)
add_executable(QQ WIN32 ${src})
target_include_directories(QQ PRIVATE ${include})
target_link_libraries(QQ PRIVATE EzUI)
# 添加资源文件到"Res"筛选项下
file(GLOB_RECURSE res_files CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/QQ/res/*.*")
target_sources(QQ PRIVATE ${res_files})
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/QQ/res" PREFIX "res" FILES ${res_files})
add_resource_package(QQ ./QQ/res ./QQ/QQ.res)
set_property(TARGET QQ PROPERTY FOLDER "demo")
#模仿酷狗音乐demo
project(kugou)
#主程序
file(GLOB src CONFIGURE_DEPENDS
"./kugou/*.h"
"./kugou/*.hpp"
"./kugou/*.c"
"./kugou/*.cpp"
"./kugou/*.rc"
)
add_executable(kugou WIN32 ${src})
# 添加资源文件到"Res"筛选项下
file(GLOB_RECURSE res_files CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/kugou/res/*.*")
target_sources(kugou PRIVATE ${res_files})
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/kugou/res" PREFIX "res" FILES ${res_files})
target_include_directories(kugou PRIVATE ${include})
#添加常用库依赖
target_include_directories(kugou PRIVATE ./kugou/include/Common/include)
target_include_directories(kugou PRIVATE ./kugou/include/vlc/include)
#添加vlc解码器依赖
target_link_directories(kugou PRIVATE ./kugou/lib/${ARCH_NAME}/Common)
target_link_directories(kugou PRIVATE ./kugou/lib/${ARCH_NAME}/vlc)
set_property(TARGET kugou PROPERTY FOLDER "demo")
#添加引用
target_link_libraries(kugou PRIVATE EzUI)
#解决 "模块对于 SAFESEH 映像是不安全的" 的报错
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
#指定为c++编译
set_target_properties(kugou PROPERTIES LINKER_LANGUAGE CXX)
target_compile_definitions(kugou PRIVATE WIN32_LEAN_AND_MEAN)
#打包kugou/res文件夹下的所有资源 输出至kugou/kugou.res
add_resource_package(kugou ./kugou/res ./kugou/kugou.res)
#执行解压vlc的解码库
add_custom_command(
TARGET kugou
POST_BUILD
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/kugou/extract${ARCH_NAME}.bat" "$<TARGET_FILE_DIR:kugou>"
COMMENT "Running extract.bat to conditionally extract dll.zip"
)

BIN
demo/QQ/QQ.APS Normal file

Binary file not shown.

1
demo/QQ/QQ.rc Normal file
View File

@@ -0,0 +1 @@
my_res EZUI_RES QQ.res

BIN
demo/QQ/QQ.res Normal file

Binary file not shown.

195
demo/QQ/QQ.vcxproj Normal file
View File

@@ -0,0 +1,195 @@
<?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>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}</ProjectGuid>
<RootNamespace>QQ</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</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'">
<OutDir>..\_bin\</OutDir>
<IntDir>..\_temp\$(Platform)$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<LibraryPath>..\..\lib;$(LibraryPath)</LibraryPath>
<TargetName>$(ProjectName)_$(Configuration)_$(Platform)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>..\_bin\</OutDir>
<IntDir>..\_temp\$(Platform)$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<LibraryPath>..\..\lib;$(LibraryPath)</LibraryPath>
<TargetName>$(ProjectName)_$(Configuration)_$(Platform)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>..\_bin\</OutDir>
<IntDir>..\_temp\$(Platform)$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<LibraryPath>..\..\lib;$(LibraryPath)</LibraryPath>
<TargetName>$(ProjectName)_$(Configuration)_$(Platform)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>..\_bin\</OutDir>
<IntDir>..\_temp\$(Platform)$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>..\..\include;$(IncludePath)</IncludePath>
<LibraryPath>..\..\lib;$(LibraryPath)</LibraryPath>
<TargetName>$(ProjectName)_$(Configuration)_$(Platform)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>EZUI_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>EZUI_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>EZUI_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>EZUI_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="loginForm.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="mainForm.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="loginForm.h" />
<ClInclude Include="mainForm.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="QQ.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="res\head.png" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 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>
<ClCompile Include="loginForm.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="mainForm.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="loginForm.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="mainForm.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="QQ.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="res\head.png">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>

4
demo/QQ/QQ.vcxproj.user Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

51
demo/QQ/loginForm.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include "loginForm.h"
#include "mainForm.h"
LoginForm::LoginForm() :LayeredWindow(320, 448)
{
umg.LoadXml("res/loginForm.htm");//加载xml里面的控件与样式
umg.SetupUI(this);
}
void LoginForm::OnNotify(Control* sender, EventArgs& args)
{
if (args.EventType == Event::OnMouseDown) {
if (sender->Name == "btnLogin") {
TextBox* editUser = (TextBox*)FindControl("user");
TextBox* editpwd = (TextBox*)FindControl("pwd");
CheckBox* ckbox = (CheckBox*)FindControl("ckbox");
if (!ckbox->GetCheck()) {
::MessageBox(Hwnd(), L"请阅读协议并勾选!", L"提示", MB_OK);
return;
}
UIString user = editUser->GetText();
UIString pwd = editpwd->GetText();
if (user == "718987717" && pwd == "123456") {
// 登录成功,跳转到主界面
Hide(); // 隐藏登录窗口
static MainForm mainForm;
mainForm.Show(); // 显示主界面
}
else {
::MessageBox(Hwnd(), L"用户名或密码错误!", L"提示", MB_OK);
}
}
if (sender->Name == "btnExit") {
Application::Exit();
}
if (!sender->GetAttribute("url").empty()) {
::ShellExecuteA(0, "open", sender->GetAttribute("url").c_str(), "", "", SW_SHOW);
}
}
__super::OnNotify(sender, args);
}
void LoginForm::OnClose(bool& bClose)
{
//bClose = false;
Application::Exit();
}
LoginForm::~LoginForm()
{
}

36
demo/QQ/loginForm.h Normal file
View File

@@ -0,0 +1,36 @@
#pragma once
#include "ezui/Application.h" //app类
#include "EzUI/Window.h" //基础窗口类
#include "EzUI/Button.h" //按钮
#include "EzUI/TextBox.h" //文本框
#include "EzUI/CheckBox.h" //复选框
#include "EzUI/PictureBox.h" //图片控件
#include "EzUI/TabLayout.h" //选项卡控件
#include "EzUI/VLayout.h" //垂直布局
#include "EzUI/HLayout.h"//水平布局
#include "EzUI/VListView.h"//垂直带滚动条列表
#include "EzUI/HListView.h"//水平带滚动条列表
#include "EzUI/TileListView.h"//瓦片列表
#include "EzUI/LayeredWindow.h"//分层窗口类-可以异型透明窗口
#include "ezui/UIManager.h"//ui管理类(使用xml生成控件)
using namespace ezui;
using Form = LayeredWindow; //支持异形透明窗口(带阴影)
//using Form = BorderlessWindow; //常规无边框窗口(带阴影)
//using Form = Window; //标准窗口(带系统标题栏)
//登录窗口
class LoginForm :public Form
{
private:
//ui管理类
UIManager umg;
protected:
virtual void OnNotify(Control* sender, EventArgs& args)override;//重载事件通知
virtual void OnClose(bool& close)override;//当窗口关闭的时候
public:
LoginForm();
virtual ~LoginForm();
};

22
demo/QQ/main.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include "loginForm.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//app类
Application app(hInstance);
app.EnableHighDpi();//启用高DPI
app.SetResource("my_res");//设定资源名称
//创建登录创建
LoginForm loginFrm;
loginFrm.Show();
//loginFrm.CloseShadowBox();
//开始消息循环
int code = app.Exec();
return code;
}

38
demo/QQ/mainForm.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "mainForm.h"
void MainForm::OnNotify(Control* sender, EventArgs& args)
{
if (args.EventType == Event::OnMouseDown) {
if (sender->Name == "btnMin") {
SendMessage(Hwnd(), WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
else if (sender->Name == "btnMax") {
if (IsZoomed(Hwnd())) {
SendMessage(Hwnd(), WM_SYSCOMMAND, SC_RESTORE, 0);
}
else {
SendMessage(Hwnd(), WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}
}
else if (sender->Name == "btnClose") {
Close();
}
}
__super::OnNotify(sender, args);
}
void MainForm::OnClose(bool& close)
{
Application::Exit();
}
MainForm::MainForm() : LayeredWindow(800, 600)
{
SetText(L"QQ主界面");
umg.LoadXml("res/mainForm.htm");
umg.SetupUI(this);
}
MainForm::~MainForm()
{
}

35
demo/QQ/mainForm.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#include "ezui/Application.h" //app类
#include "EzUI/Window.h" //基础窗口类
#include "EzUI/Button.h" //按钮
#include "EzUI/TextBox.h" //文本框
#include "EzUI/CheckBox.h" //复选框
#include "EzUI/PictureBox.h" //图片控件
#include "EzUI/TabLayout.h" //选项卡控件
#include "EzUI/VLayout.h" //垂直布局
#include "EzUI/HLayout.h"//水平布局
#include "EzUI/VListView.h"//垂直带滚动条列表
#include "EzUI/HListView.h"//水平带滚动条列表
#include "EzUI/TileListView.h"//瓦片列表
#include "EzUI/LayeredWindow.h"//分层窗口类-可以异型透明窗口
#include "ezui/UIManager.h"//ui管理类(使用xml生成控件)
#include "EzUI/LayeredWindow.h"
#include "EzUI/Label.h"
#include "EzUI/VLayout.h"
#include "EzUI/HLayout.h"
#include "EzUI/UIManager.h"
using namespace ezui;
// 主界面
class MainForm : public LayeredWindow
{
private:
UIManager umg;
protected:
virtual void OnNotify(Control* sender, EventArgs& args) override;
virtual void OnClose(bool& close) override;
public:
MainForm();
virtual ~MainForm();
};

BIN
demo/QQ/res/check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

BIN
demo/QQ/res/check_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

BIN
demo/QQ/res/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

BIN
demo/QQ/res/down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

BIN
demo/QQ/res/gif2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

BIN
demo/QQ/res/head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

86
demo/QQ/res/loginForm.htm Normal file
View File

@@ -0,0 +1,86 @@
<vbox id="mainLayout" action="move">
<hbox height="20" margin-top="5" action="move">
<spacer></spacer>
<label size="20,20" style="background-image: url(res/setting.png)"></label>
<spacer width="10"></spacer>
<label id="btnExit" size="20,20" action="close" style="background-image: url(res/close.png)"></label>
<spacer width="10"></spacer>
</hbox>
<!--<spacer height="40"></spacer>-->
<label margin-top="30" id="headImg" size="80,80" action="move"></label>
<!-- 账号输入框 -->
<hbox margin-top="25" size="258,42" style="border-radius:5px;background-color:white;">
<spacer width="24"></spacer>
<input id="user" halign="center" placeholder="输入QQ号" />
<label size="24,24" margin-right="5" style="background-image:url(res/down.png)"></label>
</hbox>
<!-- 密码输入框 -->
<hbox margin-top="10" size="258,42" style="border-radius:5px;background-color:white;">
<spacer width="24"></spacer>
<input passwordchar="*" id="pwd" halign="center" placeholder="输入密码" />
<label size="15,15" margin-right="10" style="background-image:url(res/close.png)"></label>
</hbox>
<!-- 协议勾选 -->
<hbox size="258,42" margin-top="10" style="font-size:12px">
<checkbox size="18,18" id="ckbox"></checkbox>
<label width="auto" text="我已阅读并同意"></label>
<button url="www.baidu.com" width="auto" style="color: #2D77E5;cursor:pointer" text="服务协议"></button>
<label width="auto" text="和"></label>
<button url="www.bing.com" width="auto" style="color: #2D77E5" text="QQ隐私保护指引"></button>
</hbox>
<button margin-top="15" size="258,38" id="btnLogin" text="登录"> </button>
<!-- 扫码登陆/更多选项 -->
<hbox size="258,20" margin-top="40" style="font-size:14px">
<spacer></spacer>
<button width="auto" text="扫码登录" style="color: #2D77E5 "></button>
<label width="auto" text="|" margin="0,5,0,5" style="color: #E4DFEB"></label>
<button width="auto" text="更多选项" style="color: #2D77E5 "></button>
<spacer></spacer>
</hbox>
</vbox>
<style>
#mainLayout {
background-color: #E8F0FF;
font-size: 14px;
}
#headImg {
background-image: url(res/head.png);
border-radius: 80px;
border: 2px solid white;
}
#ckbox {
background-image: url(res/check.png);
}
#ckbox:checked {
background-image: url(res/check_1.png);
}
#btnLogin {
background-color: #0099FF;
color: white;
border-radius: 8px;
}
/*登录按钮鼠标悬浮时候的外观*/
#btnLogin:hover {
background-color: #008DEB;
}
</style>

18
demo/QQ/res/mainForm.htm Normal file
View File

@@ -0,0 +1,18 @@
<vlayout id="mainLayout" action="move">
<!-- 标题栏 -->
<hbox height="20" margin-top="5" action="move">
<spacer></spacer>
<!-- 退出按钮 -->
<button id="btnExitMain" size="20,20" style="background-image: url(res/close.png)"></button>
<spacer width="10"></spacer>
</hbox>
</vlayout>
<style>
#mainLayout {
background-color: #E8F0FF;
font-size: 14px;
}
</style>

BIN
demo/QQ/res/setting.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,183 @@
#include "FileSystem.h"
namespace ezui {
namespace File {
bool Exists(const UIString& filename) {
DWORD dwAttr = ::GetFileAttributesW(filename.unicode().c_str());
return (dwAttr != INVALID_FILE_ATTRIBUTES && !(dwAttr & FILE_ATTRIBUTE_DIRECTORY));
}
bool Copy(const UIString& src, const UIString& desc) {
return ::CopyFileW(src.unicode().c_str(), desc.unicode().c_str(), FALSE);
}
bool Delete(const UIString& file) {
return ::DeleteFileW(file.unicode().c_str());
}
bool Move(const UIString& oldName, const UIString& newName) {
return ::MoveFileExW(oldName.unicode().c_str(), newName.unicode().c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
}
bool Create(const UIString& fileName) {
std::ofstream ofs(fileName.unicode(), std::ios::out | std::ios::binary);
return ofs.is_open();
}
bool Write(const char* fileData, size_t fileSize, const UIString& outFileName) {
std::ofstream ofs(outFileName.unicode(), std::ios::binary | std::ios::app);
if (ofs.is_open()) {
ofs.write(fileData, fileSize);
return ofs.good();
}
return false;
}
size_t Read(const UIString& fileName, std::string* data) {
std::ifstream ifs(fileName.unicode(), std::ios::binary);
ifs.seekg(0, std::ios::end);
size_t size = ifs.tellg();
data->resize(size);
ifs.seekg(0);
ifs.read((char*)data->data(), size);
return size;
}
}
namespace Path {
void Format(std::string* _str) {
auto& str = *_str;
size_t size = str.size();
if (size == 0) {
return;
}
char* buf = new char[size];
size_t j = 0;
for (size_t i = 0; i < size; i++)
{
if (str[i] == '\\') {
buf[j] = '/';
}
else {
buf[j] = str[i];
}
j++;
}
for (size_t i = 0; i < size; i++)
{
// 将多个斜杠替换成单个斜杠
if (buf[i] == '/') {
size_t k = i + 1;
while (buf[k] == '/' && k < size) {
k++;
}
if (k > i + 1) {
for (size_t m = i + 1; m < size - (k - i - 1); m++) {
buf[m] = buf[m + (k - i - 1)];
}
size -= (k - i - 1);
}
}
}
str.clear();
str.append(buf, size);
delete[] buf; // 释放内存
}
UIString GetFileNameWithoutExtension(const UIString& _filename) {
UIString newStr = _filename;
Path::Format(&newStr);
int bPos = newStr.rfind("/");
int ePos = newStr.rfind(".");
newStr = newStr.substr(bPos + 1, ePos - bPos - 1);
return newStr;
}
UIString GetDirectoryName(const UIString& _filename) {
UIString newStr = _filename;
Path::Format(&newStr);
int pos = newStr.rfind("/");
return newStr.substr(0, pos);
}
UIString GetExtension(const UIString& _filename) {
size_t pos = _filename.rfind(".");
return pos == size_t(-1) ? "" : _filename.substr(pos);
}
UIString GetFileName(const UIString& filename) {
return Path::GetFileNameWithoutExtension(filename) + Path::GetExtension(filename);
}
}
namespace Directory {
void __Find(const std::wstring& path, std::vector<FileInfo>* result, const std::wstring& pattern, bool looDir) {
WIN32_FIND_DATAW findData;
HANDLE findHandle = FindFirstFileW((path + L"/" + pattern).c_str(), &findData);
if (findHandle == INVALID_HANDLE_VALUE) {
return;
}
do
{
if (findData.cFileName[0] == L'.') {
continue;
}
FileInfo file;
std::wstring name = path + L"/" + findData.cFileName;
file.Name = name;
file.Attr = findData.dwFileAttributes;
result->push_back(file);
if (file.IsDirectory() && looDir) {
__Find(name, result, pattern, looDir);
}
} while (FindNextFileW(findHandle, &findData));
FindClose(findHandle);
}
bool Exists(const UIString& directoryNme) {
DWORD dwAttr = GetFileAttributesW(directoryNme.unicode().c_str());
if (dwAttr == DWORD(-1)) {
return false;
}
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
{
return true;
}
return false;
}
bool Create(const UIString& path) {
::CreateDirectoryW(path.unicode().c_str(), NULL);
if (Exists(path)) {
return true;
}
//创建多级目录
if (path.find(":") != size_t(-1)) {
UIString dir = path + "/";
Path::Format(&dir);
auto arr = dir.split("/");
UIString root;
if (!arr.empty()) {
root += arr[0] + "/";
for (size_t i = 1; i < arr.size(); i++)
{
if (arr[i].empty()) {
continue;
}
root += arr[i] + "/";
if (!Exists(root)) {
::CreateDirectoryW(root.unicode().c_str(), NULL);
}
}
}
}
return Exists(path);
}
void Copy(const UIString& srcPath, const UIString& desPath)
{
UIString basePath = srcPath;
Path::Format(&basePath);
std::vector<FileInfo> result;
Directory::Find(srcPath, &result);
for (auto& it : result) {
auto fileName = it.Name;
fileName = fileName.replace(basePath, "");
if (it.IsDirectory()) {
Directory::Create(desPath + "/" + fileName);
}
else {
File::Copy(it.Name, desPath + "/" + fileName);
}
}
}
void Find(const UIString& directory, std::vector<FileInfo>* result, const UIString& pattern, bool loopDir)
{
__Find(directory.unicode(), result, pattern.unicode(), loopDir);
}
}
}

View File

@@ -0,0 +1,50 @@
#pragma once
#include "EzUI/EzUI.h"
#include "EzUI/UIString.h"
namespace ezui {
struct FileInfo final {
UIString Name;
DWORD Attr;
bool IsDirectory() {
return (Attr & FILE_ATTRIBUTE_DIRECTORY);
}
};
namespace File {
//判断文件是否存在
UI_EXPORT bool Exists(const UIString& filenNme);
//拷贝文件
UI_EXPORT bool Copy(const UIString& src, const UIString& desc);
//删除文件
UI_EXPORT bool Delete(const UIString& file);
//文件移动或者改名
UI_EXPORT bool Move(const UIString& oldName, const UIString& newName);
//创建一个文件(如果文件已存在则清空其内容)
UI_EXPORT bool Create(const UIString& fileName);
//将指定数据以二进制方式写入文件(如果文件存在内容则追加)
UI_EXPORT bool Write(const char* fileData, size_t fileSize, const UIString& outFileName);
//读取文件到内存中
UI_EXPORT size_t Read(const UIString& fileName, std::string* data);
}
namespace Path {
//格式化路径
UI_EXPORT void Format(std::string* str);
//获取文件名(不包括目录名 不包括扩展名)
UI_EXPORT UIString GetFileNameWithoutExtension(const UIString& _filename);
//获取文件所在目录
UI_EXPORT UIString GetDirectoryName(const UIString& _filename);
//获取文件扩展名
UI_EXPORT UIString GetExtension(const UIString& _filename);
//获取文件名(文件名+扩展名)
UI_EXPORT UIString GetFileName(const UIString& filename);
}
namespace Directory {
//检测目录是否存在
UI_EXPORT bool Exists(const UIString& directoryNme);
//创建目录 不存在的多级目录将会自动创建
UI_EXPORT bool Create(const UIString& path);
//将目录和目录下的文件复制到指定的位置
UI_EXPORT void Copy(const UIString& srcPath, const UIString& desPath);
//使用通配符搜索文件和目录
UI_EXPORT void Find(const UIString& directory, std::vector<FileInfo>* result, const UIString& pattern = "*.*", bool loopDir = true);
}
};

42
demo/ResPackage/main.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "mainFrom.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//格式化命令行参数
int argc = 0;
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
std::vector<UIString> args;
for (int i = 0; i < argc; i++) {
args.emplace_back(argv[i]);
}
LocalFree(argv);
// 查找 "-package" 参数
auto it = std::find(args.begin(), args.end(), L"-package");
if (it != args.end()) {
size_t index = std::distance(args.begin(), it);
UIString packageDir = args[index + 1];
UIString outFile = args[index + 2];
UIString log = UIString("packaging... %s -> %s \n").format(packageDir.c_str(), outFile.c_str()).ansi();
printf(log.c_str());
bool bRet = Resource::Package(packageDir, outFile);
if (bRet) {
printf("package succeeded !");
}
else {
printf("package failed !");
}
return 0;
}
Application app;
app.EnableHighDpi();
MainFrm frm(lpCmdLine);
frm.Show();
return app.Exec();
};

88
demo/ResPackage/main.html Normal file
View File

@@ -0,0 +1,88 @@
<vbox id="main">
<hbox height="40">
<radiobutton class="btnTab" tablayout="tab" checked="true" text="打包" width="100"></radiobutton>
<radiobutton class="btnTab" tablayout="tab" text="解包" width="100"></radiobutton>
</hbox>
<tablayout id="tab">
<hbox id="page1">
<spacer width="10"></spacer>
<vbox>
<spacer height="10"></spacer>
<label height="30" halign="left" text="请选择你要打包的目录 :"></label>
<hbox height="30"> <textbox class="edit" id="editPackDir"></textbox> <spacer width="10"></spacer><button class="btn" id="btnBrowserDir" width="100" text="浏览"></button> </hbox>
<label halign="left" style="color:#ff0000" id="labelTipsErr" height="20"></label>
<spacer></spacer>
<label height="30" halign="left" text="请选择输出目录 :"></label>
<hbox height="30"> <textbox class="edit" id="editPackName"></textbox> <spacer width="10"></spacer><button class="btn" id="btnSatrtPackage" width="100" text="开始打包"></button> </hbox>
<spacer></spacer>
<!-- <hbox height="30"> <spacer></spacer> <button class="btn" id="btnSatrtPackage" width="100" text="开始"></button> <spacer></spacer></hbox>-->
<spacer height="10"></spacer>
</vbox>
<spacer width="10"></spacer>
</hbox>
<hbox id="page2">
<spacer width="10"></spacer>
<vbox>
<spacer height="10"></spacer>
<label height="30" halign="left" text="请选择你要预览的文件 :"></label>
<hbox height="30"> <textbox class="edit" readonly="true" id="editResFile"></textbox> <spacer width="10"></spacer><button class="btn" id="btnBrowserFile" width="100" text="浏览"></button><spacer width="10"></spacer><button class="btn" height="30" id="btnUnPackage" width="100" text="解压至..."></button> </hbox>
<spacer height="10"></spacer>
<vlist id="listFiles" scrollbar="fileScrollbar" style="background-color:rgba(175, 106, 106, 0.5)"></vlist>
</vbox>
<spacer width="10"></spacer>
</hbox>
</tablayout>
<hbox margin="0,10" height="30">
<label id="labelTips" text="技术支持 718987717@qq.com/19980103ly@gmail.com"></label>
</hbox>
</vbox>
<style>
.btn {
border-radius: 5;
border: 1;
border-color: #D0D0D0;
background-color: #FDFDFD;
font-size: 13;
}
.btn:hover {
border-color: #0078D4;
background-color: #E0EEF9;
}
.btn:active {
font-size: 14;
}
.edit {
border: 1;
border-radius: 2;
border-color: #808080;
}
#tab {
background-color: #F0F0F0;
}
.btnTab:checked {
background-color: #F0F0F0;
}
.btnTab:hover {
cursor: pointer;
}
#fileScrollbar {
border-radius: 5;
background-color: rgba(50,50,50,0.5);
fore-color: rgba(200,200,200,0.5);
}
#fileScrollbar:active {
fore-color: rgba(200,200,200,0.8);
}
</style>

View File

@@ -0,0 +1,311 @@
#include "mainFrom.h"
#include "FileSystem.h"
const wchar_t* xml = LR"xml(
<vbox id="main">
<hbox height="40">
<radiobutton class="btnTab" tablayout="tab" checked="true" text="" width="100"></radiobutton>
<radiobutton class="btnTab" tablayout="tab" text="" width="100"></radiobutton>
</hbox>
<tablayout id="tab">
<hbox id="page1">
<spacer width="10"></spacer>
<vbox>
<spacer height="10"></spacer>
<label height="30" halign="left" text="请选择你要打包的目录 :"></label>
<hbox height="30">
<textbox class="edit" id="editPackDir"></textbox>
<spacer width="10"></spacer>
<button class="btn" id="btnBrowserDir" width="100" text=""></button>
</hbox>
<label halign="left" style="color:#ff0000" id="labelTipsErr" height="20"></label>
<spacer></spacer>
<label height="30" halign="left" text="请选择输出目录 :"></label>
<hbox height="30">
<textbox class="edit" id="editPackName"></textbox>
<spacer width="10"></spacer>
<button class="btn" id="btnSatrtPackage" width="100" text=""></button>
</hbox>
<spacer></spacer>
<spacer height="10"></spacer>
</vbox>
<spacer width="10"></spacer>
</hbox>
<hbox id="page2">
<spacer width="10"></spacer>
<vbox>
<spacer height="10"></spacer>
<label height="30" halign="left" text="请选择你要预览的文件 :"></label>
<hbox height="30">
<textbox class="edit" readonly="true" id="editResFile"></textbox>
<spacer width="10"></spacer>
<button class="btn" id="btnBrowserFile" width="100" text=""></button>
<spacer width="10"></spacer>
<button class="btn" height="30" id="btnUnPackage" width="100" text="..."></button>
</hbox>
<spacer height="10"></spacer>
<vlist id="listFiles" scrollbar="fileScrollbar" style="background-color:rgba(175, 106, 106, 0.5)"></vlist>
</vbox>
<spacer width="10"></spacer>
</hbox>
</tablayout>
<hbox margin="0,10" height="30">
<label id="labelTips" text="技术支持 718987717@qq.com/19980103ly@gmail.com"></label>
</hbox>
</vbox>
<style>
.btn {
border-radius: 5px;
border: 1px #D0D0D0 solid;
background-color: #FDFDFD;
font-size: 13px;
}
.btn:hover {
border-color: #0078D4;
background-color: #E0EEF9;
}
.btn:active {
font-size: 14px;
}
.edit {
border: 1px #808080 solid;
border-radius: 2px;
}
#tab {
background-color: #F0F0F0;
}
.btnTab:checked {
background-color: #F0F0F0;
}
.btnTab:hover {
cursor: pointer;
}
#fileScrollbar {
border-radius: 5px;
background-color: rgba(50,50,50,0.5);
fore-color: rgba(200,200,200,0.5);
}
#fileScrollbar:active {
fore-color: rgba(200,200,200,0.8);
}
</style>
)xml";
void MainFrm::Init() {
this->SetText(L"EzUI资源打包器");
//ui.LoadXmlFile("main.html");
UIString xmlData = xml;
ui.LoadXml(xmlData.c_str(), xmlData.size());
ui.SetupUI(this);
//第一页的控件
this->tab = (TabLayout*)this->FindControl("tab");
this->editPackDir = (TextBox*)this->FindControl("editPackDir");
this->editPackName = (TextBox*)this->FindControl("editPackName");
this->btnSatrtPackage = (Button*)this->FindControl("btnSatrtPackage");
this->labelTipsErr = (Label*)this->FindControl("labelTipsErr");
this->labelTips = (Label*)this->FindControl("labelTips");
this->editPackDir->TextChanged = [=](const UIString text)->void {
this->OnPackDirChange();
};
//第二页的控件
this->editResFile = (TextBox*)this->FindControl("editResFile");
this->btnBrowserFile = (Button*)this->FindControl("btnBrowserFile");
this->listFiles = (VListView*)this->FindControl("listFiles");
this->btnUnPackage = (Button*)this->FindControl("btnUnPackage");
}
MainFrm::MainFrm(const UIString& cmdLine) :Window(600, 400) {
Init();
editPackDir->SetText(cmdLine);
OnPackDirChange();
}
void MainFrm::OnPackDirChange()
{
UIString dir = editPackDir->GetText();
if (dir.empty() || !PathExist(dir)) {
editPackName->SetText("");
editPackName->Invalidate();
labelTipsErr->SetText(L"打包目录无效!");
labelTipsErr->Invalidate();
return;
}
else {
labelTipsErr->SetText("");
labelTipsErr->Invalidate();
}
ui_text::Replace(&dir, "\"", "");
ui_text::Replace(&dir, "\\", "/");
ui_text::Replace(&dir, "//", "/");
if (dir[dir.size() - 1] == '/') {
dir.erase(dir.size() - 1, 1);
}
UIString resDir = dir;
UIString rootDir;
size_t pos = dir.rfind('/');
UIString dirName;
if (pos != size_t(-1)) {
rootDir = dir.substr(0, pos);
dirName = dir.substr(pos + 1);
}
UIString resFile = rootDir + "/" + dirName + ".bin";
editPackName->SetText(resFile);
editPackName->Invalidate();
}
void MainFrm::OnClose(bool& close) {
Application::Exit(0);
}
bool MainFrm::FileExists(const UIString& fileName) {
DWORD dwAttr = GetFileAttributesW(fileName.unicode().c_str());
if (dwAttr == DWORD(-1)) {
return false;
}
if (dwAttr & FILE_ATTRIBUTE_ARCHIVE) {
return true;
}
return false;
}
void MainFrm::OnNotify(Control* sd, EventArgs& args) {
if (args.EventType == Event::OnMouseDown) {
if (sd->Name == "btnBrowserDir") {
UIString dir = ShowFolderDialog(Hwnd(), "", "");
if (!dir.empty()) {
this->editPackDir->SetText(dir);
this->editPackDir->Invalidate();
this->OnPackDirChange();
}
}
if (sd->Name == "btnSatrtPackage") {
do
{
UIString resDir = editPackDir->GetText();
UIString resFile = editPackName->GetText();
if (task && !task->IsStopped()) {
::MessageBoxW(Hwnd(), L"请等待上次任务完成!", L"失败", 0);
break;
}
if (FileExists(resFile) && ::DeleteFileW(resFile.unicode().c_str()) == FALSE) {
::MessageBoxW(Hwnd(), L"文件已存在且无法覆盖!", L"失败", 0);
break;
}
if (task) {
delete task;
task = NULL;
}
if (resFile.empty()) {
::MessageBoxW(Hwnd(), L"打包文件路径不正确!", L"失败", 0);
break;
}
labelTips->SetText(L"正在计算...");
labelTips->Invalidate();
task = new Task([resDir, resFile, this]() {
Resource::Package(resDir, resFile, [=](const UIString& file, int index, int count) {
Invoke([&]() {
int rate = (index + 1) * 1.0f / count * 100 + 0.5;
labelTips->SetText(UIString("(" + std::to_string(rate) + "%)") + UIString(L"正在打包\"") + file + "\"");
labelTips->Invalidate();
});
Sleep(2);
});
Invoke([&]() {
labelTips->SetText(L"打包成功!");
labelTips->Invalidate();
::MessageBoxW(Hwnd(), L"打包成功!", L"成功", 0);
});
});
} while (false);
}
if (sd->Name == "btnBrowserFile") {
UIString resFile = ShowFileDialog(Hwnd());
OnResFileChange(resFile);
}
if (sd->Name == "btnUnPackage") {
UIString resDir = ShowFolderDialog(Hwnd());
if (!resDir.empty() && PathExist(resDir)) {
for (auto& it : this->res->Items) {
UIString fileName = resDir + "/" + it.Name;
UIString dir = Path::GetDirectoryName(fileName);
Directory::Create(dir);
File::Delete(fileName);
UIString data;
this->res->GetFile(it, &data);
File::Write(data.c_str(), data.size(), fileName);
}
::MessageBoxW(Hwnd(), L"解压完成!", L"", 0);
}
}
}
ezui::DefaultNotify(sd, args);
}
void MainFrm::OnResFileChange(UIString& resFile)
{
do
{
if (FileExists(resFile)) {
Resource* newRes = new Resource(resFile);
if (!newRes->IsGood()) {
::MessageBoxW(Hwnd(), L"不是标准的资源文件", L"错误", 0);
delete newRes;
break;
}
if (res) {
delete res;
res = NULL;
}
res = newRes;
listFiles->Clear(true);
for (auto& item : res->Items) {
FileItem* fileItem = new FileItem(item.Name, item.Size);
listFiles->Add(fileItem);
}
listFiles->Invalidate();
this->editResFile->SetText(resFile);
this->editResFile->Invalidate();
}
} while (false);
}
LRESULT MainFrm::WndProc(UINT msg, WPARAM wp, LPARAM lp) {
//准备做一个解压的功能
if (msg == WM_DROPFILES) {
HDROP hDrop = (HDROP)wp;
UINT numFiles = ::DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); // 获取拖入的文件数量
TCHAR szFilePath[MAX_PATH]{ 0 };
::DragQueryFileW(hDrop, 0, szFilePath, sizeof(szFilePath)); // 获取第一个文件路径
UIString file = szFilePath;
if (tab->GetPageIndex() == 0) {
//打包
if (PathExist(file)) {
this->editPackDir->SetText(file);
this->editPackDir->Invalidate();
this->OnPackDirChange();
}
}
else if (tab->GetPageIndex() == 1) {
//解包
if (FileExists(file)) {
this->OnResFileChange(file);
}
}
}
return __super::WndProc(msg, wp, lp);
}
MainFrm::~MainFrm() {
if (task) {
delete task;
}
if (res) {
delete res;
}
}

189
demo/ResPackage/mainFrom.h Normal file
View File

@@ -0,0 +1,189 @@
#include "EzUI/Application.h"
#include "EzUI/VLayout.h"
#include "EzUI/TextBox.h"
#include "EzUI/Button.h"
#include "EzUI/Window.h"
#include "EzUI/Resource.h"
#include "EzUI/Task.h"
#include "EzUI/HLayout.h"
#include "EzUI/UIManager.h"
using namespace ezui;
class MainFrm :public Window {
Task* task = NULL;
UIManager ui;
//选项卡
TabLayout* tab;
//第一页的控件
//要打包的目录
TextBox* editPackDir;
//打包之后要输出的文件名
TextBox* editPackName;
//开始打包的按钮
Button* btnSatrtPackage;
//提示文本
Label* labelTips;
Label* labelTipsErr;
//第二页的控件
TextBox* editResFile;
Button* btnBrowserFile;
VListView* listFiles;
Button* btnUnPackage;
//资源指针
Resource* res = NULL;
public:
void Init();
MainFrm(const UIString& cmdLine);
void OnPackDirChange();
void OnClose(bool& close) override;
bool FileExists(const UIString& fileName);
void OnNotify(Control* sender, EventArgs& args)override;
void OnResFileChange(UIString& resFile);
virtual LRESULT WndProc(UINT msg, WPARAM wp, LPARAM lp);
virtual ~MainFrm();
};
inline bool FileExists(const UIString& filename) {
DWORD dwAttr = GetFileAttributesW(filename.unicode().c_str());
if (dwAttr == DWORD(-1)) {
return false;
}
if (dwAttr & FILE_ATTRIBUTE_ARCHIVE) {
return true;
}
return false;
}
inline bool PathExist(const UIString& dir) {
DWORD dwAttr = GetFileAttributesW(dir.unicode().c_str());
if (dwAttr == DWORD(-1)) {
return false;
}
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
{
return true;
}
return false;
}
inline bool CreatePath(const UIString& path) {
::CreateDirectoryW(path.unicode().c_str(), NULL);
if (PathExist(path)) {
return true;
}
//创建多级目录
if (path.find(":") != size_t(-1)) {
UIString dir = path + "/";
dir = dir.replace("\\", "/");
dir = dir.replace("//", "/");
auto arr = dir.split("/");
UIString root;
if (arr.size() > 0) {
root += arr[0] + "/";
for (size_t i = 1; i < arr.size(); i++)
{
if (arr[i].empty()) {
continue;
}
root += arr[i] + "/";
if (!PathExist(root)) {
::CreateDirectoryW(root.unicode().c_str(), NULL);
}
}
}
}
return PathExist(path);
}
inline UIString ShowFileDialog(HWND ownerWnd, const UIString& defaultPath = "", const UIString& title = "") {
OPENFILENAMEW ofn; // 打开文件对话框结构体
WCHAR szFile[512]{ 0 }; // 选择的文件名
// 初始化OPENFILENAME结构体
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.hwndOwner = ownerWnd;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All Files\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// 显示文件对话框
if (GetOpenFileNameW(&ofn) == TRUE) {
return szFile;
}
return szFile;
}
#include <ShlObj.h>
inline UIString ShowFolderDialog(HWND ownerWnd, const UIString& defaultPath = "", const UIString& title = "") {
WCHAR selectedPath[MAX_PATH]{ 0 };
BROWSEINFOW browseInfo{ 0 };
browseInfo.hwndOwner = ownerWnd;
browseInfo.pszDisplayName = selectedPath;
auto wTitle = title.unicode();
browseInfo.lpszTitle = wTitle.c_str();
//设置根目录
LPITEMIDLIST pidlRoot;
::SHParseDisplayName(defaultPath.unicode().c_str(), NULL, &pidlRoot, 0, NULL);
browseInfo.pidlRoot = pidlRoot;
browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
LPITEMIDLIST itemIdList = SHBrowseForFolderW(&browseInfo);
if (itemIdList != nullptr) {
SHGetPathFromIDListW(itemIdList, selectedPath);//设置路径
CoTaskMemFree(itemIdList);//清理
return selectedPath;
}
return selectedPath;
}
inline std::string GetFileSize(__int64 _KEY_FILE_SIZE) {
std::string ext;
std::string disp_size;
long double KEY_FILE_SIZE = _KEY_FILE_SIZE;
if (KEY_FILE_SIZE > 1024) {
KEY_FILE_SIZE = KEY_FILE_SIZE / 1024.0f; // kb
ext = "KB";
if (KEY_FILE_SIZE > 1024) {
KEY_FILE_SIZE = KEY_FILE_SIZE / 1024.0f; // mb
ext = "MB";
if (KEY_FILE_SIZE > 1024) {
KEY_FILE_SIZE = KEY_FILE_SIZE / 1024.0f; // gb
ext = "GB";
}
}
}
else {
ext = "BT";
}
disp_size = ui_text::ToString(KEY_FILE_SIZE, 2) + " " + ext;
return disp_size;
}
class FileItem :public HBox {
Label name;
Label size;
public:
FileItem(const UIString& fileName, size_t fileSize) {
this->SetFixedHeight(25);
this->SetDockStyle(DockStyle::Horizontal);
name.TextAlign = TextAlign::MiddleLeft;
name.SetText(" " + fileName);
name.SetElidedText("...");
this->Add(&name);
size.SetFixedWidth(100);
size.SetText(GetFileSize(fileSize));
this->Add(&size);
name.SetHitTestVisible(false);
this->HoverStyle.BackColor = Color(100, 100, 100, 50);
this->Style.FontSize = 13;
this->ActiveStyle.FontSize = 14;
}
};

188
demo/helloWorld/main.cpp Normal file
View File

@@ -0,0 +1,188 @@
//WIN32 desktop application UI framework (2d graphical library:direct2d,后期可能会采用其他跨平台的2d图形库对整个UI框架进行跨平台)
#include <Windows.h>
#include "EzUI/EzUI.h"
#include "EzUI/BorderlessWindow.h"
#include "EzUI/Button.h"
#include "EzUI/TileListView.h"
#include "EzUI/VListView.h"
#include "EzUI/HListView.h"
#include "EzUI/HLayout.h"
#include "EzUI/VLayout.h"
#include "EzUI/Application.h"
#include "EzUI/TextBox.h"
#include "EzUI/ComBoBox.h"
#include "EzUI/CheckBox.h"
#include "EzUI/radiobutton.h"
#include "EzUI/TreeView.h"
using namespace ezui;
class MainFrm :public Window {
public:
HLayout* main;
MainFrm(int cx, int cy) :Window(cx, cy) {
//以下代码专用与测试释放托管问题
main = new HLayout;
for (size_t i = 1; i <= 3; i++)
{
auto ck = new RadioButton(this);
ck->CheckedStyle.Border.Bottom = 10;
ck->CheckedStyle.Border.Style = StrokeStyle::Solid;
ck->CheckedStyle.Border.Color = Color::Red;
ck->CheckedStyle.BackImage = Image::Make("headImg.jpg");
ck->SetText("aaa" + std::to_string(i));
main->Add(ck);
}
SetLayout(main);
}
virtual ~MainFrm() {
delete main;
}
void OnClose(bool& b) {
if (this->GetText() == "modal") {
//Application::Exit(0);
}
else {
Application::Exit(0);
}
}
};
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
Application app;//消息循环对象
app.EnableHighDpi();
//{
// MainFrm frm(800, 600);//无边框窗口
// frm.Show();
// return app.Exec();
//}
MainFrm frm(800, 600);//无边框窗口
VLayout mainLayout;//窗口中的main布局
mainLayout.Style.BackColor = Color::White;//主布局背景颜色
//HLayout title(&mainLayout);//标题
//title.SetFixedHeight(45);//设置固定高度
//title.Style.BackgroundColor = Color::Pink;//控件背景颜色
//title.Action = ControlAction::MoveWindow;//可移动窗口的行为
//Label text(&title);//标题文字
//text.Action = ControlAction::MoveWindow;//可移动窗口的行为
//text.SetText(L"hello world ");//给label设置文字
Label closeBtn;//关闭按钮
closeBtn.Action = ControlAction::Close;//关闭窗口的行为
closeBtn.Style.FontFamily = L"Marlett";//设置成icon字体
closeBtn.Style.FontSize = 13;//字体大小
closeBtn.HoverStyle.ForeColor = Color::White;//伪样式 鼠标悬浮字体颜色变成白色
closeBtn.SetFixedWidth(45);//设置绝对高度
closeBtn.SetText(L"r");//窗口的关闭按钮icon
//Label labelBottom;
//labelBottom.SetText(L"这是一个简单的窗口示例!");
HListView list;
list.SetParent(&mainLayout);
//list.SetAutoHeight(true);
for (size_t i = 0; i < 10; i++)
{
Label* lb = new Label;// (&list);
//lb->Dock = DockStyle::Horizontal;
lb->SetText(std::to_string(i));
lb->Name = std::to_string(i);
lb->SetFixedSize({ 100,30 });
lb->Style.BackColor = Color::LightGray;
lb->HoverStyle.BackColor = Color::Red;
lb->Margin = 1;
lb->EventHandler = [&list](Control* sd, const EventArgs& arg)->void {
if (arg.EventType == Event::OnMouseDown) {
/*list.Remove(sd);
list.Invalidate();*/
MainFrm frm(500, 300);//无边框窗口
frm.SetText("modal");
VLayout mainLayout;//窗口中的main布局
mainLayout.Style.BackColor = Color::White;//主布局背景颜色
frm.SetLayout(&mainLayout);
frm.ShowModal();
}
};
list.Add(lb);
}
ComboBox cbox;
cbox.Style.Border = 1;
cbox.Style.Border.Color = Color::Gray;
cbox.Style.Border.Style = StrokeStyle::Solid;
cbox.SetFixedSize({ 100,30 });
cbox.SetParent(&mainLayout);
cbox.AddItem(L"-请选择-");
cbox.AddItem(L"青菜");
cbox.AddItem(L"牛肉");
cbox.AddItem(L"猪肉");
cbox.SetCheck(0);
TreeView treeView;
mainLayout.Add(&treeView);
for (size_t i = 0; i < 20; i++)
{
treeView.AddNode("nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_nodeName_"+std::to_string(i));
}
TextBox text;
text.SetParent(&mainLayout);
//text.SetFixedSize({ 100,50 });
text.Style.Border.Color = Color::Gray;
text.Style.Border = 1;
text.SetMultiLine(true);
text.Margin.Left = 20;
text.Margin.Right = 20;
//text.Style.Border.Radius = 20;
text.SetText(L"啊撒旦艰苦换个房间看电视进\n口的方电视进\n口的方电视进\n口的方电视进\n口的方电视进\n口的方电视进\n口的方电视进\n口的方电视进\n口的方电视进\n口的方式但是几乎都是复活节过段时间韩国");
//text.HoverStyle.FontSize = 50;
//text.ActiveStyle.FontSize = 50;
text.GetScrollBar()->SetFixedWidth(20);
Button btn;
btn.SetParent(&mainLayout);
btn.SetText(L"单行/多行切换");
btn.SetFixedSize({ 150,40 });
btn.EventHandler = [&text](Control* sd, const EventArgs& arg)->void {
if (arg.EventType == Event::OnMouseDown) {
text.SetMultiLine(!text.IsMultiLine());
text.Invalidate();
}
};
/*for (size_t i = 0; i < 99999; i++)
{
Button* lb = new Button(&list);
lb->SetText("button" + std::to_string(i));
lb->SetFixedSize({ 50,30 });
}*/
//mainLayout.AddControl(&labelBottom);//添加控件
frm.SetLayout(&mainLayout);//给窗口设置布局
frm.Show();//显示窗口
return app.Exec();//进行消息循环
}

BIN
demo/kugou/7-zip.dll Normal file

Binary file not shown.

BIN
demo/kugou/7z.dll Normal file

Binary file not shown.

BIN
demo/kugou/7z.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1,59 @@
#include "desktopLrcFrm.h"
HWND GetDeskTopWnd() {
HWND windowHandle = ::FindWindowW(L"Progman", L"Program Manager");
::SendMessageW(windowHandle, 0x052c, 0, 0);
::EnumWindows([](HWND tophandle, LPARAM lParam)->BOOL {
HWND defview = ::FindWindowExW(tophandle, 0, L"SHELLDLL_DefView", NULL);
if (defview != NULL)
{
HWND workerw = ::FindWindowExW(0, tophandle, L"WorkerW", 0);
if (workerw == NULL) {
workerw = ::FindWindowExW(tophandle, 0, L"WorkerW", 0);
*((HWND*)lParam) = workerw;
::ShowWindow(workerw, SW_SHOW);
}
else
{
::ShowWindow(workerw, SW_HIDE);
}
return FALSE;
}
return TRUE;
}, (LPARAM)&windowHandle);
return windowHandle;
}
DesktopLrcFrm::DesktopLrcFrm(VlcPlayer* player) :_player(player), LayeredWindow(0, 0) {
//关闭默认的窗口阴影
this->CloseShadowBox();
//获取桌面的窗口句柄
HWND workWnd = GetDeskTopWnd();
::SetParent(Hwnd(), workWnd);
RECT workRect;
::GetClientRect(workWnd, &workRect);
::SetWindowPos(Hwnd(), NULL, workRect.left, workRect.top, workRect.left + workRect.right, workRect.top + workRect.bottom, SWP_NOZORDER | SWP_NOACTIVATE);
//设置窗口布局
_lrc.Style.FontSize = 20;
_lrc.Style.ForeColor = Color::White;
this->SetLayout(&_lrc);
}
void DesktopLrcFrm::LoadLrc(const UIString& lrcData) {
_lrc.LoadLrc(lrcData);
}
void DesktopLrcFrm::ChangePostion(int postion) {
_lrc.ChangePostion(postion);
}
void DesktopLrcFrm::OnPaint(PaintEventArgs& arg) {
//绘制视频的帧图像到窗口上
if (_player->BuffBitmap) {
Image img(_player->BuffBitmap->GetHBITMAP());
img.SizeMode = ImageSizeMode::Cover;
arg.Graphics.DrawImage(&img, this->GetClientRect());
arg.Graphics.SetColor(Color(0, 0, 0, 100));
arg.Graphics.FillRectangle(this->GetClientRect());
}
__super::OnPaint(arg);
}

View File

@@ -0,0 +1,15 @@
#include "global.h"
#include "lrcPanel.h"
#include "VlcPlayer.h"
class DesktopLrcFrm :public LayeredWindow {
private:
VlcPlayer* _player;
LrcPanel _lrc;
protected:
void OnPaint(PaintEventArgs& args)override;
public:
DesktopLrcFrm(VlcPlayer* player);
void LoadLrc(const UIString& lrcData);
void ChangePostion(int postion);
};

674
demo/kugou/MainFrm.cpp Normal file
View File

@@ -0,0 +1,674 @@
#include "mainFrm.h"
MainFrm::MainFrm() :Form(1020, 690)
{
InitForm();
//托盘初始化
ntfi.SetTips(L"酷苟音乐");
ntfi.SetIcon(nullptr);//托盘图标
Menu* menu = new Menu(&ntfi);
UINT_PTR id_open = menu->Append(L"打开主程序");
UINT_PTR id_exit = menu->Append(L"退出");
ntfi.SetMenu(menu);
menu->MouseClick = [=](UINT_PTR menuId) {
if (menuId == id_open) {
::ShowWindow(Hwnd(), SW_RESTORE);
}
if (menuId == id_exit) {
Application::Exit();
}
};
//加载ico图标
std::string fileData;
HICON icon = ezui::LoadIcon("res/icon.ico");
ntfi.SetIcon(icon);
ntfi.EventHandler = [=](const MouseEventArgs& args)->void {
if (args.EventType == Event::OnMouseDoubleClick && args.Button == MouseButton::Left) {
::ShowWindow(Hwnd(), SW_RESTORE);
}
};
this->SetMiniSize({ 800,600 });
}
void MainFrm::InitForm() {
this->SetResizable(true);
this->SetText(L"酷苟音乐");
this->LoadXml("res/xml/main.htm");
//找到三个Frame
titleFrame = (IFrame*)this->FindControl("titleFrame");
centerFrame = (IFrame*)this->FindControl("centerFrame");
bottomFrame = (IFrame*)this->FindControl("bottomFrame");
//将这些Frame页的通知转到这个OnNotify中处理
titleFrame->NotifyHandler = centerFrame->NotifyHandler = bottomFrame->NotifyHandler = [this](Control* sender, EventArgs& args)->void {
this->OnNotify(sender, args);
};
//设置窗口边框样式
this->GetLayout()->Style.Border.Radius = 15;
this->GetLayout()->Style.Border.Color = Color(128, 128, 128, 100);
this->GetLayout()->Style.Border.Style = StrokeStyle::Solid;
this->GetLayout()->Style.Border = 1;
//关闭阴影
//this->CloseShadowBox();
//加载本地播放过的音乐
listFile = new ConfigIni(Path::StartPath() + "\\list.ini");
//找到每一个控件先
mainLayout = this->FindControl("mainLayout");
tools = centerFrame->FindControl("tools");
centerLayout = centerFrame->FindControl("centerLayout");
centerLeft = centerFrame->FindControl("centerLeft");
mediaCtl = (TabLayout*)bottomFrame->FindControl("mediaCtl");
labelTime = (Label*)bottomFrame->FindControl("labelTime");
labelSinger = (Label*)bottomFrame->FindControl("labelSinger");
playerBar2 = bottomFrame->FindControl("playerBar2");
playerBar = bottomFrame->FindControl("playerBar");
tabCtrl = (TabLayout*)centerFrame->FindControl("rightView");
vlistLocal = (VListView*)centerFrame->FindControl("playList");
vlistSearch = (VListView*)centerFrame->FindControl("searchList");
editSearch = (TextBox*)titleFrame->FindControl("searchEdit");
labelDeskLrc = (CheckBox*)bottomFrame->FindControl("deskLrc");
player.Name = "player";
centerFrame->FindControl("vlcDock")->Add(&player);
centerFrame->FindControl("lrcView2")->Add(&lrcPanel);//添加歌词控件
//创建桌面歌词视频窗口
deskTopWnd = new DesktopLrcFrm(&player);
//给默认背景图片设置缩放属性
if (mainLayout->Style.BackImage) {
mainLayout->Style.BackImage->SizeMode = ImageSizeMode::Cover;
}
for (size_t i = 0; i < 1; i++)
{
//加载左侧播放过的音乐
for (auto& item : listFile->GetSections()) {
listFile->SetSection(item);
UIString name = listFile->ReadString("name");
int dur = listFile->ReadInt("dur");
UIString singer = listFile->ReadString("singer");
LocalItem* it = new LocalItem(name, global::toTimeStr(dur));
it->SetAttribute("FileHash", item);
it->SetAttribute("SingerName", singer);
it->SetTips(name);
Song s;
s.SongName = listFile->ReadString("name");
s.hash = item;
s.Duration = listFile->ReadInt("dur");
s.SingerName = listFile->ReadString("singer");
songLsit.push_back(s);
vlistLocal->Add(it);
}
}
//滚动条滚动事件 滚动条滚动到底部加载剩余音乐
vlistSearch->GetScrollBar()->Scroll = [=](ScrollBar* sb, float pos, Event type)->void {
if (type == Event::OnMouseWheel) {
NextPage(pos);
}
};
//可穿透父控件
playerBar2->SetHitTestVisible(false);
//创建启动一个实时获取歌曲进度以及状态
timer = new Timer;
timer->Interval = 10;
timer->Tick = [=](Timer*) {
TimerTick();
};
//添加一些事件到窗口中的OnNotify函数
player.NotifyFlags = player.NotifyFlags | Event::OnPaint;
mainLayout->NotifyFlags = mainLayout->NotifyFlags | Event::OnPaint;
//播放视频的时候每一帧的回调
player.PlayingCallback = [&](Bitmap* bitmap)->void {
BeginInvoke([&]() {
this->Invalidate();
if (deskTopWnd->IsVisible()) {
this->deskTopWnd->GetLayout()->Style.BackImage = NULL;
this->deskTopWnd->Invalidate();
}
});
};
//打开默认显示界面
OpenSongView();
}
void MainFrm::OnPaint(PaintEventArgs& args) {
__super::OnPaint(args);
//args.Graphics.SetColor(Color::Red);
//Geometry path;
//PointF p1(100, 150); // 尖朝下(底部顶点)
//PointF p2(50, 50); // 左上角
//PointF p3(150, 50); // 右上角
//path.BeginFigure(p1); // BeginFigure
//path.AddLine(p2); //
//path.AddLine(p3); //
//path.CloseFigure();
//args.Graphics.FillGeometry(&path);
}
MainFrm::~MainFrm()
{
if (timer) {
delete timer;
}
if (downloadTask) {
delete downloadTask;
}
if (listFile) {
delete listFile;
}
if (headImg) {
delete headImg;
}
if (bkImg) {
delete bkImg;
}
if (vlistSearch) {
vlistSearch->Clear(true);
}
if (vlistLocal) {
vlistLocal->Clear(true);
}
if (deskTopWnd) {
delete deskTopWnd;
}
}
void MainFrm::OnClose(bool& cal) {
cal = false;
//给窗口添加淡出效果
Animation* ant = new Animation(this);//绑定父对象为frm,则ant无需手动释放
ant->SetStartValue(1.0);
ant->SetEndValue(0);
ant->ValueChanged = [&](float value) {
Invoke([this, value] {
this->Opacity = value;//修改透明度
this->Invalidate();//刷新
if (value <= 0.1) {
//退出消息循环 程序结束
Application::Exit(0);
}
});
};
this->Opacity = 1;
ant->Start(200);//开始动画
}
size_t MainFrm::FindLocalSong(const UIString& hash)
{
for (size_t i = 0; i < songLsit.size(); i++)
{
if (songLsit[i].hash == hash) {
return i;
}
}
return size_t(-1);
}
void MainFrm::DownLoadImage(UIString singers, UIString headImageUrl)
{
//随机选一个歌手
auto strs = singers.split("");
Random rdom;
int pos = rdom.Next(0, strs.size() - 1);
UIString SingerName = strs[pos];
std::string headFileData;
//下载歌手头像 酷狗的接口
{
headImg = NULL;
WebClient wc2;
auto code = wc2.HttpGet(headImageUrl.replace("{size}", "400"), &headFileData, 5);
if (code == 200) {
headImg = new Image(headFileData.c_str(), headFileData.size());
headImg->SizeMode = ImageSizeMode::Cover;
}
}
//下载歌手写真
{
bkImg = NULL;
auto rect = GetClientRect();
UIString bkurl = global::GetSingerBackground(SingerName);
if (!bkurl.empty()) {
std::string fileData;
WebClient wc2;
auto code = wc2.HttpGet(bkurl, &fileData, 5);
if (code == 200) {
Image* img = new Image(1020, 690);
{
Image* tmp = new Image(fileData.c_str(), fileData.size());
tmp->SizeMode = ImageSizeMode::Cover;
DXRender render(img);
render.DrawImage(tmp, RectF(0, 0, img->Width(), img->Height()));
delete tmp;
}
bkImg = img;
bkImg->SizeMode = ImageSizeMode::Cover;
}
}
}
//回到主线程去设置歌手头像 歌手背景图
BeginInvoke([=]() {
if (headImg) {
labelSinger->Style.ForeImage = headImg;
labelSinger->Style.BackImage->Visible = false;
}
else {
labelSinger->Style.BackImage->Visible = true;
}
if (bkImg) {
mainLayout->Style.ForeImage = bkImg;
mainLayout->Style.BackImage->Visible = false;
deskTopWnd->GetLayout()->Style.BackImage = bkImg;
}
else {
mainLayout->Style.BackImage->Visible = true;
}
labelSinger->Invalidate();
mainLayout->Invalidate();
});
}
bool MainFrm::PlaySong(const UIString& hash, Song& info)
{
timer->Stop();
UIString errStr;
bool ret = global::GetSongInfo(hash, errStr, info);
if (!ret) {
::MessageBoxW(Hwnd(), errStr.unicode().c_str(), L"无法播放", MB_OK);
return false;
}
playType = 1;//当前正在播放音乐
centerFrame->FindControl("lrcView")->SendEvent(Event::OnMouseDown);
if (this->FindLocalSong(hash) == size_t(-1)) {
info.hash = hash;
songLsit.push_back(info);
//创建左侧音乐Item
LocalItem* item = new LocalItem(info.fileName, global::toTimeStr(info.Duration));
item->SetAttribute("FileHash", hash);
item->SetAttribute("SingerName", info.SingerName);
//添加到左侧音乐列表
vlistLocal->Add(item);
vlistLocal->RefreshLayout();
vlistLocal->GetScrollBar()->ScrollTo(item);
vlistLocal->Invalidate();
//写入本地文件
listFile->SetSection(hash);
listFile->WriteString("name", info.fileName);
listFile->WriteString("singer", info.SingerName);
listFile->WriteString("dur", std::to_string(info.Duration));
}
//请求歌手头像和写真
RequestNewImage(info);
//设置一些状态
this->nowSong = hash;
this->SetText(info.fileName);
((Label*)bottomFrame->FindControl("songName"))->SetText(info.fileName);
//系统托盘处弹出正在播放音乐的提示
ntfi.ShowBalloonTip(L"播放音乐", info.fileName, 2000);
//打开URL 准备开始播放音乐
player.OpenUrl(info.url);
player.SetDuration(info.Duration);
player.Play();
UIString lrcData = global::GetSongLrc(hash);
lrcPanel.LoadLrc(lrcData);
deskTopWnd->LoadLrc(lrcData);
timer->Start();
return true;
}
void MainFrm::OnKeyDown(WPARAM wparam, LPARAM lParam)
{
//回车搜索歌曲
if (wparam == VK_RETURN) {
global::page = 1;
global::nextPage = true;
centerFrame->FindControl("songView")->SendEvent(Event::OnMouseDown);
UIString keyword = editSearch->GetText();
std::vector<Song> songs = global::SearchSongs(keyword);
vlistSearch->Clear(true);
for (auto& it : songs) {
SearchItem* sit = new SearchItem(it);
vlistSearch->Add(sit);
}
vlistSearch->Invalidate();
}
__super::OnKeyDown(wparam, lParam);
}
void MainFrm::OnNotify(Control* sender, EventArgs& args) {
do {
if (args.EventType == Event::OnPaint) {
if (sender == &player) {
if (tabCtrl->GetPageIndex() == 2) {
break;
}
return;
}
if (playType == 2 && sender == mainLayout && player.BuffBitmap) {
if (tabCtrl->GetPageIndex() == 1) {
PaintEventArgs& arg = (PaintEventArgs&)args;
Image img(player.BuffBitmap->GetHBITMAP());
img.SizeMode = ImageSizeMode::Cover;
arg.Graphics.DrawImage(&img, mainLayout->GetRect());
return;
}
else if (deskTopWnd->IsVisible()) {
deskTopWnd->Invalidate();
}
break;
}
break;
}
if (args.EventType == Event::OnMouseDoubleClick) {
if (!sender->GetAttribute("FileHash").empty()) {
UIString hash = sender->GetAttribute("FileHash");
Song info;
this->PlaySong(hash, info);
}
break;
}
if (args.EventType == Event::OnMouseDown) {
if (sender->Name == "login") {
OpenLoginFrm(sender);
break;
}
if (sender->Name == "next") {
NextSong();
break;
}
if (sender->Name == "up") {
UpSong();
break;
}
if (sender->Name == "deskLrc") {
OpenDesktopLrc();
break;
}
if (sender->Name == "play") {
player.Play();
mediaCtl->SetPageIndex(1);
mediaCtl->Invalidate();
break;
}
if (sender->Name == "pause") {
player.Pause();
mediaCtl->SetPageIndex(0);
mediaCtl->Invalidate();
break;
}
if (sender->Name == "dellocal") {
LocalItem* songItem = (LocalItem*)sender->Parent;
vlistLocal->Remove(songItem);
UIString hash = songItem->GetAttribute("FileHash");
if (!hash.empty()) {
listFile->DeleteSection(hash);
}
delete songItem;
vlistLocal->Invalidate();
return;
}
if (sender->GetAttribute("tablayout") == "rightView") {
size_t pos = sender->Parent->IndexOf(sender);
if (pos == 0) {
OpenSongView();
}
else if (pos == 1) {
OpenLrcView();
}
else {
Invalidate();
}
break;
}
if (!sender->GetAttribute("mvhash").empty()) {
timer->Stop();
UIString mvhash = sender->GetAttribute("mvhash");
UIString songHash = sender->Parent->GetAttribute("FileHash");
PlayMv(mvhash, songHash);
break;
}
if (sender == playerBar) {
const MouseEventArgs& arg = (MouseEventArgs&)args;
double f_pos = arg.Location.X * 1.0 / playerBar->Width();
player.SetPosition(f_pos);
player.Play();
break;
}
}
} while (false);
ezui::DefaultNotify(sender, args);
}
void MainFrm::OpenDesktopLrc()
{
if (deskTopWnd->IsVisible()) {
deskTopWnd->SetVisible(false);
}
else {
deskTopWnd->SetVisible(true);
deskTopWnd->Invalidate();
}
}
void MainFrm::OpenLoginFrm(ezui::Control* sender)
{
//测试代码
LoginFrm loginFrm(Hwnd());
//给窗口添加淡入效果
Animation* ant = new Animation(&loginFrm);
ant->SetStartValue(0.1);
ant->SetEndValue(1.0);
ant->ValueChanged = [&](double value) {
HWND hWnd = loginFrm.Hwnd();
BeginInvoke([&, value, hWnd] {
if (!::IsWindow(hWnd))return;
loginFrm.Opacity = value;//修改透明度
loginFrm.Invalidate();//刷新
});
};
loginFrm.Opacity = 0.1;
ant->Start(300);//开始动画
int code = loginFrm.ShowModal(true);//阻塞函数内部进行消息循环
if (code == 1) {
UIString text = UIString(L"欢迎您,%s").format(loginFrm.m_userName.c_str());
((Label*)sender)->SetText(text);
sender->Invalidate();
}
}
void MainFrm::UpSong()
{
int pos = this->FindLocalSong(this->nowSong);
pos--;
UIString hash;
if (pos < 0) {
hash = songLsit[songLsit.size() - 1].hash;
}
else {
hash = songLsit[pos].hash;
}
auto it = vlistLocal->FindSingleChild("FileHash", hash);
if (it) {
vlistLocal->GetScrollBar()->ScrollTo(it);
it->SendEvent(MouseEventArgs(Event::OnMouseDoubleClick));
}
}
void MainFrm::NextSong()
{
int pos = this->FindLocalSong(this->nowSong);
pos++;
UIString hash;
if (pos >= songLsit.size()) {
hash = songLsit[0].hash;
}
else {
hash = songLsit[pos].hash;
}
auto it = vlistLocal->FindSingleChild("FileHash", hash);
if (it) {
vlistLocal->GetScrollBar()->ScrollTo(it);
it->SendEvent(MouseEventArgs(Event::OnMouseDoubleClick));
}
}
void MainFrm::PlayMv(const UIString& mvhash, const UIString& songHash)
{
playType = 2;//当前正在播放视频
Song info;
global::GetMvInfo(mvhash, info);
RequestNewImage(info);
centerFrame->FindControl("mvView")->SendEvent(Event::OnMouseDown);
this->SetText(info.SongName);
((Label*)bottomFrame->FindControl("songName"))->SetText(info.SongName);
((Label*)bottomFrame->FindControl("songName"))->Invalidate();
UIString filehash = songHash;
UIString lrcData = global::GetSongLrc(filehash);
player.OpenUrl(info.url);
player.Play();
player.SetDuration(info.Duration / 1000);
lrcPanel.LoadLrc(lrcData);
deskTopWnd->LoadLrc(lrcData);
timer->Start();
}
void MainFrm::RequestNewImage(Song& info)
{
//重置头像和写真
if (headImg) {
delete headImg;
labelSinger->Style.ForeImage = NULL;
headImg = NULL;
labelSinger->Invalidate();
}
if (bkImg) {
delete bkImg;
mainLayout->Style.ForeImage = NULL;
deskTopWnd->GetLayout()->Style.BackImage = NULL;
bkImg = NULL;
mainLayout->Invalidate();
}
if (downloadTask) {
delete downloadTask;
}
downloadTask = new Task([this](UIString singname, UIString imgUrl) {
this->DownLoadImage(singname, imgUrl);
}, info.SingerName, info.imgUrl);
}
void MainFrm::TimerTick() {
Invoke([=]() {
if (player.GetState() == libvlc_state_t::libvlc_Playing) {
long long position = player.Position();
auto duration = player.Duration();
double rate = position / (duration * 1000.0);
int w = playerBar->Width() * rate;
lrcPanel.ChangePostion(position);
if (deskTopWnd->IsVisible()) {
deskTopWnd->ChangePostion(position);
}
UIString f1 = global::toTimeStr(position / 1000);
UIString f2 = global::toTimeStr(duration);
UIString fen = f1 + "/" + f2;
if (mediaCtl->GetPageIndex() != 1) {
mediaCtl->SetPageIndex(1);
mediaCtl->Invalidate();
}
labelTime->SetText(fen);
labelTime->Invalidate();
playerBar2->SetFixedWidth(w);
playerBar2->SetVisible(w > 0);
playerBar2->Invalidate();
}
else {
if (mediaCtl->GetPageIndex() != 0) {
mediaCtl->SetPageIndex(0);
mediaCtl->Invalidate();
}
}
});
}
void MainFrm::NextPage(float scrollPos) {
if (scrollPos >= 1.0f && global::nextPage) {
global::page++;
UIString keyword = editSearch->GetText();
std::vector<Song> songs = global::SearchSongs(keyword);
for (auto& it : songs) {
SearchItem* sit = new SearchItem(it);
vlistSearch->Add(sit);
}
if (!global::nextPage) {
Label* end = new Label;
end->SetFixedHeight(35);
end->Style.BackColor = Color(254, 249, 229);
end->SetText(L"已经没有更多数据");
vlistSearch->Add(end);
}
vlistSearch->Invalidate();
}
}
void MainFrm::OpenSongView() {
centerLeft->Style.BackColor = Color::Transparent;
tools->Style.Border.Bottom = 1;
tools->Style.Border.Color = Color(238, 238, 238);
vlistLocal->GetScrollBar()->Style.BackColor = Color(200, 200, 200, 50);
vlistLocal->GetScrollBar()->Style.ForeColor = Color(217, 217, 217);
vlistLocal->GetScrollBar()->ActiveStyle.ForeColor = Color(191, 191, 191);
centerLayout->Style.BackColor = Color::White;
centerLayout->Style.ForeColor = Color::Black;
Invalidate();
}
void MainFrm::OpenLrcView() {
centerLeft->Style.BackColor = Color(200, 200, 200, 100);
tools->Style.Border.Bottom = 1;
tools->Style.Border.Color = Color(238, 238, 238);
vlistLocal->GetScrollBar()->Style.BackColor = Color(200, 200, 200, 50);
vlistLocal->GetScrollBar()->Style.ForeColor = Color(255, 255, 255, 100);
vlistLocal->GetScrollBar()->ActiveStyle.ForeColor = Color(255, 255, 255, 150);
centerLayout->Style.BackColor = Color::Transparent;
centerLayout->Style.ForeColor = Color::White;
Invalidate();
}

81
demo/kugou/MainFrm.h Normal file
View File

@@ -0,0 +1,81 @@
#pragma once
#include "global.h"
#include "widgets.h"
#include "vlcPlayer.h"
#include "lrcPanel.h"
#include "desktopLrcFrm.h"
//using Form = Window; //经典win32窗口样式
//using Form = BorderlessWindow; //无边框窗口 带windows吸附效果
using Form = LayeredWindow; //分层窗口 支持异形 圆角
class MainFrm :
public Form
{
private:
//标题Frame
IFrame* titleFrame;
//窗口中间部分Frame
IFrame* centerFrame;
//窗口底部Frame
IFrame* bottomFrame;
std::vector<Song> songLsit;
//no new 不需要释放
NotifyIcon ntfi;
VlcPlayer player;
VListView* vlistLocal = NULL, * vlistSearch = NULL;
TextBox* editSearch;
LrcPanel lrcPanel;
Label* labelTime, * labelSinger;
TabLayout* tabCtrl, * mediaCtl;
Control* mainLayout, * centerLayout, * centerLeft, * tools, * playerBar, * playerBar2;
CheckBox* labelDeskLrc;
//need new 需要释放
Timer* timer = NULL;
ConfigIni* listFile = NULL;
Image* bkImg = NULL, * headImg = NULL;
Task* downloadTask = NULL;
DesktopLrcFrm* deskTopWnd;
UIString nowSong;
//1:歌曲 2:视频
int playType = 0;
protected:
virtual void OnClose(bool& bClose) override;
virtual void OnKeyDown(WPARAM wparam, LPARAM lParam)override;
virtual void OnNotify(Control* sender, EventArgs& args)override;
virtual void OnPaint(PaintEventArgs& args)override;
private:
//打开/关闭桌面歌词
void OpenDesktopLrc();
//打开登录窗口
void OpenLoginFrm(ezui::Control* sender);
//上一首
void UpSong();
//下一首
void NextSong();
//播放mv
void PlayMv(const UIString& mvhash, const UIString& songHash);
//请求新的头像和写真
void RequestNewImage(Song& info);
//打开歌曲界面
void OpenSongView();
//计时器处理的函数
void TimerTick();
//打开歌词滚动界面
void OpenLrcView();
//初始化窗口
void InitForm();
//下载歌手头像和写真
void DownLoadImage(UIString SingerName, UIString headImageUrl);
//播放歌曲
bool PlaySong(const UIString& hash, Song& info);
//寻找左侧列表中的歌曲
size_t FindLocalSong(const UIString& hash);
//下一页
void NextPage(float scrollPos);
public:
MainFrm();
virtual ~MainFrm();
};

159
demo/kugou/VlcPlayer.cpp Normal file
View File

@@ -0,0 +1,159 @@
#include "vlcPlayer.h"
void* lock_cb(void* opaque, void** planes)
{
VlcPlayer* vp = (VlcPlayer*)opaque;
vp->mtx.Lock();
*planes = vp->BuffBitmap->GetPixel(); /*tell VLC to put decoded data to this buffer*/
return NULL;
}
/*##get the argb picture AND save to file*/
void unlock_cb(void* opaque, void* picture, void* const* planes)
{
VlcPlayer* vp = (VlcPlayer*)opaque;
vp->mtx.UnLock();
}
void display_cb(void* opaque, void* picture)
{
VlcPlayer* vp = (VlcPlayer*)opaque;
// 通知主线程刷新
BeginInvoke([=] {
if (vp->PlayingCallback) {
vp->PlayingCallback(vp->BuffBitmap);
}
vp->Invalidate();
});
}
void cleanup_cb(void* opaque)
{
VlcPlayer* vp = (VlcPlayer*)opaque;
}
unsigned setup_cb(void** opaque, char* chroma, unsigned* width, unsigned* height, unsigned* pitches, unsigned* lines)
{
int w = *width;
int h = *height;
VlcPlayer* vp = (VlcPlayer*)*opaque;
if (vp->BuffBitmap != NULL) {
delete vp->BuffBitmap;
}
vp->BuffBitmap = new Bitmap(w, h);
memcpy(chroma, "RV32", 4);
*pitches = w * 4;
*lines = h;
return 1;
}
VlcPlayer::VlcPlayer()
{
m_vlc = libvlc_new(NULL, NULL);
m_vlcplayer = libvlc_media_player_new(m_vlc);
libvlc_video_set_callbacks(m_vlcplayer, lock_cb, unlock_cb, display_cb, this);
libvlc_video_set_format_callbacks(m_vlcplayer, setup_cb, cleanup_cb);
}
VlcPlayer::~VlcPlayer()
{
Stop();
if (m_task) {
delete m_task;
}
if (m_vlcplayer) {
libvlc_media_player_release(m_vlcplayer);
}
libvlc_release(m_vlc);
if (BuffBitmap) {
delete BuffBitmap;
}
}
void VlcPlayer::OnBackgroundPaint(PaintEventArgs& args) {
__super::OnBackgroundPaint(args);
if (BuffBitmap) {
Image img(BuffBitmap);
img.SizeMode = ImageSizeMode::Fit;
//img.Offset = Rect(500,50,200,200);
args.Graphics.DrawImage(&img, GetRect());
}
}
void VlcPlayer::SetConfig()
{
}
void VlcPlayer::OpenPath(const UIString& file_)
{
if (m_task && m_task->IsStopped()) {
delete m_task;
m_task = NULL;
}
else if (m_task && !m_task->IsStopped()) {
//上一次播放请求尚未完成
return;
}
m_task = new Task([&, file_]() {
#ifdef _DEBUG
OutputDebugStringA("-----------------------------------------------------------stop in..\n");
#endif // _DEBUG
Stop();
//回到主线程进行处理
Invoke([&]() {
UIString file = file_.replace("/", "\\");
libvlc_media_t* pmedia = libvlc_media_new_path(m_vlc, file.c_str());
libvlc_media_parse(pmedia);//
libvlc_media_player_set_media(m_vlcplayer, pmedia);
m_duration = libvlc_media_get_duration(pmedia);//
libvlc_media_player_play(m_vlcplayer);
libvlc_media_release(pmedia);
});
#ifdef _DEBUG
OutputDebugStringA("-----------------------------------------------------------stop out..\n");
#endif // _DEBUG
});
}
void VlcPlayer::OpenUrl(const UIString& url)
{
Stop();
libvlc_media_t* pmedia = libvlc_media_new_location(m_vlc, url.c_str());
libvlc_media_parse(pmedia);//
libvlc_media_player_set_media(m_vlcplayer, pmedia);
m_duration = libvlc_media_get_duration(pmedia);//
libvlc_media_player_play(m_vlcplayer);
libvlc_media_release(pmedia);
}
void VlcPlayer::Play()
{
libvlc_media_player_play(m_vlcplayer);
}
void VlcPlayer::SetVolume(int volume) {
libvlc_audio_set_volume(m_vlcplayer, volume);
}
void VlcPlayer::Pause()
{
if (libvlc_media_player_can_pause(m_vlcplayer))
{
libvlc_media_player_pause(m_vlcplayer);
}
}
void VlcPlayer::Stop()
{
libvlc_media_player_stop(m_vlcplayer);
}
long long VlcPlayer::Duration() {
return m_duration;
}
void VlcPlayer::SetDuration(int dur)
{
m_duration = dur;
}
long long VlcPlayer::Position() {
libvlc_time_t play_time = libvlc_media_player_get_time(m_vlcplayer);
return play_time;
}
void VlcPlayer::SetPosition(float f_pos)
{
libvlc_media_player_set_position(m_vlcplayer, f_pos);
}
libvlc_state_t VlcPlayer::GetState() {
return libvlc_media_player_get_state(m_vlcplayer);
}

47
demo/kugou/VlcPlayer.h Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
#include "EzUI/Control.h"
#include "EzUI/BorderlessWindow.h"
#include "EzUI/Label.h"
#include "EzUI/Task.h"
#include <mutex>
#ifdef _WIN32
#include <basetsd.h>
typedef SSIZE_T ssize_t;
#endif
#include "vlc/vlc.h"
#pragma comment(lib,"libvlc.lib")
#pragma comment(lib,"libvlccore.lib")
//封装用于播放视频的控件
using namespace ezui;
class VlcPlayer :public Control
{
private:
libvlc_instance_t* m_vlc = NULL;
libvlc_media_player_t* m_vlcplayer = NULL;
libvlc_time_t m_duration = 0;
Task * m_task = NULL;
public:
Mutex mtx;
unsigned int IMG_WIDTH = 0;
unsigned int IMG_HEIGHT = 0;
Bitmap* BuffBitmap = NULL;
std::function<void(Bitmap* bitmap)> PlayingCallback;
protected:
void SetConfig();
virtual void OnBackgroundPaint(PaintEventArgs& args) override;
public:
VlcPlayer();
virtual ~VlcPlayer();
void OpenPath(const UIString& file);
void OpenUrl(const UIString& url);
void Play();
void SetVolume(int volume);
void Pause();
void Stop();
long long Duration();
void SetDuration(int dur);
long long Position();
void SetPosition(float f_pos);
libvlc_state_t GetState();
};

272
demo/kugou/base64.cpp Normal file
View File

@@ -0,0 +1,272 @@
/*
base64.cpp and base64.h
base64 encoding and decoding with C++.
More information at
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
Version: 2.rc.08 (release candidate)
Copyright (C) 2004-2017, 2020, 2021 Ren?? Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
Ren?? Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
#include "base64.h"
#include <algorithm>
#include <stdexcept>
//
// Depending on the url parameter in base64_chars, one of
// two sets of base64 characters needs to be chosen.
// They differ in their last two characters.
//
static const char* base64_chars[2] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"+/",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"-_" };
static unsigned int pos_of_char(const unsigned char chr) {
//
// Return the position of chr within base64_encode()
//
if (chr >= 'A' && chr <= 'Z') return chr - 'A';
else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1;
else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_'
else
//
// 2020-10-23: Throw std::exception rather than const char*
//(Pablo Martin-Gomez, https://github.com/Bouska)
//
throw std::runtime_error("Input is not valid base64-encoded data.");
}
static std::string insert_linebreaks(std::string str, size_t distance) {
//
// Provided by https://github.com/JomaCorpFX, adapted by me.
//
if (!str.length()) {
return "";
}
size_t pos = distance;
while (pos < str.size()) {
str.insert(pos, "\n");
pos += distance + 1;
}
return str;
}
template <typename String, unsigned int line_length>
static std::string encode_with_line_breaks(String s) {
return insert_linebreaks(base64_encode(s, false), line_length);
}
template <typename String>
static std::string encode_pem(String s) {
return encode_with_line_breaks<String, 64>(s);
}
template <typename String>
static std::string encode_mime(String s) {
return encode_with_line_breaks<String, 76>(s);
}
template <typename String>
static std::string encode(String s, bool url) {
return base64_encode(reinterpret_cast<const unsigned char*>(s.data()), s.length(), url);
}
std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) {
size_t len_encoded = (in_len + 2) / 3 * 4;
unsigned char trailing_char = url ? '.' : '=';
//
// Choose set of base64 characters. They differ
// for the last two positions, depending on the url
// parameter.
// A bool (as is the parameter url) is guaranteed
// to evaluate to either 0 or 1 in C++ therefore,
// the correct character set is chosen by subscripting
// base64_chars with url.
//
const char* base64_chars_ = base64_chars[url];
std::string ret;
ret.reserve(len_encoded);
unsigned int pos = 0;
while (pos < in_len) {
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);
if (pos + 1 < in_len) {
ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);
if (pos + 2 < in_len) {
ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
ret.push_back(base64_chars_[bytes_to_encode[pos + 2] & 0x3f]);
}
else {
ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
ret.push_back(trailing_char);
}
}
else {
ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
ret.push_back(trailing_char);
ret.push_back(trailing_char);
}
pos += 3;
}
return ret;
}
template <typename String>
static std::string decode(String encoded_string, bool remove_linebreaks) {
//
// decode(??) is templated so that it can be used with String = const std::string&
// or std::string_view (requires at least C++17)
//
if (encoded_string.empty()) return std::string();
if (remove_linebreaks) {
std::string copy(encoded_string);
copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end());
return base64_decode(copy, false);
}
size_t length_of_string = encoded_string.length();
size_t pos = 0;
//
// The approximate length (bytes) of the decoded string might be one or
// two bytes smaller, depending on the amount of trailing equal signs
// in the encoded string. This approximation is needed to reserve
// enough space in the string to be returned.
//
size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
std::string ret;
ret.reserve(approx_length_of_decoded_string);
while (pos < length_of_string) {
//
// Iterate over encoded input string in chunks. The size of all
// chunks except the last one is 4 bytes.
//
// The last chunk might be padded with equal signs or dots
// in order to make it 4 bytes in size as well, but this
// is not required as per RFC 2045.
//
// All chunks except the last one produce three output bytes.
//
// The last chunk produces at least one and up to three bytes.
//
size_t pos_of_char_1 = pos_of_char(encoded_string[pos + 1]);
//
// Emit the first output byte that is produced in each chunk:
//
ret.push_back(static_cast<std::string::value_type>(((pos_of_char(encoded_string[pos + 0])) << 2) + ((pos_of_char_1 & 0x30) >> 4)));
if ((pos + 2 < length_of_string) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045)
encoded_string[pos + 2] != '=' &&
encoded_string[pos + 2] != '.' // accept URL-safe base 64 strings, too, so check for '.' also.
)
{
//
// Emit a chunk's second byte (which might not be produced in the last chunk).
//
unsigned int pos_of_char_2 = pos_of_char(encoded_string[pos + 2]);
ret.push_back(static_cast<std::string::value_type>(((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2)));
if ((pos + 3 < length_of_string) &&
encoded_string[pos + 3] != '=' &&
encoded_string[pos + 3] != '.'
)
{
//
// Emit a chunk's third byte (which might not be produced in the last chunk).
//
ret.push_back(static_cast<std::string::value_type>(((pos_of_char_2 & 0x03) << 6) + pos_of_char(encoded_string[pos + 3])));
}
}
pos += 4;
}
return ret;
}
std::string base64_decode(std::string const& s, bool remove_linebreaks) {
return decode(s, remove_linebreaks);
}
std::string base64_encode(std::string const& s, bool url) {
return encode(s, url);
}
std::string base64_encode_pem(std::string const& s) {
return encode_pem(s);
}
std::string base64_encode_mime(std::string const& s) {
return encode_mime(s);
}
#if __cplusplus >= 201703L
//
// Interface with std::string_view rather than const std::string&
// Requires C++17
// Provided by Yannic Bonenberger (https://github.com/Yannic)
//
std::string base64_encode(std::string_view s, bool url) {
return encode(s, url);
}
std::string base64_encode_pem(std::string_view s) {
return encode_pem(s);
}
std::string base64_encode_mime(std::string_view s) {
return encode_mime(s);
}
std::string base64_decode(std::string_view s, bool remove_linebreaks) {
return decode(s, remove_linebreaks);
}
#endif // __cplusplus >= 201703L

35
demo/kugou/base64.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
//
// base64 encoding and decoding with C++.
// Version: 2.rc.08 (release candidate)
//
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#include <string>
#if __cplusplus >= 201703L
#include <string_view>
#endif // __cplusplus >= 201703L
std::string base64_encode(std::string const& s, bool url = false);
std::string base64_encode_pem(std::string const& s);
std::string base64_encode_mime(std::string const& s);
std::string base64_decode(std::string const& s, bool remove_linebreaks = false);
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
#if __cplusplus >= 201703L
//
// Interface with std::string_view rather than const std::string&
// Requires C++17
// Provided by Yannic Bonenberger (https://github.com/Yannic)
//
std::string base64_encode(std::string_view s, bool url = false);
std::string base64_encode_pem(std::string_view s);
std::string base64_encode_mime(std::string_view s);
std::string base64_decode(std::string_view s, bool remove_linebreaks = false);
#endif // __cplusplus >= 201703L
#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */

25
demo/kugou/extractx64.bat Normal file
View File

@@ -0,0 +1,25 @@
@echo off
setlocal
set OUTDIR=%1
set MARKER_FILE=%OUTDIR%\dll_marker.txt
set SCRIPT_DIR=%~dp0
if exist "%MARKER_FILE%" (
echo DLL already extracted. Skipping.
goto :EOF
)
echo Extracting dll.zip to %OUTDIR%...
"%SCRIPT_DIR%7z.exe" x "%SCRIPT_DIR%dllx64.zip" -o"%OUTDIR%" -aoa -y
if errorlevel 1 (
echo Extraction failed!
exit /b 1
)
echo extracted > "%MARKER_FILE%"
echo Extraction complete.
endlocal

25
demo/kugou/extractx86.bat Normal file
View File

@@ -0,0 +1,25 @@
@echo off
setlocal
set OUTDIR=%1
set MARKER_FILE=%OUTDIR%\dll_marker.txt
set SCRIPT_DIR=%~dp0
if exist "%MARKER_FILE%" (
echo DLL already extracted. Skipping.
goto :EOF
)
echo Extracting dll.zip to %OUTDIR%...
"%SCRIPT_DIR%7z.exe" x "%SCRIPT_DIR%dllx86.zip" -o"%OUTDIR%" -aoa -y
if errorlevel 1 (
echo Extraction failed!
exit /b 1
)
echo extracted > "%MARKER_FILE%"
echo Extraction complete.
endlocal

156
demo/kugou/global.cpp Normal file
View File

@@ -0,0 +1,156 @@
#include "global.h"
namespace global {
int pageSize = 50;
int page = 1;
bool nextPage = true;
UIString toTimeStr(long dur) {
UIString fen = std::to_string(dur / 60);
if (fen.size() <= 1) fen = "0" + fen;
UIString yu = std::to_string(dur % 60);
if (yu.size() <= 1) yu = "0" + yu;
return fen + ":" + yu;
}
int HttpGet(const UIString& url, UIString& resp) {
UIString newUrl = url;
size_t pos1 = newUrl.find("://");
UIString host;
if (pos1 != UIString::npos) {
host = newUrl.substr(pos1 + 3);
pos1 = host.find("/");
if (pos1 != UIString::npos) {
host = host.substr(0, pos1);
}
}
WebClient wc;
wc.AddHeader("Accept", " */*");
wc.AddHeader("Accept-Language", " en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.2");
wc.AddHeader("User-Agent", " Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
wc.AddHeader("Host", host);
wc.AddHeader("Connection", " Keep-Alive");
wc.AddHeader("Cache-Control", " no-cache");
UIString userid = "1581500898";//
newUrl += "&userid=" + userid;
return wc.HttpGet(newUrl, &resp);
}
std::vector<Song> SearchSongs(const UIString& keyword) {
char buf[999]{ 0 };
UIString resp;
sprintf(buf, "https://songsearch.kugou.com/song_search_v2?platform=WebFilter&pagesize=%d&page=%d&keyword=%s", pageSize, page, Util::UrlEncode(keyword).c_str());
HttpGet(buf, resp);
JsonValue json(resp);
int total = json["data"]["total"].asInt();
int pageCount = total * 1.0 / pageSize + 0.9;
if (page >= pageCount) {
nextPage = false;
}
std::vector<Song> songs;
for (auto&& it : json["data"]["lists"]) {
Song s;
s.hash = it["FileHash"].asString();
s.Duration = it["Duration"].asInt();
s.MvHash = it["MvHash"].asString();
s.SongName = it["FileName"].asString();
s.SingerName = it["SingerName"].asString();
s.AlbumID = it["AlbumID"].asString();
s.AlbumName = it["AlbumName"].asString();
s.QualityLevel = it["QualityLevel"].asInt();
songs.push_back(s);
}
return songs;
}
UIString GetSongLrc(const UIString& hash, const UIString& AlbumID) {
UIString url = "http://krcs.kugou.com/search?ver=1&man=yes&client=mobi&keyword=&duration=&hash=" + hash + "&album_audio_id=" + AlbumID;
UIString resp;
HttpGet(url, resp);
JsonValue json(resp);
if (json["status"].asInt() != 200 || json["candidates"].size() == 0) {
return UIString(L"[00:00.00]无歌词");
}
UIString id = (*json["candidates"].begin())["id"].asString();
UIString accesskey = (*json["candidates"].begin())["accesskey"].asString();
resp.clear();
url = "http://lyrics.kugou.com/download?ver=1&client=pc&id=" + id + "&accesskey=" + accesskey + "&fmt=lrc&charset=utf8";
HttpGet(url, resp);
JsonValue json2(resp);
UIString base64Text = json2["content"].asString();
base64Text = base64_decode(base64Text);
return base64Text;
}
bool GetSongInfo(const UIString& hash, UIString& errorInfo, Song& info)
{
UIString url = "http://m.kugou.com/app/i/getSongInfo.php?hash={hash}&cmd=playInfo";
url = url.replace("{hash}", hash);
UIString resp;
global::HttpGet(url, resp);
auto w = resp.unicode();
JsonValue json(resp);
if (json["errcode"].asInt() != 0) {
errorInfo = UIString(json["error"].asString());
return false;
}
int dur = json["timeLength"].asInt();
UIString playUrl = json["url"].asCString();
UIString SingerName = json["author_name"].asCString();
info.fileName = json["fileName"].asString();
info.Duration = dur;
info.url = playUrl;
info.SingerName = SingerName;
info.imgUrl = json["imgUrl"].asCString();
if (playUrl.empty()) {
errorInfo = L"歌曲收费";
return false;
}
return true;
}
bool GetMvInfo(const UIString& mvhash, Song& info) {
UIString resp;
WebClient wc;
wc.HttpGet("http://m.kugou.com/app/i/mv.php?cmd=100&hash=" + mvhash + "&ismp3=1&ext=mp4", &resp);
auto w = resp.unicode();
JsonValue json(resp);
std::vector<UIString> urls;
urls.reserve(6);
for (auto& it : json["mvdata"]) {
UIString url = it["downurl"].asString();
if (!url.empty()) {
urls.push_back(url);
}
}
info.imgUrl = json["mvicon"].asString();
info.SingerName = json["singer"].asString();
info.Duration = json["timelength"].asInt();
info.SongName = json["songname"].asString();
info.url = urls[urls.size() - 1];
return true;
}
UIString GetSingerBackground(const UIString& SingerName) {
UIString imageUrl = "https://artistpicserver.kuwo.cn/pic.web?type=big_artist_pic&pictype=url&content=list&&id=0&name=" + Util::UrlEncode(SingerName) + "&from=pc&json=1&version=1&width=" + std::to_string(1920) + "&height=" + std::to_string(1080);
UIString resp;
WebClient wc;
wc.HttpGet(imageUrl, &resp, 5);
JsonValue json(resp);
UIString bkurl;
//使用最清晰的图片
if (bkurl.empty()) {
for (auto&& it : json["array"]) {
if (!it["bkurl"].isNull()) {
bkurl = it["bkurl"].asString();
break;
}
}
}
for (auto&& it : json["array"]) {
if (!it["wpurl"].isNull()) {
bkurl = it["wpurl"].asString();
break;
}
}
return bkurl;
}
}

84
demo/kugou/global.h Normal file
View File

@@ -0,0 +1,84 @@
#pragma once
#include "EzUI/EzUI.h"
#include "EzUI/TextBox.h"
#include "EzUI/BorderlessWindow.h"
#include "EzUI/Application.h"
#include "EzUI/UIManager.h"
#include "EzUI/HLayout.h"
#include "EzUI/Label.h"
#include "EzUI/VListView.h"
#include "EzUI/VLayout.h"
#include "EzUI/Button.h"
#include "EzUI/TabLayout.h"
#include "EzUI/NotifyIcon.h"
#include "EzUI/LayeredWindow.h"
#include "EzUI/Task.h"
#include "EzUI/UISelector.h"
#include "EzUI/Animation.h"
#include "EzUI/IFrame.h"
#include "WebClient.h"
#include "JsonValue.h"
#include "Util.h"
#include "base64.h"
#include "ConfigIni.h"
#ifdef _DEBUG
#pragma comment(lib,"Debug/Common.lib")
#else
#pragma comment(lib,"Release/Common.lib")
#endif
#include <random>
class Random {
std::mt19937 randomer;
public:
Random() :randomer(std::random_device()()) {
}
int Next(int lower, int upper) {
std::uniform_int_distribution<int> distribution(lower, upper);
return distribution(randomer);
}
float Next(float lower, float upper) {
std::uniform_real_distribution<float> distribution(lower, upper);
return distribution(randomer);
}
};
using namespace ezui;
struct Song {
UIString hash;//歌曲哈希值
UIString SongName;//歌曲名称
UIString SingerName;//歌手名称
UIString MvHash;//mv哈希值
int Duration;//音乐时长 单位:秒
UIString AlbumID;//
UIString AlbumName;//
int QualityLevel;//歌曲热度
UIString url;
UIString imgUrl;
UIString fileName;
};
namespace global {
extern int pageSize;
extern int page;
extern bool nextPage;
//歌曲长度转字符串显示
extern UIString toTimeStr(long dur);
//http对酷狗api的请求
extern int HttpGet(const UIString& url, UIString& resp);
//根据关键字进行歌曲搜索
extern std::vector<Song> SearchSongs(const UIString& keyword);
//使用歌曲的AlbumId寻找查找对应的歌词
extern UIString GetSongLrc(const UIString& hash, const UIString& AlbumID = "");
//获取歌曲信息
extern bool GetSongInfo(const UIString& hash, UIString& errorInfo, Song& info);
//获取mv信息
extern bool GetMvInfo(const UIString& mvhash, Song& info);
//获取歌手写真(酷我的接口)
extern UIString GetSingerBackground(const UIString& SingerName);
};

View File

@@ -0,0 +1,89 @@
//#include "os.h"
//#include "WebClient.h"
//
//inline void Loop() {
// /*Socket s;
// s.Bind("0.0.0.0", 80);
// bool b = s.Listen();
// for (; b;) {
// Socket client = s.Accep();
// printf("连接进入 %s %d\n", client.Address.c_str(), client.Port);
//
// std::string resp;
// size_t pos = -1;
// size_t length = 0;
// std::string body;
// bool end = false;
// for (;;) {
// char buf[128]{ 0 };
// int len = client.Receive(buf, sizeof(buf));
// if (len == -1 || len == 0) {
// client.Close();
// printf("客户端断开 %s %d\n", client.Address.c_str(), client.Port);
// break;
// }
// if (!end) {
// resp.append(buf, len);
// }
// else {
// body.append(buf, len);
// }
// if (!end && (pos = resp.find("\r\n\r\n")) != -1) {
// body.append(resp.c_str() + pos + 4, resp.size() - pos - 4);
// end = true;
// auto pos2 = resp.find("Content-Length:");
// if (pos2 != -1) {
// std::string len;
// for (size_t i = pos2 + 7; i < resp.size(); i++)
// {
// if (resp.at(i) >= '0' && resp.at(i) <= '9') {
// len += resp.at(i);
// }
// else {
// length = std::atoi(len.c_str());
// break;
// }
// }
// }
// }
// if (end && body.size() >= length) {
// client.Close();
// printf("服务端断开 %s %d\n", client.Address.c_str(), client.Port);
// break;
// }
// }
// printf("%s\n", body.c_str());
// }*/
//}
//
//int main(int argc, char* argv[])
//{
//
// StopWatch sw;
// for (size_t i = 0; i < 15; i++)
// {
// WebClient wc;
// std::string resp;
// std::string key = "var items=";
// size_t pos1 = size_t(-1), pos2 = size_t(-1);
// wc.CallBack = ([=, &pos1, &pos2](char* contents, size_t size, size_t nmemb, void* respone)->size_t {
// size_t count = size * nmemb;
// std::string* str = (std::string*)respone;
// (*str).append(contents, count);
// if (pos1 == size_t(-1)) {
// pos1 = str->find(key);
// }
// if (pos1 != size_t(-1)) {
// pos2 = str->find("}];", key.size() + pos1);
// if (pos2 != size_t(-1)) {
// *str = str->substr(pos1 + key.size(), pos2 - (pos1 + key.size())) + "}]";
// return 23;//终止
// }
// }
// return count;
// });
// wc.HttpGet("http://163.197.44.13/Web/reserve/materialx?languages=1", resp, 999);
// }
// auto time = sw.ElapsedMilliseconds();
// return 0;
//}

View File

@@ -0,0 +1,30 @@
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <fstream>
#include <vector>
#include <sstream>
#include <mutex>
#include <memory>
#include <map>
#include <io.h>
#include <Windows.h>
#include <winuser.h>
#include <assert.h>
#pragma warning(disable:4018)
#pragma warning(disable:4244)
#pragma warning(disable:4551)
#pragma warning(disable:4293)
#pragma warning(disable:4996)
#pragma warning(disable:4099)
#pragma warning(disable:4800)
#pragma warning(disable:4101)
#pragma warning(disable:4267)
#include "Text.h"
#include "FileSystem.h"
#include "Time.hpp"//防止和系统的time.h重命名
#include "WinTool.h"

View File

@@ -0,0 +1,38 @@
#pragma once
#include <Windows.h>
#include "Text.h"
class ConfigIni {
protected:
size_t buffSize;
Text::String filename;
Text::String section;
DWORD GetValue(const Text::String& key, const Text::String& filename, Text::String& outResult);
bool SetValue(const Text::String& key, const Text::String& Value, const Text::String& absoluteFilename);
private:
ConfigIni() = delete;
ConfigIni(const ConfigIni&) = delete;
public:
//FileName //一定要绝对路径
ConfigIni(const Text::String& filename, const Text::String& defaultSection = "setting", size_t buffSize = 1024);
//设置一个名称
void SetSection(const Text::String& sectionName);
//读取ini中的字符
Text::String ReadString(const Text::String& key, const Text::String& defaultValue = "");
//读取ini中的数字
float ReadFloat(const Text::String& key, float defaultValue = 0);
//读取ini中的int数字
int ReadInt(const Text::String& key, int defaultValue = 0);
//读取bool类型值
bool ReadBool(const Text::String& key, bool defaultValue = false);
//写入ini
bool WriteString(const Text::String& key, const Text::String& value);
bool WriteFloat(const Text::String& key, float value);
bool WriteInt(const Text::String& key, int value);
bool WriteBool(const Text::String& key, bool defaultValue);
//获取所有的Section
std::vector<Text::String> GetSections();
//删除所有的Section
void DeleteSection(const Text::String& section);
};

View File

@@ -0,0 +1,147 @@
#pragma once
#include <functional>
#include <fstream>
#include <Windows.h>
#include "Text.h"
namespace FileSystem {
class FileInfo;
enum FileType :int
{
File = 2,
Directory = 4
};
//重载枚举的 | 运算符
inline FileType operator|(FileType left, FileType right)
{
return static_cast<FileType>(static_cast<int>(left) | static_cast<int>(right));
}
};
namespace File {
typedef std::string FileStream;
//创建文件
extern bool Create(const Text::String& filename);
//删除文件
extern bool Delete(const Text::String& filename);
//判断文件是否存在
extern bool Exists(const Text::String& filename);
//文件移动或者改名
extern bool Move(const Text::String& oldname, const Text::String& newname);
//读取文件并out返回
extern bool ReadFile(const Text::String& filename, FileStream* fileStream);
//写入文件
extern bool WriteFile(const FileStream* fileStream, const Text::String& filename);
//写入文件
extern bool WriteFile(const char* fileStream, size_t count, const Text::String& filename);
//拷贝文件
extern bool Copy(const Text::String& filename, const Text::String& des_filename, bool overwrite = true);
//获取文件字节大小
extern ULONGLONG GetFileSize(const Text::String& fileName);
};
namespace Directory {
//创建目录
extern bool Create(const Text::String& path);
//拷贝目录所有文件到目标目录
extern bool Copy(const Text::String& srcPath, const Text::String& desPath, bool overwrite = true);
//移动目录到新位置
extern bool Move(const Text::String& oldname, const Text::String& newname);
//删除路径 如果存在子文件夹或者文件 将会递归删除
extern bool Delete(const Text::String& directoryName);
//通配符查找文件夹/文件
extern size_t Find(const Text::String& path, std::vector<FileSystem::FileInfo>& result, const Text::String& pattern = "*.*", bool loopSubDir = false, FileSystem::FileType fileType = FileSystem::FileType::Directory | FileSystem::FileType::File);
//检查路径是否存在
extern bool Exists(const Text::String& path);
};
namespace Path {
//格式化路径为统一反斜杠
extern Text::String Format(const Text::String& path);
//判断路径是不是相同
extern bool Equal(const Text::String& path1, const Text::String& path2);
//获取文件名称(文件名称)
extern Text::String GetFileNameWithoutExtension(const Text::String& _filename);
//获取文件目录名称(所在目录)
extern Text::String GetDirectoryName(const Text::String& _filename);
//获取文件名称+后缀
extern Text::String GetFileName(const Text::String& _filename);
//获取用户桌面路径
extern Text::String UserDesktop(bool publicUser = true);
//获取开始菜单路径
extern Text::String StartPrograms(bool publicUser = true);
//获取文件后缀名(后缀名)
extern Text::String GetExtension(const Text::String& _filename);
//获取进程所在绝对路径目录
extern Text::String StartPath();
//获取进程所在绝对路径包含文件名称
extern const Text::String& StartFileName();
#undef GetTempPath
/// <summary>
/// 获取应当前windows用户的临时目录
/// </summary>
/// <returns></returns>
extern Text::String GetTempPath();
/// <summary>
/// 获取应用程序的临时目录
/// </summary>
/// <returns></returns>
extern Text::String GetAppTempPath(const Text::String& appName = "");
/// <summary>
/// 获取应用程序数据存储目录 C:/Users/%s/AppData/Local/%s
/// </summary>
/// <returns></returns>
extern Text::String GetAppDataPath(const Text::String& appName = "");
};
namespace FileSystem {
class FileInfo
{
private:
std::ifstream* ifs = NULL;
ULONGLONG StreamPos = 0;
public:
DWORD dwFileAttributes;
const Text::String FileName;
bool IsFile() const {
return !(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
}
bool IsReadOnly() const {
return dwFileAttributes & FILE_ATTRIBUTE_READONLY;
}
const ULONGLONG FileSize = 0;
FileInfo() {}
FileInfo(const Text::String& fileName) {
if (File::Exists(fileName)) {
(Text::String)FileName = fileName;
//获取大小
ifs = new std::ifstream(fileName.unicode(), std::ios::binary);
ifs->seekg(0, std::ios::end);
(ULONGLONG&)FileSize = ifs->tellg();
}
}
size_t Read(char* _buf_, size_t _rdCount = 255) {
size_t rdbufCount = _rdCount;
if (StreamPos + _rdCount >= FileSize) {
rdbufCount = FileSize - StreamPos;
}
if (rdbufCount == 0) {
return 0;
}
if (ifs == NULL) {
ifs = new std::ifstream(FileName.unicode(), std::ios::binary);
}
ifs->seekg(StreamPos);
ifs->read(_buf_, rdbufCount);
StreamPos += rdbufCount;
return rdbufCount;
}
void Close() {
ifs->close();
}
~FileInfo() {
if (ifs) {
delete ifs;
}
}
};
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include <string>
#include <Windows.h>
#define USEJSONCPP 1 //是否使用JsonCpp库
#if USEJSONCPP
#include <json/json.h>
#ifdef _WIN64
#ifdef _DEBUG
#pragma comment (lib,"X64/json_libd.lib")
#else
#pragma comment (lib,"X64/json_lib.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment (lib,"json_libd.lib")
#else
#pragma comment (lib,"json_lib.lib")
#endif
#endif
struct JsonValue :public Json::Value {
private:
bool b = false;
Json::Reader rd;
public:
bool IsJson();
//JObject(const Json::Value& right);
JsonValue& operator = (const Json::Value& other);
JsonValue(const std::string& jsonStr);
};
#endif

View File

@@ -0,0 +1,37 @@
#pragma once
#include <iostream>
#include "FileSystem.h"
#include "Time.hpp"
namespace Log {
//是否启用日志
extern bool Enable;
extern bool WriteFile;
extern void WriteLog(const Text::String& log);
template<typename ...T>
/// <summary>
/// 打印utf8的字符
/// </summary>
/// <typeparam name="...T"></typeparam>
/// <param name="formatStr"></param>
/// <param name="...args"></param>
inline Text::String Info(const Text::String& formatStr, const T &...args) {
if (!Enable)return "";
// 计算格式化后的字符串所需的内存大小
int bufSize = ::snprintf(nullptr, 0, formatStr.c_str(), args...) + 2; // +1是为了换行符和结束符 \n '\0'
char* buf = new char[bufSize];
auto count = ::sprintf_s(buf, bufSize, formatStr.c_str(), std::forward<const T&>(args)...);
buf[count] = '\n';
buf[count + 1] = 0;
Text::String info(buf);
info = Time::Now().ToString("HH:mm:ss ") + info;
delete[] buf;
//转为本地可识别的编码
auto ansi = info.ansi();
std::cout << ansi;
OutputDebugStringA(ansi.c_str());
WriteLog(info);
return info;
}
};

View File

@@ -0,0 +1,46 @@
#pragma once
#include <unordered_map>
template<class T1, class T2>
class Map :protected std::unordered_map<T1, T2> {
using __base = std::unordered_map<T1, T2>;
T2 defaultValue = T2();//当获取不到value的时候返回的默认值
public:
typename __base::iterator begin() {
return __base::begin();
}
typename __base::iterator end() {
return __base::end();
}
bool insert(const T1& key, const T2& value) {
auto itor = __base::insert(std::pair<T1, T2>(key, value));
return itor.second;
}
bool empty() {
return __base::empty();
}
size_t size() {
return __base::size();
}
const T2& operator[](const T1& key) const {
auto itor = __base::find(key);
if (itor != __base::end()) {
return itor->second;
}
return defaultValue;
}
typename __base::iterator find(const T1& key) {
return __base::find(key);
}
void erase(const typename __base::iterator& itor) {
__base::erase(itor);
}
bool erase(const T1& key) {
auto itor = __base::find(key);
if (itor != __base::end()) {
__base::erase(itor);
return true;
}
return false;
}
};

View File

@@ -0,0 +1,284 @@
#pragma once
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <winsock.h>
#include <mysql/mysql.h>
#pragma comment(lib,"libmysql.lib")
#include <vector>
#include <string>
#include "JsonValue.h"
/*
mysql的连接类
*/
class MySqlClient
{
public:
//处理防注入的
class PreparedStatement {
struct Pair {
char type;
int value_int;//type 0
std::string value_str;//type 1
};
std::string sql;
std::vector<Pair> values;
friend MySqlClient;
public:
PreparedStatement(const std::string& sql) :sql(sql) {
}
PreparedStatement& Replace(int value) {
values.push_back({ 0,value });
return *this;
}
PreparedStatement& Replace(const std::string& value) {
values.push_back({ 1,0,value });
return *this;
}
};
private:
std::string host;
std::string user;
std::string pwd;
std::string database;
std::string charset;
unsigned int port = 3306;
private:
static size_t get_data(MYSQL_RES* result, std::string& jsonArr) {
std::vector<std::string> fields;
//获取列名
size_t filedCount = mysql_num_fields(result);
for (size_t i = 0; i < filedCount; i++)
{
std::string name = mysql_fetch_field(result)->name;
fields.push_back(name);
//std::cout << name << std::endl;
}
jsonArr = "[";
//获取每行的数据
MYSQL_ROW sql_row;
size_t rowCount = 0;
while (sql_row = mysql_fetch_row(result))//获取具体的数据
{
rowCount++;
jsonArr.append("{");
bool frist_ = true;
for (size_t i = 0; i < filedCount; i++)
{
if (sql_row[i]) {
jsonArr.append("\"" + fields[i] + "\":\"" + sql_row[i] + "\"");
}
else {
jsonArr.append("\"" + fields[i] + "\":\"\"");
}
jsonArr.append(",");
}
jsonArr.erase(jsonArr.length() - 1, 1);
jsonArr.append("},");
}
jsonArr.erase(jsonArr.length() - 1, 1);
jsonArr.append("]");
if (rowCount == 0) {
jsonArr = "[]";
}
return rowCount;
}
public:
bool OpenConn(MYSQL& mysql);
void CloseConn(MYSQL& mysql);
MySqlClient(const std::string& host, unsigned int port, const std::string& user, const std::string& pwd, const std::string& database, const std::string& charset = "utf8mb4");
/*执行查询*/
bool ExecuteQuery(const std::string& sql, std::string& result);
/*执行增删改*/
size_t ExecuteNoQuery(const std::string& sql);
size_t Insert(const std::string& tableName, const Json::Value& jv);
size_t Update(const std::string& tableName, const Json::Value& jv, const std::string& whereText);
bool ExecuteQuery(const std::string& sql, Json::Value& result);
bool ExecuteSTMT(const PreparedStatement& _stmt, std::string& result);
virtual ~MySqlClient();
};
inline bool MySqlClient::OpenConn(MYSQL& mysql)
{
const char* unix_socket = NULL;
unsigned long client_flag = 0;
mysql_init(&mysql); //初始化
if ((mysql_real_connect(&mysql, host.c_str(), user.c_str(), pwd.c_str(), database.c_str(), port, unix_socket, client_flag)) == NULL) //连接MySQL
{
//数据库打开失败
printf("%s\n", mysql_error(&mysql));
return false;
}
else {
//数据库打开
return true;
}
}
inline void MySqlClient::CloseConn(MYSQL& mysql)
{
mysql_close(&mysql);
}
inline MySqlClient::MySqlClient(const std::string& host, unsigned int port, const std::string& user, const std::string& pwd, const std::string& database, const std::string& charset)
{
this->host = host;
this->user = user;
this->pwd = pwd;
this->database = database;
this->charset = charset;
this->port = port;
}
inline bool MySqlClient::ExecuteSTMT(const PreparedStatement& _stmt, std::string& resultJson) {
MYSQL mysql;
if (!OpenConn(mysql)) {
return false;
}
std::string charset_ = "set names ";
charset_.append(charset);
mysql_query(&mysql, charset_.c_str());
MYSQL_BIND* binds = NULL;
MYSQL_STMT* stmt = NULL;
MYSQL_RES* result = NULL;
bool ok = false;
do
{
binds = new MYSQL_BIND[_stmt.values.size()];
::memset(binds, 0, sizeof(MYSQL_BIND) * _stmt.values.size());
int pos = 0;
for (auto& it : _stmt.values) {
if (it.type == 0) {
binds[pos].buffer_type = MYSQL_TYPE_LONG;
binds[pos].buffer = (char*)&it.value_int;
binds[pos].is_null = 0;
}
else if (it.type == 1) {
binds[pos].buffer_type = MYSQL_TYPE_STRING;
binds[pos].buffer = (char*)it.value_str.c_str();
binds[pos].buffer_length = it.value_str.size();
binds[pos].is_null = 0;
}
++pos;
}
stmt = mysql_stmt_init(&mysql);
if (mysql_stmt_prepare(stmt, _stmt.sql.c_str(), _stmt.sql.size()) != 0) {
std::cerr << "Failed to mysql_stmt_prepare: " << mysql_stmt_error(stmt) << std::endl;
break;
}
if (mysql_stmt_bind_param(stmt, binds) != 0) {
std::cerr << "Failed to mysql_stmt_bind_param: " << mysql_stmt_error(stmt) << std::endl;
break;
}
//执行
if (mysql_stmt_execute(stmt) != 0) {
std::cerr << "Failed to mysql_stmt_execute: " << mysql_stmt_error(stmt) << std::endl;
break;
}
result = mysql_stmt_result_metadata(stmt);
ok = true;
} while (false);
//获取结果
if (result == NULL) {
resultJson = "[]";
}
else {
get_data(result, resultJson);
}
//释放
CloseConn(mysql);
delete[] binds;
mysql_stmt_close(stmt);
mysql_free_result(result);
return ok;
}
inline bool MySqlClient::ExecuteQuery(const std::string& sql, std::string& resultx)
{
MYSQL mysql;
if (!OpenConn(mysql)) {
return false;
}
std::string charset_ = "set names ";
charset_.append(charset);
mysql_query(&mysql, charset_.c_str());
mysql_query(&mysql, sql.c_str());
MYSQL_RES* result = NULL;
result = mysql_store_result(&mysql);
//查询失败
if (!result) {
mysql_free_result(result);
CloseConn(mysql);
resultx = "[]";
return false;
}
get_data(result, resultx);
//释放
mysql_free_result(result);
CloseConn(mysql);
return true;
}
inline size_t MySqlClient::ExecuteNoQuery(const std::string& sql)
{
MYSQL mysql;
if (!OpenConn(mysql)) {
return false;
}
std::string charset_ = "set names ";
charset_.append(charset);
mysql_query(&mysql, charset_.c_str());
mysql_query(&mysql, sql.c_str());
size_t affected_row = mysql_affected_rows(&mysql);
CloseConn(mysql);
return affected_row;
}
inline size_t MySqlClient::Update(const std::string& tableName, const Json::Value& jv, const std::string& whereText) {
std::string sql = "update " + tableName + " set ";
for (const auto& key : jv.getMemberNames()) {
if (jv[key].isNumeric()) {
sql += (key + "=" + jv[key].toString() + "");
}
else if (jv[key].isString()) {
sql += (key + "='" + jv[key].asString() + "'");
}
else {
sql += (key + "='" + jv[key].toString() + "'");
}
sql += ",";
}
sql.erase(sql.size() - 1, 1);
sql += " " + whereText;
return this->ExecuteNoQuery(sql);
}
inline size_t MySqlClient::Insert(const std::string& tableName, const Json::Value& jv) {
std::string keys = "(";
std::string values = "(";
for (const auto& key : jv.getMemberNames()) {
keys += "" + key + ",";
if (jv[key].isNumeric()) {
values += jv[key].toString() + ",";
}
else if (jv[key].isString()) {
values += "'" + jv[key].asString() + "',";
}
else {
values += "'" + jv[key].asString() + "',";
}
}
keys.erase(keys.size() - 1, 1);
values.erase(values.size() - 1, 1);
keys += ")";
values += ")";
std::string sql = "insert into " + tableName + " " + keys + "values" + values;
return this->ExecuteNoQuery(sql);
}
inline bool MySqlClient::ExecuteQuery(const std::string& sql, Json::Value& result)
{
std::string str;
auto ret = this->ExecuteQuery(sql, str);
result = JsonValue(str);
return ret;
}
inline MySqlClient::~MySqlClient()
{
}

View File

@@ -0,0 +1,132 @@
#pragma once
#include <iostream>
#include <occi/occi.h>
using namespace oracle::occi;
#ifdef _DEBUG
#pragma comment(lib,"oraocci12d.lib")
#else
#pragma comment(lib,"oraocci12.lib")
#endif // _DEBUG
#include <string>
class OrcaleClient
{
private:
std::string host;
unsigned int port = 1521;
std::string user;
std::string pwd;
std::string server_name;
std::string charset;
Environment* outEnv = NULL;
std::string dbStr;
public:
virtual ~OrcaleClient() {
if (outEnv) {
Environment::terminateEnvironment(outEnv);
}
}
OrcaleClient(const std::string& host, unsigned int port, const std::string& user, const std::string& pwd, const std::string& server_name, const std::string& charset = "UTF8");
void CloseConn(Connection* conn);
Connection* OpenConn();
bool ExecuteQuery(const std::string& sql, std::string& sqlResult);
size_t ExecuteNoQuery(const std::string& sql);
};
inline Connection* OrcaleClient::OpenConn() {
try
{
auto conn = outEnv->createConnection(user, pwd, dbStr);
return conn;
}
catch (const std::exception& ex)
{
printf("%s\n", ex.what());
return NULL;
}
}
inline void OrcaleClient::CloseConn(Connection* conn) {
outEnv->terminateConnection(conn);
}
inline OrcaleClient::OrcaleClient(const std::string& host, unsigned int port, const std::string& user, const std::string& pwd, const std::string& server_name, const std::string& charset) {
this->host = host;
this->port = port;
this->user = user;
this->pwd = pwd;
this->server_name = server_name;
this->charset = charset;
this->dbStr = host + ":" + std::to_string(port) + "/" + server_name;
this->outEnv = Environment::createEnvironment("ZHS16GBK", this->charset);//编码问题
}
inline size_t OrcaleClient::ExecuteNoQuery(const std::string& sql) {
size_t affRow = 0;
auto conn = OpenConn();
if (conn) {
Statement* stmt = NULL;
try {
stmt = conn->createStatement();
affRow = stmt->executeUpdate(sql);
}
catch (SQLException& ex)
{
printf("%s\n", ex.what());
}
if (stmt) {
conn->terminateStatement(stmt);
}
CloseConn(conn);
}
return 0;
}
inline bool OrcaleClient::ExecuteQuery(const std::string& sql, std::string& sqlResult) {
bool ok = false;
auto conn = OpenConn();
if (conn) {
std::vector<std::string> fields;
Statement* stmt = NULL;
ResultSet* rset = NULL;
try {
stmt = conn->createStatement();
rset = stmt->executeQuery(sql);
for (auto item : rset->getColumnListMetaData()) {
std::string s = item.getString(MetaData::ATTR_NAME);
fields.push_back(s);
}
sqlResult = "[";
//获取每行的数据
bool frist = true;
size_t rowCount = 0;
while (rset->next())//获取具体的数据
{
rowCount++;
sqlResult.append("{");
bool frist_ = true;
for (size_t i = 0; i < fields.size(); i++)
{
sqlResult.append("\"" + fields[i] + "\":\"" + rset->getString(i + 1) + "\"");
sqlResult.append(",");
}
sqlResult.erase(sqlResult.length() - 1, 1);
sqlResult.append("},");
if (frist) {
frist = false;
}
}
sqlResult.erase(sqlResult.length() - 1, 1);
sqlResult.append("]");
if (rowCount == 0) {
sqlResult = "[]";
}
ok = true;
}
catch (SQLException& ex)
{
printf("%s\n", ex.what());
}
if (stmt && rset) {
stmt->closeResultSet(rset);
conn->terminateStatement(stmt);
}
CloseConn(conn);
}
return ok;
}

View File

@@ -0,0 +1,169 @@
#pragma once
#include "Common.h"
#include "qrcode/qrencode.h"
#ifdef _WIN64
#ifdef _DEBUG
#pragma comment (lib,"X64/libqrencode_d.lib")
#else
#pragma comment (lib,"X64/libqrencode.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"libqrencode_d.lib")
#else
#pragma comment(lib,"libqrencode.lib")
#endif // !_DEBUG
#endif
namespace QrenCode {
//生成二维码 返回位图 用完位图记得释放
inline HBITMAP Generate(const std::string& str, QRecLevel level = QRecLevel::QR_ECLEVEL_M) {
unsigned int unWidth, x, y, l, n, unWidthAdjusted;
byte* pRGBData = NULL, * pSourceData, * pDestData;
QRcode* pQRC = NULL;
HBITMAP bmp = NULL;
do
{
if (pQRC = QRcode_encodeString(str.c_str(), 0, level, QR_MODE_8, 1))
{
unWidth = pQRC->width;
unWidthAdjusted = unWidth * 8 * 3;
if (unWidthAdjusted % 4) {
unWidthAdjusted = (unWidthAdjusted / 4 + 1) * 4;
}
BITMAPINFO bmpInfo;
memset(&bmpInfo, 0, sizeof(bmpInfo));
BITMAPINFOHEADER& kInfoHeader = bmpInfo.bmiHeader;
kInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
kInfoHeader.biWidth = unWidth * 8;
kInfoHeader.biHeight = -((int)unWidth * 8);
kInfoHeader.biPlanes = 1;
kInfoHeader.biBitCount = 24;
kInfoHeader.biCompression = BI_RGB;
kInfoHeader.biSizeImage = 0;
kInfoHeader.biXPelsPerMeter = 0;
kInfoHeader.biYPelsPerMeter = 0;
kInfoHeader.biClrUsed = 0;
kInfoHeader.biClrImportant = 0;
// Convert QrCode bits to bmp pixels
pSourceData = pQRC->data;
bmp = ::CreateDIBSection(NULL, &bmpInfo, DIB_RGB_COLORS, (void**)&pRGBData, NULL, 0);
for (y = 0; y < unWidth; y++)
{
pDestData = pRGBData + unWidthAdjusted * y * 8;
for (x = 0; x < unWidth; x++)
{
if (*pSourceData & 1)
{
for (l = 0; l < 8; l++)
{
for (n = 0; n < 8; n++)
{
//以下三行是设置三基色三基色都设置为0x00则生成的二维码图片就是黑色的了要什么颜色自己调整
*(pDestData + n * 3 + unWidthAdjusted * l) = 0x00;
*(pDestData + 1 + n * 3 + unWidthAdjusted * l) = 0x00;
*(pDestData + 2 + n * 3 + unWidthAdjusted * l) = 0x00;
}
}
}
pDestData += 3 * 8;
pSourceData++;
}
}
}
} while (false);
if (pQRC) {
QRcode_free(pQRC);
}
return bmp;
////绑定dc
//HDC dc=::CreateCompatibleDC(NULL);
//::SelectObject(dc, bmp);
////用完释放
//::DeleteDC(dc);
//::DeleteObject(bmp);
}
//生成二维码到内存
inline bool Generate(const std::string& str, std::string& outFileData, QRecLevel level = QRecLevel::QR_ECLEVEL_M) {
const char* szSourceSring = str.c_str();
unsigned int unWidth, x, y, l, n, unWidthAdjusted, unDataBytes;
byte* pSourceData, * pDestData;
QRcode* pQRC = NULL;
do
{
if (pQRC = QRcode_encodeString(szSourceSring, 0, level, QR_MODE_8, 1))
{
unWidth = pQRC->width;
unWidthAdjusted = unWidth * 8 * 3;
if (unWidthAdjusted % 4) {
unWidthAdjusted = (unWidthAdjusted / 4 + 1) * 4;
}
unDataBytes = unWidthAdjusted * unWidth * 8;
// Prepare bmp headers
BITMAPFILEHEADER kFileHeader;
kFileHeader.bfType = 0x4d42;
kFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + unDataBytes;
kFileHeader.bfReserved1 = 0;
kFileHeader.bfReserved2 = 0;
kFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BITMAPINFOHEADER kInfoHeader;
kInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
kInfoHeader.biWidth = unWidth * 8;
kInfoHeader.biHeight = -((int)unWidth * 8);
kInfoHeader.biPlanes = 1;
kInfoHeader.biBitCount = 24;
kInfoHeader.biCompression = BI_RGB;
kInfoHeader.biSizeImage = 0;
kInfoHeader.biXPelsPerMeter = 0;
kInfoHeader.biYPelsPerMeter = 0;
kInfoHeader.biClrUsed = 0;
kInfoHeader.biClrImportant = 0;
// Convert QrCode bits to bmp pixels
pSourceData = pQRC->data;
//因为是放在内存 所以简化了一些
outFileData.resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + unDataBytes);
byte* ptr = (byte*)outFileData.c_str();
::memcpy(ptr, (char*)&kFileHeader, sizeof(kFileHeader));
ptr += sizeof(kFileHeader);
::memcpy(ptr, (char*)&kInfoHeader, sizeof(kInfoHeader));
ptr += sizeof(kInfoHeader);
byte* pRGBData = ptr;
// Preset to white
::memset(pRGBData, 0xff, unDataBytes);
for (y = 0; y < unWidth; y++)
{
pDestData = pRGBData + unWidthAdjusted * y * 8;
for (x = 0; x < unWidth; x++)
{
if (*pSourceData & 1)
{
for (l = 0; l < 8; l++)
{
for (n = 0; n < 8; n++)
{
//以下三行是设置三基色三基色都设置为0x00则生成的二维码图片就是黑色的了要什么颜色自己调整
*(pDestData + n * 3 + unWidthAdjusted * l) = 0x00;
*(pDestData + 1 + n * 3 + unWidthAdjusted * l) = 0x00;
*(pDestData + 2 + n * 3 + unWidthAdjusted * l) = 0x00;
}
}
}
pDestData += 3 * 8;
pSourceData++;
}
}
}
} while (false);
if (pQRC) {
QRcode_free(pQRC);
}
return !outFileData.empty();
}
};

View File

@@ -0,0 +1,16 @@
#pragma once
#include <random>
class Random {
std::mt19937 randomer;
public:
Random() :randomer(std::random_device()()) {
}
int Next(int lower, int upper) {
std::uniform_int_distribution<int> distribution(lower, upper);
return distribution(randomer);
}
float Next(float lower, float upper) {
std::uniform_real_distribution<float> distribution(lower, upper);
return distribution(randomer);
}
};

View File

@@ -0,0 +1,168 @@
//#pragma once
//#include <windows.h>
//#include <stdio.h>
//#include <strsafe.h>
//
//namespace Regedit {
// //删除指定key
// BOOL DelKey(HKEY keyRoot, LPTSTR keyPath);
// //判断是否存在key
// BOOL Exist(HKEY keyRoot, LPTSTR keyPath);
//
// bool SetValue(HKEY hKey, const TString&key, const TString&value = TEXT(""));
// void SetValueEx(HKEY hKey, const TString&key, const TString&value);
// HKEY CreateKey(HKEY rootKey, const TString&keyPath, const TString&defaultValue = TEXT(""));
//};
//
//namespace Regedit {
// inline bool SetValue(HKEY hKey, const TString&key, const TString&value) {
// return !::RegSetValue(hKey, key.c_str(), REG_SZ, value.c_str(), value.size());
// }
// inline void SetValueEx(HKEY hKey, const TString&key, const TString&value) {
// RegSetValueEx(hKey, key.c_str(), NULL, REG_SZ, (BYTE*)value.c_str(), value.size());
// }
// inline HKEY CreateKey(HKEY rootKey, const TString&keyPath, const TString&defaultValue) {
// HKEY hKey;
// RegCreateKey(rootKey, keyPath.c_str(), &hKey);
// SetValue(hKey, TEXT(""), defaultValue);
// return hKey;
// }
//
// inline BOOL DelKey(HKEY hKeyRoot, LPTSTR lpSubKey)
// {
// LPTSTR lpEnd;
// LONG lResult;
// DWORD dwSize;
// TCHAR szName[MAX_PATH];
// HKEY hKey;
// FILETIME ftWrite;
// // First, see if we can delete the key without having
// // to recurse.
// lResult = RegDeleteKey(hKeyRoot, lpSubKey);
// if (lResult == ERROR_SUCCESS) {
// return TRUE;
// }
// lResult = RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
//
// if (lResult != ERROR_SUCCESS)
// {
// if (lResult == ERROR_FILE_NOT_FOUND) {
// printf("Key not found.\n");
// return TRUE;
// }
// else {
// printf("Error opening key.\n");
// return FALSE;
// }
// }
//
// // Check for an ending slash and add one if it is missing.
//
// lpEnd = lpSubKey + lstrlen(lpSubKey);
//
// if (*(lpEnd - 1) != TEXT('\\'))
// {
// *lpEnd = TEXT('\\');
// lpEnd++;
// *lpEnd = TEXT('\0');
// }
//
// // Enumerate the keys
//
// dwSize = MAX_PATH;
// lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
// NULL, NULL, &ftWrite);
//
// if (lResult == ERROR_SUCCESS)
// {
// do {
//
// StringCchCopy(lpEnd, MAX_PATH * 2, szName);
//
// if (!DelKey(hKeyRoot, lpSubKey)) {
// break;
// }
//
// dwSize = MAX_PATH;
//
// lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
// NULL, NULL, &ftWrite);
//
// } while (lResult == ERROR_SUCCESS);
// }
//
// lpEnd--;
// *lpEnd = TEXT('\0');
//
// RegCloseKey(hKey);
// // Try again to delete the key.
// lResult = RegDeleteKey(hKeyRoot, lpSubKey);
//
// if (lResult == ERROR_SUCCESS)
// return TRUE;
//
// return FALSE;
// }
// inline BOOL Exist(HKEY keyRoot, LPTSTR keyPath)
// {
// HKEY hExtKey;
// if (RegOpenKey(keyRoot, keyPath, &hExtKey) == ERROR_SUCCESS)
// {
// RegCloseKey(hExtKey);
// return TRUE;
// }
// return FALSE;
// }
//};
//
//
//struct Version {
// WORD v1, v2, v3, v4;
//};
//struct Product {
//private:
// HKEY hExtKey = NULL;
// TString ProductName;
// DWORD type = REG_SZ;
// DWORD dwLen = MAX_PATH;
//public:
// Product(const TString&ProductName) {
// this->ProductName = ProductName;
// if (RegOpenKey(HKEY_CLASSES_ROOT, ProductName.c_str(), &hExtKey) != ERROR_SUCCESS)//如果打不开
// {
// hExtKey = ::Regedit::CreateKey(HKEY_CLASSES_ROOT, ProductName);//就创建
// }
// }
// void SetValue(const TString&key, const TString&value) {
// Regedit::SetValueEx(hExtKey, key, value);
// }
// TString GetValue(const TString&key, const TString&defaulValue = "") {
// TCHAR bufStr[MAX_PATH]{ 0 };
// if (::RegQueryValueEx(hExtKey, key.c_str(), 0, &type, (LPBYTE)bufStr, &dwLen) != ERROR_SUCCESS) {
// auto code = ::GetLastError();
// SetValue(key, defaulValue);
// return defaulValue;
// }
// return bufStr;
// }
// Version GetVersion() {//从注册表中获取程序版本
// TString localVer = GetValue("ver", "0.0.0.0");
// Version ver{ 0,0,0,0 };//当前程序版本
// auto vers = Text::Split(localVer, ".");
// ver.v1 = (WORD)std::stoi(vers.at(0));
// ver.v2 = (WORD)std::stoi(vers.at(1));
// ver.v3 = (WORD)std::stoi(vers.at(2));
// ver.v4 = (WORD)std::stoi(vers.at(3));
// return ver;
// }
// void SetVersion(const Version&ver) {//设置新版本
// TCHAR newVer[MAX_PATH] = { 0 };
// Text::Format(newVer, MAX_PATH, "%d.%d.%d.%d", ver.v1, ver.v2, ver.v3, ver.v4);
// SetValue("ver", newVer);
// }
// ~Product() {
// if (hExtKey) {
// ::RegCloseKey(hExtKey);
// }
// }
//};

View File

@@ -0,0 +1,37 @@
#pragma once
#include <vector>
#include <iostream>
#include <string>
#include <memory>
#include <mutex>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h> // 先包含 winsock2.h避免冲突
#include <windows.h> // 再包含 windows.h
#include <ws2tcpip.h> // ws2tcpip.h 依赖 winsock2.h可以放在后面
#pragma comment(lib, "ws2_32.lib")
#endif
class Socket
{
private:
SOCKET socket = NULL;
sockaddr_in sockaddr = {};
public:
static std::vector<std::string> GetIpByName(const std::string& hostname);
public:
size_t Port = 0;
std::string Address;
int Receive(char* outBuf, size_t recvLen, int flags = 0) const;
bool Connect(const std::string& ip, size_t port);
bool Bind(const std::string& ip, size_t port);
bool Listen(int backlog = 5);
Socket Accep() const;
int Write(const char* buff, int size)const;
void Close() const;
Socket();
Socket(SOCKET socket);
virtual ~Socket();
};

View File

@@ -0,0 +1,84 @@
#pragma once
#include <vector>
#include <string>
#include <Windows.h>
#ifdef _WINDLL
#define UI_EXPORT __declspec(dllexport)
#define UI_VAR_EXPORT UI_EXPORT
#else
#define UI_EXPORT
#define UI_VAR_EXPORT __declspec(dllimport)
#endif // _WINDLL
namespace Text {
//-----------------------------------------------Copy Start-----------------------------------------------
/// <summary>
/// utf8字符串
/// </summary>
class UI_EXPORT String :public std::string {
public:
String();
virtual ~String();
String(const String& _right)noexcept;
String(String&& _right)noexcept;
String& operator=(const String& _right)noexcept;
String& operator=(String&& _right)noexcept;
String(const std::string& str)noexcept;
String(const char* szbuf)noexcept;
String(const wchar_t* szbuf)noexcept;
String(const std::wstring& wstr)noexcept;
//获取utf8字符串的字符串长度
virtual size_t length() const final;
std::wstring unicode() const;
std::string ansi() const;
void erase(char _ch);
void erase(size_t pos, size_t count);
String replace(char oldChar, char newChar)const;
String replace(const String& oldText, const String& newText, bool allReplace = true)const;
String toLower()const;
String toUpper()const;
//去除前后空格
String trim()const;
//find value count
size_t count(const String& value);
std::vector<String> split(const String& ch)const;
bool operator==(const wchar_t* szbuf)const;
bool operator==(const std::wstring& wStr)const;
template<typename ...T>
inline String format(const T &...args) {
auto bufSize = ::snprintf(nullptr, 0, this->c_str(), std::forward<const T&>(args)...) + 1; // +1是为了'结束符\0'
char* buf = new char[bufSize] {0};
auto count = ::sprintf_s(buf, bufSize, this->c_str(), std::forward<const T&>(args)...);
String ret(buf);
delete[] buf;
return ret;
}
};
//base convert
UI_EXPORT void AnyToUnicode(const std::string& src_str, UINT codePage, std::wstring* out_wstr);
UI_EXPORT void UnicodeToAny(const std::wstring& unicode_wstr, UINT codePage, std::string* out_str);
//
UI_EXPORT void GBKToUTF8(const std::string& str, std::string* outStr);
UI_EXPORT void UTF8ToGBK(const std::string& str, std::string* outStr);
UI_EXPORT void ANSIToUniCode(const std::string& str, std::wstring* outStr);
UI_EXPORT void ANSIToUTF8(const std::string& str, std::string* outStr);
UI_EXPORT void UnicodeToANSI(const std::wstring& wstr, std::string* outStr);
UI_EXPORT void UnicodeToUTF8(const std::wstring& wstr, std::string* outStr);
UI_EXPORT void UTF8ToANSI(const std::string& str, std::string* outStr);
UI_EXPORT void UTF8ToUnicode(const std::string& str, std::wstring* outStr);
//
UI_EXPORT void Tolower(std::string* str_in_out);
UI_EXPORT void Toupper(std::string* str_in_out);
UI_EXPORT void Erase(std::string* str_in_out, char ch);
UI_EXPORT void Replace(std::string* str_in_out, char oldChar, char newChar);
UI_EXPORT size_t Replace(std::string* str_in_out, const std::string& oldText, const std::string& newText, bool replaceAll = true);
UI_EXPORT void Split(const std::string& str_in, const std::string& ch, std::vector<std::string>* strs_out);
//
UI_EXPORT String ToString(double number, size_t keepBitSize);
//-----------------------------------------------Copy End-----------------------------------------------
};
using u8String = Text::String;

View File

@@ -0,0 +1,137 @@
#pragma once
#include <vector>
#include <thread>
#include <queue>
#include <condition_variable>
#include <mutex>
#include <future>
#include <list>
class Thread {
bool _bStop = false;
std::thread* _task = NULL;
bool _bJoin = false;
std::mutex _mtx;
std::condition_variable _codv;
private:
Thread(const Thread&) = delete;
public:
template<class Func, class... Args>
Thread(Func&& f, Args&& ...args) {
std::function<void()>* func = new std::function<void()>(std::bind(std::forward<Func>(f), std::forward<Args>(args)...));
_task = new std::thread([this, func]() mutable {
(*func)();
delete func;
{
std::unique_lock<std::mutex> autoLock(_mtx);
_bStop = true;
}
_codv.notify_all();
});
}
void Wait() {
if (!_bJoin)
{
_bJoin = true;
std::unique_lock<std::mutex> autoLock(_mtx);
_codv.wait(autoLock, [this]() ->bool {
return _bStop;
});
_task->join();
}
}
bool IsStopped() {
std::unique_lock<std::mutex> autoLock(_mtx);
return _bStop;
}
virtual ~Thread() {
Wait();
delete _task;
}
};
class ThreadPool {
bool bStop = false;
std::list<Thread*> tasks;
std::list<std::function<void()>> funcs;
std::mutex mtx;
std::condition_variable codv;
//用于等待任务清空的锁和条件变量
std::mutex mtx2;
std::condition_variable codv2;
private:
ThreadPool(const ThreadPool&) = delete;
public:
ThreadPool(int maxTaskCount = 50) {
for (size_t i = 0; i < maxTaskCount; ++i)
{
tasks.push_back(new Thread([this]() {
while (true)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> autoLock(this->mtx);
this->codv.wait(autoLock, [this]()->bool {
return this->bStop || !this->funcs.empty();
});
if (funcs.empty()) {
this->codv2.notify_all();
}
if (this->bStop && funcs.empty()) {
break;
}
task = std::move(*funcs.begin());
funcs.pop_front();
}
task();
}
}));
}
}
void WaitAll() {
codv.notify_all();
std::unique_lock<std::mutex> lock2(this->mtx2);
this->codv2.wait(lock2, [this]()->bool {
return funcs.empty();
});
}
virtual ~ThreadPool() {
{
std::unique_lock<std::mutex> autoLock(mtx);
bStop = true;
}
WaitAll();
while (!tasks.empty())
{
for (auto itor = tasks.begin(); itor != tasks.end(); )
{
if ((*itor)->IsStopped()) {
(*itor)->Wait();
delete (*itor);
itor = tasks.erase(itor);
}
else {
++itor;
}
}
}
}
//添加到任务队列中的末尾(先后顺序执行)
template<class Func, class... Args>
void Add(Func&& f, Args&& ...args) {
{
std::unique_lock<std::mutex> autoLock(mtx);
funcs.emplace_back(std::bind(std::forward<Func>(f), std::forward<Args>(args)...));
}
codv.notify_one();
}
//添加至任务队列的第一位(优先执行)
template<class Func, class... Args>
void AddToFrist(Func&& f, Args&& ...args) {
{
std::unique_lock<std::mutex> autoLock(mtx);
funcs.emplace_front(std::bind(std::forward<Func>(f), std::forward<Args>(args)...));
}
codv.notify_one();
}
};

View File

@@ -0,0 +1,83 @@
#pragma once
#include <Windows.h>
#include <time.h>
#include <string>
#include "Text.h"
#include <sstream>
#include <iomanip>
class Time {
time_t _time;
public:
static Time Now() {
return Time(::time(NULL));
}
public:
Time(time_t second) {
_time = second;
}
Time(const std::string& timeStr, const std::string& format = "yyyy-MM-dd HH:mm:ss") {
std::string formatStr = format;
Text::Replace(&formatStr, "yyyy", "%Y");
Text::Replace(&formatStr, "MM", "%m");
Text::Replace(&formatStr, "dd", "%d");
Text::Replace(&formatStr, "HH", "%H");
Text::Replace(&formatStr, "mm", "%M");
Text::Replace(&formatStr, "ss", "%S");
std::tm tm{};
std::istringstream ss(timeStr);
ss >> std::get_time(&tm, formatStr.c_str());
tm.tm_isdst = -1; // Enable daylight saving time
std::time_t timeStamp = std::mktime(&tm);
if (timeStamp == -1) {
throw std::runtime_error("Error converting time string to timestamp.");
}
this->_time = timeStamp;
}
std::string ToString(const std::string& format = "yyyy-MM-dd HH:mm:ss") const{
std::string formatStr = format;
Text::Replace(&formatStr, "yyyy", "%Y");
Text::Replace(&formatStr, "MM", "%m");
Text::Replace(&formatStr, "dd", "%d");
Text::Replace(&formatStr, "HH", "%H");
Text::Replace(&formatStr, "mm", "%M");
Text::Replace(&formatStr, "ss", "%S");
char timeStr[128]{ 0 };
time_t t = _time;
struct tm* ttime = std::localtime(&t);
std::strftime(timeStr, sizeof(timeStr), formatStr.c_str(), ttime);
return timeStr;
}
time_t operator - (const Time& right) {
return this->_time - right._time;
}
bool operator == (const Time& right) {
return this->_time == right._time;
}
bool operator != (const Time& right) {
return this->_time != right._time;
}
bool operator > (const Time& right) {
return this->_time > right._time;
}
bool operator < (const Time& right) {
return this->_time < right._time;
}
Time& operator += (time_t right) {
this->_time += right;
return *this;
}
Time& operator -= (time_t right) {
this->_time -= right;
return *this;
}
Time operator + (time_t right) {
return Time(this->_time + right);
}
Time operator - (time_t right) {
return Time(this->_time - right);
}
};

View File

@@ -0,0 +1,81 @@
#pragma once
#include "Text.h"
#include "FileSystem.h"
DECLARE_HANDLE(HZIP_U);
struct ZipItem
{
int index; // index of this file within the zip
TCHAR name[MAX_PATH]; // filename within the zip
DWORD attr; // attributes, as in GetFileAttributes.
FILETIME atime, ctime, mtime;// access, create, modify filetimes
long comp_size; // sizes of item, compressed and uncompressed. These
long unc_size; // may be -1 if not yet known (e.g. being streamed in)
bool isDir()const {
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
return true;
}
return false;
}
};
/// <summary>
/// 专门负责解压缩的类
/// </summary>
class UnZiper {
HZIP_U ptr = NULL;
int itemCount = 0;
public:
UnZiper(const std::wstring& fileName, const std::string& password = "");
UnZiper(const char* fileData, unsigned int size, const std::string& password = "");
bool Find(const std::string& itemName, ZipItem* item);
bool Find(int index, ZipItem* item);
bool UnZipItem(const ZipItem& item, byte** data);
int GetCount();
virtual ~UnZiper();
public:
static bool UnZip(UnZiper* zip, const Text::String& outDir, const std::string& password = "", std::function<void(const Text::String&, int total, int index, bool& stop)> callback = NULL) {
bool ok = true;
for (int i = 0; i < zip->GetCount(); i++)
{
ZipItem ze;
zip->Find(i, &ze);
Text::String itemName = outDir + "/" + Text::String(ze.name);
if (ze.isDir()) {
if (!Directory::Create(itemName)) {
ok = false;
}
}
else {
File::Delete(itemName);
byte* data = NULL;
zip->UnZipItem(ze, &data);
std::ofstream ofs(itemName.unicode(), std::ios::binary);
ofs.write((char*)data, ze.unc_size);
ofs.flush();
ofs.close();
if (!ofs.good()) {
ok = false;
}
if (data) {
delete[] data;
}
}
if (callback) {
bool stop = false;
callback(itemName, zip->GetCount(), i, stop);
if (stop) {
break;
}
}
}
return ok;
}
static bool UnZip(const Text::String& zipFileName, const Text::String& outDir, const std::string& password = "", std::function<void(const Text::String&, int total, int index, bool& stop)> callback = NULL) {
Directory::Create(outDir);
UnZiper zip(zipFileName.unicode(), password);
return UnZip(&zip, outDir, password, callback);
}
};

View File

@@ -0,0 +1,30 @@
#pragma once
#include <Windows.h>
#include <string>
namespace Util {
//文件的md5
std::string MD5FromFile(const std::wstring& filename);
//字符串的md5
std::string MD5FromString(const std::string& string);
//base64编码
std::string Base64Encode(const char* str, int strLen);
//base64编码
std::string Base64Encode(const std::string& string);
//base64解码
std::string Base64Decode(const char* base64Str, int strLen);
//base64解码
std::string Base64Decode(const std::string& string);
//url编码
std::string UrlEncode(const std::string& str);
//url解码
std::string UrlDecode(const std::string& str, bool convert_plus_to_space = false);
//少一个GZIP
namespace XOR {
//XOR加密 必须输入密码才能加密
std::string EnCode(const std::string& data, const std::string& password);
//XOR解密
std::string DeCode(const std::string& data, const std::string& password);
}
};

View File

@@ -0,0 +1,76 @@
#pragma once
#include <string>
#include <Windows.h>
#include <functional>
#include <mutex>
#include <map>
#include "FileSystem.h"
#include "Text.h"
#define USECURL 1 //是否使用curl 使用curl会导致库变得很大
#if USECURL
namespace PostForm {
//字段类型
enum FieldType :char
{
None,
Text,
File
};
class Field {
public:
FieldType FieldType = FieldType::None;
std::string FieldName;
std::string FieldValue;
std::string FileName;
Field(const std::string& FieldName, const std::string& ValueOrFullFileName, PostForm::FieldType FieldType = PostForm::FieldType::Text) {
this->FieldName = FieldName;
this->FieldType = FieldType;
if (FieldType == PostForm::FieldType::File) {
this->FieldValue = Path::GetFileName(ValueOrFullFileName);
this->FileName = ValueOrFullFileName;
}
else {
this->FieldValue = ValueOrFullFileName;
}
}
};
}
class WebClient
{
public:
struct Content
{
void* tag = NULL;
bool cancel = false;
int type = 0;//0:正常请求 1:下载文件
};
private:
Content content;
public:
std::function<size_t(char* contents, size_t size, size_t nmemb, void* respone)> CallBack = NULL;
private:
void* Init(const std::string& url, std::string* resp, int timeOut);
long CleanUp(void* curl, int code);
std::map<std::string, std::string> Header;
void* curl_header = NULL;//类型参见 curl_slist
public:
std::string Cookies;
std::string Proxy;
WebClient();
virtual ~WebClient();
//取消请求/下载
void Cancel();
void AddHeader(const std::string& key, const std::string& value);
void RemoveHeader(const std::string& key);
int HttpGet(const std::string& strUrl, std::string* response = NULL, int nTimeout = 60);
int HttpPost(const std::string& strUrl, const std::string& data = "", std::string* response = NULL, int nTimeout = 60);
int DownloadFile(const std::string& strUrl, const std::wstring& filename, const std::function<void(long long dltotal, long long dlnow)>& progressCallback = NULL, int nTimeout = 99999);
int FtpDownLoad(const std::string& strUrl, const std::string& user, const std::string& pwd, const std::wstring& outFileName, int nTimeout = 99999);
int UploadFile(const std::string& strUrl, const std::string& filename, const std::string& field, std::string* response = NULL, const std::function<void(long long dltotal, long long dlnow)>& progressCallback = NULL, int nTimeout = 99999);
int SubmitForm(const std::string& strUrl, const std::vector<PostForm::Field>& fieldValues, std::string* response = NULL, int nTimeout = 99999);
};
#endif

View File

@@ -0,0 +1,172 @@
#pragma once
#include <map>
#include <functional>
#include <Windows.h>
#include <TlHelp32.h>
#include "Text.h"
#ifdef GetUserName
#undef GetUserName
inline void GetUserName(LPSTR lpBuffer, LPDWORD pcbBuffer) {
::GetUserNameA(lpBuffer, pcbBuffer);
}
inline void GetUserName(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
::GetUserNameW(lpBuffer, pcbBuffer);
}
#endif
#ifdef GetComputerName
#undef GetComputerName
inline void GetComputerName(LPSTR lpBuffer, LPDWORD pcbBuffer) {
::GetComputerNameA(lpBuffer, pcbBuffer);
}
inline void GetComputerName(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
::GetComputerNameW(lpBuffer, pcbBuffer);
}
#endif
namespace WinTool {
/// <summary>
/// 路由信息
/// </summary>
struct RouterInfo {
Text::String IP;
Text::String MAC;
};
typedef struct {
unsigned long processId;
HWND best_handle;
}handle_data;
typedef struct _MyAdpterInfo
{
std::vector<std::string> Ip;
std::string MacAddress;
std::string Description;
std::string Name;
UINT Type;
}MyAdpterInfo;
struct AppInfo {
/// app名称
Text::String DisplayName;
/// 版本号
Text::String DisplayVersion;
//显示图标
Text::String DisplayIcon;
// 发布者
Text::String Publisher;
//软件安装路径
Text::String InstallLocation;
// 主程序启动完整路径 C:\\Program Files\\xxx\xxx.exe
Text::String PragmaFile;
// 卸载执行的命令行
Text::String UninstallString;
// 产品帮助链接
Text::String HelpLink;
//帮助说明[这是一款桌面工具]
Text::String Comments;
//产品官网
Text::String URLInfoAbout;
//是否禁用控制面板修改按钮
bool NoModify = false;
//是否禁用控制面板修复按钮
bool NoRepair = false;
// 是否创建桌面快捷方式
bool DesktopLink = true;
// 是否开机启动
bool AutoBoot = false;
//为所有用户注册
bool AllUsers = true;
};
//给进程提权
extern BOOL EnablePrivilege(HANDLE process = NULL);
//创捷快捷方式
extern bool CreateLink(const Text::String& pragmaFilename, const Text::String& outDir, const Text::String& LnkName = L"", const Text::String& cmdline = L"", const Text::String& iconFilename = L"");
//删除快捷方式
extern void DeleteLink(const Text::String& linkDir, const Text::String& pragmaFilename, const Text::String& LnkName = "");
/// 删除注册表中某个项及其子项和值
extern void DeleteKeyRecursively(HKEY hKeyParent, const wchar_t* subKey);
//获取软件相关信息
extern Text::String GetAppValue(const Text::String& appName_en, const Text::String& key);
//根据软件名称修改一些信息
extern bool SetAppValue(const Text::String& appName_en, const Text::String& key, const Text::String& value);
//注册软件到电脑
extern bool RegisterApp(const AppInfo& appInfo);
//从电脑上注销软件
extern void UnRegisterApp(const Text::String& appName_en);
//给软件注册许可
extern bool RegisterLicenser(const Text::String& exeFilename, const Text::String& softwareData);
//获取软件许可证书
extern Text::String FindLicenser(const Text::String& exeFilename);
//设置程序自启动 rootKey参数:HKEY_CURRENT_USER(当前用户), HKEY_LOCAL_MACHINE//所有用户(需要管理员)
extern bool SetAutoBoot(const Text::String& filename = L"", bool enable = true, HKEY rootKey = HKEY_CURRENT_USER);
//获取程序自启动状态 rootKey参数:HKEY_CURRENT_USER(当前用户), HKEY_LOCAL_MACHINE//所有用户(需要管理员)
extern bool IsAutoBoot(const Text::String& _keyName, HKEY rootKey = HKEY_CURRENT_USER);
//检查计划任务
extern bool IsInTask(const Text::String& _taskName);
//添加到启动计划任务
extern bool AddBootTask(const Text::String& _taskName, const Text::String& _exeFile);
//寻找进程中的窗口
extern HWND FindMainWindow(DWORD processId);
//获取进程信息
extern std::vector<PROCESSENTRY32W> FindProcessInfo(const Text::String& _proccname);
//根据进程名称打开进程
extern HANDLE OpenProcess(const Text::String& _proccname);
//获取进程ID集合
extern std::vector<DWORD> FindProcessId(const Text::String& proccname);
//获取进程文件路径
extern Text::String FindProcessFilename(DWORD processId);
//关闭所有进程
extern int CloseProcess(const std::vector<DWORD>& processIds);
//使用进程ID关闭进程
extern bool CloseProcess(DWORD processId);
//使用句柄关闭进程
extern bool CloseProcess(HANDLE hProcess, UINT exitCode = 0);
//获取进程是不是64位的
extern bool Is64BitPorcess(DWORD processId);
//获取进程是不是32位的
extern bool Is86BitPorcess(DWORD processId);
//获取当前进程ID
extern DWORD GetCurrentProcessId();
//获取系统位数
extern int GetSystemBits();
//获取计算机唯一识别码
extern Text::String GetComputerID();
//用户当前用户名称
extern Text::String GetUserName();
//获取计算机名称
extern Text::String GetComputerName();
//获取网卡相关
extern int GetAdptersInfo(std::vector<MyAdpterInfo>& adpterInfo);
/// 获取磁盘可以用空间单位:GB
extern double GetDiskFreeSize(const Text::String& path);
/// 直接执行可执行文件并获取返回内容
extern Text::String ExecuteCMD(const Text::String& cmdStr, std::function<void(const Text::String&)> callback = NULL, HANDLE* outHandle = NULL);
///获取首选网卡的mac地址
extern Text::String GetMacAddress();
/// 获取操作系统的版本号
extern Text::String GetWinVersion();
/// 弹出选择文件对话框(filter传入参数的方式存在问题 以后改)
extern Text::String ShowFileDialog(HWND ownerWnd = NULL, const Text::String& defaultPath = "", const Text::String& title = "Select a File", const Text::String& filter = "All Files\0*.*\0");
/// 弹出选择目录对话框
extern Text::String ShowFolderDialog(HWND ownerWnd = NULL, const Text::String& defaultPath = "", const Text::String& title = "Select a directory");
/// 获取路由信息
extern RouterInfo GetRouterInfo();
/// 获取电脑的com端口名称
extern std::vector<Text::String> GetComPorts();
/// 安装带有.inf文件的驱动
extern bool InstallDriver(const Text::String& infPath, bool* needReboot = NULL);
/// 获取已安装的应用
extern std::map<Text::String, Text::String> GetApps();
/// 检测程序是否被调试
extern bool CheckDebug();
/// 检查程序是否正在运行 使用文件独占方式
extern bool IsRunning(const Text::String& productName = "", bool lock = true);
/// 添加一个程序到防火墙规则 ps:需要管理员权限运行
extern void AddFirewallRule(const Text::String& programFile);
//是否接管异常(仅限正式环境调用 使用vs启动会被vs接管异常)
extern bool IsExceptionHijacked();
};

View File

@@ -0,0 +1,43 @@
#pragma once
#include "Text.h"
#include "FileSystem.h"
#include <Windows.h>
DECLARE_HANDLE(HZIP_Z);
/// <summary>
/// 专门负责压缩的库
/// </summary>
class Ziper {
HZIP_Z ptr = NULL;
public:
Ziper(const std::wstring& createFileName, const std::string& pwd = "");
void AddFile(const std::wstring& showFileName, const std::wstring& localFileName);
void AddFolder(const std::wstring& showFolder);
void Close();
virtual ~Ziper();
public:
static void Zip(const Text::String& _dirName, const Text::String& outFileName, const Text::String& pwd = "", std::function<bool(const Text::String&, int, int)> callback = NULL) {
std::vector<FileSystem::FileInfo> result;
Ziper zip(outFileName.unicode(), pwd);
Text::String dirName = _dirName + "/";
dirName = Path::Format(dirName);
Directory::Find(dirName, result, "*.*", true);
for (int i = 0; i < result.size(); i++)
{
Text::String ItemNmae = result[i].FileName.replace(dirName, "");
if (result[i].IsFile()) {
zip.AddFile(ItemNmae.unicode(), result[i].FileName.unicode());
}
else {
zip.AddFolder(ItemNmae.unicode());
}
if (callback) {
if (callback(ItemNmae, i, result.size())) {
break;
}
}
}
}
};

View File

@@ -0,0 +1,35 @@
//
// base64 encoding and decoding with C++.
// Version: 2.rc.09 (release candidate)
//
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#include <string>
#if __cplusplus >= 201703L
#include <string_view>
#endif // __cplusplus >= 201703L
std::string base64_encode (std::string const& s, bool url = false);
std::string base64_encode_pem (std::string const& s);
std::string base64_encode_mime(std::string const& s);
std::string base64_decode(std::string const& s, bool remove_linebreaks = false);
std::string base64_encode(unsigned char const*, size_t len, bool url = false);
#if __cplusplus >= 201703L
//
// Interface with std::string_view rather than const std::string&
// Requires C++17
// Provided by Yannic Bonenberger (https://github.com/Yannic)
//
std::string base64_encode (std::string_view s, bool url = false);
std::string base64_encode_pem (std::string_view s);
std::string base64_encode_mime(std::string_view s);
std::string base64_decode(std::string_view s, bool remove_linebreaks = false);
#endif // __cplusplus >= 201703L
#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */

View File

@@ -0,0 +1,39 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2020, 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.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 urlapi.h options.h
pkgincludedir= $(includedir)/curl
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
CS_ = $(CS_0)
checksrc:
$(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

View File

@@ -0,0 +1,714 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2021 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_compile_check_sizeof.m4 \
$(top_srcdir)/m4/curl-amissl.m4 \
$(top_srcdir)/m4/curl-bearssl.m4 \
$(top_srcdir)/m4/curl-compilers.m4 \
$(top_srcdir)/m4/curl-confopts.m4 \
$(top_srcdir)/m4/curl-functions.m4 \
$(top_srcdir)/m4/curl-gnutls.m4 \
$(top_srcdir)/m4/curl-mbedtls.m4 \
$(top_srcdir)/m4/curl-mesalink.m4 $(top_srcdir)/m4/curl-nss.m4 \
$(top_srcdir)/m4/curl-openssl.m4 \
$(top_srcdir)/m4/curl-override.m4 \
$(top_srcdir)/m4/curl-reentrant.m4 \
$(top_srcdir)/m4/curl-rustls.m4 \
$(top_srcdir)/m4/curl-schannel.m4 \
$(top_srcdir)/m4/curl-sectransp.m4 \
$(top_srcdir)/m4/curl-sysconfig.m4 \
$(top_srcdir)/m4/curl-wolfssl.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)`
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@
AR_FLAGS = @AR_FLAGS@
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@
CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
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_MQTT = @CURL_DISABLE_MQTT@
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@
CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@
CYGPATH_W = @CYGPATH_W@
DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@
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@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
GCOV = @GCOV@
GREP = @GREP@
HAVE_BROTLI = @HAVE_BROTLI@
HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@
HAVE_LDAP_SSL = @HAVE_LDAP_SSL@
HAVE_LIBZ = @HAVE_LIBZ@
HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@
HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@
HAVE_ZSTD = @HAVE_ZSTD@
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@
LIBCURL_NO_SHARED = @LIBCURL_NO_SHARED@
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_BACKENDS = @SSL_BACKENDS@
SSL_ENABLED = @SSL_ENABLED@
SSL_LIBS = @SSL_LIBS@
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
USE_ARES = @USE_ARES@
USE_BEARSSL = @USE_BEARSSL@
USE_GNUTLS = @USE_GNUTLS@
USE_HYPER = @USE_HYPER@
USE_LIBRTMP = @USE_LIBRTMP@
USE_LIBSSH = @USE_LIBSSH@
USE_LIBSSH2 = @USE_LIBSSH2@
USE_MBEDTLS = @USE_MBEDTLS@
USE_MESALINK = @USE_MESALINK@
USE_NGHTTP2 = @USE_NGHTTP2@
USE_NGHTTP3 = @USE_NGHTTP3@
USE_NGTCP2 = @USE_NGTCP2@
USE_NGTCP2_CRYPTO_GNUTLS = @USE_NGTCP2_CRYPTO_GNUTLS@
USE_NGTCP2_CRYPTO_OPENSSL = @USE_NGTCP2_CRYPTO_OPENSSL@
USE_NSS = @USE_NSS@
USE_OPENLDAP = @USE_OPENLDAP@
USE_QUICHE = @USE_QUICHE@
USE_RUSTLS = @USE_RUSTLS@
USE_SCHANNEL = @USE_SCHANNEL@
USE_SECTRANSP = @USE_SECTRANSP@
USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
USE_WIN32_CRYPTO = @USE_WIN32_CRYPTO@
USE_WIN32_LARGE_FILES = @USE_WIN32_LARGE_FILES@
USE_WIN32_SMALL_FILES = @USE_WIN32_SMALL_FILES@
USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
USE_WOLFSSH = @USE_WOLFSSH@
USE_WOLFSSL = @USE_WOLFSSL@
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 - 2020, 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.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 urlapi.h options.h
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
CS_ = $(CS_0)
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__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
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: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(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:
$(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

View File

@@ -0,0 +1,77 @@
#ifndef CURLINC_CURLVER_H
#define CURLINC_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, 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.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 - 2021 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.80.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 80
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons 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 0x075000
/*
* 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 "2021-11-10"
#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 /* CURLINC_CURLVER_H */

View File

@@ -0,0 +1,123 @@
#ifndef CURLINC_EASY_H
#define CURLINC_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, 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.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
/* Flag bits in the curl_blob struct: */
#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */
#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
struct curl_blob {
void *data;
size_t len;
unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
left zeroes */
};
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);
/*
* NAME curl_easy_upkeep()
*
* DESCRIPTION
*
* Performs connection upkeep for the given session handle.
*/
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,50 @@
#ifndef CURLINC_MPRINTF_H
#define CURLINC_MPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, 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.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 <stdarg.h>
#include <stdio.h> /* needed for FILE */
#include "curl.h" /* for CURL_EXTERN */
#ifdef __cplusplus
extern "C" {
#endif
CURL_EXTERN int curl_mprintf(const char *format, ...);
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
const char *format, ...);
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
const char *format, va_list args);
CURL_EXTERN char *curl_maprintf(const char *format, ...);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef __cplusplus
}
#endif
#endif /* CURLINC_MPRINTF_H */

View File

@@ -0,0 +1,456 @@
#ifndef CURLINC_MULTI_H
#define CURLINC_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, 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.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_RECURSIVE_API_CALL, /* an api function was called from inside a
callback */
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
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_poll()
*
* 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_poll(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_wakeup()
*
* Desc: wakes up a sleeping curl_multi_poll call.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);
/*
* 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 individual 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 null-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);
typedef enum {
/* This is the socket callback function pointer */
CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
/* This is the argument passed to the socket callback */
CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
/* set to 1 to enable pipelining for this multi handle */
CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
/* This is the timer callback function pointer */
CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
/* This is the argument passed to the timer callback */
CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
/* maximum number of entries in the connection cache */
CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
/* maximum number of (pipelining) connections to one host */
CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
/* maximum number of requests in a pipeline */
CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
/* a connection with a content-length longer than this
will not be considered for pipelining */
CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
/* a connection with a chunk length longer than this
will not be considered for pipelining */
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
/* a list of site names(+port) that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
/* a list of server types that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
/* maximum number of open connections in total */
CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
/* This is the server push callback function pointer */
CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
/* This is the argument passed to the server push callback */
CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
/* maximum number of concurrent streams to support on a connection */
CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
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. It can also decide
* to completely fail the connection.
*
* Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT
*/
#define CURL_PUSH_OK 0
#define CURL_PUSH_DENY 1
#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */
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

View File

@@ -0,0 +1,68 @@
#ifndef CURLINC_OPTIONS_H
#define CURLINC_OPTIONS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2018 - 2020, 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.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
typedef enum {
CURLOT_LONG, /* long (a range of values) */
CURLOT_VALUES, /* (a defined set or bitmask) */
CURLOT_OFF_T, /* curl_off_t (a range of values) */
CURLOT_OBJECT, /* pointer (void *) */
CURLOT_STRING, /* (char * to zero terminated buffer) */
CURLOT_SLIST, /* (struct curl_slist *) */
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
CURLOT_BLOB, /* blob (struct curl_blob *) */
CURLOT_FUNCTION /* function pointer */
} curl_easytype;
/* Flag bits */
/* "alias" means it is provided for old programs to remain functional,
we prefer another name */
#define CURLOT_FLAG_ALIAS (1<<0)
/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
to use for curl_easy_setopt() for the given id */
struct curl_easyoption {
const char *name;
CURLoption id;
curl_easytype type;
unsigned int flags;
};
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_name(const char *name);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_id (CURLoption id);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_next(const struct curl_easyoption *prev);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_OPTIONS_H */

View File

@@ -0,0 +1,33 @@
#ifndef CURLINC_STDCHEADERS_H
#define CURLINC_STDCHEADERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, 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.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 /* CURLINC_STDCHEADERS_H */

View File

@@ -0,0 +1,504 @@
#ifndef CURLINC_SYSTEM_H
#define CURLINC_SYSTEM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, 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.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_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# 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
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__SALFORDC__)
# 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
#elif defined(__BORLANDC__)
# if (__BORLANDC__ < 0x520)
# 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
# else
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TURBOC__)
# 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
#elif defined(__WATCOMC__)
# if defined(__386__)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# 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
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__POCC__)
# if (__POCC__ < 280)
# 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
# elif defined(_MSC_VER)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__LCC__)
# if defined(__e2k__) /* MCST eLbrus C Compiler */
# 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 socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# else /* Local (or Little) C Compiler */
# 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
#elif defined(__SYMBIAN32__)
# if defined(__EABI__) /* Treat all ARM compilers equally */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__CW32__)
# pragma longlong on
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__VC32__)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__MWERKS__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__MINGW32__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# 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_WS2TCPIP_H 1
#elif defined(__VMS)
# if defined(__VAX)
# 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
# else
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__OS400__)
# if defined(__ILEC400__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# 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
# endif
#elif defined(__MVS__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
# elif defined(_LP64)
# 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_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_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_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# 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)
# elif defined(_LP64)
# 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_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_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_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(TPF)
# 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
#elif defined(__TINYC__) /* also known as tcc */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# 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) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || \
defined(__sparcv8) || \
defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64) || \
defined(__amd64) || defined(__sparcv9)
# 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
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__xlc__) /* IBM xlc compiler */
# if !defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# 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
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# 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_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# 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
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
/* ===================================== */
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
#elif defined(__GNUC__) && !defined(_SCO_DS)
# if !defined(__LP64__) && \
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
defined(__XTENSA__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# 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(__e2k__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
# 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
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# 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_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
#ifdef _AIX
/* AIX needs <sys/poll.h> */
#define CURL_PULL_SYS_POLL_H
#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
/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
/* sys/poll.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_POLL_H
# include <sys/poll.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 CURLINC_OFF_T_C_HLPR2(x) x
# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
#else
# ifdef CURL_ISOCPP
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# else
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# endif
# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
#endif
#endif /* CURLINC_SYSTEM_H */

View File

@@ -0,0 +1,707 @@
#ifndef CURLINC_TYPECHECK_GCC_H
#define CURLINC_TYPECHECK_GCC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, 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.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(curlcheck_sometype_option(_curl_opt))
* if(!curlcheck_sometype(value))
* _curl_easy_setopt_err_sometype();
* block and define curlcheck_sometype_option, curlcheck_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(curlcheck_long_option(_curl_opt)) \
if(!curlcheck_long(value)) \
_curl_easy_setopt_err_long(); \
if(curlcheck_off_t_option(_curl_opt)) \
if(!curlcheck_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(curlcheck_string_option(_curl_opt)) \
if(!curlcheck_string(value)) \
_curl_easy_setopt_err_string(); \
if(curlcheck_write_cb_option(_curl_opt)) \
if(!curlcheck_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
if(!curlcheck_resolver_start_callback(value)) \
_curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!curlcheck_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!curlcheck_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!curlcheck_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!curlcheck_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!curlcheck_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!curlcheck_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!curlcheck_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(curlcheck_conv_cb_option(_curl_opt)) \
if(!curlcheck_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!curlcheck_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(curlcheck_cb_data_option(_curl_opt)) \
if(!curlcheck_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!curlcheck_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!curlcheck_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(curlcheck_postfields_option(_curl_opt)) \
if(!curlcheck_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!curlcheck_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!curlcheck_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(curlcheck_slist_option(_curl_opt)) \
if(!curlcheck_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!curlcheck_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
#define curl_easy_getinfo(handle, info, arg) \
__extension__({ \
__typeof__(info) _curl_info = info; \
if(__builtin_constant_p(_curl_info)) { \
if(curlcheck_string_info(_curl_info)) \
if(!curlcheck_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(curlcheck_long_info(_curl_info)) \
if(!curlcheck_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(curlcheck_double_info(_curl_info)) \
if(!curlcheck_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(curlcheck_slist_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(curlcheck_tlssessioninfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(curlcheck_certinfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(curlcheck_socket_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(curlcheck_off_t_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/*
* 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 CURLWARNING(id, message) \
static void __attribute__((__warning__(message))) \
__attribute__((__unused__)) __attribute__((__noinline__)) \
id(void) { __asm__(""); }
CURLWARNING(_curl_easy_setopt_err_long,
"curl_easy_setopt expects a long argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
CURLWARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a "
"string ('char *' or char[]) argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_resolver_start_callback,
"curl_easy_setopt expects a "
"curl_resolver_start_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_ioctl_cb,
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_sockopt_cb,
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_opensocket_cb,
"curl_easy_setopt expects a "
"curl_opensocket_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_progress_cb,
"curl_easy_setopt expects a curl_progress_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_debug_cb,
"curl_easy_setopt expects a curl_debug_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb,
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_conv_cb,
"curl_easy_setopt expects a curl_conv_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_seek_cb,
"curl_easy_setopt expects a curl_seek_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_cb_data,
"curl_easy_setopt expects a "
"private data pointer as argument for this option")
CURLWARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option")
CURLWARNING(_curl_easy_setopt_err_FILE,
"curl_easy_setopt expects a 'FILE *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_postfields,
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_httpost,
"curl_easy_setopt expects a 'struct curl_httppost *' "
"argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_mimepost,
"curl_easy_setopt expects a 'curl_mime *' "
"argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_slist,
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
CURLWARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to 'char *' for this info")
CURLWARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
CURLWARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_tlssessioninfo *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_certinfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_certinfo *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_socket,
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
CURLWARNING(_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 curlcheck_long_option(option) \
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define curlcheck_off_t_option(option) \
(((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
/* evaluates to true if option takes a char* argument */
#define curlcheck_string_option(option) \
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
(option) == CURLOPT_ACCEPT_ENCODING || \
(option) == CURLOPT_ALTSVC || \
(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_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_HSTS || \
(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_ISSUERCERT || \
(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_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_SASL_AUTHZID || \
(option) == CURLOPT_SERVICE_NAME || \
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 || \
(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_TLS13_CIPHERS || \
(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_AWS_SIGV4 || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \
(option) == CURLOPT_SSL_EC_CURVES || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
#define curlcheck_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \
(option) == CURLOPT_WRITEFUNCTION)
/* evaluates to true if option takes a curl_conv_callback argument */
#define curlcheck_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 curlcheck_cb_data_option(option) \
((option) == CURLOPT_CHUNK_DATA || \
(option) == CURLOPT_CLOSESOCKETDATA || \
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \
(option) == CURLOPT_HSTSREADDATA || \
(option) == CURLOPT_HSTSWRITEDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
(option) == CURLOPT_PREREQDATA || \
(option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_READDATA || \
(option) == CURLOPT_SEEKDATA || \
(option) == CURLOPT_SOCKOPTDATA || \
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_RESOLVER_START_DATA || \
(option) == CURLOPT_TRAILERDATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
#define curlcheck_postfields_option(option) \
((option) == CURLOPT_POSTFIELDS || \
(option) == CURLOPT_COPYPOSTFIELDS || \
0)
/* evaluates to true if option takes a struct curl_slist * argument */
#define curlcheck_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 || \
(option) == CURLOPT_CONNECT_TO || \
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 curlcheck_string_info(info) \
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
(info) != CURLINFO_PRIVATE)
/* evaluates to true if info expects a pointer to long argument */
#define curlcheck_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
#define curlcheck_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
#define curlcheck_slist_info(info) \
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
#define curlcheck_tlssessioninfo_info(info) \
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
/* true if info expects a pointer to struct curl_certinfo * argument */
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
/* true if info expects a pointer to struct curl_socket_t argument */
#define curlcheck_socket_info(info) \
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
/* true if info expects a pointer to curl_off_t argument */
#define curlcheck_off_t_info(info) \
(CURLINFO_OFF_T < (info))
/* typecheck helpers -- check whether given expression has requested type*/
/* For pointers, you can use the curlcheck_ptr/curlcheck_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 if expr is a pointer */
#define curlcheck_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 curlcheck_NULL(expr) \
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
/* evaluates to true if expr is type*, const type* or NULL */
#define curlcheck_ptr(expr, type) \
(curlcheck_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 curlcheck_arr(expr, type) \
(curlcheck_ptr((expr), type) || \
__builtin_types_compatible_p(__typeof__(expr), type []))
/* evaluates to true if expr is a string */
#define curlcheck_string(expr) \
(curlcheck_arr((expr), char) || \
curlcheck_arr((expr), signed char) || \
curlcheck_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 curlcheck_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 curlcheck_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 curlcheck_error_buffer(expr) \
(curlcheck_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 curlcheck_cb_data(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_ptr((expr), FILE))
#else /* be less strict */
#define curlcheck_cb_data(expr) \
curlcheck_any_ptr(expr)
#endif
/* evaluates to true if expr is of type FILE* */
#define curlcheck_FILE(expr) \
(curlcheck_NULL(expr) || \
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define curlcheck_postfields(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_arr((expr), char) || \
curlcheck_arr((expr), unsigned char))
/* helper: __builtin_types_compatible_p distinguishes between functions and
* function pointers, hide it */
#define curlcheck_cb_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_resolver_start_callback */
#define curlcheck_resolver_start_callback(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define curlcheck_read_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
curlcheck_cb_compatible((expr), curl_read_callback) || \
curlcheck_cb_compatible((expr), _curl_read_callback1) || \
curlcheck_cb_compatible((expr), _curl_read_callback2) || \
curlcheck_cb_compatible((expr), _curl_read_callback3) || \
curlcheck_cb_compatible((expr), _curl_read_callback4) || \
curlcheck_cb_compatible((expr), _curl_read_callback5) || \
curlcheck_cb_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 curlcheck_write_cb(expr) \
(curlcheck_read_cb(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
curlcheck_cb_compatible((expr), curl_write_callback) || \
curlcheck_cb_compatible((expr), _curl_write_callback1) || \
curlcheck_cb_compatible((expr), _curl_write_callback2) || \
curlcheck_cb_compatible((expr), _curl_write_callback3) || \
curlcheck_cb_compatible((expr), _curl_write_callback4) || \
curlcheck_cb_compatible((expr), _curl_write_callback5) || \
curlcheck_cb_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 curlcheck_ioctl_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
curlcheck_cb_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 curlcheck_sockopt_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
curlcheck_cb_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 curlcheck_opensocket_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
curlcheck_cb_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 curlcheck_progress_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_progress_callback) || \
curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
curlcheck_cb_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 curlcheck_debug_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_debug_callback) || \
curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
curlcheck_cb_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 curlcheck_ssl_ctx_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
curlcheck_cb_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 curlcheck_conv_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_conv_callback) || \
curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
curlcheck_cb_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 curlcheck_seek_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_seek_callback) || \
curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
curlcheck_cb_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 /* CURLINC_TYPECHECK_GCC_H */

View File

@@ -0,0 +1,133 @@
#ifndef CURLINC_URLAPI_H
#define CURLINC_URLAPI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2018 - 2021, 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.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 "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
/* the error codes for the URL API */
typedef enum {
CURLUE_OK,
CURLUE_BAD_HANDLE, /* 1 */
CURLUE_BAD_PARTPOINTER, /* 2 */
CURLUE_MALFORMED_INPUT, /* 3 */
CURLUE_BAD_PORT_NUMBER, /* 4 */
CURLUE_UNSUPPORTED_SCHEME, /* 5 */
CURLUE_URLDECODE, /* 6 */
CURLUE_OUT_OF_MEMORY, /* 7 */
CURLUE_USER_NOT_ALLOWED, /* 8 */
CURLUE_UNKNOWN_PART, /* 9 */
CURLUE_NO_SCHEME, /* 10 */
CURLUE_NO_USER, /* 11 */
CURLUE_NO_PASSWORD, /* 12 */
CURLUE_NO_OPTIONS, /* 13 */
CURLUE_NO_HOST, /* 14 */
CURLUE_NO_PORT, /* 15 */
CURLUE_NO_QUERY, /* 16 */
CURLUE_NO_FRAGMENT, /* 17 */
CURLUE_LAST
} CURLUcode;
typedef enum {
CURLUPART_URL,
CURLUPART_SCHEME,
CURLUPART_USER,
CURLUPART_PASSWORD,
CURLUPART_OPTIONS,
CURLUPART_HOST,
CURLUPART_PORT,
CURLUPART_PATH,
CURLUPART_QUERY,
CURLUPART_FRAGMENT,
CURLUPART_ZONEID /* added in 7.65.0 */
} CURLUPart;
#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
if the port number matches the
default for the scheme */
#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
missing */
#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
#define CURLU_URLDECODE (1<<6) /* URL decode on get */
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
typedef struct Curl_URL CURLU;
/*
* curl_url() creates a new CURLU handle and returns a pointer to it.
* Must be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url(void);
/*
* curl_url_cleanup() frees the CURLU handle and related resources used for
* the URL parsing. It will not free strings previously returned with the URL
* API.
*/
CURL_EXTERN void curl_url_cleanup(CURLU *handle);
/*
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
* handle must also be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
/*
* curl_url_get() extracts a specific part of the URL from a CURLU
* handle. Returns error code. The returned pointer MUST be freed with
* curl_free() afterwards.
*/
CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
char **part, unsigned int flags);
/*
* curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
* error code. The passed in string will be copied. Passing a NULL instead of
* a part string, clears that part.
*/
CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
const char *part, unsigned int flags);
/*
* curl_url_strerror() turns a CURLUcode value into the equivalent human
* readable error string. This is useful for printing meaningful error
* messages.
*/
CURL_EXTERN const char *curl_url_strerror(CURLUcode);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_URLAPI_H */

View File

@@ -0,0 +1,113 @@
#include <gzip/config.hpp>
// zlib
#include "zlib.h"
// std
#include <limits>
#include <stdexcept>
#include <string>
namespace gzip {
class Compressor
{
std::size_t max_;
int level_;
public:
Compressor(int level = Z_DEFAULT_COMPRESSION,
std::size_t max_bytes = 2000000000) // by default refuse operation if uncompressed data is > 2GB
: max_(max_bytes),
level_(level)
{
}
template <typename InputType>
void compress(InputType& output,
const char* data,
std::size_t size) const
{
#ifdef DEBUG
// Verify if size input will fit into unsigned int, type used for zlib's avail_in
if (size > std::numeric_limits<unsigned int>::max())
{
throw std::runtime_error("size arg is too large to fit into unsigned int type");
}
#endif
if (size > max_)
{
throw std::runtime_error("size may use more memory than intended when decompressing");
}
z_stream deflate_s;
deflate_s.zalloc = Z_NULL;
deflate_s.zfree = Z_NULL;
deflate_s.opaque = Z_NULL;
deflate_s.avail_in = 0;
deflate_s.next_in = Z_NULL;
// The windowBits parameter is the base two logarithm of the window size (the size of the history buffer).
// It should be in the range 8..15 for this version of the library.
// Larger values of this parameter result in better compression at the expense of memory usage.
// This range of values also changes the decoding type:
// -8 to -15 for raw deflate
// 8 to 15 for zlib
// (8 to 15) + 16 for gzip
// (8 to 15) + 32 to automatically detect gzip/zlib header (decompression/inflate only)
constexpr int window_bits = 15 + 16; // gzip with windowbits of 15
constexpr int mem_level = 8;
// The memory requirements for deflate are (in bytes):
// (1 << (window_bits+2)) + (1 << (mem_level+9))
// with a default value of 8 for mem_level and our window_bits of 15
// this is 128Kb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
if (deflateInit2(&deflate_s, level_, Z_DEFLATED, window_bits, mem_level, Z_DEFAULT_STRATEGY) != Z_OK)
{
throw std::runtime_error("deflate init failed");
}
#pragma GCC diagnostic pop
deflate_s.next_in = reinterpret_cast<z_const Bytef*>(data);
deflate_s.avail_in = static_cast<unsigned int>(size);
std::size_t size_compressed = 0;
do
{
size_t increase = size / 2 + 1024;
if (output.size() < (size_compressed + increase))
{
output.resize(size_compressed + increase);
}
// There is no way we see that "increase" would not fit in an unsigned int,
// hence we use static cast here to avoid -Wshorten-64-to-32 error
deflate_s.avail_out = static_cast<unsigned int>(increase);
deflate_s.next_out = reinterpret_cast<Bytef*>((&output[0] + size_compressed));
// From http://www.zlib.net/zlib_how.html
// "deflate() has a return value that can indicate errors, yet we do not check it here.
// Why not? Well, it turns out that deflate() can do no wrong here."
// Basically only possible error is from deflateInit not working properly
deflate(&deflate_s, Z_FINISH);
size_compressed += (increase - deflate_s.avail_out);
} while (deflate_s.avail_out == 0);
deflateEnd(&deflate_s);
output.resize(size_compressed);
}
};
inline std::string compress(const char* data,
std::size_t size,
int level = Z_DEFAULT_COMPRESSION)
{
Compressor comp(level);
std::string output;
comp.compress(output, data, size);
return output;
}
} // namespace gzip

View File

@@ -0,0 +1,5 @@
#pragma once
#ifndef ZLIB_CONST
#define ZLIB_CONST
#endif

View File

@@ -0,0 +1,105 @@
#include <gzip/config.hpp>
// zlib
#include "zlib.h"
// std
#include <limits>
#include <stdexcept>
#include <string>
namespace gzip {
class Decompressor
{
std::size_t max_;
public:
Decompressor(std::size_t max_bytes = 1000000000) // by default refuse operation if compressed data is > 1GB
: max_(max_bytes)
{
}
template <typename OutputType>
void decompress(OutputType& output,
const char* data,
std::size_t size) const
{
z_stream inflate_s;
inflate_s.zalloc = Z_NULL;
inflate_s.zfree = Z_NULL;
inflate_s.opaque = Z_NULL;
inflate_s.avail_in = 0;
inflate_s.next_in = Z_NULL;
// The windowBits parameter is the base two logarithm of the window size (the size of the history buffer).
// It should be in the range 8..15 for this version of the library.
// Larger values of this parameter result in better compression at the expense of memory usage.
// This range of values also changes the decoding type:
// -8 to -15 for raw deflate
// 8 to 15 for zlib
// (8 to 15) + 16 for gzip
// (8 to 15) + 32 to automatically detect gzip/zlib header
constexpr int window_bits = 15 + 32; // auto with windowbits of 15
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
if (inflateInit2(&inflate_s, window_bits) != Z_OK)
{
throw std::runtime_error("inflate init failed");
}
#pragma GCC diagnostic pop
inflate_s.next_in = reinterpret_cast<z_const Bytef*>(data);
#ifdef DEBUG
// Verify if size (long type) input will fit into unsigned int, type used for zlib's avail_in
std::uint64_t size_64 = size * 2;
if (size_64 > std::numeric_limits<unsigned int>::max())
{
inflateEnd(&inflate_s);
throw std::runtime_error("size arg is too large to fit into unsigned int type x2");
}
#endif
if (size > max_ || (size * 2) > max_)
{
inflateEnd(&inflate_s);
throw std::runtime_error("size may use more memory than intended when decompressing");
}
inflate_s.avail_in = static_cast<unsigned int>(size);
std::size_t size_uncompressed = 0;
do
{
std::size_t resize_to = size_uncompressed + 2 * size;
if (resize_to > max_)
{
inflateEnd(&inflate_s);
throw std::runtime_error("size of output string will use more memory then intended when decompressing");
}
output.resize(resize_to);
inflate_s.avail_out = static_cast<unsigned int>(2 * size);
inflate_s.next_out = reinterpret_cast<Bytef*>(&output[0] + size_uncompressed);
int ret = inflate(&inflate_s, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR)
{
std::string error_msg = inflate_s.msg;
inflateEnd(&inflate_s);
throw std::runtime_error(error_msg);
}
size_uncompressed += (2 * size - inflate_s.avail_out);
} while (inflate_s.avail_out == 0);
inflateEnd(&inflate_s);
output.resize(size_uncompressed);
}
};
inline std::string decompress(const char* data, std::size_t size)
{
Decompressor decomp;
std::string output;
decomp.decompress(output, data, size);
return output;
}
} // namespace gzip

View File

@@ -0,0 +1,22 @@
#include <cstdlib>
namespace gzip {
// These live in gzip.hpp because it doesnt need to use deps.
// Otherwise, they would need to live in impl files if these methods used
// zlib structures or functions like inflate/deflate)
inline bool is_compressed(const char* data, std::size_t size)
{
return size > 2 &&
(
// zlib
(
static_cast<uint8_t>(data[0]) == 0x78 &&
(static_cast<uint8_t>(data[1]) == 0x9C ||
static_cast<uint8_t>(data[1]) == 0x01 ||
static_cast<uint8_t>(data[1]) == 0xDA ||
static_cast<uint8_t>(data[1]) == 0x5E)) ||
// gzip
(static_cast<uint8_t>(data[0]) == 0x1F && static_cast<uint8_t>(data[1]) == 0x8B));
}
} // namespace gzip

View File

@@ -0,0 +1,16 @@
#pragma once
/// The major version number
#define GZIP_VERSION_MAJOR 1
/// The minor version number
#define GZIP_VERSION_MINOR 0
/// The patch number
#define GZIP_VERSION_PATCH 0
/// The complete version number
#define GZIP_VERSION_CODE (GZIP_VERSION_MAJOR * 10000 + GZIP_VERSION_MINOR * 100 + GZIP_VERSION_PATCH)
/// Version number as string
#define GZIP_VERSION_STRING "1.0.0"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
// 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)
#pragma pack()
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,62 @@
// 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)
#pragma pack()
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

View File

@@ -0,0 +1,406 @@
// 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)
#pragma pack()
namespace Json {
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
* Value.
*
* \deprecated Use CharReader and CharReaderBuilder.
*/
class JSON_API Reader {
public:
using Char = char;
using Location = const Char*;
/** \brief An error tagged with where in the JSON text it was encountered.
*
* The offsets give the [start, limit) range of bytes within the text. Note
* that this is bytes, not codepoints.
*/
struct StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
String message;
};
/** \brief Constructs a Reader allowing all features for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
Reader();
/** \brief Constructs a Reader allowing the specified feature set for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
Reader(const Features& features);
/** \brief Read a Value from a <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.
* - `"skipBom": false or true`
* - If true, if the input starts with the Unicode byte order mark (BOM),
* it is skipped.
*
* You can examine 'settings_` yourself to see the defaults. You can also
* write and read them just like any JSON Value.
* \sa setDefaults()
*/
Json::Value settings_;
CharReaderBuilder();
~CharReaderBuilder() override;
CharReader* newCharReader() const override;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
*/
bool validate(Json::Value* invalid) const;
/** A simple way to update a specific setting.
*/
Value& operator[](const String& key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
*/
static void setDefaults(Json::Value* settings);
/** Same as old Features::strictMode().
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
*/
static void strictMode(Json::Value* settings);
};
/** Consume entire stream and use its begin/end.
* Someday we might have a real StreamReader, but for now this
* is convenient.
*/
bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
String* errs);
/** \brief Read from 'sin' into 'root'.
*
* Always keep comments from the input JSON.
*
* This can be used to read a file into a particular sub-object.
* For example:
* \code
* Json::Value root;
* cin >> root["dir"]["file"];
* cout << root;
* \endcode
* Result:
* \verbatim
* {
* "dir": {
* "file": {
* // The input stream JSON would be nested here.
* }
* }
* }
* \endverbatim
* \throw std::exception on parse error.
* \see Json::operator<<()
*/
JSON_API IStream& operator>>(IStream&, Value&);
} // namespace Json
#pragma pack(pop)
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // JSON_READER_H_INCLUDED

View File

@@ -0,0 +1,961 @@
// 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 4275)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma pack(push)
#pragma pack()
/** \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 toString() const;
String toStyledString() const;
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
/// \brief Returns a reference to the first element in the `Value`.
/// Requires that this value holds an array or json object, with at least one element.
const Value& front() const;
/// \brief Returns a reference to the first element in the `Value`.
/// Requires that this value holds an array or json object, with at least one element.
Value& front();
/// \brief Returns a reference to the last element in the `Value`.
/// Requires that value holds an array or json object, with at least one element.
const Value& back() const;
/// \brief Returns a reference to the last element in the `Value`.
/// Requires that this value holds an array or json object, with at least one element.
Value& back();
// 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*() const { return const_cast<reference>(deref()); }
pointer operator->() const { return const_cast<pointer>(&deref()); }
};
inline void swap(Value& a, Value& b) { a.swap(b); }
inline const Value& Value::front() const { return *begin(); }
inline Value& Value::front() { return *begin(); }
inline const Value& Value::back() const { return *(--end()); }
inline Value& Value::back() { return *(--end()); }
} // 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

View File

@@ -0,0 +1,28 @@
#ifndef JSON_VERSION_H_INCLUDED
#define JSON_VERSION_H_INCLUDED
// Note: version must be updated in three places when doing a release. This
// annoying process ensures that amalgamate, CMake, and meson all report the
// correct version.
// 1. /meson.build
// 2. /include/json/version.h
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.5"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 5
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
#ifdef JSONCPP_USING_SECURE_MEMORY
#undef JSONCPP_USING_SECURE_MEMORY
#endif
#define JSONCPP_USING_SECURE_MEMORY 0
// If non-zero, the library zeroes any memory that it has allocated before
// it frees its memory.
#endif // JSON_VERSION_H_INCLUDED

View File

@@ -0,0 +1,370 @@
// 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)
#pragma pack()
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.
* - "emitUTF8": false or true
* - If true, outputs raw UTF8 strings instead of escaping them.
* You can examine 'settings_` yourself
* to see the defaults. You can also write and read them just like any
* JSON Value.
* \sa setDefaults()
*/
Json::Value settings_;
StreamWriterBuilder();
~StreamWriterBuilder() override;
/**
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
StreamWriter* newStreamWriter() const override;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
*/
bool validate(Json::Value* invalid) const;
/** A simple way to update a specific setting.
*/
Value& operator[](const String& key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
*/
static void setDefaults(Json::Value* settings);
};
/** \brief Abstract class for writers.
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
*/
class JSON_API Writer {
public:
virtual ~Writer();
virtual String write(const Value& root) = 0;
};
/** \brief Outputs a Value in <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 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 outputted according to their
*#CommentPlacement.
*
* \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder.
*/
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API
StyledWriter : public Writer {
public:
StyledWriter();
~StyledWriter() override = default;
public: // overridden from Writer
/** \brief Serialize a Value in <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 outputted according to their
#CommentPlacement.
*
* \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder.
*/
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API
StyledStreamWriter {
public:
/**
* \param indentation Each level will be indented by this amount extra.
*/
StyledStreamWriter(String indentation = "\t");
~StyledStreamWriter() = default;
public:
/** \brief Serialize a Value in <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

Some files were not shown because too many files have changed in this diff Show More