diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..bfa1cc6 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "C:/Users/lnk/Downloads/mingw32/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8af2ea9 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "d:/canneng/云前置移植项目/zw/Linux_Front1056/LFtid1056", + "program": "d:/canneng/云前置移植项目/zw/Linux_Front1056/LFtid1056/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..044d393 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,64 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false, + "files.associations": { + "new": "cpp", + "mutex": "cpp", + "ostream": "cpp" + } +} \ No newline at end of file diff --git a/LFtid1056/build.sh b/LFtid1056/build.sh new file mode 100644 index 0000000..b666e3f --- /dev/null +++ b/LFtid1056/build.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +TARGET="cloud-front-test" +SRC_DIR="./cloudfront/code" +LIB_DIR="./cloudfront/lib" +OUT_DIR="./bin" + +# 创建输出目录 +mkdir -p "$OUT_DIR" + +# 源文件,所有主 cpp 文件 +SRC="$SRC_DIR/main.cpp \ +$SRC_DIR/worker.cpp \ +$SRC_DIR/log4.cpp \ +$SRC_DIR/cfg_parser.cpp \ +$SRC_DIR/interface.cpp \ +$SRC_DIR/rocketmq.cpp \ +$SRC_DIR/tinyxml2.cpp \ +./client2.cpp \ +./dealMsg.cpp \ +./main_thread.cpp \ +./PQSMsg.cpp " + +INCLUDE_DIRS="-I$SRC_DIR \ +-I$SRC_DIR/nlohmann \ +-I$SRC_DIR/curl \ +-I$SRC_DIR/log4cplus \ +-I$SRC_DIR/rocketmq \ +-I$SRC_DIR \ +-I./lib/libuv-v1.51.0/include \ +-I. " + +LIB_DIRS="-L$LIB_DIR -L/usr/lib64 -L/usr/local/lib" + +LIBS="-lcurl -lssl -lcrypto \ +-lpthread -ldl -lrt \ +-llog4cplus \ +-lstdc++fs \ +-lz \ +./libuv.a -pthread" + +# 如果有静态 rocketmq 库就加上 +if [ -f "$LIB_DIR/librocketmq.a" ]; then + LIBS="$LIB_DIR/librocketmq.a $LIBS" +fi + +# 判断是否为 debug 版本 +if [[ "$1" == "debug" ]]; then + CXXFLAGS="-std=c++11 -g -O0" + TARGET="${TARGET}d" + echo "🟢 编译调试版本 (-g -O0)" +else + CXXFLAGS="-std=c++11 -O2 -static-libstdc++ -static-libgcc" + echo "🔵 编译正式版本 (-O2 -static)" +fi + +# 编译命令 +g++ $CXXFLAGS $SRC $INCLUDE_DIRS $LIB_DIRS $LIBS -o "$OUT_DIR/$TARGET" + +# 编译结果检查 +if [ $? -eq 0 ]; then + echo "✅ 编译成功,生成可执行文件: $OUT_DIR/$TARGET" + echo "🔍 依赖库检查:" + ldd "$OUT_DIR/$TARGET" || echo "是静态编译程序 ✔" +else + echo "❌ 编译失败" +fi \ No newline at end of file diff --git a/LFtid1056/cloudfront/boot/feservice b/LFtid1056/cloudfront/boot/feservice new file mode 100644 index 0000000..95db549 --- /dev/null +++ b/LFtid1056/cloudfront/boot/feservice @@ -0,0 +1,22 @@ +#!/bin/bash + +case "$1" in + 'start') + $FEP_ENV/boot/start_fe.sh + ;; + + 'stop') + $FEP_ENV/boot/stop_fe.sh + ;; + + 'restart') + $FEP_ENV/boot/stop_fe.sh + $FEP_ENV/boot/start_fe.sh + ;; + + *) + echo "Usage: feservice start|stop|restart" + exit 1 + ;; +esac + diff --git a/LFtid1056/cloudfront/boot/ps_fe.sh b/LFtid1056/cloudfront/boot/ps_fe.sh new file mode 100644 index 0000000..62b4812 --- /dev/null +++ b/LFtid1056/cloudfront/boot/ps_fe.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# @file: $RCSfile: ps_fe.sh,v $ +# @brief: $ϵͳӦʾ̽ű +# @version: $Revision: 1.2 $ +# @date: $Date: 2017/02/23 03:42:58 $ +# @author: $Author: zhanchengguo $ +# @state: $State: Exp $ +# @latest: $Id: ps_fe.sh,v 1.2 2017/02/23 03:42:58 zhanchengguo Exp $ + +echo "" + +RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf" + +while read LINE ; do + if [ -n "$LINE" ] ; then + if [ ${LINE:0:1} != "#" ]; then + BINPATH=`echo $LINE | awk -F '^' '{printf $1}'` + BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $BINPATH + BIN=`echo $LINE | awk -F '^' '{printf $2}'` + BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $BIN + SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'` + SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $SPECIAL + + SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'` + SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $SLEEPSEC + STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'` + STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $STARTFLAG + +# if [ "`echo $STARTFLAG`" != "IGNORE_START" ]; then + CMD_STR=" ps -w | grep `echo "'"``echo $BIN``echo "'"` | grep -v 'grep'" + BIN2=`echo $BIN` + ps -ef | grep "$BIN2" | grep -v 'grep' +# fi + fi + fi +done < $RUNTIME_CF_FILE + +echo "" diff --git a/LFtid1056/cloudfront/boot/start_fe.sh b/LFtid1056/cloudfront/boot/start_fe.sh new file mode 100644 index 0000000..bf19973 --- /dev/null +++ b/LFtid1056/cloudfront/boot/start_fe.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# @file: $RCSfile: start_fe.sh,v $ +# @brief: $ϵͳӦű +# @version: $Revision: 1.1 $ +# @date: $Date: 2018/12/26 07:19:31 $ +# @author: $Author: lizhongming $ +# @state: $State: Exp $ +# @latest: $Id: start_fe.sh,v 1.1 2018/12/26 07:19:31 lizhongming Exp $ + +QTDIR=/qt-4.8.4 +export QTDIR + +FEP_ENV=/FeProject +export FEP_ENV + +PATH=$FEP_ENV/bin:$QTDIR/bin:$PATH +export PATH + +LD_LIBRARY_PATH=$FEP_ENV/lib:$FEP_ENV/lib3rd:$QTDIR/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH + +check_log_file() +{ +if [ -n "$1" ] ; then + FILE_SIZE=0 + FILE_SIZE=`du $1 | awk '{print $1}'` + if [ $FILE_SIZE -ge 5120 ] + then + if [ -f "$1".3 ]; then + rm -f "$1".3 + fi + if [ -f "$1".2 ]; then + mv "$1".2 "$1".3 + fi + if [ -f "$1".1 ]; then + mv "$1".1 "$1".2 + fi + mv "$1" "$1".1 + fi +fi +} + +LOGFILE="$FEP_ENV/dat/log/start_fe.log" +check_log_file $LOGFILE + + +echo "" ; echo "" +echo "******* `date "+%F %R:%S"` Start Processes *******" +echo "" >>"$LOGFILE" +echo "" >>"$LOGFILE" +echo "******* `date "+%F %R:%S"` Start Processes *******" >>"$LOGFILE" +#sysctl -w "kernel.core_pattern=/usr/local/sascore/%e.%p.%t.core" &> /dev/null + +#ִг·^ִг ^в^״в^״ǰʱ^Ƿ^״Ƿ + +RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf" + +echo "Using config file name: $RUNTIME_CF_FILE" +echo "Using config file name: $RUNTIME_CF_FILE">>"$LOGFILE" +CURDIR=`pwd` +while read LINE ; do + if [ -n "$LINE" ] ; then + if [ ${LINE:0:1} != "#" ]; then + BINPATH=`echo $LINE | awk -F '^' '{printf $1}'` + BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $BINPATH + BIN=`echo $LINE | awk -F '^' '{printf $2}'` + BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $BIN + SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'` + SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $SPECIAL + + SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'` + SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $SLEEPSEC + STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'` + STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $STARTFLAG + + RESTARTFLAG=`echo $LINE | awk -F '^' '{printf $6}'` + RESTARTFLAG=`echo "$RESTARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` + echo $RESTARTFLAG + + if [ "$RESTARTFLAG" = "IGNORE_RESTART" ]; then +# echo "" ; + CMD_STR=" sleep `echo $SLEEPSEC` " + echo "$CMD_STR" + echo "$CMD_STR" >>"$LOGFILE" + $CMD_STR + + CMD_STR=" `echo $BINPATH``echo $BIN` `echo $SPECIAL` " + echo "$CMD_STR" + echo "$CMD_STR" >>"$LOGFILE" + $CMD_STR &>/dev/null + fi + fi + fi +done < $RUNTIME_CF_FILE + +cd $CURDIR + +DT=`date "+%F %R:%S.%N"` +echo "******* ${DT:0:23} Start Processes Succcessfully *******" +echo "******* ${DT:0:23} Start Processes Succcessfully *******" >>"$LOGFILE" diff --git a/LFtid1056/cloudfront/boot/stop_fe.sh b/LFtid1056/cloudfront/boot/stop_fe.sh new file mode 100644 index 0000000..acf99ff --- /dev/null +++ b/LFtid1056/cloudfront/boot/stop_fe.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# @file: $RCSfile: stop_fe.sh,v $ +# @brief: $ϵͳӦֹͣ̽ű +# @version: $Revision: 1.5 $ +# @date: $Date: 2017/02/28 08:40:43 $ +# @author: $Author: zhanchengguo $ +# @state: $State: Exp $ +# @latest: $Id: stop_fe.sh,v 1.5 2017/02/28 08:40:43 zhanchengguo Exp $ + +check_log_file() +{ +if [ -n "$1" ] ; then + FILE_SIZE=0 + FILE_SIZE=`du $1 | awk '{print $1}'` + if [ $FILE_SIZE -ge 5120 ] + then + if [ -f "$1".3 ]; then + rm -f "$1".3 + fi + if [ -f "$1".2 ]; then + mv "$1".2 "$1".3 + fi + if [ -f "$1".1 ]; then + mv "$1".1 "$1".2 + fi + mv "$1" "$1".1 + fi +fi +} + +LOGFILE="$FEP_ENV/dat/log/start_fe.log" +check_log_file $LOGFILE + +echo "" ; echo "" +echo "****** `date "+%F %R:%S"` Stop Processes ******" +echo "" >>"$LOGFILE" +echo "" >>"$LOGFILE" +echo "****** `date "+%F %R:%S"` Stop Processes ******" >>"$LOGFILE" + +RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf" + +#cat $RUNTIME_CF_FILE |tac > /tmp/runtime.cf +sed '1!G;h;$!d' $RUNTIME_CF_FILE > /tmp/runtime.cf + +echo "Using config file name: $RUNTIME_CF_FILE" +echo "Using config file name: $RUNTIME_CF_FILE">>"$LOGFILE" + +while read LINE ; do + if [ -n "$LINE" ] ; then + if [ ${LINE:0:1} != "#" ]; then + BINPATH=`echo $LINE | awk -F '^' '{printf $1}'` + BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $BINPATH + BIN=`echo $LINE | awk -F '^' '{printf $2}'` + BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $BIN + SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'` + SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $SPECIAL + + SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'` + SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $SLEEPSEC + STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'` + STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"` +# echo $STARTFLAG + + if [ "`echo $STARTFLAG`" != "IGNORE_START" ]; then +# echo "" +# echo "" >>"$LOGFILE" + CMD_STR=" ps -w | grep `echo "'"``echo $BIN``echo "'"` | grep -v 'grep'" + BIN2=`echo $BIN` + BIN3=`echo $BIN |awk '{print$1}'` +# CMD_STR="killall `echo $BIN | awk '{print$1}'` 2>&1 " + PIDSTR=`ps -ef | grep "$BIN2" | grep -v 'grep'` + if [ -n "$PIDSTR" ] ; then + if [ "$BIN3" == "fe_main" ]; then + CMD_STR=" sleep 3 " + echo "$CMD_STR" + echo "$CMD_STR" >>"$LOGFILE" + $CMD_STR + fi + + CMD_STR="kill -15 `echo $PIDSTR | awk '{print$2}'` " + echo " Kill process: \"$BIN\" with PID `echo $PIDSTR | awk '{print$2}'`" + echo " Kill process: \"$BIN\" with PID `echo $PIDSTR | awk '{print$2}'`" >>"$LOGFILE" + echo " Executing: $CMD_STR" + echo " Executing: $CMD_STR" >>"$LOGFILE" + CMD_RESULT=`$CMD_STR` + if [ -n "$CMD_RESULT" ] ; then + echo "$CMD_RESULT" + echo "$CMD_RESULT" >>"$LOGFILE" + fi + + else + echo " Process \"$BIN\" not running." + fi + fi + fi + fi +done < /tmp/runtime.cf + +DT=`date "+%F %R:%S.%N"` +echo "****** ${DT:0:23} Stop Processes Succcessfully ******" +echo "" >>"$LOGFILE" +echo "****** ${DT:0:23} Stop Processes Succcessfully ******" >>"$LOGFILE" diff --git a/LFtid1056/cloudfront/build.sh b/LFtid1056/cloudfront/build.sh new file mode 100644 index 0000000..797bf77 --- /dev/null +++ b/LFtid1056/cloudfront/build.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +TARGET="cloud-front" +SRC_DIR="./code" +LIB_DIR="./lib" +OUT_DIR="./bin" + +# 创建输出目录 +mkdir -p "$OUT_DIR" + +# 源文件,所有主 cpp 文件 +SRC="$SRC_DIR/main.cpp \ +$SRC_DIR/worker.cpp \ +$SRC_DIR/log4.cpp \ +$SRC_DIR/cfg_parser.cpp \ +$SRC_DIR/interface.cpp \ +$SRC_DIR/rocketmq.cpp \ +$SRC_DIR/tinyxml2.cpp" + +INCLUDE_DIRS="-I$SRC_DIR \ +-I$SRC_DIR/nlohmann \ +-I$SRC_DIR/curl \ +-I$SRC_DIR/log4cplus \ +-I$SRC_DIR/rocketmq \ +-I$SRC_DIR" # tinyxml2.h 所在目录 + +LIB_DIRS="-L$LIB_DIR -L/usr/lib64 -L/usr/local/lib" + +LIBS="-lcurl -lssl -lcrypto \ +-lpthread -ldl -lrt \ +-llog4cplus \ +-lstdc++fs \ +-lz" + +# 如果有静态 rocketmq 库就加上 +if [ -f "$LIB_DIR/librocketmq.a" ]; then + LIBS="$LIB_DIR/librocketmq.a $LIBS" +fi + +# 判断是否为 debug 版本 +if [[ "$1" == "debug" ]]; then + CXXFLAGS="-std=c++11 -g -O0" + TARGET="${TARGET}d" + echo "🟢 编译调试版本 (-g -O0)" +else + CXXFLAGS="-std=c++11 -O2 -static-libstdc++ -static-libgcc" + echo "🔵 编译正式版本 (-O2 -static)" +fi + +# 编译命令 +g++ $CXXFLAGS $SRC $INCLUDE_DIRS $LIB_DIRS $LIBS -o "$OUT_DIR/$TARGET" + +# 编译结果检查 +if [ $? -eq 0 ]; then + echo "✅ 编译成功,生成可执行文件: $OUT_DIR/$TARGET" + echo "🔍 依赖库检查:" + ldd "$OUT_DIR/$TARGET" || echo "是静态编译程序 ✔" +else + echo "❌ 编译失败" +fi \ No newline at end of file diff --git a/LFtid1056/cloudfront/code/cfg_parser.cpp b/LFtid1056/cloudfront/code/cfg_parser.cpp new file mode 100644 index 0000000..13af018 --- /dev/null +++ b/LFtid1056/cloudfront/code/cfg_parser.cpp @@ -0,0 +1,2617 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include //流解析 +#include //写去重的设备类型 +#include //打开文件 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////////////////////////// + +#include "nlohmann/json.hpp" +#include "curl/curl.h" +#include "log4cplus/log4.h" //关键上送日志 +#include "interface.h" //台账结构 +#include "tinyxml2.h" +#include "rocketmq.h" + +///////////////////////////////////////////////////////////////////////////////////////////////// + +using namespace std; + +///////////////////////////////////////////////////////////////////////////////////////////////// + +//进程标识 +extern std::string subdir; +extern int g_front_seg_index; +extern int g_front_seg_num; +extern unsigned int g_node_id; //前置程序类型(100-600) + +//初始化完成标识 +extern int INITFLAG; + +//线程阻塞计数 +extern uint32_t g_ontime_blocked_times; + +//台账锁 +extern std::mutex ledgermtx; + +//队列 +extern std::mutex queue_data_list_mutex; //queue发送数据锁 +extern std::list queue_data_list; //queue发送数据链表 + +extern int three_secs_enabled; + +extern std::vector terminal_devlist; + +extern std::map xmlinfo_list;//保存所有型号对应的icd映射文件解析数据 +extern XmlConfig xmlcfg;//星形接线xml节点解析的数据-默认映射文件解析数据 +extern std::list topicList; //队列发送主题链表 + +extern XmlConfig xmlcfg2;//角型接线xml节点解析的数据-默认映射文件解析数据 +extern std::list topicList2; //角型接线发送主题链表 +extern std::map xmlinfo_list2;//保存所有型号角形接线对应的icd映射文件解析数据 + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//补招 +std::list g_StatisticLackList; //日志补招结构类链表 +std::mutex g_StatisticLackList_list_mutex; //补招队列数据锁 + +std::string DEFAULT_CONFIG_FN = "Default_Config.xml"; //默认映射文件 +std::string LEDGER_UPDATE_FN = "LedgerUpdate.log"; //台账更新本地记录日志 + +//一个终端最大检测点数 +const int MAX_CPUNO = 10; + +//角型接线标志,0不存在角形接线,1存在角形接线 +int isdelta_flag = 0; + +//多前置flag:1为开启,0为关闭 +int MULTIPLE_NODE_FLAG = 1; + +//终端台账数量配置 +int IED_COUNT = 300; //默认300 + +//前置标志 +std::string FRONT_INST = ""; +std::string FRONT_IP = ""; + +//终端和监测点的状态筛选 +std::string TERMINAL_STATUS = ""; +std::string MONITOR_STATUS = ""; +std::string ICD_FLAG = ""; + +//web接口 +std::string WEB_DEVICE = ""; +std::string WEB_ICD = ""; +std::string WEB_EVENT = ""; +std::string WEB_FILEUPLOAD = ""; +std::string WEB_FILEDOWNLOAD = ""; + +////////////////////////////////////////////////////////////////////////////mq配置 + +//备用 +std::string BROKER_LIST = ""; + +//通用主题 +std::string TOPIC_STAT = ""; +std::string TOPIC_PST = ""; +std::string TOPIC_PLT = ""; +std::string TOPIC_EVENT = ""; +std::string TOPIC_ALARM = ""; +std::string TOPIC_SNG = ""; +std::string TOPIC_RTDATA = ""; + +//通用tagkey +std::string G_ROCKETMQ_TAG = "";//tag +std::string G_ROCKETMQ_KEY = "";//key + +//生产者 +std::string G_ROCKETMQ_PRODUCER = ""; //rocketmq producer +std::string G_MQPRODUCER_IPPORT = ""; //rocketmq ip+port +std::string G_MQPRODUCER_ACCESSKEY = ""; //rocketmq 认证 +std::string G_MQPRODUCER_SECRETKEY = ""; //rocketmq 秘钥 + +//日志 +std::string G_LOG_TOPIC = "";//topie +std::string G_LOG_TAG = "";//tag +std::string G_LOG_KEY = "";//key +//终端连接 +std::string G_CONNECT_TOPIC = "";//consumer topie +std::string G_CONNECT_TAG = "";//consumer tag +std::string G_CONNECT_KEY = "";//consumer key +//心跳 +std::string Heart_Beat_Topic = ""; +std::string Heart_Beat_Tag = ""; +std::string Heart_Beat_Key = ""; +//消息响应 +std::string Topic_Reply_Topic = ""; +std::string Topic_Reply_Tag = ""; +std::string Topic_Reply_Key = ""; + +//消费者 +std::string G_ROCKETMQ_CONSUMER = "";//rocketmq consumer +std::string G_MQCONSUMER_IPPORT = "";//consumer ip+port +std::string G_MQCONSUMER_ACCESSKEY = ""; +std::string G_MQCONSUMER_SECRETKEY = ""; +std::string G_MQCONSUMER_CHANNEL = ""; +//实时数据请求 +std::string G_MQCONSUMER_TOPIC_RT = "";//consumer topie +std::string G_MQCONSUMER_TAG_RT = "";//consumer tag +std::string G_MQCONSUMER_KEY_RT = "";//consumer key +//台账更新请求 +std::string G_MQCONSUMER_TOPIC_UD = "";//consumer topie +std::string G_MQCONSUMER_TAG_UD = "";//consumer tag +std::string G_MQCONSUMER_KEY_UD = "";//consumer key +//补招数据请求 +std::string G_MQCONSUMER_TOPIC_RC = "";//consumer topie +std::string G_MQCONSUMER_TAG_RC = "";//consumer tag +std::string G_MQCONSUMER_KEY_RC = "";//consumer key +//进程控制请求 +std::string G_MQCONSUMER_TOPIC_SET = "";//consumer topie +std::string G_MQCONSUMER_TAG_SET = "";//consumer tag +std::string G_MQCONSUMER_KEY_SET = "";//consumer key +//日志数据请求 +std::string G_MQCONSUMER_TOPIC_LOG = "";//consumer topie +std::string G_MQCONSUMER_TAG_LOG = "";//consumer tag +std::string G_MQCONSUMER_KEY_LOG = "";//consumer key + +//测试用的主题 +std::string G_ROCKETMQ_TOPIC_TEST = "";//topie +std::string G_ROCKETMQ_TAG_TEST = "";//tag +std::string G_ROCKETMQ_KEY_TEST = "";//key + +//测试相关配置 +int G_TEST_FLAG = 0; +int G_TEST_NUM = 0; +int G_TEST_TYPE = 0; +int TEST_PORT = 11000; //用于当前进程登录测试shell的端口 +std::string G_TEST_LIST = ""; //测试用的发送实际数据的终端列表 +std::vector TESTARRAY; //解析的列表数组 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////其他文件定义的函数引用声明 + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////当前文件函数声明 + +void create_ledger_log(trigger_update_xml_t* ledger_update_xml); +void print_trigger_update_xml(const trigger_update_xml_t& trigger_update); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////辅助函数 + +//去除字符串前后空格 +static void trim(std::string& s) { + auto not_space = [](int ch) { return !std::isspace(ch); }; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), not_space)); + s.erase(std::find_if(s.rbegin(), s.rend(), not_space).base(), s.end()); +} + +//判断空格 +bool is_blank(const std::string& str) +{ + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + { + if (!std::isspace(*it)) { + return false; + } + } + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////配置文件读取 + +//将 G_TEST_LIST 按逗号分割,填充 TESTARRAY +static void parseTestList() { + TESTARRAY.clear(); + std::istringstream iss(G_TEST_LIST); + std::string token; + while (std::getline(iss, token, ',')) { + trim(token); + if (!token.empty()) { + TESTARRAY.push_back(token); + } + } +} + +//简易映射方式解析配置文件文件 +void loadConfig(const std::string& filename) { + // 1. 构造“节.键 → 变量地址”映射表 + std::unordered_map strMap; + std::unordered_map intMap; + + // [Flag] + strMap["Flag.FrontInst"] = &FRONT_INST; + strMap["Flag.FrontIP"] = &FRONT_IP; + + // [Ledger] + intMap["Ledger.IedCount"] = &IED_COUNT; + strMap["Ledger.TerminalStatus"]= &TERMINAL_STATUS; + strMap["Ledger.MonitorStatus"] = &MONITOR_STATUS; + strMap["Ledger.IcdFlag"] = &ICD_FLAG; + + // [Http] + strMap["Http.WebDevice"] = &WEB_DEVICE; + strMap["Http.WebIcd"] = &WEB_ICD; + strMap["Http.WebEvent"] = &WEB_EVENT; + strMap["Http.WebFileupload"] = &WEB_FILEUPLOAD; + strMap["Http.WebFiledownload"]= &WEB_FILEDOWNLOAD; + + // [Queue] + strMap["Queue.BrokerList"] = &BROKER_LIST; + strMap["Queue.RTDataTopic"] = &TOPIC_RTDATA; + strMap["Queue.HisTopic"] = &TOPIC_STAT; + strMap["Queue.PSTTopic"] = &TOPIC_PST; + strMap["Queue.PLTTopic"] = &TOPIC_PLT; + strMap["Queue.EventTopic"] = &TOPIC_EVENT; + strMap["Queue.AlmTopic"] = &TOPIC_ALARM; + strMap["Queue.SngTopic"] = &TOPIC_SNG; + strMap["Queue.QUEUE_TAG"] = &G_ROCKETMQ_TAG; + strMap["Queue.QUEUE_KEY"] = &G_ROCKETMQ_KEY; + + // [RocketMq] —— 生产者 + strMap["RocketMq.producer"] = &G_ROCKETMQ_PRODUCER; + strMap["RocketMq.Ipport"] = &G_MQPRODUCER_IPPORT; + strMap["RocketMq.AccessKey"] = &G_MQPRODUCER_ACCESSKEY; + strMap["RocketMq.SecretKey"] = &G_MQPRODUCER_SECRETKEY; + + strMap["RocketMq.LOGTopic"] = &G_LOG_TOPIC; + strMap["RocketMq.LOGTag"] = &G_LOG_TAG; + strMap["RocketMq.LOGKey"] = &G_LOG_KEY; + + strMap["RocketMq.CONNECTTopic"] = &G_CONNECT_TOPIC; + strMap["RocketMq.CONNECTTag"] = &G_CONNECT_TAG; + strMap["RocketMq.CONNECTKey"] = &G_CONNECT_KEY; + + strMap["RocketMq.Heart_Beat_Topic"] = &Heart_Beat_Topic; + strMap["RocketMq.Heart_Beat_Tag"] = &Heart_Beat_Tag; + strMap["RocketMq.Heart_Beat_Key"] = &Heart_Beat_Key; + + strMap["RocketMq.Topic_Reply_Topic"] = &Topic_Reply_Topic; + strMap["RocketMq.Topic_Reply_Tag"] = &Topic_Reply_Tag; + strMap["RocketMq.Topic_Reply_Key"] = &Topic_Reply_Key; + + // [RocketMq] —— 消费者 + strMap["RocketMq.consumer"] = &G_ROCKETMQ_CONSUMER; + strMap["RocketMq.ConsumerIpport"] = &G_MQCONSUMER_IPPORT; + strMap["RocketMq.ConsumerAccessKey"] = &G_MQCONSUMER_ACCESSKEY; + strMap["RocketMq.ConsumerSecretKey"] = &G_MQCONSUMER_SECRETKEY; + strMap["RocketMq.ConsumerChannel"] = &G_MQCONSUMER_CHANNEL; + + strMap["RocketMq.ConsumerTopicRT"] = &G_MQCONSUMER_TOPIC_RT; + strMap["RocketMq.ConsumerTagRT"] = &G_MQCONSUMER_TAG_RT; + strMap["RocketMq.ConsumerKeyRT"] = &G_MQCONSUMER_KEY_RT; + + strMap["RocketMq.ConsumerTopicUD"] = &G_MQCONSUMER_TOPIC_UD; + strMap["RocketMq.ConsumerTagUD"] = &G_MQCONSUMER_TAG_UD; + strMap["RocketMq.ConsumerKeyUD"] = &G_MQCONSUMER_KEY_UD; + + strMap["RocketMq.ConsumerTopicRC"] = &G_MQCONSUMER_TOPIC_RC; + strMap["RocketMq.ConsumerTagRC"] = &G_MQCONSUMER_TAG_RC; + strMap["RocketMq.ConsumerKeyRC"] = &G_MQCONSUMER_KEY_RC; + + strMap["RocketMq.ConsumerTopicSET"] = &G_MQCONSUMER_TOPIC_SET; + strMap["RocketMq.ConsumerTagSET"] = &G_MQCONSUMER_TAG_SET; + strMap["RocketMq.ConsumerKeySET"] = &G_MQCONSUMER_KEY_SET; + + strMap["RocketMq.ConsumerTopicLOG"] = &G_MQCONSUMER_TOPIC_LOG; + strMap["RocketMq.ConsumerTagLOG"] = &G_MQCONSUMER_TAG_LOG; + strMap["RocketMq.ConsumerKeyLOG"] = &G_MQCONSUMER_KEY_LOG; + + strMap["RocketMq.Topic_Test"] = &G_ROCKETMQ_TOPIC_TEST; + strMap["RocketMq.Tag_Test"] = &G_ROCKETMQ_TAG_TEST; + strMap["RocketMq.Key_Test"] = &G_ROCKETMQ_KEY_TEST; + + intMap["RocketMq.Testflag"] = &G_TEST_FLAG; + intMap["RocketMq.Testnum"] = &G_TEST_NUM; + intMap["RocketMq.Testtype"] = &G_TEST_TYPE; + intMap["RocketMq.TestPort"] = &TEST_PORT; + strMap["RocketMq.TestList"] = &G_TEST_LIST; + + // 2. 打开并逐行解析 INI 文件 + std::ifstream fin(filename); + if (!fin.is_open()) { + std::cerr << "无法打开配置文件: " << filename << "\n"; + return; + } + + std::string line; + std::string currentSection; + while (std::getline(fin, line)) { + trim(line); + if (line.empty() || line[0] == ';' || line[0] == '#') { + continue; // 跳过空白或注释 + } + if (line.front() == '[' && line.back() == ']') { + currentSection = line.substr(1, line.size() - 2); + trim(currentSection); + continue; + } + auto pos = line.find('='); + if (pos == std::string::npos) { + continue; + } + std::string key = line.substr(0, pos); + std::string value = line.substr(pos + 1); + trim(key); + trim(value); + + // 去掉值两端双引号 + if (value.size() >= 2 && value.front() == '"' && value.back() == '"') { + value = value.substr(1, value.size() - 2); + } + + // 拼出 "节.键" + std::string fullKey = currentSection + "." + key; + + // 如果在字符串映射表里,就写入对应的全局 std::string + auto sit = strMap.find(fullKey); + if (sit != strMap.end()) { + *(sit->second) = value; + continue; + } + // 如果在整型映射表里,就 stoi 后写入对应的全局 int + auto iit = intMap.find(fullKey); + if (iit != intMap.end()) { + try { + *(iit->second) = std::stoi(value); + } catch (...) { + *(iit->second) = 0; + } + } + } + fin.close(); + + // 3. 将 G_TEST_LIST 拆分到 TESTARRAY + parseTestList(); +} + +//打印所有全局变量,名称对齐 +void printConfig() { + const int nameWidth = 30; // 变量名区域宽度 + std::cout << "------- Loaded Configuration -------\n"; + + // 辅助 lambda 方便打印 + auto printStr = [&](const std::string& name, const std::string& val) { + std::cout << std::left << std::setw(nameWidth) << name + << " = " << val << "\n"; + }; + auto printInt = [&](const std::string& name, int val) { + std::cout << std::left << std::setw(nameWidth) << name + << " = " << val << "\n"; + }; + + std::cout << "\n// 前置区分 —— 通用\n"; + printInt("IED_COUNT", IED_COUNT); + printStr("FRONT_INST", FRONT_INST); + printStr("FRONT_IP", FRONT_IP); + + std::cout << "\n// 消息队列 —— 通用\n"; + printStr("BROKER_LIST", BROKER_LIST); + printStr("TOPIC_STAT", TOPIC_STAT); + printStr("TOPIC_PST", TOPIC_PST); + printStr("TOPIC_PLT", TOPIC_PLT); + printStr("TOPIC_EVENT", TOPIC_EVENT); + printStr("TOPIC_ALARM", TOPIC_ALARM); + printStr("TOPIC_SNG", TOPIC_SNG); + printStr("TOPIC_RTDATA", TOPIC_RTDATA); + + std::cout << "\n// MQ —— 生产者\n"; + printStr("G_ROCKETMQ_PRODUCER", G_ROCKETMQ_PRODUCER); + printStr("G_MQPRODUCER_IPPORT", G_MQPRODUCER_IPPORT); + printStr("G_MQPRODUCER_ACCESSKEY", G_MQPRODUCER_ACCESSKEY); + printStr("G_MQPRODUCER_SECRETKEY", G_MQPRODUCER_SECRETKEY); + + printStr("G_LOG_TOPIC", G_LOG_TOPIC); + printStr("G_LOG_TAG", G_LOG_TAG); + printStr("G_LOG_KEY", G_LOG_KEY); + + printStr("G_CONNECT_TOPIC", G_CONNECT_TOPIC); + printStr("G_CONNECT_TAG", G_CONNECT_TAG); + printStr("G_CONNECT_KEY", G_CONNECT_KEY); + + std::cout << "\n// MQ —— 心跳 & 响应\n"; + printStr("Heart_Beat_Topic", Heart_Beat_Topic); + printStr("Heart_Beat_Tag", Heart_Beat_Tag); + printStr("Heart_Beat_Key", Heart_Beat_Key); + + printStr("Topic_Reply_Topic", Topic_Reply_Topic); + printStr("Topic_Reply_Tag", Topic_Reply_Tag); + printStr("Topic_Reply_Key", Topic_Reply_Key); + + std::cout << "\n// MQ —— 消费者\n"; + printStr("G_ROCKETMQ_CONSUMER", G_ROCKETMQ_CONSUMER); + printStr("G_MQCONSUMER_IPPORT", G_MQCONSUMER_IPPORT); + printStr("G_MQCONSUMER_ACCESSKEY", G_MQCONSUMER_ACCESSKEY); + printStr("G_MQCONSUMER_SECRETKEY", G_MQCONSUMER_SECRETKEY); + printStr("G_MQCONSUMER_CHANNEL", G_MQCONSUMER_CHANNEL); + + std::cout << "\n// MQ —— 主题细分类\n"; + printStr("G_MQCONSUMER_TOPIC_RT", G_MQCONSUMER_TOPIC_RT); + printStr("G_MQCONSUMER_TAG_RT", G_MQCONSUMER_TAG_RT); + printStr("G_MQCONSUMER_KEY_RT", G_MQCONSUMER_KEY_RT); + + printStr("G_MQCONSUMER_TOPIC_UD", G_MQCONSUMER_TOPIC_UD); + printStr("G_MQCONSUMER_TAG_UD", G_MQCONSUMER_TAG_UD); + printStr("G_MQCONSUMER_KEY_UD", G_MQCONSUMER_KEY_UD); + + printStr("G_MQCONSUMER_TOPIC_RC", G_MQCONSUMER_TOPIC_RC); + printStr("G_MQCONSUMER_TAG_RC", G_MQCONSUMER_TAG_RC); + printStr("G_MQCONSUMER_KEY_RC", G_MQCONSUMER_KEY_RC); + + printStr("G_MQCONSUMER_TOPIC_SET", G_MQCONSUMER_TOPIC_SET); + printStr("G_MQCONSUMER_TAG_SET", G_MQCONSUMER_TAG_SET); + printStr("G_MQCONSUMER_KEY_SET", G_MQCONSUMER_KEY_SET); + + printStr("G_MQCONSUMER_TOPIC_LOG", G_MQCONSUMER_TOPIC_LOG); + printStr("G_MQCONSUMER_TAG_LOG", G_MQCONSUMER_TAG_LOG); + printStr("G_MQCONSUMER_KEY_LOG", G_MQCONSUMER_KEY_LOG); + + std::cout << "\n// MQ —— 测试用主题 & 参数\n"; + printStr("G_ROCKETMQ_TOPIC_TEST", G_ROCKETMQ_TOPIC_TEST); + printStr("G_ROCKETMQ_TAG_TEST", G_ROCKETMQ_TAG_TEST); + printStr("G_ROCKETMQ_KEY_TEST", G_ROCKETMQ_KEY_TEST); + + printInt("G_TEST_FLAG", G_TEST_FLAG); + printInt("G_TEST_NUM", G_TEST_NUM); + printInt("G_TEST_TYPE", G_TEST_TYPE); + printInt("TEST_PORT", TEST_PORT); + printStr("G_TEST_LIST", G_TEST_LIST); + + // 打印解析后的 TESTARRAY + std::cout << std::left << std::setw(nameWidth) << "TESTARRAY" << " = ["; + for (size_t i = 0; i < TESTARRAY.size(); ++i) { + std::cout << TESTARRAY[i]; + if (i + 1 < TESTARRAY.size()) { + std::cout << ", "; + } + } + std::cout << "]\n"; + + std::cout << "\n// 终端 & 监测点状态筛选\n"; + printStr("TERMINAL_STATUS", TERMINAL_STATUS); + printStr("MONITOR_STATUS", MONITOR_STATUS); + printStr("ICD_FLAG", ICD_FLAG); + + std::cout << "\n// Web 接口\n"; + printStr("WEB_DEVICE", WEB_DEVICE); + printStr("WEB_ICD", WEB_ICD); + printStr("WEB_EVENT", WEB_EVENT); + printStr("WEB_FILEUPLOAD", WEB_FILEUPLOAD); + printStr("WEB_FILEDOWNLOAD", WEB_FILEDOWNLOAD); + + std::cout << "-------------------------------------\n"; +} + +//初始化配置 +void init_config() { + + loadConfig(FRONT_PATH + "/config/front.cfg"); + printConfig(); + + //多前置处理 + if (g_front_seg_index > 0 && g_front_seg_num > 0) { + MULTIPLE_NODE_FLAG = 1; + std::cout << "this is multiple process of index:" << g_front_seg_index << std::endl; + + if(g_front_seg_index > g_front_seg_num){ + DIY_ERRORLOG("process","【ERROR】前置当前进程的进程号为:%d,前置的多进程最大进程号为:%d,当前进程的进程号应该为1到最大进程号范围内的整数,退出该进程",g_front_seg_index,g_front_seg_num); + exit(-1039); + } + + } + else if(g_front_seg_num == 0 && g_front_seg_index == 0){ + MULTIPLE_NODE_FLAG = 0; + std::cout << "this is single process" << std::endl; + } + else{ + DIY_ERRORLOG("process","【ERROR】前置当前进程的进程号为:%d,前置的多进程最大进程号为:%d,应该为大于0的整数,退出该进程",g_front_seg_index,g_front_seg_num); + exit(-1039); + } + + //测试进程端口 + if (g_node_id == STAT_DATA_BASE_NODE_ID)//统计采集 + TEST_PORT = TEST_PORT + STAT_DATA_BASE_NODE_ID + g_front_seg_index; + else if (g_node_id == RECALL_HIS_DATA_BASE_NODE_ID) {//补召 + TEST_PORT = TEST_PORT + RECALL_HIS_DATA_BASE_NODE_ID + g_front_seg_index; + } + else if (g_node_id == THREE_SECS_DATA_BASE_NODE_ID) {//3秒采集 + TEST_PORT = TEST_PORT + THREE_SECS_DATA_BASE_NODE_ID + g_front_seg_index; + } + else if (g_node_id == SOE_COMTRADE_BASE_NODE_ID) {//暂态录波 + TEST_PORT = TEST_PORT + SOE_COMTRADE_BASE_NODE_ID + g_front_seg_index; + } + +} + +////////////////////////////////////////////////////////////////////////////////////////////获取当前时间 + +// 用于获取当前时间,单位毫秒 +double sGetMsTime() { + auto now = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast( + now.time_since_epoch() + ).count(); + return static_cast(ms); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////实时触发部分 + +//获取实时触发文件 +std::string get_3s_trig_fn() { + const std::string dirPath = FRONT_PATH + "/etc/trigger3s"; + DIR* dp = opendir(dirPath.c_str()); + if (!dp) return ""; + + struct dirent* entry; + std::vector> xmlFiles; + + while ((entry = readdir(dp)) != nullptr) { + if (strstr(entry->d_name, ".xml")) { + std::string fullPath = dirPath + "/" + entry->d_name; + struct stat st; + if (stat(fullPath.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { + xmlFiles.emplace_back(entry->d_name, st.st_mtime); + } + } + } + closedir(dp); + + if (xmlFiles.empty()) return ""; + + std::sort(xmlFiles.begin(), xmlFiles.end(), + [](const std::pair& a, const std::pair& b) { + return a.second > b.second; // 最近时间在前 + }); + + return xmlFiles.front().first; +} + +// 打印 trigger_t 结构体的函数 +void print_trigger(const trigger_t& trigger) { + std::cout << " dev_idx: " << trigger.dev_idx + << ", line_id: " << trigger.line_id + << ", real_data: " << trigger.real_data + << ", soe_data: " << trigger.soe_data + << ", limit: " << trigger.limit + << ", count: " << trigger.count + << std::endl; +} + +// 打印 trigger_3s_xml_t 结构体的函数 +void print_trigger_3s_xml(const trigger_3s_xml_t& trigger_3s_xml) { + std::cout << "Work Trigger Count: " << trigger_3s_xml.work_trigger_num << std::endl; + for (int i = 0; i < trigger_3s_xml.work_trigger_num; ++i) { + std::cout << " Work Trigger [" << (i + 1) << "]:" << std::endl; + print_trigger(trigger_3s_xml.work_triggers[i]); + } + + std::cout << "New Trigger Count: " << trigger_3s_xml.new_trigger_num << std::endl; + for (int i = 0; i < trigger_3s_xml.new_trigger_num; ++i) { + std::cout << " New Trigger [" << (i + 1) << "]:" << std::endl; + print_trigger(trigger_3s_xml.new_triggers[i]); + } + + std::cout << "Delete Trigger Count: " << trigger_3s_xml.delete_trigger_num << std::endl; + for (int i = 0; i < trigger_3s_xml.delete_trigger_num; ++i) { + std::cout << " Delete Trigger [" << (i + 1) << "]:" << std::endl; + print_trigger(trigger_3s_xml.delete_triggers[i]); + } + + std::cout << "Modify Trigger Count: " << trigger_3s_xml.modify_trigger_num << std::endl; + for (int i = 0; i < trigger_3s_xml.modify_trigger_num; ++i) { + std::cout << " Modify Trigger [" << (i + 1) << "]:" << std::endl; + print_trigger(trigger_3s_xml.modify_triggers[i]); + } +} + +//处理触发标志 +int getValueFromElemAttrStr(std::string str) +{ + if (str == "true") + return 1; + else if (str == "false") + return 0; + else + return -1; +} + +//将文件内容读取到结构中 +void parse_3s_trigger(trigger_3s_xml_t* trigger_3s_xml, const std::string& parentTag, tinyxml2::XMLElement* trigger_e) +{ + if (!trigger_3s_xml || !trigger_e) return; + + trigger_t trigger; + + const char* attr = nullptr; + + // DevSeries + attr = trigger_e->Attribute("DevSeries"); + trigger.dev_idx = attr ? std::atoi(attr) : 0; + + // Line + attr = trigger_e->Attribute("Line"); + trigger.line_id = attr ? std::atoi(attr) : 0; + + // RealData + attr = trigger_e->Attribute("RealData"); + std::string realDataStr = attr ? attr : ""; + std::transform(realDataStr.begin(), realDataStr.end(), realDataStr.begin(), ::tolower); + trigger.real_data = getValueFromElemAttrStr(realDataStr); + + // SOEData + attr = trigger_e->Attribute("SOEData"); + std::string soeDataStr = attr ? attr : ""; + std::transform(soeDataStr.begin(), soeDataStr.end(), soeDataStr.begin(), ::tolower); + trigger.soe_data = getValueFromElemAttrStr(soeDataStr); + + // Limit + attr = trigger_e->Attribute("Limit"); + trigger.limit = attr ? std::atoi(attr) : 0; + + // Count + attr = trigger_e->Attribute("Count"); + trigger.count = attr ? std::atoi(attr) : 0; + + // 分类插入 + if (parentTag == "Work") { + trigger_3s_xml->work_triggers[trigger_3s_xml->work_trigger_num++] = trigger; + } else if (parentTag == "New") { + trigger_3s_xml->new_triggers[trigger_3s_xml->new_trigger_num++] = trigger; + } else if (parentTag == "Delete") { + trigger_3s_xml->delete_triggers[trigger_3s_xml->delete_trigger_num++] = trigger; + } else if (parentTag == "Modify") { + trigger_3s_xml->modify_triggers[trigger_3s_xml->modify_trigger_num++] = trigger; + } + + // 调试用 + print_trigger_3s_xml(*trigger_3s_xml); +} + +//实时触发文件处理 +int load_3s_data_from_xml(trigger_3s_xml_t* trigger_3s_xml, const std::string& xml_fn) { + if (!trigger_3s_xml) return 1; + + tinyxml2::XMLDocument doc; + tinyxml2::XMLError result = doc.LoadFile(xml_fn.c_str()); + if (result == tinyxml2::XML_ERROR_FILE_NOT_FOUND) { + return 1; + } else if (result != tinyxml2::XML_SUCCESS) { + return 1; + } + + tinyxml2::XMLElement* root = doc.RootElement(); + if (!root) return 1; + + for (tinyxml2::XMLElement* groupElem = root->FirstChildElement(); groupElem != nullptr; groupElem = groupElem->NextSiblingElement()) { + std::string strTag = groupElem->Name(); + if (strTag == "Work" || strTag == "New" || strTag == "Delete" || strTag == "Modify") { + for (tinyxml2::XMLElement* triggerElem = groupElem->FirstChildElement("Trigger"); triggerElem != nullptr; triggerElem = triggerElem->NextSiblingElement("Trigger")) { + parse_3s_trigger(trigger_3s_xml, strTag, triggerElem); + } + } + } + + return 0; +} + +//将内容写入协议 +void process_3s_config(trigger_3s_xml_t *trigger_3s_xml) +{ + //根据协议补充内容 + + //根据协议补充内容 +} + +//实时触发处理 +int parse_3s_xml(trigger_3s_xml_t* trigger_3s_xml) { + std::cout << "begin 3s xml..." << std::endl; + std::memset(trigger_3s_xml, 0, sizeof(trigger_3s_xml_t)); + + std::string THREE_SECS_WEBSERVICE_DIR = FRONT_PATH + "/etc/trigger3s/"; //实时数据读取目录 + std::string BAK_WEBSERVICE_3S_TRIG_COMMAND_XML_FN = THREE_SECS_WEBSERVICE_DIR + "bak_3s_trig_command.txt"; //实时触发文件备份文件名 + + std::string the_webservice_xml_fn = get_3s_trig_fn(); // 获取目录下最新 XML 文件名 + + if (the_webservice_xml_fn.length() > 4) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待 0.1 秒 + + std::string full_path = std::string(THREE_SECS_WEBSERVICE_DIR) + the_webservice_xml_fn; + + if (load_3s_data_from_xml(trigger_3s_xml, full_path) != 0) { + std::cerr << "Failed to load 3s data from XML: " << full_path << std::endl; + return 1; + } + + std::remove(BAK_WEBSERVICE_3S_TRIG_COMMAND_XML_FN.c_str()); // 删除旧备份 + if (std::rename(full_path.c_str(), BAK_WEBSERVICE_3S_TRIG_COMMAND_XML_FN.c_str()) != 0) { + std::perror("Rename failed"); + } + + std::cout << "/etc/trigger3s/*.xml success..." << std::endl; + DIY_WARNLOG("process", "【WARN】前置读取实时数据触发文件成功,即将注册实时数据报告"); + + return 0; + } + + std::cout << "3s xml fail..." << std::endl; + return 1; +} + +void check_3s_config() { + double now; + static double last_check_3s_config_time = 0.0; // 初始化时间 + trigger_3s_xml_t trigger_3s_xml; // 3s触发文件 + + if (!three_secs_enabled) // 只有cfg_3s_data进程才会开启 + return; + + now = sGetMsTime(); // 当前时间 + if (std::fabs(now - last_check_3s_config_time) < 3 * 1000) // wait 3secs + return; // 当前进程任务执行时查看当前时间和上次执行时间间隔,小于3秒不执行,大于等于3秒往下执行 + + last_check_3s_config_time = now; // 记录本次运行时间 + while (0 == parse_3s_xml(&trigger_3s_xml)) { // 处理3秒文件,一次处理一个 + process_3s_config(&trigger_3s_xml); // 根据文件处理数据 + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////补招部分 + +//将文件内容读取到结构中 +void parse_recall(recall_xml_t* recall_xml, const std::string& parentTag, const std::map& attributes, const std::string& id) { + recall_t recall; + std::memset(&recall, 0, sizeof(recall_t)); + + // 设置监测点 ID + recall.line_id = id; + + // 解析时间字符串 + auto parse_time = [](const std::string& time_str) -> std::time_t { + std::tm tm = {}; + std::istringstream ss(time_str); + ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S"); + if (ss.fail()) return 0; + return std::mktime(&tm); + }; + + recall.start_time = parse_time(attributes.at("StartTime")); + recall.end_time = parse_time(attributes.at("EndTime")); + recall.need_steady = std::stoi(attributes.at("STEADY")); + recall.need_voltage = std::stoi(attributes.at("VOLTAGE")); + + std::cout << parentTag << " -> " << recall.line_id + << " " << recall.need_steady + << " " << recall.need_voltage + << " " << recall.start_time + << " " << recall.end_time << std::endl; + + if (parentTag == "Work" && recall_xml->work_recall_num < MAX_RECALL_NUM) { + recall_xml->work_recalls[recall_xml->work_recall_num++] = recall; + } else if (parentTag == "New" && recall_xml->new_recall_num < MAX_RECALL_NUM) { + recall_xml->new_recalls[recall_xml->new_recall_num++] = recall; + } +} + +//读取补招文件 +int parse_recall_xml(recall_xml_t* recall_xml, const std::string& id) { + std::string cfg_dir = FRONT_PATH + "/etc/recall"; + std::string pattern = subdir + "_" + std::to_string(g_front_seg_index) + "_" + id + "_*_Recall.xml"; + + DIR* dir = opendir(cfg_dir.c_str()); + if (!dir) { + DIY_ERRORLOG("process", "【ERROR】前置的%s%d号进程 无法解析补招文件,补招文件路径FRONT_PATH + /etc/recall/不存在", get_front_msg_from_subdir(), g_front_seg_index); + return false; + } + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + std::string filename = entry->d_name; + if (fnmatch(pattern.c_str(), filename.c_str(), 0) != 0) continue; + + std::string filepath = cfg_dir + "/" + filename; + tinyxml2::XMLDocument doc; + if (doc.LoadFile(filepath.c_str()) != tinyxml2::XML_SUCCESS) { + DIY_ERRORLOG("process", "【ERROR】前置的%s%d号进程 无法解析补招文件%s,补招内容无效", get_front_msg_from_subdir(), g_front_seg_index, filepath.c_str()); + continue; + } + + tinyxml2::XMLElement* root = doc.RootElement(); + if (!root) continue; + + for (tinyxml2::XMLElement* elem = root->FirstChildElement(); elem != nullptr; elem = elem->NextSiblingElement()) { + std::string tag = elem->Name(); + if (tag == "Work" || tag == "New") { + for (tinyxml2::XMLElement* recallElem = elem->FirstChildElement("Recall"); recallElem != nullptr; recallElem = recallElem->NextSiblingElement("Recall")) { + std::map attrs; + const char* start = recallElem->Attribute("StartTime"); + const char* end = recallElem->Attribute("EndTime"); + const char* steady = recallElem->Attribute("STEADY"); + const char* voltage = recallElem->Attribute("VOLTAGE"); + + if (start && end && steady && voltage) { + attrs["StartTime"] = start; + attrs["EndTime"] = end; + attrs["STEADY"] = steady; + attrs["VOLTAGE"] = voltage; + + parse_recall(recall_xml, tag, attrs, id); + } + } + } + } + } + + closedir(dir); + return 0; +} + +//将读取到的补招文件写入到监测点的运行结构中,后续根据实际补充 +void process_recall_config(recall_xml_t* recall_xml) +{ + +} + +//根据监测点id来获取补招数据,补招时调用这个 +void Check_Recall_Config(const std::string& id) { + if (g_node_id == HIS_DATA_BASE_NODE_ID || + g_node_id == NEW_HIS_DATA_BASE_NODE_ID || + g_node_id == RECALL_HIS_DATA_BASE_NODE_ID || + g_node_id == RECALL_ALL_DATA_BASE_NODE_ID) { + + recall_xml_t recall_xml; + std::memset(&recall_xml, 0, sizeof(recall_xml_t)); + + // 解析补招文件 + parse_recall_xml(&recall_xml, id); + + // 将补招数据赋值到全局变量 + process_recall_config(&recall_xml); + } +} + +//补招成功后删除补招文件,补招后调用这个 +int delete_recall_xml(const std::string& id) { + std::string cfg_dir = FRONT_PATH + "/etc/recall"; + std::string pattern = std::string(subdir) + "_" + + std::to_string(g_front_seg_index) + "_" + + id + "_*_Recall.xml"; + + DIR* dir = opendir(cfg_dir.c_str()); + if (!dir) { + std::cerr << "Folder does not exist or cannot be opened: " << cfg_dir << std::endl; + return false; + } + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + std::string filename = entry->d_name; + if (fnmatch(pattern.c_str(), filename.c_str(), 0) == 0) { + std::string fullpath = cfg_dir + "/" + filename; + if (remove(fullpath.c_str()) == 0) { + std::cout << "Deleted: " << fullpath << std::endl; + } else { + std::cerr << "Failed to delete: " << fullpath << std::endl; + } + } + } + + closedir(dir); + return 0; +} + +//删除过期的xmllnk:多个进程并发删除导致的失败不会影响进程 +void DeletcRecallXml() { + std::string cfg_dir = FRONT_PATH + "/etc/recall"; + std::string pattern = std::string(subdir) + "_*_Recall.xml"; + + DIR* dir = opendir(cfg_dir.c_str()); + if (!dir) { + std::cerr << "folder does not exist!" << std::endl; + DIY_ERRORLOG("process", "【ERROR】前置的%s%d号进程 删除旧的补招文件失败,补招文件路径FRONT_PATH + /etc/recall/不存在",get_front_msg_from_subdir(), g_front_seg_index); + return; + } + + // 获取当前时间,计算 2 天前的时间戳 + std::time_t now = std::time(nullptr); + std::time_t cutoff = now - 2 * 24 * 60 * 60; // 两天前 + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + std::string filename = entry->d_name; + + if (fnmatch(pattern.c_str(), filename.c_str(), 0) == 0) { + std::string fullpath = cfg_dir + "/" + filename; + + struct stat file_stat; + if (stat(fullpath.c_str(), &file_stat) == 0) { + if (file_stat.st_mtime < cutoff) { + if (remove(fullpath.c_str()) == 0) { + DIY_INFOLOG("process", "【NORMAL】前置的%s%d号进程 删除超过两天的补招文件",get_front_msg_from_subdir(), g_front_seg_index); + } else { + std::cerr << "Failed to remove file: " << fullpath << std::endl; + } + } + } + } + } + + closedir(dir); +} + +//根据补招列表创建补招文件 +void CreateRecallXml() { + std::time_t now = std::time(nullptr); + std::tm* tm_now = std::localtime(&now); + char timestamp[32] = {0}; + std::strftime(timestamp, sizeof(timestamp), "%Y%m%d%H%M%S", tm_now); + + g_StatisticLackList_list_mutex.lock(); + + if (!g_StatisticLackList.empty()) { + DIY_INFOLOG("process", "【NORMAL】前置的%s%d号进程 开始写入补招文件", get_front_msg_from_subdir(), g_front_seg_index); + + std::map> id_map; + for (const auto& jr : g_StatisticLackList) { + id_map[jr.MonitorID].push_back(jr); + } + + for (const auto& pair : id_map) { + const std::string& monitor_id = pair.first; + const std::list& recalls = pair.second; + + std::ostringstream path; + path << FRONT_PATH << "/etc/recall/" << subdir << "_" << g_front_seg_index << "_" << monitor_id << "_" << timestamp << "_Recall.xml"; + + tinyxml2::XMLDocument doc; + tinyxml2::XMLDeclaration* decl = doc.NewDeclaration(); + doc.InsertFirstChild(decl); + + tinyxml2::XMLElement* root = doc.NewElement("RecallList"); + doc.InsertEndChild(root); + + // 空 Work 段 + tinyxml2::XMLElement* work = doc.NewElement("Work"); + root->InsertEndChild(work); + + // New 段 + tinyxml2::XMLElement* new_elem = doc.NewElement("New"); + for (const auto& jr : recalls) { + tinyxml2::XMLElement* recall = doc.NewElement("Recall"); + recall->SetAttribute("MonitorID", jr.MonitorID.c_str()); + recall->SetAttribute("StartTime", jr.StartTime.c_str()); + recall->SetAttribute("EndTime", jr.EndTime.c_str()); + recall->SetAttribute("STEADY", jr.STEADY.c_str()); + recall->SetAttribute("VOLTAGE", jr.VOLTAGE.c_str()); + new_elem->InsertEndChild(recall); + } + root->InsertEndChild(new_elem); + + tinyxml2::XMLError save_result = doc.SaveFile(path.str().c_str()); + if (save_result != tinyxml2::XML_SUCCESS) { + DIY_ERRORLOG("process", "【ERROR】前置的%s%d号进程 无法将补招文件写入路径: %s",get_front_msg_from_subdir(), g_front_seg_index, path.str().c_str()); + continue; + } + } + } + + g_StatisticLackList.clear(); + g_StatisticLackList_list_mutex.unlock(); +} + +//生成待补招xml文件 +void create_recall_xml() +{ + if (g_node_id == HIS_DATA_BASE_NODE_ID || g_node_id == NEW_HIS_DATA_BASE_NODE_ID || g_node_id == RECALL_HIS_DATA_BASE_NODE_ID || (g_node_id == RECALL_ALL_DATA_BASE_NODE_ID)) { + DeletcRecallXml(); + CreateRecallXml(); + } +} + +// 工具函数:将时间字符串转为 time_t(秒级) +static long long parse_time_to_epoch(const std::string& time_str) { + std::tm tm = {}; + std::istringstream ss(time_str); + ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S"); + if (ss.fail()) { + return 0; + } + return static_cast(std::mktime(&tm)); +} + +// 数据完整性补招判断(划分为1小时) +void Get_Recall_Time_Char(const std::string& start_time_str, + const std::string& end_time_str, + std::vector& recallinfo_list_hour) { + long long starttime = parse_time_to_epoch(start_time_str); + long long endtime = parse_time_to_epoch(end_time_str); + + if (starttime == 0 || endtime == 0 || starttime >= endtime) { + return; + } + + // 初始区间加入 + RecallInfo initial; + initial.starttime = starttime; + initial.endtime = endtime; + + std::vector recallinfo_list; + recallinfo_list.push_back(initial); + + const long long max_interval = 3600; // 1小时 + for (const auto& interval : recallinfo_list) { + long long duration = interval.endtime - interval.starttime; + + for (long long j = 0; j <= duration; j += max_interval) { + RecallInfo info; + info.starttime = interval.starttime + j; + if (j + max_interval > duration) { + info.endtime = interval.endtime; + } else { + info.endtime = interval.starttime + j + max_interval - 1; + } + recallinfo_list_hour.push_back(info); + } + } +} + +//mq调用将补招信息写入补招列表 +int recall_json_handle(const std::string& jstr) { + // 不指定稳态/暂态则全部补招 + int stat = 0; + int voltage = 0; + try { + std::vector recallParams; + + // 1. 解析 JSON 数组 + auto json_root = nlohmann::json::parse(jstr); + if (!json_root.is_array()) { + std::cout << "json root解析错误" << std::endl; + return 10000; + } + + // 2. 遍历每个补招项 + for (auto& item : json_root) { + // 获取必需字段 + if (!item.contains("monitorId") || + !item.contains("timeInterval") || + !item.contains("dataType")) + { + std::cout << "json内容解析错误" << std::endl; + return 10000; + } + + // 2.1 解析 dataType + std::string datatype = item["dataType"].get(); + if (!datatype.empty()) { + stat = (datatype == "0") ? 1 : 0; // 稳态 + voltage = (datatype == "1") ? 1 : 0; // 暂态 + } else { + stat = voltage = 1; // 全补 + } + + // 2.2 处理 monitorId 数组 + auto& midArr = item["monitorId"]; + auto& tiArr = item["timeInterval"]; + if (midArr.is_array() && tiArr.is_array() && !midArr.empty()) { + for (auto& idItem : midArr) { + std::string monitorId = idItem.get(); + + // 判断此监测点是否归属当前进程 + bool mppair = false; + for (const auto& dev : terminal_devlist) { + // 只处理本进程对应的终端 + if (std::stoi(dev.processNo) != g_front_seg_index && + g_front_seg_index != 0) { + continue; + } + for (const auto& mon : dev.line) { + if (mon.monitor_id.empty()) continue; + if (mon.monitor_id == monitorId) { + mppair = true; + std::cout << "Matched monitorId " << monitorId + << " in terminal " << dev.terminal_id + << std::endl; + break; + } + } + if (mppair) break; + } + if (!mppair) continue; + + // 遍历 timeInterval 数组 + for (auto& timeItem : tiArr) { + std::string ti = timeItem.get(); + auto pos = ti.find('~'); + std::string start = ti.substr(0, pos); + std::string end = ti.substr(pos + 1); + + JournalRecall param; + param.MonitorID = monitorId; + param.StartTime = start; + param.EndTime = end; + param.STEADY = std::to_string(stat); + param.VOLTAGE = std::to_string(voltage); + recallParams.push_back(param); + } + } + } + // 2.3 monitorId 数组存在但为空 -> 补招所有监测点 + else if (midArr.is_array() && midArr.empty()) { + std::cout << "monitorIdArray is null,补招所有监测点" << std::endl; + for (const auto& dev : terminal_devlist) { + if (std::stoi(dev.processNo) != g_front_seg_index && + g_front_seg_index != 0) { + continue; + } + for (const auto& mon : dev.line) { + if (mon.monitor_id.empty()) continue; + for (auto& timeItem : tiArr) { + std::string ti = timeItem.get(); + auto pos = ti.find('~'); + std::string start = ti.substr(0, pos); + std::string end = ti.substr(pos + 1); + + JournalRecall param; + param.MonitorID = mon.monitor_id; + param.StartTime = start; + param.EndTime = end; + param.STEADY = std::to_string(stat); + param.VOLTAGE = std::to_string(voltage); + recallParams.push_back(param); + } + } + } + } else { + std::cout << "monitorIdArray 不存在或类型不正确" << std::endl; + } + } + + // 3. 生成具体补招记录 + for (auto& rp : recallParams) { + std::string start_time = rp.StartTime; + std::string end_time = rp.EndTime; + + std::cout << "mp_id " << rp.MonitorID + << " start_time " << start_time + << " end_time " << end_time + << " stat " << rp.STEADY + << " voltage " << rp.VOLTAGE + << std::endl; + + std::vector recallinfo_list_hour; + Get_Recall_Time_Char(start_time, end_time, recallinfo_list_hour); + + for (auto& info : recallinfo_list_hour) { + JournalRecall jr; + jr.MonitorID = rp.MonitorID; + + // 转换 starttime + char buf[20]; + std::tm tm{}; + time_t st = static_cast(info.starttime); + localtime_r(&st, &tm); + std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); + jr.StartTime = buf; + + // 转换 endtime + std::tm tm2{}; + time_t et = static_cast(info.endtime); + localtime_r(&et, &tm2); + std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm2); + jr.EndTime = buf; + + jr.STEADY = rp.STEADY; + jr.VOLTAGE = rp.VOLTAGE; + + std::lock_guard lk(g_StatisticLackList_list_mutex); + g_StatisticLackList.push_back(jr); + } + } + } + catch (const std::exception& e) { + std::cout << "处理客户端发送的消息错误,原因:" << e.what() << std::endl; + return 10004; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////台账接口打印 + +// 打印 terminal_dev_map 中所有内容的函数 +void printTerminalDevMap(const std::map& terminal_dev_map) { + for (const auto& kv : terminal_dev_map) { + const std::string& key = kv.first; + const terminal_dev& dev = kv.second; // 引用对象 + + std::cout << "Key: " << key + << ", Terminal ID: " << dev.terminal_id + << ", Terminal Code: " << dev.terminal_code + << ", Organization Name: "<< dev.org_name + << ", Maintenance Name: " << dev.maint_name + << ", Station Name: " << dev.station_name + << ", Factory: " << dev.tmnl_factory + << ", Status: " << dev.tmnl_status + << ", Device Type: " << dev.dev_type + << ", Device Key: " << dev.dev_key + << ", Device Series: " << dev.dev_series + << ", ProcessNo: " << dev.processNo + << ", MaxProcessNum: " << dev.maxProcessNum + << ", Address: " << dev.addr_str + << ", Port: " << dev.port + << ", Timestamp: " << dev.timestamp + << std::endl; + + // 打印监测点信息 + for (size_t i = 0; i < dev.line.size(); ++i) { + const auto& m = dev.line[i]; + std::cout << " Monitor [" << i << "] " + << "ID: " << m.monitor_id + << ", Code: " << m.terminal_code + << ", Name: " << m.monitor_name + << ", Seq: " << m.logical_device_seq + << ", Voltage: "<< m.voltage_level + << ", Connect: "<< m.terminal_connect + << ", Timestamp:"<< m.timestamp + << ", Status: " << m.status + << std::endl; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////更新台账 + +//在台账更新目录查找自己进程要处理的文件 +std::list find_xml_belong_to_this_process() +{ + char prefix[20]; // 假设最多需要20个字符(根据实际需要调整) + sprintf(prefix, "%d_%d", g_node_id, g_front_seg_index); // 将g_node_id和g_front_seg_index格式化为字符串 + + std::string LEDGER_UPDATE_DIR = FRONT_PATH + "/etc/ledgerupdate/"; //台账更新读取目录 + + DIR *dir = opendir(LEDGER_UPDATE_DIR.c_str()); // 打开目录 + struct dirent *entry; + std::list found_files; // 用于存储找到的所有匹配文件名 + + if (dir == NULL) { + std::cout << "Failed to open directory: " << LEDGER_UPDATE_DIR << std::endl; + return found_files; // 返回空的list + } + + // 遍历目录中的所有文件 + while ((entry = readdir(dir)) != NULL) { + std::string filename = entry->d_name; + + // 排除 "." 和 ".." 目录 + if (filename == "." || filename == "..") { + continue; + } + + std::cout << "find" << filename << "in" << LEDGER_UPDATE_DIR << std::endl; + + + // 判断文件名是否以 prefix 开头且扩展名是 .xml + if (filename.find(prefix) == 0 && filename.substr(filename.find_last_of('.') + 1) == "xml") { + std::string full_path = LEDGER_UPDATE_DIR + filename; + found_files.push_back(full_path); // 将完整路径加入容器 + } + } + + closedir(dir); // 关闭目录 + + return found_files; // 返回所有找到的文件名 +} + +// 根据 str_tag 将 terminal 添加到对应的数组 +void add_terminal_to_trigger_update(trigger_update_xml_t& trigger_update_xml, + const std::string& str_tag, + const terminal_dev& work_terminal) { + if (str_tag == "add") { + std::cout << "new ledger!!!!" << std::endl; + trigger_update_xml.new_updates.push_back(work_terminal); + } else if (str_tag == "modify") { + std::cout << "modify ledger!!!" << std::endl; + trigger_update_xml.modify_updates.push_back(work_terminal); + } else { + std::cerr << "Unknown tag: " << str_tag << std::endl; + } +} + +// 将添加和修改的文件内容写入结构 +void parse_terminal_from_data(trigger_update_xml_t& trigger_update_xml, + const std::string& str_tag, + const std::string& data, + const std::string& guid_value) { + terminal_dev work_terminal; + work_terminal.guid = guid_value; + + tinyxml2::XMLDocument doc; + if (doc.Parse(data.c_str()) != tinyxml2::XML_SUCCESS) { + return; + } + + auto root = doc.FirstChildElement("terminal"); + if (!root) return; + + auto get_value = [&](const char* tag) -> std::string { + auto elem = root->FirstChildElement(tag); + return elem && elem->GetText() ? elem->GetText() : ""; + }; + + work_terminal.terminal_id = get_value("id"); + work_terminal.terminal_code = get_value("terminalCode"); + work_terminal.org_name = get_value("orgName"); + work_terminal.maint_name = get_value("maintName"); + work_terminal.station_name = get_value("stationName"); + work_terminal.tmnl_factory = get_value("manufacturer"); + work_terminal.tmnl_status = get_value("status"); + work_terminal.dev_type = get_value("devType"); + work_terminal.dev_key = get_value("devKey"); + work_terminal.dev_series = get_value("series"); + work_terminal.processNo = get_value("processNo"); + work_terminal.addr_str = get_value("ip"); + work_terminal.port = get_value("port"); + work_terminal.timestamp = get_value("updateTime"); + + for (tinyxml2::XMLElement* monitor = root->FirstChildElement("monitorData"); + monitor; + monitor = monitor->NextSiblingElement("monitorData")) { + ledger_monitor mon; + mon.monitor_id = monitor->FirstChildElement("id") ? monitor->FirstChildElement("id")->GetText() : "N/A"; + mon.monitor_name = monitor->FirstChildElement("name") ? monitor->FirstChildElement("name")->GetText() : "N/A"; + mon.voltage_level = monitor->FirstChildElement("voltageLevel") ? monitor->FirstChildElement("voltageLevel")->GetText() : "N/A"; + mon.terminal_connect = monitor->FirstChildElement("ptType") ? monitor->FirstChildElement("ptType")->GetText() : "N/A"; + mon.logical_device_seq = monitor->FirstChildElement("lineNo") ? monitor->FirstChildElement("lineNo")->GetText() : "N/A"; + mon.timestamp = monitor->FirstChildElement("timestamp") ? monitor->FirstChildElement("timestamp")->GetText() : "N/A"; + mon.terminal_code = monitor->FirstChildElement("terminal_code") ? monitor->FirstChildElement("terminal_code")->GetText() : "N/A"; + mon.status = monitor->FirstChildElement("status") ? monitor->FirstChildElement("status")->GetText() : "N/A"; + + work_terminal.line.push_back(mon); + } + + add_terminal_to_trigger_update(trigger_update_xml, str_tag, work_terminal); +} + +// 统一处理文件内容和结构 +void parse_ledger_update(trigger_update_xml_t& trigger_update_xml, + const std::string& strTag, + const std::string& data, + const std::string& guid_value) { + std::cout << "record one xml.." << std::endl; + + if (strTag == "add" || strTag == "modify") { + parse_terminal_from_data(trigger_update_xml, strTag, data, guid_value); + } else if (strTag == "delete") { + terminal_dev delete_terminal; + tinyxml2::XMLDocument doc; + + if (doc.Parse(data.c_str()) != tinyxml2::XML_SUCCESS) { + std::cerr << "Failed to parse XML for delete tag." << std::endl; + return; + } + + tinyxml2::XMLElement* root = doc.FirstChildElement("terminalData"); + if (!root) { + std::cerr << "Missing terminalData element in delete tag." << std::endl; + return; + } + + tinyxml2::XMLElement* idElem = root->FirstChildElement("id"); + if (idElem && idElem->GetText()) { + delete_terminal.terminal_id = idElem->GetText(); + } else { + std::cerr << "Missing id element in delete tag." << std::endl; + return; + } + + delete_terminal.guid = guid_value; + trigger_update_xml.delete_updates.push_back(delete_terminal); + } else { + std::cerr << "Unsupported strTag: " << strTag << std::endl; + } +} + +//读取台账更新文件 +int load_ledger_update_from_xml(trigger_update_xml_t& trigger_update_xml, const std::string& xml_fn) { + std::cout << "start to load one xml.." << std::endl; + + std::ifstream file(xml_fn); + if (!file.is_open()) { + std::cerr << "Failed to open file: " << xml_fn << std::endl; + return -1; + } + + std::stringstream buffer; + buffer << file.rdbuf(); + std::string content = buffer.str(); + file.close(); + + tinyxml2::XMLDocument doc; + if (doc.Parse(content.c_str()) != tinyxml2::XML_SUCCESS) { + std::cerr << "Failed to parse XML content." << std::endl; + return -1; + } + + auto* root = doc.FirstChildElement("ledger_update"); + if (!root) { + std::cerr << "Missing root tag." << std::endl; + return -1; + } + + std::string guid_value; + auto* guidElem = root->FirstChildElement("guid"); + if (guidElem && guidElem->GetText()) { + guid_value = guidElem->GetText(); + std::cout << "Found guid: " << guid_value << std::endl; + } + + const char* tag_names[] = {"add", "modify", "delete"}; + tinyxml2::XMLElement* tagElem = nullptr; + std::string target_tag; + + for (const auto& tag : tag_names) { + tagElem = root->FirstChildElement(tag); + if (tagElem) { + target_tag = tag; + break; + } + } + + if (!tagElem) { + std::cerr << "No , , or tag found!" << std::endl; + return -1; + } + + for (auto* termElem = tagElem->FirstChildElement("terminalData"); + termElem; + termElem = termElem->NextSiblingElement("terminalData")) { + tinyxml2::XMLPrinter printer; + termElem->Accept(&printer); + std::string data_content = printer.CStr(); + + std::cout << "ledger data_content is " << data_content << std::endl; + parse_ledger_update(trigger_update_xml, target_tag, data_content, guid_value); + } + + std::cout << "load one xml finish" << std::endl; + return 0; +} + +//台账更新处理文件 +int parse_ledger_update_xml(trigger_update_xml_t& trigger_update_xml) +{ + std::list result = find_xml_belong_to_this_process(); + + if (result.empty()) return 1; + + for (const auto& filename : result) { + std::cout << "Found XML: " << filename << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (!load_ledger_update_from_xml(trigger_update_xml, filename)) { + DIY_WARNLOG("process", "【WARN】成功读取台账更新文件: %s", filename.c_str()); + } + + if (std::remove(filename.c_str()) != 0) { + DIY_ERRORLOG("process", "【ERROR】删除台账更新文件失败: %s", filename.c_str()); + return 1; + } else { + DIY_INFOLOG("process", "【NORMAL】成功删除台账更新文件: %s", filename.c_str()); + } + } + + if (!trigger_update_xml.new_updates.empty() || + !trigger_update_xml.modify_updates.empty() || + !trigger_update_xml.delete_updates.empty()) { + std::cout << "ledger update xml have data..." << std::endl; + return 0; + } + + std::cout << "ledger update xml no data..." << std::endl; + return 1; +} + +//更新单个台账 +int update_one_terminal_ledger(const terminal_dev& update,terminal_dev& target_dev) { + // 更新基本信息 + if (!update.terminal_id.empty()) { + target_dev.terminal_id = update.terminal_id; + std::cout << "terminal_id: " << target_dev.terminal_id << std::endl; + } + if (!update.terminal_code.empty()) { + target_dev.terminal_code = update.terminal_code; + std::cout << "terminal_code: " << target_dev.terminal_code << std::endl; + } + if (!update.tmnl_factory.empty()) { + target_dev.tmnl_factory = update.tmnl_factory; + std::cout << "tmnl_factory: " << target_dev.tmnl_factory << std::endl; + } + if (!update.tmnl_status.empty()) { + target_dev.tmnl_status = update.tmnl_status; + std::cout << "tmnl_status: " << target_dev.tmnl_status << std::endl; + } + if (!update.dev_type.empty()) { + target_dev.dev_type = update.dev_type; + std::cout << "dev_type: " << target_dev.dev_type << std::endl; + } + if (!update.processNo.empty()) { + target_dev.processNo = update.processNo; + std::cout << "processNo: " << target_dev.processNo << std::endl; + } + if (!update.dev_series.empty()) { + target_dev.dev_series = update.dev_series; + std::cout << "dev_series: " << target_dev.dev_series << std::endl; + } + if (!update.dev_key.empty()) { + target_dev.dev_key = update.dev_key; + std::cout << "dev_key: " << target_dev.dev_key << std::endl; + } + + if (!update.addr_str.empty()) { + target_dev.addr_str = update.addr_str; + std::cout << "addr_str: " << target_dev.addr_str << std::endl; + } + if (!update.port.empty()) { + target_dev.port = update.port; + std::cout << "port: " << target_dev.port << std::endl; + } + + if (!update.timestamp.empty()) { + struct tm timeinfo = {}; + if (sscanf(update.timestamp.c_str(), "%4d-%2d-%2d %2d:%2d:%2d", + &timeinfo.tm_year, &timeinfo.tm_mon, &timeinfo.tm_mday, + &timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec) == 6) { + timeinfo.tm_year -= 1900; + timeinfo.tm_mon -= 1; + timeinfo.tm_isdst = -1; + time_t raw_time = mktime(&timeinfo); + if (raw_time != -1) { + target_dev.timestamp = static_cast(raw_time); + std::cout << "timestamp (unix): " << target_dev.timestamp << std::endl; + } else { + std::cerr << "Error: mktime failed." << std::endl; + return -1; + } + } else { + std::cerr << "Error: invalid timestamp format." << std::endl; + return -1; + } + } + + // 清空旧监测点并重新填充 + target_dev.line.clear(); + + for (const auto& mon : update.line) { + if (mon.monitor_id.empty()) break; + + ledger_monitor m; + m.monitor_id = mon.monitor_id; + m.monitor_name = mon.monitor_name; + m.logical_device_seq = mon.logical_device_seq; + m.voltage_level = mon.voltage_level; + m.terminal_connect = mon.terminal_connect; + m.status = mon.status; + m.terminal_code = mon.terminal_code; + m.timestamp = mon.timestamp; + + if (m.terminal_connect != "0") { + isdelta_flag = 1; + std::cout << "monitor_id " << m.monitor_id << " uses delta wiring." << std::endl; + } + + if (!m.timestamp.empty()) { + struct tm timeinfo = {}; + if (sscanf(m.timestamp.c_str(), "%4d-%2d-%2d %2d:%2d:%2d", + &timeinfo.tm_year, &timeinfo.tm_mon, &timeinfo.tm_mday, + &timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec) == 6) { + timeinfo.tm_year -= 1900; + timeinfo.tm_mon -= 1; + timeinfo.tm_isdst = -1; + time_t raw_time = mktime(&timeinfo); + if (raw_time != -1) { + m.timestamp = static_cast(raw_time); + std::cout << "monitor time (unix): " << m.timestamp << std::endl; + } + } + } + + target_dev.line.push_back(m); + } + + return 0; +} + +//台账更新到台账列表 +void process_ledger_update(trigger_update_xml_t& ledger_update_xml) +{ + // --- 1. 新增处理 --- + std::cout << "add ledger num: " << ledger_update_xml.new_updates.size() << std::endl; + + for (auto it = ledger_update_xml.new_updates.begin(); it != ledger_update_xml.new_updates.end(); ) { + terminal_dev& new_dev = *it; + + auto found = std::find_if(terminal_devlist.begin(), terminal_devlist.end(), + [&](const terminal_dev& d) { return d.terminal_id == new_dev.terminal_id; }); + + if (found != terminal_devlist.end()) { + if (ledger_update_xml.modify_updates.size() < MAX_UPDATEA_NUM) { + ledger_update_xml.modify_updates.push_back(new_dev); + } else { + std::cerr << "Exceeded MAX_UPDATEA_NUM limit for modify_updates!" << std::endl; + } + it = ledger_update_xml.new_updates.erase(it); // 删除已处理项 + continue; + } + + if (terminal_devlist.size() >= static_cast(IED_COUNT)) { + send_reply_to_queue(new_dev.guid, "2", + "终端 id: " + new_dev.terminal_id + " 台账更新失败,配置台账数量已满"); + ++it; + continue; + } + + terminal_dev target_dev; + if (update_one_terminal_ledger(new_dev, target_dev) != 0) { + send_reply_to_queue(new_dev.guid, "2", + "终端 id: " + new_dev.terminal_id + " 台账更新失败,无法写入台账"); + ++it; + continue; + } + + if (parse_model_cfg_web_one(target_dev.dev_type).empty()) { + send_reply_to_queue(new_dev.guid, "2", + "终端 id: " + new_dev.terminal_id + " 台账更新失败,未找到装置型号"); + ++it; + continue; + } + + Set_xml_nodeinfo_one(target_dev.dev_type); + init_loggers_bydevid(target_dev.terminal_id); + terminal_devlist.push_back(target_dev); + + send_reply_to_queue(new_dev.guid, "2", + "终端 id: " + new_dev.terminal_id + " 台账添加成功"); + + it = ledger_update_xml.new_updates.erase(it); + } + + // --- 2. 修改处理 --- + std::cout << "modify ledger num: " << ledger_update_xml.modify_updates.size() << std::endl; + + for (auto& mod_dev : ledger_update_xml.modify_updates) { + auto it = std::find_if(terminal_devlist.begin(), terminal_devlist.end(), + [&](const terminal_dev& d) { return d.terminal_id == mod_dev.terminal_id; }); + + if (it != terminal_devlist.end()) { + remove_loggers_by_terminal_id(mod_dev.terminal_id); + if (update_one_terminal_ledger(mod_dev, *it) != 0) { + send_reply_to_queue(mod_dev.guid, "2", + "终端 id: " + mod_dev.terminal_id + " 台账更新失败,写入失败"); + continue; + } + + if (parse_model_cfg_web_one(it->dev_type).empty()) { + send_reply_to_queue(mod_dev.guid, "2", + "终端 id: " + mod_dev.terminal_id + " 台账更新失败,未找到装置型号"); + continue; + } + + Set_xml_nodeinfo_one(it->dev_type); + init_loggers_bydevid(mod_dev.terminal_id); + send_reply_to_queue(mod_dev.guid, "2", + "终端 id: " + mod_dev.terminal_id + " 台账修改成功"); + } else { + send_reply_to_queue(mod_dev.guid, "2", + "终端 id: " + mod_dev.terminal_id + " 台账修改失败,未找到终端"); + } + } + + // --- 3. 删除处理 --- + std::cout << "delete ledger num: " << ledger_update_xml.delete_updates.size() << std::endl; + + for (auto& del_dev : ledger_update_xml.delete_updates) { + auto it = std::find_if(terminal_devlist.begin(), terminal_devlist.end(), + [&](const terminal_dev& d) { return d.terminal_id == del_dev.terminal_id; }); + + if (it != terminal_devlist.end()) { + remove_loggers_by_terminal_id(del_dev.terminal_id); + terminal_devlist.erase(it); + send_reply_to_queue(del_dev.guid, "2", + "终端 id: " + del_dev.terminal_id + " 台账删除成功"); + } else { + send_reply_to_queue(del_dev.guid, "2", + "终端 id: " + del_dev.terminal_id + " 台账删除失败,未找到终端"); + } + } + + // --- 4. 日志记录 --- + if (!ledger_update_xml.modify_updates.empty() || + !ledger_update_xml.new_updates.empty() || + !ledger_update_xml.delete_updates.empty()) { + create_ledger_log(&ledger_update_xml); + } +} + +//台账更新处理函数 +void check_ledger_update() +{ + static double last_check_time = 0.0; + double now = sGetMsTime(); + + if (now - last_check_time < 3000.0) + return; + + last_check_time = now; + + std::unique_ptr trigger_ledger_update_xml(new trigger_update_xml_t()); + + if (0 == parse_ledger_update_xml(*trigger_ledger_update_xml)) { + print_trigger_update_xml(*trigger_ledger_update_xml); + std::lock_guard lock(ledgermtx); + process_ledger_update(*trigger_ledger_update_xml); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////台账更新记录日志 + +// 获取当前时间并格式化为 "YYYY-MM-DD HH:MM:SS" +std::string get_current_time() { + std::time_t t = std::time(NULL); + struct std::tm tm = *std::localtime(&t); + + char buffer[80]; + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm); + return std::string(buffer); +} + +// 写入日志条目 +void write_log_entry(std::ofstream &log_file, const std::string &action, const std::string &terminal_id, const std::string ¤t_time) { + log_file << terminal_id << "\t" << action << "time:" << current_time << "\n"; +} + +// 创建台账更新日志 +void create_ledger_log(trigger_update_xml_t* ledger_update_xml) { + std::cout << "create_ledger_log." << std::endl; + + std::string log_filename = FRONT_PATH + "/etc/" + LEDGER_UPDATE_FN; + std::ofstream log_file(log_filename.c_str(), std::ios::app); // 以追加模式打开文件 + + if (!log_file.is_open()) { + std::cerr << "Failed to open log file: " << log_filename << std::endl; + return; + } + + std::vector> new_entries; + std::vector> modify_entries; + std::vector> delete_entries; + + std::string current_time = get_current_time(); // 获取当前时间 + + // new_updates + for (const auto& dev : ledger_update_xml->new_updates) { + new_entries.emplace_back(dev.terminal_id, current_time); + } + + // modify_updates + for (const auto& dev : ledger_update_xml->modify_updates) { + modify_entries.emplace_back(dev.terminal_id, current_time); + } + + // delete_updates + for (const auto& dev : ledger_update_xml->delete_updates) { + delete_entries.emplace_back(dev.terminal_id, current_time); + } + + // 写入日志 + if (!new_entries.empty()) { + log_file << "\n"; + for (const auto& entry : new_entries) { + write_log_entry(log_file, "add", entry.first, entry.second); + } + log_file << "\n"; + } + + if (!modify_entries.empty()) { + log_file << "\n"; + for (const auto& entry : modify_entries) { + write_log_entry(log_file, "modify", entry.first, entry.second); + } + log_file << "\n"; + } + + if (!delete_entries.empty()) { + log_file << "\n"; + for (const auto& entry : delete_entries) { + write_log_entry(log_file, "delete", entry.first, entry.second); + } + log_file << "\n"; + } + + log_file.close(); + std::cout << "Ledger log has been updated." << std::endl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////shell打印日志 + +// ------------------ 全局日志列表和锁 ------------------ +std::list errorList; +std::list warnList; +std::list normalList; + +pthread_mutex_t errorListMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t warnListMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t normalListMutex = PTHREAD_MUTEX_INITIALIZER; + +// ------------------ 输出开关 ------------------ +bool errorOutputEnabled = false; // 是否将 error 级别写入 errorList +bool warnOutputEnabled = false; // 是否将 warn 级别写入 warnList +bool normalOutputEnabled = false; // 是否将 normal 级别写入 normalList + +// ------------------ 用于恢复原始缓冲区 ------------------ +static std::streambuf* g_originalCoutBuf = NULL; +static std::streambuf* g_originalClogBuf = NULL; +static std::streambuf* g_originalCerrBuf = NULL; + +// ------------------ 日志级别枚举(C++98) ------------------ +enum LogLevel { + LOGERROR, + LOGWARN, + LOGNORMAL +}; + +// ------------------------------------------------------------------ +// TeeStreamBuf: 先写到原始buf(保持终端输出),再拷贝到list里 +// ------------------------------------------------------------------ +class TeeStreamBuf : public std::streambuf +{ +public: + // 默认构造:先把指针设为NULL + TeeStreamBuf() + : m_originalBuf(NULL), m_level(LOGNORMAL) + { + pthread_mutex_init(&m_mutex, NULL); + } + + // 带参构造:直接初始化 + TeeStreamBuf(std::streambuf* originalBuf, LogLevel level) + : m_originalBuf(originalBuf), m_level(level) + { + pthread_mutex_init(&m_mutex, NULL); + } + + // 析构函数:销毁互斥锁 + virtual ~TeeStreamBuf() + { + pthread_mutex_destroy(&m_mutex); + } + + // 自定义 init(...) 函数:在同一个对象上重新设置 + void init(std::streambuf* originalBuf, LogLevel level) + { + m_originalBuf = originalBuf; + m_level = level; + pthread_mutex_lock(&m_mutex); + m_buffer.clear(); + pthread_mutex_unlock(&m_mutex); + } + +protected: + // 当 flush 或 std::endl 时会调用 sync() + virtual int sync() + { + // 先让原始缓冲区执行同步 + if (m_originalBuf) { + m_originalBuf->pubsync(); + } + // 再将自身的缓存 flush + flushBuffer(); + return 0; // 成功 + } + + // 当写入一个新字符时,overflow() 被调用 + virtual int_type overflow(int_type ch) + { + if (ch == traits_type::eof()) { + return ch; + } + // 1) 写到原始缓冲区 → 保留终端输出 + if (m_originalBuf) { + if (m_originalBuf->sputc(static_cast(ch)) == traits_type::eof()) { + return traits_type::eof(); + } + } + // 2) 存到我们的临时缓存,注意加锁保护 + pthread_mutex_lock(&m_mutex); //防止多线程推入崩溃lnk20250305 + m_buffer.push_back(static_cast(ch)); + // 3) 遇到换行就 flushBuffer() + if (ch == '\n') { + flushBuffer_locked(); + } + pthread_mutex_unlock(&m_mutex); + return ch; + } + +private: + // 内部版本:假定互斥锁已经被加锁 + void flushBuffer_locked() + { + if (m_buffer.empty()) { + return; + } + // 根据等级和对应开关,将 m_buffer 写入相应的 list + switch (m_level) { + case LOGERROR: + if (normalOutputEnabled) { + pthread_mutex_lock(&normalListMutex); + normalList.push_back(m_buffer); + pthread_mutex_unlock(&normalListMutex); + } + else if (warnOutputEnabled) { + pthread_mutex_lock(&warnListMutex); + warnList.push_back(m_buffer); + pthread_mutex_unlock(&warnListMutex); + } + else if (errorOutputEnabled) { + pthread_mutex_lock(&errorListMutex); + errorList.push_back(m_buffer); + pthread_mutex_unlock(&errorListMutex); + } + break; + + case LOGWARN: + if (normalOutputEnabled) { + pthread_mutex_lock(&normalListMutex); + normalList.push_back(m_buffer); + pthread_mutex_unlock(&normalListMutex); + } + else if (warnOutputEnabled) { + pthread_mutex_lock(&warnListMutex); + warnList.push_back(m_buffer); + pthread_mutex_unlock(&warnListMutex); + } + break; + + case LOGNORMAL: + if (normalOutputEnabled) { + pthread_mutex_lock(&normalListMutex); + normalList.push_back(m_buffer); + pthread_mutex_unlock(&normalListMutex); + } + break; + } + m_buffer.clear(); + } + + // 对外接口,内部对 m_buffer 加锁 + void flushBuffer() + { + pthread_mutex_lock(&m_mutex); + flushBuffer_locked(); + pthread_mutex_unlock(&m_mutex); + } + +private: + // 禁止自动生成的赋值函数 + TeeStreamBuf& operator=(const TeeStreamBuf&); + +private: + std::streambuf* m_originalBuf; + LogLevel m_level; + std::string m_buffer; + pthread_mutex_t m_mutex; +}; + +// ------------------ 全局Tee对象(避免重复赋值) ------------------ +static TeeStreamBuf g_errorTeeBuf; +static TeeStreamBuf g_warnTeeBuf; +static TeeStreamBuf g_normalTeeBuf; + +// ------------------ 重定向函数 ------------------ +// 只在第一次启用时,用 init(...) 初始化 TeeStreamBuf; +// 之后再启用时,不再 new 或 赋值,而是直接用之前构造好的对象。 +void redirectErrorOutput(bool enabled) +{ + errorOutputEnabled = enabled; + if (enabled) { + if (g_originalCerrBuf == NULL) { + g_originalCerrBuf = std::cerr.rdbuf(); + g_errorTeeBuf.init(g_originalCerrBuf, LOGERROR); + } + std::cerr.rdbuf(&g_errorTeeBuf); + } else { + if (g_originalCerrBuf) { + std::cerr.rdbuf(g_originalCerrBuf); + } + } +} + +void redirectWarnOutput(bool enabled) +{ + warnOutputEnabled = enabled; + if (enabled) { + if (g_originalClogBuf == NULL) { + g_originalClogBuf = std::clog.rdbuf(); + g_warnTeeBuf.init(g_originalClogBuf, LOGWARN); + } + std::clog.rdbuf(&g_warnTeeBuf); + } else { + if (g_originalClogBuf) { + std::clog.rdbuf(g_originalClogBuf); + } + } +} + +void redirectNormalOutput(bool enabled) +{ + normalOutputEnabled = enabled; + if (enabled) { + if (g_originalCoutBuf == NULL) { + g_originalCoutBuf = std::cout.rdbuf(); + g_normalTeeBuf.init(g_originalCoutBuf, LOGNORMAL); + } + std::cout.rdbuf(&g_normalTeeBuf); + } else { + if (g_originalCoutBuf) { + std::cout.rdbuf(g_originalCoutBuf); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////脚本控制 + +void execute_bash(string fun,int process_num,string type) +{ + // 为 char 数组分配足够的空间 + char p_num_str[20]; + // 使用 sprintf 转换 + std::sprintf(p_num_str, "%d", process_num); + const char* script = std::string(FRONT_PATH + "/bin/set_process.sh").c_str();//使用setsid防止端口占用 + const char* param1 = fun.c_str(); + const char* param2 = p_num_str; + const char* param3 = type.c_str(); + + // 构造完整的命令 + char command[256]; + snprintf(command, sizeof(command), "%s %s %s %s &", script, param1, param2, param3); + + std::cout << "command:" << command < *ctopiclist, const std::string& path) +{ + // 注释同原代码 + const std::string strPhasic[4] = { "A", "B", "C", "T" }; + const std::string strLine[4] = { "AB", "BC", "CA", "T" }; + int nStart = 1, nEnd = 1; + std::string strValueTemp; + + tinyxml2::XMLDocument doc; + std::string xmlFile; + if (path == "not define") { + xmlFile = FRONT_PATH + "/etc/" + DEFAULT_CONFIG_FN; //默认映射文件 + std::cout << "[调试] 加载XML路径: " << xmlFile << std::endl; + } else { + xmlFile = FRONT_PATH + "/dat/" + path + ".xml"; + std::cout << "[调试] 加载XML路径: " << xmlFile << std::endl; + } + auto result = doc.LoadFile(xmlFile.c_str()); + if (result != tinyxml2::XML_SUCCESS) { + std::cout << "[错误] 无法打开XML文件: " << xmlFile << std::endl; + return false; + } + + tinyxml2::XMLElement* root = doc.RootElement(); + if (!root) { + std::cout << "[错误] XML无根节点!" << std::endl; + return false; + } + for (tinyxml2::XMLElement* topicElem = root->FirstChildElement(); topicElem; topicElem = topicElem->NextSiblingElement()) { + std::string strTag = topicElem->Name(); + if (strTag == "Topic") { + CTopic* topic = new CTopic(); + topic->strTopic = topicElem->Attribute("name") ? topicElem->Attribute("name") : ""; + ctopiclist->push_back(topic); + std::cout << "[调试] 解析Topic节点: " << topic->strTopic << std::endl; + + // HISDATA、RTDATA + if (topic->strTopic == "HISDATA" || topic->strTopic == "RTDATA") { + for (tinyxml2::XMLElement* dataTypeElem = topicElem->FirstChildElement(); dataTypeElem; dataTypeElem = dataTypeElem->NextSiblingElement()) { + if (std::string(dataTypeElem->Name()) == "DataType") { + CDataType* dt = new CDataType(); + dt->iDataType = dataTypeElem->IntAttribute("value", 0); + dt->type = dataTypeElem->Attribute("type") ? dataTypeElem->Attribute("type") : ""; + dt->BaseFlag0 = 0; + dt->BaseFlag1 = 0; + topic->DataTypeList.push_back(dt); + + // 监测点 + for (tinyxml2::XMLElement* monitorElem = dataTypeElem->FirstChildElement(); monitorElem; monitorElem = monitorElem->NextSiblingElement()) { + if (std::string(monitorElem->Name()) == "Monitor") { + CMonitor* mt = new CMonitor(); + mt->strMonitor = monitorElem->Attribute("name") ? monitorElem->Attribute("name") : ""; + mt->type = monitorElem->Attribute("type") ? monitorElem->Attribute("type") : ""; + dt->MonitorList.push_back(mt); + + // 数据项 + for (tinyxml2::XMLElement* itemElem = monitorElem->FirstChildElement(); itemElem; itemElem = itemElem->NextSiblingElement()) { + if (std::string(itemElem->Name()) == "Item") { + CItem* it = new CItem(); + it->strItemName = itemElem->Attribute("name") ? itemElem->Attribute("name") : ""; + it->type = itemElem->Attribute("type") ? itemElem->Attribute("type") : ""; + if (it->strItemName == "FLAG") + it->strItemValue = itemElem->Attribute("value") ? itemElem->Attribute("value") : ""; + mt->ItemList.push_back(it); + + // Sequence + for (tinyxml2::XMLElement* seqElem = itemElem->FirstChildElement(); seqElem; seqElem = seqElem->NextSiblingElement()) { + if (std::string(seqElem->Name()) == "Sequence") { + std::string strPhase = seqElem->Attribute("value") ? seqElem->Attribute("value") : ""; + + // 读取ABC三相 + if ((!xml_flag || it->strItemName != "V") && strPhase == "7") { + for (int n = 0; n < 3; ++n) { + CSequence* sq = new CSequence(); + sq->strSValue = strPhase; + sq->type = seqElem->Attribute("type") ? seqElem->Attribute("type") : ""; + sq->strSeq = strPhasic[n]; + it->SequenceList.push_back(sq); + + for (tinyxml2::XMLElement* valueElem = seqElem->FirstChildElement(); valueElem; valueElem = valueElem->NextSiblingElement()) { + if (std::string(valueElem->Name()) == "Value") { + std::string strDVName = valueElem->Attribute("name") ? valueElem->Attribute("name") : ""; + std::string strDAName = valueElem->Attribute("DA") ? valueElem->Attribute("DA") : ""; + + // l_phs* → phsAB + if (strDAName.find("l_phs*") != std::string::npos) { + strDAName.replace(strDAName.find("l_phs"), 5, "phs"); + size_t starPos = strDAName.find("*"); + if (starPos != std::string::npos) + strDAName.replace(starPos, 1, strLine[n]); + } else if (strDAName.find("phs*") != std::string::npos) { + size_t starPos = strDAName.find("*"); + if (starPos != std::string::npos) + strDAName.replace(starPos, 1, sq->strSeq); + } + + // 谐波数据 + if (strDVName.find("%") != std::string::npos && strDAName.find("%-") != std::string::npos) { + size_t firstP = strDVName.find('%'), lastP = strDVName.rfind('%'); + if (firstP != std::string::npos && lastP != std::string::npos && firstP != lastP) { + std::string harmRange = strDVName.substr(firstP + 1, lastP - firstP - 1); // 0,49 + size_t comma = harmRange.find(','); + if (comma != std::string::npos) { + nStart = std::stoi(harmRange.substr(0, comma)); + nEnd = std::stoi(harmRange.substr(comma + 1)); + strValueTemp = "%" + harmRange + "%"; + } + } + // 取DA的范围 + size_t lb = strDAName.find('['), rb = strDAName.find(']'); + int strDAoffset = 0; + if (lb != std::string::npos && rb != std::string::npos && lb < rb) { + std::string sub = strDAName.substr(lb + 1, rb - lb - 1); + size_t dash = sub.find('-'); + if (dash != std::string::npos) + strDAoffset = std::stoi(sub.substr(dash + 1)); + } + int offset = valueElem->IntAttribute("Offset", 0); + for (int i = nStart; i <= nEnd; ++i) { + std::string strDVNameTemp = strDVName; + std::string strDANameTemp = strDAName; + CDataValue* dv1 = new CDataValue(); + dv1->type = valueElem->Attribute("type") ? valueElem->Attribute("type") : ""; + if (valueElem->Attribute("Coefficient")) { + dv1->strCoefficient = valueElem->Attribute("Coefficient"); + dv1->fCoefficient = valueElem->FloatAttribute("Coefficient", 1.0f); + } + dv1->strOffset = valueElem->Attribute("Offset") ? valueElem->Attribute("Offset") : ""; + dv1->iOffset = offset; + dv1->DO = valueElem->Attribute("DO") ? valueElem->Attribute("DO") : ""; + + size_t tmpPos = strDVNameTemp.find(strValueTemp); + if (tmpPos != std::string::npos) + strDVNameTemp.replace(tmpPos, strValueTemp.size(), std::to_string(i + offset)); + size_t subPos = strDANameTemp.find('['); + size_t subPos2 = strDANameTemp.find(']'); + if (subPos != std::string::npos && subPos2 != std::string::npos) + strDANameTemp.replace(subPos + 1, subPos2 - subPos - 1, std::to_string(i - strDAoffset)); + dv1->strName = strDVNameTemp; + dv1->DA = strDANameTemp; + + // BaseFlag, LimitUp, LimitDown + if (valueElem->Attribute("BaseFlag")) { + dv1->BaseFlag = valueElem->Attribute("BaseFlag"); + if (dv1->BaseFlag == "1") dt->BaseFlag1++; else dt->BaseFlag0++; + } else { + dt->BaseFlag0++; + dv1->BaseFlag = "0"; + } + dv1->LimitUp = valueElem->Attribute("LimitUp") ? valueElem->Attribute("LimitUp") : "not define"; + dv1->LimitDown = valueElem->Attribute("LimitDown") ? valueElem->Attribute("LimitDown") : "not define"; + + if (!dv1->DO.empty() && !dv1->DA.empty()) + dv1->strFullName = dv1->DO + "$" + dv1->DA; + else + dv1->strFullName = "not define"; + sq->DataValueList.push_back(dv1); + + // 调试打印谐波展开 + std::cout << "[调试] 谐波展开DataValue: " << dv1->strName << " DA=" << dv1->DA << std::endl; + } + } else { + // 非谐波数据 + CDataValue* dv2 = new CDataValue(); + dv2->strName = strDVName; + dv2->type = valueElem->Attribute("type") ? valueElem->Attribute("type") : ""; + if (valueElem->Attribute("Coefficient")) { + dv2->strCoefficient = valueElem->Attribute("Coefficient"); + dv2->fCoefficient = valueElem->FloatAttribute("Coefficient", 1.0f); + } + dv2->DO = valueElem->Attribute("DO") ? valueElem->Attribute("DO") : ""; + dv2->DA = strDAName; + + if (valueElem->Attribute("BaseFlag")) { + dv2->BaseFlag = valueElem->Attribute("BaseFlag"); + if (dv2->BaseFlag == "1") dt->BaseFlag1++; else dt->BaseFlag0++; + } else { + dt->BaseFlag0++; + dv2->BaseFlag = "0"; + } + dv2->LimitUp = valueElem->Attribute("LimitUp") ? valueElem->Attribute("LimitUp") : "not define"; + dv2->LimitDown = valueElem->Attribute("LimitDown") ? valueElem->Attribute("LimitDown") : "not define"; + + if (valueElem->Attribute("PltFlag") && std::string(valueElem->Attribute("PltFlag")) == "True") + dv2->bPlt = true; + else + dv2->bPlt = false; + if (!dv2->DO.empty() && !dv2->DA.empty()) + dv2->strFullName = dv2->DO + "$" + dv2->DA; + else + dv2->strFullName = "not define"; + sq->DataValueList.push_back(dv2); + + std::cout << "[调试] 普通DataValue: " << dv2->strName << " DA=" << dv2->DA << std::endl; + } + } + } + } + } + + // T相 + if (strPhase == "8") { + CSequence* sq = new CSequence(); + sq->strSValue = strPhase; + sq->type = seqElem->Attribute("type") ? seqElem->Attribute("type") : ""; + sq->strSeq = strPhasic[3]; + it->SequenceList.push_back(sq); + for (tinyxml2::XMLElement* valueElem = seqElem->FirstChildElement(); valueElem; valueElem = valueElem->NextSiblingElement()) { + if (std::string(valueElem->Name()) == "Value") { + CDataValue* dv2 = new CDataValue(); + dv2->strName = valueElem->Attribute("name") ? valueElem->Attribute("name") : ""; + dv2->type = valueElem->Attribute("type") ? valueElem->Attribute("type") : ""; + if (valueElem->Attribute("Coefficient")) { + dv2->strCoefficient = valueElem->Attribute("Coefficient"); + dv2->fCoefficient = valueElem->FloatAttribute("Coefficient", 1.0f); + } + dv2->DO = valueElem->Attribute("DO") ? valueElem->Attribute("DO") : ""; + dv2->DA = valueElem->Attribute("DA") ? valueElem->Attribute("DA") : ""; + + if (valueElem->Attribute("BaseFlag")) { + dv2->BaseFlag = valueElem->Attribute("BaseFlag"); + if (dv2->BaseFlag == "1") dt->BaseFlag1++; else dt->BaseFlag0++; + } else { + dt->BaseFlag0++; + dv2->BaseFlag = "0"; + } + dv2->LimitUp = valueElem->Attribute("LimitUp") ? valueElem->Attribute("LimitUp") : "not define"; + dv2->LimitDown = valueElem->Attribute("LimitDown") ? valueElem->Attribute("LimitDown") : "not define"; + if (!dv2->DO.empty() && !dv2->DA.empty()) + dv2->strFullName = dv2->DO + "$" + dv2->DA; + else + dv2->strFullName = "not define"; + sq->DataValueList.push_back(dv2); + + std::cout << "[调试] T相DataValue: " << dv2->strName << std::endl; + } + } + } + } + } + } + } + } + } + } + } + } + // RTDATASOE + else if (topic->strTopic == "RTDATASOE") { + for (tinyxml2::XMLElement* dataTypeElem = topicElem->FirstChildElement(); dataTypeElem; dataTypeElem = dataTypeElem->NextSiblingElement()) { + if (std::string(dataTypeElem->Name()) == "DataType") { + CDataType* dt = new CDataType(); + dt->iDataType = dataTypeElem->IntAttribute("value", 0); + dt->type = dataTypeElem->Attribute("type") ? dataTypeElem->Attribute("type") : ""; + topic->DataTypeList.push_back(dt); + + for (tinyxml2::XMLElement* soeElem = dataTypeElem->FirstChildElement(); soeElem; soeElem = soeElem->NextSiblingElement()) { + if (std::string(soeElem->Name()) == "SOE") { + CEventData* ed = new CEventData(); + ed->triggerFlag = soeElem->Attribute("TriggerFlag") ? soeElem->Attribute("TriggerFlag") : ""; + ed->DO = soeElem->Attribute("DO") ? soeElem->Attribute("DO") : ""; + ed->DA = soeElem->Attribute("DA") ? soeElem->Attribute("DA") : ""; + ed->type = soeElem->Attribute("type") ? soeElem->Attribute("type") : ""; + if (!ed->DO.empty() && !ed->DA.empty()) + ed->strFullName = ed->DO + "$" + ed->DA; + else + ed->strFullName = "not define"; + dt->SOEList.push_back(ed); + std::cout << "[调试] SOE事件: " << ed->strFullName << std::endl; + } + } + } + } + } + // SOEDATA + else if (topic->strTopic == "SOEDATA") { + for (tinyxml2::XMLElement* dataTypeElem = topicElem->FirstChildElement(); dataTypeElem; dataTypeElem = dataTypeElem->NextSiblingElement()) { + if (std::string(dataTypeElem->Name()) == "DataType") { + CEventData* ed = new CEventData(); + ed->triggerFlag = dataTypeElem->Attribute("name") ? dataTypeElem->Attribute("name") : ""; + ed->DO = dataTypeElem->Attribute("DO") ? dataTypeElem->Attribute("DO") : ""; + ed->DA = dataTypeElem->Attribute("DA") ? dataTypeElem->Attribute("DA") : ""; + ed->type = dataTypeElem->Attribute("type") ? dataTypeElem->Attribute("type") : ""; + if (!ed->DO.empty() && !ed->DA.empty()) + ed->strFullName = ed->DO + "$" + ed->DA; + else + ed->strFullName = "not define"; + cfg->SOEList.push_back(ed); + std::cout << "[调试] SOEDATA事件: " << ed->strFullName << std::endl; + } + } + } + } + // 其他节点 + else if (strTag == "WavePhasic") { + const char* flagAttr = topicElem->Attribute("Flag"); + if (flagAttr) + cfg->WavePhasicFlag = flagAttr; + if (!cfg->WavePhasicFlag.empty() && cfg->WavePhasicFlag == "1") { + const char* aAttr = topicElem->Attribute("A"); + if (aAttr) cfg->WavePhasicA = aAttr; + const char* bAttr = topicElem->Attribute("B"); + if (bAttr) cfg->WavePhasicB = bAttr; + const char* cAttr = topicElem->Attribute("C"); + if (cAttr) cfg->WavePhasicC = cAttr; + } + std::cout << "[调试] WavePhasic解析" << std::endl; + } else if (strTag == "UnitOfTime") { + const char* unitAttr = topicElem->Attribute("Unit"); + if (unitAttr) + cfg->UnitOfTimeUnit = unitAttr; + std::cout << "[调试] UnitOfTime解析" << std::endl; + } else if (strTag == "ValueOfTime") { + const char* unitAttr = topicElem->Attribute("Unit"); + if (unitAttr) + cfg->ValueOfTimeUnit = unitAttr; + std::cout << "[调试] ValueOfTime解析" << std::endl; + } else if (strTag == "ComtradeFile") { + const char* waveTimeFlag = topicElem->Attribute("WaveTimeFlag"); + if (waveTimeFlag) + cfg->WaveTimeFlag = waveTimeFlag; + std::cout << "[调试] ComtradeFile解析" << std::endl; + } else if (strTag == "IED") { + const char* nameAttr = topicElem->Attribute("name"); + if (nameAttr) + cfg->IEDname = nameAttr; + std::cout << "[调试] IED解析" << std::endl; + } else if (strTag == "LDevice") { + const char* prefixAttr = topicElem->Attribute("Prefix"); + if (prefixAttr) + cfg->LDevicePrefix = prefixAttr; + std::cout << "[调试] LDevice解析" << std::endl; + } + + } + return true; +} + +//清理旧的映射配置 +void clearXmlConfigAndTopicList(Xmldata* data) { + // 清空 XmlConfig + data->xmlcfg = XmlConfig(); // 通过重新赋值重置 xmlcfg + + // 清空 topicList + std::list::iterator it; + for (it = data->topicList.begin(); it != data->topicList.end(); ++it) { + delete *it; // 释放内存 + } + data->topicList.clear(); // 清空链表 +} + +//配置映射文件单个 +void Set_xml_nodeinfo_one(const std::string& dev_type) +{ + bool ret = false; + + // 假定 xmlinfo_list 是 std::map + if (xmlinfo_list.count(dev_type) && xmlinfo_list[dev_type] != nullptr) { // 已存在这个类型的节点 + if (xmlinfo_list[dev_type]->updataflag == true) { // 需要更新 + + // 删除这个点的 xmlcfg 和 topicList + clearXmlConfigAndTopicList(xmlinfo_list[dev_type]); + + ret = ParseXMLConfig2( + 0, + &(xmlinfo_list[dev_type]->xmlcfg), + &(xmlinfo_list[dev_type]->topicList), + xmlinfo_list[dev_type]->xmlbase.MODEL_ID + ); + if (!ret) { + std::cout << "!!!! this ledger xml config fail!!!!" << std::endl; + } + } + } + else { + std::cout << "xmlinfo_list not contain this devtype" << std::endl; + } + + // 处理角形 + if (isdelta_flag) { + if (xmlinfo_list2.count(dev_type) && xmlinfo_list2[dev_type] != nullptr) { // 已存在 + if (xmlinfo_list2[dev_type]->updataflag == true) { // 需要更新 + + // 删除这个点的 xmlcfg 和 topicList + clearXmlConfigAndTopicList(xmlinfo_list2[dev_type]); + + ret = ParseXMLConfig2( + 1, + &(xmlinfo_list2[dev_type]->xmlcfg), + &(xmlinfo_list2[dev_type]->topicList), + xmlinfo_list2[dev_type]->xmlbase.MODEL_ID + ); + if (!ret) { + std::cout << "!!!! this ledger xml config fail!!!!" << std::endl; + } + } + } + else { + std::cout << "xmlinfo_list2 not contain this devtype" << std::endl; + } + } +} + +//配置映射文件全部 +void Set_xml_nodeinfo() +{ + // 配置无对应 xml 文件时的默认解析配置 + if (!DEFAULT_CONFIG_FN.empty()) { //可改为在配置中读取默认映射文件名 + std::string path = "not define"; + ParseXMLConfig2(0, &xmlcfg, &topicList, path); // 调用 ParseXMLConfig() 解析 JiangSu_Config.xml 配置文件 + if (isdelta_flag) { + ParseXMLConfig2(1, &xmlcfg2, &topicList2, path); // 角型接线 + } + } + + if (!xmlinfo_list.empty()) { + std::cout << "!!!!!!!!!! xmlinfo_list.size() != 0 !!!!!!!!!!!" << std::endl; + + for (auto& pair : xmlinfo_list) { + const std::string& key = pair.first; + Xmldata* value = pair.second; + + if (value && value->updataflag) { + ParseXMLConfig2(0, &(value->xmlcfg), &(value->topicList), value->xmlbase.MODEL_ID); + } + } + + if (isdelta_flag) { + for (auto& pair : xmlinfo_list2) { + const std::string& key = pair.first; + Xmldata* value = pair.second; + + if (value && value->updataflag) { + ParseXMLConfig2(1, &(value->xmlcfg), &(value->topicList), value->xmlbase.MODEL_ID); + } + } + } + + } else { + std::cout << "!!!!!!!!!! xmlinfo_list.size() == 0 !!!!!!!!!!!" << std::endl; + } +} + + diff --git a/LFtid1056/cloudfront/code/curl/Makefile b/LFtid1056/cloudfront/code/curl/Makefile new file mode 100644 index 0000000..4f7f295 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/Makefile @@ -0,0 +1,663 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# include/curl/Makefile. Generated from Makefile.in by configure. + +# 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. + + + + +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)/curl +pkglibdir = $(libdir)/curl +pkglibexecdir = $(libexecdir)/curl +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 = x86_64-pc-linux-gnu +host_triplet = x86_64-pc-linux-gnu +subdir = include/curl +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(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-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-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_$(V)) +am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +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 = ${SHELL} '/home/pq/ToolProject/src/curl-8.12.1/missing' aclocal-1.16 +AMTAR = $${TAR-tar} +AM_DEFAULT_VERBOSITY = 0 +APXS = +AR = /opt/rh/devtoolset-8/root/usr/bin/ar +AR_FLAGS = cr +AS = as +AUTOCONF = ${SHELL} '/home/pq/ToolProject/src/curl-8.12.1/missing' autoconf +AUTOHEADER = ${SHELL} '/home/pq/ToolProject/src/curl-8.12.1/missing' autoheader +AUTOMAKE = ${SHELL} '/home/pq/ToolProject/src/curl-8.12.1/missing' automake-1.16 +AWK = gawk +BLANK_AT_MAKETIME = +CADDY = /usr/bin/caddy +CC = gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -Werror-implicit-function-declaration -O2 -Wno-system-headers -pthread +CFLAG_CURL_SYMBOL_HIDING = -fvisibility=hidden +CONFIGURE_OPTIONS = " '--with-ssl' '--without-libpsl'" +CPP = gcc -E +CPPFLAGS = -D_GNU_SOURCE +CSCOPE = cscope +CTAGS = ctags +CURLVERSION = 8.12.1 +CURL_CA_BUNDLE = /etc/pki/tls/certs/ca-bundle.crt +CURL_CA_EMBED = +CURL_CFLAG_EXTRAS = +CURL_CPP = gcc -E -D_GNU_SOURCE +CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX = +CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME = 4 +CURL_NETWORK_AND_TIME_LIBS = +CYGPATH_W = echo +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /usr/bin/grep -E +ENABLE_SHARED = yes +ENABLE_STATIC = yes +ETAGS = etags +EXEEXT = +FGREP = /usr/bin/grep -F +FILECMD = file +FISH_FUNCTIONS_DIR = +GCOV = +GREP = /usr/bin/grep +HAVE_LIBZ = 1 +HTTPD = +HTTPD_NGHTTPX = +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LCOV = +LD = /opt/rh/devtoolset-8/root/usr/libexec/gcc/x86_64-redhat-linux/8/ld -m elf_x86_64 +LDFLAGS = +LIBCURL_PC_CFLAGS = +LIBCURL_PC_CFLAGS_PRIVATE = -DCURL_STATICLIB +LIBCURL_PC_LDFLAGS_PRIVATE = +LIBCURL_PC_LIBS = +LIBCURL_PC_LIBS_PRIVATE = -lssl -lcrypto -lz -pthread +LIBCURL_PC_REQUIRES = +LIBCURL_PC_REQUIRES_PRIVATE = zlib,openssl +LIBOBJS = +LIBS = -lssl -lcrypto -lz +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBOBJS = +LT_SYS_LIBRARY_PATH = +MAINT = # +MAKEINFO = ${SHELL} '/home/pq/ToolProject/src/curl-8.12.1/missing' makeinfo +MANIFEST_TOOL = : +MKDIR_P = /usr/bin/mkdir -p +NM = /opt/rh/devtoolset-8/root/usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = curl +PACKAGE_BUGREPORT = a suitable curl mailing list: https://curl.se/mail/ +PACKAGE_NAME = curl +PACKAGE_STRING = curl - +PACKAGE_TARNAME = curl +PACKAGE_URL = +PACKAGE_VERSION = - +PATH_SEPARATOR = : +PERL = /usr/bin/perl +PKGCONFIG = no +RANLIB = ranlib +RC = +SED = /usr/bin/sed +SET_MAKE = +SHELL = /bin/sh +SSL_BACKENDS = OpenSSL +STRIP = strip +SUPPORT_FEATURES = alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets +SUPPORT_PROTOCOLS = DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS IPFS IPNS MQTT POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP WS WSS +TEST_NGHTTPX = nghttpx +VERSION = - +VERSIONNUM = 080c01 +VSFTPD = /usr/sbin/vsftpd +ZLIB_LIBS = -lz +ZSH_FUNCTIONS_DIR = +abs_builddir = /home/pq/ToolProject/src/curl-8.12.1/include/curl +abs_srcdir = /home/pq/ToolProject/src/curl-8.12.1/include/curl +abs_top_builddir = /home/pq/ToolProject/src/curl-8.12.1 +abs_top_srcdir = /home/pq/ToolProject/src/curl-8.12.1 +ac_ct_AR = +ac_ct_CC = gcc +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +build = x86_64-pc-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = pc +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-pc-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = pc +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /home/pq/ToolProject/src/curl-8.12.1/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +libext = a +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = $(MKDIR_P) +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +runstatedir = ${localstatedir}/run +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target_alias = +top_build_prefix = ../../ +top_builddir = ../.. +top_srcdir = ../.. + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , 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. +# +# SPDX-License-Identifier: curl +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h options.h header.h websockets.h + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: # $(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) --gnu include/curl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu 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: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(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 +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)/usr/bin/perl $(top_srcdir)/scripts/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +# for debug builds, we scan the sources on all regular make invokes +#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: diff --git a/LFtid1056/cloudfront/code/curl/Makefile.am b/LFtid1056/cloudfront/code/curl/Makefile.am new file mode 100644 index 0000000..8864d60 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/Makefile.am @@ -0,0 +1,41 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , 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. +# +# SPDX-License-Identifier: curl +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h options.h header.h websockets.h + +pkgincludedir= $(includedir)/curl + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + +checksrc: + $(CHECKSRC)@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +if DEBUGBUILD +# for debug builds, we scan the sources on all regular make invokes +all-local: checksrc +endif diff --git a/LFtid1056/cloudfront/code/curl/Makefile.in b/LFtid1056/cloudfront/code/curl/Makefile.in new file mode 100644 index 0000000..8947636 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/Makefile.in @@ -0,0 +1,663 @@ +# 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/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-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-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@ +APXS = @APXS@ +AR = @AR@ +AR_FLAGS = @AR_FLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@ +CADDY = @CADDY@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@ +CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURLVERSION = @CURLVERSION@ +CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ +CURL_CA_EMBED = @CURL_CA_EMBED@ +CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ +CURL_CPP = @CURL_CPP@ +CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX = @CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX@ +CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME = @CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME@ +CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SHARED = @ENABLE_SHARED@ +ENABLE_STATIC = @ENABLE_STATIC@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ +GCOV = @GCOV@ +GREP = @GREP@ +HAVE_LIBZ = @HAVE_LIBZ@ +HTTPD = @HTTPD@ +HTTPD_NGHTTPX = @HTTPD_NGHTTPX@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCURL_PC_CFLAGS = @LIBCURL_PC_CFLAGS@ +LIBCURL_PC_CFLAGS_PRIVATE = @LIBCURL_PC_CFLAGS_PRIVATE@ +LIBCURL_PC_LDFLAGS_PRIVATE = @LIBCURL_PC_LDFLAGS_PRIVATE@ +LIBCURL_PC_LIBS = @LIBCURL_PC_LIBS@ +LIBCURL_PC_LIBS_PRIVATE = @LIBCURL_PC_LIBS_PRIVATE@ +LIBCURL_PC_REQUIRES = @LIBCURL_PC_REQUIRES@ +LIBCURL_PC_REQUIRES_PRIVATE = @LIBCURL_PC_REQUIRES_PRIVATE@ +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@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +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@ +PKGCONFIG = @PKGCONFIG@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_BACKENDS = @SSL_BACKENDS@ +STRIP = @STRIP@ +SUPPORT_FEATURES = @SUPPORT_FEATURES@ +SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ +TEST_NGHTTPX = @TEST_NGHTTPX@ +VERSION = @VERSION@ +VERSIONNUM = @VERSIONNUM@ +VSFTPD = @VSFTPD@ +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@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , 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. +# +# SPDX-License-Identifier: curl +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h options.h header.h websockets.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) --gnu include/curl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu 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 +@DEBUGBUILD_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)/scripts/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +# for debug builds, we scan the sources on all regular make invokes +@DEBUGBUILD_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: diff --git a/LFtid1056/cloudfront/code/curl/curl.h b/LFtid1056/cloudfront/code/curl/curl.h new file mode 100644 index 0000000..84cf5f2 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/curl.h @@ -0,0 +1,3312 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.se/libcurl/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER /* not used since 8.11.0 */ +#endif + +/* Compile-time deprecation macros. */ +#if (defined(__GNUC__) && \ + ((__GNUC__ > 12) || ((__GNUC__ == 12) && (__GNUC_MINOR__ >= 1))) || \ + (defined(__clang__) && __clang_major__ >= 3) || \ + defined(__IAR_SYSTEMS_ICC__)) && \ + !defined(__INTEL_COMPILER) && \ + !defined(CURL_DISABLE_DEPRECATION) && !defined(BUILDING_LIBCURL) +#define CURL_DEPRECATED(version, message) \ + __attribute__((deprecated("since " # version ". " message))) +#if defined(__IAR_SYSTEMS_ICC__) +#define CURL_IGNORE_DEPRECATION(statements) \ + _Pragma("diag_suppress=Pe1444") \ + statements \ + _Pragma("diag_default=Pe1444") +#else +#define CURL_IGNORE_DEPRECATION(statements) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + statements \ + _Pragma("GCC diagnostic pop") +#endif +#else +#define CURL_DEPRECATED(version, message) +#define CURL_IGNORE_DEPRECATION(statements) statements +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things runtime */ + +#include +#include + +#if defined(__FreeBSD__) || defined(__MidnightBSD__) +/* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2.h inclusion if winsock.h already was + included, since they cannot co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ + (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \ + defined(__sun__) || defined(__serenity__) || defined(__vxworks__) +#include +#endif + +#if !defined(_WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(_WIN32) +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURL; +typedef void CURLSH; + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(_WIN32) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS CURL_DEPRECATED(8.3.0, "") = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT CURL_DEPRECATED(8.3.0, "") = 5, + CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS CURL_DEPRECATED(7.61.0, "") = 10, + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK CURL_DEPRECATED(7.82.0, "") = 12, + CURLSSLBACKEND_BEARSSL = 13, + CURLSSLBACKEND_RUSTLS = 14 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_AWSLC CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a filename */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a filename */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The filename to show. If not set, the + actual filename will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE (10*1024*1024) +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a bad buffer size for uploads on Windows, + while 16K for some odd reason performed a lot better. We do the ifndef + check to allow this value to easier be changed at build time for those + who feel adventurous. The practical minimum is about 400 bytes since + libcurl uses a buffer of this size as a scratch area (unrelated to + network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +/* This is a magic return code for the write callback that, when returned, + will signal an error from the callback. */ +#define CURL_WRITEFUNC_ERROR 0xFFFFFFFF + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* These are libcurl private struct fields. Previously used by libcurl, so + they must never be interfered with. */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we do not need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern does not match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking cannot be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors */ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback */ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* This is the CURLOPT_PREREQFUNCTION callback prototype. */ +typedef int (*curl_prereq_callback)(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port); + +/* Return code for when the pre-request callback has terminated without + any errors */ +#define CURL_PREREQFUNC_OK 0 +/* Return code for when the pre-request callback wants to abort the + request */ +#define CURL_PREREQFUNC_ABORT 1 + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - could not open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" did not work */ + CURLE_OBSOLETE34, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - could not resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_OBSOLETE41, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - could not use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + was not verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_OBSOLETE62, /* 62 - NOT IN USE since 7.82.0 */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_OBSOLETE75, /* 75 - NOT IN USE since 7.82.0 */ + CURLE_OBSOLETE76, /* 76 - NOT IN USE since 7.82.0 */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it is ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + CURLE_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */ + CURLE_TOO_LARGE, /* 100 - a value/data met its maximum */ + CURLE_ECH_REQUIRED, /* 101 - ECH tried but failed */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* removed in 7.53.0 */ +#define CURLE_FUNCTION_NOT_FOUND CURLE_OBSOLETE41 + +/* removed in 7.56.0 */ +#define CURLE_HTTP_POST_ERROR CURLE_OBSOLETE34 + +/* Previously obsolete error code reused in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes reused in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* Added for 7.78.0 */ +#define CURLE_TELNET_OPTION_SYNTAX CURLE_SETOPT_OPTION_SYNTAX + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME +#define CURLE_LDAP_INVALID_URL CURLE_OBSOLETE62 +#define CURLE_CONV_REQD CURLE_OBSOLETE76 +#define CURLE_CONV_FAILED CURLE_OBSOLETE75 + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 +#define CURLOPT_OBSOLETE72 9999 +#define CURLOPT_OBSOLETE40 9999 + +#endif /* !CURL_NO_OLDIES */ + +/* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was + * return for the transfers. + */ +typedef enum { + CURLPX_OK, + CURLPX_BAD_ADDRESS_TYPE, + CURLPX_BAD_VERSION, + CURLPX_CLOSED, + CURLPX_GSSAPI, + CURLPX_GSSAPI_PERMSG, + CURLPX_GSSAPI_PROTECTION, + CURLPX_IDENTD, + CURLPX_IDENTD_DIFFER, + CURLPX_LONG_HOSTNAME, + CURLPX_LONG_PASSWD, + CURLPX_LONG_USER, + CURLPX_NO_AUTH, + CURLPX_RECV_ADDRESS, + CURLPX_RECV_AUTH, + CURLPX_RECV_CONNECT, + CURLPX_RECV_REQACK, + CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED, + CURLPX_REPLY_COMMAND_NOT_SUPPORTED, + CURLPX_REPLY_CONNECTION_REFUSED, + CURLPX_REPLY_GENERAL_SERVER_FAILURE, + CURLPX_REPLY_HOST_UNREACHABLE, + CURLPX_REPLY_NETWORK_UNREACHABLE, + CURLPX_REPLY_NOT_ALLOWED, + CURLPX_REPLY_TTL_EXPIRED, + CURLPX_REPLY_UNASSIGNED, + CURLPX_REQUEST_FAILED, + CURLPX_RESOLVE_HOST, + CURLPX_SEND_AUTH, + CURLPX_SEND_CONNECT, + CURLPX_SEND_REQUEST, + CURLPX_UNKNOWN_FAIL, + CURLPX_UNKNOWN_MODE, + CURLPX_USER_REJECTED, + CURLPX_LAST /* never use */ +} CURLproxycode; + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or wolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* HTTPS but stick to HTTP/1 added in 7.52.0 */ + CURLPROXY_HTTPS2 = 3, /* HTTPS and attempt HTTP/2 added in 8.2.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + hostname rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#ifndef CURL_NO_OLDIES + /* functionality removed since 8.8.0 */ +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#endif +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a null-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we cannot answer right now. + Causes a CURLE_PEER_FAILED_VERIFICATION error but the + connection will be left intact etc */ + CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed with */ + /* CURLOPT_SSH_KEYDATA */ + +typedef int + (*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed */ + /* with CURLOPT_SSH_HOSTKEYDATA */ + int keytype, /* CURLKHTYPE */ + const char *key, /* hostkey to check */ + size_t keylen); /* length of the key */ + /* return CURLE_OK to accept */ + /* or something else to refuse */ + + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1<<2) + +/* - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline + checks and ignore missing revocation list for those SSL backends where such + behavior is present. */ +#define CURLSSLOPT_REVOKE_BEST_EFFORT (1<<3) + +/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of + operating system. Currently implemented under MS-Windows. */ +#define CURLSSLOPT_NATIVE_CA (1<<4) + +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5) + +/* If possible, send data using TLS 1.3 early data */ +#define CURLSSLOPT_EARLYDATA (1<<6) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /* !CURL_NO_OLDIES */ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + + +struct curl_hstsentry { + char *name; + size_t namelen; + unsigned int includeSubDomains:1; + char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */ +}; + +struct curl_index { + size_t index; /* the provided entry's "index" or count */ + size_t total; /* total number of entries to save */ +}; + +typedef enum { + CURLSTS_OK, + CURLSTS_DONE, + CURLSTS_FAIL +} CURLSTScode; + +typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy, + struct curl_hstsentry *e, + void *userp); +typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, + struct curl_hstsentry *e, + struct curl_index *i, + void *userp); + +/* CURLHSTS_* are bits for the CURLOPT_HSTS option */ +#define CURLHSTS_ENABLE (long)(1<<0) +#define CURLHSTS_READONLYFILE (long)(1<<1) + +/* The CURLPROTO_ defines below are for the **deprecated** CURLOPT_*PROTOCOLS + options. Do not use. */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_MQTT (1<<28) +#define CURLPROTO_GOPHERS (1<<29) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 +#define CURLOPTTYPE_BLOB 40000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + + +#define CURLOPT(na,t,nu) na = t + nu +#define CURLOPTDEPRECATED(na,t,nu,v,m) na CURL_DEPRECATED(v,m) = t + nu + +/* CURLOPT aliases that make no runtime difference */ + +/* 'char *' argument to a string with a trailing zero */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'struct curl_slist *' argument */ +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'void *' argument passed untouched to callback */ +#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'long' argument with a set of values/bitmask */ +#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG + +/* + * All CURLOPT_* values. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1), + + /* The full URL to get/put */ + CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3), + + /* Name of proxy to use. */ + CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13), + + /* If CURLOPT_READDATA is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14), + + /* POST static input fields. */ + CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19), + + /* Set the "low speed time" */ + CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21), + + /* Set cookie in request: */ + CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CURLOPTDEPRECATED(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24, + 7.56.0, "Use CURLOPT_MIMEPOST"), + + /* name of the file keeping your private SSL-certificate */ + CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26), + + /* send TYPE parameter? */ + CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27), + + /* send linked-list of QUOTE commands */ + CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32), + + /* What kind of HTTP time condition to use, see defines */ + CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), + + /* 40 is not used */ + + /* talk a lot */ + CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), + + /* throw the header out too */ + CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42), + + /* shut off the progress meter */ + CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43), + + /* use HEAD to get http document */ + CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44), + + /* no output on http error codes >= 400 */ + CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45), + + /* this is an upload */ + CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46), + + /* HTTP POST method */ + CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47), + + /* bare names when listing directories */ + CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48), + + /* Append instead of overwrite on upload! */ + CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50), + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51), + + /* use Location: Luke! */ + CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52), + + /* transfer data in text/ASCII format */ + CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53), + + /* HTTP PUT */ + CURLOPTDEPRECATED(CURLOPT_PUT, CURLOPTTYPE_LONG, 54, + 7.12.1, "Use CURLOPT_UPLOAD"), + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CURLOPTDEPRECATED(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56, + 7.32.0, "Use CURLOPT_XFERINFOFUNCTION"), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57), +#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA + + /* We want the referrer field set automatically when following locations */ + CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60), + + /* tunnel non-http operations through an HTTP proxy */ + CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but does not match one of these, 'private' will be used. */ + CURLOPT(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69), + + /* This points to a linked list of telnet options */ + CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), + + /* 72 = OBSOLETE */ + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you are absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be reused + when done. Do not use this unless you are absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75), + + /* Set to a filename that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CURLOPTDEPRECATED(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76, + 7.84.0, "Serves no purpose anymore"), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CURLOPTDEPRECATED(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77, + 7.84.0, "Serves no purpose anymore"), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81), + + /* Specify which filename to write all known cookies in after completed + operation. Set filename to "-" (dash) to make it go to stdout. */ + CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82), + + /* Specify which TLS 1.2 (1.1, 1.0) ciphers to use */ + CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90), + + /* Non-zero value means to use the global dns cache */ + /* DEPRECATED, do not use! */ + CURLOPTDEPRECATED(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91, + 7.11.1, "Use CURLOPT_SHARE"), + + /* DNS cache timeout */ + CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93), + + /* set the debug function */ + CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95), + + /* mark this as start of a cookie session */ + CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102), + + /* Set pointer to private data */ + CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + wolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111), + + /* Option that changes the timeout, in seconds, associated with getting a + response. This is different from transfer timeout time and essentially + places a demand on the server to acknowledge commands in a timely + manner. For FTP, SMTP, IMAP and POP3. */ + CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112), + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115), + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117), + + /* Set this option to the filename of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129), + + CURLOPTDEPRECATED(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130, + 7.18.0, "Use CURLOPT_SEEKFUNCTION"), + CURLOPTDEPRECATED(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131, + 7.18.0, "Use CURLOPT_SEEKDATA"), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* null-terminated string for pass on to the FTP server when asked for + "account" info */ + CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135), + + /* ignore Content-Length */ + CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138), + + /* Local port number to bind the socket to */ + CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPTDEPRECATED(CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPTTYPE_FUNCTIONPOINT, 142, + 7.82.0, "Serves no purpose anymore"), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPTDEPRECATED(CURLOPT_CONV_TO_NETWORK_FUNCTION, + CURLOPTTYPE_FUNCTIONPOINT, 143, + 7.82.0, "Serves no purpose anymore"), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CURLOPTDEPRECATED(CURLOPT_CONV_FROM_UTF8_FUNCTION, + CURLOPTTYPE_FUNCTIONPOINT, 144, + 7.82.0, "Serves no purpose anymore"), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145), + CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147), + + /* callback function for setting socket options */ + CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148), + CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149), + + /* set to 0 to disable session ID reuse for this transfer, default is + enabled (== 1) */ + CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150), + + /* allowed SSH authentication methods */ + CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152), + CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155), + CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157), + CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), + CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), + + /* Set the behavior of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163), + CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164), + + /* POST volatile input fields. */ + CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166), + + /* Callback function for seeking in the input stream */ + CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167), + CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168), + + /* CRL file */ + CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169), + + /* Issuer certificate */ + CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173), + CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175), + CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178), + + /* Socks Service */ + /* DEPRECATED, do not use! */ + CURLOPTDEPRECATED(CURLOPT_SOCKS5_GSSAPI_SERVICE, + CURLOPTTYPE_STRINGPOINT, 179, + 7.49.0, "Use CURLOPT_PROXY_SERVICE_NAME"), + + /* Socks Service */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CURLOPTDEPRECATED(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181, + 7.85.0, "Use CURLOPT_PROTOCOLS_STR"), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CURLOPTDEPRECATED(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182, + 7.85.0, "Use CURLOPT_REDIR_PROTOCOLS_STR"), + + /* set the SSH knownhost filename to use */ + CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185), + + /* set the SMTP mail originator */ + CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189), + + /* The RTSP session identifier */ + CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190), + + /* The RTSP stream URI */ + CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202), + + /* send linked-list of name:port:address sets */ + CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + is not any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208), + CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209), + + /* allow GSSAPI credential delegation */ + CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210), + + /* Set the name servers to use for DNS resolution. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212), + + /* Set TCP keepalive */ + CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214), + CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216), + + /* Set the SMTP auth originator */ + CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223), + + /* Set authentication options directly */ + CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CURLOPTDEPRECATED(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225, + 7.86.0, "Has no function"), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226), + + /* Time to wait for a response to an HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232), + + /* Set if we should enable TLS false start. */ + CURLOPT(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233), + + /* Do not squash dot-dot sequences */ + CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234), + + /* Proxy Service Name */ + CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235), + + /* Service Name */ + CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236), + + /* Wait/do not wait for pipe/mutex to clarify */ + CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239), + + /* Set stream dependency on another curl handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another curl handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250), + + /* Set a username for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258), + + /* Specify which TLS 1.2 (1.1, 1.0) ciphers to use for proxy */ + CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259), + + /* CRL file for proxy */ + CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261), + + /* Name of pre proxy to use. */ + CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265), + + /* The request target, instead of extracted from the URL */ + CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267), + + /* Enable/disable SSH compression */ + CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268), + + /* Post MIME data. */ + CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271), + + /* Function that will be called before a resolver request is made */ + CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276), + CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278), + + /* DNS-over-HTTPS URL */ + CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281), + + /* Specify URL using CURL URL API. */ + CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285), + + /* alt-svc control bitmask */ + CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286), + + /* alt-svc cache filename to possibly read from/write to */ + CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), + + /* maximum age (idle time) of a connection to consider it for reuse + * (in seconds) */ + CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), + + /* SASL authorization identity */ + CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289), + + /* allow RCPT TO command to fail for some recipients */ + CURLOPT(CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOPTTYPE_LONG, 290), + + /* the private SSL-certificate as a "blob" */ + CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291), + CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292), + CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293), + CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294), + CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295), + + /* Issuer certificate for proxy */ + CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296), + CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297), + + /* the EC curves requested by the TLS client (RFC 8422, 5.1); + * OpenSSL support via 'set_groups'/'set_curves': + * https://docs.openssl.org/master/man3/SSL_CTX_set1_curves/ + */ + CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298), + + /* HSTS bitmask */ + CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299), + /* HSTS filename */ + CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300), + + /* HSTS read callback */ + CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301), + CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302), + + /* HSTS write callback */ + CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), + CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + + /* Parameters for V4 signature */ + CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + + /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), + + /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, CURLOPTTYPE_STRINGPOINT, 311), + + /* Function that will be called immediately before the initial request + is made on a connection (after any protocol negotiation step). */ + CURLOPT(CURLOPT_PREREQFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 312), + + /* Data passed to the CURLOPT_PREREQFUNCTION callback */ + CURLOPT(CURLOPT_PREREQDATA, CURLOPTTYPE_CBPOINT, 313), + + /* maximum age (since creation) of a connection to consider it for reuse + * (in seconds) */ + CURLOPT(CURLOPT_MAXLIFETIME_CONN, CURLOPTTYPE_LONG, 314), + + /* Set MIME option flags. */ + CURLOPT(CURLOPT_MIME_OPTIONS, CURLOPTTYPE_LONG, 315), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_HOSTKEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 316), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_HOSTKEYDATA, CURLOPTTYPE_CBPOINT, 317), + + /* specify which protocols that are allowed to be used for the transfer, + which thus helps the app which takes URLs from users or other external + inputs and want to restrict what protocol(s) to deal with. Defaults to + all built-in protocols. */ + CURLOPT(CURLOPT_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 318), + + /* specify which protocols that libcurl is allowed to follow directs to */ + CURLOPT(CURLOPT_REDIR_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 319), + + /* WebSockets options */ + CURLOPT(CURLOPT_WS_OPTIONS, CURLOPTTYPE_LONG, 320), + + /* CA cache timeout */ + CURLOPT(CURLOPT_CA_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 321), + + /* Can leak things, gonna exit() soon */ + CURLOPT(CURLOPT_QUICK_EXIT, CURLOPTTYPE_LONG, 322), + + /* set a specific client IP for HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323), + + /* millisecond version */ + CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), + + /* set ECH configuration */ + CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 325), + + /* maximum number of keepalive probes (Linux, *BSD, macOS, etc.) */ + CURLOPT(CURLOPT_TCP_KEEPCNT, CURLOPTTYPE_LONG, 326), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +/* */ +#define CURLOPT_FTP_RESPONSE_TIMEOUT CURLOPT_SERVER_RESPONSE_TIMEOUT + +/* Added in 8.2.0 */ +#define CURLOPT_MAIL_RCPT_ALLLOWFAILS CURLOPT_MAIL_RCPT_ALLOWFAILS + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */ + + /* Convenient "aliases" */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we do not care, and that we + would like the library to choose the best + possible for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + CURL_HTTP_VERSION_3 = 30, /* Use HTTP/3, fallback to HTTP/2 or HTTP/1 if + needed. For HTTPS only. For HTTP, this option + makes libcurl return error. */ + CURL_HTTP_VERSION_3ONLY = 31, /* Use HTTP/3 without fallback. For HTTPS + only. For HTTP, this makes libcurl + return error. */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +#define CURL_SSLVERSION_DEFAULT 0 +#define CURL_SSLVERSION_TLSv1 1 /* TLS 1.x */ +#define CURL_SSLVERSION_SSLv2 2 +#define CURL_SSLVERSION_SSLv3 3 +#define CURL_SSLVERSION_TLSv1_0 4 +#define CURL_SSLVERSION_TLSv1_1 5 +#define CURL_SSLVERSION_TLSv1_2 6 +#define CURL_SSLVERSION_TLSv1_3 7 + +#define CURL_SSLVERSION_LAST 8 /* never use, keep last */ + +#define CURL_SSLVERSION_MAX_NONE 0 +#define CURL_SSLVERSION_MAX_DEFAULT (CURL_SSLVERSION_TLSv1 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_0 (CURL_SSLVERSION_TLSv1_0 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_1 (CURL_SSLVERSION_TLSv1_1 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_2 (CURL_SSLVERSION_TLSv1_2 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_3 (CURL_SSLVERSION_TLSv1_3 << 16) + + /* never use, keep last */ +#define CURL_SSLVERSION_MAX_LAST (CURL_SSLVERSION_LAST << 16) + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a null-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime curl_mime; /* Mime context. */ +typedef struct curl_mimepart curl_mimepart; /* Mime part context. */ + +/* CURLMIMEOPT_ defines are for the CURLOPT_MIME_OPTIONS option. */ +#define CURLMIMEOPT_FORMESCAPE (1<<0) /* Use backslash-escaping for forms. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote filename. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +typedef enum { + /********* the first one is unused ************/ + CURLFORM_NOTHING CURL_DEPRECATED(7.56.0, ""), + CURLFORM_COPYNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"), + CURLFORM_PTRNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"), + CURLFORM_NAMELENGTH CURL_DEPRECATED(7.56.0, ""), + CURLFORM_COPYCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_PTRCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_CONTENTSLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_FILECONTENT CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"), + CURLFORM_ARRAY CURL_DEPRECATED(7.56.0, ""), + CURLFORM_OBSOLETE, + CURLFORM_FILE CURL_DEPRECATED(7.56.0, "Use curl_mime_filedata()"), + + CURLFORM_BUFFER CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"), + CURLFORM_BUFFERPTR CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_BUFFERLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + + CURLFORM_CONTENTTYPE CURL_DEPRECATED(7.56.0, "Use curl_mime_type()"), + CURLFORM_CONTENTHEADER CURL_DEPRECATED(7.56.0, "Use curl_mime_headers()"), + CURLFORM_FILENAME CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"), + CURLFORM_END, + CURLFORM_OBSOLETE2, + + CURLFORM_STREAM CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"), + CURLFORM_CONTENTLEN /* added in 7.46.0, provide a curl_off_t length */ + CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK CURL_DEPRECATED(7.56.0, ""), /* 1st, no error */ + + CURL_FORMADD_MEMORY CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_OPTION_TWICE CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_NULL CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_UNKNOWN_OPTION CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_INCOMPLETE CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_ILLEGAL_ARRAY CURL_DEPRECATED(7.56.0, ""), + /* libcurl was built with form api disabled */ + CURL_FORMADD_DISABLED CURL_DEPRECATED(7.56.0, ""), + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode CURL_DEPRECATED(7.56.0, "Use curl_mime_init()") +curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int CURL_DEPRECATED(7.56.0, "") +curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void CURL_DEPRECATED(7.56.0, "Use curl_mime_free()") +curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ASCII string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + + * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the + * curl_version_info_data.features flag (fetch by curl_version_info()). + + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines will be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* + * NAME curl_global_trace() + * + * DESCRIPTION + * + * curl_global_trace() can be invoked at application start to + * configure which components in curl should participate in tracing. + + * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the + * curl_version_info_data.features flag (fetch by curl_version_info()). + + */ +CURL_EXTERN CURLcode curl_global_trace(const char *config); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +struct curl_ssl_backend { + curl_sslbackend id; + const char *name; +}; +typedef struct curl_ssl_backend curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *list, + const char *data); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *list); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, for SSL backends that support it. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there is a + linked list with textual information for a + certificate in the format "name:content". + eg "Subject:foo", "Issuer:bar", etc. */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_UPLOAD_T") + = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD + CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_DOWNLOAD_T") + = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD + CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_DOWNLOAD_T") + = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD + CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_UPLOAD_T") + = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD + CURL_DEPRECATED(7.55.0, + "Use CURLINFO_CONTENT_LENGTH_DOWNLOAD_T") + = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD + CURL_DEPRECATED(7.55.0, + "Use CURLINFO_CONTENT_LENGTH_UPLOAD_T") + = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET CURL_DEPRECATED(7.45.0, "Use CURLINFO_ACTIVESOCKET") + = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION CURL_DEPRECATED(7.48.0, "Use CURLINFO_TLS_SSL_PTR") + = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL CURL_DEPRECATED(7.85.0, "Use CURLINFO_SCHEME") + = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, + CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59, + CURLINFO_REFERER = CURLINFO_STRING + 60, + CURLINFO_CAINFO = CURLINFO_STRING + 61, + CURLINFO_CAPATH = CURLINFO_STRING + 62, + CURLINFO_XFER_ID = CURLINFO_OFF_T + 63, + CURLINFO_CONN_ID = CURLINFO_OFF_T + 64, + CURLINFO_QUEUE_TIME_T = CURLINFO_OFF_T + 65, + CURLINFO_USED_PROXY = CURLINFO_LONG + 66, + CURLINFO_POSTTRANSFER_TIME_T = CURLINFO_OFF_T + 67, + CURLINFO_EARLYDATA_SENT_T = CURLINFO_OFF_T + 68, + CURLINFO_HTTPAUTH_USED = CURLINFO_LONG + 69, + CURLINFO_PROXYAUTH_USED = CURLINFO_LONG + 70, + CURLINFO_LASTONE = 70 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_HSTS, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* do not use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option, + ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *share); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, /* 7.10 */ + CURLVERSION_SECOND, /* 7.11.1 */ + CURLVERSION_THIRD, /* 7.12.0 */ + CURLVERSION_FOURTH, /* 7.16.1 */ + CURLVERSION_FIFTH, /* 7.57.0 */ + CURLVERSION_SIXTH, /* 7.66.0 */ + CURLVERSION_SEVENTH, /* 7.70.0 */ + CURLVERSION_EIGHTH, /* 7.72.0 */ + CURLVERSION_NINTH, /* 7.75.0 */ + CURLVERSION_TENTH, /* 7.77.0 */ + CURLVERSION_ELEVENTH, /* 7.87.0 */ + CURLVERSION_TWELFTH, /* 8.8.0 */ + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_TWELFTH + +struct curl_version_info_data { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ + + /* These fields were added in CURLVERSION_SEVENTH */ + const char *cainfo; /* the built-in default CURLOPT_CAINFO, might + be NULL */ + const char *capath; /* the built-in default CURLOPT_CAPATH, might + be NULL */ + + /* These fields were added in CURLVERSION_EIGHTH */ + unsigned int zstd_ver_num; /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *zstd_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_NINTH */ + const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_ELEVENTH */ + /* feature_names is terminated by an entry with a NULL feature name */ + const char * const *feature_names; + + /* These fields were added in CURLVERSION_TWELFTH */ + const char *rtmp_version; /* human readable string. */ +}; +typedef struct curl_version_info_data curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ +#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ +#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ +#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */ +#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */ +#define CURL_VERSION_THREADSAFE (1<<30) /* libcurl API is thread-safe */ + +/* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +/* + * NAME curl_easy_ssls_import() + * + * DESCRIPTION + * + * The curl_easy_ssls_import function adds a previously exported SSL session + * to the SSL session cache of the easy handle (or the underlying share). + */ +CURL_EXTERN CURLcode curl_easy_ssls_import(CURL *handle, + const char *session_key, + const unsigned char *shmac, + size_t shmac_len, + const unsigned char *sdata, + size_t sdata_len); + +/* This is the curl_ssls_export_cb callback prototype. It + * is passed to curl_easy_ssls_export() to extract SSL sessions/tickets. */ +typedef CURLcode curl_ssls_export_cb(CURL *handle, + void *userptr, + const char *session_key, + const unsigned char *shmac, + size_t shmac_len, + const unsigned char *sdata, + size_t sdata_len, + curl_off_t valid_until, + int ietf_tls_id, + const char *alpn, + size_t earlydata_max); + +/* + * NAME curl_easy_ssls_export() + * + * DESCRIPTION + * + * The curl_easy_ssls_export function iterates over all SSL sessions stored + * in the easy handle (or underlying share) and invokes the passed + * callback. + * + */ +CURL_EXTERN CURLcode curl_easy_ssls_export(CURL *handle, + curl_ssls_export_cb *export_fn, + void *userptr); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" +#include "options.h" +#include "header.h" +#include "websockets.h" +#ifndef CURL_SKIP_INCLUDE_MPRINTF +#include "mprintf.h" +#endif + +/* the typechecker does not work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#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) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus && !CURL_DISABLE_TYPECHECK */ + +#endif /* CURLINC_CURL_H */ diff --git a/LFtid1056/cloudfront/code/curl/curlver.h b/LFtid1056/cloudfront/code/curl/curlver.h new file mode 100644 index 0000000..fc8ba4c --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/curlver.h @@ -0,0 +1,79 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* 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 "Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "8.12.1" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 8 +#define LIBCURL_VERSION_MINOR 12 +#define LIBCURL_VERSION_PATCH 1 + +/* 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 0x080c01 + +/* + * 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 "2025-02-13" + +#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 */ diff --git a/LFtid1056/cloudfront/code/curl/easy.h b/LFtid1056/cloudfront/code/curl/easy.h new file mode 100644 index 0000000..56f8060 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/easy.h @@ -0,0 +1,125 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#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 pointing to the specific type of the used option + * which is documented in each manpage of the option. 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 +} /* end of extern "C" */ +#endif + +#endif diff --git a/LFtid1056/cloudfront/code/curl/header.h b/LFtid1056/cloudfront/code/curl/header.h new file mode 100644 index 0000000..8df11e1 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/header.h @@ -0,0 +1,74 @@ +#ifndef CURLINC_HEADER_H +#define CURLINC_HEADER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +struct curl_header { + char *name; /* this might not use the same case */ + char *value; + size_t amount; /* number of headers using this name */ + size_t index; /* ... of this instance, 0 or higher */ + unsigned int origin; /* see bits below */ + void *anchor; /* handle privately used by libcurl */ +}; + +/* 'origin' bits */ +#define CURLH_HEADER (1<<0) /* plain server header */ +#define CURLH_TRAILER (1<<1) /* trailers */ +#define CURLH_CONNECT (1<<2) /* CONNECT headers */ +#define CURLH_1XX (1<<3) /* 1xx headers */ +#define CURLH_PSEUDO (1<<4) /* pseudo headers */ + +typedef enum { + CURLHE_OK, + CURLHE_BADINDEX, /* header exists but not with this index */ + CURLHE_MISSING, /* no such header exists */ + CURLHE_NOHEADERS, /* no headers at all exist (yet) */ + CURLHE_NOREQUEST, /* no request with this number was used */ + CURLHE_OUT_OF_MEMORY, /* out of memory while processing */ + CURLHE_BAD_ARGUMENT, /* a function argument was not okay */ + CURLHE_NOT_BUILT_IN /* if API was disabled in the build */ +} CURLHcode; + +CURL_EXTERN CURLHcode curl_easy_header(CURL *easy, + const char *name, + size_t index, + unsigned int origin, + int request, + struct curl_header **hout); + +CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy, + unsigned int origin, + int request, + struct curl_header *prev); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_HEADER_H */ diff --git a/LFtid1056/cloudfront/code/curl/mprintf.h b/LFtid1056/cloudfront/code/curl/mprintf.h new file mode 100644 index 0000000..88059c8 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/mprintf.h @@ -0,0 +1,85 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CURL_TEMP_PRINTF +#if (defined(__GNUC__) || defined(__clang__) || \ + defined(__IAR_SYSTEMS_ICC__)) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(CURL_NO_FMT_CHECKS) +#if defined(__MINGW32__) && !defined(__clang__) +#if defined(__MINGW_PRINTF_FORMAT) /* mingw-w64 3.0.0+. Needs stdio.h. */ +#define CURL_TEMP_PRINTF(fmt, arg) \ + __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg))) +#else +#define CURL_TEMP_PRINTF(fmt, arg) +#endif +#else +#define CURL_TEMP_PRINTF(fmt, arg) \ + __attribute__((format(printf, fmt, arg))) +#endif +#else +#define CURL_TEMP_PRINTF(fmt, arg) +#endif +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...) + CURL_TEMP_PRINTF(1, 2); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...) + CURL_TEMP_PRINTF(2, 3); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...) + CURL_TEMP_PRINTF(2, 3); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...) + CURL_TEMP_PRINTF(3, 4); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args) + CURL_TEMP_PRINTF(1, 0); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args) + CURL_TEMP_PRINTF(2, 0); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args) + CURL_TEMP_PRINTF(2, 0); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args) + CURL_TEMP_PRINTF(3, 0); +CURL_EXTERN char *curl_maprintf(const char *format, ...) + CURL_TEMP_PRINTF(1, 2); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args) + CURL_TEMP_PRINTF(1, 0); + +#undef CURL_TEMP_PRINTF + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/LFtid1056/cloudfront/code/curl/multi.h b/LFtid1056/cloudfront/code/curl/multi.h new file mode 100644 index 0000000..42469bb --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/multi.h @@ -0,0 +1,481 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +/* + This is an "external" header file. Do not 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 + * 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 + +typedef void CURLM; + +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 are 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_ABORTED_BY_CALLBACK, + CURLM_UNRECOVERABLE_POLL, + 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 do not 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; +}; + +/* + * Name: curl_multi_init() + * + * Desc: initialize 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 is 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 is 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 simple and only contain 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 will 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 manpage 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_DEPRECATED(7.19.5, "Use curl_multi_socket_action()") +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_DEPRECATED(7.19.5, "Use curl_multi_socket_action()") +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_multi_get_handles() + * + * Desc: Returns an allocated array holding all handles currently added to + * the multi handle. Marks the final entry with a NULL pointer. If + * there is no easy handle added to the multi handle, this function + * returns an array with the first entry as a NULL pointer. + * + * Returns: NULL on failure, otherwise a CURL **array pointer + */ +CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle); + +/* + * 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); + +/* + * Name: curl_multi_waitfds() + * + * Desc: Ask curl for fds for polling. The app can use these to poll on. + * We want curl_multi_perform() called as soon as one of them are + * ready. Passing zero size allows to get just a number of fds. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_waitfds(CURLM *multi, + struct curl_waitfd *ufds, + unsigned int size, + unsigned int *fd_count); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/LFtid1056/cloudfront/code/curl/options.h b/LFtid1056/cloudfront/code/curl/options.h new file mode 100644 index 0000000..1ed76a9 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/options.h @@ -0,0 +1,70 @@ +#ifndef CURLINC_OPTIONS_H +#define CURLINC_OPTIONS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#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 null-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 */ diff --git a/LFtid1056/cloudfront/code/curl/stdcheaders.h b/LFtid1056/cloudfront/code/curl/stdcheaders.h new file mode 100644 index 0000000..7451aa3 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/stdcheaders.h @@ -0,0 +1,35 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include + +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 */ diff --git a/LFtid1056/cloudfront/code/curl/system.h b/LFtid1056/cloudfront/code/curl/system.h new file mode 100644 index 0000000..820fe96 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/system.h @@ -0,0 +1,440 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* + * 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__) +# 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(__BORLANDC__) +# 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(__POCC__) +# if 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(__MCST__) /* MCST eLbrus Compiler Collection */ +# 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(macintosh) +# include +# if TYPE_LONGLONG +# 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 unsigned int + +#elif defined(__TANDEM) +# 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 +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# 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 +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int +# endif + +#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__) +# include +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T PRId64 +# define CURL_FORMAT_CURL_OFF_TU PRIu64 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_PULL_SYS_TYPES_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__) +# 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(__MVS__) +# 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 +# else /* _LP64 and default */ +# 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(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# 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 +# else /* _LP64 and default */ +# 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 + +#elif defined(__hpux) /* HP aCC 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 >= 1800) +# include +# define CURL_FORMAT_CURL_OFF_T PRId64 +# define CURL_FORMAT_CURL_OFF_TU PRIu64 +# else +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# endif +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# 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 */ +#define CURL_PULL_SYS_POLL_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 +#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 +#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 +#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(__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 */ diff --git a/LFtid1056/cloudfront/code/curl/typecheck-gcc.h b/LFtid1056/cloudfront/code/curl/typecheck-gcc.h new file mode 100644 index 0000000..e532e69 --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/typecheck-gcc.h @@ -0,0 +1,718 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* 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 will + * just need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + CURLoption _curl_opt = (option); \ + if(__builtin_constant_p(_curl_opt)) { \ + CURL_IGNORE_DEPRECATION( \ + 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__({ \ + CURLINFO _curl_info = (info); \ + if(__builtin_constant_p(_curl_info)) { \ + CURL_IGNORE_DEPRECATION( \ + 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 do not + * 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_ECH || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_HSTS || \ + (option) == CURLOPT_HAPROXY_CLIENT_IP || \ + (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_PROTOCOLS_STR || \ + (option) == CURLOPT_PROXY || \ + (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_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REDIR_PROTOCOLS_STR || \ + (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 || \ + (option) == CURLOPT_SSH_HOSTKEYDATA || \ + 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 are 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 */ diff --git a/LFtid1056/cloudfront/code/curl/urlapi.h b/LFtid1056/cloudfront/code/curl/urlapi.h new file mode 100644 index 0000000..b4a6e5d --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/urlapi.h @@ -0,0 +1,155 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#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_NO_ZONEID, /* 18 */ + CURLUE_BAD_FILE_URL, /* 19 */ + CURLUE_BAD_FRAGMENT, /* 20 */ + CURLUE_BAD_HOSTNAME, /* 21 */ + CURLUE_BAD_IPV6, /* 22 */ + CURLUE_BAD_LOGIN, /* 23 */ + CURLUE_BAD_PASSWORD, /* 24 */ + CURLUE_BAD_PATH, /* 25 */ + CURLUE_BAD_QUERY, /* 26 */ + CURLUE_BAD_SCHEME, /* 27 */ + CURLUE_BAD_SLASHES, /* 28 */ + CURLUE_BAD_USER, /* 29 */ + CURLUE_LACKS_IDN, /* 30 */ + CURLUE_TOO_LARGE, /* 31 */ + 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 */ +#define CURLU_PUNYCODE (1<<12) /* get the hostname in punycode */ +#define CURLU_PUNY2IDN (1<<13) /* punycode => IDN conversion */ +#define CURLU_GET_EMPTY (1<<14) /* allow empty queries and fragments + when extracting the URL or the + components */ +#define CURLU_NO_GUESS_SCHEME (1<<15) /* for get, do not accept a guess */ + +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(const 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(const 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 */ diff --git a/LFtid1056/cloudfront/code/curl/websockets.h b/LFtid1056/cloudfront/code/curl/websockets.h new file mode 100644 index 0000000..6ef6a2b --- /dev/null +++ b/LFtid1056/cloudfront/code/curl/websockets.h @@ -0,0 +1,84 @@ +#ifndef CURLINC_WEBSOCKETS_H +#define CURLINC_WEBSOCKETS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +struct curl_ws_frame { + int age; /* zero */ + int flags; /* See the CURLWS_* defines */ + curl_off_t offset; /* the offset of this data into the frame */ + curl_off_t bytesleft; /* number of pending bytes left of the payload */ + size_t len; /* size of the current data chunk */ +}; + +/* flag bits */ +#define CURLWS_TEXT (1<<0) +#define CURLWS_BINARY (1<<1) +#define CURLWS_CONT (1<<2) +#define CURLWS_CLOSE (1<<3) +#define CURLWS_PING (1<<4) +#define CURLWS_OFFSET (1<<5) + +/* + * NAME curl_ws_recv() + * + * DESCRIPTION + * + * Receives data from the websocket connection. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen, + size_t *recv, + const struct curl_ws_frame **metap); + +/* flags for curl_ws_send() */ +#define CURLWS_PONG (1<<6) + +/* + * NAME curl_ws_send() + * + * DESCRIPTION + * + * Sends data over the websocket connection. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer, + size_t buflen, size_t *sent, + curl_off_t fragsize, + unsigned int flags); + +/* bits for the CURLOPT_WS_OPTIONS bitmask: */ +#define CURLWS_RAW_MODE (1<<0) + +CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_WEBSOCKETS_H */ diff --git a/LFtid1056/cloudfront/code/front.h b/LFtid1056/cloudfront/code/front.h new file mode 100644 index 0000000..32d9f7a --- /dev/null +++ b/LFtid1056/cloudfront/code/front.h @@ -0,0 +1,122 @@ +#ifndef FRONT_H +#define FRONT_H + +#include +#include +#include +#include +#include //任务队列 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "rocketmq.h" // mq +#include "worker.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////命名空间 + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////线程池类 + +class ThreadPool { +public: + explicit ThreadPool(size_t numThreads) : stop(false) { + for (size_t i = 0; i < numThreads; ++i) { + workers.emplace_back([this]() { + for (;;) { + std::function task; + + { + std::unique_lock lock(queueMutex); + condition.wait(lock, [this]() { return stop || !tasks.empty(); }); + if (stop && tasks.empty()) + return; + task = std::move(tasks.front()); + tasks.pop(); + } + + task(); + } + }); + } + } + + // 添加任务 + template + void enqueue(F&& f) { + { + std::unique_lock lock(queueMutex); + if (stop) + throw std::runtime_error("enqueue on stopped ThreadPool"); + + tasks.emplace(std::function(std::forward(f))); + } + condition.notify_one(); + } + + // 析构:停止所有线程 + ~ThreadPool() { + { + std::unique_lock lock(queueMutex); + stop = true; + } + condition.notify_all(); + for (std::thread &worker : workers) + worker.join(); + } + +private: + std::vector workers; // 工作线程 + std::queue> tasks; // 任务队列 + std::mutex queueMutex; // 队列锁 + std::condition_variable condition; // 条件变量 + bool stop; // 停止标志 +}; + +/////////////////////////////////////////////////////////////////////////////////////////front类 + +class Front { +public: + Worker m_worker; + + std::unique_ptr m_mqConsumer; + std::shared_ptr m_listener; + + rocketmq::RocketMQProducer* m_producer = nullptr; + + std::thread m_FrontThread; + std::thread m_MQConsumerThread; + std::thread m_MQProducerThread; + std::thread m_TimerThread; + + std::atomic m_IsMQProducerCancel{false}; + std::atomic m_IsTimerCancel{false}; + std::atomic m_bIsFrontThreadCancle{false}; + std::atomic m_IsMQConsumerCancel{false}; + + std::mutex m_threadCheckMutex; + std::atomic m_needRestartFrontThread{false}; + std::atomic m_needRestartConsumerThread{false}; + std::atomic m_needRestartProducerThread{false}; + std::atomic m_needRestartTimerThread{false}; + + Front(); + ~Front(); + + void FormClosing(); + + void StartFrontThread(); + void StartMQConsumerThread(); + void StartMQProducerThread(); + void StartTimerThread(); + + void FrontThread(); + void mqconsumerThread(); + void mqproducerThread(); + void OnTimerThread(); + +private: + ThreadPool m_threadPool; +}; + +#endif // FRONT_H \ No newline at end of file diff --git a/LFtid1056/cloudfront/code/interface.cpp b/LFtid1056/cloudfront/code/interface.cpp new file mode 100644 index 0000000..d67b65d --- /dev/null +++ b/LFtid1056/cloudfront/code/interface.cpp @@ -0,0 +1,1291 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include // for std::move +#include // for std::free +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "curl/curl.h" +#include "interface.h" +#include "rocketmq.h" +#include "nlohmann/json.hpp" +#include "log4cplus/log4.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using json = nlohmann::json; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +std::map xmlinfo_list;//保存所有型号对应的icd映射文件解析数据 +XmlConfig xmlcfg;//星形接线xml节点解析的数据-默认映射文件解析数据 +std::list topicList; //队列发送主题链表 + +XmlConfig xmlcfg2;//角型接线xml节点解析的数据-默认映射文件解析数据 +std::list topicList2; //角型接线发送主题链表 +std::map xmlinfo_list2;//保存所有型号角形接线对应的icd映射文件解析数据 + +//台账list +std::vector terminal_devlist; + +//台账锁 +std::mutex ledgermtx; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// +extern int g_front_seg_index; +extern int g_front_seg_num; +extern std::string FRONT_IP; +extern uint32_t g_node_id; + +//筛选的终端状态:数组【0,1】筛选运行和在运 +extern std::string TERMINAL_STATUS; + +//筛选的icd范围:1根据台账获取0获取全部 +extern std::string ICD_FLAG; + +//五个接口 +extern std::string WEB_FILEUPLOAD; +extern std::string WEB_FILEDOWNLOAD; +extern std::string WEB_ICD; +extern std::string WEB_DEVICE; +extern std::string WEB_EVENT; + +//角型接线标志 +extern int isdelta_flag; + +//单个进程的台账数量 +extern int IED_COUNT; + +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +void handleCommentResponse(const std::string& response); + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +extern void execute_bash(std::string fun,int process_num,std::string type); + +////////////////////////////////////////////////////////////////////////////////////////////////////////通用curl请求接口 + +size_t req_reply_web(void* ptr, size_t size, size_t nmemb, void* stream) +{ + std::string* str = (std::string*)stream; + (*str).append((char*)ptr, size * nmemb); + return size * nmemb; +} + +void SendJsonAPI_web(const std::string& strUrl, //接口路径 + const std::string& code, //上传文件用 + const std::string& json, //请求json + std::string& responseStr) //响应 +{ + CURL* curl = curl_easy_init(); + CURLcode res; + + responseStr.clear(); + + if (curl) { + // 使用 std::string 拼接完整 URL + std::string fullUrl = strUrl + "?" + code; + std::cout << ">>>json " << fullUrl << std::endl; + + curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply_web); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseStr); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); + + if (!json.empty()) { + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); + } + + struct curl_slist* headers = nullptr; + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + std::cerr << "web failed, res code: " << curl_easy_strerror(res) << std::endl; + } else { + std::cout << ">>> web return str: " << responseStr << std::endl; + } + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + } else { + std::cerr << ">>> web curl init failed" << std::endl; + } +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////上传文件接口 + +//处理文件上传响应 +void handleUploadResponse(const std::string& response, std::string& wavepath) { + + using nlohmann::json; //把 nlohmann::json 这个名字带到当前作用域 + + // 解析 JSON 响应 + json json_data; + try { + json_data = json::parse(response); + } + catch (const json::parse_error& e) { + std::cerr << "Error parsing response: " << e.what() << std::endl; + DIY_ERRORLOG("process", "【ERROR】前置上传暂态录波文件失败,web返回的消息不是json格式"); + return; + } + + // 提取字段 + if (!json_data.contains("code") || !json_data.contains("data")) { + std::cerr << "Error: Missing expected fields in JSON response." << std::endl; + DIY_ERRORLOG("process", "【ERROR】前置上传暂态录波文件失败,web返回的消息没有远端文件名"); + return; + } + + std::string code = json_data["code"].get(); + std::cout << "Response Code: " << code << std::endl; + + std::string msg = json_data.value("msg", std::string{"not found"}); + std::cout << "Message: " << msg << std::endl; + + auto& data = json_data["data"]; + if (!data.contains("name") || !data.contains("fileName") || !data.contains("url")) { + std::cerr << "Error: Missing expected fields in JSON data object." << std::endl; + DIY_ERRORLOG("process", "【ERROR】前置上传暂态录波文件失败,web返回的消息没有远端文件名"); + return; + } + + std::string name = data["name"].get(); + std::string fileName = data["fileName"].get(); + std::string url = data["url"].get(); + + // 输出信息 + std::cout << "File Path: " << name << std::endl; + std::cout << "Uploaded File Name: " << fileName << std::endl; + std::cout << "File URL: " << url << std::endl; + + // 找到最后一个 '.' + size_t pos = fileName.find_last_of('.'); + std::string nameWithoutExt; + if (pos != std::string::npos) { + // 截取去掉后缀的部分 + nameWithoutExt = fileName.substr(0, pos); + } else { + // 如果没有后缀,直接使用原文件名 + nameWithoutExt = fileName; + } + + // 拷贝到 wavepath + wavepath = nameWithoutExt; + + std::cout << "wavepath: " << wavepath << std::endl; + DIY_INFOLOG("process", "【NORMAL】前置上传暂态录波文件成功,远端文件名:%s", wavepath.c_str()); +} + +//上传文件 +void SendFileWeb(const std::string& strUrl, const std::string& localpath, const std::string& cloudpath, std::string& wavepath) { + // 初始化 curl + CURL* curl = curl_easy_init(); + if (curl) { + // 设置请求 URL 和 POST 请求 + curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str()); + curl_easy_setopt(curl, CURLOPT_POST, 1); + + // 创建表单数据 + curl_httppost* formpost = nullptr; + curl_httppost* lastptr = nullptr; + + if (access(localpath.c_str(), F_OK) != 0) { + std::cerr << "Local file does not exist: " << localpath << std::endl; + return; + } + + // 添加文件字段,直接从本地路径读取文件内容 + curl_formadd(&formpost, &lastptr, + CURLFORM_COPYNAME, "file", + CURLFORM_FILE, localpath, + CURLFORM_END); + + // 添加 `path` 字段 + curl_formadd(&formpost, &lastptr, + CURLFORM_COPYNAME, "path", + CURLFORM_COPYCONTENTS, cloudpath, + CURLFORM_END); + + // 添加 `isReserveName` 字段 + curl_formadd(&formpost, &lastptr, + CURLFORM_COPYNAME, "isReserveName", + CURLFORM_COPYCONTENTS, "true", + CURLFORM_END); + + // 设置表单数据到请求 + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + + // 设置头信息 + struct curl_slist* header_list = nullptr; + header_list = curl_slist_append(header_list, "Content-Type: multipart/form-data"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + + // 设置超时时间 + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); + + // 设置写入响应数据的函数 + std::string resPost0; + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&resPost0); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply_web); + + // 执行请求 + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + std::cerr << "http web failed: " << curl_easy_strerror(res) << std::endl; + DIY_ERRORLOG("process","【ERROR】前置上传暂态录波文件 %s 失败,请检查文件上传接口配置",localpath); + } else { + std::cout << "http web success, response: " << resPost0 << std::endl; + handleUploadResponse(resPost0, wavepath); // 处理响应 + } + + // 清理 + curl_formfree(formpost); // 释放表单数据 + curl_slist_free_all(header_list); // 释放头部列表 + curl_easy_cleanup(curl); + } else { + std::cerr << ">>> curl init failed" << std::endl; + } +} + +//上传暂态文件 +void SOEFileWeb(std::string& localpath,std::string& cloudpath, std::string& wavepath) +{ + SendFileWeb(WEB_FILEUPLOAD,localpath,cloudpath,wavepath); +} + +//上传文件测试函数 +void Fileupload_test() +{ + std::string localpath = FRONT_PATH + "/bin/file_test.txt"; + std::string cloudpath = "/fileuploadtest/"; + std::string wavepath; + SOEFileWeb(localpath,cloudpath,wavepath); + std::cout << "wavepath:" << wavepath << std::endl; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////映射文件下载接口 +void download_xml_for_icd(const std::string& MODEL_ID, + const std::string& TMNL_TYPE, + const std::string& FILE_PATH, + const std::string& FILE_NAME, + const std::string& time) +{ + if (MODEL_ID.empty() || TMNL_TYPE.empty() || FILE_PATH.empty() || FILE_NAME.empty()) + { + std::cerr << "Function download_xml_for_icd Error, param empty!" << std::endl; + return; + } + std::cout << "Function download_xml_for_icd Start!" << std::endl; + + std::string id(MODEL_ID); + std::string type(TMNL_TYPE); + std::string filepath(FILE_PATH); + std::string name(FILE_NAME); + std::string currentTime(time); + + // 调试用 + std::cout << "terminal type:" << TMNL_TYPE << std::endl; + + auto it = xmlinfo_list.find(type); + if (it == xmlinfo_list.end()) // 在终端类型列表中没查到 + { + Xmldata* config = new Xmldata(); // 没找到就插个新的终端类型到列表中 + xmlinfo_list[type] = config; //在这里将 config 转成一个Xmldata 的右值引用,触发 unique_ptr 的移动赋值 + + // 调试 + std::cout << "xmlinfo_list insert type:" << type << std::endl; + } + else // 查到就更新覆盖 + { + // 调试 + std::cout << "xmlinfo_list type contain:" << type << std::endl; + + if (xmlinfo_list[type]->xmlbase.updatetime == currentTime) { // 终端型号更新标志,如果新增的型号错误,导致实际用的映射文件不一样,或者覆盖了原来的映射文件这里可能出问题。数据库在录入型号和映射文件时要注意 + xmlinfo_list[type]->updataflag = false; // 时间值一样说明是没有更新,当前业务中不包含时间值,所以每次都会更新 + } + else { + xmlinfo_list[type]->updataflag = true; + } + } + + xmlinfo_list[type]->xmlbase.MODEL_ID = id; + xmlinfo_list[type]->xmlbase.TMNL_TYPE = type; + xmlinfo_list[type]->xmlbase.FILE_PATH = filepath; + xmlinfo_list[type]->xmlbase.FILE_NAME = name; + + xmlinfo_list[type]->xmlbase.updatetime = currentTime; + + //调试 + std::cout << "##################################isdelta_flag is " << isdelta_flag << std::endl; + + if (isdelta_flag) { + std::cout << "xmllist2 create" << std::endl; + + auto it2 = xmlinfo_list2.find(type); + if (it2 == xmlinfo_list2.end()) + { + Xmldata* config = new Xmldata(); + xmlinfo_list2[type] = config; + } + else + { + if (xmlinfo_list2[type]->xmlbase.updatetime == currentTime) { + xmlinfo_list2[type]->updataflag = false; + } + else { + xmlinfo_list2[type]->updataflag = true; + } + } + xmlinfo_list2[type]->xmlbase.MODEL_ID = id; + xmlinfo_list2[type]->xmlbase.TMNL_TYPE = type; + xmlinfo_list2[type]->xmlbase.FILE_PATH = filepath; + xmlinfo_list2[type]->xmlbase.FILE_NAME = name; + xmlinfo_list2[type]->xmlbase.updatetime = currentTime; + } + + //下载文件 + std::string remote_file_name = name; + std::string save_name = FRONT_PATH + "/dat/" + id + ".xml"; // 本地保存路径 + + std::cout << "remote file name:" << remote_file_name << "local save name:" << save_name << std::endl; + + // mq日志 + DIY_WARNLOG("process","【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name); + + std::string fileContent; + std::string fullPath = std::string("filePath=") + filepath; //填写远端路径作为入参 + + // 调试 + std::cout << "input fullpath" << fullPath << std::endl; + + SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", fileContent); + + if (!fileContent.empty()) { + // 创建并打开文件 + std::ofstream outFile(save_name, std::ios::out); // 文本模式打开 + if (outFile.is_open()) { + + // 将文件流写入文件 + outFile.write(fileContent.c_str(), fileContent.size()); + outFile.close(); + + std::cout << "File saved successfully!" << std::endl; + DIY_WARNLOG("process","【WARN】前置下载映射文件%s成功",save_name); + } else { + std::cerr << "Error: Unable to open file for writing." << std::endl; + DIY_ERRORLOG("process","【ERROR】前置写入本地映射文件%s失败",save_name); + } + } else { + std::cerr << "Error: Unable to download file." << std::endl; + DIY_ERRORLOG("process","【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////台账接口 + +//读最新本地台账 +std::string read_latest_ledger_file() { + const char* dir = std::string(FRONT_PATH + "/dat/ledger").c_str(); + DIR* dp = opendir(dir); + if (!dp) return ""; + + struct dirent* entry; + std::string latest_file; + time_t latest_time = 0; + + while ((entry = readdir(dp)) != nullptr) { + if (strstr(entry->d_name, "_ledger.txt")) { + std::string filepath = std::string(dir) + "/" + entry->d_name; + std::cout << "localledger filepath" << filepath << std::endl; + struct stat st; + if (stat(filepath.c_str(), &st) == 0 && st.st_mtime > latest_time) { + latest_time = st.st_mtime; + latest_file = filepath; + } + } + } + closedir(dp); + + if (!latest_file.empty()) { + std::ifstream inFile(latest_file); + if (inFile) { + std::string content((std::istreambuf_iterator(inFile)), + std::istreambuf_iterator()); + return content; + } + } + + return ""; +} + +//保存台账到本地 +void save_ledger_json(const std::string& content) { + if (content.empty()) return; + + const std::string dir = FRONT_PATH + "/dat/ledger"; + + // 确保目录存在 + struct stat st; + if (stat(dir.c_str(), &st) != 0) { + mkdir(FRONT_PATH.c_str(), 0755); // 确保上级目录存在(可选) + mkdir(std::string(FRONT_PATH + "/dat").c_str(), 0755); + mkdir(dir.c_str(), 0755); + } + + // 删除已有 *_ledger.txt 文件 + DIR* dp = opendir(dir.c_str()); + if (dp) { + struct dirent* entry; + while ((entry = readdir(dp)) != nullptr) { + if (strstr(entry->d_name, "_ledger.txt")) { + std::string old_file_path = dir + "/" + entry->d_name; + std::remove(old_file_path.c_str()); + } + } + closedir(dp); + } + + // 当前时间格式化为 yyyyMMddHHmmss + char time_buf[32]; + time_t now = time(nullptr); + struct tm* tm_info = localtime(&now); + strftime(time_buf, sizeof(time_buf), "%Y%m%d%H%M%S", tm_info); + + // 构造文件路径 + std::string filepath = dir + "/" + time_buf + "_ledger.txt"; + + // 写入文件 + std::ofstream outFile(filepath); + if (outFile) { + outFile << content; + outFile.close(); + } else { + std::cerr << "Error: Unable to open ledger file for writing: " << filepath << std::endl; + } +} + +//找看门狗中最大的进程号 +int get_max_stat_data_index(const std::string& filepath) { + std::ifstream file(filepath.c_str()); + if (!file.is_open()) { + std::cerr << "Failed to open file: " << filepath << std::endl; + return -1; + } + + std::string line; + int max_value = -1; + + while (std::getline(file, line)) { + // 查找符合要求的行 + if (line.find("pt61850netd_pqfe -d cfg_stat_data -s") != std::string::npos) { + // 找到 -s 参数位置 + std::size_t pos = line.find("-s"); + if (pos != std::string::npos) { + std::istringstream iss(line.substr(pos + 2)); + std::string token; + iss >> token; + + // 格式应该是 1_2 或类似格式 + std::size_t under_pos = token.find('_'); + if (under_pos != std::string::npos) { + std::string first = token.substr(0, under_pos); + std::string second = token.substr(under_pos + 1); + + int val1 = std::atoi(first.c_str()); + int val2 = std::atoi(second.c_str()); + + if (val1 > max_value) max_value = val1; + if (val2 > max_value) max_value = val2; + } + } + } + } + + file.close(); + return max_value; +} + +//台账信息获取 +int terminal_ledger_web(std::map& terminal_dev_map, + const std::string& inputstring) +{ + if (inputstring.empty()) { + std::cerr << "Error: inputstring is empty\n"; + DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程调用web台账接口的入参为空", get_front_msg_from_subdir(), g_front_seg_index); + return 1; + } + + std::string inputparm = inputstring; + std::string responseStr; + int retry = 0; + nlohmann::json json_data; + + // 1. 拉取并解析 JSON,最多 3 次 + while (true) { + SendJsonAPI_web(WEB_DEVICE, "", inputparm, responseStr); + if (!responseStr.empty()) { + try { + json_data = nlohmann::json::parse(responseStr); + if (json_data.contains("data") && json_data["data"].is_array() && !json_data["data"].empty()) { + break; + } + std::cerr << "data 无效或为空数组,重试\n"; + DIY_ERRORLOG("process","【ERROR】前置从web接口中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",inputparm.c_str()); + } catch (const nlohmann::json::parse_error& e) { + std::cerr << "parse error: " << e.what() << ", retrying...\n"; + } + } else { + std::cerr << "HTTP response NULL, retrying...\n"; + } + + if (++retry > 3) { + std::cerr << "web error after 3 retry, fallback to local file\n"; + std::string ledger = read_latest_ledger_file(); + if (!ledger.empty()) { + try { + json_data = nlohmann::json::parse(ledger); + if (json_data.contains("data") && json_data["data"].is_array() && !json_data["data"].empty()) { + break; + } + DIY_ERRORLOG("process", "【ERROR】前置从本地台账中获取的台账信息为空或者无效信息无法解析,请核对前置使用的入参信息:%s",inputparm.c_str()); + } catch (const nlohmann::json::parse_error& e) { + std::cerr << "local parse error: " << e.what() << "\n"; + } + } + std::cerr << "still failed, sleep 5 min then retry...\n"; + std::this_thread::sleep_for(std::chrono::minutes(5)); + retry = 0; + continue; + } + } + + // 2. 安全读取 code/msg + std::string code = json_data.value("code", "not found"); + std::string msg = json_data.value("msg", "not found"); + std::cout << "code: " << code << "\n"; + std::cout << "msg : " << msg << "\n"; + + // 3. 逐条解析 data + const auto& data = json_data["data"]; + for (size_t i = 0; i < data.size(); ++i) { + const auto& item = data[i]; + if (!item.is_object()) { + std::cerr << "Warning: Invalid item at index " << i << "\n"; + continue; + } + terminal_dev dev; // 不用 new + + auto safe_str = [](const nlohmann::json& j, const char* key) -> std::string { + if (!j.contains(key) || j[key].is_null()) return "N/A"; + if (j[key].is_string()) return j[key].get(); + if (j[key].is_number_integer()) return std::to_string(j[key].get()); + if (j[key].is_number_unsigned()) return std::to_string(j[key].get()); + if (j[key].is_number_float()) return std::to_string(j[key].get()); + return "N/A"; + }; + dev.terminal_id = safe_str(item, "id"); + dev.addr_str = safe_str(item, "ip"); + dev.terminal_code = safe_str(item, "name"); + dev.org_name = safe_str(item, "org_name"); + dev.maint_name = safe_str(item, "maint_name"); + dev.station_name = safe_str(item, "stationName"); + dev.tmnl_factory = safe_str(item, "manufacturer"); + dev.tmnl_status = safe_str(item, "status"); + dev.dev_type = safe_str(item, "devType"); + dev.dev_key = safe_str(item, "devKey"); + dev.dev_series = safe_str(item, "series"); + dev.port = safe_str(item, "port"); + dev.timestamp = safe_str(item, "updateTime"); + dev.processNo = safe_str(item, "processNo"); + dev.maxProcessNum = safe_str(item, "maxProcessNum"); + + if (item.contains("monitorData") && item["monitorData"].is_array()) { + for (auto& mon : item["monitorData"]) { + if (dev.line.size() >= 10) break; + ledger_monitor m; + m.monitor_id = safe_str(mon, "id"); + m.terminal_code = safe_str(mon, "terminal_code"); + m.monitor_name = safe_str(mon, "name"); + m.logical_device_seq = safe_str(mon, "lineNo"); + m.voltage_level = safe_str(mon, "voltageLevel"); + m.terminal_connect = safe_str(mon, "ptType"); + m.timestamp = safe_str(mon, "updateTime"); + m.status = safe_str(mon, "status"); + dev.line.push_back(m); + } + } + + // 插入 map(去重 + 仅本进程号匹配时插入) + // dev 已经是对象类型 + std::string key = dev.terminal_id; + auto it = terminal_dev_map.find(key); + bool match = false; + try { + match = (std::stoi(dev.processNo) == g_front_seg_index || g_front_seg_index == 0); + } catch (...) { + std::cerr << "processNo parse error for terminal: " << dev.terminal_id << "\n"; + } + if (it != terminal_dev_map.end()) { + std::cerr << "Duplicate terminal_id: " << key << std::endl; + terminal_dev_map.erase(it); // 覆盖前先提示并擦除 + if (match) { + std::cout << "remove duplicate terminal ledger and insert lastest terminal ledger id:" << key << std::endl; + terminal_dev_map[key] = dev; + } + } else { + if (match) { + std::cout << "process num match, terminal ledger insert id:" << key << std::endl; + terminal_dev_map[key] = dev; + } + } + } + + // 5. 主进程保存台账 + if (g_node_id == STAT_DATA_BASE_NODE_ID && g_front_seg_index == 1) { + save_ledger_json(responseStr); + } + + return 0; +} + +//台账信息写入全局 +int parse_device_cfg_web() +{ + std::cout << "parse_device_cfg_web" << std::endl; + + // 1. 构造入参 JSON + std::string input_jstr = "{"; + input_jstr += "\"ip\":\"" + FRONT_IP + "\","; + input_jstr += "\"runFlag\":" + TERMINAL_STATUS; + input_jstr += "}"; + + std::cout << "input_jstr: " << input_jstr << std::endl; + DIY_DEBUGLOG("process","【DEBUG】前置的%s%d号进程调用web接口获取台账使用的请求输入为:%s",get_front_msg_from_subdir(), g_front_seg_index, input_jstr.c_str()); + + // 2. 调用接口 + std::map terminal_dev_map; + if (terminal_ledger_web(terminal_dev_map, input_jstr)) { + return 1; // 入参为空或接口失败 + } + + // 3. 调试打印 + printTerminalDevMap(terminal_dev_map); + + // 4. 看门狗配置校验(仅主进程稳态) + if (g_node_id == STAT_DATA_BASE_NODE_ID && g_front_seg_index == 1) { + int max_index = get_max_stat_data_index(FRONT_PATH + "/etc/runtime.cf"); + std::cout << "max_index = " << max_index << std::endl; + + int max_process_num = 0; + auto it = terminal_dev_map.begin(); + if (it != terminal_dev_map.end()) { + const terminal_dev& dev = it->second; + max_process_num = std::atoi(dev.maxProcessNum.c_str()); + std::cout << "maxProcessNum = " << max_process_num << std::endl; + } else { + std::cout << "terminal_dev_map is empty." << std::endl; + } + + if (max_process_num != max_index) { + if (max_process_num >= 1 && max_process_num <= 9) { + DIY_WARNLOG("process", "【WARN】前置比对台账获取的进程数:%d和本地配置的进程数:%d,不匹配,按照台账进程数重置前置的进程数量",max_process_num, max_index); + execute_bash("reset", max_process_num, "all"); + } else { + DIY_ERRORLOG("process","【ERROR】前置从台账获取的进程数:%d不符合范围1~9,按照本地配置进程数启动进程",max_process_num); + } + } + } + + // 5. 台账数量与配置比对 + int count_cfg = static_cast(terminal_dev_map.size()); + std::cout << "terminal_ledger_num: " << count_cfg << std::endl; + DIY_DEBUGLOG("process", "【DEBUG】前置的%s%d号进程调用获取到的台账的数量为:%d",get_front_msg_from_subdir(), g_front_seg_index, count_cfg); + + if (IED_COUNT < count_cfg) { + std::cout << "!!!!!!!!!!single process can not add any ledger unless reboot!!!!!!!" << std::endl; + DIY_WARNLOG("process","【WARN】前置的%s%d号进程获取到的台账的数量大于配置文件中给单个进程配置的台账数量:%d,这个进程将按照获取到的台账的数量来创建台账空间,这个进程不能直接通过台账添加来新增台账,只能通过重启进程或者先删除已有台账再添加台账的方式来添加新台账",get_front_msg_from_subdir(), g_front_seg_index, IED_COUNT); + } else { + DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程根据配置文件中给单个进程配置的台账数量:%d来创建台账空间",get_front_msg_from_subdir(), g_front_seg_index, IED_COUNT); + } + + ///////////////////////////////////////////////////////////////////////////////用例这里将局部的map拷贝到全局map,后续根据协议台账修改 + // 先清空全局 container,再逐个拷贝 map 中的 terminal_dev + terminal_devlist.clear(); + for (const auto& kv : terminal_dev_map) { + terminal_devlist.push_back(kv.second); // kv.second 是对象,不用判断指针 + } + + // 判断监测点接线类型 + for (auto& dev : terminal_devlist) { + for (auto& mon : dev.line) { + if (!mon.terminal_connect.empty() && mon.terminal_connect != "0") { + isdelta_flag = 1; + std::cout << "monitor_id " << mon.monitor_id<< " v_wiring_type: " << mon.terminal_connect << " is delta wiring: " << isdelta_flag << std::endl; + DIY_WARNLOG("process","【WARN】前置连接的监测点%s是角形接线,对应终端为%s 终端类型是%s",mon.monitor_id.c_str(),dev.terminal_id.c_str(),dev.dev_type.c_str()); + } + } + } + + terminal_dev_map.clear(); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////icd接口 + +int parse_model_web(std::map* icd_model_map, + const std::string& inputstr) +{ + // 1. 清理调用方 map 中的旧数据 + for (auto& kv : *icd_model_map) { + delete kv.second; + } + icd_model_map->clear(); + + // 2. 准备请求参数 + std::string inputparm = inputstr; // 装置型号列表,格式 ["型号1","型号2",...] 或 [] + + // 3. 调用接口并重试解析 JSON(最多 3 次) + std::string responseStr; + nlohmann::json root; + bool parsed = false; + const int maxRetry = 3; + for (int attempt = 1; attempt <= maxRetry; ++attempt) { + + // 发起 HTTP 请求 + SendJsonAPI_web(WEB_ICD, "", inputparm, responseStr); + + if (responseStr.empty()) { + std::cerr << "Attempt " << attempt << ": received NULL response, retrying...\n"; + continue; + } + + std::cout << "Attempt " << attempt << " icd responseStr: " << responseStr << "\n"; + + // 尝试解析 + try { + root = nlohmann::json::parse(responseStr); + parsed = true; + break; + } + catch (const nlohmann::json::parse_error& e) { + std::cerr << "Attempt " << attempt << " parse error: " << e.what() << ", retrying...\n"; + } + } + + // 4. 如果解析仍失败,返回错误 + if (!parsed) { + std::cerr << "Error: failed to retrieve or parse JSON after " << maxRetry << " attempts\n"; + return 1; + } + + // 5. 打印 code / msg + std::string code = root.value("code", "not found"); + std::string msg = root.value("msg", "not found"); + std::cout << "code: " << code << "\n"; + std::cout << "msg : " << msg << "\n"; + + // 6. 处理 data 数组,将每个条目填充到调用方的 map + if (root.contains("data") && root["data"].is_array()) { + for (auto& item : root["data"]) { + auto model = new icd_model(); + + if (item.contains("id") && item["id"].is_string()) + model->model_id = item["id"].get(); + if (item.contains("devType") && item["devType"].is_string()) + model->tmnl_type = item["devType"].get(); + if (item.contains("devTypeId") && item["devTypeId"].is_string()) + model->tmnl_type_id = item["devTypeId"].get(); + if (item.contains("devFactory") && item["devFactory"].is_string()) + model->tmnl_factory = item["devFactory"].get(); + if (item.contains("fileName") && item["fileName"].is_string()) + model->file_name = item["fileName"].get(); + if (item.contains("filePath") && item["filePath"].is_string()) + model->file_path = item["filePath"].get(); + if (item.contains("updateTime") && item["updateTime"].is_string()) + model->updatetime = item["updateTime"].get(); + + // 只有当 model_id 不为空时才插入 + if (!model->model_id.empty()) { + (*icd_model_map)[model->model_id] = model; + } else { + delete model; + } + } + } + + return 0; +} + +int parse_model_cfg_web() +{ + // 1. 根据全局终端列表去重 + std::set devTypes; + for (auto& dev : terminal_devlist) { + if (!dev.dev_type.empty()) { + devTypes.insert(dev.dev_type); + } + } + + std::cout << "终端总数: " << terminal_devlist.size() << "\n"; + std::cout << "不同的 dev_type 个数: " << devTypes.size() << "\n"; + for (auto& t : devTypes) { + std::cout << " - " << t << "\n"; + } + + // 2. 构造 JSON 参数 + std::string input_jstr; + if (ICD_FLAG == "1") { + input_jstr = "["; + bool first = true; + for (auto& t : devTypes) { + if (!first) input_jstr += ","; + first = false; + input_jstr += "\"" + t + "\""; + } + input_jstr += "]"; + } else { + input_jstr = "[]"; + } + std::cout << "input_jstr: " << input_jstr << "\n"; + + // 3. 调用接口 + std::map icd_model_map; + if (parse_model_web(&icd_model_map, input_jstr)) { + DIY_ERRORLOG("process", "【ERROR】前置的%s%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置",get_front_msg_from_subdir(), g_front_seg_index); + // 确保释放 map + for (auto& kv : icd_model_map) delete kv.second; + return 0; + } + + // 4. 遍历并下载 + try { + for (auto& kv : icd_model_map) { + icd_model* mdl = kv.second; + if (!mdl) continue; + + std::cout << "model_id : " << mdl->model_id << "\n"; + std::cout << "tmnl_type : " << mdl->tmnl_type << "\n"; + std::cout << "file_path : " << mdl->file_path << "\n"; + std::cout << "file_name : " << mdl->file_name << "\n"; + std::cout << "timestamp : " << mdl->updatetime << "\n"; + + download_xml_for_icd( + mdl->model_id, + mdl->tmnl_type, + mdl->file_path, + mdl->file_name, + mdl->updatetime + ); + } + } + catch (const std::exception& e) { + std::cout << "icd model error, ERROR code=" << e.what() << std::endl; + // 释放 map + for (auto& kv : icd_model_map) delete kv.second; + return 1; + } + + // 5. 释放所有 icd_model 对象 + for (auto& kv : icd_model_map) { + delete kv.second; + } + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////icd接口台账更新 +std::string parse_model_cfg_web_one(const std::string& terminal_type) +{ + // 本地 map,用完后我们会把里面的指针 delete + std::map icd_model_map; + + // 1. 构造 JSON 数组:["terminal_type"] + std::string input_jstr = "[\"" + terminal_type + "\"]"; + std::cout << "input_jstr: " << input_jstr << std::endl; + + // 2. 拉取并解析 + if (parse_model_web(&icd_model_map, input_jstr) != 0) { + std::cerr << "parse_model_web failed for type: " << terminal_type << std::endl; + DIY_ERRORLOG("process","【ERROR】前置的%s%d号进程 icd模型接口异常,将使用默认的icd模型,请检查接口配置",get_front_msg_from_subdir(), g_front_seg_index); + // 清理(即使 map 为空,也安全) + for (auto& kv : icd_model_map) delete kv.second; + return ""; + } + + std::string ret_model_id; + + // 3. 找到第一个模型,打印并下载 + if (icd_model_map.empty()) { + std::cerr << "Warning: no ICD model returned for type: " << terminal_type << std::endl; + } + else { + auto& kv = *icd_model_map.begin(); + icd_model* mdl = kv.second; + if (mdl) { + ret_model_id = mdl->model_id; + std::cout << "model_id : " << mdl->model_id << std::endl; + std::cout << "tmnl_type : " << mdl->tmnl_type << std::endl; + std::cout << "file_path : " << mdl->file_path << std::endl; + std::cout << "file_name : " << mdl->file_name << std::endl; + std::cout << "updatetime : " << mdl->updatetime << std::endl; + + try { + download_xml_for_icd( + mdl->model_id, + mdl->tmnl_type, + mdl->file_path, + mdl->file_name, + mdl->updatetime + ); + } catch (const std::exception& e) { + std::cerr << "download_xml_for_icd exception: " << e.what() << std::endl; + } + } + } + + // 4. 释放所有 new 出来的 icd_model + for (auto& kv : icd_model_map) { + delete kv.second; + } + icd_model_map.clear(); + + return ret_model_id; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////暂态接口 +std::string FormatTimeForFilename(const std::string& timeStr) { + std::string result; + for (char c : timeStr) { + if (isdigit(c)) { + result += c; + } + } + return result; +} + +// 将 JSON 字符串写入指定文件(C++11 版本,使用 std::string) +static void writeJsonToFile(const std::string& filePath, const std::string& jsonString) +{ + FILE* fp = fopen(filePath.c_str(), "w"); + if (!fp) { + DIY_ERRORLOG("process", "【ERROR】无法将暂态事件写入本地缓存"); + std::cerr << "Failed to write in file : " << filePath << std::endl; + return; + } + fprintf(fp, "%s", jsonString.c_str()); + fclose(fp); +} + +// 获取指定目录下所有文件的信息(文件名、修改时间、大小),以便后续做删除或判断文件总大小 +struct FileInfo { + std::string fileName; + time_t modTime; // 上次修改时间 + long long fileSize; // 文件大小 +}; + +// 扫描目录,获取该目录下所有普通文件的信息 +static void getDirectoryFilesInfo(const std::string& dirPath, std::vector& fileList) +{ + DIR* dp = opendir(dirPath.c_str()); + if (!dp) { + std::cerr << "Failed to open directory: " << dirPath << " - " << strerror(errno) << std::endl; + return; + } + + struct dirent* entry = nullptr; + while ((entry = readdir(dp)) != nullptr) { + // 跳过 . 和 .. + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + // 拼接完整路径 + std::string fullPath = dirPath; + if (fullPath.back() != '/' && fullPath.back() != '\\') { + fullPath += '/'; + } + fullPath += entry->d_name; + + // 获取文件信息 + struct stat st; + if (stat(fullPath.c_str(), &st) == 0) { + if (S_ISREG(st.st_mode)) { + FileInfo fi; + fi.fileName = fullPath; + fi.modTime = st.st_mtime; + fi.fileSize = static_cast(st.st_size); + fileList.push_back(fi); + } + } else { + std::cerr << "Failed to stat file: " << fullPath << " - " << strerror(errno) << std::endl; + } + } + + closedir(dp); +} + +// 检查 qvvr 目录下文件总大小,若超过 10M 则删除最老的一个文件 +// 注意:该逻辑严格按照你需求“只删一个最老的文件”来实现,而不是循环删到小于10M +static void checkAndRemoveOldestIfNeeded(const std::string& dirPath, long long maxBytes) +{ + // 1) 判断目录是否存在,不存在则尝试创建 + struct stat st; + if (stat(dirPath.c_str(), &st) == -1) { + if (errno == ENOENT) { + // 目录不存在,尝试创建(只创建最后一级,不递归) + if (mkdir(dirPath.c_str(), 0777) != 0) { + std::cerr << "Failed to create directory: " << dirPath << std::endl; + return; + } + } else { + std::cerr << "stat error: " << strerror(errno) << std::endl; + return; + } + } else if (!S_ISDIR(st.st_mode)) { + std::cerr << dirPath << " exists but is not a directory." << std::endl; + return; + } + + // 2) 获取目录下所有文件信息 + std::vector fileList; + getDirectoryFilesInfo(dirPath, fileList); + + // 3) 计算总大小 + long long totalSize = 0; + for (const auto& file : fileList) { + totalSize += file.fileSize; + } + + // 4) 如果超过阈值,则删除最老的文件 + if (totalSize > maxBytes && !fileList.empty()) { + std::sort(fileList.begin(), fileList.end(), [](const FileInfo& a, const FileInfo& b) { + return a.modTime < b.modTime; + }); + + std::remove(fileList[0].fileName.c_str()); + } +} + +// 扫描目录下的离线文件,依次读取并发送;若发送成功则删除该文件,发送不成功则保留 +static void scanAndResendOfflineFiles(const std::string& dirPath) +{ + // 获取目录下所有文件信息 + std::vector fileList; + std::cout << "getDirectoryFilesInfo" << std::endl; + getDirectoryFilesInfo(dirPath, fileList); + + std::cout << "send every file" << std::endl; + + for (const auto& file : fileList) { + // 读取 JSON 文件内容 + std::ifstream inFile(file.fileName.c_str()); + if (!inFile) { + DIY_ERRORLOG("process", "【ERROR】无法打开本地缓存的暂态事件"); + std::cerr << "fail to open existing file: " << file.fileName << std::endl; + continue; + } + + std::string jsonContent((std::istreambuf_iterator(inFile)), + std::istreambuf_iterator()); + inFile.close(); + + std::cout << "send jsonContent: " << jsonContent << std::endl; + + // 尝试发送 + std::string response; + SendJsonAPI_web(WEB_EVENT, "", jsonContent, response); + + if (!response.empty()) { + try { + json j_r = json::parse(response); + + DIY_WARNLOG("process", "【WARN】前置重发暂态事件成功"); + std::cout << "old file send success, remove it" << std::endl; + + std::remove(file.fileName.c_str()); + } catch (...) { + std::cout << "old file send fail (response parse failed)" << std::endl; + + DIY_WARNLOG("process", "【WARN】前置重发暂态事件失败"); + handleCommentResponse(response); // 仍然处理文本响应 + } + } else { + std::cout << "old file send fail (no response)" << std::endl; + // 不删除文件,等待下次重发 + } + } +} + +int transfer_json_qvvr_data(unsigned int func_type, int monitor_id, + double mag, double dur, long long start_tm, long long end_tm, int dis_kind, + const std::string& uuid_cfg, const std::string& uuid_dat, + const std::string& mp_id, const std::string& Qvvr_rptname, const std::string& devtype) { + + // 监测点日志的 key, lnk20250526 + std::string full_key_m_c = "monitor." + mp_id + ".COM"; + std::string full_key_m_d = "monitor." + mp_id + ".DATA"; + // 监测点日志的 key, lnk20250526 + + // 获取装置类型的映射配置 + XmlConfig c_xmlcfg; + if (xmlinfo_list.count(devtype)) { + c_xmlcfg = xmlinfo_list[devtype]->xmlcfg; + } else { + c_xmlcfg = xmlcfg; + } + + if (mp_id.empty()) { + std::cout << "mp_id is null" << std::endl; + return 0; + } + + // 构造 JSON 对象 + json root; + root["monitorId"] = mp_id; + root["amplitude"] = mag; + root["duration"] = dur; + root["eventType"] = dis_kind; + + // 时间处理 + time_t start_sec = start_tm / 1000; //毫秒级取秒 + struct tm* time_info = localtime(&start_sec); + char time_buf[32]; + strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", time_info); + std::ostringstream start_time_stream; + start_time_stream << time_buf << "." << std::setfill('0') << std::setw(3) << (start_tm % 1000);//构造成年月日时分秒.毫秒 + std::string start_time_str = start_time_stream.str(); + + root["startTime"] = start_time_str; + root["wavePath"] = uuid_dat; //接口提供了两个文件名入参,实际上名字一样只用一个,可优化 + + if (c_xmlcfg.WavePhasicFlag == "1") { //映射配置分相 + if (Qvvr_rptname.find(c_xmlcfg.WavePhasicA) != std::string::npos) { + root["phase"] = "A"; + } else if (Qvvr_rptname.find(c_xmlcfg.WavePhasicB) != std::string::npos) { + root["phase"] = "B"; + } else if (Qvvr_rptname.find(c_xmlcfg.WavePhasicC) != std::string::npos) { + root["phase"] = "C"; + } else { + root["phase"] = "unknow"; + } + } else { + root["phase"] = "unknow"; //不分相 + } + + std::string json_string = root.dump(4); + std::cout << json_string << std::endl; + + // 发送到暂态接口 + std::string response; + SendJsonAPI_web(WEB_EVENT, "", json_string, response); + + // ================ 插入新功能 ========================= + if (!response.empty()) { + try { + json j_r = json::parse(response); + // 有效响应,略过 + } catch (...) { + // 响应异常,保存 json + DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件", mp_id.c_str()); + + std::cout << "qvvr send fail ,store in local" << std::endl; + std::string qvvrDir = FRONT_PATH + "/dat/qvvr/"; + std::string fileName = qvvrDir + mp_id + "-" + FormatTimeForFilename(start_time_str) + "-" + std::to_string(dis_kind) + ".txt"; + writeJsonToFile(fileName, json_string); + checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024); + } + } else { + // 无响应,保存 json + DIY_ERRORLOG(full_key_m_d.c_str(), "【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件", mp_id.c_str()); + + std::cout << "qvvr send fail ,store in local" << std::endl; + std::string qvvrDir = FRONT_PATH + "/dat/qvvr/"; + std::string fileName = qvvrDir + mp_id + "-" + FormatTimeForFilename(start_time_str) + "-" + std::to_string(dis_kind) + ".txt"; + writeJsonToFile(fileName, json_string); + checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024); + return 1; + } + + // 离线重发机制 + { + std::string qvvrDir = FRONT_PATH + "/dat/qvvr/"; + scanAndResendOfflineFiles(qvvrDir); + } + + // 响应处理 + std::cout << "current qvvr handle response" << std::endl; + handleCommentResponse(response); + + return 0; +} + +void qvvr_test() +{ + char uuid_cfg[] = {"/comtrade/"}; + char uuid_dat[] = {"/comtrade/"}; + char mp_id[] = {"qvvrtest123"}; + char Qvvr_rptname[] = {"unknow"}; + char devtype[] = {"01"}; + + transfer_json_qvvr_data(1, 123456789, 220, 180, 1730894400.123, 1730894580, 1210001,uuid_cfg,uuid_dat,mp_id,Qvvr_rptname,devtype); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////通用接口响应 + +void handleCommentResponse(const std::string& response) { + try { + auto json_data = json::parse(response); // 或 json::parse(response); + + std::string code = "not found"; + std::string msg = "not found"; + if (json_data.contains("code")) { + if (json_data["code"].is_string()) { + code = json_data["code"]; + } else if (json_data["code"].is_number_integer() || json_data["code"].is_number()) { + code = std::to_string(json_data["code"].get()); + } + } + + if (json_data.contains("msg")) { + if (json_data["msg"].is_string()) { + msg = json_data["msg"]; + } + } + + if (code != "not found") { + std::cout << "Response Code: " << code << std::endl; + std::cout << "Message: " << msg << std::endl; + } else { + std::cerr << "Error: Missing expected fields in JSON response." << std::endl; + } + } catch (const json::parse_error& e) { + std::cerr << "Error parsing response: " << e.what() << std::endl; + } catch (const std::exception& e) { + std::cerr << "Unexpected exception: " << e.what() << std::endl; + } +} + diff --git a/LFtid1056/cloudfront/code/interface.h b/LFtid1056/cloudfront/code/interface.h new file mode 100644 index 0000000..a48a632 --- /dev/null +++ b/LFtid1056/cloudfront/code/interface.h @@ -0,0 +1,358 @@ +#ifndef INTERFACE_H +#define INTERFACE_H +/////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////////// + +class Front; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#define STAT_DATA_BASE_NODE_ID 100 +#define THREE_SECS_DATA_BASE_NODE_ID 200 +#define SOE_COMTRADE_BASE_NODE_ID 300 +#define HIS_DATA_BASE_NODE_ID 400 +#define NEW_HIS_DATA_BASE_NODE_ID 500 +#define RECALL_HIS_DATA_BASE_NODE_ID 600 +#define RECALL_ALL_DATA_BASE_NODE_ID 700 + +/////////////////////////////////////////////////////////////////////////////////////////// + +//单条补招结构 +class RecallInfo +{ +public: + long long starttime;//开始时间 + long long endtime; //结束时间 +}; + +//日志补招结构类 +class JournalRecall +{ +public: + std::string MonitorID; //线路监测点号 + std::string StartTime; //数据补招起始时间 + std::string EndTime; //数据补招结束时间 + std::string STEADY; //补招历史统计数据标识 0-不补招;1-补招 + std::string VOLTAGE; //补招暂态事件标识 0-不补招;1-补招 +}; + +//监测点台账 +class ledger_monitor +{ +public: + std::string monitor_id; //监测点id + std::string terminal_code; //监测点 + std::string monitor_name; //监测点名 + std::string logical_device_seq; //监测点序号 + std::string voltage_level; //监测点电压等级 + std::string terminal_connect; //监测点接线方式 + std::string timestamp; //更新时间 + std::string status; //监测点状态 +}; + +//终端台账 +class terminal_dev +{ +public: + std::string guid; + + std::string terminal_id; + std::string terminal_code; + std::string org_name; + std::string maint_name; + std::string station_name; + std::string tmnl_factory; + std::string tmnl_status; + std::string dev_type; + std::string dev_key; + std::string dev_series; + std::string addr_str; + std::string port; + std::string timestamp; + std::string processNo; + std::string maxProcessNum; + + std::vector line; +}; + +//icd模型 +class icd_model +{ +public: + std::string model_id; //模型id + std::string tmnl_type; //终端类型 + std::string tmnl_type_id; //终端类型id + std::string tmnl_factory; //终端厂家 + std::string file_name; //文件名 + std::string file_path; //文件路径 + std::string updatetime; //更新时间 + + icd_model() = default; +}; + +class queue_data_t //发送数据结构类 +{ +public: + int monitor_no; //监测点排号 + std::string strTopic; //发送topic + std::string strText; //发送的json字符串 + std::string mp_id; //监测点id +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// SOE 事件类 +class CEventData { +public: + int nDataType; // 告警 SOE 事件类型 + std::string type; // 参数等级 type 类型 + std::string triggerFlag; // 告警触发指标名称 + int nIndex; // 数据在每条线路值数组中的位置 + std::string DO; // 数据对象名 + std::string DA; // 数据属性名 + std::string strFullName; // 数据对象名 $ 数据属性名 +}; + +// 数据值类 +class CDataValue { +public: + std::string strName; // 数据名 + float fValue; // 数据值 + bool bIsValue; // 数据是否赋值成功标识 + int nIndex; // 数据在每条线路值数组中的位置 + std::string type; // 参数等级 type 类型 + std::string DO; // 数据对象名 + std::string DA; // 数据属性名 + std::string strFullName; // 数据对象名 $ 数据属性名 + std::string strCoefficient; // 数据系数(字符型) + float fCoefficient; // 数据系数(浮点型) + std::string strOffset; // 起始序号偏移量(字符型) + int iOffset; // 起始序号偏移量(整型) + bool bIsAngle; // 角度标志 + bool bPlt; // 长时闪变标识:true-长时闪变 false-短时闪变 + std::string BaseFlag; // 历史数据部分新增指标 BaseFlag + std::string LimitUp; // 历史数据部分新增指标 LimitUp + std::string LimitDown; // 历史数据部分新增指标 LimitDown + + CDataValue() + : fValue(0.0f), bIsValue(false), nIndex(0), + fCoefficient(1.0f), iOffset(0), bIsAngle(false), bPlt(false) {} +}; + +// 相别(A、B、C、T)类 +class CSequence { +public: + std::string strSValue; // 相别值 例:7:ABC三项,8:T相,112:AB、BC、CA三项 + std::string strSeq; // 相别 例:A、B、C、T + std::string type; // 参数等级 type 类型 + std::list DataValueList; // 数据值链表 +}; + +// 数据项类 +class CItem { +public: + std::string strItemName; // 数据项名 + std::string strItemValue; // 数据项值 + std::string type; // 参数等级 type 类型 + std::list SequenceList; // 相别列表 +}; + +// 监测点类 +class CMonitor { +public: + std::string strMonitor; // 监测点名 + std::string type; // 参数等级 type 类型 + std::list ItemList; // 数据项链表 +}; + +// 数据类型类 +class CDataType { +public: + int iDataType; // 数据类型值:1-稳态 2-闪变 3-暂态 + std::string type; // 参数等级 type 类型 + int BaseFlag1; // 记录基础数据总个数 + int BaseFlag0; // 记录非基础数据个数 + std::list MonitorList; // 监测点列表 + std::list SOEList; // 暂态事件列表 + + CDataType() : iDataType(0), BaseFlag1(0), BaseFlag0(0) {} +}; + +// 队列生产者发送主题类 +class CTopic { +public: + std::string strTopic; // 队列生产者发送的主题名 + std::list DataTypeList; // 数据类型链表 +}; + +/////////////////////////////////////////////////////////////////////////////////////////////// + +// XML 解析配置类 +class XmlConfig { +public: + std::string WavePhasicFlag; // 是否分相 0-不分相 1-分相 + std::string WavePhasicA; + std::string WavePhasicB; + std::string WavePhasicC; + std::string UnitOfTimeUnit; // 暂态事件持续单位:0-毫秒 1-秒 + std::string ValueOfTimeUnit; // 上送值时间:UTC 或 北京时间 + std::string WaveTimeFlag; // 录波文件时间:UTC 或 北京时间 + std::string IEDname; // 例:PQMonitor + std::string LDevicePrefix; // 例:PQM + std::list SOEList; // SOE 告警事件链表 +}; + +// 数据库模型表数据类 +class XmlDataBase { +public: + std::string MODEL_ID; // 模型编码 GUID + std::string TMNL_TYPE; // 终端型号 + std::string TMNL_FACTORY; // 终端厂家 + std::string FILE_PATH; // 远端模型文件路径 + std::string FILE_NAME; // 远端文件名 + std::string updatetime; // 更新时间 +}; + +class Xmldata +{ +public: + XmlDataBase xmlbase; //模型数据 + XmlConfig xmlcfg; //icd映射文件解析数据 + std::list topicList; //队列发送主题链表 + bool updataflag = true; //更新标志 +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +//台账更新结构///////////////////////////////////////////// +#define MAX_UPDATEA_NUM 10 +typedef struct trigger_update_xml_t trigger_update_xml_t; +struct trigger_update_xml_t { + std::vector new_updates; + std::vector modify_updates; + std::vector delete_updates; + std::vector work_updates; + + trigger_update_xml_t() = default; +}; + +//实时触发结构//////////////////////////////////////////////////////// +#define MAX_TRIGGER_NUM 300 +typedef struct trigger_t trigger_t; +struct trigger_t{ + int dev_idx; + int line_id; + int real_data; + int soe_data; + int limit; + int count; +}; +typedef struct trigger_3s_xml_t trigger_3s_xml_t; +struct trigger_3s_xml_t{ + int work_trigger_num; + int new_trigger_num; + int delete_trigger_num; + int modify_trigger_num; + trigger_t work_triggers[MAX_TRIGGER_NUM]; + trigger_t new_triggers[MAX_TRIGGER_NUM]; + trigger_t delete_triggers[MAX_TRIGGER_NUM]; + trigger_t modify_triggers[MAX_TRIGGER_NUM]; +}; + +//补招触发结构////////////////////////////////////////////////////////// +#define MAX_RECALL_NUM 300 +typedef struct recall_t recall_t; +struct recall_t{ + std::string line_id; + long long start_time; //待召唤日志起始时间 + long long end_time; //待召唤日志结束时间 + int need_steady; + int need_voltage; +}; +typedef struct recall_xml_t recall_xml_t; +struct recall_xml_t{ + int work_recall_num; + int new_recall_num; + recall_t work_recalls[MAX_RECALL_NUM]; + recall_t new_recalls[MAX_RECALL_NUM]; +}; + +/////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////////interface的函数声明 + +std::string parse_model_cfg_web_one(const std::string& terminal_type); + +int parse_device_cfg_web(); +int parse_model_cfg_web(); + +void qvvr_test(); +void Fileupload_test(); + +//////////////////////////////////////////////////////////////////////////////////cfg_parse的函数声明 + +void init_config(); +void Set_xml_nodeinfo(); +void Set_xml_nodeinfo_one(const std::string& dev_type); + +void check_3s_config(); +void check_ledger_update(); +void create_recall_xml(); + +double sGetMsTime(); +std::string get_current_time(); + +bool is_blank(const std::string& str); + +void print_terminal(const terminal_dev& tmnl); +void printTerminalDevMap(const std::map& terminal_dev_map); + +////////////////////////////////////////////////////////////////////////////////mq + + + +/////////////////////////////////////////////////////////////////////////////////主函数类声明 + +std::string get_front_msg_from_subdir(); + +extern std::string FRONT_PATH; + +void* cloudfrontthread(void* arg); + +struct ThreadArgs { + int argc; + char **argv; +}; + +//////////////////////////////////////////////////////////////////////////////////主要架构 + +/* 常量定义 */ +#define THREAD_CONNECTIONS 10 // 最大线程数 +#define MONITOR_INTERVAL 1 // 监控间隔(秒) + +/* 线程状态枚举 */ +typedef enum { + THREAD_RUNNING, // 0:运行中 + THREAD_STOPPED, // 1:正常停止 + THREAD_RESTARTING, // 2:重启中 + THREAD_CRASHED // 3:异常崩溃 +} thread_state_t; + +/* 线程控制结构体 */ +typedef struct { + pthread_t tid; // 线程ID + int index; // 线程编号(0~CONNECTIONS-1) + thread_state_t state; // 当前状态 + pthread_mutex_t lock; // 线程专用互斥锁 +} thread_info_t; + +#endif + + diff --git a/LFtid1056/cloudfront/code/log4.cpp b/LFtid1056/cloudfront/code/log4.cpp new file mode 100644 index 0000000..bffb006 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4.cpp @@ -0,0 +1,534 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "log4cplus/logger.h" +#include "log4cplus/configurator.h" +#include "log4cplus/fileappender.h" +#include "log4cplus/layout.h" +#include "log4cplus/ndc.h" +#include "log4cplus/log4.h" +#include "log4cplus/spi/loggingevent.h" + +#include "rocketmq.h" +#include "interface.h" +#include "log4cplus/log4.h" +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//log4命名空间 +using namespace log4cplus; +using namespace log4cplus::helpers; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//queue结构定义 +extern std::mutex queue_data_list_mutex; //queue发送数据锁 +extern std::list queue_data_list; //queue发送数据链表 + +extern unsigned int g_node_id; +extern int g_front_seg_index; +extern std::string FRONT_INST; +extern std::string subdir; + +//mq +extern std::mutex queue_data_list_mutex; //queue发送数据锁 +extern std::list queue_data_list; //queue发送数据链表 + +//日志主题 +extern std::string G_LOG_TOPIC; + +extern std::vector terminal_devlist; + +////////////////////////////////////////////////////////辅助函数 +std::string get_front_type_from_subdir() { + if (subdir == "cfg_3s_data") + return "realTime"; + else if (subdir == "cfg_soe_comtrade") + return "comtrade"; + else if (subdir == "cfg_recallhis_data") + return "recall"; + else if (subdir == "cfg_stat_data") + return "stat"; + else + return "unknown"; +} + +// 递归创建目录 +bool create_directory_recursive(const std::string& path) { + size_t pos = 0; + std::string current; + while (pos != std::string::npos) { + pos = path.find('/', pos + 1); + current = path.substr(0, pos); + if (!current.empty() && access(current.c_str(), F_OK) != 0) { + if (mkdir(current.c_str(), 0755) != 0) { + perror(("mkdir failed: " + current).c_str()); + return false; + } + } + } + return true; +} +////////////////////////////////////////////////////////////////////// +std::string extract_logger_id(const std::string& logger_name) { + size_t pos = logger_name.find('.'); + if (pos != std::string::npos && pos + 1 < logger_name.size()) { + return logger_name.substr(pos + 1); + } + return ""; // 没有找到 '.' 或 '.' 后为空 +} + +std::string get_level_str(int level) { + switch (level) { + case 10000: return "DEBUG"; + case 20000: return "NORMAL"; // 或 "INFO" 根据你业务定义 + case 30000: return "WARN"; + case 40000: return "ERROR"; + default: return "UNKNOWN"; + } +} +////////////////////////////////////////////////////////////////////// +TypedLogger::TypedLogger() {} +TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), logtype(t) {} + +DebugSwitch::DebugSwitch() : debug_open(false), min_level(WARN_LOG_LEVEL) {} +void DebugSwitch::open() { debug_open = true; } +void DebugSwitch::close() { + debug_open = false; + targets.clear(); + type_enable.clear(); +} +void DebugSwitch::set_target(const std::string& name) { targets.insert(name); } +void DebugSwitch::set_level(int level) { min_level = level; } +void DebugSwitch::enable_type(int type) { type_enable[type] = true; } +void DebugSwitch::disable_type(int type) { type_enable[type] = false; } + +bool DebugSwitch::match(const std::string& logger_name, int level, int logtype) { + if (!debug_open) return false; + if (level < min_level) return false; + if (type_enable.count(logtype) && !type_enable[logtype]) return false; + std::set::iterator it; + for (it = targets.begin(); it != targets.end(); ++it) { + if (logger_name.find(*it) != std::string::npos) + return true; + } + return false; +} + +std::map logger_map; +DebugSwitch g_debug_switch; + +class SendAppender : public Appender { +protected: + void append(const spi::InternalLoggingEvent& event) { + std::string logger_name = event.getLoggerName(); + int level = event.getLogLevel(); + std::string msg = event.getMessage(); + + int logtype = (logger_name.find(".COM") != std::string::npos) ? LOGTYPE_COM : LOGTYPE_DATA; + std::string level_str; + if (logger_name.find("process") == 0) + level_str = "process"; + else if (logger_name.find("monitor") != std::string::npos) + level_str = "measurepoint"; + else + level_str = "terminal"; + + if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) { + std::ostringstream oss; + oss << "{\"processNo\":\"" << std::to_string(g_front_seg_index) + << "\",\"nodeId\":\"" << FRONT_INST + << "\",\"businessId\":\"" << extract_logger_id(logger_name) + << "\",\"level\":\"" << level_str + << "\",\"grade\":\"" << get_level_str(level) + << "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data") + << "\",\"frontType\":\"" << get_front_type_from_subdir() + << "\",\"log\":\"" << escape_json(msg) << "\"}"; + + std::string jsonString = oss.str(); + + queue_data_t connect_info; + connect_info.strTopic = G_LOG_TOPIC; + connect_info.strText = jsonString; + + std::lock_guard lock(queue_data_list_mutex); + queue_data_list.push_back(connect_info); + } + } + + std::string escape_json(const std::string& input) { + std::ostringstream ss; + for (unsigned int i = 0; i < input.size(); ++i) { + switch (input[i]) { + case '\\': ss << "\\\\"; break; + case '"': ss << "\\\""; break; + case '\n': ss << "\\n"; break; + case '\r': ss << "\\r"; break; + case '\t': ss << "\\t"; break; + default: ss << input[i]; break; + } + } + return ss.str(); + } + + virtual void close() { + // 可空实现 + } + +public: + SendAppender() {} + virtual ~SendAppender() { + destructorImpl(); // 重要!释放 log4cplus 基类资源 + } +}; + +//用来控制日志上送的结构 +struct LOGEntry { + std::string id; + std::string level; // terminal / measurepoint + int logtype; // com / data + int min_grade; + int countdown; +}; + +//日志上送map管理 +std::map g_log_entries; +pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER; + +// 生成唯一 key +std::string build_debug_key(const std::string& id, const std::string& level, int logtype) { + return id + "|" + level + "|" + (logtype == 1 ? "COM" : "DATA"); +} + +// 外部线程中调用:每秒更新所有倒计时,0 则删除 +void update_log_entries_countdown() { + pthread_mutex_lock(&g_log_mutex); + std::map::iterator it = g_log_entries.begin(); + while (it != g_log_entries.end()) { + if (it->second.countdown > 0) { + it->second.countdown--; + if (it->second.countdown == 0) { + std::cout << "[LOG] debug日志上送自动关闭: " << it->first << std::endl; + it = g_log_entries.erase(it); + continue; + } + } + ++it; + } + pthread_mutex_unlock(&g_log_mutex); +} + +void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str) { + if (level != "terminal" && level != "measurepoint") return; + + int type = (logtype_str == "com") ? LOGTYPE_COM : LOGTYPE_DATA; + int grade_level = (grade == "DEBUG") ? DEBUG_LOG_LEVEL : INFO_LOG_LEVEL; + + std::string key = build_debug_key(id, level, type); + + pthread_mutex_lock(&g_log_mutex); + + LOGEntry& entry = g_log_entries[key]; // 会自动 insert 或取已有 + entry.id = id; + entry.level = level; + entry.logtype = type; + entry.min_grade = grade_level; + entry.countdown = 60; // 重置倒计时 + + pthread_mutex_unlock(&g_log_mutex); + +} + +Logger init_logger(const std::string& full_name, const std::string& file_dir, const std::string& base_file, SharedAppenderPtr fileAppender) { + create_directory_recursive(file_dir); + + Logger logger = Logger::getInstance(full_name); + if (!fileAppender) { + std::string file_path = file_dir + "/" + base_file + ".log"; + fileAppender = SharedAppenderPtr(new RollingFileAppender(file_path, 1 * 1024 * 1024, 2)); + fileAppender->setLayout(std::unique_ptr( + new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); + } + + SharedAppenderPtr sendAppender(new SendAppender()); + logger.addAppender(fileAppender); + logger.addAppender(sendAppender); + logger.setLogLevel(DEBUG_LOG_LEVEL); + return logger; +} + +// 重载版本:无 Appender 传入时调用上面的实现 +log4cplus::Logger init_logger(const std::string& full_name, + const std::string& file_dir, + const std::string& base_file) { + return init_logger(full_name, file_dir, base_file, + log4cplus::SharedAppenderPtr()); // 空指针 +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////应用函数 + +//进程的日志 +void init_logger_process() { + std::string base_dir = FRONT_PATH + "/" + subdir + "/processNo" + std::to_string(g_front_seg_index) + "/log"; + logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DATA); + std::cout << "process log init ok" << std::endl; +} + +//单个终端的日志初始化 +void init_loggers_bydevid(const std::string& dev_id) +{ + if (dev_id.empty()) return; + + std::string terminal_id = dev_id; + std::string base_dir = FRONT_PATH + "/" + subdir + "/processNo" + std::to_string(g_front_seg_index) + "/log"; + + for (size_t i = 0; i < terminal_devlist.size(); ++i) { + terminal_dev& term = terminal_devlist[i]; + + // 跳过终端台账信息为空的节点 + if (term.terminal_id.empty()) { + std::cout << "terminal_dev No." << i << " is null" << std::endl; + continue; + } + + // 跳过不匹配的终端 + if (term.terminal_id != dev_id) continue; + + std::string ip_str = term.addr_str.empty() ? "unknown" : term.addr_str; + std::string device_dir = base_dir + "/" + ip_str; + std::string device_key_c = std::string("terminal.") + dev_id + ".COM"; + std::string device_key_d = std::string("terminal.") + dev_id + ".DATA"; + + // 添加判断:终端日志 logger 是否已存在 + if (logger_map.find(device_key_c) == logger_map.end() && + logger_map.find(device_key_d) == logger_map.end()) { + + // 所有终端日志(com 和 data)写到同一个 device 日志文件中 + std::string file_path_t = device_dir + "/" + dev_id + ".log"; + + // 共用一个 appender 实例 + SharedAppenderPtr device_appender(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2)); + device_appender->setLayout(std::unique_ptr(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); + + Logger device_logger_c = init_logger(device_key_c, device_dir, dev_id, device_appender); + Logger device_logger_d = init_logger(device_key_d, device_dir, dev_id, device_appender); + logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM); + logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA); + + DIY_WARNLOG(device_key_d.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str()); + } + + // 初始化监测点日志,monitor..COM / .DATA + for (size_t j = 0; j < term.line.size(); ++j) { + const ledger_monitor& monitor = term.line[j]; + if (!monitor.monitor_id.empty()) { + std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name; + mon_key_c << "monitor." << monitor.monitor_id << ".COM"; + mon_key_d << "monitor." << monitor.monitor_id << ".DATA"; + mon_path << device_dir << "/monitor" << j; + mon_name << monitor.monitor_id; + + // 判断监测点 logger 是否已存在 + if (logger_map.find(mon_key_c.str()) == logger_map.end() && + logger_map.find(mon_key_d.str()) == logger_map.end()) { + + // 所有监测点日志(com 和 data)写到同一个 monitor 日志文件中 + std::string file_path_m = mon_path.str() + "/" + mon_name.str() + ".log"; + + // 共用一个 appender 实例 + SharedAppenderPtr monitor_appender(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2)); + monitor_appender->setLayout(std::unique_ptr(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); + + Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender); + Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender); + logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM); + logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA); + + DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", monitor.monitor_name.c_str(), monitor.monitor_id.c_str()); + } + } + } + + break; // 只匹配一个 terminal_id + } +} + +//初始化台账日志 +void init_loggers() +{ + std::string base_dir = FRONT_PATH + "/" + subdir + "/processNo" + std::to_string(g_front_seg_index) + "/log"; + + // 遍历所有终端 + for (size_t t = 0; t < terminal_devlist.size(); ++t) { + terminal_dev& term = terminal_devlist[t]; + + // 跳过无效终端 + if (term.terminal_id.empty()) { + std::cout << "terminal_dev No." << t << " is null" << std::endl; + continue; + } + + std::string ip_str = term.addr_str.empty() ? "unknown" : term.addr_str; + std::string device_dir = base_dir + "/" + ip_str; + + std::string device_key_c = std::string("terminal.") + term.terminal_id + ".COM"; + std::string device_key_d = std::string("terminal.") + term.terminal_id + ".DATA"; + + // 所有终端日志(com 和 data)写到同一个 device 日志文件中 + std::string file_path_t = device_dir + "/" + term.terminal_id + ".log"; + + // 共用一个 appender 实例 + SharedAppenderPtr device_appender(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2)); + device_appender->setLayout(std::unique_ptr(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); + + Logger device_logger_c = init_logger(device_key_c, device_dir, term.terminal_id, device_appender); + Logger device_logger_d = init_logger(device_key_d, device_dir, term.terminal_id, device_appender); + + logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM); + logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA); + + DIY_WARNLOG(device_key_d.c_str(), "【WARN】终端id:%s终端级日志初始化完毕", term.terminal_id.c_str()); + + // 初始化监测点日志 + for (size_t i = 0; i < term.line.size(); ++i) { + const ledger_monitor& monitor = term.line[i]; + + if (!monitor.monitor_id.empty()) { + std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name; + mon_key_c << "monitor." << monitor.monitor_id << ".COM"; + mon_key_d << "monitor." << monitor.monitor_id << ".DATA"; + + mon_path << device_dir << "/monitor" << i; // 用monitor+序号作为目录 + mon_name << monitor.monitor_id; + + std::string file_path_m = mon_path.str() + "/" + mon_name.str() + ".log"; + + // 共用一个 appender 实例 + SharedAppenderPtr monitor_appender(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2)); + monitor_appender->setLayout(std::unique_ptr(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n"))); + + Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender); + Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender); + + logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM); + logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA); + + DIY_WARNLOG(mon_key_d.str().c_str(), "【WARN】监测点:%s - id:%s监测点级日志初始化完毕", + monitor.monitor_name.c_str(), monitor.monitor_id.c_str()); + } + } + } +} + +//单个终端的日志删除 +void remove_loggers_by_terminal_id(const std::string& terminal_id) { + // 遍历所有终端 + for (size_t t = 0; t < terminal_devlist.size(); ++t) { + terminal_dev& term = terminal_devlist[t]; + if (term.terminal_id != terminal_id) continue; + + // 删除终端日志 logger + std::string com_key = "terminal." + terminal_id + ".COM"; + std::string data_key = "terminal." + terminal_id + ".DATA"; + + if (logger_map.count(com_key)) { + logger_map[com_key].logger.removeAllAppenders(); + logger_map.erase(com_key); + } + + if (logger_map.count(data_key)) { + logger_map[data_key].logger.removeAllAppenders(); + logger_map.erase(data_key); + } + + // 删除监测点日志 logger + for (size_t i = 0; i < term.line.size(); ++i) { + const ledger_monitor& monitor = term.line[i]; + if (!monitor.monitor_id.empty()) { + std::string mon_prefix = "monitor." + monitor.monitor_id; + std::string mon_com_key = mon_prefix + ".COM"; + std::string mon_data_key = mon_prefix + ".DATA"; + + if (logger_map.count(mon_com_key)) { + logger_map[mon_com_key].logger.removeAllAppenders(); + logger_map.erase(mon_com_key); + } + + if (logger_map.count(mon_data_key)) { + logger_map[mon_data_key].logger.removeAllAppenders(); + logger_map.erase(mon_data_key); + } + } + } + + std::cout << "[LOG] Logger for terminal_id=" << terminal_id << " removed." << std::endl; + break; // 找到匹配终端后退出 + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////封装函数,C/C++通用 + +#ifdef __cplusplus +extern "C" { +#endif + + // 公共函数 + void log4_log_with_level(const char* key, const char* msg, int level) { + std::map::iterator it = logger_map.find(key); + if (it == logger_map.end()) return; + + Logger logger = it->second.logger; + switch (level) { + case 0: LOG4CPLUS_DEBUG(logger, msg); break; + case 1: LOG4CPLUS_INFO(logger, msg); break; + case 2: LOG4CPLUS_WARN(logger, msg); break; + case 3: LOG4CPLUS_ERROR(logger, msg); break; + default: break; + } + } + + // 四个包装函数 + void log_debug(const char* key, const char* msg) { log4_log_with_level(key, msg, 0); } + void log_info (const char* key, const char* msg) { log4_log_with_level(key, msg, 1); } + void log_warn (const char* key, const char* msg) { log4_log_with_level(key, msg, 2); } + void log_error(const char* key, const char* msg) { log4_log_with_level(key, msg, 3); } + + void send_reply_to_queue_c(const char* guid, const char* step, const char* result) { + send_reply_to_queue(std::string(guid), std::string(step), std::string(result)); + } + + //标准化日志接口 + void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...) { + // 写入时间 + time_t now = time(NULL); + struct tm tm_info; + localtime_r(&now, &tm_info); + strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S ", &tm_info); // 时间+空格 + + // 处理可变参数并写入剩余内容 + va_list args; + va_start(args, fmt); + vsnprintf(buf + strlen(buf), buf_size - strlen(buf), fmt, args); + va_end(args); + } + +#ifdef __cplusplus +} +#endif diff --git a/LFtid1056/cloudfront/code/log4cplus/appender.h b/LFtid1056/cloudfront/code/log4cplus/appender.h new file mode 100644 index 0000000..972359a --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/appender.h @@ -0,0 +1,340 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_APPENDER_HEADER_ +#define LOG4CPLUS_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace log4cplus { + + + namespace helpers + { + + class Properties; + + } + + + /** + * This class is used to "handle" errors encountered in an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT ErrorHandler + { + public: + ErrorHandler (); + virtual ~ErrorHandler() = 0; + virtual void error(const log4cplus::tstring& err) = 0; + virtual void reset() = 0; + }; + + + class LOG4CPLUS_EXPORT OnlyOnceErrorHandler + : public ErrorHandler + { + public: + // Ctor + OnlyOnceErrorHandler(); + virtual ~OnlyOnceErrorHandler (); + virtual void error(const log4cplus::tstring& err); + virtual void reset(); + + private: + bool firstTime; + }; + + + /** + * Extend this class for implementing your own strategies for printing log + * statements. + * + *

Properties

+ *
+ * + *
layout
+ *
This property specifies message layout used by + * Appender. + * \sa Layout + *
+ * + *
filters
+ *
This property specifies possibly multiple filters used by + * Appender. Each of multple filters and its properties is under a + * numbered subkey of filters key. E.g.: + * filters.1=log4cplus::spi::LogLevelMatchFilter. Filter + * subkey numbers must be consecutive.
+ * + *
Threshold
+ *
This property specifies log level threshold. Events with + * lower log level than the threshold will not be logged by + * appender.
+ * + *
UseLockFile
+ *
Set this property to true if you want your output + * through this appender to be synchronized between multiple + * processes. When this property is set to true then log4cplus + * uses OS specific facilities (e.g., lockf()) to + * provide inter-process locking. With the exception of + * FileAppender and its derived classes, it is also necessary to + * provide path to a lock file using the LockFile + * property. + * \sa FileAppender + *
+ * + *
LockFile
+ *
This property specifies lock file, file used for + * inter-process synchronization of log file access. The property + * is only used when UseLockFile is set to true. Then it + * is mandatory. + * \sa FileAppender + *
+ * + *
AsyncAppend
+ *
Set this property to true if you want all appends using + * this appender to be done asynchronously. Default is false.
+ * + *
+ */ + class LOG4CPLUS_EXPORT Appender + : public virtual log4cplus::helpers::SharedObject + { + public: + // Ctor + Appender(); + Appender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~Appender(); + + /** + * This function is for derived appenders to call from their + * destructors. All classes derived from `Appender` class + * _must_ call this function from their destructors. It + * ensures that appenders will get properly closed during + * shutdown by call to `close()` function before they are + * destroyed. + */ + void destructorImpl(); + + // Methods + /** + * Release any resources allocated within the appender such as file + * handles, network connections, etc. + * + * It is a programming error to append to a closed appender. + */ + virtual void close() = 0; + + /** + * Check if this appender is in closed state. + */ + bool isClosed() const; + + /** + * This method performs threshold checks and invokes filters before + * delegating actual logging to the subclasses specific {@link + * #append} method. + */ + void syncDoAppend(const log4cplus::spi::InternalLoggingEvent& event); + + /** + * This method performs book keeping related to asynchronous logging + * and executes `syncDoAppend()` to do the actual logging. + */ + + void asyncDoAppend(const log4cplus::spi::InternalLoggingEvent& event); + + /** + * This function checks `async` flag. It either executes + * `syncDoAppend()` directly or enqueues its execution to thread pool + * thread. + */ + void doAppend(const log4cplus::spi::InternalLoggingEvent& event); + + /** + * Get the name of this appender. The name uniquely identifies the + * appender. + */ + virtual log4cplus::tstring getName(); + + /** + * Set the name of this appender. The name is used by other + * components to identify this appender. + */ + virtual void setName(const log4cplus::tstring& name); + + /** + * Set the {@link ErrorHandler} for this Appender. + */ + virtual void setErrorHandler(std::unique_ptr eh); + + /** + * Return the currently set {@link ErrorHandler} for this + * Appender. + */ + virtual ErrorHandler* getErrorHandler(); + + /** + * Set the layout for this appender. Note that some appenders have + * their own (fixed) layouts or do not use one. For example, the + * SocketAppender ignores the layout set here. + */ + virtual void setLayout(std::unique_ptr layout); + + /** + * Returns the layout of this appender. The value may be NULL. + * + * This class owns the returned pointer. + */ + virtual Layout* getLayout(); + + /** + * Set the filter chain on this Appender. + */ + void setFilter(log4cplus::spi::FilterPtr f); + + /** + * Get the filter chain on this Appender. + */ + log4cplus::spi::FilterPtr getFilter() const; + + /** + * Add filter at the end of the filters chain. + */ + void addFilter (log4cplus::spi::FilterPtr f); + + /** + * Add filter at the end of the filters chain. + */ + void addFilter (std::function< + spi::FilterResult (const log4cplus::spi::InternalLoggingEvent &)>); + + /** + * Returns this appenders threshold LogLevel. See the {@link + * #setThreshold} method for the meaning of this option. + */ + LogLevel getThreshold() const { return threshold; } + + /** + * Set the threshold LogLevel. All log events with lower LogLevel + * than the threshold LogLevel are ignored by the appender. + * + * In configuration files this option is specified by setting the + * value of the Threshold option to a LogLevel + * string, such as "DEBUG", "INFO" and so on. + */ + void setThreshold(LogLevel th) { threshold = th; } + + /** + * Check whether the message LogLevel is below the appender's + * threshold. If there is no threshold set, then the return value is + * always true. + */ + bool isAsSevereAsThreshold(LogLevel ll) const { + return ((ll != NOT_SET_LOG_LEVEL) && (ll >= threshold)); + } + + /** + * This method waits for all events that are being asynchronously + * logged to finish. + */ + void waitToFinishAsyncLogging(); + + protected: + // Methods + /** + * Subclasses of Appender should implement this + * method to perform actual logging. + * @see doAppend method. + */ + virtual void append(const log4cplus::spi::InternalLoggingEvent& event) = 0; + + tstring & formatEvent (const log4cplus::spi::InternalLoggingEvent& event) const; + + // Data + /** The layout variable does not need to be set if the appender + * implementation has its own layout. */ + std::unique_ptr layout; + + /** Appenders are named. */ + log4cplus::tstring name; + + /** There is no LogLevel threshold filtering by default. */ + LogLevel threshold; + + /** The first filter in the filter chain. Set to null + * initially. */ + log4cplus::spi::FilterPtr filter; + + /** It is assumed and enforced that errorHandler is never null. */ + std::unique_ptr errorHandler; + + //! Optional system wide synchronization lock. + std::unique_ptr lockFile; + + //! Use lock file for inter-process synchronization of access + //! to log file. + bool useLockFile; + + //! Asynchronous append. + bool async; +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + std::atomic in_flight; + std::mutex in_flight_mutex; + std::condition_variable in_flight_condition; +#endif + + /** Is this appender closed? */ + bool closed; + + private: +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + void subtract_in_flight(); +#endif + }; + + /** This is a pointer to an Appender. */ + typedef helpers::SharedObjectPtr SharedAppenderPtr; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/asyncappender.h b/LFtid1056/cloudfront/code/log4cplus/asyncappender.h new file mode 100644 index 0000000..1a5439a --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/asyncappender.h @@ -0,0 +1,110 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: asyncappender.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_ASYNCAPPENDER_H +#define LOG4CPLUS_ASYNCAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED + +#include +#include +#include +#include + + +namespace log4cplus +{ + + +/** + This `Appender` is a wrapper to which other appenders can be attached. The + attached appendres are then appended to from a separate thread which reads + events appended to this appender from a queue. + +

Properties

+
+ +
QueueLimit
+
Events queue size limit. Default is 100.
+ + +
Appender
+
`Appender` and its properties to use as sink for logged events.
+ + +
+ + \sa helpers::AppenderAttachableImpl + */ +class LOG4CPLUS_EXPORT AsyncAppender + : public Appender + , public helpers::AppenderAttachableImpl +{ +public: + AsyncAppender (SharedAppenderPtr const & app, unsigned max_len); + AsyncAppender (helpers::Properties const &); + virtual ~AsyncAppender (); + + virtual void close (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + void init_queue_thread (unsigned); + + thread::AbstractThreadPtr queue_thread; + thread::QueuePtr queue; + +private: + AsyncAppender (AsyncAppender const &); + AsyncAppender & operator = (AsyncAppender const &); +}; + + +typedef helpers::SharedObjectPtr AsyncAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_SINGLE_THREADED + +#endif // LOG4CPLUS_ASYNCAPPENDER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/boost/deviceappender.hxx b/LFtid1056/cloudfront/code/log4cplus/boost/deviceappender.hxx new file mode 100644 index 0000000..eb41edf --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/boost/deviceappender.hxx @@ -0,0 +1,201 @@ +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX +#define LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + + +namespace device_appender_detail +{ + + +template +struct device_type_traits +{ + typedef T & device_type; + + static + device_type + unwrap (device_type x) + { + return x; + } +}; + + +template +struct device_type_traits > +{ + typedef boost::shared_ptr device_type; + + static + T & + unwrap (device_type const & ptr) + { + return *ptr; + } +}; + + +} // namespace device_appender_detail + + +template +class DeviceAppender + : public Appender +{ +public: + typedef device_appender_detail::device_type_traits device_traits; + typedef typename device_traits::device_type device_type; + + template + DeviceAppender (D & d, bool close_device = true) + : device (d) + , close_flag (close_device) + { } + + template + DeviceAppender (boost::shared_ptr const & d, bool close_device = true) + : device (d) + , close_flag (close_device) + { } + + template + DeviceAppender (D & d, const helpers::Properties & props) + : Appender (props) + , device (d) + { + if (props.exists (LOG4CPLUS_TEXT ("CloseDevice"))) + close_flag = true; + else + close_flag = false; + } + + template + DeviceAppender (boost::shared_ptr const & d, + const helpers::Properties & props) + : Appender (props) + , device (d) + { + if (props.exists (LOG4CPLUS_TEXT ("CloseDevice"))) + close_flag = true; + else + close_flag = false; + } + + virtual + ~DeviceAppender () + { } + + virtual + void + close () + { + if (close_flag) + boost::iostreams::close (device_traits::unwrap (device)); + } + +protected: + virtual + void + append (log4cplus::spi::InternalLoggingEvent const & event) + { + tstring & str = formatEvent (event); + boost::iostreams::write (device_traits::unwrap (device), + str.c_str (), str.size ()); + } + + device_type device; + bool close_flag; + +private: + DeviceAppender (DeviceAppender const &); + DeviceAppender & operator = (DeviceAppender const &); +}; + + +template +inline +SharedAppenderPtr +make_device_appender (T & d, bool close_device = true) +{ + SharedAppenderPtr app (new DeviceAppender (d, close_device)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender (T & d, const helpers::Properties & props) +{ + SharedAppenderPtr app (new DeviceAppender (d, props)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender_sp (boost::shared_ptr const & p, + bool close_device = true) +{ + SharedAppenderPtr app ( + new DeviceAppender > (p, close_device)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender_sp (boost::shared_ptr const & p, + const helpers::Properties & props) +{ + SharedAppenderPtr app ( + new DeviceAppender > (p, props)); + return app; +} + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX diff --git a/LFtid1056/cloudfront/code/log4cplus/callbackappender.h b/LFtid1056/cloudfront/code/log4cplus/callbackappender.h new file mode 100644 index 0000000..0c61bed --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/callbackappender.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +// Copyright (C) 2015-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +/** @file */ + +#ifndef LOG4CPLUS_CALLBACK_APPENDER_HEADER_ +#define LOG4CPLUS_CALLBACK_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + +/** +* Send log events to a C function callback. +*/ +class LOG4CPLUS_EXPORT CallbackAppender + : public Appender { +public: + CallbackAppender(); + CallbackAppender(log4cplus_log_event_callback_t callback, void * cookie); + CallbackAppender(const log4cplus::helpers::Properties&); + + virtual ~CallbackAppender(); + virtual void close(); + + void setCookie(void *); + void setCallback(log4cplus_log_event_callback_t); + +protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + +private: + log4cplus_log_event_callback_t callback; + void * cookie; + + // Disallow copying of instances of this class + CallbackAppender(const CallbackAppender&) = delete; + CallbackAppender& operator=(const CallbackAppender&) = delete; +}; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CALLBACK_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/clfsappender.h b/LFtid1056/cloudfront/code/log4cplus/clfsappender.h new file mode 100644 index 0000000..e764315 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/clfsappender.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: clfsappender.h +// Created: 5/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_CLFSAPPENDER_H +#define LOG4CPLUS_CLFSAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +#if defined (LOG4CPLUS_CLFSAPPENDER_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS_CLFSAPPENDER) +# define LOG4CPLUS_CLFSAPPENDER_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_CLFSAPPENDER_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_CLFSAPPENDER_EXPORT +#endif + + +namespace log4cplus +{ + + +class LOG4CPLUS_CLFSAPPENDER_EXPORT CLFSAppender + : public Appender +{ +public: + CLFSAppender (tstring const & logname, unsigned long logsize, + unsigned long buffersize); + explicit CLFSAppender (helpers::Properties const &); + virtual ~CLFSAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + void init (tstring const & logname, unsigned long logsize, + unsigned long buffersize); + + struct Data; + + Data * data; + +private: + CLFSAppender (CLFSAppender const &); + CLFSAppender & operator = (CLFSAppender const &); +}; + + +typedef helpers::SharedObjectPtr CLFSAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_CLFSAPPENDER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/clogger.h b/LFtid1056/cloudfront/code/log4cplus/clogger.h new file mode 100644 index 0000000..b8b2a43 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/clogger.h @@ -0,0 +1,126 @@ +// -*- C -*- +/** + * Module: Log4CPLUS + * File: clogger.h + * Created: 01/2011 + * Author: Jens Rehsack + * + * + * Copyright 2011-2017 Jens Rehsack & Tad E. Smith + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * This header defines the C API for log4cplus and the logging macros. */ + +#ifndef LOG4CPLUS_CLOGGERHEADER_ +#define LOG4CPLUS_CLOGGERHEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +// TODO UNICDE capable + +typedef void * log4cplus_logger_t; +typedef log4cplus_logger_t logger_t; + +typedef int log4cplus_loglevel_t; +typedef log4cplus_loglevel_t loglevel_t; + +#define L4CP_OFF_LOG_LEVEL 60000 +#define L4CP_FATAL_LOG_LEVEL 50000 +#define L4CP_ERROR_LOG_LEVEL 40000 +#define L4CP_WARN_LOG_LEVEL 30000 +#define L4CP_INFO_LOG_LEVEL 20000 +#define L4CP_DEBUG_LOG_LEVEL 10000 +#define L4CP_TRACE_LOG_LEVEL 0 +#define L4CP_ALL_LOG_LEVEL TRACE_LOG_LEVEL +#define L4CP_NOT_SET_LOG_LEVEL -1 + +#ifdef UNICODE +typedef wchar_t log4cplus_char_t; +#else +typedef char log4cplus_char_t; +#endif // UNICODE + +#if ! defined (LOG4CPLUS_TEXT) +#ifdef UNICODE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) +#endif // LOG4CPLUS_TEXT + +LOG4CPLUS_EXPORT void * log4cplus_initialize(void); +LOG4CPLUS_EXPORT int log4cplus_deinitialize(void * initializer); + +LOG4CPLUS_EXPORT int log4cplus_file_configure(const log4cplus_char_t *pathname); +LOG4CPLUS_EXPORT int log4cplus_file_reconfigure(const log4cplus_char_t *pathname); +LOG4CPLUS_EXPORT int log4cplus_str_configure(const log4cplus_char_t *config); +LOG4CPLUS_EXPORT int log4cplus_str_reconfigure(const log4cplus_char_t *config); +LOG4CPLUS_EXPORT int log4cplus_basic_configure(void); +LOG4CPLUS_EXPORT int log4cplus_basic_reconfigure(int logToStdErr); +LOG4CPLUS_EXPORT void log4cplus_shutdown(void); + +LOG4CPLUS_EXPORT int log4cplus_logger_exists(const log4cplus_char_t *name); +LOG4CPLUS_EXPORT int log4cplus_logger_is_enabled_for( + const log4cplus_char_t *name, log4cplus_loglevel_t ll); + +LOG4CPLUS_EXPORT int log4cplus_logger_log(const log4cplus_char_t *name, + log4cplus_loglevel_t ll, const log4cplus_char_t *msgfmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 4); + +LOG4CPLUS_EXPORT int log4cplus_logger_log_str(const log4cplus_char_t *name, + log4cplus_loglevel_t ll, const log4cplus_char_t *msg); + +LOG4CPLUS_EXPORT int log4cplus_logger_force_log(const log4cplus_char_t *name, + log4cplus_loglevel_t ll, const log4cplus_char_t *msgfmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 4); + +LOG4CPLUS_EXPORT int log4cplus_logger_force_log_str(const log4cplus_char_t *name, + log4cplus_loglevel_t ll, const log4cplus_char_t *msg); + +//! CallbackAppender callback type. +typedef void (* log4cplus_log_event_callback_t)(void * cookie, + log4cplus_char_t const * message, log4cplus_char_t const * loggerName, + log4cplus_loglevel_t ll, log4cplus_char_t const * thread, + log4cplus_char_t const * thread2, + unsigned long long timestamp_secs, unsigned long timestamp_usecs, + log4cplus_char_t const * file, log4cplus_char_t const * function, int line); + +LOG4CPLUS_EXPORT int log4cplus_add_callback_appender( + const log4cplus_char_t * logger, log4cplus_log_event_callback_t callback, + void * cookie); + +// Custom LogLevel +LOG4CPLUS_EXPORT int log4cplus_add_log_level(unsigned int ll, + const log4cplus_char_t *ll_name); +LOG4CPLUS_EXPORT int log4cplus_remove_log_level(unsigned int ll, + const log4cplus_char_t *ll_name); + +#ifdef __cplusplus +} +#endif + +#endif /*?LOG4CPLUS_CLOGGERHEADER_*/ diff --git a/LFtid1056/cloudfront/code/log4cplus/config.h.cmake.in b/LFtid1056/cloudfront/code/log4cplus/config.h.cmake.in new file mode 100644 index 0000000..2bf4342 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config.h.cmake.in @@ -0,0 +1,335 @@ +/* include/log4cplus/config.h.in. Generated from configure.in by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +/* #undef HAS_C99_VARIADIC_MACROS */ + +/* Defined if the compiler supports GNU style variadic macros. */ +/* #undef HAS_GNU_VARIADIC_MACROS */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ftime' function. */ +#cmakedefine HAVE_FTIME 1 + +/* */ +#cmakedefine HAVE_GETADDRINFO 1 + +/* */ +#cmakedefine HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define to 1 if you have the `htonl' function. */ +#cmakedefine HAVE_HTONL 1 + +/* Define to 1 if you have the `htons' function. */ +#cmakedefine HAVE_HTONS 1 + +/* Define to 1 if you have the `iconv' function. */ +#cmakedefine HAVE_ICONV 1 + +/* Define to 1 if you have the `iconv_close' function. */ +#cmakedefine HAVE_ICONV_CLOSE 1 + +/* Define to 1 if you have the `iconv_open' function. */ +#cmakedefine HAVE_ICONV_OPEN 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#cmakedefine HAVE_LIBADVAPI32 1 + +/* Define to 1 if you have the `libiconv' function. */ +/* #undef HAVE_LIBICONV */ + +/* Define to 1 if you have the `libiconv_close' function. */ +/* #undef HAVE_LIBICONV_CLOSE */ + +/* Define to 1 if you have the `libiconv_open' function. */ +/* #undef HAVE_LIBICONV_OPEN */ + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#cmakedefine HAVE_LIBKERNEL32 1 + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#cmakedefine HAVE_LIBNSL 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +#cmakedefine HAVE_LIBRT 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#cmakedefine HAVE_LIBWS2_32 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `ntohl' function. */ +#cmakedefine HAVE_NTOHL 1 + +/* Define to 1 if you have the `ntohs' function. */ +#cmakedefine HAVE_NTOHS 1 + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if you have the `stat' function. */ +#cmakedefine HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfprintf_s' function. */ +#cmakedefine HAVE_VFPRINTF_S 1 + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#cmakedefine HAVE_VFWPRINTF_S 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#cmakedefine HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsprintf_s' function. */ +#cmakedefine HAVE_VSPRINTF_S 1 + +/* Define to 1 if you have the `vswprintf_s' function. */ +#cmakedefine HAVE_VSWPRINTF_S 1 + +/* Define to 1 if you have the `_vsnprintf' function. */ +#cmakedefine HAVE__VSNPRINTF 1 + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#cmakedefine HAVE__VSNPRINTF_S 1 + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#cmakedefine HAVE__VSNWPRINTF_S 1 + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#cmakedefine HAVE___FUNCTION___MACRO 1 + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#cmakedefine HAVE___PRETTY_FUNCTION___MACRO 1 + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#cmakedefine HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#cmakedefine HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT @LOG4CPLUS_DECLSPEC_EXPORT@ + +/* Defined if the compiler understands __declspec(dllexport) or construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT @LOG4CPLUS_DECLSPEC_IMPORT@ /**/ + +/* */ +#cmakedefine LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETTID 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_HTONS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_CLOSE 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_OPEN 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NTOHS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STAT 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VFPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VFWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNPRINTF 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNWPRINTF_S 1 + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. Seems to be unused*/ +#cmakedefine STDC_HEADERS 1 + +/* Define to int if undefined. */ +#cmakedefine socklen_t int + +#endif // LOG4CPLUS_CONFIG_H diff --git a/LFtid1056/cloudfront/code/log4cplus/config.h.in b/LFtid1056/cloudfront/code/log4cplus/config.h.in new file mode 100644 index 0000000..9e62eb6 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config.h.in @@ -0,0 +1,471 @@ +/* include/log4cplus/config.h.in. Generated from configure.ac by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* define if the compiler supports basic C++11 syntax */ +#undef HAVE_CXX11 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the `ftime' function. */ +#undef HAVE_FTIME + +/* Define to 1 if the system has the `constructor' function attribute */ +#undef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* Define to 1 if the system has the `constructor_priority' function attribute + */ +#undef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR_PRIORITY + +/* */ +#undef HAVE_GETADDRINFO + +/* */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the `htonl' function. */ +#undef HAVE_HTONL + +/* Define to 1 if you have the `htons' function. */ +#undef HAVE_HTONS + +/* Define to 1 if you have the `iconv' function. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the `iconv_close' function. */ +#undef HAVE_ICONV_CLOSE + +/* Define to 1 if you have the `iconv_open' function. */ +#undef HAVE_ICONV_OPEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#undef HAVE_LIBADVAPI32 + +/* Define to 1 if you have the `libiconv' function. */ +#undef HAVE_LIBICONV + +/* Define to 1 if you have the `libiconv_close' function. */ +#undef HAVE_LIBICONV_CLOSE + +/* Define to 1 if you have the `libiconv_open' function. */ +#undef HAVE_LIBICONV_OPEN + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#undef HAVE_LIBKERNEL32 + +/* Define to 1 if you have the `oleaut32' library (-loleaut32). */ +#undef HAVE_LIBOLEAUT32 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#undef HAVE_LIBWS2_32 + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the `lockf' function. */ +#undef HAVE_LOCKF + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef HAVE_MBSTOWCS + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `ntohl' function. */ +#undef HAVE_NTOHL + +/* Define to 1 if you have the `ntohs' function. */ +#undef HAVE_NTOHS + +/* Define to 1 if you have the `OutputDebugStringW' function. */ +#undef HAVE_OUTPUTDEBUGSTRINGW + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the `pipe2' function. */ +#undef HAVE_PIPE2 + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* If available, contains the Python version number currently in use. */ +#undef HAVE_PYTHON + +/* Define to 1 if you have the `shutdown' function. */ +#undef HAVE_SHUTDOWN + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Defined if the compiler understands __thread or __declspec(thread) + construct. */ +#undef HAVE_TLS_SUPPORT + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#undef HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* Define to 1 if you have the `vfprintf_s' function. */ +#undef HAVE_VFPRINTF_S + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#undef HAVE_VFWPRINTF_S + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsnwprintf' function. */ +#undef HAVE_VSNWPRINTF + +/* Define to 1 if you have the `vsprintf_s' function. */ +#undef HAVE_VSPRINTF_S + +/* Define to 1 if you have the `vswprintf_s' function. */ +#undef HAVE_VSWPRINTF_S + +/* Define to 1 if you have the `wcstombs' function. */ +#undef HAVE_WCSTOMBS + +/* Define to 1 if you have the `_vsnprintf' function. */ +#undef HAVE__VSNPRINTF + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#undef HAVE__VSNPRINTF_S + +/* Define to 1 if you have the `_vsnwprintf' function. */ +#undef HAVE__VSNWPRINTF + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#undef HAVE__VSNWPRINTF_S + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#undef HAVE___FUNCTION___MACRO + +/* Defined if the compiler supports __func__ symbol. */ +#undef HAVE___FUNC___SYMBOL + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#undef HAVE___PRETTY_FUNCTION___MACRO + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the compiler understands __attribute__((visibility("hidden"))) + or __hidden construct. */ +#undef LOG4CPLUS_DECLSPEC_PRIVATE + +/* */ +#undef LOG4CPLUS_HAVE_ARPA_INET_H + +/* */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL_H + +/* */ +#undef LOG4CPLUS_HAVE_FLOCK + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_FUNCTION_MACRO + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR_PRIORITY + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_SYMBOL + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTID + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_ICONV + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_CLOSE + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_H + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_OPEN + +/* */ +#undef LOG4CPLUS_HAVE_LIMITS_H + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LOCKF + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_MBSTOWCS + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_TCP_H + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* */ +#undef LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING + +/* */ +#undef LOG4CPLUS_HAVE_PIPE + +/* */ +#undef LOG4CPLUS_HAVE_PIPE2 + +/* */ +#undef LOG4CPLUS_HAVE_POLL + +/* */ +#undef LOG4CPLUS_HAVE_POLL_H + +/* */ +#undef LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO + +/* */ +#undef LOG4CPLUS_HAVE_SHUTDOWN + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDLIB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_FILE_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SYSCALL_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_TLS_SUPPORT + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* */ +#undef LOG4CPLUS_HAVE_VFPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VFWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VSNPRINTF + +/* */ +#undef LOG4CPLUS_HAVE_VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE_VSPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VSWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_WCSTOMBS + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF_S + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_THREAD_LOCAL_VAR + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define when iconv() is available. */ +#undef LOG4CPLUS_WITH_ICONV + +/* Defined to enable unit tests. */ +#undef LOG4CPLUS_WITH_UNIT_TESTS + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +#undef LOG4CPLUS_WORKING_C_LOCALE + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Defined to the actual TLS support construct. */ +#undef TLS_SUPPORT_CONSTRUCT + +/* Substitute for socklen_t */ +#undef socklen_t + +#endif // LOG4CPLUS_CONFIG_H diff --git a/LFtid1056/cloudfront/code/log4cplus/config.hxx b/LFtid1056/cloudfront/code/log4cplus/config.hxx new file mode 100644 index 0000000..99e5156 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config.hxx @@ -0,0 +1,217 @@ +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_CONFIG_HXX +#define LOG4CPLUS_CONFIG_HXX + +#if defined (_WIN32) +# include +#elif (defined(__MWERKS__) && defined(__MACOS__)) +# include +#else +# include +#endif + +# if ! defined (LOG4CPLUS_WORKING_LOCALE) \ + && ! defined (LOG4CPLUS_WORKING_C_LOCALE) \ + && ! defined (LOG4CPLUS_WITH_ICONV) +# define LOG4CPLUS_POOR_MANS_CHCONV +#endif + +#ifndef LOG4CPLUS_DECLSPEC_EXPORT +#define LOG4CPLUS_DECLSPEC_EXPORT /* empty */ +#endif + +#ifndef LOG4CPLUS_DECLSPEC_IMPORT +#define LOG4CPLUS_DECLSPEC_IMPORT /* empty */ +#endif + +#ifndef LOG4CPLUS_DECLSPEC_PRIVATE +#define LOG4CPLUS_DECLSPEC_PRIVATE /* empty */ +#endif + +#define LOG4CPLUS_PRIVATE LOG4CPLUS_DECLSPEC_PRIVATE + +#if !defined(_WIN32) +# define LOG4CPLUS_USE_BSD_SOCKETS +# if !defined(LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_USE_PTHREADS +# endif +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_EXPORT +# else +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_IMPORT +# endif // defined (INSIDE_LOG4CPLUS) + +#endif // !_WIN32 + +#if defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \ + && defined (LOG4CPLUS_BUILD_DLL) +# define LOG4CPLUS_INLINE_EXPORT inline +#else +# define LOG4CPLUS_INLINE_EXPORT +#endif + +#if defined (UNICODE) +# if defined (_MSC_VER) && _MSC_VER >= 1400 +# define LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T +# endif +# if defined (_MSC_VER) && _MSC_VER >= 1600 +# define LOG4CPLUS_HAVE_CODECVT_UTF8_FACET +# define LOG4CPLUS_HAVE_CODECVT_UTF16_FACET +# endif +#endif + +// C++11 stuff + +#if ! defined (__has_feature) +//! __has_feature(X) is Clangs way for testing features. +//! Define it to 0 if it does not exist. +# define __has_feature(X) 0 +#endif + +#if __has_feature (cxx_noexcept) \ + || (defined (__GNUC__) \ + && (__GNUC__ > 4 \ + || __GNUC__ == 4 && __GNUC_MINOR__ >= 6)) \ + || (defined (_MSC_VER) && _MSC_VER >= 1900) +# define LOG4CPLUS_NOEXCEPT noexcept +# define LOG4CPLUS_NOEXCEPT_FALSE noexcept(false) +#else +# define LOG4CPLUS_NOEXCEPT /* empty */ +# define LOG4CPLUS_NOEXCEPT_FALSE /* empty */ +#endif + +#if ! defined (UNICODE) && defined (__GNUC__) && __GNUC__ >= 3 +# define LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, format_index, first_arg_index) \ + __attribute__ ((format (archetype, format_index, first_arg_index))) +#else +# define LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, fmt_index, first_arg_index) \ + /* empty */ +#endif + +#if defined (__GNUC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) \ + && ! defined (__INTEL_COMPILER) \ + && ! defined (__CUDACC__) +# define LOG4CPLUS_CALLER_FILE() __builtin_FILE () +# define LOG4CPLUS_CALLER_LINE() __builtin_LINE () +# define LOG4CPLUS_CALLER_FUNCTION() __builtin_FUNCTION () +#else +# define LOG4CPLUS_CALLER_FILE() (nullptr) +# define LOG4CPLUS_CALLER_LINE() (-1) +# define LOG4CPLUS_CALLER_FUNCTION() (nullptr) +#endif + +#if defined (__GNUC__) && __GNUC__ >= 3 +# define LOG4CPLUS_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +# define LOG4CPLUS_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# define LOG4CPLUS_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) +# define LOG4CPLUS_BUILTIN_EXPECT(exp, c) __builtin_expect ((exp), (c)) +#else +# if ! defined (LOG4CPLUS_ATTRIBUTE_NORETURN) +# define LOG4CPLUS_ATTRIBUTE_NORETURN /* empty */ +# endif +# define LOG4CPLUS_ATTRIBUTE_PURE /* empty */ +# define LOG4CPLUS_ATTRIBUTE_DEPRECATED /* empty */ +# define LOG4CPLUS_BUILTIN_EXPECT(exp, c) (exp) +#endif + +#define LOG4CPLUS_LIKELY(cond) LOG4CPLUS_BUILTIN_EXPECT(!! (cond), 1) +#define LOG4CPLUS_UNLIKELY(cond) LOG4CPLUS_BUILTIN_EXPECT(!! (cond), 0) + +#if defined (_MSC_VER) \ + || (defined (__BORLANDC__) && __BORLANDC__ >= 0x0650) \ + || (defined (__COMO__) && __COMO_VERSION__ >= 400) /* ??? */ \ + || (defined (__DMC__) && __DMC__ >= 0x700) /* ??? */ \ + || (defined (__clang__) && __clang_major__ >= 3) \ + || (defined (__GNUC__) && (__GNUC__ >= 4 \ + || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))) +# define LOG4CPLUS_HAVE_PRAGMA_ONCE +# pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR_PRIORITY) +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) \ + __attribute__ ((__constructor__ ((prio)))) +#elif defined (LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR) +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) \ + __attribute__ ((__constructor__)) +#else +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) /* empty */ +#endif + +#if defined (LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY) +# define LOG4CPLUS_INIT_PRIORITY(prio) \ + __attribute__ ((__init_priority__ ((prio)))) +#else +# define LOG4CPLUS_INIT_PRIORITY(prio) /* empty */ +#endif + +#define LOG4CPLUS_INIT_PRIORITY_BASE (65535 / 2) + +#include + +#if defined (LOG4CPLUS_SINGLE_THREADED) +#define LOG4CPLUS_THREADED(x) +#else +#define LOG4CPLUS_THREADED(x) x +#endif + +#if defined(__cplusplus) +#include + +namespace log4cplus +{ + +//! Per thread cleanup function. Users should call this function before +//! a thread ends its execution. It frees resources allocated in thread local +//! storage. It is important only for multi-threaded static library builds +//! of log4cplus and user threads. In all other cases the clean up is provided +//! automatically by other means. +LOG4CPLUS_EXPORT void threadCleanup (); + +//! Initializes log4cplus. +//! +//! \note using `log4cplus::Initializer` is preferred +LOG4CPLUS_EXPORT void initialize (); + +//! Deinitializes log4cplus. +//! +//! \note using `log4cplus::Initializer` is preferred +LOG4CPLUS_EXPORT void deinitialize (); + +//! Set thread pool size. +LOG4CPLUS_EXPORT void setThreadPoolSize (std::size_t pool_size); + +//! Set behaviour on full thread pool queue. Default is to block. +LOG4CPLUS_EXPORT void setThreadPoolBlockOnFull (bool block); + +//! Set thread pool queue size limit. +LOG4CPLUS_EXPORT void setThreadPoolQueueSizeLimit (std::size_t queue_size_limit); + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_CONFIG_HXX diff --git a/LFtid1056/cloudfront/code/log4cplus/config/defines.hxx.in b/LFtid1056/cloudfront/code/log4cplus/config/defines.hxx.in new file mode 100644 index 0000000..3c80749 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config/defines.hxx.in @@ -0,0 +1,247 @@ +#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX +#define LOG4CPLUS_CONFIG_DEFINES_HXX + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_ARPA_INET_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_TCP_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SYSCALL_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_FILE_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL_H + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDLIB_H + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_H + +/* */ +#undef LOG4CPLUS_HAVE_LIMITS_H + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL + +/* */ +#undef LOG4CPLUS_HAVE_LOCKF + +/* */ +#undef LOG4CPLUS_HAVE_FLOCK + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* Define to 1 if you have the `shutdown' function. */ +#undef LOG4CPLUS_HAVE_SHUTDOWN + +/* */ +#undef LOG4CPLUS_HAVE_PIPE + +/* */ +#undef LOG4CPLUS_HAVE_PIPE2 + +/* */ +#undef LOG4CPLUS_HAVE_POLL + +/* */ +#undef LOG4CPLUS_HAVE_POLL_H + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +#undef LOG4CPLUS_WORKING_C_LOCALE + +/* Define to int if undefined. */ +#undef socklen_t + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllexport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the compiler understands + __attribute__((visibility("hidden"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_PRIVATE + +/* */ +#undef LOG4CPLUS_HAVE_TLS_SUPPORT + +/* */ +#undef LOG4CPLUS_THREAD_LOCAL_VAR + +/* Defined if the host OS provides ENAMETOOLONG errno value. */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* */ +#undef LOG4CPLUS_HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsnwprintf' function. */ +#undef LOG4CPLUS_HAVE_VSNWPRINTF + +/* Define to 1 if you have the `_vsnwprintf' function. */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF + +/* Define to 1 if you have the `vfprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VFPRINTF_S + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VFWPRINTF_S + +/* Define to 1 if you have the `vsprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VSPRINTF_S + +/* Define to 1 if you have the `vswprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VSWPRINTF_S + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#undef LOG4CPLUS_HAVE__VSNPRINTF_S + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF_S + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#undef LOG4CPLUS_HAVE_FUNCTION_MACRO + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#undef LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO + +/* Defined if the compiler supports __func__ symbol. */ +#undef LOG4CPLUS_HAVE_FUNC_SYMBOL + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef LOG4CPLUS_HAVE_MBSTOWCS + +/* Define to 1 if you have the `wcstombs' function. */ +#undef LOG4CPLUS_HAVE_WCSTOMBS + +/* Define to 1 if you have Linux style syscall(SYS_gettid). */ +#undef LOG4CPLUS_HAVE_GETTID + +/* Define when iconv() is available. */ +#undef LOG4CPLUS_WITH_ICONV + +/* Define to 1 if you have the `iconv' function. */ +#undef LOG4CPLUS_HAVE_ICONV + +/* Define to 1 if you have the `iconv_close' function. */ +#undef LOG4CPLUS_HAVE_ICONV_CLOSE + +/* Define to 1 if you have the `iconv_open' function. */ +#undef LOG4CPLUS_HAVE_ICONV_OPEN + +/* Define to 1 if you have the `OutputDebugString' function. */ +#undef LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING + +/* Define to 1 if the system has the `constructor' function attribute + with priority */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR_PRIORITY + +/* Define to 1 if the system has the `constructor' function attribute */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#undef LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* Defined to enable unit tests. */ +#undef LOG4CPLUS_WITH_UNIT_TESTS + +#endif // LOG4CPLUS_CONFIG_DEFINES_HXX diff --git a/LFtid1056/cloudfront/code/log4cplus/config/macosx.h b/LFtid1056/cloudfront/code/log4cplus/config/macosx.h new file mode 100644 index 0000000..3f793c5 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config/macosx.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: config-macosx.h +// Created: 7/2003 +// Author: Christopher R. Bailey +// +// +// Copyright 2003-2017 Christopher R. Bailey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_MACOSX_HEADER_ +#define LOG4CPLUS_CONFIG_MACOSX_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if (defined(__APPLE__) || (defined(__MWERKS__) && defined(__MACOS__))) + +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 +#define socklen_t int + +#endif // MACOSX +#endif // LOG4CPLUS_CONFIG_MACOSX_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/config/win32.h b/LFtid1056/cloudfront/code/log4cplus/config/win32.h new file mode 100644 index 0000000..5d3a0b4 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config/win32.h @@ -0,0 +1,194 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: config-win32.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_WIN32_HEADER_ +#define LOG4CPLUS_CONFIG_WIN32_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (__MINGW32__) || defined (__MINGW64__) +# include <_mingw.h> +#endif + +#ifdef _WIN32 + +#if (defined (_MSC_VER) && _MSC_VER > 1400) \ + || (defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 3) +# define LOG4CPLUS_HAVE_INTRIN_H +#endif + +// Time related functions and headers. +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_SYS_TIMEB_H +#define LOG4CPLUS_HAVE_FTIME +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define LOG4CPLUS_HAVE_GMTIME_S +#endif + +// Use Winsock on Windows. +#define LOG4CPLUS_USE_WINSOCK + +// Enable Win32DebugAppender +#define LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING + +// Enable Win32ConsoleAppender. +#define LOG4CPLUS_HAVE_WIN32_CONSOLE + +#define LOG4CPLUS_HAVE_SYS_TYPES_H +#define LOG4CPLUS_HAVE_SYS_LOCKING_H +#define LOG4CPLUS_HAVE_FCNTL_H +#define LOG4CPLUS_HAVE_IO_H +#define LOG4CPLUS_HAVE_STDIO_H +#define LOG4CPLUS_HAVE_WCHAR_H +#define LOG4CPLUS_HAVE_STDARG_H +#define LOG4CPLUS_HAVE_STDLIB_H +#define LOG4CPLUS_HAVE_ERRNO_H +#define LOG4CPLUS_HAVE_SYS_STAT_H +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_STDLIB_H +#define LOG4CPLUS_HAVE_DIRECT_H + +// MSVC has both and so does MinGW. +#define LOG4CPLUS_HAVE_VSNPRINTF +#define LOG4CPLUS_HAVE__VSNPRINTF +#define LOG4CPLUS_HAVE__VSNWPRINTF + +// Limit the use of foo_s() functions to builds using Visual Studio +// 2005 and its run time library. In MinGW land, limit the foo_s() +// functions to MinGw-w64 toolchain and __MSVCRT_VERSION__ >= 0x0900. +#if (defined (_MSC_VER) && _MSC_VER >= 1400) \ + || (defined (__MSVCRT_VERSION__) && __MSVCRT_VERSION__ >= 0x0900 \ + && defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 2) +// MS secure versions of vprintf(). +# define LOG4CPLUS_HAVE_VSPRINTF_S +# define LOG4CPLUS_HAVE_VSWPRINTF_S + +// MS secure versions of vfprintf(). +# define LOG4CPLUS_HAVE_VFPRINTF_S +# define LOG4CPLUS_HAVE_VFWPRINTF_S + +// MS secure versions of vsnprintf(). +# define LOG4CPLUS_HAVE_VSNPRINTF_S +# define LOG4CPLUS_HAVE__VSNPRINTF_S +# define LOG4CPLUS_HAVE__VSNWPRINTF_S + +// MS secure version of _tsopen(). +# define LOG4CPLUS_HAVE__TSOPEN_S +#endif + +#if defined (_MSC_VER) && _MSC_VER >= 1400 +// MS printf-like functions supporting positional parameters. +# define LOG4CPLUS_HAVE__VSPRINTF_P +# define LOG4CPLUS_HAVE__VSWPRINTF_P +#endif + +#if defined (_MSC_VER) +# define LOG4CPLUS_HAVE_LOCALTIME_S +#endif + +#define LOG4CPLUS_HAVE__TSOPEN + +#define LOG4CPLUS_DLLMAIN_HINSTANCE HINSTANCE +#define LOG4CPLUS_HAVE_NT_EVENT_LOG + +// log4cplus_EXPORTS is used by the CMake build system. DLL_EXPORT is +// used by the autotools build system. +#if (defined (log4cplus_EXPORTS) || defined (log4cplusU_EXPORTS) \ + || (defined (DLL_EXPORT) && defined (INSIDE_LOG4CPLUS))) \ + && ! defined (LOG4CPLUS_STATIC) +# undef LOG4CPLUS_BUILD_DLL +# define LOG4CPLUS_BUILD_DLL +#endif + +#if ! defined (LOG4CPLUS_BUILD_DLL) +# undef LOG4CPLUS_STATIC +# define LOG4CPLUS_STATIC +#endif + +#if defined (LOG4CPLUS_STATIC) && defined (LOG4CPLUS_BUILD_DLL) +# error LOG4CPLUS_STATIC and LOG4CPLUS_BUILD_DLL cannot be defined both. +#endif + +#if defined (LOG4CPLUS_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_EXPORT +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED +# define LOG4CPLUS_USE_WIN32_THREADS +#endif + +#if defined(_MSC_VER) + // Warning about: identifier was truncated to '255' characters in the debug information +# pragma warning( disable : 4786 ) + // Warning about: needs to have dll-interface to be used by clients of class +# pragma warning( disable : 4251 ) + +# define LOG4CPLUS_INLINES_ARE_EXPORTED + +# if _MSC_VER >= 1400 +# define LOG4CPLUS_WORKING_LOCALE +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_FUNCSIG_MACRO +# define LOG4CPLUS_ATTRIBUTE_NORETURN __declspec(noreturn) +# endif +#endif + +#if defined (__GNUC__) +# undef LOG4CPLUS_INLINES_ARE_EXPORTED +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_FUNC_SYMBOL +# endif +// This has worked for some versions of MinGW with GCC 4.7+ but it +// appears to be broken again in 4.8.x. Thus, we disable this for GCC +// completely forever. +// +//# define LOG4CPLUS_INLINES_ARE_EXPORTED +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# if defined (__MINGW32__) +# define LOG4CPLUS_WORKING_C_LOCALE +# endif +#endif + +#if defined (__BORLANDC__) && __BORLANDC__ >= 0x0650 +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +#endif // __BORLANDC__ + +#if ! defined (LOG4CPLUS_DISABLE_DLL_RUNTIME_WARNING) +# if defined (LOG4CPLUS_STATIC) && defined (_MSC_VER) && ! defined (_DLL) +# pragma message("You are not using DLL C run time library. " \ + "You must call log4cplus::initialize() once before " \ + "you use any other log4cplus API.") +# endif +#endif + +#endif // _WIN32 +#endif // LOG4CPLUS_CONFIG_WIN32_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/config/windowsh-inc-full.h b/LFtid1056/cloudfront/code/log4cplus/config/windowsh-inc-full.h new file mode 100644 index 0000000..bff5925 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config/windowsh-inc-full.h @@ -0,0 +1,42 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: windowsh-inc.h +// Created: 9/2018 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2018, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// NOTE: This file is a fragment intentionally left without include guards. + +#if defined (_WIN32) +#include +#include +#include +#if defined (LOG4CPLUS_HAVE_INTRIN_H) +#include +#endif +#endif + +// NOTE: This file is a fragment intentionally left without include guards. diff --git a/LFtid1056/cloudfront/code/log4cplus/config/windowsh-inc.h b/LFtid1056/cloudfront/code/log4cplus/config/windowsh-inc.h new file mode 100644 index 0000000..0ed1c50 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/config/windowsh-inc.h @@ -0,0 +1,159 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: windowsh-inc.h +// Created: 4/2010 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2010-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// NOTE: This file is a fragment intentionally left without include guards. + +#if defined (_WIN32) +#undef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN + +#undef NOGDICAPMASKS +#define NOGDICAPMASKS + +#undef NOVIRTUALKEYCODES +#define NOVIRTUALKEYCODES + +#undef NOWINMESSAGES +#define NOWINMESSAGES + +#undef NOWINSTYLES +#define NOWINSTYLES + +#undef NOSYSMETRICS +#define NOSYSMETRICS + +#undef NOMENUS +#define NOMENUS + +#undef NOICONS +#define NOICONS + +#undef NOKEYSTATES +#define NOKEYSTATES + +#undef NOSYSCOMMANDS +#define NOSYSCOMMANDS + +#undef NORASTEROPS +#define NORASTEROPS + +#undef NOSHOWWINDOW +#define NOSHOWWINDOW + +#undef NOATOM +#define NOATOM + +#undef NOCLIPBOARD +#define NOCLIPBOARD + +#undef NOCOLOR +#define NOCOLOR + +#undef NOCTLMGR +#define NOCTLMGR + +#undef NODRAWTEXT +#define NODRAWTEXT + +#undef NOGDI +#define NOGDI + +#undef NOKERNEL +#define NOKERNEL + +#undef NOUSER +#define NOUSER + +#undef NONLS +#define NONLS + +#undef NOMB +#define NOMB + +#undef NOMEMMGR +#define NOMEMMGR + +#undef NOMETAFILE +#define NOMETAFILE + +#undef NOMINMAX +#define NOMINMAX + +#undef NOMSG +#define NOMSG + +#undef NOOPENFILE +#define NOOPENFILE + +#undef NOSCROLL +#define NOSCROLL + +#undef NOSERVICE +#define NOSERVICE + +#undef NOSOUND +#define NOSOUND + +#undef NOTEXTMETRIC +#define NOTEXTMETRIC + +#undef NOWH +#define NOWH + +#undef NOWINOFFSETS +#define NOWINOFFSETS + +#undef NOCOMM +#define NOCOMM + +#undef NOKANJI +#define NOKANJI + +#undef NOHELP +#define NOHELP + +#undef NOPROFILER +#define NOPROFILER + +#undef NODEFERWINDOWPOS +#define NODEFERWINDOWPOS + +#undef NOMCX +#define NOMCX + +#include +#include +#include +#if defined (LOG4CPLUS_HAVE_INTRIN_H) +#include +#endif +#endif + +// NOTE: This file is a fragment intentionally left without include guards. diff --git a/LFtid1056/cloudfront/code/log4cplus/configurator.h b/LFtid1056/cloudfront/code/log4cplus/configurator.h new file mode 100644 index 0000000..0120325 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/configurator.h @@ -0,0 +1,389 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: configurator.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIGURATOR_HEADER_ +#define LOG4CPLUS_CONFIGURATOR_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + class Hierarchy; + + + /** + * Provides configuration from an external file. See configure() for + * the expected format. + * + * All option values admit variable substitution. For + * example, if userhome environment property is set to + * /home/xyz and the File option is set to the string + * ${userhome}/test.log, then File option will be + * interpreted as the string /home/xyz/test.log. + * + * The syntax of variable substitution is similar to that of UNIX + * shells. The string between an opening "${" and + * closing "}" is interpreted as a key. Its value is + * searched in the environment properties. The corresponding value replaces + * the ${variableName} sequence. + * + * Configuration files also recognize include + * file.properties directive that allow composing + * configuration from multiple files. There is no cyclic includes + * detection mechanism to stop unbound recursion. + */ + class LOG4CPLUS_EXPORT PropertyConfigurator + { + public: + enum PCFlags + { + fRecursiveExpansion = (1 << 0) + , fShadowEnvironment = (1 << 1) + , fAllowEmptyVars = (1 << 2) + + // These encoding related options occupy 2 bits of the flags + // and are mutually exclusive. These flags are synchronized with + // PFlags in Properties. + + , fEncodingShift = 3 + , fEncodingMask = 0x3 + , fUnspecEncoding = (0 << fEncodingShift) +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) + , fUTF8 = (1 << fEncodingShift) +#endif +#if (defined (LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ + && defined (UNICODE) + , fUTF16 = (2 << fEncodingShift) +#endif +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) + , fUTF32 = (3 << fEncodingShift) +#endif + , fThrow = (1 << 5) + }; + + // ctor and dtor + PropertyConfigurator(const log4cplus::tstring& propertyFile, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(const log4cplus::helpers::Properties& props, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(log4cplus::tistream& propertyStream, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + virtual ~PropertyConfigurator(); + + /** + * This method eliminates the need to create a temporary + * PropertyConfigurator to configure log4cplus. + * It is equivalent to the following:
+ * + * PropertyConfigurator config("filename"); + * config.configure(); + * + */ + static void doConfigure(const log4cplus::tstring& configFilename, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + + /** + * Read configuration from a file. The existing configuration is + * not cleared nor reset. If you require a different behavior, + * then call {@link Hierarchy::resetConfiguration + * resetConfiguration} method before calling + * doConfigure. + * + * The configuration file consists of statements in the format + * key=value. The syntax of different configuration + * elements are discussed below. + * + *

Appender configuration

+ * + * Appender configuration syntax is: + *
+         * # For appender named appenderName, set its class.
+         * # Note: The appender name can contain dots.
+         * log4cplus.appender.appenderName=fully.qualified.name.of.appender.class
+         *
+         * # Set appender specific options.
+         * log4cplus.appender.appenderName.option1=value1
+         * ...
+         * log4cplus.appender.appenderName.optionN=valueN
+         * 
+ * + * For each named appender you can configure its {@link Layout}. The + * syntax for configuring an appender's layout is: + *
+         * log4cplus.appender.appenderName.layout=fully.qualified.name.of.layout.class
+         * log4cplus.appender.appenderName.layout.option1=value1
+         * ....
+         * log4cplus.appender.appenderName.layout.optionN=valueN
+         * 
+ * + *

Configuring loggers

+ * + * The syntax for configuring the root logger is: + *
+         * log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
+         * 
+ * + * This syntax means that an optional LogLevel value can + * be supplied followed by appender names separated by commas. + * + * The LogLevel value can consist of the string values FATAL, + * ERROR, WARN, INFO, DEBUG or a custom LogLevel value. + * + * If a LogLevel value is specified, then the root LogLevel is set + * to the corresponding LogLevel. If no LogLevel value is specified, + * then the root LogLevel remains untouched. + * + * The root logger can be assigned multiple appenders. + * + * Each appenderName (separated by commas) will be added to + * the root logger. The named appender is defined using the + * appender syntax defined above. + * + * For non-root loggers the syntax is almost the same: + *
+         * log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
+         * 
+ * + * The meaning of the optional LogLevel value is discussed above + * in relation to the root logger. In addition however, the value + * INHERITED can be specified meaning that the named logger should + * inherit its LogLevel from the logger hierarchy. + * + * By default loggers inherit their LogLevel from the + * hierarchy. However, if you set the LogLevel of a logger and + * later decide that that logger should inherit its LogLevel, then + * you should specify INHERITED as the value for the LogLevel value. + * + * Similar to the root logger syntax, each appenderName + * (separated by commas) will be attached to the named logger. + * + * See the appender + * additivity rule in the user manual for the meaning of the + * additivity flag. + * + * The user can override any of the {@link + * Hierarchy#disable} family of methods by setting the a key + * "log4cplus.disableOverride" to true or any value other + * than false. As in
log4cplus.disableOverride=true 
+ * + *

Global configuration

+ * + *
    + *
  • Property
    log4cplus.threadPoolSize
    can be used to adjust + * size of log4cplus' internal thread pool.
  • + *
  • Property
    log4cplus.threadPoolBlockOnFull
    can be + * used to change behaviour of the thread pool when its queue is full. + * The default value is
    true
    , to block the thread until + * there is a space in the queue. Setting this property to + *
    false
    makes the thread pool not to block when it is full. + * The items that could not be inserted are dropped instead.
  • + *
  • Property
    log4cplus.threadPoolQueueSizeLimit
    can be used to + * set thread pool queue size limit.
  • + *
+ * + *

Example

+ * + * An example configuration is given below. + * + *
+         *
+         * # Set options for appender named "A1".
+         * # Appender "A1" will be a SyslogAppender
+         * log4cplus.appender.A1=log4cplus::SyslogAppender
+         *
+         * # The syslog daemon resides on www.abc.net
+         * log4cplus.appender.A1.SyslogHost=www.abc.net
+         *
+         * # A1's layout is a PatternLayout, using the conversion pattern
+         * # %r %-5p %c{2} %M.%L %x - %m\n. Thus, the log output will
+         * # include # the relative time since the start of the application in
+         * # milliseconds, followed by the LogLevel of the log request,
+         * # followed by the two rightmost components of the logger name,
+         * # followed by the callers method name, followed by the line number,
+         * # the nested disgnostic context and finally the message itself.
+         * # Refer to the documentation of {@link PatternLayout} for further information
+         * # on the syntax of the ConversionPattern key.
+         * log4cplus.appender.A1.layout=log4cplus::PatternLayout
+         * log4cplus.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
+         *
+         * # Set options for appender named "A2"
+         * # A2 should be a RollingFileAppender, with maximum file size of 10 MB
+         * # using at most one backup file. A2's layout is TTCC, using the
+         * # ISO8061 date format with context printing enabled.
+         * log4cplus.appender.A2=log4cplus::RollingFileAppender
+         * log4cplus.appender.A2.MaxFileSize=10MB
+         * log4cplus.appender.A2.MaxBackupIndex=1
+         * log4cplus.appender.A2.layout=log4cplus::TTCCLayout
+         * log4cplus.appender.A2.layout.ContextPrinting=true
+         * log4cplus.appender.A2.layout.DateFormat=ISO8601
+         *
+         * # Root logger set to DEBUG using the A2 appender defined above.
+         * log4cplus.rootLogger=DEBUG, A2
+         *
+         * # Logger definitions:
+         * # The SECURITY logger inherits is LogLevel from root. However, it's output
+         * # will go to A1 appender defined above. It's additivity is non-cumulative.
+         * log4cplus.logger.SECURITY=INHERIT, A1
+         * log4cplus.additivity.SECURITY=false
+         *
+         * # Only warnings or above will be logged for the logger "SECURITY.access".
+         * # Output will go to A1.
+         * log4cplus.logger.SECURITY.access=WARN
+         *
+         *
+         * # The logger "class.of.the.day" inherits its LogLevel from the
+         * # logger hierarchy.  Output will go to the appender's of the root
+         * # logger, A2 in this case.
+         * log4cplus.logger.class.of.the.day=INHERIT
+         * 
+ * + * Refer to the setOption method in each Appender and + * Layout for class specific options. + * + * Use the # character at the beginning of a line + * for comments. + */ + virtual void configure(); + + /** + * \return The return value is reference to Properties + * container of properties with the "log4cplus." + * prefix removed and references to other properties and/or + * environment variables expanded. + */ + log4cplus::helpers::Properties const & getProperties () const; + + /** + * \return The return value is a reference to log4cplus::tstring + * containing filename of properties source file. It will be + * string "UNAVAILABLE" if the PropertyConfigurator instance has been + * constructed using one of the other constructors that do not take + * filename as parameter. + */ + log4cplus::tstring const & getPropertyFilename () const; + + protected: + // Methods + void init(); // called by the ctor + void reconfigure(); + void replaceEnvironVariables(); + void configureLoggers(); + void configureLogger(log4cplus::Logger logger, const log4cplus::tstring& config); + void configureAppenders(); + void configureAdditivity(); + + virtual Logger getLogger(const log4cplus::tstring& name); + virtual void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + // Types + typedef std::map AppenderMap; + + // Data + Hierarchy& h; + log4cplus::tstring propertyFilename; + log4cplus::helpers::Properties properties; + AppenderMap appenders; + unsigned flags; + + private: + // Disable copy + PropertyConfigurator(const PropertyConfigurator&); + PropertyConfigurator& operator=(PropertyConfigurator&); + }; + + + + /** + * Use this class to quickly configure the package. For file based + * configuration see PropertyConfigurator. BasicConfigurator + * automatically attaches ConsoleAppender to + * rootLogger, with output going to standard output, + * using DEBUG LogLevel value. The additional parameter + * logToStdErr may redirect the output to standard error. + */ + class LOG4CPLUS_EXPORT BasicConfigurator : public PropertyConfigurator { + public: + // ctor and dtor + BasicConfigurator(Hierarchy& h = Logger::getDefaultHierarchy(), + bool logToStdErr = false); + virtual ~BasicConfigurator(); + + /** + * This method eliminates the need to create a temporary + * BasicConfigurator object to configure log4cplus. + * It is equivalent to the following:
+ *
+         * BasicConfigurator config;
+         * config.configure();
+         * 
+ */ + static void doConfigure(Hierarchy& h = Logger::getDefaultHierarchy(), + bool logToStdErr = false); + + //! Property name for disable override. + static log4cplus::tstring const DISABLE_OVERRIDE_KEY; + + private: + // Disable copy + BasicConfigurator(const BasicConfigurator&); + BasicConfigurator& operator=(BasicConfigurator&); + }; + + +#if !defined(LOG4CPLUS_SINGLE_THREADED) + // Forward Declarations + class ConfigurationWatchDogThread; + + + class LOG4CPLUS_EXPORT ConfigureAndWatchThread { + public: + // ctor and dtor + ConfigureAndWatchThread(const log4cplus::tstring& propertyFile, + unsigned int millis = 60 * 1000); + virtual ~ConfigureAndWatchThread(); + + private: + // Disallow copying of instances of this class + ConfigureAndWatchThread(const ConfigureAndWatchThread&); + ConfigureAndWatchThread& operator=(const ConfigureAndWatchThread&); + + // Data + ConfigurationWatchDogThread * watchDogThread; + }; +#endif + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CONFIGURATOR_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/consoleappender.h b/LFtid1056/cloudfront/code/log4cplus/consoleappender.h new file mode 100644 index 0000000..3da24c8 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/consoleappender.h @@ -0,0 +1,105 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: consoleappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONSOLE_APPENDER_HEADER_ +#define LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +namespace log4cplus { + /** + * ConsoleAppender appends log events to std::cout or + * std::cerr using a layout specified by the + * user. The default target is std::cout. + * + *

Properties

+ *
+ *
logToStdErr
+ *
When it is set true, the output stream will be + * std::cerr instead of std::cout.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
Locale
+ *
This property specifies a locale name that will be imbued + * into output stream. Locale can be specified either by system + * specific locale name, e.g., en_US.UTF-8, or by one of + * four recognized keywords: GLOBAL, DEFAULT + * (which is an alias for GLOBAL), USER and + * CLASSIC. When specified locale is not available, + * GLOBAL is used instead. It is possible to register + * additional locale keywords by registering an instance of + * spi::LocaleFactory in + * spi::LocaleFactoryRegistry. + * \sa spi::getLocaleFactoryRegistry(). + * + * Note: if Locale is set, ImmediateFlush will + * be set to true automatically. + *
+ * + *
+ * \sa Appender + */ + class LOG4CPLUS_EXPORT ConsoleAppender : public Appender { + public: + // Ctors + ConsoleAppender(bool logToStdErr = false, bool immediateFlush = false); + ConsoleAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~ConsoleAppender(); + + // Methods + virtual void close(); + + //! This mutex is used by ConsoleAppender and helpers::LogLog + //! classes to synchronize output to console. + static log4cplus::thread::Mutex const & getOutputMutex(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + bool logToStdErr; + /** + * Immediate flush means that the underlying output stream + * will be flushed at the end of each append operation. + */ + bool immediateFlush; + + std::unique_ptr locale; + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + diff --git a/LFtid1056/cloudfront/code/log4cplus/exception.h b/LFtid1056/cloudfront/code/log4cplus/exception.h new file mode 100644 index 0000000..7531edb --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/exception.h @@ -0,0 +1,56 @@ +// Copyright (C) 2023, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_EXCEPTION_HXX +#define LOG4CPLUS_EXCEPTION_HXX + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus +{ + +/** + * \brief Exception class thrown by LogLog. + * \sa helpers::LogLog + * + */ +class LOG4CPLUS_EXPORT exception : public std::runtime_error +{ +public: + exception (tstring const &); + exception (exception const &); + exception & operator=(exception const &); + virtual ~exception (); +}; + +} // namespace log4cplus + +#endif // LOG4CPLUS_EXCEPTION_HXX \ No newline at end of file diff --git a/LFtid1056/cloudfront/code/log4cplus/fileappender.h b/LFtid1056/cloudfront/code/log4cplus/fileappender.h new file mode 100644 index 0000000..36f6d35 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/fileappender.h @@ -0,0 +1,428 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: fileappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_FILE_APPENDER_HEADER_ +#define LOG4CPLUS_FILE_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + + /** + * Base class for Appenders writing log events to a file. + * It is constructed with uninitialized file object, so all + * classes derived from FileAppenderBase _must_ call init() method. + * + *

Properties

+ *
+ *
File
+ *
This property specifies output file name.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
Append
+ *
When it is set true, output file will be appended to + * instead of being truncated at opening.
+ * + *
ReopenDelay
+ *
This property sets a delay after which the appender will try + * to reopen log file again, after last logging failure. + *
+ * + *
BufferSize
+ *
Non-zero value of this property sets up buffering of output + * stream using a buffer of given size. + *
+ * + *
UseLockFile
+ *
Set this property to true if you want your output + * to go into a log file shared by multiple processes. When this + * property is set to true then log4cplus uses OS specific + * facilities (e.g., lockf()) to provide + * inter-process file locking. + * \sa Appender + *
+ * + *
LockFile
+ *
This property specifies lock file, file used for + * inter-process synchronization of log file access. When this + * property is not specified, the value is derived from + * File property by addition of ".lock" suffix. The + * property is only used when UseLockFile is set to true. + * \sa Appender + *
+ * + *
Locale
+ *
This property specifies a locale name that will be imbued + * into output stream. Locale can be specified either by system + * specific locale name, e.g., en_US.UTF-8, or by one of + * four recognized keywords: GLOBAL, DEFAULT + * (which is an alias for GLOBAL), USER and + * CLASSIC. When specified locale is not available, + * GLOBAL is used instead. It is possible to register + * additional locale keywords by registering an instance of + * spi::LocaleFactory in + * spi::LocaleFactoryRegistry. + * \sa spi::getLocaleFactoryRegistry() + *
+ * + *
CreateDirs
+ *
Set this property to true if you want to create + * missing directories in path leading to log file and lock file. + *
+ * + *
TextMode
+ *
Set this property to Binary if the underlying stream should + * not translate EOLs to OS specific character sequence. The default value + * is Text and the underlying stream will be opened in text + * mode.
+ *
+ */ + class LOG4CPLUS_EXPORT FileAppenderBase : public Appender { + public: + // Methods + virtual void close(); + + //! Redefine default locale for output stream. It may be a good idea to + //! provide UTF-8 locale in case UNICODE macro is defined. + virtual std::locale imbue(std::locale const& loc); + + //! \returns Locale imbued in fstream. + virtual std::locale getloc () const; + + protected: + // Ctors + FileAppenderBase(const log4cplus::tstring& filename, + std::ios_base::openmode mode = std::ios_base::trunc, + bool immediateFlush = true, + bool createDirs = false); + FileAppenderBase(const log4cplus::helpers::Properties& properties, + std::ios_base::openmode mode = std::ios_base::trunc); + + void init(); + + virtual void append(const spi::InternalLoggingEvent& event); + + virtual void open(std::ios_base::openmode mode); + bool reopen(); + + // Data + /** + * Immediate flush means that the underlying writer or output stream + * will be flushed at the end of each append operation. Immediate + * flush is slower but ensures that each append request is actually + * written. If immediateFlush is set to + * false, then there is a good chance that the last few + * logs events are not actually written to persistent media if and + * when the application crashes. + * + * The immediateFlush variable is set to + * true by default. + */ + bool immediateFlush; + + /** + * When this variable is true, FileAppender will try to create + * missing directories in path leading to log file. + * + * The `createDirs` variable is set to `false` by default. + */ + bool createDirs; + + /** + * When any append operation fails, reopenDelay says + * for how many seconds the next attempt to re-open the log file and + * resume logging will be delayed. If reopenDelay is zero, + * each failed append operation will cause log file to be re-opened. + * By default, reopenDelay is 1 second. + */ + int reopenDelay; + + unsigned long bufferSize; + std::unique_ptr buffer; + + log4cplus::tofstream out; + log4cplus::tstring filename; + log4cplus::tstring localeName; + log4cplus::tstring lockFileName; + std::ios_base::openmode fileOpenMode; + + log4cplus::helpers::Time reopen_time; + + private: + // Disallow copying of instances of this class + FileAppenderBase(const FileAppenderBase&); + FileAppenderBase& operator=(const FileAppenderBase&); + }; + + + /** + * Appends log events to a file. + * + *

Properties

+ *

It has no properties additional to {@link FileAppenderBase}. + */ + class LOG4CPLUS_EXPORT FileAppender : public FileAppenderBase { + public: + // Ctors + FileAppender(const log4cplus::tstring& filename, + std::ios_base::openmode mode = std::ios_base::trunc, + bool immediateFlush = true, + bool createDirs = false); + FileAppender(const log4cplus::helpers::Properties& properties, + std::ios_base::openmode mode = std::ios_base::trunc); + + // Dtor + virtual ~FileAppender(); + + protected: + void init(); + }; + + typedef helpers::SharedObjectPtr SharedFileAppenderPtr; + + + + /** + * RollingFileAppender extends FileAppender to backup the log + * files when they reach a certain size. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
MaxFileSize
+ *
This property specifies maximal size of output file. The + * value is in bytes. It is possible to use MB and + * KB suffixes to specify the value in megabytes or + * kilobytes instead.
+ * + *
MaxBackupIndex
+ *
This property limits the number of backup output + * files; e.g. how many log.1, log.2 etc. files + * will be kept.
+ *
+ */ + class LOG4CPLUS_EXPORT RollingFileAppender : public FileAppender { + public: + // Ctors + RollingFileAppender(const log4cplus::tstring& filename, + long maxFileSize = 10*1024*1024, // 10 MB + int maxBackupIndex = 1, + bool immediateFlush = true, + bool createDirs = false); + RollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~RollingFileAppender(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(bool alreadyLocked = false); + + // Data + long maxFileSize; + int maxBackupIndex; + + private: + LOG4CPLUS_PRIVATE void init(long maxFileSize, int maxBackupIndex); + }; + + + typedef helpers::SharedObjectPtr + SharedRollingFileAppenderPtr; + + + enum DailyRollingFileSchedule { MONTHLY, WEEKLY, DAILY, + TWICE_DAILY, HOURLY, MINUTELY}; + + /** + * DailyRollingFileAppender extends {@link FileAppender} so that the + * underlying file is rolled over at a user chosen frequency. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
Schedule
+ *
This property specifies rollover schedule. The possible + * values are MONTHLY, WEEKLY, DAILY, + * TWICE_DAILY, HOURLY and + * MINUTELY.
+ * + *
MaxBackupIndex
+ *
This property limits how many backup files are kept per + * single logging period; e.g. how many log.2009-11-07.1, + * log.2009-11-07.2 etc. files are kept.
+ * + *
RollOnClose
+ *
This property specifies whether to rollover log files upon + * shutdown. By default it's set to true to retain compatibility + * with legacy code, however it may lead to undesired behaviour + * as described in the github issue #120.
+ * + *
DatePattern
+ *
This property specifies filename suffix pattern to use for + * periodical backups of the logfile. The patern should be in + * format supported by {@link log4cplus::helpers::Time::getFormatterTime()}. + * Please notice that the format of the pattern is similar but not identical + * to the one used for this option in the corresponding Log4J class. + * If the property isn't specified a reasonable default for a given + * schedule type is used.
+ * + *
+ */ + class LOG4CPLUS_EXPORT DailyRollingFileAppender : public FileAppender { + public: + // Ctors + DailyRollingFileAppender(const log4cplus::tstring& filename, + DailyRollingFileSchedule schedule = DAILY, + bool immediateFlush = true, + int maxBackupIndex = 10, + bool createDirs = false, + bool rollOnClose = true, + const log4cplus::tstring& datePattern = log4cplus::tstring()); + DailyRollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~DailyRollingFileAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(bool alreadyLocked = false); + log4cplus::helpers::Time calculateNextRolloverTime(const log4cplus::helpers::Time& t) const; + log4cplus::tstring getFilename(const log4cplus::helpers::Time& t) const; + + // Data + DailyRollingFileSchedule schedule; + log4cplus::tstring scheduledFilename; + log4cplus::helpers::Time nextRolloverTime; + int maxBackupIndex; + bool rollOnClose; + log4cplus::tstring datePattern; + + private: + LOG4CPLUS_PRIVATE void init(DailyRollingFileSchedule schedule); + }; + + typedef helpers::SharedObjectPtr + SharedDailyRollingFileAppenderPtr; + + + /** + * TimeBasedRollingFileAppender extends {@link FileAppenderBase} so that + * the underlying file is rolled over at a user chosen frequency while also + * keeping in check a total maximum number of produced files. + * + *

Properties

+ *

Properties additional to {@link FileAppenderBase}'s properties: + * + *

+ * + *
FilenamePattern
+ *
The mandatory fileNamePattern property defines the name of the + * rolled-over (archived) log files. Its value should consist of the name + * of the file, plus a suitably placed %d conversion specifier. The %d + * conversion specifier may contain a date-and-time pattern as specified by + * the java's SimpleDateFormat. The rollover period is inferred from the + * value of fileNamePattern.
+ * + *
MaxHistory
+ *
The optional maxHistory property controls the maximum number of + * archive files to keep, deleting older files.
+ * + *
CleanHistoryOnStart
+ *
If set to true, archive removal will be executed on appender start + * up. By default this property is set to false.
+ * + *
RollOnClose
+ *
This property specifies whether to rollover log files upon + * shutdown. By default it's set to true to retain compatibility + * with legacy code, however it may lead to undesired behaviour + * as described in the github issue #120.
+ * + *
+ */ + class LOG4CPLUS_EXPORT TimeBasedRollingFileAppender : public FileAppenderBase { + public: + // Ctors + TimeBasedRollingFileAppender(const tstring& filename = LOG4CPLUS_TEXT(""), + const tstring& filenamePattern = LOG4CPLUS_TEXT("%d.log"), + int maxHistory = 10, + bool cleanHistoryOnStart = false, + bool immediateFlush = true, + bool createDirs = false, + bool rollOnClose = true); + TimeBasedRollingFileAppender(const helpers::Properties& properties); + + // Dtor + ~TimeBasedRollingFileAppender(); + + protected: + void append(const spi::InternalLoggingEvent& event); + void open(std::ios_base::openmode mode); + void close(); + void rollover(bool alreadyLocked = false); + void clean(helpers::Time time); + helpers::Time::duration getRolloverPeriodDuration() const; + helpers::Time calculateNextRolloverTime(const helpers::Time& t) const; + + // Data + tstring filenamePattern; + DailyRollingFileSchedule schedule; + tstring scheduledFilename; + int maxHistory; + bool cleanHistoryOnStart; + log4cplus::helpers::Time lastHeartBeat; + log4cplus::helpers::Time nextRolloverTime; + bool rollOnClose; + + private: + LOG4CPLUS_PRIVATE void init(); + }; + + typedef helpers::SharedObjectPtr + SharedTimeBasedRollingFileAppenderPtr; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_FILE_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/fstreams.h b/LFtid1056/cloudfront/code/log4cplus/fstreams.h new file mode 100644 index 0000000..a7dcd66 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/fstreams.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: fstreams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_FSTREAMS_HEADER_ +#define LOG4CPLUS_FSTREAMS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus +{ + + +typedef std::basic_ofstream tofstream; +typedef std::basic_ifstream tifstream; + +//! \def LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) +//! \brief Expands into expression that picks the right type for +//! std::fstream file name parameter. +#if defined (LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T) && defined (UNICODE) +# define LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (X) +#else +# define LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (LOG4CPLUS_TSTRING_TO_STRING(X)) +#endif + + +} + +#endif // LOG4CPLUS_FSTREAMS_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/appenderattachableimpl.h b/LFtid1056/cloudfront/code/log4cplus/helpers/appenderattachableimpl.h new file mode 100644 index 0000000..52ed096 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/appenderattachableimpl.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appenderattachableimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ +#define LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachableImpl + : public log4cplus::spi::AppenderAttachable + { + public: + // Data + thread::Mutex appender_list_mutex; + + // Ctors + AppenderAttachableImpl(); + + // Dtor + virtual ~AppenderAttachableImpl(); + + // Methods + /** + * Add an appender. If the appender is already in the list in + * won't be added again. + */ + virtual void addAppender(SharedAppenderPtr newAppender); + + /** + * Get all previously added appenders as an vectory. + */ + virtual SharedAppenderPtrList getAllAppenders(); + + /** + * Look for an attached appender named as name. + * + * Return the appender with that name if in the list. Return null + * otherwise. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders(); + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender); + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name); + + /** + * Call the doAppend method on all attached appenders. + */ + int appendLoopOnAppenders(const spi::InternalLoggingEvent& event) const; + + protected: + // Types + typedef std::vector ListType; + + // Data + /** Array of appenders. */ + ListType appenderList; + + private: + AppenderAttachableImpl(AppenderAttachableImpl const &); + AppenderAttachableImpl & operator = (AppenderAttachableImpl const &); + }; // end class AppenderAttachableImpl + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/connectorthread.h b/LFtid1056/cloudfront/code/log4cplus/helpers/connectorthread.h new file mode 100644 index 0000000..6df3ce5 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/connectorthread.h @@ -0,0 +1,107 @@ +// -*- C++ -*- +// Copyright (C) 2013-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_CONNECTORTHREAD_H +#define LOG4CPLUS_HELPERS_CONNECTORTHREAD_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT ConnectorThread; + +//! Interface implemented by users of ConnectorThread. +class LOG4CPLUS_EXPORT IConnectorThreadClient +{ +protected: + virtual ~IConnectorThreadClient (); + + //! \return Mutex for synchronization between ConnectorThread and + //! its client object. This is usually SharedObject::access_mutex. + virtual thread::Mutex const & ctcGetAccessMutex () const = 0; + + //! \return Socket variable in ConnectorThread client to maintain. + virtual helpers::Socket & ctcGetSocket () = 0; + + //! \return ConnectorThread client's function returning connected + //! socket. + virtual helpers::Socket ctcConnect () = 0; + + //! Sets connected flag to true in ConnectorThread's client. + virtual void ctcSetConnected () = 0; + + friend class LOG4CPLUS_EXPORT ConnectorThread; +}; + + +//! This class is used by SocketAppender and (remote) SysLogAppender +//! to provide asynchronous re-connection. +class LOG4CPLUS_EXPORT ConnectorThread + : public thread::AbstractThread +{ +public: + //! \param client reference to ConnectorThread's client object + ConnectorThread (IConnectorThreadClient & client); + virtual ~ConnectorThread (); + + virtual void run(); + + //! Call this function to terminate ConnectorThread. The function + //! sets `exit_flag` and then triggers `trigger_ev` to wake up the + //! ConnectorThread. + void terminate (); + + //! This function triggers (`trigger_ev`) connection check and + //! attempt to re-connect a broken connection, when necessary. + void trigger (); + +protected: + //! reference to ConnectorThread's client + IConnectorThreadClient & ctc; + + //! This event is the re-connection trigger. + thread::ManualResetEvent trigger_ev; + + //! When this variable set to true when ConnectorThread is signaled to + bool exit_flag; +}; + + +} } // namespace log4cplus { namespace helpers { + +#endif // ! defined (LOG4CPLUS_SINGLE_THREADED) + +#endif // LOG4CPLUS_HELPERS_CONNECTORTHREAD_H diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/eventcounter.h b/LFtid1056/cloudfront/code/log4cplus/helpers/eventcounter.h new file mode 100644 index 0000000..be9f192 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/eventcounter.h @@ -0,0 +1,91 @@ +// -*- C++ -*- +// +// Copyright (C) 2024, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_EVENTCOUNTER_H +#define LOG4CPLUS_HELPERS_EVENTCOUNTER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + + +namespace log4cplus { + +namespace helpers { + +class LOG4CPLUS_EXPORT BaseEventCounter +{ +public: + BaseEventCounter (); + virtual ~BaseEventCounter (); + + virtual std::size_t record_event (); + +protected: + std::atomic event_count {0}; +}; + + +class LOG4CPLUS_EXPORT SteadyClockGate + : public BaseEventCounter +{ +public: + using Clock = std::chrono::steady_clock; + using Duration = Clock::duration; + using TimePoint = std::chrono::time_point; + + struct LOG4CPLUS_EXPORT Info + { + ~Info (); + + std::size_t count; + Duration time_span; + }; + + SteadyClockGate (SteadyClockGate::Duration pause_duraiton); + virtual ~SteadyClockGate (); + + bool latch_open (Info &); + +private: + log4cplus::thread::SimpleMutex mtx; + Duration const pause_duration; + TimePoint timeout_point; + TimePoint prev_timeout_point; +}; + + +} // namespace helpers + +} // namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_EVENTCOUNTER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/fileinfo.h b/LFtid1056/cloudfront/code/log4cplus/helpers/fileinfo.h new file mode 100644 index 0000000..88004ee --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/fileinfo.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +// +// Copyright (C) 2012-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_HELPERS_FILEINFO_H) +#define LOG4CPLUS_HELPERS_FILEINFO_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif + + +namespace log4cplus { namespace helpers { + +//! FileInfo structure is OS independent abstraction of the +//! stat() function. +struct LOG4CPLUS_EXPORT FileInfo +{ + helpers::Time mtime; + bool is_link; + off_t size; +}; + + +//! OS independent abstraction of stat() function. +LOG4CPLUS_EXPORT int getFileInfo (FileInfo * fi, tstring const & name); + + +} } // namespace log4cplus { namespace helpers { + +#endif // LOG4CPLUS_HELPERS_FILEINFO_H diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/lockfile.h b/LFtid1056/cloudfront/code/log4cplus/helpers/lockfile.h new file mode 100644 index 0000000..3856dcd --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/lockfile.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +// +// Copyright (C) 2012-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_HELPERS_LOCKFILE_H) +#define LOG4CPLUS_HELPERS_LOCKFILE_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT LockFile +{ +public: + LockFile (tstring const & lock_file, bool create_dirs = false); + ~LockFile (); + + void lock () const; + void unlock () const; + +private: + void open (int) const; + void close () const; + + struct Impl; + + tstring lock_file_name; + Impl * data; + bool create_dirs; +}; + + +typedef log4cplus::thread::SyncGuard LockFileGuard; + + +} } // namespace log4cplus { namespace helpers { + + +#endif // LOG4CPLUS_HELPERS_LOCKFILE_H diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/loglog.h b/LFtid1056/cloudfront/code/log4cplus/helpers/loglog.h new file mode 100644 index 0000000..4f92ef8 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/loglog.h @@ -0,0 +1,145 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loglog.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_LOGLOG +#define LOG4CPLUS_HELPERS_LOGLOG + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This class used to output log statements from within the log4cplus package. + * + * Log4cplus components cannot make log4cplus logging calls. However, it is + * sometimes useful for the user to learn about what log4cplus is + * doing. You can enable log4cplus internal logging by defining the + * log4cplus.configDebug variable. + * + * All log4cplus internal debug calls go to cout + * where as internal error messages are sent to + * cerr. All internal messages are prepended with + * the string "log4clus: ". + */ + class LOG4CPLUS_EXPORT LogLog + { + public: + //! Return type of getLogLog(). + typedef LogLog * Ptr; + + /** + * Returns a reference to the LogLog singleton. + */ + static Ptr getLogLog(); + + + /** + * Allows to enable/disable log4cplus internal logging. + */ + void setInternalDebugging(bool enabled); + + /** + * In quite mode no LogLog generates strictly no output, not even + * for errors. + * + * @param quietMode A true for not + */ + void setQuietMode(bool quietMode); + + /** + * This method is used to output log4cplus internal debug + * statements. Output goes to std::cout. + */ + void debug(const log4cplus::tstring& msg) const; + void debug(tchar const * msg) const; + + /** + * This method is used to output log4cplus internal error + * statements. There is no way to disable error + * statements. Output goes to + * std::cerr. Optionally, this method can + * throw std::runtime_error exception too. + */ + void error(const log4cplus::tstring& msg, bool throw_flag = false) const; + void error(tchar const * msg, bool throw_flag = false) const; + + /** + * This method is used to output log4cplus internal warning + * statements. There is no way to disable warning statements. + * Output goes to std::cerr. + */ + void warn(const log4cplus::tstring& msg) const; + void warn(tchar const * msg) const; + + // Public ctor and dtor to be used only by internal::DefaultContext. + LogLog(); + virtual ~LogLog(); + + private: + enum TriState + { + TriUndef = -1, + TriFalse, + TriTrue + }; + + template + LOG4CPLUS_PRIVATE + void logging_worker (tostream & os, + bool (LogLog:: * cond) () const, tchar const *, + StringType const &, bool throw_flag = false) const; + + LOG4CPLUS_PRIVATE static void set_tristate_from_env (TriState *, + tchar const * envvar); + + LOG4CPLUS_PRIVATE bool get_quiet_mode () const; + LOG4CPLUS_PRIVATE bool get_not_quiet_mode () const; + LOG4CPLUS_PRIVATE bool get_debug_mode () const; + + // Data + mutable TriState debugEnabled; + mutable TriState quietMode; + thread::Mutex mutex; + + LOG4CPLUS_PRIVATE LogLog(const LogLog&); + LOG4CPLUS_PRIVATE LogLog & operator = (LogLog const &); + }; + + LOG4CPLUS_EXPORT LogLog & getLogLog (); + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_LOGLOG + diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/pointer.h b/LFtid1056/cloudfront/code/log4cplus/helpers/pointer.h new file mode 100644 index 0000000..d9ccfd4 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/pointer.h @@ -0,0 +1,210 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: pointer.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// Note: Some of this code uses ideas from "More Effective C++" by Scott +// Myers, Addison Wesley Longmain, Inc., (c) 1996, Chapter 29, pp. 183-213 +// + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_POINTERS_HEADER_ +#define LOG4CPLUS_HELPERS_POINTERS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#if ! defined (LOG4CPLUS_SINGLE_THREADED) +#include +#endif + + +namespace log4cplus { + namespace helpers { + + /****************************************************************************** + * Class SharedObject (from pp. 204-205) * + ******************************************************************************/ + + class LOG4CPLUS_EXPORT SharedObject + { + public: + void addReference() const LOG4CPLUS_NOEXCEPT; + void removeReference() const; + + protected: + // Ctor + SharedObject() + : access_mutex() + , count__(0) + { } + + SharedObject(const SharedObject&) + : access_mutex() + , count__(0) + { } + + SharedObject(SharedObject &&) + : access_mutex() + , count__(0) + { } + + // Dtor + virtual ~SharedObject(); + + // Operators + SharedObject& operator=(const SharedObject&) LOG4CPLUS_NOEXCEPT { return *this; } + SharedObject& operator=(SharedObject &&) LOG4CPLUS_NOEXCEPT { return *this; } + + public: + thread::Mutex access_mutex; + + private: +#if defined (LOG4CPLUS_SINGLE_THREADED) + typedef unsigned count_type; +#else + typedef std::atomic count_type; +#endif + mutable count_type count__; + }; + + + /****************************************************************************** + * Template Class SharedObjectPtr (from pp. 203, 206) * + ******************************************************************************/ + template + class SharedObjectPtr + { + public: + // Ctor + explicit + SharedObjectPtr(T* realPtr = 0) LOG4CPLUS_NOEXCEPT + : pointee(realPtr) + { + addref (); + } + + SharedObjectPtr(const SharedObjectPtr& rhs) LOG4CPLUS_NOEXCEPT + : pointee(rhs.pointee) + { + addref (); + } + + SharedObjectPtr(SharedObjectPtr && rhs) LOG4CPLUS_NOEXCEPT + : pointee (std::move (rhs.pointee)) + { + rhs.pointee = 0; + } + + SharedObjectPtr & operator = (SharedObjectPtr && rhs) LOG4CPLUS_NOEXCEPT + { + rhs.swap (*this); + return *this; + } + + // Dtor + ~SharedObjectPtr() + { + if (pointee) + pointee->removeReference(); + } + + // Operators + bool operator==(const SharedObjectPtr& rhs) const + { return (pointee == rhs.pointee); } + bool operator!=(const SharedObjectPtr& rhs) const + { return (pointee != rhs.pointee); } + bool operator==(const T* rhs) const { return (pointee == rhs); } + bool operator!=(const T* rhs) const { return (pointee != rhs); } + T* operator->() const {assert (pointee); return pointee; } + T& operator*() const {assert (pointee); return *pointee; } + + SharedObjectPtr& operator=(const SharedObjectPtr& rhs) + { + return this->operator = (rhs.pointee); + } + + SharedObjectPtr& operator=(T* rhs) + { + SharedObjectPtr (rhs).swap (*this); + return *this; + } + + // Methods + T* get() const { return pointee; } + + void swap (SharedObjectPtr & other) LOG4CPLUS_NOEXCEPT + { + std::swap (pointee, other.pointee); + } + + typedef T * (SharedObjectPtr:: * unspec_bool_type) () const; + operator unspec_bool_type () const + { + return pointee ? &SharedObjectPtr::get : 0; + } + + bool operator ! () const + { + return ! pointee; + } + + private: + // Methods + void addref() const LOG4CPLUS_NOEXCEPT + { + if (pointee) + pointee->addReference(); + } + + // Data + T* pointee; + }; + + + //! Boost `intrusive_ptr` helpers. + //! @{ + inline + void + intrusive_ptr_add_ref (SharedObject const * so) + { + so->addReference(); + } + + inline + void + intrusive_ptr_release (SharedObject const * so) + { + so->removeReference(); + } + //! @} + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_POINTERS_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/property.h b/LFtid1056/cloudfront/code/log4cplus/helpers/property.h new file mode 100644 index 0000000..fa81bc3 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/property.h @@ -0,0 +1,172 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: property.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_PROPERTY_HEADER_ +#define LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + //! \sa log4cplus::PropertyConfigurator + class LOG4CPLUS_EXPORT Properties { + public: + enum PFlags + { + // These encoding related options occupy 2 bits of the flags + // and are mutually exclusive. These flags are synchronized + // with PCFlags in PropertyConfigurator. + + fEncodingShift = 3 + , fEncodingMask = 0x3 + , fUnspecEncoding = (0 << fEncodingShift) +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) + , fUTF8 = (1 << fEncodingShift) +#endif +#if (defined (LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ + && defined (UNICODE) + , fUTF16 = (2 << fEncodingShift) +#endif +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) + , fUTF32 = (3 << fEncodingShift) +#endif + , fThrow = (1 << 5) + }; + + Properties(); + explicit Properties(log4cplus::tistream& input); + explicit Properties(const log4cplus::tstring& inputFile, unsigned flags = 0); + virtual ~Properties(); + + // constants + static const tchar PROPERTIES_COMMENT_CHAR; + + // methods + /** + * Tests to see if key can be found in this map. + */ + bool exists(const log4cplus::tstring& key) const; + bool exists(tchar const * key) const; + + /** + * Returns the number of entries in this map. + */ + std::size_t size() const + { + return data.size(); + } + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns null if the property is not found. + */ + log4cplus::tstring const & getProperty(const log4cplus::tstring& key) const; + log4cplus::tstring const & getProperty(tchar const * key) const; + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns the default value argument if the property is + * not found. + */ + log4cplus::tstring getProperty(const log4cplus::tstring& key, + const log4cplus::tstring& defaultVal) const; + + /** + * Returns all the keys in this property list. + */ + std::vector propertyNames() const; + + /** + * Inserts value into this map indexed by key. + */ + void setProperty(const log4cplus::tstring& key, const log4cplus::tstring& value); + + /** + * Removed the property index by key from this map. + */ + bool removeProperty(const log4cplus::tstring& key); + + /** + * Returns a subset of the "properties" whose keys start with + * "prefix". The returned "properties" have "prefix" trimmed from + * their keys. + */ + Properties getPropertySubset(const log4cplus::tstring& prefix) const; + + bool getInt (int & val, log4cplus::tstring const & key) const; + bool getUInt (unsigned & val, log4cplus::tstring const & key) const; + bool getLong (long & val, log4cplus::tstring const & key) const; + bool getULong (unsigned long & val, log4cplus::tstring const & key) const; + bool getBool (bool & val, log4cplus::tstring const & key) const; + bool getString (log4cplus::tstring & val, log4cplus::tstring const & key) const; + + protected: + // Types + typedef std::map StringMap; + + // Methods + void init(log4cplus::tistream& input); + + // Data + StringMap data; + unsigned flags; + + private: + template + log4cplus::tstring const & get_property_worker ( + StringType const & key) const; + + template + bool get_type_val_worker (ValType & val, + log4cplus::tstring const & key) const; + }; + + + class LogLog; + + + bool + substVars (tstring & dest, const tstring & val, + Properties const & props, LogLog& loglog, + unsigned flags); + } // end namespace helpers + +} + + +#endif // LOG4CPLUS_HELPERS_PROPERTY_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/queue.h b/LFtid1056/cloudfront/code/log4cplus/helpers/queue.h new file mode 100644 index 0000000..113d695 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/queue.h @@ -0,0 +1,158 @@ +// -*- C++ -*- +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_QUEUE_H +#define LOG4CPLUS_HELPERS_QUEUE_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + +#include +#include +#include +#include + + +namespace log4cplus { namespace thread { + + +//! Single consumer, multiple producers queue. +class LOG4CPLUS_EXPORT Queue + : public virtual helpers::SharedObject +{ +public: + //! Type of the state flags field. + typedef unsigned flags_type; + + //! Queue storage type. + typedef std::deque queue_storage_type; + + explicit Queue (unsigned len = 100); + virtual ~Queue (); + + // Producers' methods. + + //! Puts event ev into queue, sets QUEUE flag and + //! sets internal event object into signaled state. If the EXIT + //! flags is already set upon entering the function, nothing is + //! inserted into the queue. The function can block on internal + //! semaphore if the queue has reached maximal allowed + //! length. Calling thread is unblocked either by consumer thread + //! removing item from queue or by any other thread calling + //! signal_exit(). + //! + //! \param ev spi::InternalLoggingEvent to be put into the queue. + //! \return Flags. + flags_type put_event (spi::InternalLoggingEvent const & ev); + + //! Sets EXIT flag and DRAIN flag and sets internal event object + //! into signaled state. + //! \param drain If true, DRAIN flag will be set, otherwise unset. + //! \return Flags, ERROR_BIT can be set upon error. + flags_type signal_exit (bool drain = true); + + // Consumer's methods. + + //! The get_events() function is used by queue's consumer. It + //! fills buf argument and sets EVENT flag in return + //! value. If EXIT flag is already set in flags member upon + //! entering the function then depending on DRAIN flag it either + //! fills buf argument or does not fill the argument, + //! if the queue is non-empty. The function blocks by waiting for + //! internal event object to be signaled if the queue is empty, + //! unless EXIT flag is set. The calling thread is unblocked when + //! items are added into the queue or when exit is signaled using + //! the signal_exit() function. + //! + //! + //! Upon error, return value has one of the error flags set. + //! + //! \param buf Pointer to storage of spi::InternalLoggingEvent + //! instances to be filled from queue. + //! \return Flags. + flags_type get_events (queue_storage_type * buf); + + //! Possible state flags. + enum Flags + { + //! EVENT flag is set in return value of get_event() call if + //! the ev argument is filled with event from the queue. + EVENT = 0x0001, + + //! QUEUE flag is set by producers when they put item into the + //! queue. + QUEUE = 0x0002, + + //! EXIT flag is set by signal_exit() call, signaling that the + //! queue worker thread should end itself. + EXIT = 0x0004, + + //! When DRAIN flag is set together with EXIT flag, the queue + //! worker thread will first drain the queue before exiting. + DRAIN = 0x0008, + + //! ERROR_BIT signals error. + ERROR_BIT = 0x0010, + + //! ERROR_AFTER signals error that has occurred after queue has + //! already been touched. + ERROR_AFTER = 0x0020 + }; + +protected: + //! Queue storage. + queue_storage_type queue; + + //! Mutex protecting queue and flags. + Mutex mutex; + + //! Event on which consumer can wait if it finds queue empty. + ManualResetEvent ev_consumer; + + //! Semaphore that limits the queue length. + Semaphore sem; + + //! State flags. + flags_type flags; + +private: + Queue (Queue const &); + Queue & operator = (Queue const &); +}; + + +typedef helpers::SharedObjectPtr QueuePtr; + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_SINGLE_THREADED + +#endif // LOG4CPLUS_HELPERS_QUEUE_H diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/snprintf.h b/LFtid1056/cloudfront/code/log4cplus/helpers/snprintf.h new file mode 100644 index 0000000..bf56935 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/snprintf.h @@ -0,0 +1,62 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_SNPRINTF_H +#define LOG4CPLUS_HELPERS_SNPRINTF_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT snprintf_buf +{ +public: + snprintf_buf (); + + tchar const * print (tchar const * fmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 2, 3); + + int print_va_list (tchar const * & str, tchar const * fmt, std::va_list) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 0); + +private: + std::vector buf; +}; + + +} } // namespace log4cplus { namespace helpers + + + +#endif // LOG4CPLUS_HELPERS_SNPRINTF_H diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/socket.h b/LFtid1056/cloudfront/code/log4cplus/helpers/socket.h new file mode 100644 index 0000000..1924bfe --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/socket.h @@ -0,0 +1,163 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socket.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + enum SocketState { ok, + not_opened, + bad_address, + connection_failed, + broken_pipe, + invalid_access_mode, + message_truncated, + accept_interrupted + }; + + typedef std::ptrdiff_t SOCKET_TYPE; + + extern LOG4CPLUS_EXPORT SOCKET_TYPE const INVALID_SOCKET_VALUE; + + class LOG4CPLUS_EXPORT AbstractSocket { + public: + AbstractSocket(); + AbstractSocket(SOCKET_TYPE sock, SocketState state, int err); + AbstractSocket(AbstractSocket const &) = delete; + AbstractSocket(AbstractSocket &&) LOG4CPLUS_NOEXCEPT; + virtual ~AbstractSocket() = 0; + + /// Close socket + virtual void close(); + virtual bool isOpen() const; + virtual void shutdown(); + AbstractSocket & operator = (AbstractSocket && rhs) LOG4CPLUS_NOEXCEPT; + + void swap (AbstractSocket &); + + protected: + SOCKET_TYPE sock; + SocketState state; + int err; + }; + + + + /** + * This class implements client sockets (also called just "sockets"). + * A socket is an endpoint for communication between two machines. + */ + class LOG4CPLUS_EXPORT Socket : public AbstractSocket { + public: + // ctor and dtor + Socket(); + Socket(SOCKET_TYPE sock, SocketState state, int err); + Socket(const tstring& address, unsigned short port, + bool udp = false, bool ipv6 = false); + Socket(Socket &&) LOG4CPLUS_NOEXCEPT; + virtual ~Socket(); + + Socket & operator = (Socket &&) LOG4CPLUS_NOEXCEPT; + + // methods + virtual bool read(SocketBuffer& buffer); + virtual bool write(const SocketBuffer& buffer); + virtual bool write(const std::string & buffer); + virtual bool write(std::size_t bufferCount, + SocketBuffer const * const * buffers); + + template + static bool write(Socket & socket, Args &&... args) + { + SocketBuffer const * const buffers[sizeof... (args)] { + (&args)... }; + return socket.write (sizeof... (args), buffers); + } + }; + + + + /** + * This class implements server sockets. A server socket waits for + * requests to come in over the network. It performs some operation + * based on that request, and then possibly returns a result to the + * requester. + */ + class LOG4CPLUS_EXPORT ServerSocket : public AbstractSocket { + public: + ServerSocket(unsigned short port, bool udp = false, + bool ipv6 = false, tstring const & host = tstring ()); + ServerSocket(ServerSocket &&) LOG4CPLUS_NOEXCEPT; + virtual ~ServerSocket(); + + ServerSocket & operator = (ServerSocket &&) LOG4CPLUS_NOEXCEPT; + + Socket accept(); + void interruptAccept (); + void swap (ServerSocket &); + + protected: + std::array interruptHandles; + }; + + + LOG4CPLUS_EXPORT SOCKET_TYPE openSocket(unsigned short port, bool udp, + bool ipv6, SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE openSocket(tstring const & host, + unsigned short port, bool udp, bool ipv6, SocketState& state); + + LOG4CPLUS_EXPORT SOCKET_TYPE connectSocket(const log4cplus::tstring& hostn, + unsigned short port, bool udp, bool ipv6, SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE acceptSocket(SOCKET_TYPE sock, SocketState& state); + LOG4CPLUS_EXPORT int closeSocket(SOCKET_TYPE sock); + LOG4CPLUS_EXPORT int shutdownSocket(SOCKET_TYPE sock); + + LOG4CPLUS_EXPORT long read(SOCKET_TYPE sock, SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, + const SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, std::size_t bufferCount, + SocketBuffer const * const * buffers); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, + const std::string & buffer); + + LOG4CPLUS_EXPORT tstring getHostname (bool fqdn); + LOG4CPLUS_EXPORT int setTCPNoDelay (SOCKET_TYPE, bool); + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/socketbuffer.h b/LFtid1056/cloudfront/code/log4cplus/helpers/socketbuffer.h new file mode 100644 index 0000000..d58b643 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/socketbuffer.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socketbuffer.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { +namespace helpers { + +/** + * + */ +class LOG4CPLUS_EXPORT SocketBuffer +{ +public: + explicit SocketBuffer(std::size_t max); + virtual ~SocketBuffer(); + + char *getBuffer() const { return buffer; } + std::size_t getMaxSize() const { return maxsize; } + std::size_t getSize() const { return size; } + void setSize(std::size_t s) { size = s; } + std::size_t getPos() const { return pos; } + + unsigned char readByte(); + unsigned short readShort(); + unsigned int readInt(); + tstring readString(unsigned char sizeOfChar); + + void appendByte(unsigned char val); + void appendShort(unsigned short val); + void appendInt(unsigned int val); + void appendString(const tstring& str); + void appendBuffer(const SocketBuffer& buffer); + +private: + // Data + std::size_t maxsize; + std::size_t size; + std::size_t pos; + char *buffer; + + SocketBuffer(SocketBuffer const & rhs); + SocketBuffer& operator= (SocketBuffer const& rhs); +}; + +} // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/stringhelper.h b/LFtid1056/cloudfront/code/log4cplus/helpers/stringhelper.h new file mode 100644 index 0000000..ee825c3 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/stringhelper.h @@ -0,0 +1,271 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: stringhelper.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ +#define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * Returns s in upper case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s); + LOG4CPLUS_EXPORT tchar toUpper(tchar); + + + /** + * Returns s in lower case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s); + LOG4CPLUS_EXPORT tchar toLower(tchar); + + + /** + * Tokenize s using c as the delimiter and + * put the resulting tokens in _result. If + * collapseTokens is false, multiple adjacent delimiters + * will result in zero length tokens. + * + * Example: + *
+         *   string s = // Set string with '.' as delimiters
+         *   list tokens;
+         *   tokenize(s, '.', back_insert_iterator >(tokens));
+         * 
+ */ + template + inline + void + tokenize(const StringType& s, typename StringType::value_type c, + OutputIter result, bool collapseTokens = true) + { + typedef typename StringType::size_type size_type; + size_type const slen = s.length(); + size_type first = 0; + size_type i = 0; + for (i=0; i < slen; ++i) + { + if (s[i] == c) + { + *result = StringType (s, first, i - first); + ++result; + if (collapseTokens) + while (i+1 < slen && s[i+1] == c) + ++i; + first = i + 1; + } + } + if (first != i) + *result = StringType (s, first, i - first); + else if (! collapseTokens && first == i) + *result = StringType (); + } + + + template + struct ConvertIntegerToStringHelper; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (charType * & it, intType & value) + { + // The sign of the result of the modulo operator is + // implementation defined. That's why we work with + // positive counterpart instead. Also, in twos + // complement arithmetic the smallest negative number + // does not have positive counterpart; the range is + // asymetric. That's why we handle the case of value + // == min() specially here. + if (LOG4CPLUS_UNLIKELY ( + value == (std::numeric_limits::min) ())) + { + intType const r = value / 10; + intType const a = (-r) * 10; + intType const mod = -(a + value); + value = -r; + + *(it - 1) + = static_cast(LOG4CPLUS_TEXT('0') + mod); + --it; + } + else + value = -value; + } + + static + bool + is_negative (intType val) + { + return val < 0; + } + }; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (charType * &, intType &) + { + // This will never be called for unsigned types. + } + + static + bool + is_negative (intType) + { + return false; + } + }; + + + template + inline + void + convertIntegerToString (stringType & str, intType value) + { + typedef std::numeric_limits intTypeLimits; + typedef typename stringType::value_type charType; + typedef ConvertIntegerToStringHelper HelperType; + + charType buffer[intTypeLimits::digits10 + 2]; + const std::size_t buffer_size + = sizeof (buffer) / sizeof (charType); + + charType * it = &buffer[buffer_size]; + charType const * const buf_end = &buffer[buffer_size]; + + if (LOG4CPLUS_UNLIKELY (value == 0)) + { + --it; + *it = LOG4CPLUS_TEXT('0'); + } + else + { + bool const negative = HelperType::is_negative (value); + if (negative) + HelperType::step1 (it, value); + + for (; value != 0; --it) + { + intType mod = value % 10; + value = value / 10; + *(it - 1) = static_cast(LOG4CPLUS_TEXT('0') + + mod); + } + + if (negative) + { + --it; + *it = LOG4CPLUS_TEXT('-'); + } + } + + str.assign (static_cast(it), buf_end); + } + + + template + inline + tstring + convertIntegerToString (intType value) + { + tstring result; + convertIntegerToString (result, value); + return result; + } + + + template + inline + std::string + convertIntegerToNarrowString (intType value) + { + std::string result; + convertIntegerToString (result, value); + return result; + } + + + //! Join a list of items into a string. + template + inline + void + join_worker (tstring & result, Iterator & start, Iterator & last, + Separator const & sep) + { + if (start != last) + result = *start++; + + for (; start != last; ++start) + { + result += sep; + result += *start; + } + } + + //! Join a list of items into a string. + template + inline + void + join (tstring & result, Iterator start, Iterator last, + tstring const & sep) + { + join_worker (result, start, last, sep); + } + + //! Join a list of items into a string. + template + inline + void + join (tstring & result, Iterator start, Iterator last, + tstring::value_type sep) + { + join_worker (result, start, last, sep); + } + + + } // namespace helpers + +} // namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/thread-config.h b/LFtid1056/cloudfront/code/log4cplus/helpers/thread-config.h new file mode 100644 index 0000000..0d89762 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/thread-config.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: thread-config.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ +#define LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_USE_PTHREADS) +# if defined (__APPLE__) +# define LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE +# endif + +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) +# define LOG4CPLUS_USE_SRW_LOCK +//# define LOG4CPLUS_POOR_MANS_SHAREDMUTEX +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR +# if defined (_MSC_VER) +// The __declspec(thread) functionality is not compatible with LoadLibrary(). +// For more information why see and "Windows and TLS" note in README. +// . +# define LOG4CPLUS_HAVE_TLS_SUPPORT 1 +# define LOG4CPLUS_THREAD_LOCAL_VAR __declspec(thread) +# endif + +#elif defined(LOG4CPLUS_SINGLE_THREADED) +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR + +#else +# error "You Must define a Threading model" + +#endif + + +#endif // LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/helpers/timehelper.h b/LFtid1056/cloudfront/code/log4cplus/helpers/timehelper.h new file mode 100644 index 0000000..40f3b42 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/helpers/timehelper.h @@ -0,0 +1,169 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: timehelper.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ +#define LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (LOG4CPLUS_HAVE_TIME_H) +#include +#endif + +#include +#include + + +namespace log4cplus { + +namespace helpers { + + +using std::time_t; +using std::tm; +namespace chrono = std::chrono; + +typedef chrono::system_clock Clock; +typedef chrono::duration Duration; +typedef chrono::time_point Time; + + +template +inline +Time +time_cast (chrono::time_point const & tp) +{ + return chrono::time_point_cast (tp); +} + + +inline +Time +now () +{ + return time_cast (Clock::now ()); +} + + +inline +Time +from_time_t (time_t t_time) +{ + return time_cast (Clock::from_time_t (t_time)); +} + + +inline +time_t +to_time_t (Time const & the_time) +{ + // This is based on . It is + // possible that to_time_t() returns rounded time and we want truncation. + + time_t time = Clock::to_time_t (the_time); + auto const rounded_time = from_time_t (time); + if (rounded_time > the_time) + --time; + + return time; +} + + +LOG4CPLUS_EXPORT Time from_struct_tm (tm * t); + + +inline +Time +truncate_fractions (Time const & the_time) +{ + return from_time_t (to_time_t (the_time)); +} + + +inline +long +microseconds_part (Time const & the_time) +{ + static_assert ((std::ratio_equal::value), + "microseconds"); + + // This is based on + return static_cast( + (the_time - from_time_t (to_time_t (the_time))).count ()); +} + + +inline +Time +time_from_parts (time_t tv_sec, long tv_usec) +{ + return from_time_t (tv_sec) + chrono::microseconds (tv_usec); +} + + +/** + * Populates tm using the gmtime() + * function. + */ + +LOG4CPLUS_EXPORT +void gmTime (tm* t, Time const &); + +/** + * Populates tm using the localtime() + * function. + */ + +LOG4CPLUS_EXPORT +void localTime (tm* t, Time const &); + +/** + * Returns a string with a "formatted time" specified by + * fmt. It used the strftime() + * function to do this. + * + * Look at your platform's strftime() documentation + * for the formatting options available. + * + * The following additional options are provided:
+ * %q - 3 character field that provides milliseconds + * %Q - 7 character field that provides fractional + * milliseconds. + */ +LOG4CPLUS_EXPORT +log4cplus::tstring getFormattedTime (log4cplus::tstring const & fmt, + Time const & the_time, bool use_gmtime = false); + + +} // namespace helpers + +} // namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/hierarchy.h b/LFtid1056/cloudfront/code/log4cplus/hierarchy.h new file mode 100644 index 0000000..80cb23c --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/hierarchy.h @@ -0,0 +1,324 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: hierarchy.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HIERARCHY_HEADER_ +#define LOG4CPLUS_HIERARCHY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { + // Forward Declarations + class HierarchyLocker; + + /** + * This class is specialized in retrieving loggers by name and + * also maintaining the logger hierarchy. + * + * The casual user should not have to deal with this class + * directly. However, if you are in an environment where + * multiple applications run in the same process, then read on. + * + * The structure of the logger hierarchy is maintained by the + * {@link #getInstance} method. The hierarchy is such that children + * link to their parent but parents do not have any pointers to their + * children. Moreover, loggers can be instantiated in any order, in + * particular descendant before ancestor. + * + * In case a descendant is created before a particular ancestor, + * then it creates a provision node for the ancestor and adds itself + * to the provision node. Other descendants of the same ancestor add + * themselves to the previously created provision node. + */ + class LOG4CPLUS_EXPORT Hierarchy + { + public: + // DISABLE_OFF should be set to a value lower than all possible + // priorities. + static const LogLevel DISABLE_OFF; + static const LogLevel DISABLE_OVERRIDE; + + // Ctors + /** + * Create a new Logger hierarchy. + */ + Hierarchy(); + + // Dtor + virtual ~Hierarchy(); + + // Methods + /** + * This call will clear all logger definitions from the internal + * hashtable. Invoking this method will irrevocably mess up the + * logger hierarchy. + * + * You should really know what you are doing before + * invoking this method. + */ + virtual void clear(); + + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + virtual bool exists(const log4cplus::tstring& name); + + /** + * Similar to {@link #disable(LogLevel)} except that the LogLevel + * argument is given as a log4cplus::tstring. + */ + virtual void disable(const log4cplus::tstring& loglevelStr); + + /** + * Disable all logging requests of LogLevel equal to or + * below the ll parameter p, for + * all loggers in this hierarchy. Logging requests of + * higher LogLevel then p remain unaffected. + * + * Nevertheless, if the + * BasicConfigurator::DISABLE_OVERRIDE_KEY property is set to + * true, then logging requests are evaluated as usual. + * + * The "disable" family of methods are there for speed. They + * allow printing methods such as debug, info, etc. to return + * immediately after an integer comparison without walking the + * logger hierarchy. In most modern computers an integer + * comparison is measured in nanoseconds where as a logger walk is + * measured in units of microseconds. + */ + virtual void disable(LogLevel ll); + + /** + * Disable all logging requests regardless of logger and LogLevel. + * This method is equivalent to calling {@link #disable} with the + * argument FATAL_LOG_LEVEL, the highest possible LogLevel. + */ + virtual void disableAll(); + + /** + * Disable all Debug logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument DEBUG_LOG_LEVEL. + */ + virtual void disableDebug(); + + /** + * Disable all Info logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument INFO_LOG_LEVEL. + */ + virtual void disableInfo(); + + /** + * Undoes the effect of calling any of {@link #disable}, {@link + * #disableAll}, {@link #disableDebug} and {@link #disableInfo} + * methods. More precisely, invoking this method sets the Logger + * class internal variable called disable to its + * default "off" value. + */ + virtual void enableAll(); + + /** + * Return a new logger instance named as the first parameter using + * the default factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated and + * then linked with its existing ancestors as well as children. + * + * @param name The name of the logger to retrieve. + */ + virtual Logger getInstance(const log4cplus::tstring& name); + + /** + * Return a new logger instance named as the first parameter using + * factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated by the + * factory parameter and linked with its existing + * ancestors as well as children. + * + * @param name The name of the logger to retrieve. + * @param factory The factory that will make the new logger instance. + */ + virtual Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Returns all the currently defined loggers in this hierarchy. + * + * The root logger is not included in the returned list. + */ + virtual LoggerList getCurrentLoggers(); + + /** + * Is the LogLevel specified by level enabled? + */ + virtual bool isDisabled(LogLevel level); + + /** + * Get the root of this hierarchy. + */ + virtual Logger getRoot() const; + + /** + * Reset all values contained in this hierarchy instance to their + * default. This removes all appenders from all loggers, sets + * the LogLevel of all non-root loggers to NOT_SET_LOG_LEVEL, + * sets their additivity flag to true and sets the LogLevel + * of the root logger to DEBUG_LOG_LEVEL. Moreover, message disabling + * is set its default "off" value. + * + * Existing loggers are not removed. They are just reset. + * + * This method should be used sparingly and with care as it will + * block all logging until it is completed.

+ */ + virtual void resetConfiguration(); + + /** + * Set the default LoggerFactory instance. + */ + virtual void setLoggerFactory(std::unique_ptr factory); + + /** + * Returns the default LoggerFactory instance. + */ + virtual spi::LoggerFactory* getLoggerFactory(); + + /** + * Shutting down a hierarchy will safely close and remove + * all appenders in all loggers including the root logger. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + virtual void shutdown(); + + private: + // Types + typedef std::vector ProvisionNode; + typedef std::map ProvisionNodeMap; + typedef std::map LoggerMap; + + // Methods + /** + * This is the implementation of the getInstance() method. + * NOTE: This method does not lock the hashtable_mutex. + */ + LOG4CPLUS_PRIVATE + Logger getInstanceImpl(const log4cplus::tstring& name, + spi::LoggerFactory& factory); + + /** + * This is the implementation of the getCurrentLoggers(). + * NOTE: This method does not lock the hashtable_mutex. + */ + LOG4CPLUS_PRIVATE + void initializeLoggerList(LoggerList& list) const; + + /** + * This method loops through all the *potential* parents of + * logger'. There 3 possible cases: + * + * 1) No entry for the potential parent of 'logger' exists + * + * We create a ProvisionNode for this potential parent and insert + * 'logger' in that provision node. + * + * 2) There is an entry of type Logger for the potential parent. + * + * The entry is 'logger's nearest existing parent. We update logger's + * parent field with this entry. We also break from the loop + * because updating our parent's parent is our parent's + * responsibility. + * + * 3) There entry is of type ProvisionNode for this potential parent. + * + * We add 'logger' to the list of children for this potential parent. + */ + LOG4CPLUS_PRIVATE void updateParents(Logger const & logger); + + /** + * We update the links for all the children that placed themselves + * in the provision node 'pn'. The second argument 'logger' is a + * reference for the newly created Logger, parent of all the + * children in 'pn' + * + * We loop on all the children 'c' in 'pn': + * + * If the child 'c' has been already linked to a child of + * 'logger' then there is no need to update 'c'. + * + * Otherwise, we set logger's parent field to c's parent and set + * c's parent field to logger. + */ + LOG4CPLUS_PRIVATE void updateChildren(ProvisionNode& pn, + Logger const & logger); + + // Data + thread::Mutex hashtable_mutex; + std::unique_ptr defaultFactory; + ProvisionNodeMap provisionNodes; + LoggerMap loggerPtrs; + Logger root; + + int disableValue; + + bool emittedNoAppenderWarning; + + // Disallow copying of instances of this class + Hierarchy(const Hierarchy&); + Hierarchy& operator=(const Hierarchy&); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::HierarchyLocker; + }; + + + LOG4CPLUS_EXPORT Hierarchy & getDefaultHierarchy (); + + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HIERARCHY_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/hierarchylocker.h b/LFtid1056/cloudfront/code/log4cplus/hierarchylocker.h new file mode 100644 index 0000000..20fa9aa --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/hierarchylocker.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: hierarchylocker.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ +#define LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus +{ + + class Hierarchy; + + + /** + * This is used to lock a Hierarchy. The dtor unlocks the Hierarchy. + */ + class LOG4CPLUS_EXPORT HierarchyLocker { + public: + // ctor & dtor + HierarchyLocker(Hierarchy& h); + ~HierarchyLocker() LOG4CPLUS_NOEXCEPT_FALSE; + + /** + * Calls the resetConfiguration() method on the locked Hierarchy. + */ + void resetConfiguration(); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + private: + // Data + Hierarchy& h; + log4cplus::thread::MutexGuard hierarchyLocker; + LoggerList loggerList; + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/initializer.h b/LFtid1056/cloudfront/code/log4cplus/initializer.h new file mode 100644 index 0000000..92245de --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/initializer.h @@ -0,0 +1,62 @@ +// Copyright (C) 2015-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_INITIALIZER_HXX +#define LOG4CPLUS_INITIALIZER_HXX + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus +{ + +/** + This class helps with initialization and shutdown of log4cplus. Its + constructor calls `log4cplus::initialize()` and its destructor calls + `log4cplus::Logger::shutdown()`. Use this class as the first thing in your + `main()`. It will ensure shutdown of log4cplus at the end of + `main()`. This is particularly important on Windows, where shutdown of + standard threads outside `main()` is impossible. + */ +class LOG4CPLUS_EXPORT Initializer +{ +public: + Initializer (); + ~Initializer (); + + Initializer (Initializer const &) = delete; + Initializer (Initializer &&) = delete; + Initializer & operator = (Initializer const &) = delete; + Initializer & operator = (Initializer &&) = delete; +}; + +} // namespace log4cplus + + +#endif // LOG4CPLUS_INITIALIZER_HXX diff --git a/LFtid1056/cloudfront/code/log4cplus/internal/customloglevelmanager.h b/LFtid1056/cloudfront/code/log4cplus/internal/customloglevelmanager.h new file mode 100644 index 0000000..386dad0 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/internal/customloglevelmanager.h @@ -0,0 +1,151 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: customloglevelmanager.h +// Created: 12/2018 +// Author: Jens Rehsack +// Author: Václav Haisman +// +// +// Copyright (C) 2018, Jens Rehsack. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared library. + */ + + +#ifndef LOG4CPLUS_INTERNAL_CUSTOMLOGLEVELMANAGER_HEADER_ +#define LOG4CPLUS_INTERNAL_CUSTOMLOGLEVELMANAGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#include + + +namespace log4cplus { + +namespace internal { + + +/** + * Custom log level manager used by C API. + */ +class CustomLogLevelManager { +protected: + log4cplus::thread::Mutex mtx; + bool pushed_methods; + std::map ll2nm; + std::map nm2ll; + +public: + CustomLogLevelManager() + : pushed_methods (false) + { } + + bool add(LogLevel ll, tstring const &nm) + { + log4cplus::thread::MutexGuard guard (mtx); + + if (! pushed_methods) + { + pushed_methods = true; + getLogLevelManager().pushToStringMethod(customToStringMethod); + getLogLevelManager().pushFromStringMethod(customFromStringMethod); + } + + auto i = ll2nm.lower_bound(ll); + if( ( i != ll2nm.end() ) && ( i->first == ll ) && ( i->second != nm ) ) + return false; + + auto j = nm2ll.lower_bound(nm); + if( ( j != nm2ll.end() ) && ( j->first == nm ) && ( j->second != ll ) ) + return false; + + // there is no else after return + ll2nm.insert( i, std::make_pair(ll, nm) ); + nm2ll.insert( j, std::make_pair(nm, ll) ); + return true; + } + + bool remove(LogLevel ll, tstring const &nm) + { + log4cplus::thread::MutexGuard guard (mtx); + + auto i = ll2nm.find(ll); + auto j = nm2ll.find(nm); + if( ( i != ll2nm.end() ) && ( j != nm2ll.end() ) && + ( i->first == j->second ) && ( i->second == j->first ) ) { + ll2nm.erase(i); + nm2ll.erase(j); + + return true; + } + + // there is no else after return + return false; + } + +protected: + tstring const & customToStringMethodWorker(LogLevel ll) + { + log4cplus::thread::MutexGuard guard (mtx); + auto i = ll2nm.find(ll); + if( i != ll2nm.end() ) + return i->second; + + return internal::empty_str; + } + + LogLevel customFromStringMethodWorker(const tstring& nm) + { + log4cplus::thread::MutexGuard guard (mtx); + auto i = nm2ll.find(nm); + if( i != nm2ll.end() ) + return i->second; + + return NOT_SET_LOG_LEVEL; + } + + LOG4CPLUS_PRIVATE static tstring const & customToStringMethod(LogLevel ll); + LOG4CPLUS_PRIVATE static LogLevel customFromStringMethod(const tstring& nm); +}; + +LOG4CPLUS_PRIVATE CustomLogLevelManager & getCustomLogLevelManager (); + +} // namespace internal + +} // namespace log4cplus + + +#endif // LOG4CPLUS_INTERNAL_CUSTOMLOGLEVELMANAGER_HEADER diff --git a/LFtid1056/cloudfront/code/log4cplus/internal/cygwin-win32.h b/LFtid1056/cloudfront/code/log4cplus/internal/cygwin-win32.h new file mode 100644 index 0000000..1b8ae6e --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/internal/cygwin-win32.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: cygwin-win32.h +// Created: 7/2011 +// Author: Vaclav Zeman +// +// Copyright (C) 2011-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_CONFIG_CYGWIN_WIN32_H) +#define LOG4CPLUS_CONFIG_CYGWIN_WIN32_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (__CYGWIN__) + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +namespace log4cplus { namespace cygwin { + +unsigned long get_current_win32_thread_id (); +void output_debug_stringW (wchar_t const *); + +} } // namespace log4cplus { namespace cygwin { + + +#endif // defined (__CYGWIN__) +#endif // LOG4CPLUS_CONFIG_CYGWIN_WIN32_H diff --git a/LFtid1056/cloudfront/code/log4cplus/internal/env.h b/LFtid1056/cloudfront/code/log4cplus/internal/env.h new file mode 100644 index 0000000..549a89f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/internal/env.h @@ -0,0 +1,102 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: env.h +// Created: 7/2010 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_INTERNAL_ENV_H +#define LOG4CPLUS_INTERNAL_ENV_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + +#if defined (_WIN32) +#include +#endif +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LOG4CPLUS_HAVE_UNISTD_H +#include +#endif + + +namespace log4cplus { namespace internal { + + +//! Get environment variable value. +bool get_env_var (tstring & value, tstring const & name); + +//! Get locale. +std::locale get_locale_by_name(tstring const& locale_name); + +//! Parse a string as a boolean value. +bool parse_bool (bool & val, tstring const & str); + +//! Parse a path into path components. +bool split_path (std::vector & components, std::size_t & special, + tstring const & path); + +//! Makes directories leading to file. +void make_dirs (tstring const & file_path); + +inline +#if defined (_WIN32) +DWORD +get_process_id () +{ + return GetCurrentProcessId (); +} + +#elif defined (LOG4CPLUS_HAVE_GETPID) +pid_t +get_process_id () +{ + return getpid (); +} + +#else +int +get_process_id () +{ + return 0; +} + +#endif + + +} } // namespace log4cplus { namespace internal { + + +#endif // LOG4CPLUS_INTERNAL_ENV_H diff --git a/LFtid1056/cloudfront/code/log4cplus/internal/internal.h b/LFtid1056/cloudfront/code/log4cplus/internal/internal.h new file mode 100644 index 0000000..2483d05 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/internal/internal.h @@ -0,0 +1,244 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: internal.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared libray. + */ + + +#ifndef LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ +#define LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + +namespace internal { + + +//! Canonical empty string. It is used when the need to return empty string +//! by reference arises. +extern log4cplus::tstring const empty_str; + + +struct gft_scratch_pad +{ + gft_scratch_pad (); + ~gft_scratch_pad (); + + void + reset () + { + uc_q_str_valid = false; + q_str_valid = false; + s_str_valid = false; + ret.clear (); + } + + log4cplus::tstring q_str; + log4cplus::tstring uc_q_str; + log4cplus::tstring s_str; + log4cplus::tstring ret; + log4cplus::tstring fmt; + log4cplus::tstring tmp; + std::vector buffer; + bool uc_q_str_valid; + bool q_str_valid; + bool s_str_valid; +}; + + +struct appender_sratch_pad +{ + appender_sratch_pad (); + ~appender_sratch_pad (); + + tostringstream oss; + tstring str; + std::string chstr; +}; + + +//! Per thread data. +struct per_thread_data +{ + per_thread_data (); + ~per_thread_data (); + + tstring macros_str; + tostringstream macros_oss; + tostringstream layout_oss; + DiagnosticContextStack ndc_dcs; + MappedDiagnosticContextMap mdc_map; + log4cplus::tstring thread_name; + log4cplus::tstring thread_name2; + gft_scratch_pad gft_sp; + appender_sratch_pad appender_sp; + log4cplus::tstring faa_str; + log4cplus::tstring ll_str; + spi::InternalLoggingEvent forced_log_ev; + std::FILE * fnull; + log4cplus::helpers::snprintf_buf snprintf_buf; +}; + + +per_thread_data * alloc_ptd (); + +// TLS key whose value is pointer struct per_thread_data. +extern log4cplus::thread::impl::tls_key_type tls_storage_key; + + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) \ + && defined (LOG4CPLUS_THREAD_LOCAL_VAR) + +extern LOG4CPLUS_THREAD_LOCAL_VAR per_thread_data * ptd; + + +inline +void +set_ptd (per_thread_data * p) +{ + ptd = p; +} + + +inline +per_thread_data * +get_ptd (bool alloc = true) +{ + if (LOG4CPLUS_UNLIKELY (! ptd && alloc)) + return alloc_ptd (); + + // The assert() does not belong here. get_ptd() might be called by + // cleanup code that can handle the returned NULL pointer. + //assert (ptd); + + return ptd; +} + + +#else // defined (LOG4CPLUS_THREAD_LOCAL_VAR) + + +inline +void +set_ptd (per_thread_data * p) +{ + thread::impl::tls_set_value (tls_storage_key, p); +} + + +inline +per_thread_data * +get_ptd (bool alloc = true) +{ + per_thread_data * ptd + = reinterpret_cast( + thread::impl::tls_get_value (tls_storage_key)); + + if (LOG4CPLUS_UNLIKELY (! ptd && alloc)) + return alloc_ptd (); + + return ptd; +} + + +#endif // defined (LOG4CPLUS_THREAD_LOCAL_VAR) + + +inline +tstring & +get_thread_name_str () +{ + return get_ptd ()->thread_name; +} + + +inline +tstring & +get_thread_name2_str () +{ + return get_ptd ()->thread_name2; +} + + +inline +gft_scratch_pad & +get_gft_scratch_pad () +{ + return get_ptd ()->gft_sp; +} + + +inline +appender_sratch_pad & +get_appender_sp () +{ + return get_ptd ()->appender_sp; +} + + +} // namespace internal { + + +namespace detail +{ + +LOG4CPLUS_EXPORT void clear_tostringstream (tostringstream &); + +} // namespace detail + + +} // namespace log4cplus { + + +#endif // LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/internal/socket.h b/LFtid1056/cloudfront/code/log4cplus/internal/socket.h new file mode 100644 index 0000000..058b48f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/internal/socket.h @@ -0,0 +1,219 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socket.h +// Created: 1/2010 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared libray. + */ + + +#ifndef LOG4CPLUS_INTERNAL_SOCKET_H_ +#define LOG4CPLUS_INTERNAL_SOCKET_H_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#if defined(_WIN32) +#include +#endif +#include + +#include +#ifdef LOG4CPLUS_HAVE_ERRNO_H +#include +#endif + +#ifdef LOG4CPLUS_HAVE_UNISTD_H +#include +#endif + +#if defined (LOG4CPLUS_HAVE_NETDB_H) +#include +#endif + + +namespace log4cplus { + +namespace helpers { + +#if defined(_WIN32) +typedef SOCKET os_socket_type; +os_socket_type const INVALID_OS_SOCKET_VALUE = INVALID_SOCKET; + +struct ADDRINFOT_deleter +{ + void + operator () (ADDRINFOA * ptr) const + { + FreeAddrInfoA(ptr); + } + + void + operator () (ADDRINFOW * ptr) const + { + FreeAddrInfoW(ptr); + } +}; + + +struct socket_closer +{ + void + operator () (SOCKET s) + { + if (s && s != INVALID_OS_SOCKET_VALUE) + { + DWORD const eno = WSAGetLastError(); + ::closesocket(s); + WSASetLastError(eno); + } + } +}; + + +#else +typedef int os_socket_type; +os_socket_type const INVALID_OS_SOCKET_VALUE = -1; + + +struct addrinfo_deleter +{ + void + operator () (struct addrinfo * ptr) const + { + freeaddrinfo(ptr); + } +}; + + +struct socket_closer +{ + void + operator () (os_socket_type s) + { + if (s >= 0) + { + int const eno = errno; + close(s); + errno = eno; + } + } +}; + +#endif + + +struct socket_holder +{ + os_socket_type sock; + + socket_holder() + : sock(INVALID_OS_SOCKET_VALUE) + { } + + socket_holder(os_socket_type s) + : sock(s) + { } + + ~socket_holder() + { + socket_closer()(sock); + } + + void + reset(os_socket_type s = INVALID_OS_SOCKET_VALUE) + { + if (sock != INVALID_OS_SOCKET_VALUE) + socket_closer()(sock); + + sock = s; + } + + os_socket_type + detach() + { + os_socket_type s = sock; + sock = INVALID_OS_SOCKET_VALUE; + return s; + } + + socket_holder(socket_holder &&) = delete; + socket_holder(socket_holder const &) = delete; + + socket_holder operator = (socket_holder &&) = delete; + socket_holder operator = (socket_holder const &) = delete; +}; + + +static inline +os_socket_type +to_os_socket (SOCKET_TYPE const & x) +{ + return static_cast(x); +} + + +static inline +SOCKET_TYPE +to_log4cplus_socket (os_socket_type const & x) +{ + return static_cast(x); +} + + +static inline +void +set_last_socket_error (int err) +{ + errno = err; +} + + +static inline +int +get_last_socket_error () +{ + return errno; +} + + +} // namespace helpers { + +} // namespace log4cplus { + + +#endif // LOG4CPLUS_INTERNAL_SOCKET_H_ diff --git a/LFtid1056/cloudfront/code/log4cplus/layout.h b/LFtid1056/cloudfront/code/log4cplus/layout.h new file mode 100644 index 0000000..a0110e4 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/layout.h @@ -0,0 +1,645 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: Layout.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_LAYOUT_HEADER_ +#define LOG4CPLUS_LAYOUT_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include +#include + + +namespace log4cplus { + + // Forward Declarations + namespace pattern + { + + class PatternConverter; + + } + + + namespace helpers + { + + class Properties; + + } + + + namespace spi + { + + class InternalLoggingEvent; + + } + + + /** + * This class is used to layout strings sent to an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT Layout + { + public: + Layout(); + Layout(const helpers::Properties& properties); + virtual ~Layout() = 0; + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event) = 0; + + protected: + LogLevelManager& llmCache; + + private: + // Disable copy + Layout(const Layout&); + Layout& operator=(Layout const &); + }; + + + + /** + * SimpleLayout consists of the LogLevel of the log statement, + * followed by " - " and then the log message itself. For example, + * + *
+     *         DEBUG - Hello world
+     * 
+ * + * {@link PatternLayout} offers a much more powerful alternative. + */ + class LOG4CPLUS_EXPORT SimpleLayout + : public Layout + { + public: + SimpleLayout(); + SimpleLayout(const log4cplus::helpers::Properties& properties); + virtual ~SimpleLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + SimpleLayout(const SimpleLayout&); + SimpleLayout& operator=(const SimpleLayout&); + }; + + + + /** + * TTCC layout format consists of time, thread, Logger and nested + * diagnostic context information, hence the name. + * + * The time format depends on the DateFormat used. Use the + * Use_gmtime to specify whether messages should be logged + * using localtime or gmtime. There are also + * ThreadPrinting, CategoryPrefixing and + * ContextPrinting properties to turn on and off thread name, + * logger name and NDC context printing respectively. + * + * Here is an example TTCCLayout output: + * + * ~~~~ + * 1 [0x60004dca0] WARN test.TestThread <> - Thread-3 TestThread.run()- Starting... + * 1 [0x60004dca0] TRACE SlowObject - ENTER: SlowObject::doSomething() + * 2 [0x60004b030] INFO SlowObject - Actually doing something...1, 2, 3, testing...DONE + * 2 [0x60004b130] INFO SlowObject - Actually doing something... + * 2 [0x60004b030] TRACE SlowObject - EXIT: SlowObject::doSomething() + * 2 [0x60004b030] TRACE SlowObject - ENTER: SlowObject::doSomething() + * 3 [0x60004b130] INFO SlowObject - Actually doing something...1, 2, 3, testing...DONE + * 3 [0x60004cad0] INFO SlowObject - Actually doing something... + * ~~~~ + * + * The first field is the number of milliseconds elapsed since + * the start of the program. + * + * The second field is the thread outputting the log + * statement. (The value is the same as that of the `t` formatter + * for PatternLayout.) + * + * The third field is the LogLevel. + * + * The fourth field is the logger to which the statement belongs. + * + * The fifth field (just before the '-') is the nested + * diagnostic context. Note the nested diagnostic context may be + * empty as in the first two statements. The text after the '-' + * is the message of the statement. + * + * PatternLayout offers a much more flexible alternative. + */ + class LOG4CPLUS_EXPORT TTCCLayout + : public Layout + { + public: + TTCCLayout(bool use_gmtime = false, bool thread_printing = true, + bool category_prefixes = true, bool context_printing = true); + TTCCLayout(const log4cplus::helpers::Properties& properties); + virtual ~TTCCLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + bool getThreadPrinting() const; + void setThreadPrinting(bool); + + bool getCategoryPrefixing() const; + void setCategoryPrefixing(bool); + + bool getContextPrinting() const; + void setContextPrinting(bool); + + protected: + log4cplus::tstring dateFormat; + bool use_gmtime = false; + bool thread_printing = true; + bool category_prefixing = true; + bool context_printing = true; + + private: + // Disallow copying of instances of this class + TTCCLayout(const TTCCLayout&); + TTCCLayout& operator=(const TTCCLayout&); + }; + + + LOG4CPLUS_EXPORT helpers::Time const & getTTCCLayoutTimeBase (); + + + /** + * A flexible layout configurable with pattern string. + * + * The goal of this class is to format a InternalLoggingEvent and return + * the results as a string. The results depend on the conversion + * pattern. + * + * The conversion pattern is closely related to the conversion + * pattern of the printf function in C. A conversion pattern is + * composed of literal text and format control expressions called + * conversion specifiers. + * + * You are free to insert any literal text within the conversion + * pattern. + * + * Each conversion specifier starts with a percent sign (%%) and is + * followed by optional format modifiers and a conversion + * character. The conversion character specifies the type of + * data, e.g. Logger, LogLevel, date, thread name. The format + * modifiers control such things as field width, padding, left and + * right justification. The following is a simple example. + * + * Let the conversion pattern be `"%-5p [%t]: %m%n"` and assume + * that the log4cplus environment was set to use a PatternLayout. Then the + * statements + * + * ~~~~{.c} + * Logger root = Logger.getRoot(); + * LOG4CPLUS_DEBUG(root, "Message 1"); + * LOG4CPLUS_WARN(root, "Message 2"); + * ~~~~ + * + * would yield the output + * + * ~~~~ + * DEBUG [main]: Message 1 + * WARN [main]: Message 2 + * ~~~~ + * + * Note that there is no explicit separator between text and + * conversion specifiers. The pattern parser knows when it has reached + * the end of a conversion specifier when it reads a conversion + * character. In the example above the conversion specifier + * "%-5p" means the LogLevel of the logging event should be left + * justified to a width of five characters. + * + * The recognized conversion characters are + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Conversion CharacterEffect
bUsed to output file name component of path name. + * E.g. main.cxx from path ../../main.cxx.
cUsed to output the logger of the logging event. The + * logger conversion specifier can be optionally followed by + * precision specifier, that is a decimal constant in + * brackets. + * + * If a precision specifier is given, then only the corresponding + * number of right most components of the logger name will be + * printed. By default the logger name is printed in full. + * + * For example, for the logger name "a.b.c" the pattern + * %c{2} will output "b.c". + * + *
dUsed to output the date of the logging event in UTC. + * + * The date conversion specifier may be followed by a date format + * specifier enclosed between braces. For example, %%d{%%H:%%M:%%s} + * or %%d{%%d %%b %%Y %%H:%%M:%%s}. If no date format + * specifier is given then %%d{%%d %%m %%Y %%H:%%M:%%s} + * is assumed. + * + * The Following format options are possible: + *
    + *
  • %%a -- Abbreviated weekday name
  • + *
  • %%A -- Full weekday name
  • + *
  • %%b -- Abbreviated month name
  • + *
  • %%B -- Full month name
  • + *
  • %%c -- Standard date and time string
  • + *
  • %%d -- Day of month as a decimal(1-31)
  • + *
  • %%H -- Hour(0-23)
  • + *
  • %%I -- Hour(1-12)
  • + *
  • %%j -- Day of year as a decimal(1-366)
  • + *
  • %%m -- Month as decimal(1-12)
  • + *
  • %%M -- Minute as decimal(0-59)
  • + *
  • %%p -- Locale's equivalent of AM or PM
  • + *
  • %%q -- milliseconds as decimal(0-999) -- Log4CPLUS specific + *
  • %%Q -- fractional milliseconds as decimal(0-999.999) -- Log4CPLUS specific + *
  • %%S -- Second as decimal(0-59)
  • + *
  • %%U -- Week of year, Sunday being first day(0-53)
  • + *
  • %%w -- Weekday as a decimal(0-6, Sunday being 0)
  • + *
  • %%W -- Week of year, Monday being first day(0-53)
  • + *
  • %%x -- Standard date string
  • + *
  • %%X -- Standard time string
  • + *
  • %%y -- Year in decimal without century(0-99)
  • + *
  • %%Y -- Year including century as decimal
  • + *
  • %%Z -- Time zone name
  • + *
  • %% -- The percent sign
  • + *
+ * + * Lookup the documentation for the strftime() function + * found in the <ctime> header for more information. + *
DUsed to output the date of the logging event in local time. + * + * All of the above information applies. + *
EUsed to output the value of a given environment variable. The + * name of is supplied as an argument in brackets. If the variable does + * exist then empty string will be used. + * + * For example, the pattern %E{HOME} will output the contents + * of the HOME environment variable. + *
FUsed to output the file name where the logging request was + * issued. + * + * NOTE Unlike log4j, there is no performance penalty for + * calling this method.
hUsed to output the hostname of this system (as returned + * by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
HUsed to output the fully-qualified domain name of this + * system (as returned by gethostbyname(2) for the hostname + * returned by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
lEquivalent to using "%F:%L" + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
LUsed to output the line number from where the logging request + * was issued. + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
mUsed to output the application supplied message associated with + * the logging event.
MUsed to output function name using + * __FUNCTION__ or similar macro. + * + * NOTE The __FUNCTION__ macro is not + * standard but it is common extension provided by all compilers + * (as of 2010). In case it is missing or in case this feature + * is disabled using the + * LOG4CPLUS_DISABLE_FUNCTION_MACRO macro, %M + * expands to an empty string.
nOutputs the platform dependent line separator character or + * characters. + *
pUsed to output the LogLevel of the logging event.
rUsed to output miliseconds since program start + * of the logging event.
tUsed to output the thread ID of the thread that generated + * the logging event. (This is either `pthread_t` value returned + * by `pthread_self()` on POSIX platforms or thread ID returned + * by `GetCurrentThreadId()` on Windows.)
TUsed to output alternative name of the thread that generated the + * logging event.
iUsed to output the process ID of the process that generated the + * logging event.
xUsed to output the NDC (nested diagnostic context) associated + * with the thread that generated the logging event. + *
XUsed to output the MDC (mapped diagnostic context) + * associated with the thread that generated the logging + * event. It takes optional key parameter. Without the key + * paramter (%%X), it outputs the whole MDC map. With the key + * (%%X{key}), it outputs just the key's value. + *
"%%"The sequence "%%" outputs a single percent sign. + *
+ * + * By default the relevant information is output as is. However, + * with the aid of format modifiers it is possible to change the + * minimum field width, the maximum field width and justification. + * + * The optional format modifier is placed between the percent sign + * and the conversion character. + * + * The first optional format modifier is the left justification + * flag which is just the minus (-) character. Then comes the + * optional minimum field width modifier. This is a decimal + * constant that represents the minimum number of characters to + * output. If the data item requires fewer characters, it is padded on + * either the left or the right until the minimum width is + * reached. The default is to pad on the left (right justify) but you + * can specify right padding with the left justification flag. The + * padding character is space. If the data item is larger than the + * minimum field width, the field is expanded to accommodate the + * data. The value is never truncated. + * + * This behavior can be changed using the maximum field + * width modifier which is designated by a period followed by a + * decimal constant. If the data item is longer than the maximum + * field, then the extra characters are removed from the + * beginning of the data item and not from the end. For + * example, it the maximum field width is eight and the data item is + * ten characters long, then the first two characters of the data item + * are dropped. This behavior deviates from the printf function in C + * where truncation is done from the end. + * + * Below are various format modifier examples for the logger + * conversion specifier. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Format modifierleft justifyminimum widthmaximum widthcomment
%20cfalse20noneLeft pad with spaces if the logger name is less than 20 + * characters long. + *
%-20c true 20 none Right pad with + * spaces if the logger name is less than 20 characters long. + *
%.30cNAnone30Truncate from the beginning if the logger name is longer than 30 + * characters. + *
%20.30cfalse2030Left pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
%-20.30ctrue2030Right pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
+ * + * Below are some examples of conversion patterns. + * + *
+ * + *
"%r [%t] %-5p %c %x - %m%n" + *
This is essentially the TTCC layout. + * + *
"%-6r [%15.15t] %-5p %30.30c %x - %m%n" + * + *
Similar to the TTCC layout except that the relative time is + * right padded if less than 6 digits, thread name is right padded if + * less than 15 characters and truncated if longer and the logger + * name is left padded if shorter than 30 characters and truncated if + * longer. + * + *
+ * + * The above text is largely inspired from Peter A. Darnell and + * Philip E. Margolis' highly recommended book "C -- a Software + * Engineering Approach", ISBN 0-387-97389-3. + * + *

Properties

+ * + *
+ *
NDCMaxDepth
+ *
This property limits how many deepest NDC components will + * be printed by %%x specifier.
+ * + *
ConversionPattern
+ *
This property specifies conversion pattern.
+ *
+ * + */ + class LOG4CPLUS_EXPORT PatternLayout + : public Layout + { + public: + // Ctors and dtor + PatternLayout(const log4cplus::tstring& pattern); + PatternLayout(const log4cplus::helpers::Properties& properties); + virtual ~PatternLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + void init(const log4cplus::tstring& pattern, unsigned ndcMaxDepth = 0); + + // Data + log4cplus::tstring pattern; + std::vector > parsedPattern; + + private: + // Disallow copying of instances of this class + PatternLayout(const PatternLayout&); + PatternLayout& operator=(const PatternLayout&); + }; + + + +} // end namespace log4cplus + +#endif // LOG4CPLUS_LAYOUT_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/log4.h b/LFtid1056/cloudfront/code/log4cplus/log4.h new file mode 100644 index 0000000..89b4d6a --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/log4.h @@ -0,0 +1,111 @@ +#ifndef LOG4_H +#define LOG4_H + +#ifdef __cplusplus + +#include +#include + +//防止#include 里的冲突 +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif +//防止#include 里的冲突 + +#include "logger.h" +#include +#include "loggingmacros.h" + +#include "appender.h" + +#define LOGTYPE_COM 1 +#define LOGTYPE_DATA 2 + +struct TypedLogger { + log4cplus::Logger logger; + int logtype; + TypedLogger(); + TypedLogger(const log4cplus::Logger& l, int t); +}; + +struct DebugSwitch { + bool debug_open; + std::set targets; + int min_level; + std::map type_enable; + + DebugSwitch(); + void open(); + void close(); + void set_target(const std::string& name); + void set_level(int level); + void enable_type(int type); + void disable_type(int type); + bool match(const std::string& logger_name, int level, int logtype); +}; + +extern std::map logger_map; +extern DebugSwitch g_debug_switch; + +extern void send_reply_to_queue(const std::string& guid, const std::string& step, const std::string& result); + + +std::string get_front_type_from_subdir(); + + +// 不带 Appender 的版本 +log4cplus::Logger init_logger(const std::string& full_name, + const std::string& file_dir, + const std::string& base_file); + +// 带 Appender 的版本 +log4cplus::Logger init_logger(const std::string& full_name, + const std::string& file_dir, + const std::string& base_file, + log4cplus::SharedAppenderPtr fileAppender); + +void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str); + + +void update_log_entries_countdown(); + +extern "C" { +#endif +void remove_loggers_by_terminal_id(const std::string& terminal_id_cstr); +void init_logger_process(); +void init_loggers(); +void init_loggers_bydevid(const std::string& dev_id); + +void log_debug(const char* key, const char* msg); +void log_info(const char* key, const char* msg); +void log_warn(const char* key, const char* msg); +void log_error(const char* key, const char* msg); + +void send_reply_to_queue_c(const char* guid, const char* step, const char* result); +void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...); + +//宏定义 +#define DIY_LOG(LEVEL_FUNC, KEY, ...) \ + do { \ + char buf[256]; \ + format_log_msg(buf, sizeof(buf), __VA_ARGS__); \ + LEVEL_FUNC(KEY, buf); \ + } while (0) + +#define DIY_ERRORLOG(KEY, ...) DIY_LOG(log_error, KEY, __VA_ARGS__) +#define DIY_WARNLOG(KEY, ...) DIY_LOG(log_warn, KEY, __VA_ARGS__) +#define DIY_INFOLOG(KEY, ...) DIY_LOG(log_info, KEY, __VA_ARGS__) +#define DIY_DEBUGLOG(KEY, ...) DIY_LOG(log_debug, KEY, __VA_ARGS__) + + +#ifdef __cplusplus +} +#endif + + + +#endif // LOG4_H diff --git a/LFtid1056/cloudfront/code/log4cplus/log4cplus.h b/LFtid1056/cloudfront/code/log4cplus/log4cplus.h new file mode 100644 index 0000000..e3ddb32 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/log4cplus.h @@ -0,0 +1,66 @@ +// Copyright (C) 2015-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_LOG4CPLUS_HXX +#define LOG4CPLUS_LOG4CPLUS_HXX + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined (LOG4CPLUS_WITH_UNIT_TESTS) +namespace log4cplus +{ + +LOG4CPLUS_EXPORT int unit_tests_main (int argc, char* argv[]); + +} // namespace log4cplus +#endif + +#endif // LOG4CPLUS_LOG4CPLUS_HXX diff --git a/LFtid1056/cloudfront/code/log4cplus/log4judpappender.h b/LFtid1056/cloudfront/code/log4cplus/log4judpappender.h new file mode 100644 index 0000000..a6422d5 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/log4judpappender.h @@ -0,0 +1,91 @@ +// -*- C++ -*- +// Module: LOG4CPLUS +// File: log4judpappender.h +// Created: 7/2012 +// Author: Siva Chandran P +// +// +// Copyright 2012-2017 Siva Chandran P +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ +#define LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ + +#include +#include +#include + +namespace log4cplus { + + /** + * Sends log events as Log4j XML to a remote a log server. + * + * The Log4jUdpAppender has the following properties: + * + *
    + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client.
  • + * + *
  • Remote logging uses the UDP protocol.
  • + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to. Default is 5000.
+ * + *
IPv6
+ *
Boolean value specifying whether to use IPv6 (true) or IPv4 + * (false). Default value is false.
+ * + *
+ */ + class LOG4CPLUS_EXPORT Log4jUdpAppender : public Appender { + public: + // Ctors + Log4jUdpAppender(const log4cplus::tstring& host, int port, + bool ipv6 = false); + Log4jUdpAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~Log4jUdpAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + int port; + bool ipv6 = false; + + private: + // Disallow copying of instances of this class + Log4jUdpAppender(const Log4jUdpAppender&); + Log4jUdpAppender& operator=(const Log4jUdpAppender&); + }; +} // end namespace log4cplus + +#endif // LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/logger.h b/LFtid1056/cloudfront/code/log4cplus/logger.h new file mode 100644 index 0000000..dbf6d11 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/logger.h @@ -0,0 +1,325 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: logger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the Logger class and the logging macros. */ + +#ifndef LOG4CPLUS_LOGGERHEADER_ +#define LOG4CPLUS_LOGGERHEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + // Forward declarations + + class Appender; + class Hierarchy; + class HierarchyLocker; + class DefaultLoggerFactory; + + namespace spi + { + + class LoggerImpl; + + } + + + /** \typedef std::vector LoggerList + * This is a list of {@link Logger Loggers}. */ + typedef std::vector LoggerList; + + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + */ + class LOG4CPLUS_EXPORT Logger + : public log4cplus::spi::AppenderAttachable + { + public: + // Static Methods + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + static bool exists(const log4cplus::tstring& name); + + /* + * Returns all the currently defined loggers in the default + * hierarchy. + * + * The root logger is not included in the returned + * list. + */ + static LoggerList getCurrentLoggers(); + + /** + * Return the default Hierarchy instance. + */ + static Hierarchy& getDefaultHierarchy(); + + /** + * Retrieve a logger with name name. If the named + * logger already exists, then the existing instance will be returned. + * Otherwise, a new instance is created. + * + * By default, loggers do not have a set LogLevel but inherit + * it from the hierarchy. This is one of the central features of + * log4cplus. + * + * @param name The name of the logger to retrieve. + */ + static Logger getInstance(const log4cplus::tstring& name); + + /** + * Like getInstance() except that the type of logger + * instantiated depends on the type returned by the {@link + * spi::LoggerFactory#makeNewLoggerInstance} method of the + * factory parameter. + * + * This method is intended to be used by sub-classes. + * + * @param name The name of the logger to retrieve. + * @param factory A {@link spi::LoggerFactory} implementation that will + * actually create a new Instance. + */ + static Logger getInstance(const log4cplus::tstring& name, + spi::LoggerFactory& factory); + + /** + * Return the root of the default logger hierrachy. + * + * The root logger is always instantiated and available. It's + * name is "root". + * + * Nevertheless, calling {@link #getInstance + * Logger.getInstance("root")} does not retrieve the root logger + * but a logger just under root named "root". + */ + static Logger getRoot(); + + /** + * Calling this method will safely close and remove all + * appenders in all the loggers including root contained in the + * default hierachy. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + static void shutdown(); + + // Non-Static Methods + /** + * If assertionVal parameter is false, then + * logs msg with FATAL_LOG_LEVEL log level. + * + * @param assertionVal Truth value of assertion condition. + * @param msg The message to print if assertion is + * false. + */ + void assertion(bool assertionVal, const log4cplus::tstring& msg) const; + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + void closeNestedAppenders() const; + + /** + * Check whether this logger is enabled for a given + * LogLevel passed as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + void log(LogLevel ll, const log4cplus::tstring& message, + const char* file = LOG4CPLUS_CALLER_FILE (), + int line = LOG4CPLUS_CALLER_LINE (), + const char* function = LOG4CPLUS_CALLER_FUNCTION ()) const; + + void log(spi::InternalLoggingEvent const &) const; + + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + void forcedLog(LogLevel ll, const log4cplus::tstring& message, + const char* file = LOG4CPLUS_CALLER_FILE (), + int line = LOG4CPLUS_CALLER_LINE (), + const char* function = LOG4CPLUS_CALLER_FUNCTION ()) const; + + void forcedLog(spi::InternalLoggingEvent const &) const; + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event the event to log. + */ + void callAppenders(const spi::InternalLoggingEvent& event) const; + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel, can be NOT_SET_LOG_LEVEL. + */ + LogLevel getLogLevel() const; + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel ll); + + /** + * Return the the {@link Hierarchy} where this Logger instance is + * attached. + */ + Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring const & getName() const; + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + // AppenderAttachable Methods + virtual void addAppender(SharedAppenderPtr newAppender); + + virtual SharedAppenderPtrList getAllAppenders(); + + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + virtual void removeAllAppenders(); + + virtual void removeAppender(SharedAppenderPtr appender); + + virtual void removeAppender(const log4cplus::tstring& name); + + Logger () LOG4CPLUS_NOEXCEPT; + Logger(const Logger& rhs) LOG4CPLUS_NOEXCEPT; + Logger& operator=(const Logger& rhs) LOG4CPLUS_NOEXCEPT; + Logger (Logger && rhs) LOG4CPLUS_NOEXCEPT; + Logger & operator = (Logger && rhs) LOG4CPLUS_NOEXCEPT; + virtual ~Logger(); + + void swap (Logger &) LOG4CPLUS_NOEXCEPT; + + /** + * Used to retrieve the parent of this Logger in the + * Logger tree. + */ + Logger getParent() const; + + protected: + // Data + /** This is a pointer to the implementation class. */ + spi::LoggerImpl * value = nullptr; + + private: + // Ctors + /** + * This constructor created a new Logger instance + * with a pointer to a Logger implementation. + * + * You should not create loggers directly. + * + * @param ptr A pointer to the Logger implementation. This value + * cannot be NULL. + */ + Logger(spi::LoggerImpl * ptr) LOG4CPLUS_NOEXCEPT; + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::Hierarchy; + friend class log4cplus::HierarchyLocker; + friend class log4cplus::DefaultLoggerFactory; + }; + + + /** + * This class is used to create the default implementation of + * the Logger class. + */ + class LOG4CPLUS_EXPORT DefaultLoggerFactory : public spi::LoggerFactory { + public: + Logger makeNewLoggerInstance(const log4cplus::tstring& name, Hierarchy& h); + + protected: + virtual spi::LoggerImpl * makeNewLoggerImplInstance( + const log4cplus::tstring& name, Hierarchy& h); + }; + + +} // end namespace log4cplus + + +#endif // LOG4CPLUS_LOGGERHEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/loggingmacros.h b/LFtid1056/cloudfront/code/log4cplus/loggingmacros.h new file mode 100644 index 0000000..9b8f400 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/loggingmacros.h @@ -0,0 +1,427 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggingmacros.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the logging macros. */ + +#ifndef LOG4CPLUS_LOGGING_MACROS_HEADER_ +#define LOG4CPLUS_LOGGING_MACROS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +#if defined(_MSC_VER) +#define LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + __pragma (warning (push)) \ + __pragma (warning (disable:4127)) + +#define LOG4CPLUS_RESTORE_DOWHILE_WARNING() \ + __pragma (warning (pop)) + +#else +#define LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() /* empty */ +#define LOG4CPLUS_RESTORE_DOWHILE_WARNING() /* empty */ + +#endif + +#define LOG4CPLUS_DOWHILE_NOTHING() \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#if defined(LOG4CPLUS_DISABLE_FATAL) && !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_DISABLE_ERROR +#endif +#if defined(LOG4CPLUS_DISABLE_ERROR) && !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_DISABLE_WARN +#endif +#if defined(LOG4CPLUS_DISABLE_WARN) && !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_DISABLE_INFO +#endif +#if defined(LOG4CPLUS_DISABLE_INFO) && !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DISABLE_DEBUG +#endif +#if defined(LOG4CPLUS_DISABLE_DEBUG) && !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_DISABLE_TRACE +#endif + + +namespace log4cplus +{ + +namespace detail +{ + + +inline +Logger +macros_get_logger (Logger const & logger) +{ + return logger; +} + + +inline +Logger const & +macros_get_logger (Logger & logger) +{ + return logger; +} + + +inline +Logger +macros_get_logger (Logger && logger) +{ + return std::move (logger); +} + +inline +Logger +macros_get_logger (tstring const & logger) +{ + return Logger::getInstance (logger); +} + + +inline +Logger +macros_get_logger (tchar const * logger) +{ + return Logger::getInstance (logger); +} + + +LOG4CPLUS_EXPORT void clear_tostringstream (tostringstream &); + + +LOG4CPLUS_EXPORT log4cplus::tostringstream & get_macro_body_oss (); +LOG4CPLUS_EXPORT log4cplus::helpers::snprintf_buf & get_macro_body_snprintf_buf (); +LOG4CPLUS_EXPORT void macro_forced_log (log4cplus::Logger const &, + log4cplus::LogLevel, log4cplus::tstring const &, char const *, int, + char const *); +LOG4CPLUS_EXPORT void macro_forced_log (log4cplus::Logger const &, + log4cplus::LogLevel, log4cplus::tchar const *, char const *, int, + char const *); + + + +} // namespace detail + +} // namespace log4cplus + + +#undef LOG4CPLUS_MACRO_FUNCTION +#define LOG4CPLUS_MACRO_FUNCTION() nullptr +#if ! defined (LOG4CPLUS_DISABLE_FUNCTION_MACRO) +# if defined (LOG4CPLUS_HAVE_FUNCSIG_MACRO) +# undef LOG4CPLUS_MACRO_FUNCTION +# define LOG4CPLUS_MACRO_FUNCTION() __FUNCSIG__ +# elif defined (LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO) +# undef LOG4CPLUS_MACRO_FUNCTION +# define LOG4CPLUS_MACRO_FUNCTION() __PRETTY_FUNCTION__ +# elif defined (LOG4CPLUS_HAVE_FUNCTION_MACRO) +# undef LOG4CPLUS_MACRO_FUNCTION +# define LOG4CPLUS_MACRO_FUNCTION() __FUNCTION__ +# elif defined (LOG4CPLUS_HAVE_FUNC_SYMBOL) +# undef LOG4CPLUS_MACRO_FUNCTION +# define LOG4CPLUS_MACRO_FUNCTION() __func__ +# endif +#endif + +#undef LOG4CPLUS_MACRO_FILE +#define LOG4CPLUS_MACRO_FILE() nullptr +#if ! defined (LOG4CPLUS_DISABLE_FILE_MACRO) +# undef LOG4CPLUS_MACRO_FILE +# define LOG4CPLUS_MACRO_FILE() __FILE__ +#endif + + +// Make TRACE and DEBUG log level unlikely and INFO, WARN, ERROR and +// FATAL log level likely. +#define LOG4CPLUS_MACRO_TRACE_LOG_LEVEL(pred) \ + LOG4CPLUS_UNLIKELY (pred) +#define LOG4CPLUS_MACRO_DEBUG_LOG_LEVEL(pred) \ + LOG4CPLUS_UNLIKELY (pred) +#define LOG4CPLUS_MACRO_INFO_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_WARN_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_ERROR_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_FATAL_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) + + +//! Dispatch to LOG4CPLUS_MACRO_LOGLEVEL_* depending on log level. +#define LOG4CPLUS_MACRO_LOGLEVEL_PRED(pred, logLevel) \ + LOG4CPLUS_MACRO_ ## logLevel (pred) + + +// Either use temporary instances of ostringstream +// and snprintf_buf, or use thread-local instances. +#if defined (LOG4CPLUS_MACRO_DISABLE_TLS) +# define LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var) \ + log4cplus::tostringstream var + +# define LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var) \ + log4cplus::helpers::snprintf_buf var + +#else +# define LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var) \ + log4cplus::tostringstream & var \ + = log4cplus::detail::get_macro_body_oss () + +# define LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var) \ + log4cplus::helpers::snprintf_buf & var \ + = log4cplus::detail::get_macro_body_snprintf_buf () + +#endif + + +#define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); \ + _log4cplus_buf << logEvent; \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _log4cplus_buf.str(), \ + LOG4CPLUS_MACRO_FILE (), __LINE__, \ + LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + + +#define LOG4CPLUS_MACRO_STR_BODY(logger, logEvent, logLevel) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, logEvent, \ + LOG4CPLUS_MACRO_FILE (), __LINE__, \ + LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#define LOG4CPLUS_MACRO_FMT_BODY(logger, logLevel, ...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF (_snpbuf); \ + log4cplus::tchar const * _logEvent \ + = _snpbuf.print (__VA_ARGS__); \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _logEvent, \ + LOG4CPLUS_MACRO_FILE (), __LINE__, \ + LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +/** + * @def LOG4CPLUS_TRACE(logger, logEvent) This macro creates a + * TraceLogger to log a TRACE_LOG_LEVEL message to logger + * upon entry and exiting of a method. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) \ + log4cplus::TraceLogger _log4cplus_trace_logger(logger, logEvent, \ + LOG4CPLUS_MACRO_FILE (), __LINE__, \ + LOG4CPLUS_MACRO_FUNCTION ()); +#define LOG4CPLUS_TRACE(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, TRACE_LOG_LEVEL) +#define LOG4CPLUS_TRACE_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, TRACE_LOG_LEVEL) +#define LOG4CPLUS_TRACE_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, TRACE_LOG_LEVEL, __VA_ARGS__) + +#else +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE_FMT(logger, logFmt, ...) LOG4CPLUS_DOWHILE_NOTHING() + +#endif + +/** + * @def LOG4CPLUS_DEBUG(logger, logEvent) This macro is used to log a + * DEBUG_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DEBUG(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, DEBUG_LOG_LEVEL) +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, DEBUG_LOG_LEVEL) +#define LOG4CPLUS_DEBUG_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, DEBUG_LOG_LEVEL, __VA_ARGS__) + +#else +#define LOG4CPLUS_DEBUG(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_DEBUG_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() + +#endif + +/** + * @def LOG4CPLUS_INFO(logger, logEvent) This macro is used to log a + * INFO_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_INFO(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO_LOG_LEVEL) +#define LOG4CPLUS_INFO_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, INFO_LOG_LEVEL) +#define LOG4CPLUS_INFO_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, INFO_LOG_LEVEL, __VA_ARGS__) + +#else +#define LOG4CPLUS_INFO(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_INFO_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_INFO_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() + +#endif + +/** + * @def LOG4CPLUS_WARN(logger, logEvent) This macro is used to log a + * WARN_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_WARN(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, WARN_LOG_LEVEL) +#define LOG4CPLUS_WARN_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, WARN_LOG_LEVEL) +#define LOG4CPLUS_WARN_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, WARN_LOG_LEVEL, __VA_ARGS__) + +#else +#define LOG4CPLUS_WARN(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_WARN_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_WARN_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() + +#endif + +/** + * @def LOG4CPLUS_ERROR(logger, logEvent) This macro is used to log a + * ERROR_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_ERROR(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, ERROR_LOG_LEVEL) +#define LOG4CPLUS_ERROR_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, ERROR_LOG_LEVEL) +#define LOG4CPLUS_ERROR_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, ERROR_LOG_LEVEL, __VA_ARGS__) + +#else +#define LOG4CPLUS_ERROR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_ERROR_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_ERROR_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() + +#endif + +/** + * @def LOG4CPLUS_FATAL(logger, logEvent) This macro is used to log a + * FATAL_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_FATAL) +#define LOG4CPLUS_FATAL(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, FATAL_LOG_LEVEL) +#define LOG4CPLUS_FATAL_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, FATAL_LOG_LEVEL) +#define LOG4CPLUS_FATAL_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, FATAL_LOG_LEVEL, __VA_ARGS__) + +#else +#define LOG4CPLUS_FATAL(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_FATAL_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_FATAL_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() + +#endif + +//! Helper macro for LOG4CPLUS_ASSERT() macro. +#define LOG4CPLUS_ASSERT_STRINGIFY(X) #X + +//! If the `condition` evaluates false, this macro logs it using FATAL +//! log level, including the `condition`'s source text. +#define LOG4CPLUS_ASSERT(logger, condition) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + if (LOG4CPLUS_UNLIKELY(! (condition))) \ + LOG4CPLUS_FATAL_STR ((logger), \ + LOG4CPLUS_TEXT ("failed condition: ") \ + LOG4CPLUS_TEXT (LOG4CPLUS_ASSERT_STRINGIFY (condition))); \ + } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +//! If the `condition` evaluates false, this macro logs a message +//! formatted from `printf` format string passed in 3rd and remaining +//! arguments. +#define LOG4CPLUS_ASSERT_FMT(logger, condition, ...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + if (! (condition)) [[unlikely]] { \ + LOG4CPLUS_FATAL_FMT ((logger), __VA_ARGS__); \ + } \ + } while (false) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +//! If the `condition` evaluates false, this macro logs a message +//! formatted from `std::format` format string passed in 3rd and remaining +//! arguments. +#define LOG4CPLUS_ASSERT_FORMAT(logger, condition, ...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + if (! (condition)) [[unlikely]] { \ + LOG4CPLUS_FATAL_FORMAT ((logger), __VA_ARGS__); \ + } \ + } while (false) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#endif /* LOG4CPLUS_LOGGING_MACROS_HEADER_ */ diff --git a/LFtid1056/cloudfront/code/log4cplus/loglevel.h b/LFtid1056/cloudfront/code/log4cplus/loglevel.h new file mode 100644 index 0000000..5f4a814 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/loglevel.h @@ -0,0 +1,200 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loglevel.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the LogLevel type. + */ + +#ifndef LOG4CPLUS_LOGLEVEL_HEADER_ +#define LOG4CPLUS_LOGLEVEL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + + /** + * \typedef int LogLevel + * Defines the minimum set of priorities recognized by the system, + * that is {@link #FATAL_LOG_LEVEL}, {@link #ERROR_LOG_LEVEL}, {@link + * #WARN_LOG_LEVEL}, {@link #INFO_LOG_LEVEL}, {@link #DEBUG_LOG_LEVEL}, + * and {@link #TRACE_LOG_LEVEL}. + */ + typedef int LogLevel; + + /** \var const LogLevel OFF_LOG_LEVEL + * The OFF_LOG_LEVEL LogLevel is used during configuration to + * turn off logging. */ + const LogLevel OFF_LOG_LEVEL = 60000; + + /** \var const LogLevel FATAL_LOG_LEVEL + * The FATAL_LOG_LEVEL LogLevel designates very severe error + * events that will presumably lead the application to abort. */ + const LogLevel FATAL_LOG_LEVEL = 50000; + + /** \var const LogLevel ERROR_LOG_LEVEL + * The ERROR_LOG_LEVEL LogLevel designates error events that + * might still allow the application to continue running. */ + const LogLevel ERROR_LOG_LEVEL = 40000; + + /** \var const LogLevel WARN_LOG_LEVEL + * The WARN_LOG_LEVEL LogLevel designates potentially harmful + * situations. */ + const LogLevel WARN_LOG_LEVEL = 30000; + + /** \var const LogLevel INFO_LOG_LEVEL + * The INFO_LOG_LEVEL LogLevel designates informational + * messages that highlight the progress of the application at + * coarse-grained level. */ + const LogLevel INFO_LOG_LEVEL = 20000; + + /** \var const LogLevel DEBUG_LOG_LEVEL + * The DEBUG_LOG_LEVEL LogLevel designates fine-grained + * informational events that are most useful to debug an application. */ + const LogLevel DEBUG_LOG_LEVEL = 10000; + + /** \var const LogLevel TRACE_LOG_LEVEL + * The TRACE_LOG_LEVEL LogLevel is used to "trace" entry + * and exiting of methods. */ + const LogLevel TRACE_LOG_LEVEL = 0; + + /** \var const LogLevel ALL_LOG_LEVEL + * The ALL_LOG_LEVEL LogLevel is used during configuration to + * turn on all logging. */ + const LogLevel ALL_LOG_LEVEL = TRACE_LOG_LEVEL; + + /** \var const LogLevel NOT_SET_LOG_LEVEL + * The NOT_SET_LOG_LEVEL LogLevel is used to indicated that + * no particular LogLevel is desired and that the default should be used. + */ + const LogLevel NOT_SET_LOG_LEVEL = -1; + + + /** + * This method type defined the signature of methods that convert LogLevels + * into strings. + * + * Note: Must return an empty tstring for unrecognized values. + */ + typedef log4cplus::tstring const & (*LogLevelToStringMethod)(LogLevel); + + + /** + * This method type defined the signature of methods that convert strings + * into LogLevels. + * + * Note: Must return NOT_SET_LOG_LEVEL for unrecognized values. + */ + typedef LogLevel (*StringToLogLevelMethod)(const log4cplus::tstring&); + + + + /** + * This class is used to "manage" LogLevel definitions. This class is also + * how "derived" LogLevels are created. Here are the steps to creating a + * "derived" LogLevel: + *
    + *
  1. Create a LogLevel constant (greater than 0)
  2. + *
  3. Define a string to represent that constant
  4. + *
  5. Implement a LogLevelToStringMethod method.
  6. + *
  7. Implement a StringToLogLevelMethod method.
  8. + *
  9. create a "static initializer" that registers those 2 methods + * with the LogLevelManager singleton.
  10. + *
+ */ + class LOG4CPLUS_EXPORT LogLevelManager { + public: + LogLevelManager(); + ~LogLevelManager(); + + /** + * This method is called by all Layout classes to convert a LogLevel + * into a string. + * + * Note: It traverses the list of LogLevelToStringMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + log4cplus::tstring const & toString(LogLevel ll) const; + + /** + * This method is called by all classes internally to log4cplus to + * convert a string into a LogLevel. + * + * Note: It traverses the list of StringToLogLevelMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + LogLevel fromString(const log4cplus::tstring& arg) const; + + /** + * When creating a "derived" LogLevel, a LogLevelToStringMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushFromStringMethod + */ + void pushToStringMethod(LogLevelToStringMethod newToString); + + /** + * When creating a "derived" LogLevel, a StringToLogLevelMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushToStringMethod + */ + void pushFromStringMethod(StringToLogLevelMethod newFromString); + + private: + // Data + struct LogLevelToStringMethodRec + { + LogLevelToStringMethodRec (); + LogLevelToStringMethodRec (LogLevelToStringMethod); + + LogLevelToStringMethod func; + }; + + typedef std::vector LogLevelToStringMethodList; + LogLevelToStringMethodList toStringMethods; + + typedef std::vector StringToLogLevelMethodList; + StringToLogLevelMethodList fromStringMethods; + + // Disable Copy + LogLevelManager(const LogLevelManager&); + LogLevelManager& operator=(const LogLevelManager&); + }; + + /** + * Returns the singleton LogLevelManager. + */ + LOG4CPLUS_EXPORT LogLevelManager& getLogLevelManager(); + +} + + +#endif // LOG4CPLUS_LOGLEVEL_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/mdc.h b/LFtid1056/cloudfront/code/log4cplus/mdc.h new file mode 100644 index 0000000..4951298 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/mdc.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_MDC_H_HEADER +#define LOG4CPLUS_MDC_H_HEADER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include + + +namespace log4cplus +{ + + +typedef std::map MappedDiagnosticContextMap; + + +class LOG4CPLUS_EXPORT MDC +{ +public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + */ + void clear(); + + void put (tstring const & key, tstring const & value); + bool get (tstring * value, tstring const & key) const; + void remove (tstring const & key); + + MappedDiagnosticContextMap const & getContext () const; + + // Public ctor and dtor but only to be used by internal::DefaultContext. + MDC (); + virtual ~MDC (); + +private: + LOG4CPLUS_PRIVATE static MappedDiagnosticContextMap * getPtr (); +}; + + +LOG4CPLUS_EXPORT MDC & getMDC (); + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_MDC_H_HEADER diff --git a/LFtid1056/cloudfront/code/log4cplus/msttsappender.h b/LFtid1056/cloudfront/code/log4cplus/msttsappender.h new file mode 100644 index 0000000..3479725 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/msttsappender.h @@ -0,0 +1,112 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: msttsappender.h +// Created: 10/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_MSTTSAPPENDER_H +#define LOG4CPLUS_MSTTSAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +#if defined (_WIN32) + #if defined (log4cplusqt4debugappender_EXPORTS) \ + || defined (log4cplusqt4debugappenderU_EXPORTS) \ + || (defined (DLL_EXPORT) && defined (INSIDE_LOG4CPLUS_MSTTSAPPENDER)) + #undef LOG4CPLUS_MSTTSAPPENDER_BUILD_DLL + #define LOG4CPLUS_MSTTSAPPENDER_BUILD_DLL + #endif + #if defined (LOG4CPLUS_MSTTSAPPENDER_BUILD_DLL) + #if defined (INSIDE_LOG4CPLUS_MSTTSAPPENDER) + #define LOG4CPLUS_MSTTSAPPENDER_EXPORT __declspec(dllexport) + #else + #define LOG4CPLUS_MSTTSAPPENDER_EXPORT __declspec(dllimport) + #endif + #else + #define LOG4CPLUS_MSTTSAPPENDER_EXPORT + #endif +#else + #if defined (INSIDE_LOG4CPLUS_MSTTSAPPENDER) + #define LOG4CPLUS_MSTTSAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_EXPORT + #else + #define LOG4CPLUS_MSTTSAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_IMPORT + #endif // defined (INSIDE_LOG4CPLUS_MSTTSAPPENDER) +#endif // !_WIN32 + + +namespace log4cplus +{ + + +class LOG4CPLUS_MSTTSAPPENDER_EXPORT MSTTSAppender + : public Appender +{ +public: + MSTTSAppender (); + explicit MSTTSAppender (helpers::Properties const &); + virtual ~MSTTSAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + struct Data; + + Data * data; + +private: + LOG4CPLUS_PRIVATE void init (long const * rate = 0, + unsigned long const * volume = 0, bool speak_punc = false, + bool async = false); + + MSTTSAppender (MSTTSAppender const &); + MSTTSAppender & operator = (MSTTSAppender const &); +}; + + +typedef helpers::SharedObjectPtr MSTTSAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_MSTTSAPPENDER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/ndc.h b/LFtid1056/cloudfront/code/log4cplus/ndc.h new file mode 100644 index 0000000..4fbf214 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/ndc.h @@ -0,0 +1,329 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: ndc.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defined the NDC class. + */ + +#ifndef _LO4CPLUS_NDC_HEADER_ +#define _LO4CPLUS_NDC_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + // Forward declarations + struct DiagnosticContext; + typedef std::deque DiagnosticContextStack; + + /** + * The NDC class implements nested diagnostic contexts as + * defined by Neil Harrison in the article "Patterns for Logging + * Diagnostic Messages" part of the book "Pattern Languages of + * Program Design 3" edited by Martin et al. + * + * A Nested Diagnostic Context, or NDC in short, is an instrument + * to distinguish interleaved log output from different sources. Log + * output is typically interleaved when a server handles multiple + * clients near-simultaneously. + * + * Interleaved log output can still be meaningful if each log entry + * from different contexts had a distinctive stamp. This is where NDCs + * come into play. + * + * Note that NDCs are managed on a per thread + * basis. NDC operations such as {@link #push}, {@link + * #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth} + * affect the NDC of the current thread only. NDCs of other + * threads remain unaffected. + * + * For example, a server can build a per client request NDC + * consisting the clients host name and other information contained in + * the the request. Cookies are another source of distinctive + * information. To build an NDC one uses the {@link #push} + * operation. Simply put, + * + * - Contexts can be nested. + * - When entering a context, call `push()`. As a side effect, if + * there is no nested diagnostic context for the current thread, + * this method will create it. + * - When leaving a context, call `pop()`. + * - When exiting a thread make sure to call `remove()`. + * + * There is no penalty for forgetting to match each push() + * operation with a corresponding pop(), except the obvious + * mismatch between the real application context and the context + * set in the NDC. Use of the NDCContextCreator class can + * automate this process and make your code exception-safe. + * + * If configured to do so, {@link log4cplus::PatternLayout} and + * {@link log4cplus::TTCCLayout} instances automatically retrieve + * the nested diagnostic context for the current thread without + * any user intervention. Hence, even if a server is serving + * multiple clients simultaneously, the logs emanating from the + * same code (belonging to the same logger) can still be + * distinguished because each client request will have a different + * NDC tag. + * + * Heavy duty systems should call the {@link #remove} method when + * leaving the run method of a thread. This ensures that the memory + * used by the thread can be freed. + * + * A thread may inherit the nested diagnostic context of another + * (possibly parent) thread using the {@link #inherit inherit} + * method. A thread may obtain a copy of its NDC with the {@link + * #cloneStack cloneStack} method and pass the reference to any other + * thread, in particular to a child. + */ + class LOG4CPLUS_EXPORT NDC + { + public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + * + * This method is equivalent to calling the {@link #setMaxDepth} + * method with a zero maxDepth argument. + */ + void clear(); + + /** + * Clone the diagnostic context for the current thread. + * + * Internally a diagnostic context is represented as a stack. A + * given thread can supply the stack (i.e. diagnostic context) to a + * child thread so that the child can inherit the parent thread's + * diagnostic context. + * + * The child thread uses the {@link #inherit inherit} method to + * inherit the parent's diagnostic context. + * + * @return Stack A clone of the current thread's diagnostic context. + */ + DiagnosticContextStack cloneStack() const; + + /** + * Inherit the diagnostic context of another thread. + * + * The parent thread can obtain a reference to its diagnostic + * context using the {@link #cloneStack} method. It should + * communicate this information to its child so that it may inherit + * the parent's diagnostic context. + * + * The parent's diagnostic context is cloned before being + * inherited. In other words, once inherited, the two diagnostic + * contexts can be managed independently. + * + * @param stack The diagnostic context of the parent thread. + */ + void inherit(const DiagnosticContextStack& stack); + + /** + * Used when printing the diagnostic context. + */ + log4cplus::tstring const & get() const; + + /** + * Get the current nesting depth of this diagnostic context. + * + * @see #setMaxDepth + */ + std::size_t getDepth() const; + + /** + * Clients should call this method before leaving a diagnostic + * context. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string is returned. If + * each call to `push()` is paired with a call to `pop()` + * (even in presence of thrown exceptions), the last `pop()` + * call frees the memory used by NDC for this + * thread. Otherwise, `remove()` must be called at the end of + * the thread to free the memory used by NDC for the thread. + * + * @return String The innermost diagnostic context. + * + * @see NDCContextCreator, remove(), push() + */ + log4cplus::tstring pop(); + + /** + * Same as pop() but without the return value. + */ + void pop_void (); + + /** + * Looks at the last diagnostic context at the top of this NDC + * without removing it. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string is returned. + * + * @return String The innermost diagnostic context. + */ + log4cplus::tstring const & peek() const; + + /** + * Push new diagnostic context information for the current thread. + * + * The contents of the message parameter is + * determined solely by the client. Each call to push() should + * be paired with a call to pop(). + * + * @param message The new diagnostic context information. + * + * @see NDCContextCreator, pop(), remove() + */ + void push(const log4cplus::tstring& message); + void push(tchar const * message); + + /** + * Remove the diagnostic context for this thread. + * + * Each thread that created a diagnostic context by calling + * push() should call this method before exiting. Otherwise, + * the memory used by the thread cannot be reclaimed. It is + * possible to omit this call if and only if each push() call + * is always paired with a pop() call (even in presence of + * thrown exceptions). Then the memory used by NDC will be + * returned by the last pop() call and a call to remove() will + * be no-op. + */ + void remove(); + + /** + * Set maximum depth of this diagnostic context. If the + * current depth is smaller or equal to `maxDepth`, then no + * action is taken. + * + * This method is a convenient alternative to multiple `pop()` + * calls. Moreover, it is often the case that at the end of + * complex call sequences, the depth of the NDC is + * unpredictable. The `setMaxDepth()` method circumvents this + * problem. + * + * For example, the combination + * + * ~~~~{.c} + * void foo() { + * NDC & ndc = getNDC(); + * std::size_t depth = ndc.getDepth(); + * //... complex sequence of calls + * ndc.setMaxDepth(depth); + * } + * ~~~~ + * + * ensures that between the entry and exit of foo the depth of the + * diagnostic stack is conserved. + * + * \note Use of the NDCContextCreator class will solve this + * particular problem. + * + * \see NDC::getDepth() + */ + void setMaxDepth(std::size_t maxDepth); + + // Public ctor but only to be used by internal::DefaultContext. + NDC(); + + // Dtor + virtual ~NDC(); + + private: + // Methods + LOG4CPLUS_PRIVATE static DiagnosticContextStack* getPtr(); + + template + LOG4CPLUS_PRIVATE + void push_worker (StringType const &); + + // Disallow construction (and copying) except by getNDC() + NDC(const NDC&); + NDC& operator=(const NDC&); + }; + + + /** + * Return a reference to the singleton object. + */ + LOG4CPLUS_EXPORT NDC& getNDC(); + + + /** + * This is the internal object that is stored on the NDC stack. + */ + struct LOG4CPLUS_EXPORT DiagnosticContext + { + // Ctors + DiagnosticContext(const log4cplus::tstring& message, + DiagnosticContext const * parent); + DiagnosticContext(tchar const * message, + DiagnosticContext const * parent); + DiagnosticContext(const log4cplus::tstring& message); + DiagnosticContext(tchar const * message); + DiagnosticContext(DiagnosticContext const &); + DiagnosticContext & operator = (DiagnosticContext const &); + DiagnosticContext(DiagnosticContext &&); + DiagnosticContext & operator = (DiagnosticContext &&); + + void swap (DiagnosticContext &); + + // Data + log4cplus::tstring message; /*!< The message at this context level. */ + log4cplus::tstring fullMessage; /*!< The entire message stack. */ + }; + + + /** + * This class ensures that a `NDC::push()` call is always matched + * with a `NDC::pop()` call even in the face of exceptions. + */ + class LOG4CPLUS_EXPORT NDCContextCreator { + public: + /** Pushes msg onto the NDC stack. */ + explicit NDCContextCreator(const log4cplus::tstring& msg); + explicit NDCContextCreator(tchar const * msg); + + NDCContextCreator() = delete; + NDCContextCreator(NDCContextCreator const &) = delete; + NDCContextCreator(NDCContextCreator &&) = delete; + NDCContextCreator & operator= (NDCContextCreator const &) = delete; + NDCContextCreator & operator= (NDCContextCreator &&) = delete; + + /** Pops the NDC stack. */ + ~NDCContextCreator(); + }; + +} // end namespace log4cplus + + +#endif // _LO4CPLUS_NDC_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/nteventlogappender.h b/LFtid1056/cloudfront/code/log4cplus/nteventlogappender.h new file mode 100644 index 0000000..2d8829f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/nteventlogappender.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: nteventlogappender.h +// Created: 4/2003 +// Author: Michael CATANZARITI +// +// Copyright 2003-2017 Michael CATANZARITI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ +#define LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG) + +#include +#include + + +namespace log4cplus { + + /** + * Appends log events to NT EventLog. + */ + class LOG4CPLUS_EXPORT NTEventLogAppender : public Appender { + public: + // ctors + NTEventLogAppender(const log4cplus::tstring& server, + const log4cplus::tstring& log, + const log4cplus::tstring& source); + NTEventLogAppender(const log4cplus::helpers::Properties & properties); + + // dtor + virtual ~NTEventLogAppender(); + + // public Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + virtual WORD getEventType(const spi::InternalLoggingEvent& event); + virtual WORD getEventCategory(const spi::InternalLoggingEvent& event); + void init(); + + /* + * Add this source with appropriate configuration keys to the registry. + */ + void addRegistryInfo(); + + // Data + log4cplus::tstring server; + log4cplus::tstring log; + log4cplus::tstring source; + HANDLE hEventLog; + SID* pCurrentUserSID; + + private: + // Disallow copying of instances of this class + NTEventLogAppender(const NTEventLogAppender&); + NTEventLogAppender& operator=(const NTEventLogAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_NT_EVENT_LOG +#endif //LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/nullappender.h b/LFtid1056/cloudfront/code/log4cplus/nullappender.h new file mode 100644 index 0000000..18e7696 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/nullappender.h @@ -0,0 +1,65 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: nullappender.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_NULL_APPENDER_HEADER_ +#define LOG4CPLUS_NULL_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { + + /** + * Appends log events to a file. + */ + class LOG4CPLUS_EXPORT NullAppender : public Appender { + public: + // Ctors + NullAppender(); + NullAppender(const log4cplus::helpers::Properties&); + + // Dtor + virtual ~NullAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + NullAppender(const NullAppender&); + NullAppender& operator=(const NullAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_NULL_APPENDER_HEADER_ + diff --git a/LFtid1056/cloudfront/code/log4cplus/qt4debugappender.h b/LFtid1056/cloudfront/code/log4cplus/qt4debugappender.h new file mode 100644 index 0000000..177dbda --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/qt4debugappender.h @@ -0,0 +1,103 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: qt4debugappender.h +// Created: 5/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_QT4DEBUGAPPENDER_H +#define LOG4CPLUS_QT4DEBUGAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (_WIN32) + #if defined (log4cplusqt4debugappender_EXPORTS) \ + || defined (log4cplusqt4debugappenderU_EXPORTS) \ + || (defined (DLL_EXPORT) && defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER)) + #undef LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL + #define LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL + #endif + #if defined (LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL) + #if defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT __declspec(dllexport) + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT __declspec(dllimport) + #endif + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT + #endif +#else + #if defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_EXPORT + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_IMPORT + #endif // defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) +#endif // !_WIN32 + + +namespace log4cplus +{ + + +class LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT Qt4DebugAppender + : public Appender +{ +public: + Qt4DebugAppender (); + explicit Qt4DebugAppender (helpers::Properties const &); + virtual ~Qt4DebugAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + +private: + Qt4DebugAppender (Qt4DebugAppender const &); + Qt4DebugAppender & operator = (Qt4DebugAppender const &); +}; + + +typedef helpers::SharedObjectPtr Qt4DebugAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_QT4DEBUGAPPENDER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/qt5debugappender.h b/LFtid1056/cloudfront/code/log4cplus/qt5debugappender.h new file mode 100644 index 0000000..e14bf23 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/qt5debugappender.h @@ -0,0 +1,103 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: qt5debugappender.h +// Created: 4/2013 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2013-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_QT5DEBUGAPPENDER_H +#define LOG4CPLUS_QT5DEBUGAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (_WIN32) + #if defined (log4cplusqt5debugappender_EXPORTS) \ + || defined (log4cplusqt5debugappenderU_EXPORTS) \ + || (defined (DLL_EXPORT) && defined (INSIDE_LOG4CPLUS_QT5DEBUGAPPENDER)) + #undef LOG4CPLUS_QT5DEBUGAPPENDER_BUILD_DLL + #define LOG4CPLUS_QT5DEBUGAPPENDER_BUILD_DLL + #endif + #if defined (LOG4CPLUS_QT5DEBUGAPPENDER_BUILD_DLL) + #if defined (INSIDE_LOG4CPLUS_QT5DEBUGAPPENDER) + #define LOG4CPLUS_QT5DEBUGAPPENDER_EXPORT __declspec(dllexport) + #else + #define LOG4CPLUS_QT5DEBUGAPPENDER_EXPORT __declspec(dllimport) + #endif + #else + #define LOG4CPLUS_QT5DEBUGAPPENDER_EXPORT + #endif +#else + #if defined (INSIDE_LOG4CPLUS_QT5DEBUGAPPENDER) + #define LOG4CPLUS_QT5DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_EXPORT + #else + #define LOG4CPLUS_QT5DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_IMPORT + #endif // defined (INSIDE_LOG4CPLUS_QT5DEBUGAPPENDER) +#endif // !_WIN32 + + +namespace log4cplus +{ + + +class LOG4CPLUS_QT5DEBUGAPPENDER_EXPORT Qt5DebugAppender + : public Appender +{ +public: + Qt5DebugAppender (); + explicit Qt5DebugAppender (helpers::Properties const &); + virtual ~Qt5DebugAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + +private: + Qt5DebugAppender (Qt5DebugAppender const &); + Qt5DebugAppender & operator = (Qt5DebugAppender const &); +}; + + +typedef helpers::SharedObjectPtr Qt5DebugAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_QT5DEBUGAPPENDER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/socketappender.h b/LFtid1056/cloudfront/code/log4cplus/socketappender.h new file mode 100644 index 0000000..f0dd564 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/socketappender.h @@ -0,0 +1,164 @@ +// -*- C++ -*- +// Module: LOG4CPLUS +// File: socketappender.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SOCKET_APPENDER_HEADER_ +#define LOG4CPLUS_SOCKET_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + +#ifndef UNICODE + std::size_t const LOG4CPLUS_MAX_MESSAGE_SIZE = 8*1024; +#else + std::size_t const LOG4CPLUS_MAX_MESSAGE_SIZE = 2*8*1024; +#endif + + + /** + * Sends {@link spi::InternalLoggingEvent} objects to a remote a log server. + * + * The SocketAppender has the following properties: + * + *
    + * + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client. + * + *
  • SocketAppenders do not use a layout. + * + *
  • Remote logging uses the TCP protocol. Consequently, if + * the server is reachable, then log events will eventually arrive + * at the server. + * + *
  • If the remote server is down, the logging requests are + * simply dropped. However, if and when the server comes back up, + * then event transmission is resumed transparently. This + * transparent reconneciton is performed by a connector + * thread which periodically attempts to connect to the server. + * + *
  • Logging events are automatically buffered by the + * native TCP implementation. This means that if the link to server + * is slow but still faster than the rate of (log) event production + * by the client, the client will not be affected by the slow + * network connection. However, if the network connection is slower + * then the rate of event production, then the client can only + * progress at the network rate. In particular, if the network link + * to the the server is down, the client will be blocked. + * + *
  • On the other hand, if the network link is up, but the server + * is down, the client will not be blocked when making log requests + * but the log events will be lost due to server unavailability. + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to.
+ * + *
ServerName
+ *
Host name of event's origin prepended to each event.
+ * + *
IPv6
+ *
Boolean value specifying whether to use IPv6 (true) or IPv4 + * (false). Default value is false.
+ * + *
+ */ + class LOG4CPLUS_EXPORT SocketAppender + : public Appender +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + , protected virtual helpers::IConnectorThreadClient +#endif + { + public: + // Ctors + SocketAppender(const log4cplus::tstring& host, unsigned short port, + const log4cplus::tstring& serverName = tstring(), + bool ipv6 = false); + SocketAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~SocketAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + void initConnector (); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + unsigned int port; + log4cplus::tstring serverName; + bool ipv6 = false; + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + virtual thread::Mutex const & ctcGetAccessMutex () const; + virtual helpers::Socket & ctcGetSocket (); + virtual helpers::Socket ctcConnect (); + virtual void ctcSetConnected (); + + volatile bool connected; + helpers::SharedObjectPtr connector; +#endif + + private: + // Disallow copying of instances of this class + SocketAppender(const SocketAppender&); + SocketAppender& operator=(const SocketAppender&); + }; + + namespace helpers { + LOG4CPLUS_EXPORT + void convertToBuffer (SocketBuffer & buffer, + const log4cplus::spi::InternalLoggingEvent& event, + const log4cplus::tstring& serverName); + + LOG4CPLUS_EXPORT + log4cplus::spi::InternalLoggingEvent readFromBuffer(SocketBuffer& buffer); + } // end namespace helpers + +} // end namespace log4cplus + +#endif // LOG4CPLUS_SOCKET_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/appenderattachable.h b/LFtid1056/cloudfront/code/log4cplus/spi/appenderattachable.h new file mode 100644 index 0000000..d0ff6fb --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/appenderattachable.h @@ -0,0 +1,88 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appenderattachable.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ +#define LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +namespace log4cplus { + // Forward Declarations + typedef std::vector SharedAppenderPtrList; + + namespace spi { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachable { + public: + // Methods + /** + * Add an appender. + */ + virtual void addAppender(SharedAppenderPtr newAppender) = 0; + + /** + * Get all previously added appenders as an Enumeration. + */ + virtual SharedAppenderPtrList getAllAppenders() = 0; + + /** + * Get an appender by name. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name) = 0; + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders() = 0; + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender) = 0; + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name) = 0; + + // Dtor + virtual ~AppenderAttachable() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/factory.h b/LFtid1056/cloudfront/code/log4cplus/spi/factory.h new file mode 100644 index 0000000..8c5234b --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/factory.h @@ -0,0 +1,275 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: factory.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_FACTORY_HEADER_ +#define LOG4CPLUS_SPI_FACTORY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class for all factories. + */ + class LOG4CPLUS_EXPORT BaseFactory { + public: + virtual ~BaseFactory() = 0; + + /** + * Returns the typename of the objects this factory creates. + */ + virtual log4cplus::tstring const & getTypeName() const = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT AppenderFactory : public BaseFactory { + public: + typedef Appender ProductType; + typedef SharedAppenderPtr ProductPtr; + + AppenderFactory(); + virtual ~AppenderFactory() = 0; + + /** + * Create an "Appender" object. + */ + virtual SharedAppenderPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Layout" + * objects. + */ + class LOG4CPLUS_EXPORT LayoutFactory : public BaseFactory { + public: + typedef Layout ProductType; + typedef std::unique_ptr ProductPtr; + + LayoutFactory(); + virtual ~LayoutFactory() = 0; + + /** + * Create a "Layout" object. + */ + virtual std::unique_ptr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT FilterFactory : public BaseFactory { + public: + typedef Filter ProductType; + typedef FilterPtr ProductPtr; + + FilterFactory(); + virtual ~FilterFactory() = 0; + + /** + * Create a "Filter" object. + */ + virtual FilterPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to + * create std::locale instances. + */ + class LOG4CPLUS_EXPORT LocaleFactory + : public BaseFactory + { + public: + typedef std::locale ProductType; + typedef std::locale ProductPtr; + + LocaleFactory(); + virtual ~LocaleFactory() = 0; + + //! \returns std::locale instance + virtual ProductPtr createObject ( + const log4cplus::helpers::Properties & props) = 0; + }; + + + /** + * This template class is used as a "Factory Registry". Objects are + * "entered" into the registry with a "name" using the + * put() method. (The registry then owns the object.) + * These object can then be retrieved using the get() + * method. + * + * Note: This class is Thread-safe. + */ + template + class LOG4CPLUS_EXPORT FactoryRegistry + : public ObjectRegistryBase + { + public: + typedef T product_type; + + virtual ~FactoryRegistry() { + clear(); + } + + // public methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool put(std::unique_ptr object) { + bool putValResult = putVal(object->getTypeName(), object.get()); + object.release(); + return putValResult; + } + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + T* get(const log4cplus::tstring& name) const { + return static_cast(getVal(name)); + } + + protected: + virtual void deleteObject(void *object) const { + delete static_cast(object); + } + }; + + + typedef FactoryRegistry AppenderFactoryRegistry; + typedef FactoryRegistry LayoutFactoryRegistry; + typedef FactoryRegistry FilterFactoryRegistry; + typedef FactoryRegistry LocaleFactoryRegistry; + + + /** + * Returns the "singleton" AppenderFactoryRegistry. + */ + LOG4CPLUS_EXPORT AppenderFactoryRegistry& getAppenderFactoryRegistry(); + + /** + * Returns the "singleton" LayoutFactoryRegistry. + */ + LOG4CPLUS_EXPORT LayoutFactoryRegistry& getLayoutFactoryRegistry(); + + /** + * Returns the "singleton" FilterFactoryRegistry. + */ + LOG4CPLUS_EXPORT FilterFactoryRegistry& getFilterFactoryRegistry(); + + /** + * Returns the "singleton" LocaleFactoryRegistry. + */ + LOG4CPLUS_EXPORT LocaleFactoryRegistry& getLocaleFactoryRegistry(); + + + template + class LocalFactoryBase + : public ProductFactoryBase + { + public: + LocalFactoryBase (tchar const * n) + : name (n) + { } + + virtual log4cplus::tstring const & getTypeName() const + { + return name; + } + + private: + log4cplus::tstring name; + }; + + + template + class FactoryTempl + : public LocalFactoryBase + { + public: + typedef typename ProductFactoryBase::ProductPtr ProductPtr; + + FactoryTempl (tchar const * n) + : LocalFactoryBase (n) + { } + + virtual ProductPtr createObject (helpers::Properties const & props) + { + return ProductPtr (new LocalProduct (props)); + } + }; + + + #define LOG4CPLUS_REG_PRODUCT(reg, productprefix, productname, productns, productfact) \ + reg.put ( \ + std::unique_ptr ( \ + new log4cplus::spi::FactoryTempl ( \ + LOG4CPLUS_TEXT(productprefix) \ + LOG4CPLUS_TEXT(#productname)))) + + #define LOG4CPLUS_REG_APPENDER(reg, appendername) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", appendername, log4cplus::, \ + log4cplus::spi::AppenderFactory) + + #define LOG4CPLUS_REG_LAYOUT(reg, layoutname) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", layoutname, log4cplus::, \ + log4cplus::spi::LayoutFactory) + + #define LOG4CPLUS_REG_FILTER(reg, filtername) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::spi::", filtername, log4cplus::spi::, \ + log4cplus::spi::FilterFactory) + + #define LOG4CPLUS_REG_LOCALE(reg, name, factory) \ + reg.put (std::unique_ptr ( \ + new factory (name))) + } // namespace spi +} + + +#endif // LOG4CPLUS_SPI_FACTORY_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/filter.h b/LFtid1056/cloudfront/code/log4cplus/spi/filter.h new file mode 100644 index 0000000..e778c75 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/filter.h @@ -0,0 +1,404 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: filter.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 1999-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines Filter and all of it's subclasses. */ + +#ifndef LOG4CPLUS_SPI_FILTER_HEADER_ +#define LOG4CPLUS_SPI_FILTER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + + namespace helpers + { + + class Properties; + + } + + namespace spi { + + + enum FilterResult { DENY, /**< The log event must be dropped immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + NEUTRAL, /**< This filter is neutral with respect to + * the log event; the remaining filters, if + * if any, should be consulted for a final + * decision. */ + ACCEPT /**< The log event must be logged immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + }; + + // Forward Declarations + class Filter; + class InternalLoggingEvent; + + + /** + * This method is used to filter an InternalLoggingEvent. + * + * Note: filter can be NULL. + */ + LOG4CPLUS_EXPORT FilterResult checkFilter(const Filter* filter, + const InternalLoggingEvent& event); + + typedef helpers::SharedObjectPtr FilterPtr; + + + /** + * Users should extend this class to implement customized logging + * event filtering. Note that the {@link Logger} and {@link + * Appender} classes have built-in filtering rules. It is suggested + * that you first use and understand the built-in rules before rushing + * to write your own custom filters. + * + * This abstract class assumes and also imposes that filters be + * organized in a linear chain. The {@link #decide + * decide(LoggingEvent)} method of each filter is called sequentially, + * in the order of their addition to the chain. + * + * If the value {@link #DENY} is returned, then the log event is + * dropped immediately without consulting with the remaining + * filters. + * + * If the value {@link #NEUTRAL} is returned, then the next filter + * in the chain is consulted. If there are no more filters in the + * chain, then the log event is logged. Thus, in the presence of no + * filters, the default behaviour is to log all logging events. + * + * If the value {@link #ACCEPT} is returned, then the log + * event is logged without consulting the remaining filters. + * + * The philosophy of log4cplus filters is largely inspired from the + * Linux ipchains. + */ + class LOG4CPLUS_EXPORT Filter + : public virtual log4cplus::helpers::SharedObject + { + public: + // ctor and dtor + Filter(); + virtual ~Filter(); + + // Methods + /** + * Appends filter to the end of this filter chain. + */ + void appendFilter(FilterPtr filter); + + /** + * If the decision is DENY, then the event will be + * dropped. If the decision is NEUTRAL, then the next + * filter, if any, will be invoked. If the decision is ACCEPT then + * the event will be logged without consulting with other filters in + * the chain. + * + * @param event The LoggingEvent to decide upon. + * @return The decision of the filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const = 0; + + // Data + /** + * Points to the next filter in the filter chain. + */ + FilterPtr next; + }; + + + + /** + * This filter drops all logging events. + * + * You can add this filter to the end of a filter chain to + * switch from the default "accept all unless instructed otherwise" + * filtering behaviour to a "deny all unless instructed otherwise" + * behaviour. + */ + class LOG4CPLUS_EXPORT DenyAllFilter : public Filter { + public: + DenyAllFilter (); + DenyAllFilter (const log4cplus::helpers::Properties&); + + /** + * Always returns the {@link #DENY} regardless of the + * {@link InternalLoggingEvent} parameter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + }; + + + /** + * This is a very simple filter based on LogLevel matching. + * + * The filter admits two options LogLevelToMatch and + * AcceptOnMatch. If there is an exact match between the value + * of the LogLevelToMatch option and the LogLevel of the {@link + * spi::InternalLoggingEvent}, then the {@link #decide} method returns + * {@link #ACCEPT} in case the AcceptOnMatch option value is set + * to true, if it is false then {@link #DENY} + * is returned. If there is no match, {@link #NEUTRAL} is returned. + */ + class LOG4CPLUS_EXPORT LogLevelMatchFilter : public Filter { + public: + LogLevelMatchFilter(); + LogLevelMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + * + * Returns {@link #NEUTRAL} if the LogLevelToMatch + * option is not set or if there is no match. Otherwise, if + * there is a match, then the returned decision is {@link #ACCEPT} + * if the AcceptOnMatch property is set to true. + * The returned decision is {@link #DENY} if the AcceptOnMatch + * property is set to false. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelToMatch; + }; + + + + /** + * This is a very simple filter based on LogLevel matching, which can be + * used to reject messages with LogLevels outside a certain range. + * + * The filter admits three options LogLevelMin, LogLevelMax + * and AcceptOnMatch. + * + * If the LogLevel of the Logging event is not between Min and Max + * (inclusive), then {@link #DENY} is returned. + * + * If the Logging event LogLevel is within the specified range, then if + * AcceptOnMatch is true, {@link #ACCEPT} is returned, and if + * AcceptOnMatch is false, {@link #NEUTRAL} is returned. + * + * If LogLevelMin is not defined, then there is no + * minimum acceptable LogLevel (ie a LogLevel is never rejected for + * being too "low"/unimportant). If LogLevelMax is not + * defined, then there is no maximum acceptable LogLevel (ie a + * LogLevel is never rejected for beeing too "high"/important). + * + * Refer to the {@link + * Appender#setThreshold setThreshold} method + * available to all appenders for a more convenient way to + * filter out events by LogLevel. + */ + class LOG4CPLUS_EXPORT LogLevelRangeFilter : public Filter { + public: + // ctors + LogLevelRangeFilter(); + LogLevelRangeFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelMin; + LogLevel logLevelMax; + }; + + + + /** + * This is a very simple filter based on string matching. + * + * The filter admits two options StringToMatch and + * AcceptOnMatch. If there is a match between the value of the + * StringToMatch option and the message of the Logging event, + * then the {@link #decide} method returns {@link #ACCEPT} if + * the AcceptOnMatch option value is true, if it is false then + * {@link #DENY} is returned. If there is no match, {@link #NEUTRAL} + * is returned. + */ + class LOG4CPLUS_EXPORT StringMatchFilter : public Filter { + public: + // ctors + StringMatchFilter(); + StringMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Returns {@link #NEUTRAL} is there is no string match. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + log4cplus::tstring stringToMatch; + }; + + /** + * This filter allows using `std::function`. + */ + class LOG4CPLUS_EXPORT FunctionFilter + : public Filter + { + public: + typedef std::function + Function; + + FunctionFilter (Function); + + /** + * Returns result returned by `function`. + */ + virtual FilterResult decide(const InternalLoggingEvent&) const; + + private: + Function function; + }; + + /** + * This is a simple filter based on the string returned by event.getNDC(). + * + * The filter admits three options NeutralOnEmpty, NDCToMatch + * and AcceptOnMatch. + * + * If NeutralOnEmpty is true and NDCToMatch is empty + * then {@link #NEUTRAL} is returned. + * + * If NeutralOnEmpty is true and the value returned by event.getNDC() is empty + * then {@link #NEUTRAL} is returned. + * + * If the string returned by event.getNDC() matches NDCToMatch, then if + * AcceptOnMatch is true, {@link #ACCEPT} is returned, and if + * AcceptOnMatch is false, {@link #DENY} is returned. + * + * If the string returned by event.getNDC() does not match NDCToMatch, then if + * AcceptOnMatch is true, {@link #DENY} is returned, and if + * AcceptOnMatch is false, {@link #ACCEPT} is returned. + * + */ + + class LOG4CPLUS_EXPORT NDCMatchFilter : public Filter + { + public: + // ctors + NDCMatchFilter(); + NDCMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Returns {@link #NEUTRAL} is there is no string match. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + /** return NEUTRAL if event.getNDC() is empty or ndcToMatch is empty. Default is true. */ + bool neutralOnEmpty; + log4cplus::tstring ndcToMatch; + }; + + /** + * This is a simple filter based on the key/value pair stored in MDC. + * + * The filter admits four options NeutralOnEmpty, MDCKeyToMatch + * MDCValueToMatch and AcceptOnMatch. + * + * If NeutralOnEmpty is true and MDCKeyToMatch or MDCValueToMatch + * is empty then {@link #NEUTRAL} is returned. + * + * If NeutralOnEmpty is true and the string returned by event.getMDC(MDCKeyToMatch) is empty + * then {@link #NEUTRAL} is returned. + * + * If the string returned by event.getMDC(MDCKeyToMatch) matches MDCValueToMatch, then if + * AcceptOnMatch is true, {@link #ACCEPT} is returned, and if + * AcceptOnMatch is false, {@link #DENY} is returned. + * + * If the string returned by event.getMDC(MDCKeyToMatch) does not match MDCValueToMatch, then if + * AcceptOnMatch is true, {@link #DENY} is returned, and if + * AcceptOnMatch is false, {@link #ACCEPT} is returned. + * + */ + + class LOG4CPLUS_EXPORT MDCMatchFilter : public Filter + { + public: + // ctors + MDCMatchFilter(); + MDCMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Returns {@link #NEUTRAL} is there is no string match. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + /** return NEUTRAL if mdcKeyToMatch is empty or event::getMDC(mdcKeyValue) is empty or mdcValueToMatch is empty. Default is true. */ + bool neutralOnEmpty; + /** The MDC key to retrieve **/ + log4cplus::tstring mdcKeyToMatch; + /** the MDC value to match **/ + log4cplus::tstring mdcValueToMatch; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif /* LOG4CPLUS_SPI_FILTER_HEADER_ */ diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/loggerfactory.h b/LFtid1056/cloudfront/code/log4cplus/spi/loggerfactory.h new file mode 100644 index 0000000..55df218 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/loggerfactory.h @@ -0,0 +1,65 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggerfactory.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER +#define LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { + // Forward Declarations + class Logger; + class Hierarchy; + + namespace spi { + class LoggerImpl; + + /** + * Implement this interface to create new instances of Logger or + * a sub-class of Logger. + */ + class LOG4CPLUS_EXPORT LoggerFactory { + public: + /** + * Creates a new Logger object. + */ + virtual Logger makeNewLoggerInstance(const log4cplus::tstring& name, + Hierarchy& h) = 0; + virtual ~LoggerFactory() = 0; + + protected: + virtual LoggerImpl * makeNewLoggerImplInstance( + const log4cplus::tstring& name, Hierarchy& h) = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/loggerimpl.h b/LFtid1056/cloudfront/code/log4cplus/spi/loggerimpl.h new file mode 100644 index 0000000..4112f0f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/loggerimpl.h @@ -0,0 +1,216 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggerimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_LOGGER_HEADER_ +#define LOG4CPLUS_SPI_LOGGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + class DefaultLoggerFactory; + + namespace spi { + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + */ + class LOG4CPLUS_EXPORT LoggerImpl + : public virtual log4cplus::helpers::SharedObject, + public log4cplus::helpers::AppenderAttachableImpl + { + public: + typedef helpers::SharedObjectPtr SharedLoggerImplPtr; + + // Methods + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event The event to log. + */ + virtual void callAppenders(const InternalLoggingEvent& event); + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + virtual void closeNestedAppenders(); + + /** + * Check whether this logger is enabled for a given LogLevel passed + * as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + virtual bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + virtual void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=nullptr, int line=-1, + const char* function=nullptr); + + virtual void log(spi::InternalLoggingEvent const &); + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel. + */ + LogLevel getLogLevel() const { return this->ll; } + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel _ll) { this->ll = _ll; } + + /** + * Return the the {@link Hierarchy} where this Logger + * instance is attached. + */ + virtual Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring const & getName() const { return name; } + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + virtual ~LoggerImpl(); + + protected: + // Ctors + /** + * This constructor created a new Logger instance and + * sets its name. + * + * It is intended to be used by sub-classes only. You should not + * create loggers directly. + * + * @param name The name of the logger. + * @param h Hierarchy + */ + LoggerImpl(const log4cplus::tstring& name, Hierarchy& h); + + + // Methods + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + virtual void forcedLog(LogLevel ll, + const log4cplus::tstring& message, + const char* file, + int line, + const char* function); + + virtual void forcedLog(spi::InternalLoggingEvent const & ev); + + + // Data + /** The name of this logger */ + log4cplus::tstring name; + + /** + * The assigned LogLevel of this logger. + */ + LogLevel ll; + + /** + * The parent of this logger. All loggers have at least one + * ancestor which is the root logger. + */ + SharedLoggerImplPtr parent; + + /** + * Additivity is set to true by default, that is children inherit + * the appenders of their ancestors by default. If this variable is + * set to false then the appenders found in the + * ancestors of this logger are not used. However, the children + * of this logger will inherit its appenders, unless the children + * have their additivity flag set to false too. See + * the user manual for more details. + */ + bool additive; + + private: + // Data + /** Loggers need to know what Hierarchy they are in. */ + Hierarchy& hierarchy; + + // Disallow copying of instances of this class + LoggerImpl(const LoggerImpl&) = delete; + LoggerImpl& operator=(const LoggerImpl&) = delete; + + // Friends + friend class log4cplus::Logger; + friend class log4cplus::DefaultLoggerFactory; + friend class log4cplus::Hierarchy; + }; + + typedef LoggerImpl::SharedLoggerImplPtr SharedLoggerImplPtr; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_LOGGER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/loggingevent.h b/LFtid1056/cloudfront/code/log4cplus/spi/loggingevent.h new file mode 100644 index 0000000..de3417e --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/loggingevent.h @@ -0,0 +1,239 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggingevent.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ +#define LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace log4cplus { + namespace spi { + /** + * The internal representation of logging events. When an affirmative + * decision is made to log then a InternalLoggingEvent + * instance is created. This instance is passed around to the + * different log4cplus components. + * + * This class is of concern to those wishing to extend log4cplus. + */ + class LOG4CPLUS_EXPORT InternalLoggingEvent { + public: + // Ctors + /** + * Instantiate a LoggingEvent from the supplied parameters. + * + * @param logger The logger of this event. + * @param loglevel The LogLevel of this event. + * @param message The message of this event. + * @param filename Name of file where this event has occurred, + * can be NULL. + * @param line Line number in file specified by + * the filename parameter. + * @param function Name of function that is logging this event. + */ + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& message, + const char* filename, int line, const char * function = nullptr); + + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& ndc, + MappedDiagnosticContextMap const & mdc, + const log4cplus::tstring& message, + const log4cplus::tstring& thread, + log4cplus::helpers::Time time, const log4cplus::tstring& file, + int line, const log4cplus::tstring & function + = log4cplus::tstring ()) LOG4CPLUS_ATTRIBUTE_DEPRECATED; + + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& ndc, + MappedDiagnosticContextMap const & mdc, + const log4cplus::tstring& message, + const log4cplus::tstring& thread, + const log4cplus::tstring& thread2, + log4cplus::helpers::Time time, const log4cplus::tstring& file, + int line, const log4cplus::tstring & function + = log4cplus::tstring ()); + + InternalLoggingEvent (); + + InternalLoggingEvent( + const log4cplus::spi::InternalLoggingEvent& rhs); + + virtual ~InternalLoggingEvent(); + + void setLoggingEvent (const log4cplus::tstring & logger, + LogLevel ll, const log4cplus::tstring & message, + const char * filename, int line, + const char * function = nullptr); + + void setFunction (char const * func); + void setFunction (log4cplus::tstring const &); + + + // public virtual methods + /** The application supplied message of logging event. */ + virtual const log4cplus::tstring& getMessage() const; + + /** Returns the 'type' of InternalLoggingEvent. Derived classes + * should override this method. (NOTE: Values <= 1000 are + * reserved for log4cplus and should not be used.) + */ + virtual unsigned int getType() const; + + /** Returns a copy of this object. Derived classes + * should override this method. + */ + virtual std::unique_ptr clone() const; + + + // public methods + /** The logger of the logging event. It is set by + * the LoggingEvent constructor. + */ + const log4cplus::tstring& getLoggerName() const + { + return loggerName; + } + + /** LogLevel of logging event. */ + LogLevel getLogLevel() const + { + return ll; + } + + /** The nested diagnostic context (NDC) of logging event. */ + const log4cplus::tstring& getNDC() const + { + if (!ndcCached) + { + ndc = log4cplus::getNDC().get(); + ndcCached = true; + } + return ndc; + } + + MappedDiagnosticContextMap const & getMDCCopy () const + { + if (!mdcCached) + { + mdc = log4cplus::getMDC().getContext (); + mdcCached = true; + } + return mdc; + } + + tstring const & getMDC (tstring const & key) const; + + /** The name of thread in which this logging event was generated. */ + const log4cplus::tstring& getThread() const + { + if (! threadCached) + { + thread = thread::getCurrentThreadName (); + threadCached = true; + } + return thread; + } + + //! The alternative name of thread in which this logging event + //! was generated. + const log4cplus::tstring& getThread2() const + { + if (! thread2Cached) + { + thread2 = thread::getCurrentThreadName2 (); + thread2Cached = true; + } + return thread2; + } + + + /** Time stamp when the event was created. */ + const log4cplus::helpers::Time& getTimestamp() const + { + return timestamp; + } + + /** The is the file where this log statement was written */ + const log4cplus::tstring& getFile() const + { + return file; + } + + /** The is the line where this log statement was written */ + int getLine() const { return line; } + + log4cplus::tstring const & getFunction () const + { + return function; + } + + void gatherThreadSpecificData () const; + + void swap (InternalLoggingEvent &); + + // public operators + log4cplus::spi::InternalLoggingEvent& + operator=(const log4cplus::spi::InternalLoggingEvent& rhs); + + // static methods + static unsigned int getDefaultType(); + + protected: + // Data + log4cplus::tstring message; + log4cplus::tstring loggerName; + LogLevel ll; + mutable log4cplus::tstring ndc; + mutable MappedDiagnosticContextMap mdc; + mutable log4cplus::tstring thread; + mutable log4cplus::tstring thread2; + log4cplus::helpers::Time timestamp; + log4cplus::tstring file; + log4cplus::tstring function; + int line; + /** Indicates whether or not the Threadname has been retrieved. */ + mutable bool threadCached; + mutable bool thread2Cached; + /** Indicates whether or not the NDC has been retrieved. */ + mutable bool ndcCached; + /** Indicates whether or not the MDC has been retrieved. */ + mutable bool mdcCached; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/objectregistry.h b/LFtid1056/cloudfront/code/log4cplus/spi/objectregistry.h new file mode 100644 index 0000000..a63cecd --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/objectregistry.h @@ -0,0 +1,113 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: objectregistry.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ +#define LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class used to implement the functionality required + * by the ObjectRegistry template class. + */ + class LOG4CPLUS_EXPORT ObjectRegistryBase { + public: + // public methods + /** + * Tests to see whether or not an object is bound in the + * registry as name. + */ + bool exists(const log4cplus::tstring& name) const; + + /** + * Returns the names of all registered objects. + */ + std::vector getAllNames() const; + + //! This function is internal implementation detail. + //! It is related to work-around needed for initialization when + //! using C++11 threads and mutexes. + void _enableLocking (bool); + + protected: + // Ctor and Dtor + ObjectRegistryBase(); + virtual ~ObjectRegistryBase(); + + // protected methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool putVal(const log4cplus::tstring& name, void* object); + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + void* getVal(const log4cplus::tstring& name) const; + + /** + * Deletes object. + */ + virtual void deleteObject(void *object) const = 0; + + /** + * Deletes all objects from this registry. + */ + virtual void clear(); + + // Types + typedef std::map ObjectMap; + + // Data + thread::Mutex mutex; + ObjectMap data; + + private: + ObjectRegistryBase (ObjectRegistryBase const &); + ObjectRegistryBase & operator = (ObjectRegistryBase const &); + + bool volatile locking; + }; + + } +} + + +#endif // LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + diff --git a/LFtid1056/cloudfront/code/log4cplus/spi/rootlogger.h b/LFtid1056/cloudfront/code/log4cplus/spi/rootlogger.h new file mode 100644 index 0000000..91d3a31 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/spi/rootlogger.h @@ -0,0 +1,75 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: rootlogger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ +#define LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +namespace log4cplus { + namespace spi { + + /** + * RootLogger sits at the top of the logger hierachy. It is a + * regular logger except that it provides several guarantees. + * + * First, it cannot be assigned a NOT_SET_LOG_LEVEL + * LogLevel. Second, since root logger cannot have a parent, the + * getChainedLogLevel method always returns the value of the + * ll field without walking the hierarchy. + */ + class LOG4CPLUS_EXPORT RootLogger : public LoggerImpl { + public: + // Ctors + /** + * The root logger names itself as "root". However, the root + * logger cannot be retrieved by name. + */ + RootLogger(Hierarchy& h, LogLevel ll); + + // Methods + /** + * Return the assigned LogLevel value without walking the logger + * hierarchy. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Setting a NOT_SET_LOG_LEVEL value to the LogLevel of the root logger + * may have catastrophic results. We prevent this here. + */ + void setLogLevel(LogLevel); + + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + diff --git a/LFtid1056/cloudfront/code/log4cplus/streams.h b/LFtid1056/cloudfront/code/log4cplus/streams.h new file mode 100644 index 0000000..5d61010 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/streams.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: streams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_STREAMS_HEADER_ +#define LOG4CPLUS_STREAMS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include + + +namespace log4cplus +{ + typedef std::basic_ostream tostream; + typedef std::basic_istream tistream; + typedef std::basic_ostringstream tostringstream; + typedef std::basic_istringstream tistringstream; + extern LOG4CPLUS_EXPORT tostream & tcout; + extern LOG4CPLUS_EXPORT tostream & tcerr; +} + +#if defined (UNICODE) && defined (LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) + +LOG4CPLUS_EXPORT log4cplus::tostream& operator <<(log4cplus::tostream&, const char* psz ); + +#endif + +#endif // LOG4CPLUS_STREAMS_HEADER_ + diff --git a/LFtid1056/cloudfront/code/log4cplus/syslogappender.h b/LFtid1056/cloudfront/code/log4cplus/syslogappender.h new file mode 100644 index 0000000..1171a36 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/syslogappender.h @@ -0,0 +1,167 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: syslogappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SYSLOG_APPENDER_HEADER_ +#define LOG4CPLUS_SYSLOG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus +{ + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
ident
+ *
First argument to openlog(), a string that + * will be prepended to every message.
+ * + *
facility
+ *
Facility is used in combination with syslog level in first + * argument to syslog(). It can be one of the supported facility + * names (case insensitive), e.g. auth, cron, kern, mail, news + * etc.
+ * + *
host
+ *
Destination syslog host. When this property is specified, + * messages are sent using UDP to destination host, otherwise + * messages are logged to local syslog.
+ * + *
port
+ *
Destination port of syslog service on host specified by the + * host property. The default value is port 514.
+ * + *
udp
When the syslog is remote, this + * property picks the IP protocol. When the value is true, UDP is + * used. When the value is false, TCP is used. The default value + * is true.
+ * + *
IPv6
+ *
Boolean value specifying whether to use IPv6 (true) or IPv4 + * (false). Default value is false.
+ * + *
fqdn
+ *
Boolean value specifying whether to use FQDN for hostname field. + * Default value is true.
+ * + *
+ * + * \note Messages sent to remote syslog using UDP are conforming + * to RFC5424. Messages sent to remote syslog using TCP are + * using octet counting as described in RFC6587. + */ + class LOG4CPLUS_EXPORT SysLogAppender + : public Appender +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + , protected virtual helpers::IConnectorThreadClient +#endif + { + public: + //! Remote syslog IP protocol type. + enum RemoteSyslogType + { + RSTUdp, + RSTTcp + }; + + // Ctors +#if defined (LOG4CPLUS_HAVE_SYSLOG_H) + SysLogAppender(const tstring& ident); +#endif + SysLogAppender(const tstring& ident, const tstring & host, + int port = 514, const tstring & facility = tstring (), + RemoteSyslogType remoteSyslogType = RSTUdp, bool ipv6 = false); + SysLogAppender(const tstring& ident, const tstring & host, + int port, const tstring & facility, + RemoteSyslogType remoteSyslogType, bool ipv6, bool fqdn); + SysLogAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~SysLogAppender(); + + // Methods + virtual void close(); + + protected: + virtual int getSysLogLevel(const LogLevel& ll) const; + virtual void append(const spi::InternalLoggingEvent& event); +#if defined (LOG4CPLUS_HAVE_SYSLOG_H) + //! Local syslog (served by `syslog()`) worker function. + void appendLocal(const spi::InternalLoggingEvent& event); +#endif + //! Remote syslog worker function. + void appendRemote(const spi::InternalLoggingEvent& event); + + // Data + tstring ident; + int facility; + + typedef void (SysLogAppender:: * AppendFuncType) ( + const spi::InternalLoggingEvent&); + AppendFuncType appendFunc; + + tstring host; + int port; + RemoteSyslogType remoteSyslogType; + helpers::Socket syslogSocket; + bool connected; + bool ipv6 = false; + + static tstring const remoteTimeFormat; + + void initConnector (); + void openSocket (); + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + virtual thread::Mutex const & ctcGetAccessMutex () const; + virtual helpers::Socket & ctcGetSocket (); + virtual helpers::Socket ctcConnect (); + virtual void ctcSetConnected (); + + helpers::SharedObjectPtr connector; +#endif + + private: + // Disallow copying of instances of this class + SysLogAppender(const SysLogAppender&); + SysLogAppender& operator=(const SysLogAppender&); + + std::string identStr; + tstring hostname; + }; + +} // end namespace log4cplus + + +#endif // LOG4CPLUS_SYSLOG_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/tchar.h b/LFtid1056/cloudfront/code/log4cplus/tchar.h new file mode 100644 index 0000000..1c99ba6 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/tchar.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file */ + +#ifndef LOG4CPLUS_TCHAR_HEADER_ +#define LOG4CPLUS_TCHAR_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (_WIN32) +#include +#endif + + +#ifdef UNICODE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) + + +namespace log4cplus +{ + +#if defined (UNICODE) +typedef wchar_t tchar; + +#else +typedef char tchar; + +#endif + +} // namespace log4cplus + + +#endif // LOG4CPLUS_TCHAR_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-cxx11.h b/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-cxx11.h new file mode 100644 index 0000000..be3cc0d --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-cxx11.h @@ -0,0 +1,35 @@ +// -*- C++ -*- +// Copyright (C) 2013-2017, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the C++11 API. It does not contain any include +//! guards because it is only a fragment to be included by +//! syncprims.h. + +namespace log4cplus { namespace thread { namespace impl { + +#include "log4cplus/thread/impl/syncprims-pmsm.h" + +} } } // namespace log4cplus { namespace thread { namespace impl { diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-impl.h b/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-impl.h new file mode 100644 index 0000000..2222a01 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-impl.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { namespace thread { namespace impl { + + +LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN + syncprims_throw_exception (char const * const msg, + char const * const file, int line); + + +class SharedMutex + : public SharedMutexImplBase +{ +public: + SharedMutex (); + ~SharedMutex (); + + void rdlock () const; + void wrlock () const; + void rdunlock () const; + void wrunlock () const; + +private: + Mutex m1; + Mutex m2; + Mutex m3; + Semaphore w; + mutable unsigned writer_count; + Semaphore r; + mutable unsigned reader_count; + + SharedMutex (SharedMutex const &); + SharedMutex & operator = (SharedMutex const &); +}; + + +} } } // namespace log4cplus { namespace thread { namespace impl { + + +// Include the appropriate implementations of the classes declared +// above. + +#include + +#undef LOG4CPLUS_THROW_RTE + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-pmsm.h b/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-pmsm.h new file mode 100644 index 0000000..bba97ea --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/impl/syncprims-pmsm.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of reader-writer locking +//! primitive using other primitives, IOW poor man's rwlock. +//! It does not contain any include guards because it is only a fragment +//! to be included by syncprims-{pthreads,win32}.h. + + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +// This implements algorithm described in "Concurrent Control with "Readers" +// and "Writers"; P.J. Courtois, F. Heymans, and D.L. Parnas; +// MBLE Research Laboratory; Brussels, Belgium" + + +inline +SharedMutex::SharedMutex () + : m1 () + , m2 () + , m3 () + , w (1, 1) + , writer_count (0) + , r (1, 1) + , reader_count (0) +{ } + + +inline +SharedMutex::~SharedMutex () +{ } + + +inline +void +SharedMutex::rdlock () const +{ + MutexGuard m3_guard (m3); + SemaphoreGuard r_guard (r); + MutexGuard m1_guard (m1); + if (reader_count + 1 == 1) + w.lock (); + + reader_count += 1; +} + + +inline +void +SharedMutex::rdunlock () const +{ + MutexGuard m1_guard (m1); + if (reader_count - 1 == 0) + w.unlock (); + + reader_count -= 1; +} + + +inline +void +SharedMutex::wrlock () const +{ + { + MutexGuard m2_guard (m2); + if (writer_count + 1 == 1) + r.lock (); + + writer_count += 1; + } + try + { + w.lock (); + } + catch (...) + { + MutexGuard m2_guard (m2); + writer_count -= 1; + throw; + } +} + + +inline +void +SharedMutex::wrunlock () const +{ + w.unlock (); + MutexGuard m2_guard (m2); + if (writer_count - 1 == 0) + r.unlock (); + + writer_count -= 1; +} diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/impl/threads-impl.h b/LFtid1056/cloudfront/code/log4cplus/thread/impl/threads-impl.h new file mode 100644 index 0000000..2c6ae4f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/impl/threads-impl.h @@ -0,0 +1,96 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ +#define LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (_WIN32) +#include +#endif +#include +#include +#include + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +#if defined (LOG4CPLUS_USE_PTHREADS) + +typedef pthread_t os_handle_type; +typedef pthread_t os_id_type; + + +inline +pthread_t +getCurrentThreadId () +{ + return pthread_self (); +} + + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + +typedef HANDLE os_handle_type; +typedef DWORD os_id_type; + + +inline +DWORD +getCurrentThreadId () +{ + return GetCurrentThreadId (); +} + + +#elif defined (LOG4CPLUS_SINGLE_THREADED) + +typedef void * os_handle_type; +typedef int os_id_type; + + +inline +int +getCurrentThreadId () +{ + return 1; +} + + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { + + +#endif // LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/impl/tls.h b/LFtid1056/cloudfront/code/log4cplus/thread/impl/tls.h new file mode 100644 index 0000000..2c1270e --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/impl/tls.h @@ -0,0 +1,193 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_IMPL_TLS_H +#define LOG4CPLUS_THREAD_IMPL_TLS_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#ifdef LOG4CPLUS_USE_PTHREADS +# include + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# include + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +# include + +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +typedef void * tls_value_type; + +#ifdef LOG4CPLUS_USE_PTHREADS +typedef pthread_key_t * tls_key_type; +typedef void (* tls_init_cleanup_func_type)(void *); + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +typedef DWORD tls_key_type; +typedef PFLS_CALLBACK_FUNCTION tls_init_cleanup_func_type; + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +typedef std::size_t tls_key_type; +typedef void (* tls_init_cleanup_func_type)(void *); + +#endif + + +inline tls_key_type tls_init (tls_init_cleanup_func_type); +inline tls_value_type tls_get_value (tls_key_type); +inline void tls_set_value (tls_key_type, tls_value_type); +inline void tls_cleanup (tls_key_type); + + +#if defined (LOG4CPLUS_USE_PTHREADS) +tls_key_type +tls_init (tls_init_cleanup_func_type cleanupfunc) +{ + pthread_key_t * key = new pthread_key_t; + int ret = pthread_key_create (key, cleanupfunc); + if (LOG4CPLUS_UNLIKELY (ret != 0)) + throw std::system_error(ret, std::system_category (), + "pthread_key_create() failed"); + return key; +} + + +tls_value_type +tls_get_value (tls_key_type key) +{ + return pthread_getspecific (*key); +} + + +void +tls_set_value (tls_key_type key, tls_value_type value) +{ + pthread_setspecific(*key, value); +} + + +void +tls_cleanup (tls_key_type key) +{ + pthread_key_delete (*key); + delete key; +} + + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +tls_key_type +tls_init (tls_init_cleanup_func_type cleanupfunc) +{ + DWORD const slot = FlsAlloc (cleanupfunc); + if (LOG4CPLUS_UNLIKELY (slot == FLS_OUT_OF_INDEXES)) + { + DWORD const eno = GetLastError (); + throw std::system_error (static_cast(eno), + std::system_category (), "FlsAlloc() failed"); + } + return slot; +} + + +tls_value_type tls_get_value (tls_key_type k) +{ + return FlsGetValue (k); +} + + +void +tls_set_value (tls_key_type k, tls_value_type value) +{ + FlsSetValue (k, value); +} + + +void +tls_cleanup (tls_key_type k) +{ + FlsFree (k); +} + + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +extern std::vector * tls_single_threaded_values; + + +tls_key_type +tls_init (tls_init_cleanup_func_type) +{ + if (! tls_single_threaded_values) + tls_single_threaded_values = new std::vector; + tls_key_type key = tls_single_threaded_values->size (); + tls_single_threaded_values->resize (key + 1); + return key; +} + + +tls_value_type +tls_get_value (tls_key_type k) +{ + assert (k < tls_single_threaded_values->size ()); + return (*tls_single_threaded_values)[k]; +} + + +void +tls_set_value (tls_key_type k, tls_value_type val) +{ + assert (k < tls_single_threaded_values->size ()); + (*tls_single_threaded_values)[k] = val; +} + + +void +tls_cleanup (tls_key_type k) +{ + assert (k < tls_single_threaded_values->size ()); + (*tls_single_threaded_values)[k] = 0; +} + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { + +#endif // LOG4CPLUS_THREAD_IMPL_TLS_H diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/syncprims-pub-impl.h b/LFtid1056/cloudfront/code/log4cplus/thread/syncprims-pub-impl.h new file mode 100644 index 0000000..d759d1f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/syncprims-pub-impl.h @@ -0,0 +1,359 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if (defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \ + && defined (LOG4CPLUS_BUILD_DLL)) \ + || defined (LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL) +#include + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) +# include +#endif + +#define LOG4CPLUS_THROW_RTE(msg) \ + do { log4cplus::thread::impl::syncprims_throw_exception (msg, __FILE__, \ + __LINE__); } while (0) + +namespace log4cplus { namespace thread { + +namespace impl +{ + +LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN + syncprims_throw_exception(char const * const msg, + char const * const file, int line); + +} + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SimpleMutex::SimpleMutex () + LOG4CPLUS_THREADED (: mtx ()) +{ } + + +LOG4CPLUS_INLINE_EXPORT +SimpleMutex::~SimpleMutex () +{ } + + +LOG4CPLUS_INLINE_EXPORT +void +SimpleMutex::lock () const +{ + LOG4CPLUS_THREADED (mtx.lock ()); +} + +LOG4CPLUS_INLINE_EXPORT +bool +SimpleMutex::try_lock () const +{ +#if defined (LOG4CPLUS_SINGLE_THREADED) + return true; +#else + return mtx.try_lock (); +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +void +SimpleMutex::unlock () const +{ + LOG4CPLUS_THREADED (mtx.unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +Mutex::Mutex () + LOG4CPLUS_THREADED (: mtx ()) +{ } + + +LOG4CPLUS_INLINE_EXPORT +Mutex::~Mutex () +{ } + + +LOG4CPLUS_INLINE_EXPORT +void +Mutex::lock () const +{ + LOG4CPLUS_THREADED (mtx.lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Mutex::unlock () const +{ + LOG4CPLUS_THREADED (mtx.unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +Semaphore::Semaphore (unsigned LOG4CPLUS_THREADED (max_), + unsigned LOG4CPLUS_THREADED (initial)) +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + : maximum(max_) + , val ((std::min) (maximum, initial)) +#endif +{ } + + +LOG4CPLUS_INLINE_EXPORT +Semaphore::~Semaphore () +{ } + + +LOG4CPLUS_INLINE_EXPORT +void +Semaphore::unlock () const +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + std::lock_guard guard (mtx); + + if (val >= maximum) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val >= max"); + + ++val; + cv.notify_all (); +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +void +Semaphore::lock () const +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + std::unique_lock guard (mtx); + + if (LOG4CPLUS_UNLIKELY(val > maximum)) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val > max"); + + while (val == 0) + cv.wait (guard); + + --val; + + if (LOG4CPLUS_UNLIKELY(val >= maximum)) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val >= max"); +#endif +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +ManualResetEvent::ManualResetEvent (bool LOG4CPLUS_THREADED (sig)) +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + : signaled (sig) + , sigcount (0) +#endif +{ } + + +LOG4CPLUS_INLINE_EXPORT +ManualResetEvent::~ManualResetEvent () +{ } + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::signal () const +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + std::unique_lock guard (mtx); + + signaled = true; + sigcount += 1; + cv.notify_all (); +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::wait () const +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + std::unique_lock guard (mtx); + + if (! signaled) + { + unsigned prev_count = sigcount; + do + { + cv.wait (guard); + } + while (prev_count == sigcount); + } +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +bool +ManualResetEvent::timed_wait (unsigned long LOG4CPLUS_THREADED (msec)) const +{ +#if defined (LOG4CPLUS_SINGLE_THREADED) + return true; + +#else + std::unique_lock guard (mtx); + + if (! signaled) + { + unsigned prev_count = sigcount; + + std::chrono::steady_clock::time_point const wait_until_time + = std::chrono::steady_clock::now () + + std::chrono::milliseconds (msec); + + do + { + int ret = static_cast( + cv.wait_until (guard, wait_until_time)); + switch (ret) + { + case static_cast(std::cv_status::no_timeout): + break; + + case static_cast(std::cv_status::timeout): + return false; + + default: + guard.unlock (); + guard.release (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + } + } + while (prev_count == sigcount); + } + + return true; +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::reset () const +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + std::lock_guard guard (mtx); + + signaled = false; +#endif +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SharedMutexImplBase::~SharedMutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SharedMutex::SharedMutex () + : sm (LOG4CPLUS_THREADED (new impl::SharedMutex)) +{ } + + +LOG4CPLUS_INLINE_EXPORT +SharedMutex::~SharedMutex () +{ + LOG4CPLUS_THREADED (delete static_cast(sm)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::rdlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->rdlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::wrlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->wrlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::rdunlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->rdunlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::wrunlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->wrunlock ()); +} + + +} } // namespace log4cplus { namespace thread { + +#endif // LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/syncprims.h b/LFtid1056/cloudfront/code/log4cplus/thread/syncprims.h new file mode 100644 index 0000000..4c288d6 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/syncprims.h @@ -0,0 +1,354 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { namespace thread { + + +template +class SyncGuard +{ +public: + SyncGuard (); + SyncGuard (SyncPrim const &); + ~SyncGuard (); + SyncGuard (SyncGuard const &) = delete; + SyncGuard & operator = (SyncGuard const &) = delete; + + void lock (); + void unlock (); + void attach (SyncPrim const &); + void attach_and_lock (SyncPrim const &); + void detach (); + +private: + SyncPrim const * sp; +}; + + +class LOG4CPLUS_EXPORT SimpleMutex +{ +public: + SimpleMutex (); + ~SimpleMutex (); + SimpleMutex (SimpleMutex const &) = delete; + SimpleMutex & operator = (SimpleMutex const &) = delete; + + void lock () const; + bool try_lock () const; + void unlock () const; + +private: + LOG4CPLUS_THREADED (mutable std::mutex mtx;) +}; + + +typedef SyncGuard SimpleMutexGuard; + + +class LOG4CPLUS_EXPORT Mutex +{ +public: + Mutex (); + ~Mutex (); + Mutex (Mutex const &) = delete; + Mutex & operator = (Mutex const &) = delete; + + void lock () const; + void unlock () const; + +private: + LOG4CPLUS_THREADED (mutable std::recursive_mutex mtx;) +}; + + +typedef SyncGuard MutexGuard; + + +class LOG4CPLUS_EXPORT Semaphore +{ +public: + Semaphore (unsigned max, unsigned initial); + ~Semaphore (); + Semaphore (Semaphore const &) = delete; + Semaphore & operator = (Semaphore const &) = delete; + + void lock () const; + void unlock () const; + +private: +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + mutable std::mutex mtx; + mutable std::condition_variable cv; + mutable unsigned maximum; + mutable unsigned val; +#endif +}; + + +typedef SyncGuard SemaphoreGuard; + + +class LOG4CPLUS_EXPORT ManualResetEvent +{ +public: + explicit ManualResetEvent (bool = false); + ~ManualResetEvent (); + ManualResetEvent (ManualResetEvent const &) = delete; + ManualResetEvent & operator = (ManualResetEvent const &) = delete; + + void signal () const; + void wait () const; + bool timed_wait (unsigned long msec) const; + void reset () const; + +private: +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + mutable std::mutex mtx; + mutable std::condition_variable cv; + mutable bool signaled; + mutable unsigned sigcount; +#endif +}; + + +class SharedMutexImplBase +{ +protected: + ~SharedMutexImplBase (); +}; + + +template +class SyncGuardFunc +{ +public: + SyncGuardFunc (SyncPrim const &); + ~SyncGuardFunc (); + + void lock (); + void unlock (); + void attach (SyncPrim const &); + void detach (); + +private: + SyncPrim const * sp; + + SyncGuardFunc (SyncGuardFunc const &); + SyncGuardFunc & operator = (SyncGuardFunc const &); +}; + + +class LOG4CPLUS_EXPORT SharedMutex +{ +public: + SharedMutex (); + ~SharedMutex (); + + void rdlock () const; + void rdunlock () const; + + void wrlock () const; + void wrunlock () const; + +private: + SharedMutexImplBase * sm; + + SharedMutex (SharedMutex const &); + SharedMutex & operator = (SharedMutex const &); +}; + + +typedef SyncGuardFunc SharedMutexReaderGuard; + + +typedef SyncGuardFunc SharedMutexWriterGuard; + + +// +// +// + +template +inline +SyncGuard::SyncGuard () + : sp (0) +{ } + + +template +inline +SyncGuard::SyncGuard (SyncPrim const & m) + : sp (&m) +{ + sp->lock (); +} + + +template +inline +SyncGuard::~SyncGuard () +{ + if (sp) + sp->unlock (); +} + + +template +inline +void +SyncGuard::lock () +{ + sp->lock (); +} + + +template +inline +void +SyncGuard::unlock () +{ + sp->unlock (); +} + + +template +inline +void +SyncGuard::attach (SyncPrim const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuard::attach_and_lock (SyncPrim const & m) +{ + attach (m); + try + { + lock(); + } + catch (...) + { + detach (); + throw; + } +} + + +template +inline +void +SyncGuard::detach () +{ + sp = 0; +} + + +// +// +// + +template +inline +SyncGuardFunc::SyncGuardFunc (SyncPrim const & m) + : sp (&m) +{ + (sp->*lock_func) (); +} + + +template +inline +SyncGuardFunc::~SyncGuardFunc () +{ + if (sp) + (sp->*unlock_func) (); +} + + +template +inline +void +SyncGuardFunc::lock () +{ + (sp->*lock_func) (); +} + + +template +inline +void +SyncGuardFunc::unlock () +{ + (sp->*unlock_func) (); +} + + +template +inline +void +SyncGuardFunc::attach (SyncPrim const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuardFunc::detach () +{ + sp = 0; +} + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_H diff --git a/LFtid1056/cloudfront/code/log4cplus/thread/threads.h b/LFtid1056/cloudfront/code/log4cplus/thread/threads.h new file mode 100644 index 0000000..c9ce7d4 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/thread/threads.h @@ -0,0 +1,113 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_THREADS_HEADER_ +#define LOG4CPLUS_THREADS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#include +#include + + +namespace log4cplus { namespace thread { + + +LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName(); +LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName2(); +LOG4CPLUS_EXPORT void setCurrentThreadName(const log4cplus::tstring & name); +LOG4CPLUS_EXPORT void setCurrentThreadName2(const log4cplus::tstring & name); +LOG4CPLUS_EXPORT void yield(); +LOG4CPLUS_EXPORT void blockAllSignals(); + +/** + * This class blocks all POSIX signals when created and unblocks them when + * destroyed. + */ +class LOG4CPLUS_EXPORT SignalsBlocker +{ +public: + SignalsBlocker(); + ~SignalsBlocker(); + +private: + struct SignalsBlockerImpl; + std::unique_ptr impl; +}; + + +#ifndef LOG4CPLUS_SINGLE_THREADED + + +/** + * There are many cross-platform C++ Threading libraries. The goal of + * this class is not to replace (or match in functionality) those + * libraries. The goal of this class is to provide a simple Threading + * class with basic functionality. + */ +class LOG4CPLUS_EXPORT AbstractThread + : public virtual log4cplus::helpers::SharedObject +{ +public: + AbstractThread(); + // Disallow copying of instances of this class. + AbstractThread(const AbstractThread&) = delete; + AbstractThread& operator=(const AbstractThread&) = delete; + + bool isRunning() const; + virtual void start(); + void join () const; + virtual void run() = 0; + +protected: + // Force objects to be constructed on the heap + virtual ~AbstractThread(); + +private: + enum Flags + { + fRUNNING = 1, + fJOINED = 2 + }; + + std::unique_ptr thread; + mutable std::atomic flags; +}; + +typedef helpers::SharedObjectPtr AbstractThreadPtr; + + +#endif // LOG4CPLUS_SINGLE_THREADED + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_THREADS_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/tracelogger.h b/LFtid1056/cloudfront/code/log4cplus/tracelogger.h new file mode 100644 index 0000000..4fdbcce --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/tracelogger.h @@ -0,0 +1,87 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: tracelogger.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright 2009-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_TRACELOGGER_H +#define LOG4CPLUS_TRACELOGGER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus +{ + + +/** + * This class is used to produce "Trace" logging. When an instance of + * this class is created, it will log a "ENTER: " + msg + * log message if TRACE_LOG_LEVEL is enabled for logger. + * When an instance of this class is destroyed, it will log a + * "ENTER: " + msg log message if TRACE_LOG_LEVEL is enabled + * for logger. + *

+ * @see LOG4CPLUS_TRACE + */ +class TraceLogger +{ +public: + TraceLogger(Logger l, log4cplus::tstring _msg, + const char* _file = LOG4CPLUS_CALLER_FILE (), + int _line = LOG4CPLUS_CALLER_LINE (), + char const * _function = LOG4CPLUS_CALLER_FUNCTION ()) + : logger(std::move (l)), msg(std::move (_msg)), file(_file), + function(_function), line(_line) + { + if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("ENTER: ") + msg, + file, line, function); + } + + ~TraceLogger() + { + if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("EXIT: ") + msg, + file, line, function); + } + +private: + TraceLogger (TraceLogger const &); + TraceLogger & operator = (TraceLogger const &); + + Logger logger; + log4cplus::tstring msg; + const char* file; + const char* function; + int line; +}; + + +} // log4cplus + + +#endif // LOG4CPLUS_TRACELOGGER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/tstring.h b/LFtid1056/cloudfront/code/log4cplus/tstring.h new file mode 100644 index 0000000..7526568 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/tstring.h @@ -0,0 +1,128 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: tstring.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2017 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_TSTRING_HEADER_ +#define LOG4CPLUS_TSTRING_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +namespace log4cplus +{ + +typedef std::basic_string tstring; + + +namespace helpers +{ + +inline +std::string +tostring (char const * str) +{ + return std::string (str); +} + +inline +std::string +tostring (std::string const & str) +{ + return str; +} + +inline +std::string const & +tostring (std::string & str) +{ + return str; +} + +inline +std::string +tostring (std::string && str) +{ + return std::move (str); +} + + +inline +std::wstring +towstring (wchar_t const * str) +{ + return std::wstring (str); +} + +inline +std::wstring +towstring (std::wstring const & str) +{ + return str; +} + +inline +std::wstring const & +towstring (std::wstring & str) +{ + return str; +} + +inline +std::wstring +towstring (std::wstring && str) +{ + return std::move (str); +} + + +LOG4CPLUS_EXPORT std::string tostring(const std::wstring&); +LOG4CPLUS_EXPORT std::string tostring(wchar_t const *); + +LOG4CPLUS_EXPORT std::wstring towstring(const std::string&); +LOG4CPLUS_EXPORT std::wstring towstring(char const *); + +} // namespace helpers + +#ifdef UNICODE + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) log4cplus::helpers::tostring(STRING) + +#else // UNICODE + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) (std::string(STRING)) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) STRING +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) STRING + +#endif // UNICODE + +} // namespace log4cplus + + +#endif // LOG4CPLUS_TSTRING_HEADER_ diff --git a/LFtid1056/cloudfront/code/log4cplus/version.h b/LFtid1056/cloudfront/code/log4cplus/version.h new file mode 100644 index 0000000..0daf2f1 --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/version.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +// Copyright (C) 2010-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#if ! defined (LOG4CPLUS_VERSION_H) +#define LOG4CPLUS_VERSION_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#define LOG4CPLUS_MAKE_VERSION(major, minor, point) \ + (major * 1000 * 1000u + minor * 1000u + point) + +#define LOG4CPLUS_MAKE_VERSION_STR(major, minor, point) \ + #major "." #minor "." #point + +//! This is log4cplus version number as unsigned integer. This must +//! be kept on a single line. It is used by Autotool and CMake build +//! systems to parse version number. +#define LOG4CPLUS_VERSION LOG4CPLUS_MAKE_VERSION(2, 1, 2) + +//! This is log4cplus version number as a string. +#define LOG4CPLUS_VERSION_STR LOG4CPLUS_MAKE_VERSION_STR(2, 1, 2) + + +namespace log4cplus +{ + +extern LOG4CPLUS_EXPORT unsigned const version; +extern LOG4CPLUS_EXPORT char const versionStr[]; + +} + +#endif diff --git a/LFtid1056/cloudfront/code/log4cplus/win32consoleappender.h b/LFtid1056/cloudfront/code/log4cplus/win32consoleappender.h new file mode 100644 index 0000000..0339c7f --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/win32consoleappender.h @@ -0,0 +1,93 @@ +// -*- C++ -*- +// Copyright (C) 2009-2017, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_WIN32CONSOLEAPPENDER_H +#define LOG4CPLUS_WIN32CONSOLEAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) + +#include + + +namespace log4cplus +{ + + /** + * Prints events to Win32 console. + * + *

Properties

+ *
+ *
AllocConsole
+ *
This boolean property specifies whether or not this appender + * will try to allocate new console using the + * AllocConsole() Win32 function.
+ * + *
logToStdErr
+ *
When it is set true, the output will be into + * STD_ERROR_HANDLE instead of STD_OUTPUT_HANDLE. + *
+ * + *
TextColor
+ *
See MSDN documentation for + * + * Character Attributes. + *
+ */ + class LOG4CPLUS_EXPORT Win32ConsoleAppender + : public Appender + { + public: + explicit Win32ConsoleAppender (bool allocConsole = true, + bool logToStdErr = false, unsigned int textColor = 0); + Win32ConsoleAppender (helpers::Properties const & properties); + virtual ~Win32ConsoleAppender (); + + virtual void close (); + + protected: + virtual void append (spi::InternalLoggingEvent const &); + + void write_handle (void *, tchar const *, std::size_t); + void write_console (void *, tchar const *, std::size_t); + + bool alloc_console; + bool log_to_std_err; + unsigned int text_color; + + private: + Win32ConsoleAppender (Win32ConsoleAppender const &); + Win32ConsoleAppender & operator = (Win32ConsoleAppender const &); + }; + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_WIN32CONSOLEAPPENDER_H diff --git a/LFtid1056/cloudfront/code/log4cplus/win32debugappender.h b/LFtid1056/cloudfront/code/log4cplus/win32debugappender.h new file mode 100644 index 0000000..31cbc3d --- /dev/null +++ b/LFtid1056/cloudfront/code/log4cplus/win32debugappender.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: win32debugappender.h +// Created: 12/2003 +// Author: Eduardo Francos, Odalio SARL +// +// +// Copyright 2003-2017 Odalio SARL +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ +#define LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING) + +#include + + +namespace log4cplus { + + /** + * Prints log events using OutputDebugString(). + */ + class LOG4CPLUS_EXPORT Win32DebugAppender + : public Appender + { + public: + // Ctors + Win32DebugAppender(); + Win32DebugAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~Win32DebugAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + Win32DebugAppender(const Win32DebugAppender&); + Win32DebugAppender& operator=(const Win32DebugAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING +#endif // LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ diff --git a/LFtid1056/cloudfront/code/main.cpp b/LFtid1056/cloudfront/code/main.cpp new file mode 100644 index 0000000..0590696 --- /dev/null +++ b/LFtid1056/cloudfront/code/main.cpp @@ -0,0 +1,597 @@ +///////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include //任务队列 +#include //信号处理 +#include //标准输入输出 +#include //字符串 +#include //数组型容器 +#include //映射 +#include //锁 +#include //线程 +#include //线程控制 +#include //原子操作 +#include //时间 +#include //时间 +#include //流处理 +#include //字符处理 +#include //格式控制 +#include //类消费者绑定 +#include //获取目录 +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "interface.h" //用于访问接口 +#include "log4cplus/log4.h" //用于日志 +#include "curl/curl.h" //用于访问接口 +#include "nlohmann/json.hpp" //用于构造json +#include "worker.h" //shell接口 +#include "rocketmq.h" +#include "rocketmq/MQClientException.h" +#include "front.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +using json = nlohmann::json; + +//////////////////////////////////////////////////////////////////////////////////////////////////////全局变量 + +//前置程序路径 +std::string FRONT_PATH; + + + +//初始化标志 +int INITFLAG = 0; + +//前置标置 +std::string subdir = "cfg_stat_data"; //默认稳态 +uint32_t g_node_id = 0; +int g_front_seg_index = 0; //默认单进程 +int g_front_seg_num = 0; //默认单进程 + +//实时进程标志 +int three_secs_enabled = 0; + +//稳态进程自动注册报告标志 +int auto_register_report_enabled = 0; + +//mq生产线程和定时线程都加上死锁计数器 +uint32_t g_mqproducer_blocked_times = 0; +uint32_t g_ontime_blocked_times = 0; + +//进程控制 +std::atomic running{true}; +void onSignal(int){ running = false; } + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +extern int G_TEST_FLAG; //测试线程开启开关 +extern int TEST_PORT; //测试端口号 + +extern std::string FRONT_INST; + +extern std::mutex queue_data_list_mutex; +extern std::list queue_data_list; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 功能函数 + +template +std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +//处理参数 +bool parse_param(int argc, char* argv[]) { + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + + // 处理 -s 参数 + if (arg == "-s" && i + 1 < argc) { + std::string val = argv[++i]; + auto pos = val.find('_'); + if (pos != std::string::npos) { + try { + g_front_seg_index = std::stoi(val.substr(0, pos)); + g_front_seg_num = std::stoi(val.substr(pos + 1)); + } catch (...) { + std::cerr << "Invalid -s format." << std::endl; + } + } + continue; + } + // 处理 -s1_5 这种紧凑写法 + if (arg.rfind("-s", 0) == 0 && arg.length() > 2) { + std::string val = arg.substr(2); + auto pos = val.find('_'); + if (pos != std::string::npos) { + try { + g_front_seg_index = std::stoi(val.substr(0, pos)); + g_front_seg_num = std::stoi(val.substr(pos + 1)); + } catch (...) { + std::cerr << "Invalid -s format." << std::endl; + } + } + continue; + } + // 处理 -d 或 -D 参数 + if ((arg == "-d" || arg == "-D") && i + 1 < argc) { + subdir = argv[++i]; + continue; + } + if ((arg.rfind("-d", 0) == 0 || arg.rfind("-D", 0) == 0) && arg.length() > 2) { + subdir = arg.substr(2); + continue; + } + // 这里可以继续添加其它参数解析,例如 -x, -y + // if (arg == "-x" ... ) {...} + } + + // 输出结果 + std::cout << "g_front_seg_index: " << g_front_seg_index << "\n"; + std::cout << "g_front_seg_num : " << g_front_seg_num << "\n"; + std::cout << "subdir : " << subdir << "\n"; + return true; +} + +//获取前置类型 +void init_global_function_enable() { + if (subdir == "cfg_stat_data") { // 历史稳态 + g_node_id = STAT_DATA_BASE_NODE_ID; + auto_register_report_enabled = 1; + } else if (subdir == "cfg_3s_data") { // 实时 + g_node_id = THREE_SECS_DATA_BASE_NODE_ID; + three_secs_enabled = 1; + } else if (subdir == "cfg_soe_comtrade") { // 告警、录波、暂态 + g_node_id = SOE_COMTRADE_BASE_NODE_ID; + } else if (subdir == "cfg_recallhis_data") { // 补招 + g_node_id = RECALL_HIS_DATA_BASE_NODE_ID; + } +} + +//获取功能名称 +std::string get_front_msg_from_subdir() { + if (subdir.find("cfg_3s_data") != std::string::npos) + return "实时数据进程"; + else if (subdir.find("cfg_soe_comtrade") != std::string::npos) + return "暂态和告警进程"; + else if (subdir.find("cfg_recallhis_data") != std::string::npos) + return "稳态补招进程"; + else if (subdir.find("cfg_stat_data") != std::string::npos) + return "稳态统计进程"; + else + return "unknown"; +} + +//获取前置路径 +std::string get_parent_directory() { + // 获取当前工作目录 + char cwd[PATH_MAX]; + if (!getcwd(cwd, sizeof(cwd))) { + // 获取失败 + return ""; + } + // dirname 可能会修改传入的字符串,需要副本 + std::string current_dir(cwd); + std::unique_ptr temp(new char[current_dir.size() + 1]); + std::strcpy(temp.get(), current_dir.c_str()); + + // 获取父目录 + char* parent = dirname(temp.get()); + if (!parent) return ""; + + // 返回绝对路径 + return std::string(parent); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////主要类结构 + +//------------------- Front 类(C++) ------------------- + + //构造函数 + Front::Front(): + m_worker(this), + m_threadPool(std::thread::hardware_concurrency()) // 用系统核数初始化线程池 + { + + //初始化g_node_id + init_global_function_enable(); + + //配置初始化 + init_config(); + + //启动进程日志 + init_logger_process(); + DIY_WARNLOG("process","【WARN】前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index); + + //读取台账 + parse_device_cfg_web(); + + //初始化日志 + init_loggers(); + + //读取模型,下载文件 + parse_model_cfg_web(); + + //解析文件 + Set_xml_nodeinfo(); + + StartFrontThread(); //开启主线程 + + StartMQConsumerThread(); //开启消费者线程 + + StartMQProducerThread(); //开启生产者线程 + + StartTimerThread(); //开启定时线程 + + //启动worker 根据启动标志启动 + if(G_TEST_FLAG){ + if(!m_worker.startServer(TEST_PORT)) { + std::cerr << "[testshell] startServer failed.\n"; + } + } + + //初始化标志 + std::this_thread::sleep_for(std::chrono::seconds(3)); + INITFLAG = 1; + + } + + Front::~Front() { + FormClosing(); + } + + // ============ 关闭所有运行中的线程============ + void Front::FormClosing() { + //确保testshell关闭 + m_worker.stopServer(); + + // **确保前置线程被关闭** + if(m_FrontThread.joinable()) { + m_bIsFrontThreadCancle = true; + m_FrontThread.join(); // **等待前置线程结束** + } + + // 定时线程 + if (m_TimerThread.joinable()) { + m_IsTimerCancel = true; + m_TimerThread.join(); + } + + // 生产者线程 + if (m_MQProducerThread.joinable()) { + m_IsMQProducerCancel = true; + m_MQProducerThread.join(); + } + + // 消费者线程 + m_IsMQConsumerCancel = true; + + if (m_mqConsumer) { + try { + m_mqConsumer->shutdown(); + } catch (...) { + std::cerr << "mq consumer shutdown error" << std::endl; + } + m_mqConsumer.reset(); + } + + m_listener.reset(); + + if (m_MQConsumerThread.joinable()) { + m_MQConsumerThread.join(); + } + + } + + //============ 线程函数 ============ + + void Front::StartFrontThread() { + m_bIsFrontThreadCancle = false; + m_FrontThread = std::thread(&Front::FrontThread, this); + } + + void Front::StartMQConsumerThread() { + m_IsMQConsumerCancel = false; + m_MQConsumerThread = std::thread(&Front::mqconsumerThread, this); + } + + void Front::StartMQProducerThread() { + m_IsMQProducerCancel = false; + m_MQProducerThread = std::thread(&Front::mqproducerThread, this); + } + + void Front::StartTimerThread() { + m_IsTimerCancel = false; + m_TimerThread = std::thread(&Front::OnTimerThread, this); + } + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////主功能线程 + +void Front::FrontThread() { + std::cout << "FrontThread::run() is called ...... \n"; + + try { + while (!m_bIsFrontThreadCancle) { + check_3s_config(); // 实时数据触发 + create_recall_xml(); // 生成待补招xml文件 + check_ledger_update(); // 触发台账更新 + } + } catch (const std::exception& e) { + std::cerr << "[FrontThread] Caught exception: " << e.what() << std::endl; + } catch (...) { + std::cerr << "[FrontThread] Caught unknown exception" << std::endl; + } + + // 设置重启标志 + { + std::lock_guard lock(m_threadCheckMutex); + m_needRestartFrontThread = true; + } + + std::cout << "[FrontThread] exited, will be restarted by monitor\n"; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////定时任务 + +void Front::OnTimerThread() +{ + try { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + std::cout << "OnTimerThread::run() is called ...... \n"; + + int counter = 0; + send_heartbeat_to_queue("1"); + + while (!m_IsTimerCancel) + { + update_log_entries_countdown(); + + if (counter >= 30) { + send_heartbeat_to_queue("1"); + counter = 0; + } + counter++; + + g_ontime_blocked_times = 0; + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + } catch (const std::exception& e) { + std::cerr << "[OnTimerThread] Caught exception: " << e.what() << std::endl; + } catch (...) { + std::cerr << "[OnTimerThread] Caught unknown exception" << std::endl; + } + + // 设置重启标志 + { + std::lock_guard lock(m_threadCheckMutex); + m_needRestartTimerThread = true; + } + + std::cout << "[OnTimerThread] exited, will be restarted by monitor\n"; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////消费者线程 + +void Front::mqconsumerThread() +{ + try { + std::string consumerGroup = subdir + std::to_string(g_front_seg_index); + std::string nameServer = G_MQCONSUMER_IPPORT; + std::vector subscriptions; + + if (g_node_id == THREE_SECS_DATA_BASE_NODE_ID) { + subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_RT, G_MQCONSUMER_TAG_RT, myMessageCallbackrtdata); + } + subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_UD, G_MQCONSUMER_TAG_UD, myMessageCallbackupdate); + if (g_node_id == RECALL_HIS_DATA_BASE_NODE_ID) { + subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_RC, G_MQCONSUMER_TAG_RC, myMessageCallbackrecall); + } + subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_SET, G_MQCONSUMER_TAG_SET, myMessageCallbackset); + subscriptions.emplace_back(FRONT_INST + "_" + G_MQCONSUMER_TOPIC_LOG, G_MQCONSUMER_TAG_LOG, myMessageCallbacklog); + + m_mqConsumer = make_unique(consumerGroup); + m_mqConsumer->setNamesrvAddr(nameServer); + m_mqConsumer->setSessionCredentials(G_MQCONSUMER_ACCESSKEY, G_MQCONSUMER_SECRETKEY, G_MQCONSUMER_CHANNEL); + m_mqConsumer->setInstanceName("inst_" + std::to_string(sGetMsTime())); + m_mqConsumer->setConsumeFromWhere(rocketmq::CONSUME_FROM_LAST_OFFSET); + + std::map callbackMap; + for (const auto& sub : subscriptions) { + std::string key = sub.topic + ":" + sub.tag; + callbackMap.emplace(key, sub.callback); + m_mqConsumer->subscribe(sub.topic, sub.tag); + std::cout << "[mqconsumerThread] 已订阅 Topic=\"" << sub.topic << "\", Tag=\"" << sub.tag << "\"" << std::endl; + } + + m_listener = std::make_shared(callbackMap); + m_mqConsumer->registerMessageListener(m_listener.get()); + + m_mqConsumer->start(); + std::cout << "[mqconsumerThread] Consumer 已启动,等待消息..." << std::endl; + + // ✳️ 保持线程不主动退出,由 RocketMQ 内部驱动执行回调 + // 如果 RocketMQ 内部机制失败或意外退出线程,就走 catch + } + catch (const rocketmq::MQClientException& e) { + std::cerr << "[mqconsumerThread] MQClientException: " << e.what() << std::endl; + std::lock_guard lock(m_threadCheckMutex); + m_needRestartConsumerThread = true; + return; + } catch (const std::exception& e) { + std::cerr << "[mqconsumerThread] std::exception: " << e.what() << std::endl; + std::lock_guard lock(m_threadCheckMutex); + m_needRestartConsumerThread = true; + return; + } catch (...) { + std::cerr << "[mqconsumerThread] Unknown exception" << std::endl; + std::lock_guard lock(m_threadCheckMutex); + m_needRestartConsumerThread = true; + return; + } + + // 程序运行中,消费者会通过回调处理消息,线程保持存活即可 + std::cout << "[mqconsumerThread] Consumer 线程正在运行,等待消息到达..." << std::endl; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////生产者线程 + +void Front::mqproducerThread() +{ + try { + // 1. 初始化生产者 + InitializeProducer(m_producer); + std::cout << "\n[mqproducerThread] is running ...... \n\n"; + + uint32_t count = 0; + + while (!m_IsMQProducerCancel) { + queue_data_t data; + bool data_gotten = false; + + if(INITFLAG) + { + std::lock_guard lock(queue_data_list_mutex); + if (!queue_data_list.empty()) { + data = queue_data_list.front(); + queue_data_list.pop_front(); + data_gotten = true; + } + } + + if (data_gotten) { + auto now = std::chrono::system_clock::now(); + auto ms_part = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + auto time_t_part = std::chrono::system_clock::to_time_t(now); + std::tm tm_buf; + localtime_r(&time_t_part, &tm_buf); + char timeStr[32]; + std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_buf); + + std::cout << "BEGIN my_queue_send no." << count + << " >>>> " << timeStr + << "." << std::setw(3) << std::setfill('0') << ms_part.count() + << std::endl; + + // 调用实际发送 + my_rocketmq_send(data, m_producer); + + now = std::chrono::system_clock::now(); + ms_part = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + time_t_part = std::chrono::system_clock::to_time_t(now); + localtime_r(&time_t_part, &tm_buf); + std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_buf); + + std::cout << "END my_queue_send no." << count++ + << " >>>> " << timeStr + << "." << std::setw(3) << std::setfill('0') << ms_part.count() + << "\n\n"; + } + + g_mqproducer_blocked_times = 0; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + std::cout << "[mqproducerThread] 正常退出\n"; + } + catch (const std::exception& e) { + std::cerr << "[mqproducerThread] std::exception: " << e.what() << std::endl; + std::lock_guard lock(m_threadCheckMutex); + m_needRestartProducerThread = true; + } + catch (...) { + std::cerr << "[mqproducerThread] unknown exception\n"; + std::lock_guard lock(m_threadCheckMutex); + m_needRestartProducerThread = true; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////用例,除通讯外其他功能都可实现 + +//int main(int argc char** argv) //变为线程 + +extern thread_info_t thread_info[THREAD_CONNECTIONS]; + +void* cloudfrontthread(void* arg) { +/////////////////////////////////////// + ThreadArgs* args = static_cast(arg); + int argc = args->argc; + char **argv = args->argv; + + printf("argc = %d, argv[0] = %s\n", argc, argv[0]); + + //添加线程处理 + int index = *(int*)argv[0]; + + // 更新线程状态为运行中 + pthread_mutex_lock(&thread_info[index].lock); + printf("cloudfrontthread %d started\n", index); + thread_info[index].state = THREAD_RUNNING; + pthread_mutex_unlock(&thread_info[index].lock); + +/////////////////////////////////////// + // 解析命令行参数 + if(!parse_param(argc,argv)){ + std::cerr << "process param error,exit" << std::endl; + return nullptr; + } + + // 线程使用完后清理参数 + delete args; + + //路径获取 + FRONT_PATH = get_parent_directory(); + std::cout << "FRONT_PATH:" << FRONT_PATH << std::endl; + + //声明前置 + std::unique_ptr FrontProcess; + FrontProcess = make_unique(); + + std::cout << "[Main] Program running in background.\n"; + + // 5) 主线程保持后台运行 + while(running) { + { + std::lock_guard lock(FrontProcess->m_threadCheckMutex); + + if (FrontProcess->m_needRestartFrontThread) { + std::cout << "[Monitor] Restarting FrontThread..." << std::endl; + FrontProcess->StartFrontThread(); + FrontProcess->m_needRestartFrontThread = false; + } + + if (FrontProcess->m_needRestartConsumerThread) { + std::cout << "[Monitor] Restarting MQConsumerThread..." << std::endl; + FrontProcess->StartMQConsumerThread(); + FrontProcess->m_needRestartConsumerThread = false; + } + + if (FrontProcess->m_needRestartProducerThread) { + std::cout << "[Monitor] Restarting MQProducerThread..." << std::endl; + FrontProcess->StartMQProducerThread(); + FrontProcess->m_needRestartProducerThread = false; + } + + if (FrontProcess->m_needRestartTimerThread) { + std::cout << "[Monitor] Restarting TimerThread..." << std::endl; + FrontProcess->StartTimerThread(); + FrontProcess->m_needRestartTimerThread = false; + } + } + + std::this_thread::sleep_for(std::chrono::seconds(60));//每分钟检测一次 + } + + return nullptr; +} + diff --git a/LFtid1056/cloudfront/code/nlohmann/adl_serializer.hpp b/LFtid1056/cloudfront/code/nlohmann/adl_serializer.hpp new file mode 100644 index 0000000..56a606c --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/adl_serializer.hpp @@ -0,0 +1,55 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +/// @sa https://json.nlohmann.me/api/adl_serializer/ +template +struct adl_serializer +{ + /// @brief convert a JSON value to any value type + /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ + template + static auto from_json(BasicJsonType && j, TargetType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /// @brief convert a JSON value to any value type + /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ + template + static auto from_json(BasicJsonType && j) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) + -> decltype(::nlohmann::from_json(std::forward(j), detail::identity_tag {})) + { + return ::nlohmann::from_json(std::forward(j), detail::identity_tag {}); + } + + /// @brief convert any value type to a JSON value + /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ + template + static auto to_json(BasicJsonType& j, TargetType && val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/byte_container_with_subtype.hpp b/LFtid1056/cloudfront/code/nlohmann/byte_container_with_subtype.hpp new file mode 100644 index 0000000..91382cd --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/byte_container_with_subtype.hpp @@ -0,0 +1,103 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // uint8_t, uint64_t +#include // tie +#include // move + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +/// @brief an internal type for a backed binary type +/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ +template +class byte_container_with_subtype : public BinaryType +{ + public: + using container_type = BinaryType; + using subtype_type = std::uint64_t; + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype() noexcept(noexcept(container_type())) + : container_type() + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) + : container_type(b) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) + : container_type(b) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ + byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + bool operator==(const byte_container_with_subtype& rhs) const + { + return std::tie(static_cast(*this), m_subtype, m_has_subtype) == + std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); + } + + bool operator!=(const byte_container_with_subtype& rhs) const + { + return !(rhs == *this); + } + + /// @brief sets the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ + void set_subtype(subtype_type subtype_) noexcept + { + m_subtype = subtype_; + m_has_subtype = true; + } + + /// @brief return the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ + constexpr subtype_type subtype() const noexcept + { + return m_has_subtype ? m_subtype : static_cast(-1); + } + + /// @brief return whether the value has a subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ + constexpr bool has_subtype() const noexcept + { + return m_has_subtype; + } + + /// @brief clears the binary subtype + /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ + void clear_subtype() noexcept + { + m_subtype = 0; + m_has_subtype = false; + } + + private: + subtype_type m_subtype = 0; + bool m_has_subtype = false; +}; + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/abi_macros.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/abi_macros.hpp new file mode 100644 index 0000000..f48b9eb --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/abi_macros.hpp @@ -0,0 +1,100 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/conversions/from_json.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/conversions/from_json.hpp new file mode 100644 index 0000000..aa2f0cb --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/conversions/from_json.hpp @@ -0,0 +1,497 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +#include +#include +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_null())) + { + JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); + } + n = nullptr; +} + +// overloads for basic_json template parameters +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < std::is_arithmetic::value&& + !std::is_same::value, + int > = 0 > +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); + } +} + +template +inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) + { + JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); + } + b = *j.template get_ptr(); +} + +template +inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); + } + s = *j.template get_ptr(); +} + +template < + typename BasicJsonType, typename StringType, + enable_if_t < + std::is_assignable::value + && is_detected_exact::value + && !std::is_same::value + && !is_json_ref::value, int > = 0 > +inline void from_json(const BasicJsonType& j, StringType& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); + } + + s = *j.template get_ptr(); +} + +template +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +#if !JSON_DISABLE_ENUM_SERIALIZATION +template::value, int> = 0> +inline void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} +#endif // JSON_DISABLE_ENUM_SERIALIZATION + +// forward_list doesn't have an insert method +template::value, int> = 0> +inline void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + l.clear(); + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get(); + }); +} + +// valarray doesn't have an insert method +template::value, int> = 0> +inline void from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + l.resize(j.size()); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType & elem) + { + return elem.template get(); + }); +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +{ + arr = *j.template get_ptr(); +} + +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template::value, + int> = 0> +auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) +{ + using std::end; + + ConstructibleArrayType ret; + ret.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(ret, end(ret)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template::value, + int> = 0> +inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) +{ + using std::end; + + ConstructibleArrayType ret; + std::transform( + j.begin(), j.end(), std::inserter(ret, end(ret)), + [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template < typename BasicJsonType, typename ConstructibleArrayType, + enable_if_t < + is_constructible_array_type::value&& + !is_constructible_object_type::value&& + !is_constructible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + + from_json_array_impl(j, arr, priority_tag<3> {}); +} + +template < typename BasicJsonType, typename T, std::size_t... Idx > +std::array from_json_inplace_array_impl(BasicJsonType&& j, + identity_tag> /*unused*/, index_sequence /*unused*/) +{ + return { { std::forward(j).at(Idx).template get()... } }; +} + +template < typename BasicJsonType, typename T, std::size_t N > +auto from_json(BasicJsonType&& j, identity_tag> tag) +-> decltype(from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + + return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); +} + +template +inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) + { + JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); + } + + bin = *j.template get_ptr(); +} + +template::value, int> = 0> +inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) + { + JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); + } + + ConstructibleObjectType ret; + const auto* inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get()); + }); + obj = std::move(ret); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < + std::is_arithmetic::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value, + int > = 0 > +inline void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); + } +} + +template +std::tuple from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) +{ + return std::make_tuple(std::forward(j).at(Idx).template get()...); +} + +template < typename BasicJsonType, class A1, class A2 > +std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) +{ + return {std::forward(j).at(0).template get(), + std::forward(j).at(1).template get()}; +} + +template +inline void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +{ + p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); +} + +template +std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) +{ + return from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +{ + t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +auto from_json(BasicJsonType&& j, TupleRelated&& t) +-> decltype(from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + + return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); +} + +template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +inline void from_json(const BasicJsonType& j, std::map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +inline void from_json(const BasicJsonType& j, std::unordered_map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM +template +inline void from_json(const BasicJsonType& j, std_fs::path& p) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); + } + p = *j.template get_ptr(); +} +#endif + +struct from_json_fn +{ + template + auto operator()(const BasicJsonType& j, T&& val) const + noexcept(noexcept(from_json(j, std::forward(val)))) + -> decltype(from_json(j, std::forward(val))) + { + return from_json(j, std::forward(val)); + } +}; + +} // namespace detail + +#ifndef JSON_HAS_CPP_17 +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +#endif +JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) + detail::static_const::value; +#ifndef JSON_HAS_CPP_17 +} // namespace +#endif + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/conversions/to_chars.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/conversions/to_chars.hpp new file mode 100644 index 0000000..e10741c --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/conversions/to_chars.hpp @@ -0,0 +1,1118 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2009 Florian Loitsch +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // array +#include // signbit, isfinite +#include // intN_t, uintN_t +#include // memcpy, memmove +#include // numeric_limits +#include // conditional + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + std::uint64_t f = 0; + int e = 0; + + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + JSON_ASSERT(x.e == y.e); + JSON_ASSERT(x.f >= y.f); + + return {x.f - y.f, x.e}; + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; + + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; + + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; + + std::uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + + return {h, x.e + y.e + 64}; + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + JSON_ASSERT(x.f != 0); + + while ((x.f >> 63u) == 0) + { + x.f <<= 1u; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + JSON_ASSERT(delta >= 0); + JSON_ASSERT(((x.f << delta) >> delta) == x.f); + + return {x.f << delta, target_exponent}; + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template +boundaries compute_boundaries(FloatType value) +{ + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional::type; + + const auto bits = static_cast(reinterpret_bits(value)); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = F == 0 && E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + std::uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr std::array kCachedPowers = + { + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + JSON_ASSERT(e >= -1500); + JSON_ASSERT(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + JSON_ASSERT(index >= 0); + JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + JSON_ASSERT(kAlpha <= cached.e + e + 64); + JSON_ASSERT(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + if (n >= 100000) + { + pow10 = 100000; + return 6; + } + if (n >= 10000) + { + pow10 = 10000; + return 5; + } + if (n >= 1000) + { + pow10 = 1000; + return 4; + } + if (n >= 100) + { + pow10 = 100; + return 3; + } + if (n >= 10) + { + pow10 = 10; + return 2; + } + + pow10 = 1; + return 1; +} + +inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) +{ + JSON_ASSERT(len >= 1); + JSON_ASSERT(dist <= delta); + JSON_ASSERT(rest <= delta); + JSON_ASSERT(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + && delta - rest >= ten_k + && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) + { + JSON_ASSERT(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + JSON_ASSERT(M_plus.e >= kAlpha); + JSON_ASSERT(M_plus.e <= kGamma); + + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + JSON_ASSERT(p1 > 0); + + std::uint32_t pow10{}; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + JSON_ASSERT(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +JSON_HEDLEY_NON_NULL(1) +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + JSON_ASSERT(m_plus.e == m_minus.e); + JSON_ASSERT(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template +JSON_HEDLEY_NON_NULL(1) +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); + + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) + const boundaries w = compute_boundaries(static_cast(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* append_exponent(char* buf, int e) +{ + JSON_ASSERT(e > -1000); + JSON_ASSERT(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + else + { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + JSON_ASSERT(min_exp < 0); + JSON_ASSERT(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n && n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast(n) - static_cast(k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (static_cast(n) + 2); + } + + if (0 < n && n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + JSON_ASSERT(k > n); + + std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); + buf[n] = '.'; + return buf + (static_cast(k) + 1U); + } + + if (min_exp < n && n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2U + static_cast(-n) + static_cast(k)); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast(k) - 1); + buf[1] = '.'; + buf += 1 + static_cast(k); + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template +JSON_HEDLEY_NON_NULL(1, 2) +JSON_HEDLEY_RETURNS_NON_NULL +char* to_chars(char* first, const char* last, FloatType value) +{ + static_cast(last); // maybe unused - fix warning + JSON_ASSERT(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + JSON_ASSERT(len <= std::numeric_limits::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; + + JSON_ASSERT(last - first >= kMaxExp + 2); + JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/conversions/to_json.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/conversions/to_json.hpp new file mode 100644 index 0000000..e39b779 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/conversions/to_json.hpp @@ -0,0 +1,446 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // copy +#include // begin, end +#include // string +#include // tuple, get +#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include // move, forward, declval, pair +#include // valarray +#include // vector + +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +////////////////// +// constructors // +////////////////// + +/* + * Note all external_constructor<>::construct functions need to call + * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an + * allocated value (e.g., a string). See bug issue + * https://github.com/nlohmann/json/issues/2865 for more information. + */ + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::boolean; + j.m_data.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value = s; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value = std::move(s); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleStringType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::string; + j.m_data.m_value.string = j.template create(str); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::binary; + j.m_data.m_value = typename BasicJsonType::binary_t(b); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::binary; + j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_float; + j.m_data.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_unsigned; + j.m_data.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::number_integer; + j.m_data.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = arr; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = std::move(arr); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value.array = j.template create(begin(arr), end(arr)); + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = value_t::array; + j.m_data.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_data.m_value.array->push_back(x); + j.set_parent(j.m_data.m_value.array->back()); + } + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray& arr) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::array; + j.m_data.m_value = value_t::array; + j.m_data.m_value.array->resize(arr.size()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); + } + j.set_parents(); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value = obj; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value = std::move(obj); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < !std::is_same::value, int > = 0 > + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_data.m_value.destroy(j.m_data.m_type); + j.m_data.m_type = value_t::object; + j.m_data.m_value.object = j.template create(begin(obj), end(obj)); + j.set_parents(); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template::value, int> = 0> +inline void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} + +template < typename BasicJsonType, typename BoolRef, + enable_if_t < + ((std::is_same::reference, BoolRef>::value + && !std::is_same ::reference, typename BasicJsonType::boolean_t&>::value) + || (std::is_same::const_reference, BoolRef>::value + && !std::is_same ::const_reference>, + typename BasicJsonType::boolean_t >::value)) + && std::is_convertible::value, int > = 0 > +inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept +{ + external_constructor::construct(j, static_cast(b)); +} + +template::value, int> = 0> +inline void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} + +template +inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor::construct(j, std::move(s)); +} + +template::value, int> = 0> +inline void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +#if !JSON_DISABLE_ENUM_SERIALIZATION +template::value, int> = 0> +inline void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} +#endif // JSON_DISABLE_ENUM_SERIALIZATION + +template +inline void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + +template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < is_compatible_array_type::value&& + !is_compatible_object_type::value&& + !is_compatible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template +inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +{ + external_constructor::construct(j, bin); +} + +template::value, int> = 0> +inline void to_json(BasicJsonType& j, const std::valarray& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template +inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > +inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor::construct(j, obj); +} + +template +inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor::construct(j, std::move(obj)); +} + +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int > = 0 > +inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + external_constructor::construct(j, arr); +} + +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +inline void to_json(BasicJsonType& j, const std::pair& p) +{ + j = { p.first, p.second }; +} + +// for https://github.com/nlohmann/json/pull/1134 +template>::value, int> = 0> +inline void to_json(BasicJsonType& j, const T& b) +{ + j = { {b.key(), b.value()} }; +} + +template +inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +{ + j = { std::get(t)... }; +} + +template::value, int > = 0> +inline void to_json(BasicJsonType& j, const T& t) +{ + to_json_tuple_impl(j, t, make_index_sequence::value> {}); +} + +#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM +template +inline void to_json(BasicJsonType& j, const std_fs::path& p) +{ + j = p.string(); +} +#endif + +struct to_json_fn +{ + template + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } +}; +} // namespace detail + +#ifndef JSON_HAS_CPP_17 +/// namespace to hold default `to_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +#endif +JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) + detail::static_const::value; +#ifndef JSON_HAS_CPP_17 +} // namespace +#endif + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/exceptions.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/exceptions.hpp new file mode 100644 index 0000000..5974d7b --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/exceptions.hpp @@ -0,0 +1,257 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +#include +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +//////////////// +// exceptions // +//////////////// + +/// @brief general exception of the @ref basic_json class +/// @sa https://json.nlohmann.me/api/basic_json/exception/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) + + static std::string name(const std::string& ename, int id_) + { + return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); + } + + static std::string diagnostics(std::nullptr_t /*leaf_element*/) + { + return ""; + } + + template + static std::string diagnostics(const BasicJsonType* leaf_element) + { +#if JSON_DIAGNOSTICS + std::vector tokens; + for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) + { + switch (current->m_parent->type()) + { + case value_t::array: + { + for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) + { + if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) + { + tokens.emplace_back(std::to_string(i)); + break; + } + } + break; + } + + case value_t::object: + { + for (const auto& element : *current->m_parent->m_data.m_value.object) + { + if (&element.second == current) + { + tokens.emplace_back(element.first.c_str()); + break; + } + } + break; + } + + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE + } + } + + if (tokens.empty()) + { + return ""; + } + + auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, + [](const std::string & a, const std::string & b) + { + return concat(a, '/', detail::escape(b)); + }); + return concat('(', str, ") "); +#else + static_cast(leaf_element); + return ""; +#endif + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/// @brief exception indicating a parse error +/// @sa https://json.nlohmann.me/api/basic_json/parse_error/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + template::value, int> = 0> + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) + { + const std::string w = concat(exception::name("parse_error", id_), "parse error", + position_string(pos), ": ", exception::diagnostics(context), what_arg); + return {id_, pos.chars_read_total, w.c_str()}; + } + + template::value, int> = 0> + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) + { + const std::string w = concat(exception::name("parse_error", id_), "parse error", + (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), + ": ", exception::diagnostics(context), what_arg); + return {id_, byte_, w.c_str()}; + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return concat(" at line ", std::to_string(pos.lines_read + 1), + ", column ", std::to_string(pos.chars_read_current_line)); + } +}; + +/// @brief exception indicating errors with iterators +/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ +class invalid_iterator : public exception +{ + public: + template::value, int> = 0> + static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) + { + const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/// @brief exception indicating executing a member function with a wrong type +/// @sa https://json.nlohmann.me/api/basic_json/type_error/ +class type_error : public exception +{ + public: + template::value, int> = 0> + static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) + { + const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/// @brief exception indicating access out of the defined range +/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ +class out_of_range : public exception +{ + public: + template::value, int> = 0> + static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) + { + const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/// @brief exception indicating other library errors +/// @sa https://json.nlohmann.me/api/basic_json/other_error/ +class other_error : public exception +{ + public: + template::value, int> = 0> + static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) + { + const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); + return {id_, w.c_str()}; + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/hash.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/hash.hpp new file mode 100644 index 0000000..4464e8e --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/hash.hpp @@ -0,0 +1,129 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // uint8_t +#include // size_t +#include // hash + +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// boost::hash_combine +inline std::size_t combine(std::size_t seed, std::size_t h) noexcept +{ + seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); + return seed; +} + +/*! +@brief hash a JSON value + +The hash function tries to rely on std::hash where possible. Furthermore, the +type of the JSON value is taken into account to have different hash values for +null, 0, 0U, and false, etc. + +@tparam BasicJsonType basic_json specialization +@param j JSON value to hash +@return hash value of j +*/ +template +std::size_t hash(const BasicJsonType& j) +{ + using string_t = typename BasicJsonType::string_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + + const auto type = static_cast(j.type()); + switch (j.type()) + { + case BasicJsonType::value_t::null: + case BasicJsonType::value_t::discarded: + { + return combine(type, 0); + } + + case BasicJsonType::value_t::object: + { + auto seed = combine(type, j.size()); + for (const auto& element : j.items()) + { + const auto h = std::hash {}(element.key()); + seed = combine(seed, h); + seed = combine(seed, hash(element.value())); + } + return seed; + } + + case BasicJsonType::value_t::array: + { + auto seed = combine(type, j.size()); + for (const auto& element : j) + { + seed = combine(seed, hash(element)); + } + return seed; + } + + case BasicJsonType::value_t::string: + { + const auto h = std::hash {}(j.template get_ref()); + return combine(type, h); + } + + case BasicJsonType::value_t::boolean: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_integer: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_unsigned: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_float: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::binary: + { + auto seed = combine(type, j.get_binary().size()); + const auto h = std::hash {}(j.get_binary().has_subtype()); + seed = combine(seed, h); + seed = combine(seed, static_cast(j.get_binary().subtype())); + for (const auto byte : j.get_binary()) + { + seed = combine(seed, std::hash {}(byte)); + } + return seed; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return 0; // LCOV_EXCL_LINE + } +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/input/binary_reader.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/input/binary_reader.hpp new file mode 100644 index 0000000..a6e100e --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/input/binary_reader.hpp @@ -0,0 +1,3009 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // generate_n +#include // array +#include // ldexp +#include // size_t +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf +#include // memcpy +#include // back_inserter +#include // numeric_limits +#include // char_traits, string +#include // make_pair, move +#include // vector + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// how to treat CBOR tags +enum class cbor_tag_handler_t +{ + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type +}; + +/*! +@brief determine system byte order + +@return true if and only if system's byte order is little endian + +@note from https://stackoverflow.com/a/1001328/266378 +*/ +static inline bool little_endianness(int num = 1) noexcept +{ + return *reinterpret_cast(&num) == 1; +} + +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using json_sax_t = SAX; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename char_traits::int_type; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) + { + (void)detail::is_sax_static_asserts {}; + } + + // make class move-only + binary_reader(const binary_reader&) = delete; + binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + binary_reader& operator=(const binary_reader&) = delete; + binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~binary_reader() = default; + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + @param[in] tag_handler how to treat CBOR tags + + @return whether parsing was successful + */ + JSON_HEDLEY_NON_NULL(3) + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + sax = sax_; + bool result = false; + + switch (format) + { + case input_format_t::bson: + result = parse_bson_internal(); + break; + + case input_format_t::cbor: + result = parse_cbor_internal(true, tag_handler); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + case input_format_t::bjdata: + result = parse_ubjson_internal(); + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result && strict) + { + if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_HEDLEY_UNLIKELY(current != char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, + exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); + } + } + + return result; + } + + private: + ////////// + // BSON // + ////////// + + /*! + @brief Reads in a BSON-object and passes it to the SAX-parser. + @return whether a valid BSON-value was passed to the SAX parser + */ + bool parse_bson_internal() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) + { + return false; + } + + return sax->end_object(); + } + + /*! + @brief Parses a C-style string from the BSON input. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @return `true` if the \x00-byte indicating the end of the string was + encountered before the EOF; false` indicates an unexpected EOF. + */ + bool get_bson_cstr(string_t& result) + { + auto out = std::back_inserter(result); + while (true) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) + { + return false; + } + if (current == 0x00) + { + return true; + } + *out++ = static_cast(current); + } + } + + /*! + @brief Parses a zero-terminated string of length @a len from the BSON + input. + @param[in] len The length (including the zero-byte at the end) of the + string to be read. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 1 + @return `true` if the string was successfully parsed + */ + template + bool get_bson_string(const NumberType len, string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 1)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); + } + + return get_string(input_format_t::bson, len - static_cast(1), result) && get() != char_traits::eof(); + } + + /*! + @brief Parses a byte array input of length @a len from the BSON input. + @param[in] len The length of the byte array to be read. + @param[in,out] result A reference to the binary variable where the read + array is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 0 + @return `true` if the byte array was successfully parsed + */ + template + bool get_bson_binary(const NumberType len, binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 0)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); + } + + // All BSON binary values have a subtype + std::uint8_t subtype{}; + get_number(input_format_t::bson, subtype); + result.set_subtype(subtype); + + return get_binary(input_format_t::bson, len, result); + } + + /*! + @brief Read a BSON document element of the given @a element_type. + @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html + @param[in] element_type_parse_position The position in the input stream, + where the `element_type` was read. + @warning Not all BSON element types are supported yet. An unsupported + @a element_type will give rise to a parse_error.114: + Unsupported BSON record type 0x... + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_internal(const char_int_type element_type, + const std::size_t element_type_parse_position) + { + switch (element_type) + { + case 0x01: // double + { + double number{}; + return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len{}; + string_t value; + return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x05: // binary + { + std::int32_t len{}; + binary_t value; + return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + const std::string cr_str{cr.data()}; + return sax->parse_error(element_type_parse_position, cr_str, + parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); + } + } + } + + /*! + @brief Read a BSON element list (as specified in the BSON-spec) + + The same binary layout is used for objects and arrays, hence it must be + indicated with the argument @a is_array which one is expected + (true --> array, false --> object). + + @param[in] is_array Determines if the element list being read is to be + treated as an object (@a is_array == false), or as an + array (@a is_array == true). + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_list(const bool is_array) + { + string_t key; + + while (auto element_type = get()) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) + { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) + { + return false; + } + + if (!is_array && !sax->key(key)) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) + { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; + } + + /*! + @brief Reads an array from the BSON input and passes it to the SAX-parser. + @return whether a valid BSON-array was passed to the SAX parser + */ + bool parse_bson_array() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) + { + return false; + } + + return sax->end_array(); + } + + ////////// + // CBOR // + ////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true) or whether the last read character should + be considered instead (false) + @param[in] tag_handler how CBOR tags should be treated + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) + { + switch (get_char ? get() : current) + { + // EOF + case char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) + - static_cast(number)); + } + + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // Binary data (one-byte uint8_t for n follows) + case 0x59: // Binary data (two-byte uint16_t for n follow) + case 0x5A: // Binary data (four-byte uint32_t for n follow) + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + case 0x5F: // Binary data (indefinite length) + { + binary_t b; + return get_cbor_binary(b) && sax->binary(b); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) && sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array( + conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(static_cast(-1), tag_handler); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(static_cast(-1), tag_handler); + + case 0xC6: // tagged item + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD8: // tagged item (1 bytes follow) + case 0xD9: // tagged item (2 bytes follow) + case 0xDA: // tagged item (4 bytes follow) + case 0xDB: // tagged item (8 bytes follow) + { + switch (tag_handler) + { + case cbor_tag_handler_t::error: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); + } + + case cbor_tag_handler_t::ignore: + { + // ignore binary subtype + switch (current) + { + case 0xD8: + { + std::uint8_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xD9: + { + std::uint16_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDA: + { + std::uint32_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDB: + { + std::uint64_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + default: + break; + } + return parse_cbor_internal(true, tag_handler); + } + + case cbor_tag_handler_t::store: + { + binary_t b; + // use binary subtype and store in binary container + switch (current) + { + case 0xD8: + { + std::uint8_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: + { + std::uint16_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: + { + std::uint32_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: + { + std::uint64_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + default: + return parse_cbor_internal(true, tag_handler); + } + get(); + return get_cbor_binary(b) && sax->binary(b); + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); + } + } + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (!get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); + } + } + } + + /*! + @brief reads a CBOR byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into the byte array. + Additionally, CBOR's byte arrays with indefinite lengths are supported. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_cbor_binary(binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) + { + return false; + } + + switch (current) + { + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + { + return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x58: // Binary data (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x59: // Binary data (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5A: // Binary data (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5F: // Binary data (indefinite length) + { + while (get() != 0xFF) + { + binary_t chunk; + if (!get_cbor_binary(chunk)) + { + return false; + } + result.insert(result.end(), chunk.begin(), chunk.end()); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); + } + } + } + + /*! + @param[in] len the length of the array or static_cast(-1) for an + array of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + if (len != static_cast(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or static_cast(-1) for an + object of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + if (len != 0) + { + string_t key; + if (len != static_cast(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + } + + return sax->end_object(); + } + + ///////////// + // MsgPack // + ///////////// + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(conditional_static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(conditional_static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) && sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xC4: // bin 8 + case 0xC5: // bin 16 + case 0xC6: // bin 32 + case 0xC7: // ext 8 + case 0xC8: // ext 16 + case 0xC9: // ext 32 + case 0xD4: // fixext 1 + case 0xD5: // fixext 2 + case 0xD6: // fixext 4 + case 0xD7: // fixext 8 + case 0xD8: // fixext 16 + { + binary_t b; + return get_msgpack_binary(b) && sax->binary(b); + } + + case 0xCA: // float 32 + { + float number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xDC: // array 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); + } + } + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); + } + } + } + + /*! + @brief reads a MessagePack byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into a byte array. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_msgpack_binary(binary_t& result) + { + // helper function to set the subtype + auto assign_and_return_true = [&result](std::int8_t subtype) + { + result.set_subtype(static_cast(subtype)); + return true; + }; + + switch (current) + { + case 0xC4: // bin 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC5: // bin 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC6: // bin 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC7: // ext 8 + { + std::uint8_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC8: // ext 16 + { + std::uint16_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC9: // ext 32 + { + std::uint32_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xD4: // fixext 1 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 1, result) && + assign_and_return_true(subtype); + } + + case 0xD5: // fixext 2 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 2, result) && + assign_and_return_true(subtype); + } + + case 0xD6: // fixext 4 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 4, result) && + assign_and_return_true(subtype); + } + + case 0xD7: // fixext 8 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 8, result) && + assign_and_return_true(subtype); + } + + case 0xD8: // fixext 16 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 16, result) && + assign_and_return_true(subtype); + } + + default: // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + //////////// + // UBJSON // + //////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO(niels): may we ignore N here? + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) + { + return false; + } + + switch (current) + { + case 'U': + { + std::uint8_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'i': + { + std::int8_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'I': + { + std::int16_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'l': + { + std::int32_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'L': + { + std::int64_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + default: + break; + } + auto last_token = get_token_string(); + std::string message; + + if (input_format != input_format_t::bjdata) + { + message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; + } + else + { + message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; + } + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); + } + + /*! + @param[out] dim an integer vector storing the ND array dimensions + @return whether reading ND array size vector is successful + */ + bool get_ubjson_ndarray_size(std::vector& dim) + { + std::pair size_and_type; + size_t dimlen = 0; + bool no_ndarray = true; + + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) + { + return false; + } + + if (size_and_type.first != npos) + { + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) + { + return false; + } + dim.push_back(dimlen); + get_ignore_noop(); + } + } + return true; + } + + /*! + @param[out] result determined size + @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector + or ndarray dimension is not allowed; `false` means ndarray + is allowed; for output, `true` means an ndarray is found; + is_ndarray can only return `true` when its initial value + is `false` + @param[in] prefix type marker if already read, otherwise set to 0 + + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) + { + if (prefix == 0) + { + prefix = get_ignore_noop(); + } + + switch (prefix) + { + case 'U': + { + std::uint8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': + { + std::int8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } + result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char + return true; + } + + case 'I': + { + std::int16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } + result = static_cast(number); + return true; + } + + case 'l': + { + std::int32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } + result = static_cast(number); + return true; + } + + case 'L': + { + std::int64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } + if (!value_in_range_of(number)) + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), nullptr)); + } + result = static_cast(number); + return true; + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = conditional_static_cast(number); + return true; + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (!value_in_range_of(number)) + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), nullptr)); + } + result = detail::conditional_static_cast(number); + return true; + } + + case '[': + { + if (input_format != input_format_t::bjdata) + { + break; + } + if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); + } + std::vector dim; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) + { + return false; + } + if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector + { + result = dim.at(dim.size() - 1); + return true; + } + if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format + { + for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container + { + if ( i == 0 ) + { + result = 0; + return true; + } + } + + string_t key = "_ArraySize_"; + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) + { + return false; + } + result = 1; + for (auto i : dim) + { + result *= i; + if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + } + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast(i)))) + { + return false; + } + } + is_ndarray = true; + return sax->end_array(); + } + result = 0; + return true; + } + + default: + break; + } + auto last_token = get_token_string(); + std::string message; + + if (input_format != input_format_t::bjdata) + { + message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; + } + else + { + message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; + } + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) + { + result.first = npos; // size + result.second = 0; // type + bool is_ndarray = false; + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (input_format == input_format_t::bjdata + && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) + { + return false; + } + + get_ignore_noop(); + if (JSON_HEDLEY_UNLIKELY(current != '#')) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); + } + + const bool is_error = get_ubjson_size_value(result.first, is_ndarray); + if (input_format == input_format_t::bjdata && is_ndarray) + { + if (inside_ndarray) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, + exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); + } + result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters + } + return is_error; + } + + if (current == '#') + { + const bool is_error = get_ubjson_size_value(result.first, is_ndarray); + if (input_format == input_format_t::bjdata && is_ndarray) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, + exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); + } + return is_error; + } + + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const char_int_type prefix) + { + switch (prefix) + { + case char_traits::eof(): // EOF + return unexpect_eof(input_format, "value"); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + std::uint8_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'i': + { + std::int8_t number{}; + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'I': + { + std::int16_t number{}; + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'l': + { + std::int32_t number{}; + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'L': + { + std::int64_t number{}; + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'h': + { + if (input_format != input_format_t::bjdata) + { + break; + } + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte2 << 8u) + byte1); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 'd': + { + float number{}; + return get_number(input_format, number) && sax->number_float(static_cast(number), ""); + } + + case 'D': + { + double number{}; + return get_number(input_format, number) && sax->number_float(static_cast(number), ""); + } + + case 'H': + { + return get_ubjson_high_precision_number(); + } + + case 'C': // char + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) && sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + break; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): + // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} + + if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) + { + size_and_type.second &= ~(static_cast(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker + auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) + { + return p.first < t; + }); + string_t key = "_ArrayType_"; + if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); + } + + string_t type = it->second; // sax->string() takes a reference + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) + { + return false; + } + + if (size_and_type.second == 'C') + { + size_and_type.second = 'U'; + } + + key = "_ArrayData_"; + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) + { + return false; + } + + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + + return (sax->end_array() && sax->end_object()); + } + + if (size_and_type.first != npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + // do not accept ND-array size in objects in BJData + if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); + } + + string_t key; + if (size_and_type.first != npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + while (current != '}') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + // Note, no reader for UBJSON binary types is implemented because they do + // not exist + + bool get_ubjson_high_precision_number() + { + // get size of following number string + std::size_t size{}; + bool no_ndarray = true; + auto res = get_ubjson_size_value(size, no_ndarray); + if (JSON_HEDLEY_UNLIKELY(!res)) + { + return res; + } + + // get number string + std::vector number_vector; + for (std::size_t i = 0; i < size; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + number_vector.push_back(static_cast(current)); + } + + // parse number string + using ia_type = decltype(detail::input_adapter(number_vector)); + auto number_lexer = detail::lexer(detail::input_adapter(number_vector), false); + const auto result_number = number_lexer.scan(); + const auto number_string = number_lexer.get_token_string(); + const auto result_remainder = number_lexer.scan(); + + using token_type = typename detail::lexer_base::token_type; + + if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) + { + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, + exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); + } + + switch (result_number) + { + case token_type::value_integer: + return sax->number_integer(number_lexer.get_number_integer()); + case token_type::value_unsigned: + return sax->number_unsigned(number_lexer.get_number_unsigned()); + case token_type::value_float: + return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: + default: + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, + exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); + } + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `char_traits::eof()` in that case. + + @return character read from the input + */ + char_int_type get() + { + ++chars_read; + return current = ia.get_character(); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + char_int_type get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianness, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + On the other hand, BSON and BJData use little endian and should reorder + on big endian systems. + */ + template + bool get_number(const input_format_t format, NumberType& result) + { + // step 1: read input into array with system's byte order + std::array vec{}; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) + { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } + else + { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of characters to read + @param[out] result string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template + bool get_string(const input_format_t format, + const NumberType len, + string_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @brief create a byte array by reading bytes from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of bytes to read + @param[out] result byte array created by reading @a len bytes + + @return whether byte array creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of memory. + */ + template + bool get_binary(const input_format_t format, + const NumberType len, + binary_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @param[in] format the current format (for diagnostics) + @param[in] context further context information (for diagnostics) + @return whether the last read character is not EOF + */ + JSON_HEDLEY_NON_NULL(3) + bool unexpect_eof(const input_format_t format, const char* context) const + { + if (JSON_HEDLEY_UNLIKELY(current == char_traits::eof())) + { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::array cr{{}}; + static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return std::string{cr.data()}; + } + + /*! + @param[in] format the current format + @param[in] detail a detailed error message + @param[in] context further context information + @return a message string to use in the parse_error exceptions + */ + std::string exception_message(const input_format_t format, + const std::string& detail, + const std::string& context) const + { + std::string error_msg = "syntax error while parsing "; + + switch (format) + { + case input_format_t::cbor: + error_msg += "CBOR"; + break; + + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; + + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; + + case input_format_t::bson: + error_msg += "BSON"; + break; + + case input_format_t::bjdata: + error_msg += "BJData"; + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + return concat(error_msg, ' ', context, ": ", detail); + } + + private: + static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast(-1); + + /// input adapter + InputAdapterType ia; + + /// the current character + char_int_type current = char_traits::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianness + const bool is_little_endian = little_endianness(); + + /// input format + const input_format_t input_format = input_format_t::json; + + /// the SAX parser + json_sax_t* sax = nullptr; + + // excluded markers in bjdata optimized type +#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ + make_array('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') + +#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ + make_array( \ + bjd_type{'C', "char"}, \ + bjd_type{'D', "double"}, \ + bjd_type{'I', "int16"}, \ + bjd_type{'L', "int64"}, \ + bjd_type{'M', "uint64"}, \ + bjd_type{'U', "uint8"}, \ + bjd_type{'d', "single"}, \ + bjd_type{'i', "int8"}, \ + bjd_type{'l', "int32"}, \ + bjd_type{'m', "uint32"}, \ + bjd_type{'u', "uint16"}) + + JSON_PRIVATE_UNLESS_TESTED: + // lookup tables + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = + JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; + + using bjd_type = std::pair; + // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) + const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = + JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; + +#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ +#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr std::size_t binary_reader::npos; +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/input/input_adapters.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/input/input_adapters.hpp new file mode 100644 index 0000000..33fca3e --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/input/input_adapters.hpp @@ -0,0 +1,492 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // array +#include // size_t +#include // strlen +#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include // shared_ptr, make_shared, addressof +#include // accumulate +#include // string, char_traits +#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include // pair, declval + +#ifndef JSON_NO_IO + #include // FILE * + #include // istream +#endif // JSON_NO_IO + +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; + +//////////////////// +// input adapters // +//////////////////// + +#ifndef JSON_NO_IO +/*! +Input adapter for stdio file access. This adapter read only 1 byte and do not use any + buffer. This adapter is a very low level adapter. +*/ +class file_input_adapter +{ + public: + using char_type = char; + + JSON_HEDLEY_NON_NULL(2) + explicit file_input_adapter(std::FILE* f) noexcept + : m_file(f) + { + JSON_ASSERT(m_file != nullptr); + } + + // make class move-only + file_input_adapter(const file_input_adapter&) = delete; + file_input_adapter(file_input_adapter&&) noexcept = default; + file_input_adapter& operator=(const file_input_adapter&) = delete; + file_input_adapter& operator=(file_input_adapter&&) = delete; + ~file_input_adapter() = default; + + std::char_traits::int_type get_character() noexcept + { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE* m_file; +}; + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter +{ + public: + using char_type = char; + + ~input_stream_adapter() + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + if (is != nullptr) + { + is->clear(is->rdstate() & std::ios::eofbit); + } + } + + explicit input_stream_adapter(std::istream& i) + : is(&i), sb(i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&&) = delete; + + input_stream_adapter(input_stream_adapter&& rhs) noexcept + : is(rhs.is), sb(rhs.sb) + { + rhs.is = nullptr; + rhs.sb = nullptr; + } + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, e.g. 0xFFFFFFFF. + std::char_traits::int_type get_character() + { + auto res = sb->sbumpc(); + // set eof manually, as we don't use the istream interface. + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) + { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream* is = nullptr; + std::streambuf* sb = nullptr; +}; +#endif // JSON_NO_IO + +// General-purpose iterator-based adapter. It might not be as fast as +// theoretically possible for some containers, but it is extremely versatile. +template +class iterator_input_adapter +{ + public: + using char_type = typename std::iterator_traits::value_type; + + iterator_input_adapter(IteratorType first, IteratorType last) + : current(std::move(first)), end(std::move(last)) + {} + + typename char_traits::int_type get_character() + { + if (JSON_HEDLEY_LIKELY(current != end)) + { + auto result = char_traits::to_int_type(*current); + std::advance(current, 1); + return result; + } + + return char_traits::eof(); + } + + private: + IteratorType current; + IteratorType end; + + template + friend struct wide_string_input_helper; + + bool empty() const + { + return current == end; + } +}; + +template +struct wide_string_input_helper; + +template +struct wide_string_input_helper +{ + // UTF-32 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } +}; + +template +struct wide_string_input_helper +{ + // UTF-16 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc || wc >= 0xE000) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else + { + if (JSON_HEDLEY_UNLIKELY(!input.empty())) + { + const auto wc2 = static_cast(input.get_character()); + const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } +}; + +// Wraps another input adapter to convert wide character types into individual bytes. +template +class wide_string_input_adapter +{ + public: + using char_type = char; + + wide_string_input_adapter(BaseInputAdapter base) + : base_adapter(base) {} + + typename std::char_traits::int_type get_character() noexcept + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + fill_buffer(); + + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index == 0); + } + + // use buffer + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + BaseInputAdapter base_adapter; + + template + void fill_buffer() + { + wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } + + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + +template +struct iterator_input_adapter_factory +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using adapter_type = iterator_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(std::move(first), std::move(last)); + } +}; + +template +struct is_iterator_of_multibyte +{ + using value_type = typename std::iterator_traits::value_type; + enum + { + value = sizeof(value_type) > 1 + }; +}; + +template +struct iterator_input_adapter_factory::value>> +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using base_adapter_type = iterator_input_adapter; + using adapter_type = wide_string_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(base_adapter_type(std::move(first), std::move(last))); + } +}; + +// General purpose iterator-based input +template +typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) +{ + using factory_type = iterator_input_adapter_factory; + return factory_type::create(first, last); +} + +// Convenience shorthand from container to iterator +// Enables ADL on begin(container) and end(container) +// Encloses the using declarations in namespace for not to leak them to outside scope + +namespace container_input_adapter_factory_impl +{ + +using std::begin; +using std::end; + +template +struct container_input_adapter_factory {}; + +template +struct container_input_adapter_factory< ContainerType, + void_t()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + + static adapter_type create(const ContainerType& container) +{ + return input_adapter(begin(container), end(container)); +} + }; + +} // namespace container_input_adapter_factory_impl + +template +typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +{ + return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); +} + +#ifndef JSON_NO_IO +// Special cases with fast paths +inline file_input_adapter input_adapter(std::FILE* file) +{ + return file_input_adapter(file); +} + +inline input_stream_adapter input_adapter(std::istream& stream) +{ + return input_stream_adapter(stream); +} + +inline input_stream_adapter input_adapter(std::istream&& stream) +{ + return input_stream_adapter(stream); +} +#endif // JSON_NO_IO + +using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); + +// Null-delimited strings, and the like. +template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + !std::is_array::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > +contiguous_bytes_input_adapter input_adapter(CharT b) +{ + auto length = std::strlen(reinterpret_cast(b)); + const auto* ptr = reinterpret_cast(b); + return input_adapter(ptr, ptr + length); +} + +template +auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + return input_adapter(array, array + N); +} + +// This class only handles inputs of input_buffer_adapter type. +// It's required so that expressions like {ptr, len} can be implicitly cast +// to the correct adapter. +class span_input_adapter +{ + public: + template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > + span_input_adapter(CharT b, std::size_t l) + : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} + + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + span_input_adapter(IteratorType first, IteratorType last) + : ia(input_adapter(first, last)) {} + + contiguous_bytes_input_adapter&& get() + { + return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) + } + + private: + contiguous_bytes_input_adapter ia; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/input/json_sax.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/input/json_sax.hpp new file mode 100644 index 0000000..c772521 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/input/json_sax.hpp @@ -0,0 +1,727 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include // string +#include // move +#include // vector + +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief a floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string value was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string value. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief a binary value was read + @param[in] val binary value + @return whether parsing should proceed + @note It is safe to move the passed binary value. + */ + virtual bool binary(binary_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; + virtual ~json_sax() = default; +}; + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @param[in,out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + } + + return true; + } + + bool end_array() + { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_array()); + + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + return &root; + } + + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_data.m_value.array->back()); + } + + JSON_ASSERT(ref_stack.back()->is_object()); + JSON_ASSERT(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep && ref_stack.back()) + { + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back()) + { + if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + } + else + { + ref_stack.back()->set_parents(); + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (keep) + { + ref_stack.back()->set_parents(); + } + else + { + // discard array + *ref_stack.back() = discarded; + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) + { + ref_stack.back()->m_data.m_value.array->pop_back(); + } + + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + JSON_ASSERT(!keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (!keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + + // check callback + const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (!keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, & root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (!ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); + return {true, & (ref_stack.back()->m_data.m_value.array->back())}; + } + + // object + JSON_ASSERT(ref_stack.back()->is_object()); + // check if we should store an element for the current key + JSON_ASSERT(!key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (!store_element) + { + return {false, nullptr}; + } + + JSON_ASSERT(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool binary(binary_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = static_cast(-1)) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = static_cast(-1)) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/input/lexer.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/input/lexer.hpp new file mode 100644 index 0000000..4b3bf77 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/input/lexer.hpp @@ -0,0 +1,1633 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // array +#include // localeconv +#include // size_t +#include // snprintf +#include // strtof, strtod, strtold, strtoll, strtoull +#include // initializer_list +#include // char_traits, string +#include // move +#include // vector + +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////// +// lexer // +/////////// + +template +class lexer_base +{ + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + JSON_HEDLEY_RETURNS_NON_NULL + JSON_HEDLEY_CONST + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case token_type::value_unsigned: + case token_type::value_integer: + case token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } +}; +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template +class lexer : public lexer_base +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename char_traits::int_type; + + public: + using token_type = typename lexer_base::token_type; + + explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept + : ia(std::move(adapter)) + , ignore_comments(ignore_comments_) + , decimal_point_char(static_cast(get_decimal_point())) + {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + lexer& operator=(lexer&) = delete; + lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + JSON_HEDLEY_PURE + static char get_decimal_point() noexcept + { + const auto* loc = localeconv(); + JSON_ASSERT(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + JSON_ASSERT(current == 'u'); + int codepoint = 0; + + const auto factors = { 12u, 8u, 4u, 0u }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' && current <= '9') + { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } + else if (current >= 'A' && current <= 'F') + { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } + else if (current >= 'a' && current <= 'f') + { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } + else + { + return -1; + } + } + + JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list ranges) + { + JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 8259. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + JSON_ASSERT(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case char_traits::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result, so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(static_cast(codepoint)); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: + { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + /*! + * @brief scan a comment + * @return whether comment could be scanned successfully + */ + bool scan_comment() + { + switch (get()) + { + // single-line comments skip input until a newline or EOF is read + case '/': + { + while (true) + { + switch (get()) + { + case '\n': + case '\r': + case char_traits::eof(): + case '\0': + return true; + + default: + break; + } + } + } + + // multi-line comments skip input until */ is read + case '*': + { + while (true) + { + switch (get()) + { + case char_traits::eof(): + case '\0': + { + error_message = "invalid comment; missing closing '*/'"; + return false; + } + + case '*': + { + switch (get()) + { + case '/': + return true; + + default: + { + unget(); + continue; + } + } + } + + default: + continue; + } + } + } + + // unexpected character after reading '/' + default: + { + error_message = "invalid comment; expecting '/' or '*' after '/'"; + return false; + } + } + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 8259. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 8259. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() // lgtm [cpp/use-of-goto] + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + JSON_HEDLEY_NON_NULL(2) + token_type scan_literal(const char_type* literal_text, const std::size_t length, + token_type return_type) + { + JSON_ASSERT(char_traits::to_char_type(current) == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_HEDLEY_UNLIKELY(char_traits::to_char_type(get()) != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(char_traits::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `char_traits::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + char_int_type get() + { + ++position.chars_read_total; + ++position.chars_read_current_line; + + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia.get_character(); + } + + if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) + { + token_string.push_back(char_traits::to_char_type(current)); + } + + if (current == '\n') + { + ++position.lines_read; + position.chars_read_current_line = 0; + } + + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. + */ + void unget() + { + next_unget = true; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + + if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) + { + JSON_ASSERT(!token_string.empty()); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(char_int_type c) + { + token_buffer.push_back(static_cast(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr position_t get_position() const noexcept + { + return position; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if (static_cast(c) <= '\x1F') + { + // escape control characters + std::array cs{{}}; + static_cast((std::snprintf)(cs.data(), cs.size(), "", static_cast(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + result += cs.data(); + } + else + { + // add character as is + result.push_back(static_cast(c)); + } + } + + return result; + } + + /// return syntax error message + JSON_HEDLEY_RETURNS_NON_NULL + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + // check if we completely parse the BOM + return get() == 0xBB && get() == 0xBF; + } + + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + + void skip_whitespace() + { + do + { + get(); + } + while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); + } + + token_type scan() + { + // initially, skip the BOM + if (position.chars_read_total == 0 && !skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + skip_whitespace(); + + // ignore comments + while (ignore_comments && current == '/') + { + if (!scan_comment()) + { + return token_type::parse_error; + } + + // skip following whitespace + skip_whitespace(); + } + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + { + std::array true_literal = {{static_cast('t'), static_cast('r'), static_cast('u'), static_cast('e')}}; + return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); + } + case 'f': + { + std::array false_literal = {{static_cast('f'), static_cast('a'), static_cast('l'), static_cast('s'), static_cast('e')}}; + return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); + } + case 'n': + { + std::array null_literal = {{static_cast('n'), static_cast('u'), static_cast('l'), static_cast('l')}}; + return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + } + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + InputAdapterType ia; + + /// whether comments should be ignored (true) or signaled as errors (false) + const bool ignore_comments = false; + + /// the current character + char_int_type current = char_traits::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position {}; + + /// raw input token string (for error messages) + std::vector token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char_int_type decimal_point_char = '.'; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/input/parser.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/input/parser.hpp new file mode 100644 index 0000000..bdf85ba --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/input/parser.hpp @@ -0,0 +1,519 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // isfinite +#include // uint8_t +#include // function +#include // string +#include // move +#include // vector + +#include +#include +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +//////////// +// parser // +//////////// + +enum class parse_event_t : std::uint8_t +{ + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value +}; + +template +using parser_callback_t = + std::function; + +/*! +@brief syntax analysis + +This class implements a recursive descent parser. +*/ +template +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; + + public: + /// a parser reading from an input adapter + explicit parser(InputAdapterType&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true, + const bool skip_comments = false) + : callback(cb) + , m_lexer(std::move(adapter), skip_comments) + , allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), nullptr)); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + + result.assert_invariant(); + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse(SAX* sax, const bool strict = true) + { + (void)detail::is_sax_static_asserts {}; + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result && strict && (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); + } + + return result; + } + + private: + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse_internal(SAX* sax) + { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (!skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); + } + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + + break; + } + + case token_type::literal_false: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_HEDLEY_UNLIKELY(!sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); + } + case token_type::end_of_input: + { + if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); + } + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::literal_or_value: + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); + } + + // states.back() is false -> object + + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); + } + } + + /// get next token from lexer + token_type get_token() + { + return last_token = m_lexer.scan(); + } + + std::string exception_message(const token_type expected, const std::string& context) + { + std::string error_msg = "syntax error "; + + if (!context.empty()) + { + error_msg += concat("while parsing ", context, ' '); + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) + { + error_msg += concat(m_lexer.get_error_message(), "; last read: '", + m_lexer.get_token_string(), '\''); + } + else + { + error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += concat("; expected ", lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/input/position_t.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/input/position_t.hpp new file mode 100644 index 0000000..8ac7c78 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/input/position_t.hpp @@ -0,0 +1,37 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // size_t + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/iterators/internal_iterator.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/internal_iterator.hpp new file mode 100644 index 0000000..2991ee6 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/internal_iterator.hpp @@ -0,0 +1,35 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iter_impl.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iter_impl.hpp new file mode 100644 index 0000000..4447091 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iter_impl.hpp @@ -0,0 +1,751 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include // conditional, is_const, remove_const + +#include +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// forward declare, to be able to friend it later on +template class iteration_proxy; +template class iteration_proxy_value; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template +class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +{ + /// the iterator with BasicJsonType of different const-ness + using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + /// allow basic_json to access private members + friend other_iter_impl; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); + // superficial check for the LegacyBidirectionalIterator named requirement + static_assert(std::is_base_of::value + && std::is_base_of::iterator_category>::value, + "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); + + public: + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + iter_impl() = default; + ~iter_impl() = default; + iter_impl(iter_impl&&) noexcept = default; + iter_impl& operator=(iter_impl&&) noexcept = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief const copy constructor + @param[in] other const iterator to copy from + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more + information refer to: https://github.com/nlohmann/json/issues/1608 + */ + iter_impl(const iter_impl& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl& other) noexcept + { + if (&other != this) + { + m_object = other.m_object; + m_it = other.m_it; + } + return *this; + } + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl::type>& other) noexcept // NOLINT(cert-oop54-cpp) + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_data.m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_data.m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_data.m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_data.m_value.array->end(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); + return &*m_it.array_iterator; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator==(const IterImpl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator!=(const IterImpl& other) const + { + return !operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return !other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return !operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return !operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_data.m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + JSON_ASSERT(m_object != nullptr); + + if (JSON_HEDLEY_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + JSON_PRIVATE_UNLESS_TESTED: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it {}; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iteration_proxy.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iteration_proxy.hpp new file mode 100644 index 0000000..76293de --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iteration_proxy.hpp @@ -0,0 +1,242 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // size_t +#include // input_iterator_tag +#include // string, to_string +#include // tuple_size, get, tuple_element +#include // move + +#if JSON_HAS_RANGES + #include // enable_borrowed_range +#endif + +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +void int_to_string( string_type& target, std::size_t value ) +{ + // For ADL + using std::to_string; + target = to_string(value); +} +template class iteration_proxy_value +{ + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; + + private: + /// the iterator + IteratorType anchor{}; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable string_type array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + string_type empty_str{}; + + public: + explicit iteration_proxy_value() = default; + explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) + noexcept(std::is_nothrow_move_constructible::value + && std::is_nothrow_default_constructible::value) + : anchor(std::move(it)) + , array_index(array_index_) + {} + + iteration_proxy_value(iteration_proxy_value const&) = default; + iteration_proxy_value& operator=(iteration_proxy_value const&) = default; + // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions + iteration_proxy_value(iteration_proxy_value&&) + noexcept(std::is_nothrow_move_constructible::value + && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + iteration_proxy_value& operator=(iteration_proxy_value&&) + noexcept(std::is_nothrow_move_assignable::value + && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + ~iteration_proxy_value() = default; + + /// dereference operator (needed for range-based for) + const iteration_proxy_value& operator*() const + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_value& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) + { + auto tmp = iteration_proxy_value(anchor, array_index); + ++anchor; + ++array_index; + return tmp; + } + + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value& o) const + { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value& o) const + { + return anchor != o.anchor; + } + + /// return key of the iterator + const string_type& key() const + { + JSON_ASSERT(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + int_to_string( array_index_str, array_index ); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } +}; + +/// proxy class for the items() function +template class iteration_proxy +{ + private: + /// the container to iterate + typename IteratorType::pointer container = nullptr; + + public: + explicit iteration_proxy() = default; + + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(&cont) {} + + iteration_proxy(iteration_proxy const&) = default; + iteration_proxy& operator=(iteration_proxy const&) = default; + iteration_proxy(iteration_proxy&&) noexcept = default; + iteration_proxy& operator=(iteration_proxy&&) noexcept = default; + ~iteration_proxy() = default; + + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() const noexcept + { + return iteration_proxy_value(container->begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() const noexcept + { + return iteration_proxy_value(container->end()); + } +}; + +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +{ + return i.key(); +} +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +{ + return i.value(); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// The Addition to the STD Namespace is required to add +// Structured Bindings Support to the iteration_proxy_value class +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +namespace std +{ + +#if defined(__clang__) + // Fix: https://github.com/nlohmann/json/issues/1401 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) + : public std::integral_constant {}; + +template +class tuple_element> // NOLINT(cert-dcl58-cpp) +{ + public: + using type = decltype( + get(std::declval < + ::nlohmann::detail::iteration_proxy_value> ())); +}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + +} // namespace std + +#if JSON_HAS_RANGES + template + inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy> = true; +#endif diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iterator_traits.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iterator_traits.hpp new file mode 100644 index 0000000..84cc27a --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/iterator_traits.hpp @@ -0,0 +1,61 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // random_access_iterator_tag + +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/iterators/json_reverse_iterator.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/json_reverse_iterator.hpp new file mode 100644 index 0000000..006d549 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -0,0 +1,130 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // ptrdiff_t +#include // reverse_iterator +#include // declval + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template +class json_reverse_iterator : public std::reverse_iterator +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) + { + return static_cast(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) + { + return static_cast(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/iterators/primitive_iterator.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/primitive_iterator.hpp new file mode 100644 index 0000000..0b6e849 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/iterators/primitive_iterator.hpp @@ -0,0 +1,132 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // ptrdiff_t +#include // numeric_limits + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + JSON_PRIVATE_UNLESS_TESTED: + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + ++m_it; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) + { + auto result = *this; + --m_it; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/json_custom_base_class.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/json_custom_base_class.hpp new file mode 100644 index 0000000..d1e2916 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/json_custom_base_class.hpp @@ -0,0 +1,39 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // conditional, is_same + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief Default base class of the @ref basic_json class. + +So that the correct implementations of the copy / move ctors / assign operators +of @ref basic_json do not require complex case distinctions +(no base class / custom base class used as customization point), +@ref basic_json always has a base class. +By default, this class is used because it is empty and thus has no effect +on the behavior of @ref basic_json. +*/ +struct json_default_base {}; + +template +using json_base_class = typename std::conditional < + std::is_same::value, + json_default_base, + T + >::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/json_pointer.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/json_pointer.hpp new file mode 100644 index 0000000..4fdcd9a --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/json_pointer.hpp @@ -0,0 +1,988 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // all_of +#include // isdigit +#include // errno, ERANGE +#include // strtoull +#ifndef JSON_NO_IO + #include // ostream +#endif // JSON_NO_IO +#include // max +#include // accumulate +#include // string +#include // move +#include // vector + +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document +/// @sa https://json.nlohmann.me/api/json_pointer/ +template +class json_pointer +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + template + friend class json_pointer; + + template + struct string_t_helper + { + using type = T; + }; + + NLOHMANN_BASIC_JSON_TPL_DECLARATION + struct string_t_helper + { + using type = StringType; + }; + + public: + // for backwards compatibility accept BasicJsonType + using string_t = typename string_t_helper::type; + + /// @brief create JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ + explicit json_pointer(const string_t& s = "") + : reference_tokens(split(s)) + {} + + /// @brief return a string representation of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ + string_t to_string() const + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + string_t{}, + [](const string_t& a, const string_t& b) + { + return detail::concat(a, '/', detail::escape(b)); + }); + } + + /// @brief return a string representation of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ + JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) + operator string_t() const + { + return to_string(); + } + +#ifndef JSON_NO_IO + /// @brief write string representation of the JSON pointer to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) + { + o << ptr.to_string(); + return o; + } +#endif + + /// @brief append another JSON pointer at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(const json_pointer& ptr) + { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } + + /// @brief append an unescaped reference token at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(string_t token) + { + push_back(std::move(token)); + return *this; + } + + /// @brief append an array index at the end of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ + json_pointer& operator/=(std::size_t array_idx) + { + return *this /= std::to_string(array_idx); + } + + /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, + const json_pointer& rhs) + { + return json_pointer(lhs) /= rhs; + } + + /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) + { + return json_pointer(lhs) /= std::move(token); + } + + /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ + friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) + { + return json_pointer(lhs) /= array_idx; + } + + /// @brief returns the parent of this JSON pointer + /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ + json_pointer parent_pointer() const + { + if (empty()) + { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; + } + + /// @brief remove last reference token + /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ + void pop_back() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + reference_tokens.pop_back(); + } + + /// @brief return last reference token + /// @sa https://json.nlohmann.me/api/json_pointer/back/ + const string_t& back() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + return reference_tokens.back(); + } + + /// @brief append an unescaped token at the end of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ + void push_back(const string_t& token) + { + reference_tokens.push_back(token); + } + + /// @brief append an unescaped token at the end of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ + void push_back(string_t&& token) + { + reference_tokens.push_back(std::move(token)); + } + + /// @brief return whether pointer points to the root document + /// @sa https://json.nlohmann.me/api/json_pointer/empty/ + bool empty() const noexcept + { + return reference_tokens.empty(); + } + + private: + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index begins not with a digit + @throw out_of_range.404 if string @a s could not be converted to an integer + @throw out_of_range.410 if an array index exceeds size_type + */ + template + static typename BasicJsonType::size_type array_index(const string_t& s) + { + using size_type = typename BasicJsonType::size_type; + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) + { + JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); + } + + const char* p = s.c_str(); + char* p_end = nullptr; + errno = 0; // strtoull doesn't reset errno + const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) + if (p == p_end // invalid input or empty string + || errno == ERANGE // out of range + || JSON_HEDLEY_UNLIKELY(static_cast(p_end - p) != s.size())) // incomplete read + { + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); + } + + // only triggered on special platforms (like 32bit), see also + // https://github.com/nlohmann/json/pull/2203 + if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) + { + JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE + } + + return static_cast(res); + } + + JSON_PRIVATE_UNLESS_TESTED: + json_pointer top() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + private: + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + template + BasicJsonType& get_and_create(BasicJsonType& j) const + { + auto* result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->type()) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + result = &result->operator[](array_index(reference_token)); + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + template + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->is_null()) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) + { + return std::isdigit(x); + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums || reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + ptr = &ptr->operator[](array_index(reference_token)); + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + template + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, detail::concat( + "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), + ") is out of range"), ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + template + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); + } + + // use unchecked array access + ptr = &ptr->operator[](array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + template + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, detail::concat( + "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), + ") is out of range"), ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + */ + template + bool contains(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + if (!ptr->contains(reference_token)) + { + // we did not find the key in the object + return false; + } + + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) + { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) + { + if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) + { + // first char should be between '1' and '9' + return false; + } + for (std::size_t i = 1; i < reference_token.size(); i++) + { + if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) + { + // other char should be between '0' and '9' + return false; + } + } + } + + const auto idx = array_index(reference_token); + if (idx >= ptr->size()) + { + // index out of range + return false; + } + + ptr = &ptr->operator[](idx); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // we do not expect primitive values if there is still a + // reference token to process + return false; + } + } + } + + // no reference token left means we found a primitive value + return true; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector split(const string_t& reference_string) + { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == string_t::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == string_t::npos) + start = (slash == string_t::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != string_t::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + JSON_ASSERT(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || + (reference_token[pos + 1] != '0' && + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); + } + } + + // finally, store the reference token + detail::unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + private: + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + template + static void flatten(const string_t& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.type()) + { + case detail::value_t::array: + { + if (value.m_data.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) + { + flatten(detail::concat(reference_string, '/', std::to_string(i)), + value.m_data.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_data.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_data.m_value.object) + { + flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); + } + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + template + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_HEDLEY_UNLIKELY(!value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_data.m_value.object) + { + if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + // can't use conversion operator because of ambiguity + json_pointer convert() const& + { + json_pointer result; + result.reference_tokens = reference_tokens; + return result; + } + + json_pointer convert()&& + { + json_pointer result; + result.reference_tokens = std::move(reference_tokens); + return result; + } + + public: +#if JSON_HAS_THREE_WAY_COMPARISON + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + bool operator==(const json_pointer& rhs) const noexcept + { + return reference_tokens == rhs.reference_tokens; + } + + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) + bool operator==(const string_t& rhs) const + { + return *this == json_pointer(rhs); + } + + /// @brief 3-way compares two JSON pointers + template + std::strong_ordering operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* + { + return reference_tokens <=> rhs.reference_tokens; // *NOPAD* + } +#else + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept; + + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const json_pointer& lhs, + const StringType& rhs); + + /// @brief compares string and JSON pointer for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const StringType& lhs, + const json_pointer& rhs); + + /// @brief compares two JSON pointers for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept; + + /// @brief compares JSON pointer and string for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const json_pointer& lhs, + const StringType& rhs); + + /// @brief compares string and JSON pointer for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const StringType& lhs, + const json_pointer& rhs); + + /// @brief compares two JSON pointer for less-than + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept; +#endif + + private: + /// the reference tokens + std::vector reference_tokens; +}; + +#if !JSON_HAS_THREE_WAY_COMPARISON +// functions cannot be defined inside class due to ODR violations +template +inline bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept +{ + return lhs.reference_tokens == rhs.reference_tokens; +} + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) +inline bool operator==(const json_pointer& lhs, + const StringType& rhs) +{ + return lhs == json_pointer(rhs); +} + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) +inline bool operator==(const StringType& lhs, + const json_pointer& rhs) +{ + return json_pointer(lhs) == rhs; +} + +template +inline bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept +{ + return !(lhs == rhs); +} + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) +inline bool operator!=(const json_pointer& lhs, + const StringType& rhs) +{ + return !(lhs == rhs); +} + +template::string_t> +JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) +inline bool operator!=(const StringType& lhs, + const json_pointer& rhs) +{ + return !(lhs == rhs); +} + +template +inline bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept +{ + return lhs.reference_tokens < rhs.reference_tokens; +} +#endif + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/json_ref.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/json_ref.hpp new file mode 100644 index 0000000..b8bb6a7 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/json_ref.hpp @@ -0,0 +1,78 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)) + {} + + json_ref(const value_type& value) + : value_ref(&value) + {} + + json_ref(std::initializer_list init) + : owned_value(init) + {} + + template < + class... Args, + enable_if_t::value, int> = 0 > + json_ref(Args && ... args) + : owned_value(std::forward(args)...) + {} + + // class should be movable only + json_ref(json_ref&&) noexcept = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + json_ref& operator=(json_ref&&) = delete; + ~json_ref() = default; + + value_type moved_or_copied() const + { + if (value_ref == nullptr) + { + return std::move(owned_value); + } + return *value_ref; + } + + value_type const& operator*() const + { + return value_ref ? *value_ref : owned_value; + } + + value_type const* operator->() const + { + return &** this; + } + + private: + mutable value_type owned_value = nullptr; + value_type const* value_ref = nullptr; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/macro_scope.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/macro_scope.hpp new file mode 100644 index 0000000..97127a6 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/macro_scope.hpp @@ -0,0 +1,482 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // declval, pair +#include +#include + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +#include + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/macro_unscope.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/macro_unscope.hpp new file mode 100644 index 0000000..c6620d1 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/macro_unscope.hpp @@ -0,0 +1,45 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +// restore clang diagnostic settings +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + +// clean up +#undef JSON_ASSERT +#undef JSON_INTERNAL_CATCH +#undef JSON_THROW +#undef JSON_PRIVATE_UNLESS_TESTED +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL +#undef JSON_EXPLICIT +#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL +#undef JSON_INLINE_VARIABLE +#undef JSON_NO_UNIQUE_ADDRESS +#undef JSON_DISABLE_ENUM_SERIALIZATION +#undef JSON_USE_GLOBAL_UDLS + +#ifndef JSON_TEST_KEEP_MACROS + #undef JSON_CATCH + #undef JSON_TRY + #undef JSON_HAS_CPP_11 + #undef JSON_HAS_CPP_14 + #undef JSON_HAS_CPP_17 + #undef JSON_HAS_CPP_20 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #undef JSON_HAS_THREE_WAY_COMPARISON + #undef JSON_HAS_RANGES + #undef JSON_HAS_STATIC_RTTI + #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#include diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/call_std/begin.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/call_std/begin.hpp new file mode 100644 index 0000000..364cc89 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/call_std/begin.hpp @@ -0,0 +1,17 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/call_std/end.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/call_std/end.hpp new file mode 100644 index 0000000..463f070 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/call_std/end.hpp @@ -0,0 +1,17 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/cpp_future.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/cpp_future.hpp new file mode 100644 index 0000000..412b5aa --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/cpp_future.hpp @@ -0,0 +1,171 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + +#pragma once + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/detected.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/detected.hpp new file mode 100644 index 0000000..1db9bf9 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/detected.hpp @@ -0,0 +1,70 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/identity_tag.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/identity_tag.hpp new file mode 100644 index 0000000..269deff --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/identity_tag.hpp @@ -0,0 +1,21 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// dispatching helper struct +template struct identity_tag {}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/is_sax.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/is_sax.hpp new file mode 100644 index 0000000..4e02bc1 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/is_sax.hpp @@ -0,0 +1,159 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // size_t +#include // declval +#include // string + +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using null_function_t = decltype(std::declval().null()); + +template +using boolean_function_t = + decltype(std::declval().boolean(std::declval())); + +template +using number_integer_function_t = + decltype(std::declval().number_integer(std::declval())); + +template +using number_unsigned_function_t = + decltype(std::declval().number_unsigned(std::declval())); + +template +using number_float_function_t = decltype(std::declval().number_float( + std::declval(), std::declval())); + +template +using string_function_t = + decltype(std::declval().string(std::declval())); + +template +using binary_function_t = + decltype(std::declval().binary(std::declval())); + +template +using start_object_function_t = + decltype(std::declval().start_object(std::declval())); + +template +using key_function_t = + decltype(std::declval().key(std::declval())); + +template +using end_object_function_t = decltype(std::declval().end_object()); + +template +using start_array_function_t = + decltype(std::declval().start_array(std::declval())); + +template +using end_array_function_t = decltype(std::declval().end_array()); + +template +using parse_error_function_t = decltype(std::declval().parse_error( + std::declval(), std::declval(), + std::declval())); + +template +struct is_sax +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static constexpr bool value = + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value; +}; + +template +struct is_sax_static_asserts +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static_assert(is_detected_exact::value, + "Missing/invalid function: bool null()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_integer(number_integer_t)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool string(string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool binary(binary_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_object(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool key(string_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_object()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_array(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_array()"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool parse_error(std::size_t, const " + "std::string&, const exception&)"); +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/std_fs.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/std_fs.hpp new file mode 100644 index 0000000..fd18039 --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/std_fs.hpp @@ -0,0 +1,29 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#if JSON_HAS_EXPERIMENTAL_FILESYSTEM +#include +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +namespace std_fs = std::experimental::filesystem; +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END +#elif JSON_HAS_FILESYSTEM +#include +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +namespace std_fs = std::filesystem; +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END +#endif diff --git a/LFtid1056/cloudfront/code/nlohmann/detail/meta/type_traits.hpp b/LFtid1056/cloudfront/code/nlohmann/detail/meta/type_traits.hpp new file mode 100644 index 0000000..e1b000d --- /dev/null +++ b/LFtid1056/cloudfront/code/nlohmann/detail/meta/type_traits.hpp @@ -0,0 +1,795 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple +#include // char_traits + +#include +#include +#include +#include +#include +#include +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template