mirror of
https://github.com/deepinsight/insightface.git
synced 2026-04-05 15:30:29 +00:00
Add the inspireface project to cpp-package.
This commit is contained in:
191
cpp-package/inspireface/cpp/inspireface/CMakeLists.txt
Normal file
191
cpp-package/inspireface/cpp/inspireface/CMakeLists.txt
Normal file
@@ -0,0 +1,191 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(InspireFaceSDK)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++14")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
|
||||
# Current version
|
||||
set(INSPIRE_FACE_VERSION_MAJOR 1)
|
||||
set(INSPIRE_FACE_VERSION_MINOR 0)
|
||||
set(INSPIRE_FACE_VERSION_PATCH 0)
|
||||
# Converts the version number to a string
|
||||
string(CONCAT INSPIRE_FACE_VERSION_MAJOR_STR ${INSPIRE_FACE_VERSION_MAJOR})
|
||||
string(CONCAT INSPIRE_FACE_VERSION_MINOR_STR ${INSPIRE_FACE_VERSION_MINOR})
|
||||
string(CONCAT INSPIRE_FACE_VERSION_PATCH_STR ${INSPIRE_FACE_VERSION_PATCH})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/information.h.in ${CMAKE_CURRENT_SOURCE_DIR}/information.h)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.txt.in ${CMAKE_CURRENT_SOURCE_DIR}/version.txt)
|
||||
|
||||
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." ON)
|
||||
|
||||
file(GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/c_api/inspireface.cc) # Add C_API file
|
||||
|
||||
|
||||
if(NOT APPLE)
|
||||
find_package(OpenCV REQUIRED)
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID)
|
||||
|
||||
if (LINUX_FETCH_MNN)
|
||||
# Include FetchContent module
|
||||
include(FetchContent)
|
||||
# Fetch MNN
|
||||
message("Downloading MNN from https://github.com/alibaba/MNN.git, this may take a while.")
|
||||
FetchContent_Declare(
|
||||
mnn
|
||||
GIT_REPOSITORY https://github.com/alibaba/MNN.git
|
||||
GIT_TAG 2.7.0
|
||||
)
|
||||
set(MNN_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
set(MNN_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(MNN_BUILD_CONVERTER OFF CACHE BOOL "" FORCE)
|
||||
if(GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA)
|
||||
set(MNN_CUDA ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
FetchContent_MakeAvailable(mnn)
|
||||
set(MNN_INCLUDE_DIRS ${mnn_SOURCE_DIR}/include)
|
||||
if (MNN_BUILD_SHARED_LIBS)
|
||||
set(MNN_LIBS ${mnn_BINARY_DIR})
|
||||
else()
|
||||
set(MNN_LIBS ${mnn_BINARY_DIR}/libMNN.a)
|
||||
endif ()
|
||||
|
||||
elseif (GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA)
|
||||
# Use MNN Cuda
|
||||
message("Global MNN CUDA device inference")
|
||||
add_definitions("-DGLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA")
|
||||
set(MNN_INCLUDE_DIRS ${LINUX_MNN_CUDA}/include)
|
||||
link_directories(${LINUX_MNN_CUDA}/lib)
|
||||
set(MNN_LIBS MNN)
|
||||
|
||||
elseif(DEFINED MNN_STATIC_PATH)
|
||||
message("Using static MNN from specified path: ${MNN_STATIC_PATH}")
|
||||
set(MNN_INCLUDE_DIRS "${MNN_STATIC_PATH}/include")
|
||||
set(MNN_LIBS "${MNN_STATIC_PATH}/lib/libMNN.a")
|
||||
else ()
|
||||
# Default or fallback case for MNN setup
|
||||
message("Default or fallback case for MNN setup")
|
||||
set(MNN_INCLUDE_DIRS ${THIRD_PARTY_DIR}/MNN/${PLAT}-static/include)
|
||||
set(MNN_LIBS ${THIRD_PARTY_DIR}/MNN/${PLAT}-static/lib/libMNN.a)
|
||||
endif ()
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_RKNN)
|
||||
set(RKNN_API_INCLUDE_DIRS ${THIRD_PARTY_DIR}/${RKNPU_MAJOR}/runtime/${RK_DEVICE_TYPE}/Linux/librknn_api/include)
|
||||
set(RKNN_API_LIB ${THIRD_PARTY_DIR}/${RKNPU_MAJOR}/runtime/${RK_DEVICE_TYPE}/Linux/librknn_api/${CPU_ARCH}/)
|
||||
link_directories(${RKNN_API_LIB})
|
||||
endif()
|
||||
|
||||
# OpenCV
|
||||
if(APPLE AND USE_MOBILE_OPENCV_IN_LOCAL)
|
||||
set(LINK_THIRD_LIBS ${LINK_THIRD_LIBS} "${OPENCV_FRAMEWORK}" ${MNN_LIBS} "${ACCELERATE_FRAMEWORK}")
|
||||
else()
|
||||
set(LINK_THIRD_LIBS ${OpenCV_LIBS} ${MNN_LIBS})
|
||||
endif()
|
||||
|
||||
# sqlite3
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/middleware/sqlite/sqlite3.c) # Add C_API file
|
||||
|
||||
if (ENABLE_RKNN)
|
||||
set(LINK_THIRD_LIBS ${LINK_THIRD_LIBS} rknn_api dl)
|
||||
# InferenceHelp use RkNN
|
||||
add_definitions("-DINFERENCE_HELPER_ENABLE_RKNN")
|
||||
|
||||
endif()
|
||||
|
||||
# cpp yaml
|
||||
file(GLOB_RECURSE CPP_YAML_SRC ${CMAKE_CURRENT_SOURCE_DIR}/middleware/cpp_yaml/src/*.cpp)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${CPP_YAML_SRC})
|
||||
set(CPP_YAML_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/middleware/cpp_yaml/include)
|
||||
|
||||
# archive
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/middleware/model_archive/microtar/microtar.c)
|
||||
|
||||
# MNN
|
||||
link_directories(${MNN_LIBS})
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
add_library(InspireFace SHARED ${SOURCE_FILES})
|
||||
else()
|
||||
add_library(InspireFace STATIC ${SOURCE_FILES})
|
||||
endif()
|
||||
|
||||
target_compile_definitions(InspireFace PUBLIC INFERENCE_HELPER_ENABLE_MNN)
|
||||
target_compile_definitions(InspireFace PUBLIC FEATURE_BLOCK_ENABLE_OPENCV)
|
||||
|
||||
# Include files
|
||||
set(NEED_INCLUDE . ${MNN_INCLUDE_DIRS})
|
||||
if (ENABLE_RKNN)
|
||||
set(NEED_INCLUDE ${NEED_INCLUDE} ${RKNN_API_INCLUDE_DIRS})
|
||||
endif ()
|
||||
if (BUILD_LINUX_ARM7)
|
||||
set(NEED_INCLUDE ${NEED_INCLUDE} ${OpenCV_STATIC_INCLUDE_DIR})
|
||||
endif ()
|
||||
|
||||
# add cpp yaml header
|
||||
set(NEED_INCLUDE ${NEED_INCLUDE} ${CPP_YAML_INCLUDE})
|
||||
|
||||
if(PLAT STREQUAL "linux")
|
||||
find_package(Threads REQUIRED)
|
||||
set(LINK_THIRD_LIBS ${LINK_THIRD_LIBS} ${CMAKE_THREAD_LIBS_INIT} dl)
|
||||
endif()
|
||||
|
||||
target_include_directories(InspireFace PUBLIC
|
||||
${NEED_INCLUDE}
|
||||
)
|
||||
|
||||
if (NOT ANDROID)
|
||||
target_link_libraries(InspireFace PUBLIC ${LINK_THIRD_LIBS})
|
||||
|
||||
set_target_properties(InspireFace PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/
|
||||
)
|
||||
else()
|
||||
|
||||
endif()
|
||||
|
||||
# Print Message
|
||||
message(STATUS "InspireFace Core:")
|
||||
message(STATUS "\t Version: ${INSPIRE_FACE_VERSION_MAJOR}.${INSPIRE_FACE_VERSION_MINOR}.${INSPIRE_FACE_VERSION_PATCH}")
|
||||
message(STATUS "\t LINUX_FETCH_MNN: ${LINUX_FETCH_MNN}")
|
||||
message(STATUS "\t MNN_INCLUDE_DIRS: ${MNN_INCLUDE_DIRS}")
|
||||
message(STATUS "\t MNN_LIBS: ${MNN_LIBS}")
|
||||
message(STATUS "\t ENABLE_RKNN: ${ENABLE_RKNN}")
|
||||
if (ENABLE_RKNN)
|
||||
message(STATUS "\t RKNN_API_INCLUDE_DIRS: ${RKNN_API_INCLUDE_DIRS}")
|
||||
message(STATUS "\t RKNN_API_LIB: ${RKNN_API_LIB}")
|
||||
endif ()
|
||||
message(STATUS "\t BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}")
|
||||
if (GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA)
|
||||
message(STATUS "\t GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA: ${GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA}")
|
||||
endif ()
|
||||
|
||||
|
||||
# Install lib
|
||||
install(TARGETS InspireFace
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/InspireFace/lib
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/InspireFace/lib
|
||||
)
|
||||
|
||||
# Install header file
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/c_api/inspireface.h DESTINATION ${CMAKE_INSTALL_PREFIX}/InspireFace/include)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/herror.h DESTINATION ${CMAKE_INSTALL_PREFIX}/InspireFace/include)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/version.txt DESTINATION ${CMAKE_INSTALL_PREFIX}/)
|
||||
|
||||
if (ENABLE_RKNN)
|
||||
# Install rknn 3rd lib
|
||||
install(FILES ${RKNN_API_LIB}/librknn_api.so DESTINATION ${CMAKE_INSTALL_PREFIX}/InspireFace/lib)
|
||||
endif ()
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by tunm on 2024/4/17.
|
||||
//
|
||||
|
||||
#include "launch.h"
|
||||
#include "log.h"
|
||||
#include "herror.h"
|
||||
|
||||
|
||||
namespace inspire {
|
||||
|
||||
std::mutex Launch::mutex_;
|
||||
std::shared_ptr<Launch> Launch::instance_ = nullptr;
|
||||
|
||||
InspireArchive& Launch::getMArchive() {
|
||||
return m_archive_;
|
||||
}
|
||||
|
||||
std::shared_ptr<Launch> Launch::GetInstance() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!instance_) {
|
||||
instance_ = std::shared_ptr<Launch>(new Launch());
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int32_t Launch::Load(const std::string &path) {
|
||||
if (!m_load_) {
|
||||
m_archive_.ReLoad(path);
|
||||
if (m_archive_.QueryStatus() == SARC_SUCCESS) {
|
||||
m_load_ = true;
|
||||
return HSUCCEED;
|
||||
} else {
|
||||
return HERR_ARCHIVE_LOAD_MODEL_FAILURE;
|
||||
}
|
||||
} else {
|
||||
INSPIRE_LOGW("There is no need to call launch more than once, as subsequent calls will not affect the initialization.");
|
||||
return HSUCCEED;
|
||||
}
|
||||
}
|
||||
|
||||
bool Launch::isMLoad() const {
|
||||
return m_load_;
|
||||
}
|
||||
|
||||
} // namespace inspire
|
||||
@@ -0,0 +1,49 @@
|
||||
// Created by tunm on 2024/04/17.
|
||||
#pragma once
|
||||
#ifndef INSPIREFACE_LAUNCH_H
|
||||
#define INSPIREFACE_LAUNCH_H
|
||||
#include "middleware/model_archive/inspire_archive.h"
|
||||
#include <mutex>
|
||||
|
||||
#ifndef INSPIRE_API
|
||||
#define INSPIRE_API
|
||||
#endif
|
||||
|
||||
#define INSPIRE_LAUNCH inspire::Launch::GetInstance()
|
||||
|
||||
namespace inspire {
|
||||
|
||||
// The Launch class acts as the main entry point for the InspireFace system.
|
||||
// It is responsible for loading static resources such as models, configurations, and parameters.
|
||||
class INSPIRE_API Launch {
|
||||
public:
|
||||
Launch(const Launch&) = delete; // Delete the copy constructor to prevent copying.
|
||||
Launch& operator=(const Launch&) = delete; // Delete the assignment operator to prevent assignment.
|
||||
|
||||
// Retrieves the singleton instance of Launch, ensuring that only one instance exists.
|
||||
static std::shared_ptr<Launch> GetInstance();
|
||||
|
||||
// Loads the necessary resources from a specified path.
|
||||
// Returns an integer status code: 0 on success, non-zero on failure.
|
||||
int32_t Load(const std::string &path);
|
||||
|
||||
// Provides access to the loaded InspireArchive instance.
|
||||
InspireArchive& getMArchive();
|
||||
|
||||
// Checks if the resources have been successfully loaded.
|
||||
bool isMLoad() const;
|
||||
|
||||
private:
|
||||
Launch() : m_load_(false) {} ///< Private constructor for the singleton pattern.
|
||||
|
||||
static std::mutex mutex_; ///< Mutex for synchronizing access to the singleton instance.
|
||||
static std::shared_ptr<Launch> instance_; ///< The singleton instance of Launch.
|
||||
|
||||
InspireArchive m_archive_; ///< The archive containing all necessary resources.
|
||||
bool m_load_; ///< Flag indicating whether the resources have been successfully loaded.
|
||||
};
|
||||
|
||||
|
||||
} // namespace inspire
|
||||
|
||||
#endif //INSPIREFACE_LAUNCH_H
|
||||
625
cpp-package/inspireface/cpp/inspireface/c_api/inspireface.cc
Normal file
625
cpp-package/inspireface/cpp/inspireface/c_api/inspireface.cc
Normal file
@@ -0,0 +1,625 @@
|
||||
//
|
||||
// Created by tunm on 2023/10/3.
|
||||
//
|
||||
|
||||
#include "inspireface.h"
|
||||
#include "intypedef.h"
|
||||
#include "inspireface_internal.h"
|
||||
#include "information.h"
|
||||
#include "feature_hub/feature_hub.h"
|
||||
#include "Initialization_module/launch.h"
|
||||
|
||||
using namespace inspire;
|
||||
|
||||
HYPER_CAPI_EXPORT extern HResult HFCreateImageStream(PHFImageData data, HFImageStream* handle) {
|
||||
if (data == nullptr || handle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
|
||||
auto stream = new HF_CameraStream();
|
||||
switch (data->rotation) {
|
||||
case HF_CAMERA_ROTATION_90: stream->impl.SetRotationMode(ROTATION_90); break;
|
||||
case HF_CAMERA_ROTATION_180: stream->impl.SetRotationMode(ROTATION_180); break;
|
||||
case HF_CAMERA_ROTATION_270: stream->impl.SetRotationMode(ROTATION_270); break;
|
||||
default: stream->impl.SetRotationMode(ROTATION_0); break;
|
||||
}
|
||||
switch (data->format) {
|
||||
case HF_STREAM_RGB: stream->impl.SetDataFormat(RGB); break;
|
||||
case HF_STREAM_BGR: stream->impl.SetDataFormat(BGR); break;
|
||||
case HF_STREAM_RGBA: stream->impl.SetDataFormat(RGBA); break;
|
||||
case HF_STREAM_BGRA: stream->impl.SetDataFormat(BGRA); break;
|
||||
case HF_STREAM_YUV_NV12: stream->impl.SetDataFormat(NV12); break;
|
||||
case HF_STREAM_YUV_NV21: stream->impl.SetDataFormat(NV21); break;
|
||||
default: return HERR_INVALID_IMAGE_STREAM_PARAM; // Assume there's a return code for unsupported formats
|
||||
}
|
||||
stream->impl.SetDataBuffer(data->data, data->height, data->width);
|
||||
|
||||
*handle = (HFImageStream)stream;
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
HYPER_CAPI_EXPORT extern HResult HFReleaseImageStream(HFImageStream streamHandle) {
|
||||
if (streamHandle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
delete (HF_CameraStream*)streamHandle;
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
void HFDeBugImageStreamImShow(HFImageStream streamHandle) {
|
||||
if (streamHandle == nullptr) {
|
||||
INSPIRE_LOGE("Handle error");
|
||||
}
|
||||
HF_CameraStream *stream = (HF_CameraStream* ) streamHandle;
|
||||
if (stream == nullptr) {
|
||||
INSPIRE_LOGE("Image error");
|
||||
return;
|
||||
}
|
||||
auto image = stream->impl.GetScaledImage(1.0f, true);
|
||||
# ifdef DISABLE_GUI
|
||||
cv::imwrite("tmp.jpg", image);
|
||||
#else
|
||||
cv::imshow("Debug", image);
|
||||
cv::waitKey(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
HResult HFReleaseInspireFaceSession(HFSession handle) {
|
||||
if (handle == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
delete (HF_FaceAlgorithmSession*)handle;
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
HResult HFCreateInspireFaceSession(HFSessionCustomParameter parameter, HFDetectMode detectMode, HInt32 maxDetectFaceNum, HFSession *handle) {
|
||||
inspire::ContextCustomParameter param;
|
||||
param.enable_mask_detect = parameter.enable_mask_detect;
|
||||
param.enable_age = parameter.enable_age;
|
||||
param.enable_liveness = parameter.enable_liveness;
|
||||
param.enable_face_quality = parameter.enable_face_quality;
|
||||
param.enable_gender = parameter.enable_gender;
|
||||
param.enable_interaction_liveness = parameter.enable_interaction_liveness;
|
||||
param.enable_ir_liveness = parameter.enable_ir_liveness;
|
||||
param.enable_recognition = parameter.enable_recognition;
|
||||
inspire::DetectMode detMode = inspire::DETECT_MODE_IMAGE;
|
||||
if (detectMode == HF_DETECT_MODE_VIDEO) {
|
||||
detMode = inspire::DETECT_MODE_VIDEO;
|
||||
}
|
||||
|
||||
HF_FaceAlgorithmSession *ctx = new HF_FaceAlgorithmSession();
|
||||
auto ret = ctx->impl.Configuration(detMode, maxDetectFaceNum, param);
|
||||
if (ret != HSUCCEED) {
|
||||
delete ctx;
|
||||
*handle = nullptr;
|
||||
} else {
|
||||
*handle = ctx;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFCreateInspireFaceSessionOptional(HOption customOption, HFDetectMode detectMode, HInt32 maxDetectFaceNum, HFSession *handle) {
|
||||
inspire::ContextCustomParameter param;
|
||||
if (customOption & HF_ENABLE_FACE_RECOGNITION) {
|
||||
param.enable_recognition = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_LIVENESS) {
|
||||
param.enable_liveness = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_IR_LIVENESS) {
|
||||
param.enable_ir_liveness = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_AGE_PREDICT) {
|
||||
param.enable_age = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_GENDER_PREDICT) {
|
||||
param.enable_gender = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_MASK_DETECT) {
|
||||
param.enable_mask_detect = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_QUALITY) {
|
||||
param.enable_face_quality = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_INTERACTION) {
|
||||
param.enable_interaction_liveness = true;
|
||||
}
|
||||
inspire::DetectMode detMode = inspire::DETECT_MODE_IMAGE;
|
||||
if (detectMode == HF_DETECT_MODE_VIDEO) {
|
||||
detMode = inspire::DETECT_MODE_VIDEO;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = new HF_FaceAlgorithmSession();
|
||||
auto ret = ctx->impl.Configuration(detMode, maxDetectFaceNum, param);
|
||||
if (ret != HSUCCEED) {
|
||||
delete ctx;
|
||||
*handle = nullptr;
|
||||
} else {
|
||||
*handle = ctx;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFLaunchInspireFace(HPath resourcePath) {
|
||||
std::string path(resourcePath);
|
||||
return INSPIRE_LAUNCH->Load(resourcePath);
|
||||
}
|
||||
|
||||
HResult HFFeatureHubDataDisable() {
|
||||
return FEATURE_HUB->DisableHub();
|
||||
}
|
||||
|
||||
HResult HFFeatureHubDataEnable(HFFeatureHubConfiguration configuration) {
|
||||
inspire::DatabaseConfiguration param = {0};
|
||||
param.db_path = (configuration.dbPath != nullptr) ? std::string(configuration.dbPath) : std::string();
|
||||
param.enable_use_db = configuration.enablePersistence;
|
||||
param.feature_block_num = configuration.featureBlockNum;
|
||||
param.recognition_threshold = configuration.searchThreshold;
|
||||
param.search_mode = (SearchMode )configuration.searchMode;
|
||||
auto ret = FEATURE_HUB->EnableHub(param);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFSessionSetTrackPreviewSize(HFSession session, HInt32 previewSize) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
return ctx->impl.SetTrackPreviewSize(previewSize);
|
||||
}
|
||||
|
||||
HResult HFSessionSetFaceTrackMode(HFSession session, HFDetectMode detectMode) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
inspire::DetectMode detMode = inspire::DETECT_MODE_IMAGE;
|
||||
if (detectMode == HF_DETECT_MODE_VIDEO) {
|
||||
detMode = inspire::DETECT_MODE_VIDEO;
|
||||
}
|
||||
return ctx->impl.SetDetectMode(detMode);
|
||||
}
|
||||
|
||||
HResult HFSessionSetFaceDetectThreshold(HFSession session, HFloat threshold) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
return ctx->impl.SetFaceDetectThreshold(threshold);
|
||||
}
|
||||
|
||||
HResult HFExecuteFaceTrack(HFSession session, HFImageStream streamHandle, PHFMultipleFaceData results) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
if (streamHandle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_CameraStream *stream = (HF_CameraStream* ) streamHandle;
|
||||
if (stream == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
auto ret = ctx->impl.FaceDetectAndTrack(stream->impl);
|
||||
results->detectedNum = ctx->impl.GetNumberOfFacesCurrentlyDetected();
|
||||
results->rects = (HFaceRect *) ctx->impl.GetFaceRectsCache().data();
|
||||
results->trackIds = (HInt32 *) ctx->impl.GetTrackIDCache().data();
|
||||
results->angles.pitch = (HFloat *) ctx->impl.GetPitchResultsCache().data();
|
||||
results->angles.roll = (HFloat *) ctx->impl.GetRollResultsCache().data();
|
||||
results->angles.yaw = (HFloat *) ctx->impl.GetYawResultsCache().data();
|
||||
results->tokens = (HFFaceBasicToken *) ctx->impl.GetFaceBasicDataCache().data();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFCopyFaceBasicToken(HFFaceBasicToken token, HPBuffer buffer, HInt32 bufferSize) {
|
||||
if (bufferSize < sizeof(inspire::HyperFaceData)) {
|
||||
return HERR_INVALID_BUFFER_SIZE;
|
||||
}
|
||||
std::memcpy(buffer, token.data, sizeof(inspire::HyperFaceData));
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFGetFaceBasicTokenSize(HPInt32 bufferSize) {
|
||||
*bufferSize = sizeof(inspire::HyperFaceData);
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFFeatureHubFaceSearchThresholdSetting(float threshold) {
|
||||
FEATURE_HUB->SetRecognitionThreshold(threshold);
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFFaceFeatureExtract(HFSession session, HFImageStream streamHandle, HFFaceBasicToken singleFace, PHFFaceFeature feature) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
if (streamHandle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_CameraStream *stream = (HF_CameraStream* ) streamHandle;
|
||||
if (stream == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
if (singleFace.data == nullptr || singleFace.size <= 0) {
|
||||
return HERR_INVALID_FACE_TOKEN;
|
||||
}
|
||||
inspire::FaceBasicData data;
|
||||
data.dataSize = singleFace.size;
|
||||
data.data = singleFace.data;
|
||||
auto ret = ctx->impl.FaceFeatureExtract(stream->impl, data);
|
||||
feature->size = ctx->impl.GetFaceFeatureCache().size();
|
||||
feature->data = (HFloat *)ctx->impl.GetFaceFeatureCache().data();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HResult HFFaceFeatureExtractCpy(HFSession session, HFImageStream streamHandle, HFFaceBasicToken singleFace, HPFloat feature) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
if (streamHandle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_CameraStream *stream = (HF_CameraStream* ) streamHandle;
|
||||
if (stream == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
if (singleFace.data == nullptr || singleFace.size <= 0) {
|
||||
return HERR_INVALID_FACE_TOKEN;
|
||||
}
|
||||
inspire::FaceBasicData data;
|
||||
data.dataSize = singleFace.size;
|
||||
data.data = singleFace.data;
|
||||
auto ret = ctx->impl.FaceFeatureExtract(stream->impl, data);
|
||||
for (int i = 0; i < ctx->impl.GetFaceFeatureCache().size(); ++i) {
|
||||
feature[i] = ctx->impl.GetFaceFeatureCache()[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HResult HFFaceComparison(HFFaceFeature feature1, HFFaceFeature feature2, HPFloat result) {
|
||||
if (feature1.data == nullptr || feature2.data == nullptr) {
|
||||
return HERR_INVALID_FACE_FEATURE;
|
||||
}
|
||||
if (feature1.size != feature2.size) {
|
||||
INSPIRE_LOGE("feature1.size: %d, feature2.size: %d", feature1.size, feature2.size);
|
||||
return HERR_INVALID_FACE_FEATURE;
|
||||
}
|
||||
*result = 0.0f;
|
||||
float res = -1.0f;
|
||||
auto ret = FEATURE_HUB->CosineSimilarity(feature1.data, feature2.data, feature1.size, res);
|
||||
*result = res;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFGetFeatureLength(HPInt32 num) {
|
||||
*num = FEATURE_HUB->GetFeatureNum();
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
HResult HFFeatureHubInsertFeature(HFFaceFeatureIdentity featureIdentity) {
|
||||
if (featureIdentity.feature->data == nullptr) {
|
||||
return HERR_INVALID_FACE_FEATURE;
|
||||
}
|
||||
std::vector<float> feat;
|
||||
feat.reserve(featureIdentity.feature->size);
|
||||
for (int i = 0; i < featureIdentity.feature->size; ++i) {
|
||||
feat.push_back(featureIdentity.feature->data[i]);
|
||||
}
|
||||
std::string tag(featureIdentity.tag);
|
||||
HInt32 ret = FEATURE_HUB->FaceFeatureInsertFromCustomId(feat, tag, featureIdentity.customId);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HResult HFFeatureHubFaceSearch(HFFaceFeature searchFeature, HPFloat confidence, PHFFaceFeatureIdentity mostSimilar) {
|
||||
if (searchFeature.data == nullptr) {
|
||||
return HERR_INVALID_FACE_FEATURE;
|
||||
}
|
||||
std::vector<float> feat;
|
||||
feat.reserve(searchFeature.size);
|
||||
for (int i = 0; i < searchFeature.size; ++i) {
|
||||
feat.push_back(searchFeature.data[i]);
|
||||
}
|
||||
inspire::SearchResult result;
|
||||
HInt32 ret = FEATURE_HUB->SearchFaceFeature(feat, result);
|
||||
mostSimilar->feature = (HFFaceFeature* ) FEATURE_HUB->GetFaceFeaturePtrCache().get();
|
||||
mostSimilar->feature->data = (HFloat* ) FEATURE_HUB->GetSearchFaceFeatureCache().data();
|
||||
mostSimilar->feature->size = FEATURE_HUB->GetSearchFaceFeatureCache().size();
|
||||
mostSimilar->tag = FEATURE_HUB->GetStringCache();
|
||||
mostSimilar->customId = result.customId;
|
||||
*confidence = result.score;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFFeatureHubFaceSearchTopK(HFFaceFeature searchFeature, HInt32 topK, PHFSearchTopKResults results) {
|
||||
if (searchFeature.data == nullptr) {
|
||||
return HERR_INVALID_FACE_FEATURE;
|
||||
}
|
||||
std::vector<float> feat;
|
||||
feat.reserve(searchFeature.size);
|
||||
for (int i = 0; i < searchFeature.size; ++i) {
|
||||
feat.push_back(searchFeature.data[i]);
|
||||
}
|
||||
HInt32 ret = FEATURE_HUB->SearchFaceFeatureTopK(feat, topK);
|
||||
if (ret == HSUCCEED) {
|
||||
results->size = FEATURE_HUB->GetTopKConfidence().size();
|
||||
results->confidence = FEATURE_HUB->GetTopKConfidence().data();
|
||||
results->customIds = FEATURE_HUB->GetTopKCustomIdsCache().data();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFFeatureHubFaceRemove(HInt32 customId) {
|
||||
auto ret = FEATURE_HUB->FaceFeatureRemoveFromCustomId(customId);
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFFeatureHubFaceUpdate(HFFaceFeatureIdentity featureIdentity) {
|
||||
if (featureIdentity.feature->data == nullptr) {
|
||||
return HERR_INVALID_FACE_FEATURE;
|
||||
}
|
||||
std::vector<float> feat;
|
||||
feat.reserve(featureIdentity.feature->size);
|
||||
for (int i = 0; i < featureIdentity.feature->size; ++i) {
|
||||
feat.push_back(featureIdentity.feature->data[i]);
|
||||
}
|
||||
std::string tag(featureIdentity.tag);
|
||||
|
||||
auto ret = FEATURE_HUB->FaceFeatureUpdateFromCustomId(feat, tag, featureIdentity.customId);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFFeatureHubGetFaceIdentity(HInt32 customId, PHFFaceFeatureIdentity identity) {
|
||||
auto ret = FEATURE_HUB->GetFaceFeatureFromCustomId(customId);
|
||||
if (ret == HSUCCEED) {
|
||||
identity->tag = FEATURE_HUB->GetStringCache();
|
||||
identity->customId = customId;
|
||||
identity->feature = (HFFaceFeature* ) FEATURE_HUB->GetFaceFeaturePtrCache().get();
|
||||
identity->feature->data = (HFloat* ) FEATURE_HUB->GetFaceFeaturePtrCache()->data;
|
||||
identity->feature->size = FEATURE_HUB->GetFaceFeaturePtrCache()->dataSize;
|
||||
} else {
|
||||
identity->customId = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HResult HFMultipleFacePipelineProcess(HFSession session, HFImageStream streamHandle, PHFMultipleFaceData faces, HFSessionCustomParameter parameter) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
if (streamHandle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_CameraStream *stream = (HF_CameraStream* ) streamHandle;
|
||||
if (stream == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
if (faces->detectedNum <= 0 || faces->tokens->data == nullptr) {
|
||||
return HERR_INVALID_FACE_LIST;
|
||||
}
|
||||
inspire::ContextCustomParameter param;
|
||||
param.enable_mask_detect = parameter.enable_mask_detect;
|
||||
param.enable_age = parameter.enable_age;
|
||||
param.enable_liveness = parameter.enable_liveness;
|
||||
param.enable_face_quality = parameter.enable_face_quality;
|
||||
param.enable_gender = parameter.enable_gender;
|
||||
param.enable_interaction_liveness = parameter.enable_interaction_liveness;
|
||||
param.enable_ir_liveness = parameter.enable_ir_liveness;
|
||||
param.enable_recognition = parameter.enable_recognition;
|
||||
|
||||
HResult ret;
|
||||
std::vector<inspire::HyperFaceData> data;
|
||||
data.resize(faces->detectedNum);
|
||||
for (int i = 0; i < faces->detectedNum; ++i) {
|
||||
auto &face = data[i];
|
||||
ret = DeserializeHyperFaceData((char* )faces->tokens[i].data, faces->tokens[i].size, face);
|
||||
if (ret != HSUCCEED) {
|
||||
return HERR_INVALID_FACE_TOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ctx->impl.FacesProcess(stream->impl, data, param);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
HResult HFMultipleFacePipelineProcessOptional(HFSession session, HFImageStream streamHandle, PHFMultipleFaceData faces, HInt32 customOption) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
if (streamHandle == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_CameraStream *stream = (HF_CameraStream* ) streamHandle;
|
||||
if (stream == nullptr) {
|
||||
return HERR_INVALID_IMAGE_STREAM_HANDLE;
|
||||
}
|
||||
if (faces->detectedNum <= 0 || faces->tokens->data == nullptr) {
|
||||
return HERR_INVALID_FACE_LIST;
|
||||
}
|
||||
|
||||
inspire::ContextCustomParameter param;
|
||||
if (customOption & HF_ENABLE_FACE_RECOGNITION) {
|
||||
param.enable_recognition = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_LIVENESS) {
|
||||
param.enable_liveness = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_IR_LIVENESS) {
|
||||
param.enable_ir_liveness = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_AGE_PREDICT) {
|
||||
param.enable_age = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_GENDER_PREDICT) {
|
||||
param.enable_gender = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_MASK_DETECT) {
|
||||
param.enable_mask_detect = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_QUALITY) {
|
||||
param.enable_face_quality = true;
|
||||
}
|
||||
if (customOption & HF_ENABLE_INTERACTION) {
|
||||
param.enable_interaction_liveness = true;
|
||||
}
|
||||
|
||||
|
||||
HResult ret;
|
||||
std::vector<inspire::HyperFaceData> data;
|
||||
data.resize(faces->detectedNum);
|
||||
for (int i = 0; i < faces->detectedNum; ++i) {
|
||||
auto &face = data[i];
|
||||
ret = DeserializeHyperFaceData((char* )faces->tokens[i].data, faces->tokens[i].size, face);
|
||||
if (ret != HSUCCEED) {
|
||||
return HERR_INVALID_FACE_TOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ctx->impl.FacesProcess(stream->impl, data, param);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
HResult HFGetRGBLivenessConfidence(HFSession session, PHFRGBLivenessConfidence confidence) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
|
||||
confidence->num = ctx->impl.GetRgbLivenessResultsCache().size();
|
||||
confidence->confidence = (HFloat* )ctx->impl.GetRgbLivenessResultsCache().data();
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFGetFaceMaskConfidence(HFSession session, PHFFaceMaskConfidence confidence) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
|
||||
confidence->num = ctx->impl.GetMaskResultsCache().size();
|
||||
confidence->confidence = (HFloat* )ctx->impl.GetMaskResultsCache().data();
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFGetFaceQualityConfidence(HFSession session, PHFFaceQualityConfidence confidence) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
|
||||
confidence->num = ctx->impl.GetFaceQualityScoresResultsCache().size();
|
||||
confidence->confidence = (HFloat* )ctx->impl.GetFaceQualityScoresResultsCache().data();
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFFaceQualityDetect(HFSession session, HFFaceBasicToken singleFace, HFloat *confidence) {
|
||||
if (session == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
HF_FaceAlgorithmSession *ctx = (HF_FaceAlgorithmSession* ) session;
|
||||
if (ctx == nullptr) {
|
||||
return HERR_INVALID_CONTEXT_HANDLE;
|
||||
}
|
||||
|
||||
inspire::FaceBasicData data;
|
||||
data.dataSize = singleFace.size;
|
||||
data.data = singleFace.data;
|
||||
|
||||
auto ret = inspire::FaceContext::FaceQualityDetect(data, *confidence);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
HResult HFFeatureHubGetFaceCount(HInt32* count) {
|
||||
*count = FEATURE_HUB->GetFaceFeatureCount();
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFFeatureHubViewDBTable() {
|
||||
return FEATURE_HUB->ViewDBTable();
|
||||
}
|
||||
|
||||
|
||||
HResult HFQueryInspireFaceVersion(PHFInspireFaceVersion version) {
|
||||
version->major = std::stoi(INSPIRE_FACE_VERSION_MAJOR_STR);
|
||||
version->minor = std::stoi(INSPIRE_FACE_VERSION_MINOR_STR);
|
||||
version->patch = std::stoi(INSPIRE_FACE_VERSION_PATCH_STR);
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFSetLogLevel(HFLogLevel level) {
|
||||
INSPIRE_SET_LOG_LEVEL(LogLevel(level));
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
HResult HFLogDisable() {
|
||||
INSPIRE_SET_LOG_LEVEL(inspire::LOG_NONE);
|
||||
return HSUCCEED;
|
||||
}
|
||||
671
cpp-package/inspireface/cpp/inspireface/c_api/inspireface.h
Normal file
671
cpp-package/inspireface/cpp/inspireface/c_api/inspireface.h
Normal file
@@ -0,0 +1,671 @@
|
||||
//
|
||||
// Created by tunm on 2023/10/3.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_INSPIREFACE_H
|
||||
#define HYPERFACEREPO_INSPIREFACE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "intypedef.h"
|
||||
#include "herror.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifdef HYPER_BUILD_SHARED_LIB
|
||||
#define HYPER_CAPI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define HYPER_CAPI_EXPORT
|
||||
#endif
|
||||
#else
|
||||
#define HYPER_CAPI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HF_ENABLE_NONE 0x00000000 ///< Flag to enable no features.
|
||||
#define HF_ENABLE_FACE_RECOGNITION 0x00000002 ///< Flag to enable face recognition feature.
|
||||
#define HF_ENABLE_LIVENESS 0x00000004 ///< Flag to enable RGB liveness detection feature.
|
||||
#define HF_ENABLE_IR_LIVENESS 0x00000008 ///< Flag to enable IR (Infrared) liveness detection feature.
|
||||
#define HF_ENABLE_MASK_DETECT 0x00000010 ///< Flag to enable mask detection feature.
|
||||
#define HF_ENABLE_AGE_PREDICT 0x00000020 ///< Flag to enable age prediction feature.
|
||||
#define HF_ENABLE_GENDER_PREDICT 0x00000040 ///< Flag to enable gender prediction feature.
|
||||
#define HF_ENABLE_QUALITY 0x00000080 ///< Flag to enable face quality assessment feature.
|
||||
#define HF_ENABLE_INTERACTION 0x00000100 ///< Flag to enable interaction feature.
|
||||
|
||||
|
||||
/**
|
||||
* Camera stream format.
|
||||
* Contains several common camera stream formats available in the market.
|
||||
*/
|
||||
typedef enum HFImageFormat {
|
||||
HF_STREAM_RGB = 0, ///< Image in RGB format.
|
||||
HF_STREAM_BGR = 1, ///< Image in BGR format (Opencv Mat default).
|
||||
HF_STREAM_RGBA = 2, ///< Image in RGB format with alpha channel.
|
||||
HF_STREAM_BGRA = 3, ///< Image in BGR format with alpha channel.
|
||||
HF_STREAM_YUV_NV12 = 4, ///< Image in YUV NV12 format.
|
||||
HF_STREAM_YUV_NV21 = 5, ///< Image in YUV NV21 format.
|
||||
} HFImageFormat;
|
||||
|
||||
|
||||
/**
|
||||
* Camera picture rotation mode.
|
||||
* To accommodate the rotation of certain devices, four image rotation modes are provided.
|
||||
*/
|
||||
typedef enum HFRotation {
|
||||
HF_CAMERA_ROTATION_0 = 0, ///< 0 degree rotation.
|
||||
HF_CAMERA_ROTATION_90 = 1, ///< 90 degree rotation.
|
||||
HF_CAMERA_ROTATION_180 = 2, ///< 180 degree rotation.
|
||||
HF_CAMERA_ROTATION_270 = 3, ///< 270 degree rotation.
|
||||
} HFRotation;
|
||||
|
||||
|
||||
/**
|
||||
* Image Buffer Data structure.
|
||||
* Defines the structure for image data stream.
|
||||
*/
|
||||
typedef struct HFImageData {
|
||||
uint8_t *data; ///< Pointer to the image data stream.
|
||||
HInt32 width; ///< Width of the image.
|
||||
HInt32 height; ///< Height of the image.
|
||||
HFImageFormat format; ///< Format of the image, indicating the data stream format to be parsed.
|
||||
HFRotation rotation; ///< Rotation angle of the image.
|
||||
} HFImageData, *PHFImageData;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a data buffer stream instantiation object.
|
||||
*
|
||||
* This function is used to create an instance of a data buffer stream with the given image data.
|
||||
*
|
||||
* @param data Pointer to the image buffer data structure.
|
||||
* @param handle Pointer to the stream handle that will be returned.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFCreateImageStream(PHFImageData data, HFImageStream *handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Release the instantiated DataBuffer object.
|
||||
*
|
||||
* This function is used to release the DataBuffer object that has been previously instantiated.
|
||||
*
|
||||
* @param streamHandle Pointer to the DataBuffer handle representing the camera stream component.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFReleaseImageStream(HFImageStream streamHandle);
|
||||
|
||||
/************************************************************************
|
||||
* Resource Function
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Launch InspireFace SDK
|
||||
* Start the InspireFace SDK at the initialization stage of your program, as it is global and designed to be used only once.
|
||||
* It serves as a prerequisite for other function interfaces, so it is essential to ensure it is initialized before calling any other APIs.
|
||||
* @param resourcePath Initializes the path to the resource file that needs to be loaded
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
* */
|
||||
HYPER_CAPI_EXPORT extern HResult HFLaunchInspireFace(HPath resourcePath);
|
||||
|
||||
/************************************************************************
|
||||
* FaceContext
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Struct for custom parameters in face recognition context.
|
||||
*
|
||||
* This struct holds various flags to enable or disable specific features
|
||||
* in the face recognition context, such as face recognition, liveness detection,
|
||||
* mask detection, age and gender prediction, etc.
|
||||
*/
|
||||
typedef struct HFSessionCustomParameter {
|
||||
HInt32 enable_recognition; ///< Enable face recognition feature.
|
||||
HInt32 enable_liveness; ///< Enable RGB liveness detection feature.
|
||||
HInt32 enable_ir_liveness; ///< Enable IR liveness detection feature.
|
||||
HInt32 enable_mask_detect; ///< Enable mask detection feature.
|
||||
HInt32 enable_age; ///< Enable age prediction feature.
|
||||
HInt32 enable_gender; ///< Enable gender prediction feature.
|
||||
HInt32 enable_face_quality; ///< Enable face quality detection feature.
|
||||
HInt32 enable_interaction_liveness; ///< Enable interaction for liveness detection feature.
|
||||
} HFSessionCustomParameter, *PHFSessionCustomParameter;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration for face detection modes.
|
||||
*/
|
||||
typedef enum HFDetectMode {
|
||||
HF_DETECT_MODE_IMAGE, ///< Image detection mode, always detect.
|
||||
HF_DETECT_MODE_VIDEO, ///< Video detection mode, face tracking.
|
||||
} HFDetectMode;
|
||||
|
||||
/**
|
||||
* @brief Create a session from a resource file.
|
||||
*
|
||||
* @param parameter Custom parameters for session.
|
||||
* @param detectMode Detection mode to be used.
|
||||
* @param maxDetectFaceNum Maximum number of faces to detect.
|
||||
* @param handle Pointer to the context handle that will be returned.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFCreateInspireFaceSession(
|
||||
HFSessionCustomParameter parameter,
|
||||
HFDetectMode detectMode,
|
||||
HInt32 maxDetectFaceNum,
|
||||
HFSession *handle
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Create a session from a resource file with additional options.
|
||||
*
|
||||
* @param customOption Custom option for additional configuration.
|
||||
* @param detectMode Detection mode to be used.
|
||||
* @param maxDetectFaceNum Maximum number of faces to detect.
|
||||
* @param handle Pointer to the context handle that will be returned.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFCreateInspireFaceSessionOptional(
|
||||
HOption customOption,
|
||||
HFDetectMode detectMode,
|
||||
HInt32 maxDetectFaceNum,
|
||||
HFSession *handle
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Release the session.
|
||||
*
|
||||
* @param handle Handle to the session to be released.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFReleaseInspireFaceSession(HFSession handle);
|
||||
|
||||
/**
|
||||
* @brief Struct representing a basic token for face data.
|
||||
*
|
||||
* This struct holds the size and data pointer for a basic token associated with face data.
|
||||
*/
|
||||
typedef struct HFFaceBasicToken {
|
||||
HInt32 size; ///< Size of the token.
|
||||
HPVoid data; ///< Pointer to the token data.
|
||||
} HFFaceBasicToken, *PHFFaceBasicToken;
|
||||
|
||||
/**
|
||||
* @brief Struct for face Euler angles.
|
||||
*
|
||||
* This struct represents the Euler angles (roll, yaw, pitch) for face orientation.
|
||||
*/
|
||||
typedef struct HFFaceEulerAngle {
|
||||
HFloat *roll; ///< Roll angle of the face.
|
||||
HFloat *yaw; ///< Yaw angle of the face.
|
||||
HFloat *pitch; ///< Pitch angle of the face.
|
||||
} HFFaceEulerAngle;
|
||||
|
||||
/**
|
||||
* @brief Struct for holding data of multiple detected faces.
|
||||
*
|
||||
* This struct stores the data related to multiple faces detected, including the number of faces,
|
||||
* their bounding rectangles, track IDs, angles, and tokens.
|
||||
*/
|
||||
typedef struct HFMultipleFaceData {
|
||||
HInt32 detectedNum; ///< Number of faces detected.
|
||||
HFaceRect *rects; ///< Array of bounding rectangles for each face.
|
||||
HInt32 *trackIds; ///< Array of track IDs for each face.
|
||||
HFFaceEulerAngle angles; ///< Euler angles for each face.
|
||||
PHFFaceBasicToken tokens; ///< Tokens associated with each face.
|
||||
} HFMultipleFaceData, *PHFMultipleFaceData;
|
||||
|
||||
/**
|
||||
* @brief Set the track preview size in the session, it works with face detection and tracking algorithms.
|
||||
* Default preview size is 192(px).
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param previewSize The size of the preview for tracking.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFSessionSetTrackPreviewSize(HFSession session, HInt32 previewSize);
|
||||
|
||||
/**
|
||||
* @brief Set the face track mode in the session.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param detectMode The mode of the detection mode for tracking.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFSessionSetFaceTrackMode(HFSession session, HFDetectMode detectMode);
|
||||
|
||||
/**
|
||||
* @brief Set the face detect threshold in the session.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param detectMode The mode of the detection mode for tracking.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFSessionSetFaceDetectThreshold(HFSession session, HFloat threshold);
|
||||
|
||||
/**
|
||||
* @brief Run face tracking in the session.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param streamHandle Handle to the data buffer representing the camera stream component.
|
||||
* @param results Pointer to the structure where the results will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFExecuteFaceTrack(HFSession session, HFImageStream streamHandle, PHFMultipleFaceData results);
|
||||
|
||||
/**
|
||||
* @brief Copies the data from a HF_FaceBasicToken to a specified buffer.
|
||||
*
|
||||
* This function copies the data pointed to by the HF_FaceBasicToken's data field
|
||||
* into a user-provided buffer. The caller is responsible for ensuring that the buffer
|
||||
* is large enough to hold the data being copied.
|
||||
*
|
||||
* @param token The HF_FaceBasicToken containing the data to be copied.
|
||||
* @param buffer The buffer where the data will be copied to.
|
||||
* @param bufferSize The size of the buffer provided by the caller. Must be large enough
|
||||
* to hold the data pointed to by the token's data field.
|
||||
* @return HResult indicating the success or failure of the operation. Returns HSUCCEED
|
||||
* if the operation was successful, or an error code if the buffer was too small
|
||||
* or if any other error occurred.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFCopyFaceBasicToken(HFFaceBasicToken token, HPBuffer buffer, HInt32 bufferSize);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the size of the data contained in a HF_FaceBasicToken.
|
||||
*
|
||||
* This function is used to query the size of the data that a HF_FaceBasicToken is
|
||||
* expected to contain. This is useful for allocating a buffer of appropriate size
|
||||
* before copying data from a HF_FaceBasicToken.
|
||||
*
|
||||
* @param bufferSize Pointer to an integer where the size of the data will be stored.
|
||||
* On successful completion, this will contain the size of the data in bytes.
|
||||
* @return HResult indicating the success or failure of the operation. Returns HSUCCEED
|
||||
* if the operation was successful, or an error code if it failed.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFGetFaceBasicTokenSize(HPInt32 bufferSize);
|
||||
|
||||
/************************************************************************
|
||||
* Face Recognition
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Struct representing a face feature.
|
||||
*
|
||||
* This struct holds the data related to a face feature, including size and actual feature data.
|
||||
*/
|
||||
typedef struct HFFaceFeature {
|
||||
HInt32 size; ///< Size of the feature data.
|
||||
HPFloat data; ///< Pointer to the feature data.
|
||||
} HFFaceFeature, *PHFFaceFeature;
|
||||
|
||||
/**
|
||||
* @brief Extract a face feature from a given face.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param streamHandle Handle to the data buffer representing the camera stream component.
|
||||
* @param singleFace Basic token representing a single face.
|
||||
* @param feature Pointer to the extracted face feature.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult
|
||||
HFFaceFeatureExtract(HFSession session, HFImageStream streamHandle, HFFaceBasicToken singleFace, PHFFaceFeature feature);
|
||||
|
||||
/**
|
||||
* @brief Extract a face feature from a given face and copy it to the provided feature buffer.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param streamHandle Handle to the data buffer representing the camera stream component.
|
||||
* @param singleFace Basic token representing a single face.
|
||||
* @param feature Pointer to the buffer where the extracted feature will be copied.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult
|
||||
HFFaceFeatureExtractCpy(HFSession session, HFImageStream streamHandle, HFFaceBasicToken singleFace, HPFloat feature);
|
||||
|
||||
/************************************************************************
|
||||
* Feature Hub
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Select the search mode in the process of face recognition search,
|
||||
* and different modes will affect the execution efficiency and results
|
||||
* */
|
||||
typedef enum HFSearchMode {
|
||||
HF_SEARCH_MODE_EAGER = 0, // Eager mode: Stops when a vector meets the threshold.
|
||||
HF_SEARCH_MODE_EXHAUSTIVE, // Exhaustive mode: Searches until the best match is found.
|
||||
} HFSearchMode;
|
||||
|
||||
/**
|
||||
* @brief Struct for database configuration.
|
||||
*
|
||||
* This struct holds the configuration settings for using a database in the face recognition context.
|
||||
*/
|
||||
typedef struct HFFeatureHubConfiguration {
|
||||
HInt32 featureBlockNum; ///< The order of magnitude of face feature database is N * 512, and 20 is recommended by default
|
||||
HInt32 enablePersistence; ///< Flag to enable or disable the use of the database.
|
||||
HString dbPath; ///< Path to the database file.
|
||||
float searchThreshold; ///< Threshold for face search
|
||||
HFSearchMode searchMode; ///< Mode of face search
|
||||
} HFFeatureHubConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* @brief A lightweight face feature vector management.
|
||||
* @details FeatureHub is a built-in global lightweight face feature vector management functionality provided in the InspireFace-SDK.
|
||||
* It supports basic face feature search, deletion, and modification functions, and offers two optional data storage modes:
|
||||
* an in-memory model and a persistence model. If you have simple storage needs, you can enable it.
|
||||
*
|
||||
* @param configuration FeatureHub configuration details.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubDataEnable(HFFeatureHubConfiguration configuration);
|
||||
|
||||
/**
|
||||
* @brief Disable the global FeatureHub feature, and you can enable it again if needed.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
* */
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubDataDisable();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Struct representing the identity of a face feature.
|
||||
*
|
||||
* This struct associates a custom identifier and a tag with a specific face feature.
|
||||
*/
|
||||
typedef struct HFFaceFeatureIdentity {
|
||||
HInt32 customId; ///< Custom identifier for the face feature.
|
||||
HString tag; ///< Tag associated with the face feature.
|
||||
PHFFaceFeature feature; ///< Pointer to the face feature.
|
||||
} HFFaceFeatureIdentity, *PHFFaceFeatureIdentity;
|
||||
|
||||
/**
|
||||
* Search structure for top-k mode
|
||||
* */
|
||||
typedef struct HFSearchTopKResults {
|
||||
HInt32 size; ///< The number of faces searched
|
||||
HPFloat confidence; ///< Search confidence(it has already been filtered once by the threshold)
|
||||
HPInt32 customIds; ///< fACE customIds
|
||||
} HFSearchTopKResults, *PHFSearchTopKResults;
|
||||
|
||||
/**
|
||||
* @brief Set the face recognition search threshold.
|
||||
*
|
||||
* This function sets the threshold for face recognition, which determines the sensitivity
|
||||
* of the recognition process. A lower threshold may yield more matches but with less confidence.
|
||||
*
|
||||
* @param threshold The threshold value to set for face recognition (default is 0.48, suitable for access control scenarios).
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubFaceSearchThresholdSetting(float threshold);
|
||||
|
||||
/**
|
||||
* @brief Perform a one-to-one comparison of two face features.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param feature1 The first face feature for comparison.
|
||||
* @param feature2 The second face feature for comparison.
|
||||
* @param result Pointer to the floating-point value where the comparison result will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFaceComparison(HFFaceFeature feature1, HFFaceFeature feature2, HPFloat result);
|
||||
|
||||
/**
|
||||
* @brief Get the length of the face feature.
|
||||
*
|
||||
* @param num Pointer to an integer where the length of the feature will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFGetFeatureLength(HPInt32 num);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Insert a face feature identity into the features group.
|
||||
*
|
||||
* @param featureIdentity The face feature identity to be inserted.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubInsertFeature(HFFaceFeatureIdentity featureIdentity);
|
||||
|
||||
/**
|
||||
* @brief Search for the most similar face feature in the features group.
|
||||
*
|
||||
* @param searchFeature The face feature to be searched.
|
||||
* @param confidence Pointer to a floating-point value where the confidence level of the match will be stored.
|
||||
* @param mostSimilar Pointer to the most similar face feature identity found.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubFaceSearch(HFFaceFeature searchFeature, HPFloat confidence, PHFFaceFeatureIdentity mostSimilar);
|
||||
|
||||
/**
|
||||
* @brief Search for the most similar k facial features in the feature group
|
||||
*
|
||||
* @param searchFeature The face feature to be searched.
|
||||
* @param confidence topK Maximum number of searches
|
||||
* @param PHFSearchTopKResults Output search result
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubFaceSearchTopK(HFFaceFeature searchFeature, HInt32 topK, PHFSearchTopKResults results);
|
||||
|
||||
/**
|
||||
* @brief Remove a face feature from the features group based on custom ID.
|
||||
*
|
||||
* @param customId The custom ID of the feature to be removed.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubFaceRemove(HInt32 customId);
|
||||
|
||||
/**
|
||||
* @brief Update a face feature identity in the features group.
|
||||
*
|
||||
* @param featureIdentity The face feature identity to be updated.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubFaceUpdate(HFFaceFeatureIdentity featureIdentity);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a face feature identity from the features group based on custom ID.
|
||||
*
|
||||
* @param customId The custom ID of the feature.
|
||||
* @param identity Pointer to the face feature identity to be retrieved.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubGetFaceIdentity(HInt32 customId, PHFFaceFeatureIdentity identity);
|
||||
|
||||
/**
|
||||
* @brief Get the count of face features in the features group.
|
||||
*
|
||||
* @param count Pointer to an integer where the count of features will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubGetFaceCount(HInt32 *count);
|
||||
|
||||
/**
|
||||
* @brief View the face database table.
|
||||
*
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFeatureHubViewDBTable();
|
||||
|
||||
/************************************************************************
|
||||
* Face Pipeline
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Process multiple faces in a pipeline.
|
||||
*
|
||||
* This function processes multiple faces detected in an image or video frame, applying
|
||||
* various face recognition and analysis features as specified in the parameters.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param streamHandle Handle to the data buffer representing the camera stream component.
|
||||
* @param faces Pointer to the structure containing data of multiple detected faces.
|
||||
* @param parameter Custom parameters for processing the faces.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult
|
||||
HFMultipleFacePipelineProcess(HFSession session, HFImageStream streamHandle, PHFMultipleFaceData faces,
|
||||
HFSessionCustomParameter parameter);
|
||||
|
||||
/**
|
||||
* @brief Process multiple faces in a pipeline with an optional custom option.
|
||||
*
|
||||
* Similar to HFMultipleFacePipelineProcess, but allows for additional custom options
|
||||
* to modify the face processing behavior.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param streamHandle Handle to the data buffer representing the camera stream component.
|
||||
* @param faces Pointer to the structure containing data of multiple detected faces.
|
||||
* @param customOption An integer representing a custom option for processing.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult
|
||||
HFMultipleFacePipelineProcessOptional(HFSession session, HFImageStream streamHandle,
|
||||
PHFMultipleFaceData faces, HInt32 customOption);
|
||||
|
||||
/**
|
||||
* @brief Struct representing RGB liveness confidence.
|
||||
*
|
||||
* This struct holds the number of faces and the confidence level of liveness detection
|
||||
* for each face, using RGB analysis.
|
||||
*/
|
||||
typedef struct HFRGBLivenessConfidence {
|
||||
HInt32 num; ///< Number of faces detected.
|
||||
HPFloat confidence; ///< Confidence level of RGB liveness detection for each face.
|
||||
} HFRGBLivenessConfidence, *PHFRGBLivenessConfidence;
|
||||
|
||||
/**
|
||||
* @brief Get the RGB liveness confidence.
|
||||
*
|
||||
* This function retrieves the confidence level of RGB liveness detection for faces detected
|
||||
* in the current context.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param confidence Pointer to the structure where RGB liveness confidence data will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult
|
||||
HFGetRGBLivenessConfidence(HFSession session, PHFRGBLivenessConfidence confidence);
|
||||
|
||||
/**
|
||||
* @brief Struct representing face mask confidence.
|
||||
*
|
||||
* This struct holds the number of faces and the confidence level of mask detection
|
||||
* for each face.
|
||||
*/
|
||||
typedef struct HFFaceMaskConfidence {
|
||||
HInt32 num; ///< Number of faces detected.
|
||||
HPFloat confidence; ///< Confidence level of mask detection for each face.
|
||||
} HFFaceMaskConfidence, *PHFFaceMaskConfidence;
|
||||
|
||||
/**
|
||||
* @brief Get the face mask confidence.
|
||||
*
|
||||
* This function retrieves the confidence level of mask detection for faces detected
|
||||
* in the current context.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param confidence Pointer to the structure where face mask confidence data will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFGetFaceMaskConfidence(HFSession session, PHFFaceMaskConfidence confidence);
|
||||
|
||||
/**
|
||||
* @brief Struct representing face quality predict confidence.
|
||||
*
|
||||
* This struct holds the number of faces and the confidence level of face quality predict
|
||||
* for each face.
|
||||
*/
|
||||
typedef struct HFFaceQualityConfidence {
|
||||
HInt32 num; ///< Number of faces detected.
|
||||
HPFloat confidence; ///< Confidence level of face quality predict for each face.
|
||||
} HFFaceQualityConfidence, *PHFFaceQualityConfidence;
|
||||
|
||||
/**
|
||||
* @brief Get the face quality predict confidence.
|
||||
*
|
||||
* This function retrieves the confidence level of face quality predict for faces detected
|
||||
* in the current context.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param confidence Pointer to the structure where face mask confidence data will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFGetFaceQualityConfidence(HFSession session, PHFFaceQualityConfidence confidence);
|
||||
|
||||
/**
|
||||
* @brief Detect the quality of a face in an image.
|
||||
*
|
||||
* This function assesses the quality of a detected face, such as its clarity and visibility.
|
||||
*
|
||||
* @param session Handle to the session.
|
||||
* @param singleFace A token representing a single face.
|
||||
* @param confidence Pointer to a floating-point value where the quality confidence will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFFaceQualityDetect(HFSession session, HFFaceBasicToken singleFace, HFloat *confidence);
|
||||
|
||||
/************************************************************************
|
||||
* System Function
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Structure representing the version information of the InspireFace library.
|
||||
*/
|
||||
typedef struct HFInspireFaceVersion {
|
||||
int major; ///< Major version number.
|
||||
int minor; ///< Minor version number.
|
||||
int patch; ///< Patch version number.
|
||||
} HFInspireFaceVersion, *PHFInspireFaceVersion;
|
||||
|
||||
/**
|
||||
* @brief Function to query the version information of the InspireFace library.
|
||||
*
|
||||
* This function retrieves the version information of the InspireFace library.
|
||||
*
|
||||
* @param version Pointer to the structure where the version information will be stored.
|
||||
* @return HResult indicating the success or failure of the operation.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern HResult HFQueryInspireFaceVersion(PHFInspireFaceVersion version);
|
||||
|
||||
/**
|
||||
* @brief SDK built-in log level mode
|
||||
* */
|
||||
typedef enum HFLogLevel {
|
||||
HF_LOG_NONE = 0, // No logging, disables all log output
|
||||
HF_LOG_DEBUG, // Debug level for detailed system information mostly useful for developers
|
||||
HF_LOG_INFO, // Information level for general system information about operational status
|
||||
HF_LOG_WARN, // Warning level for non-critical issues that might need attention
|
||||
HF_LOG_ERROR, // Error level for error events that might still allow the application to continue running
|
||||
HF_LOG_FATAL // Fatal level for severe error events that will presumably lead the application to abort
|
||||
} HFLogLevel;
|
||||
|
||||
/**
|
||||
* @brief Set the log level built into the SDK.The default is HF LOG DEBUG
|
||||
* */
|
||||
HYPER_CAPI_EXPORT extern HResult HFSetLogLevel(HFLogLevel level);
|
||||
|
||||
/**
|
||||
* @brief Disable the log function. Like HFSetLogLevel(HF_LOG_NONE)
|
||||
* */
|
||||
HYPER_CAPI_EXPORT extern HResult HFLogDisable();
|
||||
|
||||
/********************************DEBUG Utils****************************************/
|
||||
|
||||
/**
|
||||
* @brief Display an image stream for debugging purposes.
|
||||
*
|
||||
* This function is used for debugging, allowing the visualization of the image stream
|
||||
* as it is being processed. It can be useful to understand the data being received
|
||||
* from the camera or image source.
|
||||
*
|
||||
* @param streamHandle Handle to the data buffer representing the camera stream component.
|
||||
*/
|
||||
HYPER_CAPI_EXPORT extern void HFDeBugImageStreamImShow(HFImageStream streamHandle);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif //HYPERFACEREPO_INSPIREFACE_H
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by tunm on 2023/10/3.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_INSPIREFACE_INTERNAL_H
|
||||
#define HYPERFACEREPO_INSPIREFACE_INTERNAL_H
|
||||
|
||||
#include "face_context.h"
|
||||
|
||||
typedef struct HF_FaceAlgorithmSession {
|
||||
inspire::FaceContext impl; ///< Implementation of the face context.
|
||||
} HF_FaceAlgorithmSession; ///< Handle for managing face context.
|
||||
|
||||
typedef struct HF_CameraStream {
|
||||
inspire::CameraStream impl; ///< Implementation of the camera stream.
|
||||
} HF_CameraStream; ///< Handle for managing camera stream.
|
||||
|
||||
|
||||
#endif //HYPERFACEREPO_INSPIREFACE_INTERNAL_H
|
||||
35
cpp-package/inspireface/cpp/inspireface/c_api/intypedef.h
Normal file
35
cpp-package/inspireface/cpp/inspireface/c_api/intypedef.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by tunm on 2023/10/3.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_INTYPEDEF_H
|
||||
#define HYPERFACEREPO_INTYPEDEF_H
|
||||
|
||||
typedef void* HPVoid; ///< Pointer to Void.
|
||||
typedef void* HFImageStream; ///< Handle for image.
|
||||
typedef void* HFSession; ///< Handle for context.
|
||||
typedef long HLong; ///< Long integer.
|
||||
typedef float HFloat; ///< Single-precision floating point.
|
||||
typedef float* HPFloat; ///< Pointer to Single-precision floating point.
|
||||
typedef double HDouble; ///< Double-precision floating point.
|
||||
typedef unsigned char HUInt8; ///< Unsigned 8-bit integer.
|
||||
typedef signed int HInt32; ///< Signed 32-bit integer.
|
||||
typedef signed int HOption; ///< Signed 32-bit integer option.
|
||||
typedef signed int* HPInt32; ///< Pointer to signed 32-bit integer.
|
||||
typedef long HResult; ///< Result code.
|
||||
typedef char* HString; ///< String.
|
||||
typedef const char* HPath; ///< Const String.
|
||||
typedef char HBuffer; ///< Character.
|
||||
typedef char* HPBuffer; ///< Pointer Character.
|
||||
typedef long HSize; ///< Size
|
||||
typedef long* HPSize; ///< Pointer Size
|
||||
|
||||
typedef struct HFaceRect {
|
||||
HInt32 x; ///< X-coordinate of the top-left corner of the rectangle.
|
||||
HInt32 y; ///< Y-coordinate of the top-left corner of the rectangle.
|
||||
HInt32 width; ///< Width of the rectangle.
|
||||
HInt32 height; ///< Height of the rectangle.
|
||||
} HFaceRect; ///< Rectangle representing a face region.
|
||||
|
||||
|
||||
#endif //HYPERFACEREPO_INTYPEDEF_H
|
||||
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Created by tunm on 2023/9/17.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_DATATOOLS_H
|
||||
#define HYPERFACEREPO_DATATOOLS_H
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "face_data_type.h"
|
||||
#include "../face_info/face_object.h"
|
||||
#include "herror.h"
|
||||
#include "data_type.h"
|
||||
|
||||
// Define the namespace "inspire" for encapsulation
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @brief Print the transformation matrix.
|
||||
* @param matrix The transformation matrix to print.
|
||||
*/
|
||||
inline void PrintTransMatrix(const TransMatrix& matrix) {
|
||||
std::cout << "Transformation Matrix:" << std::endl;
|
||||
std::cout << "m00: " << matrix.m00 << "\t";
|
||||
std::cout << "m01: " << matrix.m01 << "\t";
|
||||
std::cout << "tx: " << matrix.tx << std::endl;
|
||||
|
||||
std::cout << "m10: " << matrix.m10 << "\t";
|
||||
std::cout << "m11: " << matrix.m11 << "\t";
|
||||
std::cout << "ty: " << matrix.ty << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print HyperFaceData structure.
|
||||
* @param data The HyperFaceData structure to print.
|
||||
*/
|
||||
inline void INSPIRE_API PrintHyperFaceData(const HyperFaceData& data) {
|
||||
std::cout << "Track State: " << data.trackState << std::endl;
|
||||
std::cout << "In Group Index: " << data.inGroupIndex << std::endl;
|
||||
std::cout << "Track ID: " << data.trackId << std::endl;
|
||||
std::cout << "Track Count: " << data.trackCount << std::endl;
|
||||
|
||||
std::cout << "Face Rectangle:" << std::endl;
|
||||
std::cout << "x: " << data.rect.x << "\t";
|
||||
std::cout << "y: " << data.rect.y << "\t";
|
||||
std::cout << "width: " << data.rect.width << "\t";
|
||||
std::cout << "height: " << data.rect.height << std::endl;
|
||||
|
||||
PrintTransMatrix(data.trans);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a FaceObject to HyperFaceData.
|
||||
* @param obj The FaceObject to convert.
|
||||
* @param group_index The group index.
|
||||
* @return The converted HyperFaceData structure.
|
||||
*/
|
||||
inline HyperFaceData INSPIRE_API FaceObjectToHyperFaceData(const FaceObject& obj, int group_index = -1) {
|
||||
HyperFaceData data;
|
||||
// Face rect
|
||||
data.rect.x = obj.bbox_.x;
|
||||
data.rect.y = obj.bbox_.y;
|
||||
data.rect.width = obj.bbox_.width;
|
||||
data.rect.height = obj.bbox_.height;
|
||||
// Trans matrix
|
||||
data.trans.m00 = obj.getTransMatrix().at<double>(0, 0);
|
||||
data.trans.m01 = obj.getTransMatrix().at<double>(0, 1);
|
||||
data.trans.m10 = obj.getTransMatrix().at<double>(1, 0);
|
||||
data.trans.m11 = obj.getTransMatrix().at<double>(1, 1);
|
||||
data.trans.tx = obj.getTransMatrix().at<double>(0, 2);
|
||||
data.trans.ty = obj.getTransMatrix().at<double>(1, 2);
|
||||
// KetPoints five
|
||||
if (!obj.high_result.lmk.empty()) {
|
||||
for (int i = 0; i < obj.high_result.lmk.size(); ++i) {
|
||||
data.keyPoints[i].x = obj.high_result.lmk[i].x;
|
||||
data.keyPoints[i].y = obj.high_result.lmk[i].y;
|
||||
}
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
data.quality[i] = obj.high_result.lmk_quality[i];
|
||||
}
|
||||
// LOGD("HIGHT");
|
||||
} else {
|
||||
for (int i = 0; i < obj.keyPointFive.size(); ++i) {
|
||||
data.keyPoints[i].x = obj.keyPointFive[i].x;
|
||||
data.keyPoints[i].y = obj.keyPointFive[i].y;
|
||||
}
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
data.quality[i] = -1.0f;
|
||||
}
|
||||
}
|
||||
// Basic data
|
||||
data.inGroupIndex = group_index;
|
||||
data.trackCount = obj.tracking_count_;
|
||||
data.trackId = obj.GetTrackingId();
|
||||
data.trackState = obj.TrackingState();
|
||||
// Face 3D Angle
|
||||
data.face3DAngle.pitch = obj.high_result.pitch;
|
||||
data.face3DAngle.roll = obj.high_result.roll;
|
||||
data.face3DAngle.yaw = obj.high_result.yaw;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a TransMatrix to a cv::Mat.
|
||||
* @param trans The TransMatrix to convert.
|
||||
* @return The converted cv::Mat.
|
||||
*/
|
||||
inline cv::Mat INSPIRE_API TransMatrixToMat(const TransMatrix& trans) {
|
||||
cv::Mat mat(2, 3, CV_64F);
|
||||
mat.at<double>(0, 0) = trans.m00;
|
||||
mat.at<double>(0, 1) = trans.m01;
|
||||
mat.at<double>(1, 0) = trans.m10;
|
||||
mat.at<double>(1, 1) = trans.m11;
|
||||
mat.at<double>(0, 2) = trans.tx;
|
||||
mat.at<double>(1, 2) = trans.ty;
|
||||
return mat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a FaceRect to cv::Rect.
|
||||
* @param faceRect The FaceRect to convert.
|
||||
* @return The converted cv::Rect.
|
||||
*/
|
||||
inline cv::Rect INSPIRE_API FaceRectToRect(const FaceRect& faceRect) {
|
||||
return {faceRect.x, faceRect.y, faceRect.width, faceRect.height};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a Point2F to cv::Point2f.
|
||||
* @param point The Point2F to convert.
|
||||
* @return The converted cv::Point2f.
|
||||
*/
|
||||
inline cv::Point2f INSPIRE_API HPointToPoint2f(const Point2F& point) {
|
||||
return {point.x, point.y};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serialize HyperFaceData to a byte stream.
|
||||
* @param data The HyperFaceData to serialize.
|
||||
* @param byteArray The output byte stream.
|
||||
* @return The result code.
|
||||
*/
|
||||
inline int32_t INSPIRE_API SerializeHyperFaceData(const HyperFaceData& data, ByteArray& byteArray) {
|
||||
byteArray.reserve(sizeof(data));
|
||||
|
||||
// Serialize the HyperFaceData structure itself
|
||||
const char* dataBytes = reinterpret_cast<const char*>(&data);
|
||||
byteArray.insert(byteArray.end(), dataBytes, dataBytes + sizeof(data));
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deserialize a byte stream to HyperFaceData.
|
||||
* @param byteArray The input byte stream.
|
||||
* @param data The output HyperFaceData structure.
|
||||
* @return The result code.
|
||||
*/
|
||||
inline int32_t INSPIRE_API DeserializeHyperFaceData(const ByteArray& byteArray, HyperFaceData &data) {
|
||||
// Check if the byte stream size is sufficient
|
||||
if (byteArray.size() >= sizeof(data)) {
|
||||
// Copy data from the byte stream to the HyperFaceData structure
|
||||
std::memcpy(&data, byteArray.data(), sizeof(data));
|
||||
} else {
|
||||
INSPIRE_LOGE("The byte stream size is insufficient to restore HyperFaceData");
|
||||
return HERR_SESS_FACE_DATA_ERROR;
|
||||
}
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deserialize a byte stream to HyperFaceData.
|
||||
* @param byteArray The input byte stream as a character array.
|
||||
* @param byteCount The size of the byte stream.
|
||||
* @param data The output HyperFaceData structure.
|
||||
* @return The result code.
|
||||
*/
|
||||
inline int32_t INSPIRE_API DeserializeHyperFaceData(const char* byteArray, size_t byteCount, HyperFaceData& data) {
|
||||
// Check if the byte stream size is sufficient
|
||||
if (byteCount >= sizeof(data)) {
|
||||
// Copy data from the byte stream to the HyperFaceData structure
|
||||
std::memcpy(&data, byteArray, sizeof(data));
|
||||
} else {
|
||||
INSPIRE_LOGE("The byte stream size is insufficient to restore HyperFaceData");
|
||||
return HERR_SESS_FACE_DATA_ERROR;
|
||||
}
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
} // namespace hyper
|
||||
#endif //HYPERFACEREPO_DATATOOLS_H
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Created by tunm on 2023/9/17.
|
||||
//
|
||||
|
||||
// Include guard to prevent double inclusion of this header file
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FACEDATATYPE_H
|
||||
#define HYPERFACEREPO_FACEDATATYPE_H
|
||||
|
||||
// Include the necessary header files
|
||||
#include "../../data_type.h"
|
||||
#include "../face_info/face_object.h"
|
||||
|
||||
// Define the namespace "inspire" for encapsulation
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* Struct to represent 3D angles of a face.
|
||||
*/
|
||||
typedef struct Face3DAngle {
|
||||
float roll; ///< Roll angle
|
||||
float yaw; ///< Yaw angle
|
||||
float pitch; ///< Pitch angle
|
||||
} Face3DAngle;
|
||||
|
||||
/**
|
||||
* Struct to represent the rectangle coordinates of a face.
|
||||
*/
|
||||
typedef struct FaceRect {
|
||||
int x; ///< X-coordinate of the top-left corner
|
||||
int y; ///< Y-coordinate of the top-left corner
|
||||
int width; ///< Width of the rectangle
|
||||
int height; ///< Height of the rectangle
|
||||
} FaceRect;
|
||||
|
||||
/**
|
||||
* Struct to represent 2D point coordinates.
|
||||
*/
|
||||
typedef struct Point2F {
|
||||
float x; ///< X-coordinate
|
||||
float y; ///< Y-coordinate
|
||||
} HPoint;
|
||||
|
||||
/**
|
||||
* Struct to represent a 2D transformation matrix.
|
||||
*/
|
||||
typedef struct TransMatrix {
|
||||
double m00; ///< Element (0,0) of the matrix
|
||||
double m01; ///< Element (0,1) of the matrix
|
||||
double m10; ///< Element (1,0) of the matrix
|
||||
double m11; ///< Element (1,1) of the matrix
|
||||
double tx; ///< Translation in the X-axis
|
||||
double ty; ///< Translation in the Y-axis
|
||||
} TransMatrix;
|
||||
|
||||
/**
|
||||
* Struct to represent hyper face data.
|
||||
*/
|
||||
typedef struct HyperFaceData {
|
||||
int trackState; ///< Track state
|
||||
int inGroupIndex; ///< Index within a group
|
||||
int trackId; ///< Track ID
|
||||
int trackCount; ///< Track count
|
||||
FaceRect rect; ///< Face rectangle
|
||||
TransMatrix trans; ///< Transformation matrix
|
||||
Point2F keyPoints[5]; ///< Key points (e.g., landmarks)
|
||||
Face3DAngle face3DAngle; ///< 3D face angles
|
||||
float quality[5]; ///< Quality values for key points
|
||||
} HyperFaceData;
|
||||
|
||||
} // namespace inspire
|
||||
|
||||
#endif //HYPERFACEREPO_FACEDATATYPE_H
|
||||
@@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by tunm on 2023/8/29.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FO_ALL_H
|
||||
#define HYPERFACEREPO_FO_ALL_H
|
||||
|
||||
#include "face_object.h"
|
||||
|
||||
#endif //HYPERFACEREPO_FO_ALL_H
|
||||
321
cpp-package/inspireface/cpp/inspireface/common/face_info/face_object.h
Executable file
321
cpp-package/inspireface/cpp/inspireface/common/face_info/face_object.h
Executable file
@@ -0,0 +1,321 @@
|
||||
#ifndef FACE_INFO_H
|
||||
#define FACE_INFO_H
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
//#include "face_action.h"
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "middleware/utils.h"
|
||||
#include "data_type.h"
|
||||
#include "face_process.h"
|
||||
#include "track_module/quality/face_pose_quality.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
enum TRACK_STATE {
|
||||
UNTRACKING = -1, DETECT = 0, READY = 1, TRACKING = 2
|
||||
};
|
||||
|
||||
class INSPIRE_API FaceObject {
|
||||
public:
|
||||
FaceObject(int instance_id, cv::Rect bbox, int num_landmark = 106) {
|
||||
face_id_ = instance_id;
|
||||
landmark_.resize(num_landmark);
|
||||
bbox_ = std::move(bbox);
|
||||
tracking_state_ = DETECT;
|
||||
confidence_ = 1.0;
|
||||
tracking_count_ = 0;
|
||||
pose_euler_angle_.resize(3);
|
||||
keyPointFive.resize(5);
|
||||
// face_action_ = std::make_shared<FaceAction>(10);
|
||||
}
|
||||
|
||||
void UpdateMatrix(const cv::Mat &matrix) {
|
||||
assert(trans_matrix_.rows == 2 && trans_matrix_.cols == 3);
|
||||
double a00 = matrix.at<double>(0, 0);
|
||||
double a01 = matrix.at<double>(0, 1);
|
||||
double a10 = matrix.at<double>(1, 0);
|
||||
double a11 = matrix.at<double>(1, 1);
|
||||
double t1x = matrix.at<double>(0, 2);
|
||||
double t1y = matrix.at<double>(1, 2);
|
||||
|
||||
double m00 = trans_matrix_.at<double>(0, 0);
|
||||
double m01 = trans_matrix_.at<double>(0, 1);
|
||||
double m10 = trans_matrix_.at<double>(1, 0);
|
||||
double m11 = trans_matrix_.at<double>(1, 1);
|
||||
double t0x = trans_matrix_.at<double>(0, 2);
|
||||
double t0y = trans_matrix_.at<double>(1, 2);
|
||||
|
||||
double n_m00 = a00 * m00 + a01 * m10;
|
||||
double n_m01 = a00 * m01 + a01 * m11;
|
||||
double n_m02 = a00 * t0x + a01 * t0y + t1x;
|
||||
double n_m10 = a10 * m00 + a11 * m10;
|
||||
double n_m11 = a10 * m01 + a11 * m11;
|
||||
double n_m12 = a10 * t0x + a11 * t0y + t1y;
|
||||
|
||||
trans_matrix_.at<double>(0, 0) = n_m00;
|
||||
trans_matrix_.at<double>(0, 1) = n_m01;
|
||||
trans_matrix_.at<double>(0, 2) = n_m02;
|
||||
trans_matrix_.at<double>(1, 0) = n_m10;
|
||||
trans_matrix_.at<double>(1, 1) = n_m11;
|
||||
trans_matrix_.at<double>(1, 2) = n_m12;
|
||||
}
|
||||
|
||||
void SetLandmark(const std::vector<cv::Point2f> &lmk, bool update_rect = true,
|
||||
bool update_matrix = true) {
|
||||
if (lmk.size() != landmark_.size()) {
|
||||
INSPIRE_LOGW("The SetLandmark function displays an exception indicating that the lmk number does not match");
|
||||
return;
|
||||
}
|
||||
std::copy(lmk.begin(), lmk.end(), landmark_.begin());
|
||||
DynamicSmoothParamUpdate(landmark_, landmark_smooth_aux_, 106 * 2, 0.06);
|
||||
|
||||
// cv::Vec3d euler_angle;
|
||||
EstimateHeadPose(landmark_, euler_angle_);
|
||||
// DynamicSmoothParamUpdate(landmark_, landmark_smooth_aux_, 106 * 2, 0.06);
|
||||
if (update_rect)
|
||||
bbox_ = cv::boundingRect(lmk);
|
||||
if (update_matrix && tracking_state_ == TRACKING) {
|
||||
// pass
|
||||
}
|
||||
|
||||
keyPointFive[0] = landmark_[55];
|
||||
keyPointFive[1] = landmark_[105];
|
||||
keyPointFive[2] = landmark_[69];
|
||||
keyPointFive[3] = landmark_[45];
|
||||
keyPointFive[4] = landmark_[50];
|
||||
|
||||
}
|
||||
|
||||
void setAlignMeanSquareError(const std::vector<cv::Point2f> &lmk_5) {
|
||||
float src_pts[] = {30.2946, 51.6963, 65.5318, 51.5014, 48.0252,
|
||||
71.7366, 33.5493, 92.3655, 62.7299, 92.2041};
|
||||
for (int i = 0; i < 5; i++) {
|
||||
*(src_pts + 2 * i) += 8.0;
|
||||
}
|
||||
float sum = 0;
|
||||
for (int i = 0; i < lmk_5.size(); i++) {
|
||||
float l2 = L2norm(src_pts[i * 2 + 0], src_pts[i * 2 + 1], lmk_5[i].x, lmk_5[i].y);
|
||||
sum += l2;
|
||||
}
|
||||
|
||||
align_mse_ = sum / 5.0f;
|
||||
}
|
||||
|
||||
// 增加跟踪次数
|
||||
void IncrementTrackingCount() {
|
||||
tracking_count_++;
|
||||
}
|
||||
|
||||
// 获取跟踪次数
|
||||
int GetTrackingCount() const {
|
||||
return tracking_count_;
|
||||
}
|
||||
|
||||
float GetAlignMSE() const { return align_mse_; }
|
||||
|
||||
std::vector<cv::Point2f> GetLanmdark() const { return landmark_; }
|
||||
|
||||
cv::Rect GetRect() const { return bbox_; }
|
||||
|
||||
cv::Rect GetRectSquare(float padding_ratio = 0.0) const {
|
||||
int cx = bbox_.x + bbox_.width / 2;
|
||||
int cy = bbox_.y + bbox_.height / 2;
|
||||
int R = std::max(bbox_.width, bbox_.height) / 2;
|
||||
int R_padding = static_cast<int>(R * (1 + padding_ratio));
|
||||
int x1 = cx - R_padding;
|
||||
int y1 = cy - R_padding;
|
||||
int x2 = cx + R_padding;
|
||||
int y2 = cy + R_padding;
|
||||
int width = x2 - x1;
|
||||
int height = y2 - y1;
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
assert(height == width);
|
||||
cv::Rect box_square(x1, y1, width, height);
|
||||
return box_square;
|
||||
}
|
||||
|
||||
void UpdateFaceAction() {
|
||||
// face_action_->RecordActionFrame(landmark_, euler_angle_);
|
||||
// face_action_->AnalysisFaceAction();
|
||||
}
|
||||
|
||||
void DisableTracking() { tracking_state_ = UNTRACKING; }
|
||||
|
||||
void EnableTracking() { tracking_state_ = TRACKING; }
|
||||
|
||||
void ReadyTracking() { tracking_state_ = READY; }
|
||||
|
||||
TRACK_STATE TrackingState() const { return tracking_state_; }
|
||||
|
||||
float GetConfidence() const { return confidence_; }
|
||||
|
||||
void SetConfidence(float confidence) { confidence_ = confidence; }
|
||||
|
||||
int GetTrackingId() const { return face_id_; }
|
||||
|
||||
const cv::Mat &getTransMatrix() const { return trans_matrix_; }
|
||||
|
||||
void setTransMatrix(const cv::Mat &transMatrix) {
|
||||
transMatrix.copyTo(trans_matrix_);
|
||||
}
|
||||
|
||||
static float L2norm(float x0, float y0, float x1, float y1) {
|
||||
return sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
|
||||
}
|
||||
|
||||
void RequestFaceAction(
|
||||
std::vector<cv::Point2f> &landmarks,
|
||||
std::vector<std::vector<cv::Point2f>> &landmarks_lastNframes,
|
||||
int lm_length, float h) {
|
||||
int n = 5;
|
||||
std::vector<cv::Point2f> landmarks_temp;
|
||||
landmarks_temp.assign(landmarks.begin(), landmarks.end());
|
||||
if (landmarks_lastNframes.size() == n) {
|
||||
for (int i = 0; i < lm_length / 2; i++) {
|
||||
float sum_d = 1;
|
||||
float max_d = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
float d = L2norm(landmarks_temp[i].x, landmarks_temp[i].y,
|
||||
landmarks_lastNframes[j][i].x,
|
||||
landmarks_lastNframes[j][i].y);
|
||||
if (d > max_d)
|
||||
max_d = d;
|
||||
}
|
||||
for (int j = 0; j < n; j++) {
|
||||
float d = exp(-max_d * (n - j) * h);
|
||||
sum_d += d;
|
||||
landmarks[i].x = landmarks[i].x + d * landmarks_lastNframes[j][i].x;
|
||||
landmarks[i].y = landmarks[i].y + d * landmarks_lastNframes[j][i].y;
|
||||
}
|
||||
landmarks[i].x = landmarks[i].x / sum_d;
|
||||
landmarks[i].y = landmarks[i].y / sum_d;
|
||||
}
|
||||
}
|
||||
std::vector<cv::Point2f> landmarks_frame;
|
||||
for (int i = 0; i < lm_length / 2; i++) {
|
||||
landmarks_frame.push_back(cv::Point2f(landmarks[i].x, landmarks[i].y));
|
||||
}
|
||||
landmarks_lastNframes.push_back(landmarks_frame);
|
||||
if (landmarks_lastNframes.size() > 5)
|
||||
landmarks_lastNframes.erase(landmarks_lastNframes.begin());
|
||||
}
|
||||
|
||||
void DynamicSmoothParamUpdate(
|
||||
std::vector<cv::Point2f> &landmarks,
|
||||
std::vector<std::vector<cv::Point2f>> &landmarks_lastNframes,
|
||||
int lm_length, float h) {
|
||||
int n = 5;
|
||||
std::vector<cv::Point2f> landmarks_temp;
|
||||
landmarks_temp.assign(landmarks.begin(), landmarks.end());
|
||||
if (landmarks_lastNframes.size() == n) {
|
||||
for (int i = 0; i < lm_length / 2; i++) {
|
||||
float sum_d = 1;
|
||||
float max_d = 0;
|
||||
for (int j = 0; j < n; j++) {
|
||||
float d = L2norm(landmarks_temp[i].x, landmarks_temp[i].y,
|
||||
landmarks_lastNframes[j][i].x,
|
||||
landmarks_lastNframes[j][i].y);
|
||||
if (d > max_d)
|
||||
max_d = d;
|
||||
}
|
||||
for (int j = 0; j < n; j++) {
|
||||
float d = exp(-max_d * (n - j) * h);
|
||||
sum_d += d;
|
||||
landmarks[i].x = landmarks[i].x + d * landmarks_lastNframes[j][i].x;
|
||||
landmarks[i].y = landmarks[i].y + d * landmarks_lastNframes[j][i].y;
|
||||
}
|
||||
landmarks[i].x = landmarks[i].x / sum_d;
|
||||
landmarks[i].y = landmarks[i].y / sum_d;
|
||||
}
|
||||
}
|
||||
std::vector<cv::Point2f> landmarks_frame;
|
||||
for (int i = 0; i < lm_length / 2; i++) {
|
||||
landmarks_frame.push_back(cv::Point2f(landmarks[i].x, landmarks[i].y));
|
||||
}
|
||||
landmarks_lastNframes.push_back(landmarks_frame);
|
||||
if (landmarks_lastNframes.size() > 5)
|
||||
landmarks_lastNframes.erase(landmarks_lastNframes.begin());
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<cv::Point2f> landmark_;
|
||||
std::vector<std::vector<cv::Point2f>> landmark_smooth_aux_;
|
||||
cv::Rect bbox_;
|
||||
cv::Vec3f euler_angle_;
|
||||
std::vector<float> pose_euler_angle_;
|
||||
|
||||
float align_mse_{};
|
||||
|
||||
const cv::Vec3f &getEulerAngle() const { return euler_angle_; }
|
||||
|
||||
const std::vector<float> &getPoseEulerAngle() const { return pose_euler_angle_; }
|
||||
|
||||
void setPoseEulerAngle(const std::vector<float> &poseEulerAngle) {
|
||||
pose_euler_angle_[0] = poseEulerAngle[0];
|
||||
pose_euler_angle_[1] = poseEulerAngle[1];
|
||||
pose_euler_angle_[2] = poseEulerAngle[2];
|
||||
|
||||
if (abs(pose_euler_angle_[0]) < 0.5 && abs(pose_euler_angle_[1]) < 0.48) {
|
||||
is_standard_ = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool isStandard() const {
|
||||
return is_standard_;
|
||||
}
|
||||
|
||||
const cv::Rect &getBbox() const { return bbox_; }
|
||||
|
||||
std::vector<cv::Point2f> getRotateLandmark(int height, int width, int rotate = 0) {
|
||||
if (rotate != 0) {
|
||||
std::vector<cv::Point2f> result = RotatePoints(landmark_, rotate, cv::Size(height, width));
|
||||
return result;
|
||||
} else {
|
||||
return GetLanmdark();
|
||||
}
|
||||
}
|
||||
|
||||
cv::Rect getRotateBbox(int height, int width, int rotate = 0, bool use_flip = false) {
|
||||
if (rotate != 0) {
|
||||
cv::Rect src_bbox = bbox_;
|
||||
std::vector<cv::Point2f> points;
|
||||
cv::Rect trans_rect;
|
||||
RotateRect(src_bbox, points, trans_rect, rotate, cv::Size(height, width));
|
||||
if (use_flip)
|
||||
trans_rect = flipRectWidth(trans_rect, cv::Size(width, height));
|
||||
return trans_rect;
|
||||
} else {
|
||||
return getBbox();
|
||||
}
|
||||
}
|
||||
|
||||
void setBbox(const cv::Rect &bbox) { bbox_ = bbox; }
|
||||
|
||||
cv::Mat trans_matrix_;
|
||||
float confidence_;
|
||||
cv::Rect detect_bbox_;
|
||||
int tracking_count_; // 跟踪次数
|
||||
|
||||
bool is_standard_;
|
||||
|
||||
FacePoseQualityResult high_result;
|
||||
|
||||
FaceProcess faceProcess;
|
||||
|
||||
std::vector<Point2f> keyPointFive;
|
||||
|
||||
private:
|
||||
TRACK_STATE tracking_state_;
|
||||
// std::shared_ptr<FaceAction> face_action_;
|
||||
int face_id_;
|
||||
};
|
||||
|
||||
typedef std::vector<FaceObject> FaceObjectList;
|
||||
|
||||
} // namespace hyper
|
||||
|
||||
#endif // FACE_INFO_H
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Created by tunm on 2023/9/12.
|
||||
//
|
||||
|
||||
// Include guard to prevent double inclusion of this header file
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FACEPROCESS_H
|
||||
#define HYPERFACEREPO_FACEPROCESS_H
|
||||
|
||||
// Include the necessary header file "data_type.h"
|
||||
#include "data_type.h"
|
||||
|
||||
// Define the namespace "inspire" for encapsulation
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* Enumeration to represent different mask information.
|
||||
*/
|
||||
typedef enum MaskInfo {
|
||||
UNKNOWN_MASK = -1, ///< Unknown mask status
|
||||
UNMASKED = 0, ///< No mask
|
||||
MASKED = 1, ///< Wearing a mask
|
||||
} MaskInfo;
|
||||
|
||||
/**
|
||||
* Enumeration to represent different RGB liveness information.
|
||||
*/
|
||||
typedef enum RGBLivenessInfo {
|
||||
UNKNOWN_RGB_LIVENESS = -1, ///< Unknown RGB liveness status
|
||||
LIVENESS_FAKE = 0, ///< Fake liveness
|
||||
LIVENESS_REAL = 1, ///< Real liveness
|
||||
} RGBLivenessInfo;
|
||||
|
||||
/**
|
||||
* Class definition for FaceProcess.
|
||||
*/
|
||||
class INSPIRE_API FaceProcess {
|
||||
public:
|
||||
/**
|
||||
* Member variable to store mask information, initialized to UNKNOWN_MASK.
|
||||
*/
|
||||
MaskInfo maskInfo = UNKNOWN_MASK;
|
||||
|
||||
/**
|
||||
* Member variable to store RGB liveness information, initialized to UNKNOWN_RGB_LIVENESS.
|
||||
*/
|
||||
RGBLivenessInfo rgbLivenessInfo = UNKNOWN_RGB_LIVENESS;
|
||||
|
||||
};
|
||||
|
||||
} // namespace hyper
|
||||
|
||||
#endif //HYPERFACEREPO_FACEPROCESS_H
|
||||
197
cpp-package/inspireface/cpp/inspireface/data_type.h
Normal file
197
cpp-package/inspireface/cpp/inspireface/data_type.h
Normal file
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// Created by tunm on 2023/5/5.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACE_DATATYPE_H
|
||||
#define HYPERFACE_DATATYPE_H
|
||||
|
||||
#include <cstdint>
|
||||
#if defined(_WIN32) && (defined(_DEBUG) || defined(DEBUG))
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include "crtdbg.h"
|
||||
#endif
|
||||
|
||||
#ifndef INSPIRE_API
|
||||
#define INSPIRE_API
|
||||
#endif
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
#endif
|
||||
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @defgroup DataType Definitions
|
||||
* @brief Defines various data types used in the HyperFace project.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if !defined(int64)
|
||||
/** @typedef int64
|
||||
* @brief 64-bit integer type.
|
||||
*/
|
||||
typedef int64_t int64;
|
||||
#endif
|
||||
|
||||
#if !defined(uint64)
|
||||
/** @typedef uint64
|
||||
* @brief 64-bit unsigned integer type.
|
||||
*/
|
||||
typedef uint64_t uint64;
|
||||
#endif
|
||||
|
||||
#if !defined(int32)
|
||||
/** @typedef int32
|
||||
* @brief 32-bit integer type.
|
||||
*/
|
||||
typedef int32_t int32;
|
||||
#endif
|
||||
|
||||
#if !defined(uint32)
|
||||
/** @typedef uint32
|
||||
* @brief 32-bit unsigned integer type.
|
||||
*/
|
||||
typedef uint32_t uint32;
|
||||
#endif
|
||||
|
||||
#if !defined(int8)
|
||||
/** @typedef int8
|
||||
* @brief 8-bit integer type.
|
||||
*/
|
||||
typedef int8_t int8;
|
||||
#endif
|
||||
|
||||
#if !defined(uint8)
|
||||
/** @typedef uint8
|
||||
* @brief 8-bit unsigned integer type.
|
||||
*/
|
||||
typedef uint8_t uint8;
|
||||
#endif
|
||||
|
||||
/** @typedef ByteArray
|
||||
* @brief Type definition for a byte array (vector of chars).
|
||||
*/
|
||||
typedef std::vector<char> ByteArray;
|
||||
|
||||
/** @typedef Point2i
|
||||
* @brief 2D coordinate point with integer precision.
|
||||
*/
|
||||
typedef cv::Point Point2i;
|
||||
|
||||
/** @typedef Point2f
|
||||
* @brief 2D coordinate point with float precision.
|
||||
*/
|
||||
typedef cv::Point2f Point2f;
|
||||
|
||||
/** @typedef PointsList2i
|
||||
* @brief List of 2D coordinate points with integer precision.
|
||||
*/
|
||||
typedef std::vector<Point2i> PointsList2i;
|
||||
|
||||
/** @typedef PointsList2f
|
||||
* @brief List of 2D coordinate points with float precision.
|
||||
*/
|
||||
typedef std::vector<Point2f> PointsList2f;
|
||||
|
||||
/** @typedef Contours2i
|
||||
* @brief Contours represented as a list of 2D integer points.
|
||||
*/
|
||||
typedef std::vector<PointsList2i> Contours2i;
|
||||
|
||||
/** @typedef Contours2f
|
||||
* @brief Contours represented as a list of 2D float points.
|
||||
*/
|
||||
typedef std::vector<PointsList2f> Contours2f;
|
||||
|
||||
/** @typedef Textures2i
|
||||
* @brief Texture lines represented as integer contours.
|
||||
*/
|
||||
typedef Contours2i Textures2i;
|
||||
|
||||
/** @typedef AnyTensorFp32
|
||||
* @brief Generic tensor representation using a vector of floats.
|
||||
*/
|
||||
typedef std::vector<float> AnyTensorFp32;
|
||||
|
||||
/** @typedef Matrix
|
||||
* @brief Generic matrix representation.
|
||||
*/
|
||||
typedef cv::Mat Matrix;
|
||||
|
||||
/** @typedef Rectangle
|
||||
* @brief Rectangle representation using integer values.
|
||||
*/
|
||||
typedef cv::Rect_<int> Rectangle;
|
||||
|
||||
/** @typedef Size
|
||||
* @brief Size representation using integer values.
|
||||
*/
|
||||
typedef cv::Size_<int> Size;
|
||||
|
||||
/** @typedef Embedded
|
||||
* @brief Dense vector for feature embedding.
|
||||
*/
|
||||
typedef std::vector<float> Embedded;
|
||||
|
||||
/** @typedef EmbeddedList
|
||||
* @brief List of dense vectors for feature embedding.
|
||||
*/
|
||||
typedef std::vector<Embedded> EmbeddedList;
|
||||
|
||||
/** @typedef String
|
||||
* @brief String type definition.
|
||||
*/
|
||||
typedef std::string String;
|
||||
|
||||
/** @typedef IndexList
|
||||
* @brief List of indices.
|
||||
*/
|
||||
typedef std::vector<int> IndexList;
|
||||
|
||||
/** @struct FaceLoc
|
||||
* @brief Struct representing standardized face landmarks for detection.
|
||||
*
|
||||
* Contains coordinates for the face, detection score, and landmarks.
|
||||
*/
|
||||
typedef struct FaceLoc {
|
||||
float x1;
|
||||
float y1;
|
||||
float x2;
|
||||
float y2;
|
||||
float score;
|
||||
float lmk[10];
|
||||
} FaceLoc;
|
||||
|
||||
/** @typedef FaceLocList
|
||||
* @brief List of FaceLoc structures.
|
||||
*/
|
||||
typedef std::vector<FaceLoc> FaceLocList;
|
||||
|
||||
/** @struct FaceBasicData
|
||||
* @brief Struct for basic face data.
|
||||
*
|
||||
* Contains the size of the data and a pointer to the data.
|
||||
*/
|
||||
typedef struct FaceBasicData {
|
||||
int32_t dataSize;
|
||||
void* data;
|
||||
} FaceBasicData;
|
||||
|
||||
/** @struct FaceFeatureEntity
|
||||
* @brief Struct for face feature data.
|
||||
*
|
||||
* Contains the size of the feature data and a pointer to the feature array.
|
||||
*/
|
||||
typedef struct FaceFeatureEntity {
|
||||
int32_t dataSize;
|
||||
float *data;
|
||||
} FaceFeaturePtr;
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace inspire
|
||||
|
||||
#endif //HYPERFACE_DATATYPE_H
|
||||
271
cpp-package/inspireface/cpp/inspireface/face_context.cpp
Normal file
271
cpp-package/inspireface/cpp/inspireface/face_context.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/7.
|
||||
//
|
||||
|
||||
#include "face_context.h"
|
||||
#include "Initialization_module/launch.h"
|
||||
#include <utility>
|
||||
#include "log.h"
|
||||
#include "herror.h"
|
||||
#include "middleware/utils.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
|
||||
FaceContext::FaceContext() = default;
|
||||
|
||||
int32_t FaceContext::Configuration(DetectMode detect_mode, int32_t max_detect_face,
|
||||
CustomPipelineParameter param) {
|
||||
m_detect_mode_ = detect_mode;
|
||||
m_max_detect_face_ = max_detect_face;
|
||||
m_parameter_ = param;
|
||||
if (!INSPIRE_LAUNCH->isMLoad()) {
|
||||
return HERR_ARCHIVE_NOT_LOAD;
|
||||
}
|
||||
if (INSPIRE_LAUNCH->getMArchive().QueryStatus() != SARC_SUCCESS) {
|
||||
return HERR_ARCHIVE_LOAD_FAILURE;
|
||||
}
|
||||
|
||||
m_face_track_ = std::make_shared<FaceTrack>(m_max_detect_face_);
|
||||
m_face_track_->Configuration(INSPIRE_LAUNCH->getMArchive());
|
||||
SetDetectMode(m_detect_mode_);
|
||||
|
||||
m_face_recognition_ = std::make_shared<FeatureExtraction>(INSPIRE_LAUNCH->getMArchive(), m_parameter_.enable_recognition);
|
||||
if (m_face_recognition_->QueryStatus() != HSUCCEED) {
|
||||
return m_face_recognition_->QueryStatus();
|
||||
}
|
||||
|
||||
m_face_pipeline_ = std::make_shared<FacePipeline>(
|
||||
INSPIRE_LAUNCH->getMArchive(),
|
||||
param.enable_liveness,
|
||||
param.enable_mask_detect,
|
||||
param.enable_age,
|
||||
param.enable_gender,
|
||||
param.enable_interaction_liveness
|
||||
);
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
int32_t FaceContext::FaceDetectAndTrack(CameraStream &image) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
m_detect_cache_.clear();
|
||||
m_face_basic_data_cache_.clear();
|
||||
m_face_rects_cache_.clear();
|
||||
m_track_id_cache_.clear();
|
||||
m_quality_results_cache_.clear();
|
||||
m_roll_results_cache_.clear();
|
||||
m_yaw_results_cache_.clear();
|
||||
m_pitch_results_cache_.clear();
|
||||
m_quality_score_results_cache_.clear();
|
||||
if (m_face_track_ == nullptr) {
|
||||
return HERR_SESS_TRACKER_FAILURE;
|
||||
}
|
||||
m_face_track_->UpdateStream(image, m_always_detect_);
|
||||
for (int i = 0; i < m_face_track_->trackingFace.size(); ++i) {
|
||||
auto &face = m_face_track_->trackingFace[i];
|
||||
HyperFaceData data = FaceObjectToHyperFaceData(face, i);
|
||||
ByteArray byteArray;
|
||||
auto ret = SerializeHyperFaceData(data, byteArray);
|
||||
if (ret != HSUCCEED) {
|
||||
return HERR_INVALID_SERIALIZATION_FAILED;
|
||||
}
|
||||
m_detect_cache_.push_back(byteArray);
|
||||
m_track_id_cache_.push_back(face.GetTrackingId());
|
||||
m_face_rects_cache_.push_back(data.rect);
|
||||
m_quality_results_cache_.push_back(face.high_result);
|
||||
m_roll_results_cache_.push_back(face.high_result.roll);
|
||||
m_yaw_results_cache_.push_back(face.high_result.yaw);
|
||||
m_pitch_results_cache_.push_back(face.high_result.pitch);
|
||||
// Process quality scores
|
||||
float avg = 0.0f;
|
||||
for (int j = 0; j < 5; ++j) {
|
||||
avg += data.quality[j];
|
||||
}
|
||||
avg /= 5.0f;
|
||||
float quality_score = 1.0f - avg; // reversal
|
||||
m_quality_score_results_cache_.push_back(quality_score);
|
||||
}
|
||||
// ptr face_basic
|
||||
m_face_basic_data_cache_.resize(m_face_track_->trackingFace.size());
|
||||
for (int i = 0; i < m_face_basic_data_cache_.size(); ++i) {
|
||||
auto &basic = m_face_basic_data_cache_[i];
|
||||
basic.dataSize = m_detect_cache_[i].size();
|
||||
basic.data = m_detect_cache_[i].data();
|
||||
}
|
||||
|
||||
|
||||
// LOGD("Track COST: %f", m_face_track_->GetTrackTotalUseTime());
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FaceContext::SetFaceDetectThreshold(float value) {
|
||||
m_face_track_->SetDetectThreshold(value);
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
FaceObjectList& FaceContext::GetTrackingFaceList() {
|
||||
return m_face_track_->trackingFace;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FeatureExtraction>& FaceContext::FaceRecognitionModule() {
|
||||
return m_face_recognition_;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FacePipeline>& FaceContext::FacePipelineModule() {
|
||||
return m_face_pipeline_;
|
||||
}
|
||||
|
||||
|
||||
const int32_t FaceContext::GetNumberOfFacesCurrentlyDetected() const {
|
||||
return m_face_track_->trackingFace.size();
|
||||
}
|
||||
|
||||
int32_t FaceContext::FacesProcess(CameraStream &image, const std::vector<HyperFaceData> &faces, const CustomPipelineParameter ¶m) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
m_mask_results_cache_.resize(faces.size(), -1.0f);
|
||||
m_rgb_liveness_results_cache_.resize(faces.size(), -1.0f);
|
||||
for (int i = 0; i < faces.size(); ++i) {
|
||||
const auto &face = faces[i];
|
||||
// RGB Liveness Detect
|
||||
if (param.enable_liveness) {
|
||||
auto ret = m_face_pipeline_->Process(image, face, PROCESS_RGB_LIVENESS);
|
||||
if (ret != HSUCCEED) {
|
||||
return ret;
|
||||
}
|
||||
m_rgb_liveness_results_cache_[i] = m_face_pipeline_->faceLivenessCache;
|
||||
}
|
||||
// Mask detection
|
||||
if (param.enable_mask_detect) {
|
||||
auto ret = m_face_pipeline_->Process(image, face, PROCESS_MASK);
|
||||
if (ret != HSUCCEED) {
|
||||
return ret;
|
||||
}
|
||||
m_mask_results_cache_[i] = m_face_pipeline_->faceMaskCache;
|
||||
}
|
||||
// Age prediction
|
||||
if (param.enable_age) {
|
||||
auto ret = m_face_pipeline_->Process(image, face, PROCESS_AGE);
|
||||
if (ret != HSUCCEED) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
// Gender prediction
|
||||
if (param.enable_age) {
|
||||
auto ret = m_face_pipeline_->Process(image, face, PROCESS_GENDER);
|
||||
if (ret != HSUCCEED) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<ByteArray>& FaceContext::GetDetectCache() const {
|
||||
return m_detect_cache_;
|
||||
}
|
||||
|
||||
const std::vector<FaceBasicData>& FaceContext::GetFaceBasicDataCache() const {
|
||||
return m_face_basic_data_cache_;
|
||||
}
|
||||
|
||||
const std::vector<FaceRect>& FaceContext::GetFaceRectsCache() const {
|
||||
return m_face_rects_cache_;
|
||||
}
|
||||
|
||||
const std::vector<int32_t>& FaceContext::GetTrackIDCache() const {
|
||||
return m_track_id_cache_;
|
||||
}
|
||||
|
||||
const std::vector<float>& FaceContext::GetRollResultsCache() const {
|
||||
return m_roll_results_cache_;
|
||||
}
|
||||
|
||||
const std::vector<float>& FaceContext::GetYawResultsCache() const {
|
||||
return m_yaw_results_cache_;
|
||||
}
|
||||
|
||||
const std::vector<float>& FaceContext::GetPitchResultsCache() const {
|
||||
return m_pitch_results_cache_;
|
||||
}
|
||||
|
||||
const std::vector<FacePoseQualityResult>& FaceContext::GetQualityResultsCache() const {
|
||||
return m_quality_results_cache_;
|
||||
}
|
||||
|
||||
const std::vector<float>& FaceContext::GetMaskResultsCache() const {
|
||||
return m_mask_results_cache_;
|
||||
}
|
||||
|
||||
const std::vector<float>& FaceContext::GetRgbLivenessResultsCache() const {
|
||||
return m_rgb_liveness_results_cache_;
|
||||
}
|
||||
|
||||
const std::vector<float>& FaceContext::GetFaceQualityScoresResultsCache() const {
|
||||
return m_quality_score_results_cache_;
|
||||
}
|
||||
|
||||
|
||||
const Embedded& FaceContext::GetFaceFeatureCache() const {
|
||||
return m_face_feature_cache_;
|
||||
}
|
||||
|
||||
int32_t FaceContext::FaceFeatureExtract(CameraStream &image, FaceBasicData& data) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
int32_t ret;
|
||||
HyperFaceData face = {0};
|
||||
ret = DeserializeHyperFaceData((char* )data.data, data.dataSize, face);
|
||||
if (ret != HSUCCEED) {
|
||||
return ret;
|
||||
}
|
||||
m_face_feature_cache_.clear();
|
||||
ret = m_face_recognition_->FaceExtract(image, face, m_face_feature_cache_);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const CustomPipelineParameter &FaceContext::getMParameter() const {
|
||||
return m_parameter_;
|
||||
}
|
||||
|
||||
|
||||
int32_t FaceContext::FaceQualityDetect(FaceBasicData& data, float &result) {
|
||||
int32_t ret;
|
||||
HyperFaceData face = {0};
|
||||
ret = DeserializeHyperFaceData((char* )data.data, data.dataSize, face);
|
||||
// PrintHyperFaceData(face);
|
||||
if (ret != HSUCCEED) {
|
||||
return ret;
|
||||
}
|
||||
float avg = 0.0f;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
avg += face.quality[i];
|
||||
}
|
||||
avg /= 5.0f;
|
||||
result = 1.0f - avg; // reversal
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t FaceContext::SetDetectMode(DetectMode mode) {
|
||||
m_detect_mode_ = mode;
|
||||
if (m_detect_mode_ == DetectMode::DETECT_MODE_IMAGE) {
|
||||
m_always_detect_ = true;
|
||||
} else {
|
||||
m_always_detect_ = false;
|
||||
}
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FaceContext::SetTrackPreviewSize(const int32_t preview_size) {
|
||||
m_face_track_->SetTrackPreviewSize(preview_size);
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
} // namespace hyper
|
||||
273
cpp-package/inspireface/cpp/inspireface/face_context.h
Normal file
273
cpp-package/inspireface/cpp/inspireface/face_context.h
Normal file
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/7.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FACE_CONTEXT_H
|
||||
#define HYPERFACEREPO_FACE_CONTEXT_H
|
||||
|
||||
/**
|
||||
* @file face_context.h
|
||||
* @brief Face context handling for HyperFaceRepo project.
|
||||
* Includes definitions for face detection, tracking, and feature extraction.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include "track_module/face_track.h"
|
||||
#include "data_type.h"
|
||||
#include "pipeline_module/face_pipeline.h"
|
||||
#include "recognition_module/face_feature_extraction.h"
|
||||
#include "middleware/model_archive/inspire_archive.h"
|
||||
|
||||
/**
|
||||
* @def DB_FILE_NAME
|
||||
* @brief Default database file name used in the FaceContext.
|
||||
*/
|
||||
#define DB_FILE_NAME ".E63520A95DD5B3892C56DA38C3B28E551D8173FD"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @enum DetectMode
|
||||
* @brief Enumeration for different detection modes.
|
||||
*/
|
||||
enum DetectMode {
|
||||
DETECT_MODE_IMAGE = 0, ///< Image detection mode: Always detect
|
||||
DETECT_MODE_VIDEO, ///< Image detection mode: Face track
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct CustomPipelineParameter
|
||||
* @brief Structure to hold custom parameters for the face detection and processing pipeline.
|
||||
*
|
||||
* Includes options for enabling various features such as recognition, liveness detection, and quality assessment.
|
||||
*/
|
||||
typedef struct CustomPipelineParameter {
|
||||
bool enable_recognition = false; ///< Enable face recognition feature
|
||||
bool enable_liveness = false; ///< Enable RGB liveness detection feature
|
||||
bool enable_ir_liveness = false; ///< Enable IR (Infrared) liveness detection feature
|
||||
bool enable_mask_detect = false; ///< Enable mask detection feature
|
||||
bool enable_age = false; ///< Enable age prediction feature
|
||||
bool enable_gender = false; ///< Enable gender prediction feature
|
||||
bool enable_face_quality = false; ///< Enable face quality assessment feature
|
||||
bool enable_interaction_liveness = false; ///< Enable interactive liveness detection feature
|
||||
|
||||
} ContextCustomParameter;
|
||||
|
||||
/**
|
||||
* @class FaceContext
|
||||
* @brief Manages the context for face detection, tracking, and feature extraction in the HyperFaceRepo project.
|
||||
*
|
||||
* Provides interfaces to configure face detection modes, manage face tracking, perform recognition,
|
||||
* and handle other face-related features. Integrates with various modules such as FaceTrack, FaceRecognition, and FacePipeline.
|
||||
*/
|
||||
class INSPIRE_API FaceContext {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor for the FaceContext class.
|
||||
*/
|
||||
explicit FaceContext();
|
||||
|
||||
/**
|
||||
* @brief Configures the face context with given parameters.
|
||||
* @param model_file_path Path to the model file for face detection.
|
||||
* @param detect_mode The detection mode to be used (image or video).
|
||||
* @param max_detect_face The maximum number of faces to detect.
|
||||
* @param param Custom parameters for the face pipeline.
|
||||
* @return int32_t Returns 0 on success, non-zero for any error.
|
||||
*/
|
||||
int32_t Configuration(DetectMode detect_mode, int32_t max_detect_face, CustomPipelineParameter param);
|
||||
|
||||
/**
|
||||
* @brief Performs face detection and tracking on a given image stream.
|
||||
* @param image The camera stream to process for face detection and tracking.
|
||||
* @return int32_t Returns the number of faces detected and tracked.
|
||||
*/// Method for face detection and tracking
|
||||
int32_t FaceDetectAndTrack(CameraStream &image);
|
||||
|
||||
/**
|
||||
* @brief Set the threshold of face detection function, which only acts on the detection model
|
||||
* @param value threshold value
|
||||
* @return int32_t Returns the number of faces detected and tracked.
|
||||
* */
|
||||
int32_t SetFaceDetectThreshold(float value);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the list of currently tracked faces.
|
||||
* @return FaceObjectList A list of face objects currently being tracked.
|
||||
*/
|
||||
FaceObjectList& GetTrackingFaceList();
|
||||
|
||||
/**
|
||||
* @brief Processes faces using the provided pipeline parameters.
|
||||
* @param image Camera stream containing faces.
|
||||
* @param faces Vector of HyperFaceData for detected faces.
|
||||
* @param param Custom pipeline parameters.
|
||||
* @return int32_t Status code of the processing.
|
||||
*/
|
||||
int32_t FacesProcess(CameraStream &image, const std::vector<HyperFaceData> &faces, const CustomPipelineParameter& param);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the face recognition module.
|
||||
* @return std::shared_ptr<FaceRecognition> Shared pointer to the FaceRecognition module.
|
||||
*/
|
||||
const std::shared_ptr<FeatureExtraction>& FaceRecognitionModule();
|
||||
|
||||
/**
|
||||
* @brief Retrieves the face pipeline module.
|
||||
* @return std::shared_ptr<FacePipeline> Shared pointer to the FacePipeline module.
|
||||
*/
|
||||
const std::shared_ptr<FacePipeline>& FacePipelineModule();
|
||||
|
||||
/**
|
||||
* @brief Gets the number of faces currently detected.
|
||||
* @return int32_t Number of faces currently detected.
|
||||
*/
|
||||
const int32_t GetNumberOfFacesCurrentlyDetected() const;
|
||||
|
||||
/**
|
||||
* @brief Extracts features of a face from an image.
|
||||
* @param image Camera stream containing the face.
|
||||
* @param data FaceBasicData to store extracted features.
|
||||
* @return int32_t Status code of the feature extraction.
|
||||
*/
|
||||
int32_t FaceFeatureExtract(CameraStream &image, FaceBasicData& data);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the custom pipeline parameters.
|
||||
* @return CustomPipelineParameter Current custom pipeline parameters.
|
||||
*/
|
||||
const CustomPipelineParameter &getMParameter() const;
|
||||
|
||||
/**
|
||||
* @brief Static method for detecting face quality.
|
||||
* @param data FaceBasicData containing the face information.
|
||||
* @param result Float to store the face quality result.
|
||||
* @return int32_t Status code of the quality detection.
|
||||
*/
|
||||
static int32_t FaceQualityDetect(FaceBasicData& data, float &result);
|
||||
|
||||
/**
|
||||
* @brief Sets the preview size for face tracking.
|
||||
* @param preview_size Integer specifying the new preview size.
|
||||
* @return int32_t Status code of the operation.
|
||||
*/
|
||||
int32_t SetTrackPreviewSize(int32_t preview_size);
|
||||
|
||||
/**
|
||||
* @brief Sets the mode for face detection.
|
||||
* @param mode You can select mode for track or detect.
|
||||
* @return int32_t Status code of the operation.
|
||||
* */
|
||||
int32_t SetDetectMode(DetectMode mode);
|
||||
|
||||
public:
|
||||
// Accessor methods for various cached data
|
||||
/**
|
||||
* @brief Retrieves the cache of detected face data.
|
||||
* @return std::vector<ByteArray> Cache of detected face data.
|
||||
*/
|
||||
const std::vector<ByteArray>& GetDetectCache() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the cache of basic face data.
|
||||
* @return std::vector<FaceBasicData> Cache of basic face data.
|
||||
*/
|
||||
const std::vector<FaceBasicData>& GetFaceBasicDataCache() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the cache of face rectangles.
|
||||
* @return std::vector<FaceRect> Cache of face rectangles.
|
||||
*/
|
||||
const std::vector<FaceRect>& GetFaceRectsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the cache of tracking IDs.
|
||||
* @return std::vector<int32_t> Cache of tracking IDs.
|
||||
*/
|
||||
const std::vector<int32_t>& GetTrackIDCache() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the cache of roll results from face pose estimation.
|
||||
* @return std::vector<float> Cache of roll results.
|
||||
*/
|
||||
const std::vector<float>& GetRollResultsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the cache of yaw results from face pose estimation.
|
||||
* @return std::vector<float> Cache of yaw results.
|
||||
*/
|
||||
const std::vector<float>& GetYawResultsCache() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of pitch results from face pose estimation.
|
||||
* @return A const reference to a vector containing pitch results.
|
||||
*/
|
||||
const std::vector<float>& GetPitchResultsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of face pose quality results.
|
||||
* @return A const reference to a vector of FacePoseQualityResult objects.
|
||||
*/
|
||||
const std::vector<FacePoseQualityResult>& GetQualityResultsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of mask detection results.
|
||||
* @return A const reference to a vector containing mask detection results.
|
||||
*/
|
||||
const std::vector<float>& GetMaskResultsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of RGB liveness detection results.
|
||||
* @return A const reference to a vector containing RGB liveness results.
|
||||
*/
|
||||
const std::vector<float>& GetRgbLivenessResultsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of face quality predict results.
|
||||
* @return A const reference to a vector containing face quality predict results.
|
||||
*/
|
||||
const std::vector<float>& GetFaceQualityScoresResultsCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of the current face features.
|
||||
* @return A const reference to the Embedded object containing current face feature data.
|
||||
*/
|
||||
const Embedded& GetFaceFeatureCache() const;
|
||||
|
||||
|
||||
private:
|
||||
// Private member variables
|
||||
CustomPipelineParameter m_parameter_; ///< Stores custom parameters for the pipeline
|
||||
int32_t m_max_detect_face_{}; ///< Maximum number of faces that can be detected
|
||||
DetectMode m_detect_mode_; ///< Current detection mode (image or video)
|
||||
bool m_always_detect_{}; ///< Flag to determine if detection should always occur
|
||||
|
||||
std::shared_ptr<FaceTrack> m_face_track_; ///< Shared pointer to the FaceTrack object
|
||||
std::shared_ptr<FeatureExtraction> m_face_recognition_; ///< Shared pointer to the FaceRecognition object
|
||||
std::shared_ptr<FacePipeline> m_face_pipeline_; ///< Shared pointer to the FacePipeline object
|
||||
|
||||
private:
|
||||
// Cache data
|
||||
std::vector<ByteArray> m_detect_cache_; ///< Cache for storing serialized detected face data
|
||||
std::vector<FaceBasicData> m_face_basic_data_cache_; ///< Cache for basic face data extracted from detection
|
||||
std::vector<FaceRect> m_face_rects_cache_; ///< Cache for face rectangle data from detection
|
||||
std::vector<int32_t> m_track_id_cache_; ///< Cache for tracking IDs of detected faces
|
||||
std::vector<float> m_roll_results_cache_; ///< Cache for storing roll results from face pose estimation
|
||||
std::vector<float> m_yaw_results_cache_; ///< Cache for storing yaw results from face pose estimation
|
||||
std::vector<float> m_pitch_results_cache_; ///< Cache for storing pitch results from face pose estimation
|
||||
std::vector<FacePoseQualityResult> m_quality_results_cache_; ///< Cache for face pose quality results
|
||||
std::vector<float> m_mask_results_cache_; ///< Cache for mask detection results
|
||||
std::vector<float> m_rgb_liveness_results_cache_; ///< Cache for RGB liveness detection results
|
||||
std::vector<float> m_quality_score_results_cache_; ///< Cache for RGB face quality score results
|
||||
Embedded m_face_feature_cache_; ///< Cache for current face feature data
|
||||
|
||||
std::mutex m_mtx_; ///< Mutex for thread safety.
|
||||
|
||||
};
|
||||
|
||||
} // namespace hyper
|
||||
|
||||
#endif //HYPERFACEREPO_FACE_CONTEXT_H
|
||||
@@ -0,0 +1,536 @@
|
||||
//
|
||||
// Created by tunm on 2023/9/8.
|
||||
//
|
||||
|
||||
#include "feature_hub.h"
|
||||
#include "simd.h"
|
||||
#include "herror.h"
|
||||
#include <thread>
|
||||
|
||||
|
||||
namespace inspire {
|
||||
|
||||
std::mutex FeatureHub::mutex_;
|
||||
std::shared_ptr<FeatureHub> FeatureHub::instance_ = nullptr;
|
||||
|
||||
FeatureHub::FeatureHub(){}
|
||||
|
||||
std::shared_ptr<FeatureHub> FeatureHub::GetInstance() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!instance_) {
|
||||
instance_ = std::shared_ptr<FeatureHub>(new FeatureHub());
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::DisableHub() {
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGW("FeatureHub is already disabled.");
|
||||
return HERR_FT_HUB_DISABLE_REPETITION;
|
||||
}
|
||||
// Close the database if it starts
|
||||
if (m_db_) {
|
||||
int ret = m_db_->CloseDatabase();
|
||||
if (ret != HSUCCEED) {
|
||||
INSPIRE_LOGE("Failed to close the database: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
m_db_.reset();
|
||||
}
|
||||
|
||||
m_feature_matrix_list_.clear();
|
||||
m_search_face_feature_cache_.clear();
|
||||
|
||||
m_db_configuration_ = DatabaseConfiguration(); // Reset using the default constructor
|
||||
m_recognition_threshold_ = 0.0f;
|
||||
m_search_mode_ = SEARCH_MODE_EAGER;
|
||||
|
||||
m_face_feature_ptr_cache_.reset();
|
||||
m_enable_ = false;
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::EnableHub(const DatabaseConfiguration &configuration, MatrixCore core) {
|
||||
int32_t ret;
|
||||
if (m_enable_) {
|
||||
INSPIRE_LOGW("You have enabled the FeatureHub feature. It is not valid to do so again");
|
||||
return HERR_FT_HUB_ENABLE_REPETITION;
|
||||
}
|
||||
// Config
|
||||
m_db_configuration_ = configuration;
|
||||
m_recognition_threshold_ = m_db_configuration_.recognition_threshold;
|
||||
if (m_recognition_threshold_ < -1.0f || m_recognition_threshold_ > 1.0f) {
|
||||
INSPIRE_LOGW("The search threshold entered does not fit the required range (-1.0f, 1.0f) and has been set to 0.5 by default");
|
||||
m_recognition_threshold_ = 0.5f;
|
||||
}
|
||||
m_search_mode_ = m_db_configuration_.search_mode;
|
||||
if (m_db_configuration_.feature_block_num <= 0) {
|
||||
m_db_configuration_.feature_block_num = 10;
|
||||
INSPIRE_LOGW("The number of feature blocks cannot be 0, but has been set to the default number of 10, that is, the maximum number of stored faces is supported: 5120");
|
||||
} else if (m_db_configuration_.feature_block_num > 25) {
|
||||
m_db_configuration_.feature_block_num = 25;
|
||||
INSPIRE_LOGW("The number of feature blocks cannot exceed 25, which has been set to the maximum value, that is, the maximum number of stored faces supported: 12800");
|
||||
}
|
||||
// Allocate memory for the feature matrix
|
||||
for (int i = 0; i < m_db_configuration_.feature_block_num; ++i) {
|
||||
std::shared_ptr<FeatureBlock> block;
|
||||
block.reset(FeatureBlock::Create(core, 512, 512));
|
||||
m_feature_matrix_list_.push_back(block);
|
||||
}
|
||||
if (m_db_configuration_.enable_use_db) {
|
||||
m_db_ = std::make_shared<SQLiteFaceManage>();
|
||||
if (IsDirectory(m_db_configuration_.db_path)){
|
||||
std::string dbFile = m_db_configuration_.db_path + "/" + DB_FILE_NAME;
|
||||
ret = m_db_->OpenDatabase(dbFile);
|
||||
} else {
|
||||
ret = m_db_->OpenDatabase(m_db_configuration_.db_path);
|
||||
}
|
||||
if (ret != HSUCCEED) {
|
||||
INSPIRE_LOGE("An error occurred while opening the database: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<FaceFeatureInfo> infos;
|
||||
ret = m_db_->GetTotalFeatures(infos);
|
||||
if (ret == HSUCCEED) {
|
||||
if (infos.empty()) {
|
||||
for (auto const &info: infos) {
|
||||
ret = InsertFaceFeature(info.feature, info.tag, info.customId);
|
||||
if (ret != HSUCCEED) {
|
||||
INSPIRE_LOGE("ID: %d, Inserting error: %d", info.customId, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_enable_ = true;
|
||||
} else {
|
||||
INSPIRE_LOGE("Failed to get the vector from the database.");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
m_enable_ = true;
|
||||
}
|
||||
|
||||
m_face_feature_ptr_cache_ = std::make_shared<FaceFeatureEntity>();
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::CosineSimilarity(const std::vector<float>& v1, const std::vector<float>& v2, float &res) {
|
||||
if (v1.size() != v2.size() || v1.empty()) {
|
||||
return HERR_SESS_REC_CONTRAST_FEAT_ERR; // The similarity cannot be calculated if the vector lengths are not equal
|
||||
}
|
||||
// Calculate the cosine similarity
|
||||
res = simd_dot(v1.data(), v2.data(), v1.size());
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
int32_t FeatureHub::CosineSimilarity(const float *v1, const float *v2, int32_t size, float &res) {
|
||||
res = simd_dot(v1, v2, size);
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
int32_t FeatureHub::RegisterFaceFeature(const std::vector<float>& feature, int featureIndex, const std::string &tag, int32_t customId) {
|
||||
if (featureIndex < 0 || featureIndex >= m_feature_matrix_list_.size() * NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_INVALID_INDEX; // Invalid feature index number
|
||||
}
|
||||
|
||||
// Compute which FeatureBlock and which row the feature vector should be stored in
|
||||
int blockIndex = featureIndex / NUM_OF_FEATURES_IN_BLOCK; // The FeatureBlock where the computation is located
|
||||
int rowIndex = featureIndex % NUM_OF_FEATURES_IN_BLOCK; // Calculate the line number in the FeatureBlock
|
||||
|
||||
// Call the appropriate FeatureBlock registration function
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->RegisterFeature(rowIndex, feature, tag, customId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::InsertFaceFeature(const std::vector<float>& feature, const std::string &tag, int32_t customId) {
|
||||
int32_t ret = HSUCCEED;
|
||||
for (int i = 0; i < m_feature_matrix_list_.size(); ++i) {
|
||||
auto &block = m_feature_matrix_list_[i];
|
||||
ret = block->AddFeature(feature, tag, customId);
|
||||
if (ret != HERR_SESS_REC_BLOCK_FULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::SearchFaceFeature(const std::vector<float>& queryFeature, SearchResult &searchResult, float threshold, bool mostSimilar) {
|
||||
if (queryFeature.size() != NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR; // Query feature size does not match expectations
|
||||
}
|
||||
|
||||
bool found = false; // Whether matching features are found
|
||||
float maxScore = -1.0f; // The maximum score is initialized to a negative number
|
||||
int maxIndex = -1; // The index corresponding to the maximum score
|
||||
std::string tag = "None";
|
||||
int maxCid = -1;
|
||||
|
||||
for (int blockIndex = 0; blockIndex < m_feature_matrix_list_.size(); ++blockIndex) {
|
||||
if (m_feature_matrix_list_[blockIndex]->GetUsedCount() == 0) {
|
||||
// If the FeatureBlock has no used features, skip to the next block
|
||||
continue;
|
||||
}
|
||||
|
||||
int startIndex = blockIndex * NUM_OF_FEATURES_IN_BLOCK;
|
||||
SearchResult tempResult;
|
||||
|
||||
// Call the appropriate FeatureBlock search function
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->SearchNearest(queryFeature, tempResult);
|
||||
|
||||
if (result != HSUCCEED) {
|
||||
// Error
|
||||
return result;
|
||||
}
|
||||
|
||||
// If you find a higher score feature
|
||||
if (tempResult.score > maxScore) {
|
||||
maxScore = tempResult.score;
|
||||
maxIndex = startIndex + tempResult.index;
|
||||
tag = tempResult.tag;
|
||||
maxCid = tempResult.customId;
|
||||
if (maxScore >= threshold) {
|
||||
found = true;
|
||||
if (!mostSimilar) {
|
||||
// Use Eager-Mode: When the score is greater than or equal to the threshold, stop searching for the next FeatureBlock
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
searchResult.score = maxScore;
|
||||
searchResult.index = maxIndex;
|
||||
searchResult.tag = tag;
|
||||
searchResult.customId = maxCid;
|
||||
} else {
|
||||
searchResult.score = -1.0f;
|
||||
searchResult.index = -1;
|
||||
searchResult.tag = "None";
|
||||
searchResult.customId = -1;
|
||||
}
|
||||
|
||||
return HSUCCEED; // No matching feature found but not an error
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t FeatureHub::SearchFaceFeatureTopK(const std::vector<float>& queryFeature, std::vector<SearchResult> &searchResultList, size_t maxTopK, float threshold) {
|
||||
if (queryFeature.size() != NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR;
|
||||
}
|
||||
|
||||
std::vector<SearchResult> tempResultList;
|
||||
searchResultList.clear();
|
||||
|
||||
for (int blockIndex = 0; blockIndex < m_feature_matrix_list_.size(); ++blockIndex) {
|
||||
if (m_feature_matrix_list_[blockIndex]->GetUsedCount() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tempResultList.clear();
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->SearchTopKNearest(queryFeature, maxTopK, tempResultList);
|
||||
if (result != HSUCCEED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const SearchResult& result : tempResultList) {
|
||||
if (result.score >= threshold) {
|
||||
searchResultList.push_back(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(searchResultList.begin(), searchResultList.end(), [](const SearchResult& a, const SearchResult& b) {
|
||||
return a.score > b.score;
|
||||
});
|
||||
|
||||
if (searchResultList.size() > maxTopK) {
|
||||
searchResultList.resize(maxTopK);
|
||||
}
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::DeleteFaceFeature(int featureIndex) {
|
||||
if (featureIndex < 0 || featureIndex >= m_feature_matrix_list_.size() * NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_INVALID_INDEX; // Invalid feature index number
|
||||
}
|
||||
|
||||
// Calculate which FeatureBlock and which row the feature vector should be removed in
|
||||
int blockIndex = featureIndex / NUM_OF_FEATURES_IN_BLOCK; // The FeatureBlock where the computation is located
|
||||
int rowIndex = featureIndex % NUM_OF_FEATURES_IN_BLOCK; // Calculate the line number in the FeatureBlock
|
||||
|
||||
// Call the appropriate FeatureBlock delete function
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->DeleteFeature(rowIndex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::GetFaceFeature(int featureIndex, Embedded &feature) {
|
||||
if (featureIndex < 0 || featureIndex >= m_feature_matrix_list_.size() * NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_INVALID_INDEX; // Invalid feature index number
|
||||
}
|
||||
// Calculate which FeatureBlock and which row the feature vector should be removed in
|
||||
int blockIndex = featureIndex / NUM_OF_FEATURES_IN_BLOCK; // The FeatureBlock where the computation is located
|
||||
int rowIndex = featureIndex % NUM_OF_FEATURES_IN_BLOCK; // Calculate the line number in the FeatureBlock
|
||||
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->GetFeature(rowIndex, feature);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::GetFaceEntity(int featureIndex, Embedded &feature, std::string& tag, FEATURE_STATE& status) {
|
||||
if (featureIndex < 0 || featureIndex >= m_feature_matrix_list_.size() * NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_INVALID_INDEX; // Invalid feature index number
|
||||
}
|
||||
// Calculate which FeatureBlock and which row the feature vector should be removed in
|
||||
int blockIndex = featureIndex / NUM_OF_FEATURES_IN_BLOCK; // The FeatureBlock where the computation is located
|
||||
int rowIndex = featureIndex % NUM_OF_FEATURES_IN_BLOCK; // Calculate the line number in the FeatureBlock
|
||||
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->GetFeature(rowIndex, feature);
|
||||
tag = m_feature_matrix_list_[blockIndex]->GetTagFromRow(rowIndex);
|
||||
status = m_feature_matrix_list_[blockIndex]->GetStateFromRow(rowIndex);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::GetFaceFeatureCount() {
|
||||
int totalFeatureCount = 0;
|
||||
|
||||
// Iterate over all FeatureBlocks and add up the number of feature vectors used
|
||||
for (const auto& block : m_feature_matrix_list_) {
|
||||
totalFeatureCount += block->GetUsedCount();
|
||||
}
|
||||
|
||||
return totalFeatureCount;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::GetFeatureNum() const {
|
||||
return NUM_OF_FEATURES_IN_BLOCK;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::UpdateFaceFeature(const std::vector<float> &feature, int featureIndex, const std::string &tag, int32_t customId) {
|
||||
if (featureIndex < 0 || featureIndex >= m_feature_matrix_list_.size() * NUM_OF_FEATURES_IN_BLOCK) {
|
||||
return HERR_SESS_REC_INVALID_INDEX; // Invalid feature index number
|
||||
}
|
||||
|
||||
// Calculate which FeatureBlock and which row the feature vector should be removed in
|
||||
int blockIndex = featureIndex / NUM_OF_FEATURES_IN_BLOCK; // The FeatureBlock where the computation is located
|
||||
int rowIndex = featureIndex % NUM_OF_FEATURES_IN_BLOCK; // Calculate the line number in the FeatureBlock
|
||||
|
||||
// Call the appropriate FeatureBlock registration function
|
||||
int32_t result = m_feature_matrix_list_[blockIndex]->UpdateFeature(rowIndex, feature, tag, customId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FeatureHub::PrintFeatureMatrixInfo() {
|
||||
m_feature_matrix_list_[0]->PrintMatrix();
|
||||
}
|
||||
|
||||
|
||||
int32_t FeatureHub::FindFeatureIndexByCustomId(int32_t customId) {
|
||||
// Iterate over all FeatureBlocks
|
||||
for (int blockIndex = 0; blockIndex < m_feature_matrix_list_.size(); ++blockIndex) {
|
||||
int startIndex = blockIndex * NUM_OF_FEATURES_IN_BLOCK;
|
||||
|
||||
// Query the customId from the current FeatureBlock
|
||||
int rowIndex = m_feature_matrix_list_[blockIndex]->FindIndexByCustomId(customId);
|
||||
|
||||
if (rowIndex != -1) {
|
||||
return startIndex + rowIndex; // 返回行号
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // If none of the featureBlocks is found, -1 is returned
|
||||
}
|
||||
|
||||
|
||||
int32_t FeatureHub::SearchFaceFeature(const Embedded &queryFeature, SearchResult &searchResult) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
m_search_face_feature_cache_.clear();
|
||||
std::memset(m_string_cache_, 0, sizeof(m_string_cache_)); // Initial Zero
|
||||
auto ret = SearchFaceFeature(queryFeature, searchResult, m_recognition_threshold_,
|
||||
m_search_mode_ == SEARCH_MODE_EXHAUSTIVE);
|
||||
if (ret == HSUCCEED) {
|
||||
if (searchResult.index != -1) {
|
||||
ret = GetFaceFeature(searchResult.index, m_search_face_feature_cache_);
|
||||
}
|
||||
m_face_feature_ptr_cache_->data = m_search_face_feature_cache_.data();
|
||||
m_face_feature_ptr_cache_->dataSize = m_search_face_feature_cache_.size();
|
||||
// Ensure that buffer overflows do not occur
|
||||
size_t copy_length = std::min(searchResult.tag.size(), sizeof(m_string_cache_) - 1);
|
||||
std::strncpy(m_string_cache_, searchResult.tag.c_str(), copy_length);
|
||||
// Make sure the string ends with a null character
|
||||
m_string_cache_[copy_length] = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::SearchFaceFeatureTopK(const Embedded& queryFeature, size_t topK) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
m_top_k_confidence_.clear();
|
||||
m_top_k_custom_ids_cache_.clear();
|
||||
auto ret = SearchFaceFeatureTopK(queryFeature, m_search_top_k_cache_, topK, m_recognition_threshold_);
|
||||
if (ret == HSUCCEED) {
|
||||
for (int i = 0; i < m_search_top_k_cache_.size(); ++i) {
|
||||
auto &item = m_search_top_k_cache_[i];
|
||||
m_top_k_custom_ids_cache_.push_back(item.customId);
|
||||
m_top_k_confidence_.push_back(item.score);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::FaceFeatureInsertFromCustomId(const std::vector<float> &feature, const std::string &tag,
|
||||
int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
auto index = FindFeatureIndexByCustomId(customId);
|
||||
if (index != -1) {
|
||||
return HERR_SESS_REC_ID_ALREADY_EXIST;
|
||||
}
|
||||
auto ret = InsertFaceFeature(feature, tag, customId);
|
||||
if (ret == HSUCCEED && m_db_ != nullptr) {
|
||||
// operational database
|
||||
FaceFeatureInfo item = {0};
|
||||
item.customId = customId;
|
||||
item.tag = tag;
|
||||
item.feature = feature;
|
||||
ret = m_db_->InsertFeature(item);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::FaceFeatureRemoveFromCustomId(int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
auto index = FindFeatureIndexByCustomId(customId);
|
||||
if (index == -1) {
|
||||
return HERR_SESS_REC_INVALID_INDEX;
|
||||
}
|
||||
auto ret = DeleteFaceFeature(index);
|
||||
if (ret == HSUCCEED && m_db_ != nullptr) {
|
||||
ret = m_db_->DeleteFeature(customId);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::FaceFeatureUpdateFromCustomId(const std::vector<float> &feature, const std::string &tag,
|
||||
int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
auto index = FindFeatureIndexByCustomId(customId);
|
||||
if (index == -1) {
|
||||
return HERR_SESS_REC_INVALID_INDEX;
|
||||
}
|
||||
auto ret = UpdateFaceFeature(feature, index, tag, customId);
|
||||
if (ret == HSUCCEED && m_db_ != nullptr) {
|
||||
FaceFeatureInfo item = {0};
|
||||
item.customId = customId;
|
||||
item.tag = tag;
|
||||
item.feature = feature;
|
||||
ret = m_db_->UpdateFeature(item);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::GetFaceFeatureFromCustomId(int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
auto index = FindFeatureIndexByCustomId(customId);
|
||||
if (index == -1) {
|
||||
return HERR_SESS_REC_INVALID_INDEX;
|
||||
}
|
||||
m_getter_face_feature_cache_.clear();
|
||||
std::string tag;
|
||||
FEATURE_STATE status;
|
||||
auto ret = GetFaceEntity(index, m_getter_face_feature_cache_, tag, status);
|
||||
m_face_feature_ptr_cache_->data = m_getter_face_feature_cache_.data();
|
||||
m_face_feature_ptr_cache_->dataSize = m_getter_face_feature_cache_.size();
|
||||
// Ensure that buffer overflows do not occur
|
||||
size_t copy_length = std::min(tag.size(), sizeof(m_string_cache_) - 1);
|
||||
std::strncpy(m_string_cache_, tag.c_str(), copy_length);
|
||||
// Make sure the string ends with a null character
|
||||
m_string_cache_[copy_length] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t FeatureHub::ViewDBTable() {
|
||||
if (!m_enable_) {
|
||||
INSPIRE_LOGE("FeatureHub is disabled, please enable it before it can be served");
|
||||
return HERR_FT_HUB_DISABLE;
|
||||
}
|
||||
auto ret = m_db_->ViewTotal();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FeatureHub::SetRecognitionThreshold(float threshold) {
|
||||
m_recognition_threshold_ = threshold;
|
||||
}
|
||||
|
||||
void FeatureHub::SetRecognitionSearchMode(SearchMode mode) {
|
||||
m_search_mode_ = mode;
|
||||
}
|
||||
|
||||
// =========== Getter ===========
|
||||
|
||||
const Embedded& FeatureHub::GetSearchFaceFeatureCache() const {
|
||||
return m_search_face_feature_cache_;
|
||||
}
|
||||
|
||||
char *FeatureHub::GetStringCache() {
|
||||
return m_string_cache_;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FaceFeaturePtr>& FeatureHub::GetFaceFeaturePtrCache() const {
|
||||
return m_face_feature_ptr_cache_;
|
||||
}
|
||||
|
||||
std::vector<float> &FeatureHub::GetTopKConfidence() {
|
||||
return m_top_k_confidence_;
|
||||
}
|
||||
|
||||
std::vector<int32_t> &FeatureHub::GetTopKCustomIdsCache() {
|
||||
return m_top_k_custom_ids_cache_;
|
||||
}
|
||||
|
||||
|
||||
} // namespace hyper
|
||||
@@ -0,0 +1,352 @@
|
||||
//
|
||||
// Created by tunm on 2023/9/8.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FACERECOGNITION_H
|
||||
#define HYPERFACEREPO_FACERECOGNITION_H
|
||||
|
||||
#include <mutex>
|
||||
#include "common/face_info/face_object.h"
|
||||
#include "common/face_data/data_tools.h"
|
||||
#include "middleware/camera_stream/camera_stream.h"
|
||||
#include "feature_hub/features_block/feature_block.h"
|
||||
#include "feature_hub/persistence/sqlite_faces_manage.h"
|
||||
#include "middleware/model_archive/inspire_archive.h"
|
||||
|
||||
/**
|
||||
* @def DB_FILE_NAME
|
||||
* @brief Default database file name used in the FaceContext.
|
||||
*/
|
||||
#define DB_FILE_NAME ".E63520A95DD5B3892C56DA38C3B28E551D8173FD"
|
||||
|
||||
#define FEATURE_HUB FeatureHub::GetInstance()
|
||||
|
||||
namespace inspire {
|
||||
|
||||
// Comparator function object to sort SearchResult by score (descending order)
|
||||
struct CompareByScore {
|
||||
bool operator()(const SearchResult& a, const SearchResult& b) const {
|
||||
return a.score > b.score;
|
||||
}
|
||||
};
|
||||
|
||||
typedef enum SearchMode {
|
||||
SEARCH_MODE_EAGER = 0, // Eager mode: Stops when a vector meets the threshold.
|
||||
SEARCH_MODE_EXHAUSTIVE, // Exhaustive mode: Searches until the best match is found.
|
||||
} SearchMode;
|
||||
|
||||
|
||||
/**
|
||||
* @struct DatabaseConfiguration
|
||||
* @brief Structure to configure database settings for FaceRecognition.
|
||||
*/
|
||||
using DatabaseConfiguration = struct DatabaseConfiguration {
|
||||
int feature_block_num = 20;
|
||||
bool enable_use_db = false; ///< Whether to enable data persistence.
|
||||
std::string db_path; ///< Path to the database file.
|
||||
float recognition_threshold = 0.48f; ///< Face search threshold
|
||||
SearchMode search_mode = SEARCH_MODE_EAGER; ///< Search mode
|
||||
};
|
||||
|
||||
/**
|
||||
* @class FeatureHub
|
||||
* @brief Service for internal feature vector storage.
|
||||
*
|
||||
* This class provides methods for face feature extraction, registration, update, search, and more.
|
||||
*/
|
||||
class INSPIRE_API FeatureHub {
|
||||
private:
|
||||
static std::mutex mutex_; ///< Mutex lock
|
||||
static std::shared_ptr<FeatureHub> instance_; ///< FeatureHub Instance
|
||||
const int32_t NUM_OF_FEATURES_IN_BLOCK = 512; ///< Number of features in each feature block.
|
||||
|
||||
FeatureHub(const FeatureHub&) = delete;
|
||||
FeatureHub& operator=(const FeatureHub&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Enables the feature hub with the specified configuration and matrix core.
|
||||
*
|
||||
* This function initializes and configures the feature hub based on the provided database
|
||||
* configuration and the specified matrix processing core. It prepares the hub for operation,
|
||||
* setting up necessary resources such as database connections and data processing pipelines.
|
||||
*
|
||||
* @param configuration The database configuration settings used to configure the hub.
|
||||
* @param core The matrix core used for processing, defaulting to OpenCV if not specified.
|
||||
* @return int32_t Returns a status code indicating success (0) or failure (non-zero).
|
||||
*/
|
||||
int32_t EnableHub(const DatabaseConfiguration& configuration, MatrixCore core = MC_OPENCV);
|
||||
|
||||
/**
|
||||
* @brief Disables the feature hub, freeing all associated resources.
|
||||
*
|
||||
* This function stops all operations within the hub, releases all occupied resources,
|
||||
* such as database connections and internal data structures. It is used to safely
|
||||
* shutdown the hub when it is no longer needed or before the application exits, ensuring
|
||||
* that all resources are properly cleaned up.
|
||||
*
|
||||
* @return int32_t Returns a status code indicating success (0) or failure (non-zero).
|
||||
*/
|
||||
int32_t DisableHub();
|
||||
|
||||
|
||||
static std::shared_ptr<FeatureHub> GetInstance();
|
||||
|
||||
/**
|
||||
* @brief Searches for a face feature within stored data.
|
||||
* @param queryFeature Embedded feature to search for.
|
||||
* @param searchResult SearchResult object to store search results.
|
||||
* @return int32_t Status code of the search operation.
|
||||
*/
|
||||
int32_t SearchFaceFeature(const Embedded& queryFeature, SearchResult &searchResult);
|
||||
|
||||
/**
|
||||
* @brief Search the stored data for the top k facial features that are most similar.
|
||||
* @param topK Maximum search
|
||||
* @return int32_t Status code of the search operation.
|
||||
*/
|
||||
int32_t SearchFaceFeatureTopK(const Embedded& queryFeature, size_t topK);
|
||||
|
||||
/**
|
||||
* @brief Inserts a face feature with a custom ID.
|
||||
* @param feature Vector of floats representing the face feature.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom ID for the feature.
|
||||
* @return int32_t Status code of the insertion operation.
|
||||
*/
|
||||
int32_t FaceFeatureInsertFromCustomId(const std::vector<float>& feature, const std::string &tag, int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Removes a face feature by its custom ID.
|
||||
* @param customId Custom ID of the feature to remove.
|
||||
* @return int32_t Status code of the removal operation.
|
||||
*/
|
||||
int32_t FaceFeatureRemoveFromCustomId(int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Updates a face feature by its custom ID.
|
||||
* @param feature Vector of floats representing the new face feature.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom ID of the feature to update.
|
||||
* @return int32_t Status code of the update operation.
|
||||
*/
|
||||
int32_t FaceFeatureUpdateFromCustomId(const std::vector<float>& feature, const std::string &tag, int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Retrieves a face feature by its custom ID.
|
||||
* @param customId Custom ID of the feature to retrieve.
|
||||
* @return int32_t Status code of the retrieval operation.
|
||||
*/
|
||||
int32_t GetFaceFeatureFromCustomId(int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Views the database table containing face data.
|
||||
* @return int32_t Status code of the operation.
|
||||
*/
|
||||
int32_t ViewDBTable();
|
||||
|
||||
/**
|
||||
* @brief Sets the recognition threshold for face recognition.
|
||||
* @param threshold Float value of the new threshold.
|
||||
*/
|
||||
void SetRecognitionThreshold(float threshold);
|
||||
|
||||
/**
|
||||
* @brief Sets the search mode for face recognition.
|
||||
* @param mode Search mode.
|
||||
*/
|
||||
void SetRecognitionSearchMode(SearchMode mode);
|
||||
|
||||
/**
|
||||
* @brief Computes the cosine similarity between two feature vectors.
|
||||
*
|
||||
* @param v1 First feature vector.
|
||||
* @param v2 Second feature vector.
|
||||
* @param res Output parameter to store the cosine similarity result.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
static int32_t CosineSimilarity(const std::vector<float>& v1, const std::vector<float>& v2, float &res);
|
||||
|
||||
/**
|
||||
* @brief Computes the cosine similarity between two feature vectors.
|
||||
*
|
||||
* @param v1 Pointer to the first feature vector.
|
||||
* @param v2 Pointer to the second feature vector.
|
||||
* @param size Size of the feature vectors.
|
||||
* @param res Output parameter to store the cosine similarity result.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
static int32_t CosineSimilarity(const float* v1, const float *v2, int32_t size, float &res);
|
||||
|
||||
public:
|
||||
// Getter Function
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the cache used for search operations in face feature data.
|
||||
* @return A const reference to the Embedded object containing face feature data for search.
|
||||
*/
|
||||
const Embedded& GetSearchFaceFeatureCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache of face feature pointers.
|
||||
* @return A shared pointer to the cache of face feature pointers.
|
||||
*/
|
||||
const std::shared_ptr<FaceFeaturePtr>& GetFaceFeaturePtrCache() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the cache for temporary string storage.
|
||||
* @return A pointer to the character array used as a string cache.
|
||||
*/
|
||||
char* GetStringCache();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the number of features in the feature block.
|
||||
*
|
||||
* @return int32_t Number of features.
|
||||
*/
|
||||
int32_t GetFeatureNum() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieves the total number of facial features stored in the feature block.
|
||||
*
|
||||
* @return int32_t Total number of facial features.
|
||||
*/
|
||||
int32_t GetFaceFeatureCount();
|
||||
|
||||
std::vector<float> &GetTopKConfidence();
|
||||
|
||||
std::vector<int32_t> &GetTopKCustomIdsCache();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor for FeatureHub class.
|
||||
*/
|
||||
FeatureHub();
|
||||
|
||||
/**
|
||||
* @brief Registers a facial feature in the feature block.
|
||||
*
|
||||
* @param feature Vector of floats representing the feature.
|
||||
* @param featureIndex Index of the feature in the block.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t RegisterFaceFeature(const std::vector<float>& feature, int featureIndex, const std::string &tag, int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Updates a facial feature in the feature block.
|
||||
*
|
||||
* @param feature Vector of floats representing the updated feature.
|
||||
* @param featureIndex Index of the feature in the block.
|
||||
* @param tag New string tag for the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t UpdateFaceFeature(const std::vector<float>& feature, int featureIndex, const std::string &tag, int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Searches for the nearest facial feature in the feature block to a given query feature.
|
||||
*
|
||||
* @param queryFeature Query feature vector.
|
||||
* @param searchResult SearchResult structure to store the search results.
|
||||
* @param threshold Threshold for considering a match.
|
||||
* @param mostSimilar Whether to find the most similar feature.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t SearchFaceFeature(const std::vector<float>& queryFeature, SearchResult &searchResult, float threshold, bool mostSimilar=true);
|
||||
|
||||
/**
|
||||
* Search for the top K face features that are most similar to a given query feature.
|
||||
* @param queryFeature A vector of floats representing the feature to query against.
|
||||
* @param searchResultList A reference to a vector where the top K search results will be stored.
|
||||
* @param maxTopK The maximum number of top results to return.
|
||||
* @param threshold A float representing the minimum similarity score threshold.
|
||||
* @return int32_t Returns a status code (0 for success, non-zero for any errors).
|
||||
*/
|
||||
int32_t SearchFaceFeatureTopK(const std::vector<float>& queryFeature, std::vector<SearchResult> &searchResultList, size_t maxTopK, float threshold);
|
||||
|
||||
/**
|
||||
* @brief Inserts a facial feature into the feature block.
|
||||
*
|
||||
* @param feature Vector of floats representing the feature.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t InsertFaceFeature(const std::vector<float>& feature, const std::string &tag, int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Deletes a facial feature from the feature block.
|
||||
*
|
||||
* @param featureIndex Index of the feature to delete.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t DeleteFaceFeature(int featureIndex);
|
||||
|
||||
/**
|
||||
* @brief Retrieves a facial feature from the feature block.
|
||||
*
|
||||
* @param featureIndex Index of the feature to retrieve.
|
||||
* @param feature Output parameter to store the retrieved feature.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t GetFaceFeature(int featureIndex, Embedded &feature);
|
||||
|
||||
/**
|
||||
* @brief Retrieves a facial entity from the feature block.
|
||||
*
|
||||
* @param featureIndex Index of the feature to retrieve.
|
||||
* @param result Output parameter to store the retrieved entity.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t GetFaceEntity(int featureIndex, Embedded &feature, std::string& tag, FEATURE_STATE& status);
|
||||
|
||||
/**
|
||||
* @brief Finds the index of a feature by its custom ID.
|
||||
*
|
||||
* @param customId Custom identifier to search for.
|
||||
* @return int32_t Index of the feature with the given custom ID, or -1 if not found.
|
||||
*/
|
||||
int32_t FindFeatureIndexByCustomId(int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Prints information about the feature matrix.
|
||||
*/
|
||||
void PrintFeatureMatrixInfo();
|
||||
|
||||
private:
|
||||
|
||||
Embedded m_search_face_feature_cache_; ///< Cache for face feature data used in search operations
|
||||
Embedded m_getter_face_feature_cache_; ///< Cache for face feature data used in search operations
|
||||
std::shared_ptr<FaceFeaturePtr> m_face_feature_ptr_cache_; ///< Shared pointer to cache of face feature pointers
|
||||
char m_string_cache_[256]; ///< Cache for temporary string storage
|
||||
|
||||
std::vector<SearchResult> m_search_top_k_cache_; ///<
|
||||
std::vector<float> m_top_k_confidence_;
|
||||
std::vector<int32_t> m_top_k_custom_ids_cache_;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<FeatureBlock>> m_feature_matrix_list_; ///< List of feature blocks.
|
||||
|
||||
DatabaseConfiguration m_db_configuration_; ///< Configuration settings for the database
|
||||
float m_recognition_threshold_{0.48f}; ///< Threshold value for face recognition
|
||||
SearchMode m_search_mode_{SEARCH_MODE_EAGER}; ///< Flag to determine if the search should find the most similar feature
|
||||
|
||||
std::shared_ptr<SQLiteFaceManage> m_db_; ///< Shared pointer to the SQLiteFaceManage object
|
||||
|
||||
bool m_enable_{false}; ///< Running status
|
||||
|
||||
std::mutex m_res_mtx_; ///< Mutex for thread safety.
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace inspire
|
||||
|
||||
#endif //HYPERFACEREPO_FACERECOGNITION_H
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
|
||||
#include "feature_block.h"
|
||||
#include "log.h"
|
||||
#include "feature_hub/features_block/implement/feature_block_none.h"
|
||||
|
||||
#ifdef FEATURE_BLOCK_ENABLE_OPENCV
|
||||
#include "feature_hub/features_block/implement/feature_block_opencv.h"
|
||||
#endif
|
||||
|
||||
namespace inspire {
|
||||
|
||||
|
||||
FeatureBlock *FeatureBlock::Create(const MatrixCore crop_type, int32_t features_max, int32_t feature_length) {
|
||||
FeatureBlock* p = nullptr;
|
||||
switch (crop_type) {
|
||||
#ifdef FEATURE_BLOCK_ENABLE_OPENCV
|
||||
case MC_OPENCV:
|
||||
p = new FeatureBlockOpenCV(features_max, feature_length);
|
||||
break;
|
||||
#endif
|
||||
#ifdef FEATURE_BLOCK_ENABLE_EIGEN
|
||||
case MC_EIGEN:
|
||||
LOGD("Not Implement");
|
||||
break;
|
||||
#endif
|
||||
case MC_NONE:
|
||||
INSPIRE_LOGD("Not Implement");
|
||||
break;
|
||||
}
|
||||
|
||||
if (p != nullptr) {
|
||||
p->m_matrix_core_ = crop_type;
|
||||
p->m_features_max_ = features_max; // Number of facial features
|
||||
p->m_feature_length_ = feature_length; // Face feature length (default: 512)
|
||||
p->m_feature_state_.resize(features_max, FEATURE_STATE::IDLE);
|
||||
p->m_tag_list_.resize(features_max, "None");
|
||||
p->m_custom_id_list_.resize(features_max, -1);
|
||||
} else {
|
||||
INSPIRE_LOGE("Create FeatureBlock error.");
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace hyper
|
||||
@@ -0,0 +1,290 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FEATUREBLOCK_H
|
||||
#define HYPERFACEREPO_FEATUREBLOCK_H
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include "data_type.h"
|
||||
|
||||
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @enum MatrixCore
|
||||
* @brief Enumeration for different types of matrix cores used in feature extraction.
|
||||
*/
|
||||
typedef enum {
|
||||
MC_NONE, ///< C/C++ Native matrix core.
|
||||
MC_OPENCV, ///< OpenCV Mat based matrix core.
|
||||
MC_EIGEN, ///< Eigen3 Mat based matrix core.
|
||||
} MatrixCore;
|
||||
|
||||
/**
|
||||
* @enum FEATURE_STATE
|
||||
* @brief Enumeration for states of feature slots in the feature block.
|
||||
*/
|
||||
typedef enum {
|
||||
IDLE = 0, ///< Slot is idle.
|
||||
USED, ///< Slot is used.
|
||||
} FEATURE_STATE;
|
||||
|
||||
|
||||
/**
|
||||
* @struct SearchResult
|
||||
* @brief Structure to store the results of a feature search.
|
||||
*/
|
||||
typedef struct SearchResult {
|
||||
float score = -1.0f; ///< Score of the search result.
|
||||
int32_t index = -1; ///< Index of the result in the feature block.
|
||||
std::string tag = "None"; ///< Tag associated with the feature.
|
||||
int32_t customId = -1; ///< Custom identifier for the feature.
|
||||
} SearchResult;
|
||||
|
||||
/**
|
||||
* @class FeatureBlock
|
||||
* @brief Class for managing and operating on a block of facial features.
|
||||
*
|
||||
* This class provides methods to add, delete, update, and search facial features
|
||||
* in a feature block, with thread safety using mutexes.
|
||||
*/
|
||||
class INSPIRE_API FeatureBlock {
|
||||
public:
|
||||
static FeatureBlock* Create(const MatrixCore crop_type, int32_t features_max = 512, int32_t feature_length = 512);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor for the FeatureBlock class.
|
||||
*/
|
||||
virtual ~FeatureBlock() {}
|
||||
|
||||
/**
|
||||
* @brief Adds a feature to the feature block.
|
||||
* @param feature Vector of floats representing the feature.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status of the feature addition.
|
||||
*/
|
||||
virtual int32_t AddFeature(const std::vector<float>& feature, const std::string &tag, int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_); // Use mutex to protect shared data
|
||||
return UnsafeAddFeature(feature, tag, customId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deletes a feature from the feature block.
|
||||
* @param rowToDelete Index of the feature to be deleted.
|
||||
* @return int32_t Status of the feature deletion.
|
||||
*/
|
||||
virtual int32_t DeleteFeature(int rowToDelete) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
return UnsafeDeleteFeature(rowToDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates a feature in the feature block.
|
||||
* @param rowToUpdate Index of the feature to be updated.
|
||||
* @param newFeature New feature vector to replace the old one.
|
||||
* @param tag New tag for the updated feature.
|
||||
* @param customId Custom identifier for the updated feature.
|
||||
* @return int32_t Status of the feature update.
|
||||
*/
|
||||
virtual int32_t UpdateFeature(int rowToUpdate, const std::vector<float>& newFeature, const std::string &tag, int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
return UnsafeUpdateFeature(rowToUpdate, newFeature, tag, customId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers a feature at a specific index in the feature block.
|
||||
* @param rowToUpdate Index at which to register the new feature.
|
||||
* @param feature Feature vector to be registered.
|
||||
* @param tag Tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status of the feature registration.
|
||||
*/
|
||||
virtual int32_t RegisterFeature(int rowToUpdate, const std::vector<float>& feature, const std::string &tag, int32_t customId) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
return UnsafeRegisterFeature(rowToUpdate, feature, tag, customId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Searches for the nearest feature in the block to a given query feature.
|
||||
* @param queryFeature Query feature vector.
|
||||
* @param searchResult SearchResult structure to store the search results.
|
||||
* @return int32_t Status of the search operation.
|
||||
*/
|
||||
virtual int32_t SearchNearest(const std::vector<float>& queryFeature, SearchResult &searchResult) = 0;
|
||||
|
||||
/**
|
||||
* @brief Search the first k features in a block that are closest to a given query feature.
|
||||
* @param topK Maximum number of similarities
|
||||
* @param searchResults outputs
|
||||
* */
|
||||
virtual int32_t SearchTopKNearest(const std::vector<float>& queryFeature, size_t topK, std::vector<SearchResult> &searchResults) = 0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves a feature from the feature block.
|
||||
* @param row Index of the feature to retrieve.
|
||||
* @param feature Vector to store the retrieved feature.
|
||||
* @return int32_t Status of the retrieval operation.
|
||||
*/
|
||||
virtual int32_t GetFeature(int row, std::vector<float>& feature) = 0;
|
||||
|
||||
/**
|
||||
* @brief Prints the size of the feature matrix.
|
||||
*/
|
||||
virtual void PrintMatrixSize() = 0;
|
||||
|
||||
/**
|
||||
* @brief Prints the entire feature matrix.
|
||||
*/
|
||||
virtual void PrintMatrix() = 0;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Retrieves the tag associated with a feature at a given row index.
|
||||
* @param row Index of the feature to retrieve the tag for.
|
||||
* @return std::string Tag associated with the feature at the given row, or an empty string if the row is invalid.
|
||||
*/
|
||||
std::string GetTagFromRow(int row) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_); // Ensure thread safety
|
||||
if (row >= 0 && row < m_tag_list_.size() && m_feature_state_[row] == FEATURE_STATE::USED) {
|
||||
return m_tag_list_[row];
|
||||
} else {
|
||||
return ""; // Return an empty string for invalid row or unused slot
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the state of a feature slot at a given row index.
|
||||
* @param row Index of the feature slot to retrieve the state for.
|
||||
* @return FEATURE_STATE State of the feature slot at the given row, or IDLE if the row is invalid.
|
||||
*/
|
||||
FEATURE_STATE GetStateFromRow(int row) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_); // Ensure thread safety
|
||||
if (row >= 0 && row < m_feature_state_.size()) {
|
||||
return m_feature_state_[row];
|
||||
} else {
|
||||
return FEATURE_STATE::IDLE; // Treat invalid rows as IDLE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds the index of the first idle (unused) feature slot.
|
||||
* @return int Index of the first idle slot, or -1 if no idle slot is found.
|
||||
*/
|
||||
int FindFirstIdleIndex() const {
|
||||
for (int i = 0; i < m_feature_state_.size(); ++i) {
|
||||
if (m_feature_state_[i] == FEATURE_STATE::IDLE) {
|
||||
return i; // Find the first IDLE index
|
||||
}
|
||||
}
|
||||
return -1; // No IDLE found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds the index of the first used feature slot.
|
||||
* @return int Index of the first used slot, or -1 if no used slot is found.
|
||||
*/
|
||||
int FindFirstUsedIndex() const {
|
||||
for (int i = 0; i < m_feature_state_.size(); ++i) {
|
||||
if (m_feature_state_[i] == FEATURE_STATE::USED) {
|
||||
return i; // Find the first USED index
|
||||
}
|
||||
}
|
||||
return -1; // not fond USED
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Counts the number of used feature slots.
|
||||
* @return int Count of used feature slots.
|
||||
*/
|
||||
int GetUsedCount() const {
|
||||
int usedCount = 0;
|
||||
for (const FEATURE_STATE& state : m_feature_state_) {
|
||||
if (state == FEATURE_STATE::USED) {
|
||||
usedCount++;
|
||||
}
|
||||
}
|
||||
return usedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if all feature slots are used.
|
||||
* @return bool True if all slots are used, false otherwise.
|
||||
*/
|
||||
bool IsUsedFull() const {
|
||||
int usedCount = GetUsedCount();
|
||||
return usedCount >= m_features_max_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds the index of a feature slot by its custom ID.
|
||||
* @param customId The custom ID to search for.
|
||||
* @return size_t Index of the slot with the given custom ID, or -1 if not found.
|
||||
*/
|
||||
size_t FindIndexByCustomId(int32_t customId) {
|
||||
auto it = std::find(m_custom_id_list_.begin(), m_custom_id_list_.end(), customId);
|
||||
if (it != m_custom_id_list_.end()) {
|
||||
return std::distance(m_custom_id_list_.begin(), it); // return index
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Adds a feature to the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param feature Vector of floats representing the feature.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status of the feature addition.
|
||||
*/
|
||||
virtual int32_t UnsafeAddFeature(const std::vector<float>& feature, const std::string &tag, int32_t customId) = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers a feature at a specific index in the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param rowToUpdate Index at which to register the new feature.
|
||||
* @param feature Feature vector to be registered.
|
||||
* @param tag Tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status of the feature registration.
|
||||
*/
|
||||
virtual int32_t UnsafeRegisterFeature(int rowToUpdate, const std::vector<float>& feature, const std::string &tag, int32_t customId) = 0;
|
||||
|
||||
/**
|
||||
* @brief Deletes a feature from the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param rowToDelete Index of the feature to be deleted.
|
||||
* @return int32_t Status of the feature deletion.
|
||||
*/
|
||||
virtual int32_t UnsafeDeleteFeature(int rowToDelete) = 0;
|
||||
|
||||
/**
|
||||
* @brief Updates a feature in the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param rowToUpdate Index of the feature to be updated.
|
||||
* @param newFeature New feature vector to replace the old one.
|
||||
* @param tag New tag for the updated feature.
|
||||
* @param customId Custom identifier for the updated feature.
|
||||
* @return int32_t Status of the feature update.
|
||||
*/
|
||||
virtual int32_t UnsafeUpdateFeature(int rowToUpdate, const std::vector<float>& newFeature, const std::string &tag, int32_t customId) = 0;
|
||||
|
||||
protected:
|
||||
MatrixCore m_matrix_core_; ///< Type of matrix core used.
|
||||
int32_t m_features_max_; ///< Maximum number of features in the block.
|
||||
int32_t m_feature_length_; ///< Length of each feature vector.
|
||||
std::mutex m_mtx_; ///< Mutex for thread safety.
|
||||
std::vector<FEATURE_STATE> m_feature_state_; ///< State of each feature slot.
|
||||
std::vector<String> m_tag_list_; ///< List of tags associated with each feature.
|
||||
std::vector<int32_t> m_custom_id_list_; ///< List of custom IDs associated with each feature.
|
||||
|
||||
};
|
||||
|
||||
} // namespace hyper
|
||||
|
||||
#endif //HYPERFACEREPO_FEATUREBLOCK_H
|
||||
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
|
||||
#include "feature_block_none.h"
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FEATUREBLOCKNONE_H
|
||||
#define HYPERFACEREPO_FEATUREBLOCKNONE_H
|
||||
|
||||
#include "feature_hub/features_block/feature_block.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
class INSPIRE_API FeatureBlockNone {
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace hyper
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //HYPERFACEREPO_FEATUREBLOCKNONE_H
|
||||
@@ -0,0 +1,246 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
|
||||
#include "feature_block_opencv.h"
|
||||
#include "herror.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
|
||||
FeatureBlockOpenCV::FeatureBlockOpenCV(int32_t features_max, int32_t feature_length)
|
||||
:m_feature_matrix_(features_max, feature_length, CV_32F, cv::Scalar(0.0f)){
|
||||
|
||||
}
|
||||
|
||||
int32_t FeatureBlockOpenCV::UnsafeAddFeature(const std::vector<float> &feature, const std::string &tag, int32_t customId) {
|
||||
if (feature.empty()) {
|
||||
return HERR_SESS_REC_ADD_FEAT_EMPTY; // If the feature is empty, it is not added
|
||||
}
|
||||
if (feature.size() != m_feature_length_) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR;
|
||||
}
|
||||
|
||||
if (IsUsedFull()) {
|
||||
return HERR_SESS_REC_BLOCK_FULL;
|
||||
}
|
||||
|
||||
cv::Mat newFeatureMat(1, feature.size(), CV_32FC1);
|
||||
for (int i = 0; i < feature.size(); ++i) {
|
||||
newFeatureMat.at<float>(0, i) = feature[i];
|
||||
}
|
||||
auto idx = FindFirstIdleIndex(); // Find the first free vector position
|
||||
if (idx == -1) {
|
||||
return HERR_SESS_REC_BLOCK_FULL;
|
||||
}
|
||||
cv::Mat rowToUpdate = m_feature_matrix_.row(idx);
|
||||
newFeatureMat.copyTo(rowToUpdate);
|
||||
|
||||
m_feature_state_[idx] = FEATURE_STATE::USED; // Set feature vector used
|
||||
m_tag_list_[idx] = tag;
|
||||
m_custom_id_list_[idx] = customId;
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FeatureBlockOpenCV::UnsafeDeleteFeature(int rowToDelete) {
|
||||
if (m_feature_matrix_.empty() || rowToDelete < 0 || rowToDelete >= m_feature_matrix_.rows) {
|
||||
return HERR_SESS_REC_DEL_FAILURE; // Invalid row numbers or matrices are empty and will not be deleted
|
||||
}
|
||||
|
||||
cv::Mat rowToUpdate = m_feature_matrix_.row(rowToDelete);
|
||||
if (m_feature_state_[rowToDelete] == FEATURE_STATE::IDLE) {
|
||||
return HERR_SESS_REC_BLOCK_DEL_FAILURE; // Rows are idle and will not be deleted
|
||||
}
|
||||
|
||||
m_feature_state_[rowToDelete] = FEATURE_STATE::IDLE;
|
||||
m_custom_id_list_[rowToDelete] = -1;
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
int32_t FeatureBlockOpenCV::UnsafeRegisterFeature(int rowToUpdate, const std::vector<float> &feature, const std::string &tag, int32_t customId) {
|
||||
if (rowToUpdate < 0 || rowToUpdate >= m_feature_matrix_.rows) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR; // Invalid line number, not updated
|
||||
}
|
||||
|
||||
if (feature.size() != m_feature_length_) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR; // The new feature does not match the expected size and will not be updated
|
||||
}
|
||||
cv::Mat rowToUpdateMat = m_feature_matrix_.row(rowToUpdate);
|
||||
// 将新特征拷贝到指定行
|
||||
for (int i = 0; i < feature.size(); ++i) {
|
||||
rowToUpdateMat.at<float>(0, i) = feature[i];
|
||||
}
|
||||
m_feature_state_[rowToUpdate] = USED;
|
||||
m_tag_list_[rowToUpdate] = tag;
|
||||
m_custom_id_list_[rowToUpdate] = customId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FeatureBlockOpenCV::UnsafeUpdateFeature(int rowToUpdate, const std::vector<float> &newFeature, const std::string &tag, int32_t customId) {
|
||||
if (rowToUpdate < 0 || rowToUpdate >= m_feature_matrix_.rows) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR; // Invalid line number, not updated
|
||||
}
|
||||
|
||||
if (newFeature.size() != m_feature_length_) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR; // The new feature does not match the expected size and will not be updated
|
||||
}
|
||||
|
||||
cv::Mat rowToUpdateMat = m_feature_matrix_.row(rowToUpdate);
|
||||
if (m_feature_state_[rowToUpdate] == FEATURE_STATE::IDLE) {
|
||||
return HERR_SESS_REC_BLOCK_UPDATE_FAILURE; // Rows are idle and not updated
|
||||
}
|
||||
|
||||
// Copies the new feature to the specified row
|
||||
for (int i = 0; i < newFeature.size(); ++i) {
|
||||
rowToUpdateMat.at<float>(0, i) = newFeature[i];
|
||||
}
|
||||
m_tag_list_[rowToUpdate] = tag;
|
||||
m_custom_id_list_[rowToUpdate] = customId;
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t FeatureBlockOpenCV::SearchNearest(const std::vector<float>& queryFeature, SearchResult &searchResult) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
|
||||
if (queryFeature.size() != m_feature_length_) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR;
|
||||
}
|
||||
|
||||
if (GetUsedCount() == 0) {
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
cv::Mat queryMat(queryFeature.size(), 1, CV_32FC1, (void*)queryFeature.data());
|
||||
|
||||
// Calculate the cosine similarity matrix
|
||||
cv::Mat cosineSimilarities;
|
||||
cv::gemm(m_feature_matrix_, queryMat, 1, cv::Mat(), 0, cosineSimilarities);
|
||||
// Asserts that cosineSimilarities are the vector of m_features_max_ x 1
|
||||
assert(cosineSimilarities.rows == m_features_max_ && cosineSimilarities.cols == 1);
|
||||
|
||||
// Used to store similarity scores and their indexes
|
||||
std::vector<std::pair<float, int>> similarityScores;
|
||||
|
||||
for (int i = 0; i < m_features_max_; ++i) {
|
||||
// Check whether the status is IDLE
|
||||
if (m_feature_state_[i] == FEATURE_STATE::IDLE) {
|
||||
continue; // Skip the eigenvector of IDLE state
|
||||
}
|
||||
|
||||
// Gets the similarity score for line i
|
||||
float similarityScore = cosineSimilarities.at<float>(i, 0);
|
||||
|
||||
// Adds the similarity score and index to the vector as a pair
|
||||
similarityScores.push_back(std::make_pair(similarityScore, i));
|
||||
}
|
||||
|
||||
// Find the index of the largest scores in similarityScores
|
||||
if (!similarityScores.empty()) {
|
||||
auto maxScoreIter = std::max_element(similarityScores.begin(), similarityScores.end());
|
||||
float maxScore = maxScoreIter->first;
|
||||
int maxScoreIndex = maxScoreIter->second;
|
||||
|
||||
// Sets the value in the searchResult
|
||||
searchResult.score = maxScore;
|
||||
searchResult.index = maxScoreIndex;
|
||||
searchResult.tag = m_tag_list_[maxScoreIndex];
|
||||
searchResult.customId = m_custom_id_list_[maxScoreIndex];
|
||||
|
||||
return HSUCCEED; // Indicates that the maximum score is found
|
||||
}
|
||||
|
||||
|
||||
searchResult.score = -1.0f;
|
||||
searchResult.index = -1;
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
int32_t FeatureBlockOpenCV::SearchTopKNearest(const std::vector<float> &queryFeature, size_t topK, std::vector<SearchResult> &searchResults) {
|
||||
std::lock_guard<std::mutex> lock(m_mtx_);
|
||||
|
||||
if (queryFeature.size() != m_feature_length_) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR;
|
||||
}
|
||||
|
||||
if (GetUsedCount() == 0) {
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
cv::Mat queryMat(queryFeature.size(), 1, CV_32FC1, (void*)queryFeature.data());
|
||||
|
||||
// Calculate the cosine similarity matrix
|
||||
cv::Mat cosineSimilarities;
|
||||
cv::gemm(m_feature_matrix_, queryMat, 1, cv::Mat(), 0, cosineSimilarities);
|
||||
// Asserts that cosineSimilarities are the vector of m_features_max_ x 1
|
||||
assert(cosineSimilarities.rows == m_features_max_ && cosineSimilarities.cols == 1);
|
||||
|
||||
// Used to store similarity scores and their indexes
|
||||
std::vector<std::pair<float, int>> similarityScores;
|
||||
|
||||
for (int i = 0; i < m_features_max_; ++i) {
|
||||
// Check whether the status is IDLE
|
||||
if (m_feature_state_[i] == FEATURE_STATE::IDLE) {
|
||||
continue; // Skip the eigenvector of IDLE state
|
||||
}
|
||||
|
||||
// Gets the similarity score for line i
|
||||
float similarityScore = cosineSimilarities.at<float>(i, 0);
|
||||
|
||||
// Adds the similarity score and index to the vector as a pair
|
||||
similarityScores.push_back(std::make_pair(similarityScore, i));
|
||||
}
|
||||
|
||||
searchResults.clear();
|
||||
if (similarityScores.size() < topK) {
|
||||
topK = similarityScores.size();
|
||||
}
|
||||
std::partial_sort(similarityScores.begin(), similarityScores.begin() + topK, similarityScores.end(),
|
||||
[](const std::pair<float, int>& a, const std::pair<float, int>& b) {
|
||||
return a.first > b.first;
|
||||
});
|
||||
|
||||
for (size_t i = 0; i < topK; i++) {
|
||||
SearchResult result;
|
||||
result.score = similarityScores[i].first;
|
||||
result.index = similarityScores[i].second;
|
||||
result.tag = m_tag_list_[result.index];
|
||||
result.customId = m_custom_id_list_[result.index];
|
||||
searchResults.push_back(result);
|
||||
}
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
void FeatureBlockOpenCV::PrintMatrixSize() {
|
||||
std::cout << m_feature_matrix_.size << std::endl;
|
||||
}
|
||||
|
||||
void FeatureBlockOpenCV::PrintMatrix() {
|
||||
INSPIRE_LOGD("Num of Features: %d", m_feature_matrix_.cols);
|
||||
INSPIRE_LOGD("Feature length: %d", m_feature_matrix_.rows);
|
||||
}
|
||||
|
||||
int32_t FeatureBlockOpenCV::GetFeature(int row, std::vector<float> &feature) {
|
||||
if (row < 0 || row >= m_feature_matrix_.rows) {
|
||||
return HERR_SESS_REC_FEAT_SIZE_ERR; // Invalid line number, not updated
|
||||
}
|
||||
cv::Mat feat = m_feature_matrix_.row(row);
|
||||
// Copies the new feature to the specified row
|
||||
for (int i = 0; i < m_feature_length_; ++i) {
|
||||
feature.push_back(feat.at<float>(0, i));
|
||||
}
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace hyper
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_FEATUREBLOCKOPENCV_H
|
||||
#define HYPERFACEREPO_FEATUREBLOCKOPENCV_H
|
||||
#include "feature_hub/features_block/feature_block.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @class FeatureBlockOpenCV
|
||||
* @brief Class derived from FeatureBlock for managing facial features using OpenCV.
|
||||
*
|
||||
* This class provides an implementation of FeatureBlock using OpenCV's Mat data structure
|
||||
* for storing and manipulating facial features.
|
||||
*/
|
||||
class INSPIRE_API FeatureBlockOpenCV : public FeatureBlock{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor for FeatureBlockOpenCV.
|
||||
* @param features_max Maximum number of features that can be stored.
|
||||
* @param feature_length Length of each feature vector.
|
||||
*/
|
||||
explicit FeatureBlockOpenCV(int32_t features_max = 512, int32_t feature_length = 512);
|
||||
|
||||
/**
|
||||
* @brief Searches for the nearest feature in the block to a given query feature.
|
||||
* @param queryFeature Query feature vector.
|
||||
* @param searchResult SearchResult structure to store the search results.
|
||||
* @return int32_t Status of the search operation.
|
||||
*/
|
||||
int32_t SearchNearest(const std::vector<float>& queryFeature, SearchResult &searchResult) override;
|
||||
|
||||
/**
|
||||
* @brief Search the first k features in a block that are closest to a given query feature.
|
||||
* @param topK Maximum number of similarities
|
||||
* @param searchResults outputs
|
||||
* */
|
||||
int32_t SearchTopKNearest(const std::vector<float>& queryFeature, size_t topK, std::vector<SearchResult> &searchResults) override;
|
||||
|
||||
/**
|
||||
* @brief Retrieves a feature from the feature block.
|
||||
* @param row Index of the feature to retrieve.
|
||||
* @param feature Vector to store the retrieved feature.
|
||||
* @return int32_t Status of the retrieval operation.
|
||||
*/
|
||||
int32_t GetFeature(int row, std::vector<float> &feature) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Adds a feature to the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param feature Vector of floats representing the feature.
|
||||
* @param tag String tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status of the feature addition.
|
||||
*/
|
||||
int32_t UnsafeAddFeature(const std::vector<float> &feature, const std::string &tag, int32_t customId) override;
|
||||
|
||||
/**
|
||||
* @brief Registers a feature at a specific index in the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param rowToUpdate Index at which to register the new feature.
|
||||
* @param feature Feature vector to be registered.
|
||||
* @param tag Tag associated with the feature.
|
||||
* @param customId Custom identifier for the feature.
|
||||
* @return int32_t Status of the feature registration.
|
||||
*/
|
||||
int32_t UnsafeDeleteFeature(int rowToDelete) override;
|
||||
|
||||
/**
|
||||
* @brief Deletes a feature from the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param rowToDelete Index of the feature to be deleted.
|
||||
* @return int32_t Status of the feature deletion.
|
||||
*/
|
||||
int32_t UnsafeUpdateFeature(int rowToUpdate, const std::vector<float> &newFeature, const std::string &tag, int32_t customId) override;
|
||||
|
||||
/**
|
||||
* @brief Updates a feature in the feature block without thread safety.
|
||||
* This method should be overridden in derived classes.
|
||||
* @param rowToUpdate Index of the feature to be updated.
|
||||
* @param newFeature New feature vector to replace the old one.
|
||||
* @param tag New tag for the updated feature.
|
||||
* @param customId Custom identifier for the updated feature.
|
||||
* @return int32_t Status of the feature update.
|
||||
*/
|
||||
int32_t UnsafeRegisterFeature(int rowToUpdate, const std::vector<float> &feature, const std::string &tag, int32_t customId) override;
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Prints the size of the feature matrix.
|
||||
*/
|
||||
void PrintMatrixSize() override;
|
||||
|
||||
/**
|
||||
* @brief Prints the entire feature matrix.
|
||||
*/
|
||||
void PrintMatrix() override;
|
||||
|
||||
private:
|
||||
|
||||
cv::Mat m_feature_matrix_; ///< Matrix for storing feature vectors.
|
||||
|
||||
};
|
||||
|
||||
} // namespace hyper
|
||||
|
||||
|
||||
#endif //HYPERFACEREPO_FEATUREBLOCKOPENCV_H
|
||||
@@ -0,0 +1,346 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/10/11.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip> // for std::setw
|
||||
#include "sqlite_faces_manage.h"
|
||||
#include "herror.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
|
||||
SQLiteFaceManage::SQLiteFaceManage() {
|
||||
|
||||
}
|
||||
|
||||
SQLiteFaceManage::~SQLiteFaceManage() {
|
||||
CloseDatabase();
|
||||
// Optionally, you can add logging here if needed:
|
||||
// LOG_INFO("SQLiteFaceManage object destroyed and database connection closed.");
|
||||
}
|
||||
|
||||
struct SQLiteDeleter {
|
||||
void operator()(sqlite3* ptr) const {
|
||||
sqlite3_close(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int32_t SQLiteFaceManage::OpenDatabase(const std::string &dbPath) {
|
||||
sqlite3* rawDb;
|
||||
if (sqlite3_open(dbPath.c_str(), &rawDb) != SQLITE_OK) {
|
||||
// Handle error
|
||||
return HERR_FT_HUB_OPEN_ERROR;
|
||||
}
|
||||
|
||||
m_db_ = std::shared_ptr<sqlite3>(rawDb, SQLiteDeleter());
|
||||
|
||||
// Check if the table exists
|
||||
const char* checkTableSQL = "SELECT name FROM sqlite_master WHERE type='table' AND name='FaceFeatures';";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
if (sqlite3_prepare_v2(m_db_.get(), checkTableSQL, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error checking for table existence: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return HERR_FT_HUB_CHECK_TABLE_ERROR; // Assuming you have this error code
|
||||
}
|
||||
|
||||
int result = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// If table doesn't exist, create it
|
||||
if (result != SQLITE_ROW) {
|
||||
return CreateTable();
|
||||
}
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
int32_t SQLiteFaceManage::CloseDatabase() {
|
||||
if (!m_db_) {
|
||||
// LOGE("Attempted to close an already closed or uninitialized database.");
|
||||
return HERR_FT_HUB_NOT_OPENED;
|
||||
}
|
||||
|
||||
// Reset the shared_ptr. This will decrease its reference count.
|
||||
// If this is the last reference, the database will be closed due to the custom deleter.
|
||||
m_db_.reset();
|
||||
|
||||
// Optionally, log that the database was successfully closed
|
||||
// LOGD("Database successfully closed.");
|
||||
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::CreateTable() {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED; // Example error code for unopened database
|
||||
}
|
||||
|
||||
const char* createTableSQL = R"(
|
||||
CREATE TABLE IF NOT EXISTS FaceFeatures (
|
||||
customId INTEGER PRIMARY KEY,
|
||||
tag TEXT,
|
||||
feature BLOB
|
||||
)
|
||||
)";
|
||||
|
||||
char* errMsg = nullptr;
|
||||
int result = sqlite3_exec(m_db_.get(), createTableSQL, 0, 0, &errMsg);
|
||||
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error creating table: %s" , errMsg);
|
||||
sqlite3_free(errMsg);
|
||||
return result;
|
||||
}
|
||||
|
||||
// LOGD("Table successfully created or already exists.");
|
||||
return SQLITE_OK; // or SUCCESS_CODE, based on your error code system
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::InsertFeature(const FaceFeatureInfo& info) {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED; // Example error code for unopened database
|
||||
}
|
||||
|
||||
const char* insertSQL = "INSERT INTO FaceFeatures (customId, tag, feature) VALUES (?, ?, ?)";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
int result = sqlite3_prepare_v2(m_db_.get(), insertSQL, -1, &stmt, nullptr);
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error preparing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Binding values
|
||||
sqlite3_bind_int(stmt, 1, info.customId);
|
||||
sqlite3_bind_text(stmt, 2, info.tag.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_blob(stmt, 3, info.feature.data(), info.feature.size() * sizeof(float), SQLITE_STATIC);
|
||||
|
||||
result = sqlite3_step(stmt);
|
||||
if (result != SQLITE_DONE) {
|
||||
INSPIRE_LOGE("Error inserting new feature: %s" , sqlite3_errmsg(m_db_.get()));
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_INSERT_FAILURE;
|
||||
}
|
||||
|
||||
// Clean up the statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// LOGD("Feature successfully inserted.");
|
||||
return SQLITE_OK; // or SUCCESS_CODE, based on your error code system
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::GetFeature(int32_t customId, FaceFeatureInfo& outInfo) {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED;
|
||||
}
|
||||
|
||||
const char* selectSQL = "SELECT customId, tag, feature FROM FaceFeatures WHERE customId = ?";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
int result = sqlite3_prepare_v2(m_db_.get(), selectSQL, -1, &stmt, nullptr);
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error preparing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return HERR_FT_HUB_PREPARING_FAILURE;
|
||||
}
|
||||
|
||||
// Bind the customId to the prepared statement
|
||||
sqlite3_bind_int(stmt, 1, customId);
|
||||
|
||||
result = sqlite3_step(stmt);
|
||||
if (result == SQLITE_ROW) {
|
||||
outInfo.customId = sqlite3_column_int(stmt, 0);
|
||||
outInfo.tag = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
|
||||
|
||||
const void* blobData = sqlite3_column_blob(stmt, 2);
|
||||
int blobSize = sqlite3_column_bytes(stmt, 2) / sizeof(float);
|
||||
const float* begin = static_cast<const float*>(blobData);
|
||||
outInfo.feature = std::vector<float>(begin, begin + blobSize);
|
||||
|
||||
} else if (result == SQLITE_DONE) {
|
||||
INSPIRE_LOGE("No feature found with customId: %d", customId);
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_NO_RECORD_FOUND; // Assuming you have an error code for record not found
|
||||
} else {
|
||||
INSPIRE_LOGE("Error executing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_EXECUTING_FAILURE;
|
||||
}
|
||||
|
||||
// Clean up the statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
INSPIRE_LOGD("Feature successfully retrieved.");
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::DeleteFeature(int32_t customId) {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED;
|
||||
}
|
||||
|
||||
const char* deleteSQL = "DELETE FROM FaceFeatures WHERE customId = ?";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
int result = sqlite3_prepare_v2(m_db_.get(), deleteSQL, -1, &stmt, nullptr);
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error preparing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return HERR_FT_HUB_PREPARING_FAILURE;
|
||||
}
|
||||
|
||||
// Bind the customId to the prepared statement
|
||||
sqlite3_bind_int(stmt, 1, customId);
|
||||
|
||||
result = sqlite3_step(stmt);
|
||||
if (result != SQLITE_DONE) {
|
||||
INSPIRE_LOGE("Error deleting feature with customId: %d, Error: %s", customId, sqlite3_errmsg(m_db_.get()));
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_EXECUTING_FAILURE;
|
||||
}
|
||||
|
||||
int changes = sqlite3_changes(m_db_.get());
|
||||
if (changes == 0) {
|
||||
INSPIRE_LOGE("No feature found with customId: %d. Nothing was deleted.", customId);
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_NO_RECORD_FOUND; // Assuming you have an error code for record not found
|
||||
}
|
||||
|
||||
// Clean up the statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// LOGD("Feature with customId: %d successfully deleted.", customId);
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::UpdateFeature(const FaceFeatureInfo& info) {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED;
|
||||
}
|
||||
|
||||
const char* updateSQL = "UPDATE FaceFeatures SET tag = ?, feature = ? WHERE customId = ?";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
int result = sqlite3_prepare_v2(m_db_.get(), updateSQL, -1, &stmt, nullptr);
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error preparing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return HERR_FT_HUB_PREPARING_FAILURE;
|
||||
}
|
||||
|
||||
// Binding values
|
||||
sqlite3_bind_text(stmt, 1, info.tag.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_blob(stmt, 2, info.feature.data(), info.feature.size() * sizeof(float), SQLITE_STATIC);
|
||||
sqlite3_bind_int(stmt, 3, info.customId);
|
||||
|
||||
result = sqlite3_step(stmt);
|
||||
if (result != SQLITE_DONE) {
|
||||
INSPIRE_LOGE("Error updating feature with customId: %d, Error: %s", info.customId, sqlite3_errmsg(m_db_.get()));
|
||||
sqlite3_finalize(stmt);
|
||||
return result;
|
||||
}
|
||||
|
||||
int changes = sqlite3_changes(m_db_.get());
|
||||
if (changes == 0) {
|
||||
INSPIRE_LOGE("No feature found with customId: %d. Nothing was updated.", info.customId);
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_NO_RECORD_FOUND; // Assuming you have an error code for record not found
|
||||
}
|
||||
|
||||
// Clean up the statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// LOGD("Feature with customId: %d successfully updated.", info.customId);
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::ViewTotal() {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED;
|
||||
}
|
||||
|
||||
const char* selectSQL = "SELECT customId, tag FROM FaceFeatures";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
int result = sqlite3_prepare_v2(m_db_.get(), selectSQL, -1, &stmt, nullptr);
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error preparing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Print table header
|
||||
std::cout << "+----------+-----------------------+\n";
|
||||
std::cout << "| customId | tag |\n";
|
||||
std::cout << "+----------+-----------------------+\n";
|
||||
|
||||
while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||
int32_t customId = sqlite3_column_int(stmt, 0);
|
||||
const unsigned char* tag = sqlite3_column_text(stmt, 1);
|
||||
|
||||
std::cout << "| " << std::setw(8) << customId << " | " << std::setw(21) << tag << " |\n";
|
||||
}
|
||||
std::cout << "+----------+-----------------------+\n";
|
||||
|
||||
if (result != SQLITE_DONE) {
|
||||
INSPIRE_LOGE("Error executing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_PREPARING_FAILURE;
|
||||
}
|
||||
|
||||
// Clean up the statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
INSPIRE_LOGD("Successfully displayed all records.");
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
int32_t SQLiteFaceManage::GetTotalFeatures(std::vector<FaceFeatureInfo>& infoList) {
|
||||
if (!m_db_) {
|
||||
INSPIRE_LOGE("Database is not opened. Please open the database first.");
|
||||
return HERR_FT_HUB_NOT_OPENED;
|
||||
}
|
||||
|
||||
const char* selectSQL = "SELECT customId, tag, feature FROM FaceFeatures";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
|
||||
int result = sqlite3_prepare_v2(m_db_.get(), selectSQL, -1, &stmt, nullptr);
|
||||
if (result != SQLITE_OK) {
|
||||
INSPIRE_LOGE("Error preparing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
return HERR_FT_HUB_PREPARING_FAILURE;
|
||||
}
|
||||
|
||||
while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||
FaceFeatureInfo featureInfo;
|
||||
|
||||
featureInfo.customId = sqlite3_column_int(stmt, 0);
|
||||
featureInfo.tag = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
|
||||
|
||||
const void* blobData = sqlite3_column_blob(stmt, 2);
|
||||
int blobSize = sqlite3_column_bytes(stmt, 2) / sizeof(float);
|
||||
const float* begin = static_cast<const float*>(blobData);
|
||||
featureInfo.feature = std::vector<float>(begin, begin + blobSize);
|
||||
|
||||
infoList.push_back(featureInfo);
|
||||
}
|
||||
|
||||
if (result != SQLITE_DONE) {
|
||||
INSPIRE_LOGE("Error executing the SQL statement: %s", sqlite3_errmsg(m_db_.get()));
|
||||
sqlite3_finalize(stmt);
|
||||
return HERR_FT_HUB_EXECUTING_FAILURE;
|
||||
}
|
||||
|
||||
// Clean up the statement
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// LOGD("Successfully retrieved all features.");
|
||||
return HSUCCEED;
|
||||
}
|
||||
|
||||
|
||||
} // namespace hyper
|
||||
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/10/11.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_SQLITEFACEMANAGE_H
|
||||
#define HYPERFACEREPO_SQLITEFACEMANAGE_H
|
||||
|
||||
#include "data_type.h"
|
||||
#include "log.h"
|
||||
#include "middleware/sqlite/sqlite3.h" // Include the SQLite3 header
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "memory"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @struct FaceFeatureInfo
|
||||
* @brief Structure to represent information about a facial feature.
|
||||
*/
|
||||
typedef struct {
|
||||
int32_t customId; ///< Custom identifier for the feature.
|
||||
std::string tag; ///< Tag associated with the feature.
|
||||
std::vector<float> feature; ///< Vector of floats representing the feature.
|
||||
} FaceFeatureInfo;
|
||||
|
||||
/**
|
||||
* @class SQLiteFaceManage
|
||||
* @brief Class for managing facial features using SQLite database.
|
||||
*
|
||||
* This class provides methods to open, close, create tables, insert, retrieve, delete, and update
|
||||
* facial features in an SQLite database. It also allows viewing the total number of features in the database.
|
||||
*/
|
||||
class INSPIRE_API SQLiteFaceManage {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for SQLiteFaceManage class.
|
||||
*/
|
||||
SQLiteFaceManage();
|
||||
|
||||
/**
|
||||
* @brief Destructor for SQLiteFaceManage class.
|
||||
*/
|
||||
~SQLiteFaceManage();
|
||||
|
||||
/**
|
||||
* @brief Opens an SQLite database at the specified path.
|
||||
*
|
||||
* @param dbPath Path to the SQLite database file.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t OpenDatabase(const std::string& dbPath);
|
||||
|
||||
/**
|
||||
* @brief Closes the currently open SQLite database.
|
||||
*
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t CloseDatabase();
|
||||
|
||||
/**
|
||||
* @brief Creates an SQLite table for storing facial features if it doesn't exist.
|
||||
*
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t CreateTable();
|
||||
|
||||
/**
|
||||
* @brief Inserts a facial feature into the SQLite database.
|
||||
*
|
||||
* @param info Information about the facial feature to be inserted.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t InsertFeature(const FaceFeatureInfo& info);
|
||||
|
||||
/**
|
||||
* @brief Retrieves information about a facial feature from the SQLite database by custom ID.
|
||||
*
|
||||
* @param customId Custom identifier of the facial feature to retrieve.
|
||||
* @param outInfo Output parameter to store the retrieved feature information.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t GetFeature(int32_t customId, FaceFeatureInfo& outInfo);
|
||||
|
||||
/**
|
||||
* @brief Deletes a facial feature from the SQLite database by custom ID.
|
||||
*
|
||||
* @param customId Custom identifier of the facial feature to delete.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t DeleteFeature(int32_t customId);
|
||||
|
||||
/**
|
||||
* @brief Updates a facial feature in the SQLite database.
|
||||
*
|
||||
* @param info Updated information about the facial feature.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t UpdateFeature(const FaceFeatureInfo& info);
|
||||
|
||||
/**
|
||||
* @brief Retrieves information about all facial features stored in the SQLite database.
|
||||
*
|
||||
* @param infoList Output parameter to store the list of facial feature information.
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t GetTotalFeatures(std::vector<FaceFeatureInfo>& infoList);
|
||||
|
||||
/**
|
||||
* @brief Displays the total number of facial features stored in the SQLite database.
|
||||
*
|
||||
* @return int32_t Status code indicating success (0) or failure.
|
||||
*/
|
||||
int32_t ViewTotal();
|
||||
|
||||
private:
|
||||
std::shared_ptr<sqlite3> m_db_; ///< Pointer to the SQLite database.
|
||||
|
||||
};
|
||||
|
||||
} // namespace inspire
|
||||
|
||||
#endif //HYPERFACEREPO_SQLITEFACEMANAGE_H
|
||||
60
cpp-package/inspireface/cpp/inspireface/feature_hub/simd.h
Executable file
60
cpp-package/inspireface/cpp/inspireface/feature_hub/simd.h
Executable file
@@ -0,0 +1,60 @@
|
||||
#include <cstdint>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* Microsoft C/C++-compatible compiler */
|
||||
#include <intrin.h>
|
||||
#elif (defined(__x86_64__) || defined(__i386__))
|
||||
/* GCC-compatible compiler, targeting x86/x86-64 */
|
||||
#include <x86intrin.h>
|
||||
#elif defined(__ARM_NEON__)
|
||||
/* GCC-compatible compiler, targeting ARM with NEON */
|
||||
#include <arm_neon.h>
|
||||
#pragma message("USE SSE")
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && \
|
||||
(defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER))
|
||||
inline float simd_dot(const float *x, const float *y, const long &len) {
|
||||
//#pragma message("USE SSE")
|
||||
float inner_prod = 0.0f;
|
||||
__m128 X, Y, Z; // 128-bit values
|
||||
__m128 acc = _mm_setzero_ps(); // set to (0, 0, 0, 0)
|
||||
float temp[4];
|
||||
|
||||
long i;
|
||||
for (i = 0; i + 4 < len; i += 4) {
|
||||
X = _mm_loadu_ps(x + i); // load chunk of 4 floats
|
||||
Y = _mm_loadu_ps(y + i);
|
||||
Z = _mm_mul_ps(X, Y);
|
||||
acc = _mm_add_ps(acc, Z);
|
||||
}
|
||||
_mm_storeu_ps(&temp[0], acc); // store acc into an array
|
||||
inner_prod = temp[0] + temp[1] + temp[2] + temp[3];
|
||||
|
||||
// add the remaining values
|
||||
for (; i < len; ++i) {
|
||||
inner_prod += x[i] * y[i];
|
||||
}
|
||||
return inner_prod;
|
||||
}
|
||||
#else
|
||||
inline float simd_dot(const float *x, const float *y, const long &len) {
|
||||
//#pragma message("USE NEON")
|
||||
float inner_prod = 0.0f;
|
||||
float32x4_t X, Y, Z; // 128-bit values
|
||||
float32x4_t acc = vdupq_n_f32(0.0f); // set to (0, 0, 0, 0)
|
||||
long i;
|
||||
for (i = 0; i + 4 < len; i += 4) {
|
||||
X = vld1q_f32(x + i); // load chunk of 4 floats
|
||||
Y = vld1q_f32(y + i);
|
||||
Z = vmulq_f32(X, Y);
|
||||
acc = vaddq_f32(acc, Z);
|
||||
}
|
||||
inner_prod = vgetq_lane_f32(acc, 0) + vgetq_lane_f32(acc, 1) +
|
||||
vgetq_lane_f32(acc, 2) + vgetq_lane_f32(acc, 3);
|
||||
for (; i < len; ++i) {
|
||||
inner_prod += x[i] * y[i];
|
||||
}
|
||||
return inner_prod;
|
||||
}
|
||||
#endif
|
||||
68
cpp-package/inspireface/cpp/inspireface/herror.h
Normal file
68
cpp-package/inspireface/cpp/inspireface/herror.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/11.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_HERROR_H
|
||||
#define HYPERFACEREPO_HERROR_H
|
||||
|
||||
|
||||
// [Anchor-Begin]
|
||||
|
||||
#define HSUCCEED (0) // Success
|
||||
#define HERR_BASIC_BASE 0X0001 // Basic error types
|
||||
#define HERR_UNKNOWN HERR_BASIC_BASE // Unknown error
|
||||
#define HERR_INVALID_PARAM (HERR_BASIC_BASE+1) // Invalid parameter
|
||||
#define HERR_INVALID_IMAGE_STREAM_HANDLE (HERR_BASIC_BASE+24) // Invalid image stream handle
|
||||
#define HERR_INVALID_CONTEXT_HANDLE (HERR_BASIC_BASE+25) // Invalid context handle
|
||||
#define HERR_INVALID_FACE_TOKEN (HERR_BASIC_BASE+30) // Invalid face token
|
||||
#define HERR_INVALID_FACE_FEATURE (HERR_BASIC_BASE+31) // Invalid face feature
|
||||
#define HERR_INVALID_FACE_LIST (HERR_BASIC_BASE+32) // Invalid face feature list
|
||||
#define HERR_INVALID_BUFFER_SIZE (HERR_BASIC_BASE+33) // Invalid copy token
|
||||
#define HERR_INVALID_IMAGE_STREAM_PARAM (HERR_BASIC_BASE+34) // Invalid image param
|
||||
#define HERR_INVALID_SERIALIZATION_FAILED (HERR_BASIC_BASE+35) // Invalid face serialization failed
|
||||
|
||||
#define HERR_SESS_BASE 0X500 // Session error types
|
||||
#define HERR_SESS_FUNCTION_UNUSABLE (HERR_SESS_BASE+2) // Function not usable
|
||||
#define HERR_SESS_TRACKER_FAILURE (HERR_SESS_BASE+3) // Tracker module not initialized
|
||||
#define HERR_SESS_INVALID_RESOURCE (HERR_SESS_BASE+10) // Invalid static resource
|
||||
#define HERR_SESS_NUM_OF_MODELS_NOT_MATCH (HERR_SESS_BASE+11) // Number of models does not match
|
||||
|
||||
#define HERR_SESS_PIPELINE_FAILURE (HERR_SESS_BASE+8) // Pipeline module not initialized
|
||||
|
||||
#define HERR_SESS_REC_EXTRACT_FAILURE (HERR_SESS_BASE+15) // Face feature extraction not registered
|
||||
#define HERR_SESS_REC_DEL_FAILURE (HERR_SESS_BASE+16) // Face feature deletion failed due to out of range index
|
||||
#define HERR_SESS_REC_UPDATE_FAILURE (HERR_SESS_BASE+17) // Face feature update failed due to out of range index
|
||||
#define HERR_SESS_REC_ADD_FEAT_EMPTY (HERR_SESS_BASE+18) // Feature vector for registration cannot be empty
|
||||
#define HERR_SESS_REC_FEAT_SIZE_ERR (HERR_SESS_BASE+19) // Incorrect length of feature vector for registration
|
||||
#define HERR_SESS_REC_INVALID_INDEX (HERR_SESS_BASE+20) // Invalid index number
|
||||
#define HERR_SESS_REC_CONTRAST_FEAT_ERR (HERR_SESS_BASE+23) // Incorrect length of feature vector for comparison
|
||||
#define HERR_SESS_REC_BLOCK_FULL (HERR_SESS_BASE+24) // Feature vector block full
|
||||
#define HERR_SESS_REC_BLOCK_DEL_FAILURE (HERR_SESS_BASE+25) // Deletion failed
|
||||
#define HERR_SESS_REC_BLOCK_UPDATE_FAILURE (HERR_SESS_BASE+26) // Update failed
|
||||
#define HERR_SESS_REC_ID_ALREADY_EXIST (HERR_SESS_BASE+27) // ID already exists
|
||||
|
||||
#define HERR_SESS_FACE_DATA_ERROR (HERR_SESS_BASE+30) // Face data parsing
|
||||
|
||||
#define HERR_SESS_FACE_REC_OPTION_ERROR (HERR_SESS_BASE+40) // An optional parameter is incorrect
|
||||
|
||||
#define HERR_FT_HUB_DISABLE (HERR_SESS_BASE+49) // FeatureHub is disabled
|
||||
#define HERR_FT_HUB_OPEN_ERROR (HERR_SESS_BASE+50) // Database open error
|
||||
#define HERR_FT_HUB_NOT_OPENED (HERR_SESS_BASE+51) // Database not opened
|
||||
#define HERR_FT_HUB_NO_RECORD_FOUND (HERR_SESS_BASE+52) // No record found
|
||||
#define HERR_FT_HUB_CHECK_TABLE_ERROR (HERR_SESS_BASE+53) // Data table check error
|
||||
#define HERR_FT_HUB_INSERT_FAILURE (HERR_SESS_BASE+54) // Data insertion error
|
||||
#define HERR_FT_HUB_PREPARING_FAILURE (HERR_SESS_BASE+55) // Data preparation error
|
||||
#define HERR_FT_HUB_EXECUTING_FAILURE (HERR_SESS_BASE+56) // SQL execution error
|
||||
#define HERR_FT_HUB_NOT_VALID_FOLDER_PATH (HERR_SESS_BASE+57) // Invalid folder path
|
||||
#define HERR_FT_HUB_ENABLE_REPETITION (HERR_SESS_BASE+58) // Enable db function repeatedly
|
||||
#define HERR_FT_HUB_DISABLE_REPETITION (HERR_SESS_BASE+59) // Disable db function repeatedly
|
||||
|
||||
#define HERR_ARCHIVE_LOAD_FAILURE (HERR_SESS_BASE+80) // Archive load failure
|
||||
#define HERR_ARCHIVE_LOAD_MODEL_FAILURE (HERR_SESS_BASE+81) // Model load failure
|
||||
#define HERR_ARCHIVE_FILE_FORMAT_ERROR (HERR_SESS_BASE+82) // The archive format is incorrect
|
||||
#define HERR_ARCHIVE_REPETITION_LOAD (HERR_SESS_BASE+83) // Do not reload the model
|
||||
#define HERR_ARCHIVE_NOT_LOAD (HERR_SESS_BASE+84) // Model not loaded
|
||||
|
||||
// [Anchor-End]
|
||||
|
||||
#endif //HYPERFACEREPO_HERROR_H
|
||||
12
cpp-package/inspireface/cpp/inspireface/information.h
Normal file
12
cpp-package/inspireface/cpp/inspireface/information.h
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by tunm on 2024/1/31.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_INFORMATION_H
|
||||
#define HYPERFACEREPO_INFORMATION_H
|
||||
|
||||
#define INSPIRE_FACE_VERSION_MAJOR_STR "1"
|
||||
#define INSPIRE_FACE_VERSION_MINOR_STR "0"
|
||||
#define INSPIRE_FACE_VERSION_PATCH_STR "0"
|
||||
|
||||
#endif //HYPERFACEREPO_INFORMATION_H
|
||||
12
cpp-package/inspireface/cpp/inspireface/information.h.in
Normal file
12
cpp-package/inspireface/cpp/inspireface/information.h.in
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by tunm on 2024/1/31.
|
||||
//
|
||||
|
||||
#ifndef HYPERFACEREPO_INFORMATION_H
|
||||
#define HYPERFACEREPO_INFORMATION_H
|
||||
|
||||
#define INSPIRE_FACE_VERSION_MAJOR_STR "@INSPIRE_FACE_VERSION_MAJOR_STR@"
|
||||
#define INSPIRE_FACE_VERSION_MINOR_STR "@INSPIRE_FACE_VERSION_MINOR_STR@"
|
||||
#define INSPIRE_FACE_VERSION_PATCH_STR "@INSPIRE_FACE_VERSION_PATCH_STR@"
|
||||
|
||||
#endif //HYPERFACEREPO_INFORMATION_H
|
||||
12
cpp-package/inspireface/cpp/inspireface/log.cpp
Normal file
12
cpp-package/inspireface/cpp/inspireface/log.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by tunm on 2024/4/8.
|
||||
//
|
||||
#include "log.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
// Static Logger initialization
|
||||
LogManager* LogManager::instance = nullptr;
|
||||
std::mutex LogManager::mutex;
|
||||
|
||||
} // namespace inspire
|
||||
157
cpp-package/inspireface/cpp/inspireface/log.h
Executable file
157
cpp-package/inspireface/cpp/inspireface/log.h
Executable file
@@ -0,0 +1,157 @@
|
||||
#ifndef LOG_MANAGER_H
|
||||
#define LOG_MANAGER_H
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#ifndef INSPIRE_API
|
||||
#define INSPIRE_API
|
||||
#endif
|
||||
|
||||
// Macro to extract the filename from the full path
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
#ifdef ANDROID
|
||||
// Android platform log macros
|
||||
const std::string TAG = "InspireFace";
|
||||
#define INSPIRE_LOGD(...) inspire::LogManager::getInstance()->logAndroid(inspire::LOG_DEBUG, TAG, __VA_ARGS__)
|
||||
#define INSPIRE_LOGI(...) inspire::LogManager::getInstance()->logAndroid(inspire::LOG_INFO, TAG, __VA_ARGS__)
|
||||
#define INSPIRE_LOGW(...) inspire::LogManager::getInstance()->logAndroid(inspire::LOG_WARN, TAG, __VA_ARGS__)
|
||||
#define INSPIRE_LOGE(...) inspire::LogManager::getInstance()->logAndroid(inspire::LOG_ERROR, TAG, __VA_ARGS__)
|
||||
#define INSPIRE_LOGF(...) inspire::LogManager::getInstance()->logAndroid(inspire::LOG_FATAL, TAG, __VA_ARGS__)
|
||||
#else
|
||||
// Standard platform log macros
|
||||
#define INSPIRE_LOGD(...) inspire::LogManager::getInstance()->logStandard(inspire::LOG_DEBUG, __FILENAME__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define INSPIRE_LOGI(...) inspire::LogManager::getInstance()->logStandard(inspire::LOG_INFO, "", "", -1, __VA_ARGS__)
|
||||
#define INSPIRE_LOGW(...) inspire::LogManager::getInstance()->logStandard(inspire::LOG_WARN, __FILENAME__, "", __LINE__, __VA_ARGS__)
|
||||
#define INSPIRE_LOGE(...) inspire::LogManager::getInstance()->logStandard(inspire::LOG_ERROR, __FILENAME__, "", __LINE__, __VA_ARGS__)
|
||||
#define INSPIRE_LOGF(...) inspire::LogManager::getInstance()->logStandard(inspire::LOG_FATAL, __FILENAME__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
||||
// Macro to set the global log level
|
||||
#define INSPIRE_SET_LOG_LEVEL(level) inspire::LogManager::getInstance()->setLogLevel(level)
|
||||
|
||||
namespace inspire {
|
||||
|
||||
// Log levels
|
||||
enum LogLevel {
|
||||
LOG_NONE = 0,
|
||||
LOG_DEBUG,
|
||||
LOG_INFO,
|
||||
LOG_WARN,
|
||||
LOG_ERROR,
|
||||
LOG_FATAL
|
||||
};
|
||||
|
||||
class INSPIRE_API LogManager {
|
||||
private:
|
||||
LogLevel currentLevel;
|
||||
static LogManager* instance;
|
||||
static std::mutex mutex;
|
||||
|
||||
// Private constructor
|
||||
LogManager() : currentLevel(LOG_DEBUG) {} // Default log level is DEBUG
|
||||
|
||||
public:
|
||||
// Disable copy construction and assignment
|
||||
LogManager(const LogManager&) = delete;
|
||||
LogManager& operator=(const LogManager&) = delete;
|
||||
|
||||
// Get the singleton instance
|
||||
static LogManager* getInstance() {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
if (instance == nullptr) {
|
||||
instance = new LogManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Set the log level
|
||||
void setLogLevel(LogLevel level) {
|
||||
currentLevel = level;
|
||||
}
|
||||
|
||||
// Get the current log level
|
||||
LogLevel getLogLevel() const {
|
||||
return currentLevel;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
// Method for logging on the Android platform
|
||||
void logAndroid(LogLevel level, const char* tag, const char* format, ...) const {
|
||||
if (level < currentLevel) return;
|
||||
|
||||
int androidLevel;
|
||||
switch (level) {
|
||||
case LOG_DEBUG: androidLevel = ANDROID_LOG_DEBUG; break;
|
||||
case LOG_INFO: androidLevel = ANDROID_LOG_INFO; break;
|
||||
case LOG_WARN: androidLevel = ANDROID_LOG_WARN; break;
|
||||
case LOG_ERROR: androidLevel = ANDROID_LOG_ERROR; break;
|
||||
case LOG_FATAL: androidLevel = ANDROID_LOG_FATAL; break;
|
||||
default: androidLevel = ANDROID_LOG_DEFAULT;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
__android_log_vprint(androidLevel, tag, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
#else
|
||||
// Method for standard platform logging
|
||||
void logStandard(LogLevel level, const char* filename, const char* function, int line, const char* format, ...) const {
|
||||
// Check whether the current level is LOG NONE or the log level is not enough to log
|
||||
if (currentLevel == LOG_NONE || level < currentLevel) return;
|
||||
|
||||
// Build log prefix dynamically based on available data
|
||||
bool hasPrintedPrefix = false;
|
||||
if (filename && strlen(filename) > 0) {
|
||||
printf("[%s]", filename);
|
||||
hasPrintedPrefix = true;
|
||||
}
|
||||
if (function && strlen(function) > 0) {
|
||||
printf("[%s]", function);
|
||||
hasPrintedPrefix = true;
|
||||
}
|
||||
if (line != -1) {
|
||||
printf("[%d]", line);
|
||||
hasPrintedPrefix = true;
|
||||
}
|
||||
|
||||
// Only add colon and space if any prefix was printed
|
||||
if (hasPrintedPrefix) {
|
||||
printf(": ");
|
||||
}
|
||||
|
||||
// Set text color for different log levels
|
||||
if (level == LOG_ERROR || level == LOG_FATAL) {
|
||||
printf("\033[1;31m"); // Red color for errors and fatal issues
|
||||
} else if (level == LOG_WARN) {
|
||||
printf("\033[1;33m"); // Yellow color for warnings
|
||||
}
|
||||
|
||||
// Print the actual log message
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
// Reset text color if needed
|
||||
if (level == LOG_ERROR || level == LOG_WARN || level == LOG_FATAL) {
|
||||
printf("\033[0m"); // Reset color
|
||||
}
|
||||
|
||||
printf("\n"); // New line after log message
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace inspire
|
||||
|
||||
#endif // LOG_MANAGER_H
|
||||
266
cpp-package/inspireface/cpp/inspireface/middleware/any_net.h
Normal file
266
cpp-package/inspireface/cpp/inspireface/middleware/any_net.h
Normal file
@@ -0,0 +1,266 @@
|
||||
//
|
||||
// Created by tunm on 2023/5/6.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef BIGGUYSMAIN_ANYNET_H
|
||||
#define BIGGUYSMAIN_ANYNET_H
|
||||
#include <utility>
|
||||
|
||||
#include "../data_type.h"
|
||||
#include "inference_helper/inference_helper.h"
|
||||
#include "configurable.h"
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "../log.h"
|
||||
#include "model_archive/inspire_archive.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
using AnyTensorOutputs = std::vector<std::pair<std::string, std::vector<float>>>;
|
||||
|
||||
/**
|
||||
* @class AnyNet
|
||||
* @brief Generic neural network class for various inference tasks.
|
||||
*
|
||||
* This class provides a general interface for different types of neural networks,
|
||||
* facilitating loading parameters, initializing models, and executing forward passes.
|
||||
*/
|
||||
class INSPIRE_API AnyNet {
|
||||
CONFIGURABLE_SUPPORT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for AnyNet.
|
||||
* @param name Name of the neural network.
|
||||
*/
|
||||
explicit AnyNet(std::string name):m_name_(std::move(name)) {}
|
||||
|
||||
~AnyNet() {
|
||||
m_nn_inference_->Finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads parameters and initializes the model for inference.
|
||||
* @param param Parameters for network configuration.
|
||||
* @param model Pointer to the model.
|
||||
* @param type Type of the inference helper (default: kMnn).
|
||||
* @return int32_t Status of the loading and initialization process.
|
||||
*/
|
||||
int32_t loadData(InspireModel &model, InferenceHelper::HelperType type = InferenceHelper::kMnn) {
|
||||
m_infer_type_ = type;
|
||||
// must
|
||||
pushData<int>(model.Config(), "model_index", 0);
|
||||
pushData<std::string>(model.Config(), "input_layer", "");
|
||||
pushData<std::vector<std::string>>(model.Config(), "outputs_layers", {"", });
|
||||
pushData<std::vector<int>>(model.Config(), "input_size", {320, 320});
|
||||
pushData<std::vector<float>>(model.Config(), "mean", {127.5f, 127.5f, 127.5f});
|
||||
pushData<std::vector<float>>(model.Config(), "norm", {0.0078125f, 0.0078125f, 0.0078125f});
|
||||
// rarely
|
||||
pushData<int>(model.Config(), "input_channel", 3);
|
||||
pushData<int>(model.Config(), "input_image_channel", 3);
|
||||
pushData<bool>(model.Config(), "nchw", true);
|
||||
pushData<bool>(model.Config(), "swap_color", false);
|
||||
pushData<int>(model.Config(), "data_type", InputTensorInfo::InputTensorInfo::kDataTypeImage);
|
||||
pushData<int>(model.Config(), "input_tensor_type", InputTensorInfo::TensorInfo::kTensorTypeFp32);
|
||||
pushData<int>(model.Config(), "output_tensor_type", InputTensorInfo::TensorInfo::kTensorTypeFp32);
|
||||
pushData<int>(model.Config(), "threads", 1);
|
||||
|
||||
m_nn_inference_.reset(InferenceHelper::Create(m_infer_type_));
|
||||
m_nn_inference_->SetNumThreads(getData<int>("threads"));
|
||||
#if defined(GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA) && !defined(ENABLE_RKNN)
|
||||
LOGW("You have forced the global use of MNN_CUDA as the neural network inference backend");
|
||||
m_nn_inference_->SetSpecialBackend(InferenceHelper::kMnnCuda);
|
||||
#endif
|
||||
m_output_tensor_info_list_.clear();
|
||||
std::vector<std::string> outputs_layers = getData<std::vector<std::string>>("outputs_layers");
|
||||
int tensor_type = getData<int>("input_tensor_type");
|
||||
int out_tensor_type = getData<int>("output_tensor_type");
|
||||
for (auto &name: outputs_layers) {
|
||||
m_output_tensor_info_list_.push_back(OutputTensorInfo(name, out_tensor_type));
|
||||
}
|
||||
auto ret = m_nn_inference_->Initialize(model.buffer, model.bufferSize, m_input_tensor_info_list_, m_output_tensor_info_list_);
|
||||
if (ret != InferenceHelper::kRetOk) {
|
||||
INSPIRE_LOGE("NN Initialize fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
m_input_tensor_info_list_.clear();
|
||||
InputTensorInfo input_tensor_info(getData<std::string>("input_layer"), tensor_type, getData<bool>("nchw"));
|
||||
std::vector<int> input_size = getData<std::vector<int>>("input_size");
|
||||
int width = input_size[0];
|
||||
int height = input_size[1];
|
||||
m_input_image_size_ = {width, height};
|
||||
int channel = getData<int>("input_channel");
|
||||
if (getData<bool>("nchw")) {
|
||||
input_tensor_info.tensor_dims = { 1, channel, m_input_image_size_.height, m_input_image_size_.width };
|
||||
} else {
|
||||
input_tensor_info.tensor_dims = { 1, m_input_image_size_.height, m_input_image_size_.width, channel };
|
||||
}
|
||||
|
||||
input_tensor_info.data_type = getData<int>("data_type");
|
||||
int image_channel = getData<int>("input_image_channel");
|
||||
input_tensor_info.image_info.channel = image_channel;
|
||||
|
||||
std::vector<float> mean = getData<std::vector<float>>("mean");
|
||||
std::vector<float> norm = getData<std::vector<float>>("norm");
|
||||
input_tensor_info.normalize.mean[0] = mean[0];
|
||||
input_tensor_info.normalize.mean[1] = mean[1];
|
||||
input_tensor_info.normalize.mean[2] = mean[2];
|
||||
input_tensor_info.normalize.norm[0] = norm[0];
|
||||
input_tensor_info.normalize.norm[1] = norm[1];
|
||||
input_tensor_info.normalize.norm[2] = norm[2];
|
||||
|
||||
input_tensor_info.image_info.width = width;
|
||||
input_tensor_info.image_info.height = height;
|
||||
input_tensor_info.image_info.channel = channel;
|
||||
input_tensor_info.image_info.crop_x = 0;
|
||||
input_tensor_info.image_info.crop_y = 0;
|
||||
input_tensor_info.image_info.crop_width = width;
|
||||
input_tensor_info.image_info.crop_height = height;
|
||||
input_tensor_info.image_info.is_bgr = getData<bool>("nchw");
|
||||
input_tensor_info.image_info.swap_color = getData<bool>("swap_color");
|
||||
|
||||
m_input_tensor_info_list_.push_back(input_tensor_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a forward pass of the network with given input data.
|
||||
* @param data The input matrix (image) to process.
|
||||
* @param outputs Outputs of the network (tensor outputs).
|
||||
*/
|
||||
void Forward(const Matrix &data, AnyTensorOutputs& outputs) {
|
||||
InputTensorInfo& input_tensor_info = getMInputTensorInfoList()[0];
|
||||
if (m_infer_type_ == InferenceHelper::kRknn) {
|
||||
// Start by simply implementing a temporary color shift on the outside
|
||||
if (getData<bool>("swap_color")) {
|
||||
cv::cvtColor(data, m_cache_, cv::COLOR_BGR2RGB);
|
||||
input_tensor_info.data = m_cache_.data;
|
||||
} else {
|
||||
input_tensor_info.data = data.data;
|
||||
}
|
||||
} else {
|
||||
input_tensor_info.data = data.data;
|
||||
}
|
||||
Forward(outputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a forward pass of the network.
|
||||
* @param outputs Outputs of the network (tensor outputs).
|
||||
*/
|
||||
void Forward(AnyTensorOutputs& outputs) {
|
||||
|
||||
// LOGD("ppPreProcess");
|
||||
if (m_nn_inference_->PreProcess(m_input_tensor_info_list_) != InferenceHelper::kRetOk) {
|
||||
INSPIRE_LOGD("PreProcess error");
|
||||
}
|
||||
// LOGD("PreProcess");
|
||||
if (m_nn_inference_->Process(m_output_tensor_info_list_) != InferenceHelper::kRetOk) {
|
||||
INSPIRE_LOGD("Process error");
|
||||
}
|
||||
// LOGD("Process");
|
||||
for (int i = 0; i < m_output_tensor_info_list_.size(); ++i) {
|
||||
std::vector<float> output_score_raw_list(m_output_tensor_info_list_[i].GetDataAsFloat(),
|
||||
m_output_tensor_info_list_[i].GetDataAsFloat() +
|
||||
m_output_tensor_info_list_[i].GetElementNum());
|
||||
// LOGE("m_output_tensor_info_list_[i].GetElementNum(): %d",m_output_tensor_info_list_[i].GetElementNum());
|
||||
outputs.push_back(std::make_pair(m_output_tensor_info_list_[i].name, output_score_raw_list));
|
||||
}
|
||||
|
||||
m_cache_.release();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Gets a reference to the input tensor information list.
|
||||
* @return Reference to the vector of input tensor information.
|
||||
*/
|
||||
std::vector<InputTensorInfo> &getMInputTensorInfoList() {
|
||||
return m_input_tensor_info_list_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a reference to the output tensor information list.
|
||||
* @return Reference to the vector of output tensor information.
|
||||
*/
|
||||
std::vector<OutputTensorInfo> &getMOutputTensorInfoList() {
|
||||
return m_output_tensor_info_list_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the size of the input image.
|
||||
* @return Size of the input image.
|
||||
*/
|
||||
cv::Size &getMInputImageSize() {
|
||||
return m_input_image_size_;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string m_name_; ///< Name of the neural network.
|
||||
|
||||
private:
|
||||
InferenceHelper::HelperType m_infer_type_; ///< Inference engine type
|
||||
std::shared_ptr<InferenceHelper> m_nn_inference_; ///< Shared pointer to the inference helper.
|
||||
std::vector<InputTensorInfo> m_input_tensor_info_list_; ///< List of input tensor information.
|
||||
std::vector<OutputTensorInfo> m_output_tensor_info_list_; ///< List of output tensor information.
|
||||
cv::Size m_input_image_size_{}; ///< Size of the input image.
|
||||
cv::Mat m_cache_; ///< Cached matrix for image data.
|
||||
|
||||
};
|
||||
|
||||
template <typename ImageT, typename TensorT>
|
||||
AnyTensorOutputs ForwardService(
|
||||
std::shared_ptr<AnyNet> net,
|
||||
const ImageT &input,
|
||||
std::function<void(const ImageT&, TensorT&)> transform) {
|
||||
InputTensorInfo& input_tensor_info = net->getMInputTensorInfoList()[0];
|
||||
TensorT transform_tensor;
|
||||
transform(input, transform_tensor);
|
||||
input_tensor_info.data = transform_tensor.data; // input tensor only support cv2::Mat
|
||||
|
||||
AnyTensorOutputs outputs;
|
||||
net->Forward(outputs);
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Executes a forward pass through the neural network for a given input, with preprocessing.
|
||||
* @tparam ImageT Type of the input image.
|
||||
* @tparam TensorT Type of the transformed tensor.
|
||||
* @tparam PreprocessCallbackT Type of the preprocessing callback function.
|
||||
* @param net Shared pointer to the AnyNet neural network object.
|
||||
* @param input The input image to be processed.
|
||||
* @param callback Preprocessing callback function to be applied to the input.
|
||||
* @param transform Transformation function to convert the input image to a tensor.
|
||||
* @return AnyTensorOutputs Outputs of the network (tensor outputs).
|
||||
*
|
||||
* This template function handles the preprocessing of the input image, transformation to tensor,
|
||||
* and then passes it through the neural network to get the output. The function is generic and
|
||||
* can work with different types of images and tensors, as specified by the template parameters.
|
||||
*/
|
||||
template <typename ImageT, typename TensorT, typename PreprocessCallbackT>
|
||||
AnyTensorOutputs ForwardService(
|
||||
std::shared_ptr<AnyNet> net,
|
||||
const ImageT &input,
|
||||
PreprocessCallbackT &callback,
|
||||
std::function<void(const ImageT&, TensorT&, PreprocessCallbackT&)> transform) {
|
||||
InputTensorInfo& input_tensor_info = net->getMInputTensorInfoList()[0];
|
||||
TensorT transform_tensor;
|
||||
transform(input, transform_tensor, callback);
|
||||
input_tensor_info.data = transform_tensor.data; // input tensor only support cv2::Mat
|
||||
|
||||
AnyTensorOutputs outputs;
|
||||
net->Forward(outputs);
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //BIGGUYSMAIN_ANYNET_H
|
||||
363
cpp-package/inspireface/cpp/inspireface/middleware/camera_stream/camera_stream.h
Executable file
363
cpp-package/inspireface/cpp/inspireface/middleware/camera_stream/camera_stream.h
Executable file
@@ -0,0 +1,363 @@
|
||||
#ifndef CAMERA_STREAM_H
|
||||
#define CAMERA_STREAM_H
|
||||
#include <memory>
|
||||
#include "MNN/ImageProcess.hpp"
|
||||
//#include "basic_types.h"
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include "log.h"
|
||||
//
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @brief Enum to represent rotation modes.
|
||||
*/
|
||||
enum ROTATION_MODE {
|
||||
ROTATION_0 = 0,
|
||||
ROTATION_90 = 1,
|
||||
ROTATION_180 = 2,
|
||||
ROTATION_270 = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enum to represent rotation modes.
|
||||
*/
|
||||
enum DATA_FORMAT {
|
||||
NV21 = 0, NV12 = 1, RGBA = 2, RGB = 3, BGR = 4, BGRA = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class to handle camera stream and image processing.
|
||||
*/
|
||||
class CameraStream {
|
||||
public:
|
||||
|
||||
CameraStream() {
|
||||
config_.sourceFormat = MNN::CV::YUV_NV21;
|
||||
config_.destFormat = MNN::CV::BGR;
|
||||
// config_.filterType = MNN::CV::BICUBIC;
|
||||
config_.filterType = MNN::CV::BILINEAR;
|
||||
// config_.filterType = MNN::CV::NEAREST;
|
||||
config_.wrap = MNN::CV::ZERO;
|
||||
rotation_mode_ = ROTATION_0;
|
||||
preview_size_ = 192;
|
||||
// preview_size_ = 352;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the data buffer, height, and width of the camera stream.
|
||||
*
|
||||
* @param data_buffer Pointer to the data buffer.
|
||||
* @param height Height of the image.
|
||||
* @param width Width of the image.
|
||||
*/
|
||||
void SetDataBuffer(const uint8_t *data_buffer, int height, int width) {
|
||||
this->buffer_ = data_buffer;
|
||||
this->height_ = height;
|
||||
this->width_ = width;
|
||||
preview_scale_ = preview_size_ / static_cast<float>(std::max(height,width));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the preview size.
|
||||
*
|
||||
* @param size Preview size.
|
||||
*/
|
||||
void SetPreviewSize(const int size)
|
||||
{
|
||||
preview_size_ = size;
|
||||
preview_scale_ = preview_size_ / static_cast<float>(std::max(this->height_,this->width_));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the rotation mode.
|
||||
*
|
||||
* @param mode Rotation mode (e.g., ROTATION_0, ROTATION_90).
|
||||
*/
|
||||
void SetRotationMode(ROTATION_MODE mode) { rotation_mode_ = mode; }
|
||||
|
||||
/**
|
||||
* @brief Set the data format.
|
||||
*
|
||||
* @param data_format Data format (e.g., NV21, RGBA).
|
||||
*/
|
||||
void SetDataFormat(DATA_FORMAT data_format) {
|
||||
if (data_format == NV21) {
|
||||
config_.sourceFormat = MNN::CV::YUV_NV21;
|
||||
}
|
||||
if (data_format == NV12) {
|
||||
config_.sourceFormat = MNN::CV::YUV_NV12;
|
||||
}
|
||||
if (data_format == RGBA) {
|
||||
config_.sourceFormat = MNN::CV::RGBA;
|
||||
}
|
||||
if (data_format == RGB) {
|
||||
config_.sourceFormat = MNN::CV::RGB;
|
||||
}
|
||||
if (data_format == BGR) {
|
||||
config_.sourceFormat = MNN::CV::BGR;
|
||||
}
|
||||
if (data_format == BGRA) {
|
||||
config_.sourceFormat = MNN::CV::BGRA;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an affine-transformed RGB image.
|
||||
*
|
||||
* @param affine_matrix Affine transformation matrix.
|
||||
* @param width_out Width of the output image.
|
||||
* @param height_out Height of the output image.
|
||||
* @return cv::Mat Affine-transformed RGB image.
|
||||
*/
|
||||
cv::Mat GetAffineRGBImage(const cv::Mat &affine_matrix, const int width_out,
|
||||
const int height_out) const {
|
||||
int sw = width_;
|
||||
int sh = height_;
|
||||
int rot_sw = sw;
|
||||
int rot_sh = sh;
|
||||
MNN::CV::Matrix tr;
|
||||
assert(affine_matrix.rows == 2);
|
||||
assert(affine_matrix.cols == 3);
|
||||
assert(affine_matrix.type() == CV_64F);
|
||||
cv::Mat trans_matrix;
|
||||
affine_matrix.convertTo(trans_matrix, CV_32F);
|
||||
std::vector<float> tr_cv({1, 0, 0, 0, 1, 0, 0, 0, 1});
|
||||
memcpy(tr_cv.data(), trans_matrix.data, sizeof(float) * 6);
|
||||
tr.set9(tr_cv.data());
|
||||
MNN::CV::Matrix tr_inv;
|
||||
tr.invert(&tr_inv);
|
||||
std::shared_ptr<MNN::CV::ImageProcess> process(
|
||||
MNN::CV::ImageProcess::create(config_));
|
||||
process->setMatrix(tr_inv);
|
||||
cv::Mat img_out(height_out, width_out, CV_8UC3);
|
||||
std::shared_ptr<MNN::Tensor> tensor(MNN::Tensor::create<uint8_t>(
|
||||
std::vector<int>{1, height_out, width_out, 3}, img_out.data));
|
||||
process->convert(buffer_, sw, sh, 0, tensor.get());
|
||||
// std::cout << std::to_string(1) << std::endl;
|
||||
return img_out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a preview image with optional rotation.
|
||||
*
|
||||
* @param with_rotation True if rotation is applied, false otherwise.
|
||||
* @return cv::Mat Preview image.
|
||||
*/
|
||||
cv::Mat GetPreviewImage(bool with_rotation){
|
||||
return GetScaledImage(preview_scale_ , with_rotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the preview scale.
|
||||
*
|
||||
* @return float Preview scale.
|
||||
*/
|
||||
float GetPreviewScale()
|
||||
{
|
||||
return preview_scale_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a scaled image with optional rotation.
|
||||
*
|
||||
* @param scale Scaling factor.
|
||||
* @param with_rotation True if rotation is applied, false otherwise.
|
||||
* @return cv::Mat Scaled image.
|
||||
*/
|
||||
cv::Mat GetScaledImage(const float scale, bool with_rotation) {
|
||||
int sw = width_;
|
||||
int sh = height_;
|
||||
int rot_sw = sw;
|
||||
int rot_sh = sh;
|
||||
// MNN::CV::Matrix tr;
|
||||
std::shared_ptr<MNN::CV::ImageProcess> process(
|
||||
MNN::CV::ImageProcess::create(config_));
|
||||
if (rotation_mode_ == ROTATION_270 && with_rotation) {
|
||||
float srcPoints[] = {
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ - 1),
|
||||
(float)(width_ - 1),
|
||||
0.0f,
|
||||
(float)(width_ - 1),
|
||||
(float)(height_ - 1),
|
||||
};
|
||||
float dstPoints[] = {(float)(height_ * scale - 1),
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ * scale - 1),
|
||||
(float)(width_ * scale - 1),
|
||||
0.0f,
|
||||
(float)(width_ * scale - 1)};
|
||||
|
||||
tr_.setPolyToPoly((MNN::CV::Point *)dstPoints,
|
||||
(MNN::CV::Point *)srcPoints, 4);
|
||||
process->setMatrix(tr_);
|
||||
int scaled_height = static_cast<int>(width_ * scale);
|
||||
int scaled_width = static_cast<int>(height_ * scale);
|
||||
cv::Mat img_out(scaled_height, scaled_width, CV_8UC3);
|
||||
std::shared_ptr<MNN::Tensor> tensor(MNN::Tensor::create<uint8_t>(
|
||||
std::vector<int>{1, scaled_height, scaled_width, 3}, img_out.data));
|
||||
process->convert(buffer_, sw, sh, 0, tensor.get());
|
||||
return img_out;
|
||||
} else if (rotation_mode_ == ROTATION_90 && with_rotation) {
|
||||
float srcPoints[] = {
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ - 1),
|
||||
(float)(width_ - 1),
|
||||
0.0f,
|
||||
(float)(width_ - 1),
|
||||
(float)(height_ - 1),
|
||||
};
|
||||
float dstPoints[] = {
|
||||
0.0f,
|
||||
(float)(width_ * scale - 1),
|
||||
(float)(height_ * scale - 1),
|
||||
(float)(width_ * scale - 1),
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ * scale - 1),
|
||||
0.0f,
|
||||
};
|
||||
tr_.setPolyToPoly((MNN::CV::Point *)dstPoints,
|
||||
(MNN::CV::Point *)srcPoints, 4);
|
||||
process->setMatrix(tr_);
|
||||
int scaled_height = static_cast<int>(width_ * scale);
|
||||
int scaled_width = static_cast<int>(height_ * scale);
|
||||
cv::Mat img_out(scaled_height, scaled_width, CV_8UC3);
|
||||
std::shared_ptr<MNN::Tensor> tensor(MNN::Tensor::create<uint8_t>(
|
||||
std::vector<int>{1, scaled_height, scaled_width, 3}, img_out.data));
|
||||
process->convert(buffer_, sw, sh, 0, tensor.get());
|
||||
return img_out;
|
||||
} else if (rotation_mode_ == ROTATION_180 && with_rotation) {
|
||||
float srcPoints[] = {
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ - 1),
|
||||
(float)(width_ - 1),
|
||||
0.0f,
|
||||
(float)(width_ - 1),
|
||||
(float)(height_ - 1),
|
||||
};
|
||||
float dstPoints[] = {
|
||||
(float)(width_ * scale - 1),
|
||||
(float)(height_ * scale - 1),
|
||||
(float)(width_ * scale - 1),
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ * scale - 1),
|
||||
0.0f,
|
||||
0.0f,
|
||||
};
|
||||
tr_.setPolyToPoly((MNN::CV::Point *)dstPoints,
|
||||
(MNN::CV::Point *)srcPoints, 4);
|
||||
process->setMatrix(tr_);
|
||||
int scaled_height = static_cast<int>(height_ * scale);
|
||||
int scaled_width = static_cast<int>(width_ * scale);
|
||||
cv::Mat img_out(scaled_height, scaled_width, CV_8UC3);
|
||||
std::shared_ptr<MNN::Tensor> tensor(MNN::Tensor::create<uint8_t>(
|
||||
std::vector<int>{1, scaled_height, scaled_width, 3}, img_out.data));
|
||||
process->convert(buffer_, sw, sh, 0, tensor.get());
|
||||
return img_out;
|
||||
} else {
|
||||
float srcPoints[] = {
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ - 1),
|
||||
(float)(width_ - 1),
|
||||
0.0f,
|
||||
(float)(width_ - 1),
|
||||
(float)(height_ - 1),
|
||||
};
|
||||
float dstPoints[] = {
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(float)(height_ * scale - 1),
|
||||
(float)(width_ * scale - 1),
|
||||
0.0f,
|
||||
(float)(width_ * scale - 1),
|
||||
(float)(height_ * scale - 1),
|
||||
};
|
||||
tr_.setPolyToPoly((MNN::CV::Point *)dstPoints,
|
||||
(MNN::CV::Point *)srcPoints, 4);
|
||||
process->setMatrix(tr_);
|
||||
int scaled_height = static_cast<int>(height_ * scale);
|
||||
int scaled_width = static_cast<int>(width_ * scale);
|
||||
cv::Mat img_out(scaled_height, scaled_width, CV_8UC3);
|
||||
std::shared_ptr<MNN::Tensor> tensor(MNN::Tensor::create<uint8_t>(
|
||||
std::vector<int>{1, scaled_height, scaled_width, 3}, img_out.data));
|
||||
auto err = process->convert(buffer_, sw, sh, 0, tensor.get());
|
||||
return img_out;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the affine transformation matrix.
|
||||
*
|
||||
* @return cv::Mat Affine transformation matrix.
|
||||
*/
|
||||
cv::Mat GetAffineMatrix() const {
|
||||
cv::Mat affine_matrix(3, 3, CV_32F);
|
||||
tr_.get9((float *)affine_matrix.data);
|
||||
cv::Mat affine = affine_matrix.rowRange(0, 2);
|
||||
cv::Mat affine_64;
|
||||
affine.convertTo(affine_64, CV_64F);
|
||||
assert(affine_64.rows == 2);
|
||||
assert(affine_64.cols == 3);
|
||||
assert(affine_64.type() == CV_64F);
|
||||
return affine_64;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the height of the camera stream image.
|
||||
*
|
||||
* @return int Height.
|
||||
*/
|
||||
int GetHeight() const{
|
||||
return height_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the width of the camera stream image.
|
||||
*
|
||||
* @return int Width.
|
||||
*/
|
||||
int GetWidth() const{
|
||||
return width_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current rotation mode.
|
||||
*
|
||||
* @return ROTATION_MODE Current rotation mode.
|
||||
*/
|
||||
ROTATION_MODE getRotationMode() const {
|
||||
return rotation_mode_;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const uint8_t *buffer_; ///< Pointer to the data buffer.
|
||||
int buffer_size_; ///< Size of the data buffer.
|
||||
std::vector<float> rotation_matrix; ///< Rotation matrix.
|
||||
int height_; ///< Height of the camera stream image.
|
||||
int width_; ///< Width of the camera stream image.
|
||||
float preview_scale_; ///< Scaling factor for the preview image.
|
||||
int preview_size_; ///< Size of the preview image.
|
||||
MNN::CV::Matrix tr_; ///< Affine transformation matrix.
|
||||
ROTATION_MODE rotation_mode_; ///< Current rotation mode.
|
||||
MNN::CV::ImageProcess::Config config_; ///< Configuration for image processing.
|
||||
std::shared_ptr<MNN::CV::ImageProcess> process_; ///< Image processing instance.
|
||||
|
||||
};
|
||||
|
||||
} // inspire
|
||||
|
||||
#endif // CAMERA_STREAM_H
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by tunm on 2023/5/5.
|
||||
//
|
||||
|
||||
#include "configurable.h"
|
||||
|
||||
namespace inspire {
|
||||
|
||||
|
||||
std::string Configurable::toString(int indent) const {
|
||||
if (indent != 0)
|
||||
return m_configuration.dump(indent);
|
||||
else
|
||||
return m_configuration.dump();
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::string> Configurable::getNameList() const {
|
||||
std::vector<std::string> keys;
|
||||
for (const auto& element : m_configuration.items()) {
|
||||
keys.push_back(element.key());
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
Configurable &Configurable::operator=(const Configurable &other) {
|
||||
if (this != &other) { // Check the self-assignment
|
||||
m_configuration = other.m_configuration; // Deep copy using the assignment operator of nlohmann::json
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} // namespace hyper
|
||||
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// Created by tunm on 2023/5/5.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef HYPERAI_PARAMETER_H
|
||||
#define HYPERAI_PARAMETER_H
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
#ifndef INSPIRE_API
|
||||
#define INSPIRE_API
|
||||
#endif
|
||||
|
||||
namespace inspire {
|
||||
|
||||
/**
|
||||
* @class Configurable
|
||||
* @brief Class for managing parameters as JSON data.
|
||||
*
|
||||
* This class provides methods to set, get, and load parameters as JSON data.
|
||||
*/
|
||||
class INSPIRE_API Configurable {
|
||||
public:
|
||||
Configurable() = default;;
|
||||
|
||||
Configurable(const Configurable& p) : m_configuration(p.m_configuration) {}
|
||||
|
||||
virtual ~Configurable() {}
|
||||
|
||||
Configurable& operator=(const Configurable& other);
|
||||
|
||||
/**
|
||||
* @brief Get a list of parameter names.
|
||||
* @return std::vector<std::string> A list of parameter names.
|
||||
*/
|
||||
std::vector<std::string> getNameList() const;
|
||||
|
||||
/**
|
||||
* @brief Convert parameters to a formatted JSON string.
|
||||
* @param indent The indentation level for formatting.
|
||||
* @return std::string The formatted JSON string representing the parameters.
|
||||
*/
|
||||
std::string toString(int indent = 4) const;
|
||||
|
||||
/**
|
||||
* @brief Check if a parameter exists by name.
|
||||
* @param name The name of the parameter to check.
|
||||
* @return bool True if the parameter exists, false otherwise.
|
||||
*/
|
||||
bool has(const std::string& name) const noexcept {
|
||||
return m_configuration.contains(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a parameter with a specific name and value.
|
||||
* @param name The name of the parameter.
|
||||
* @param value The value to set for the parameter.
|
||||
*/
|
||||
template <typename ValueType>
|
||||
void set(const std::string& name, const ValueType& value) {
|
||||
m_configuration[name] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a parameter with a specific name and value.
|
||||
* @param name The name of the parameter.
|
||||
* @param value The value to set for the parameter.
|
||||
*/
|
||||
template <typename ValueType>
|
||||
ValueType get(const std::string& name) const {
|
||||
if (!has(name)) {
|
||||
throw std::out_of_range("out_of_range in Parameter::get : " + name);
|
||||
}
|
||||
return m_configuration.at(name).get<ValueType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load parameters from a JSON object.
|
||||
* @param j The JSON object containing parameters.
|
||||
*/
|
||||
void load(const nlohmann::json& j) {
|
||||
for (const auto& item : j.items()) {
|
||||
const auto& key = item.key();
|
||||
const auto& value = item.value();
|
||||
|
||||
if (value.is_boolean()) {
|
||||
set<bool>(key, value.get<bool>());
|
||||
} else if (value.is_number_integer()) {
|
||||
set<int>(key, value.get<int>());
|
||||
} else if (value.is_number_float()) {
|
||||
set<float>(key, value.get<float>());
|
||||
} else if (value.is_string()) {
|
||||
set<std::string>(key, value.get<std::string>());
|
||||
} else if (value.is_array()) {
|
||||
if (!value.empty()) {
|
||||
if (value[0].is_number_integer()) {
|
||||
set<std::vector<int>>(key, value.get<std::vector<int>>());
|
||||
} else if (value[0].is_number_float()) {
|
||||
set<std::vector<float>>(key, value.get<std::vector<float>>());
|
||||
} // add more types as needed
|
||||
// ...
|
||||
}
|
||||
}
|
||||
// Add handling for other types as needed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
json m_configuration; ///< JSON object to store parameters.
|
||||
};
|
||||
|
||||
#define CONFIGURABLE_SUPPORT \
|
||||
protected: \
|
||||
inspire::Configurable m_configuration; \
|
||||
\
|
||||
public: \
|
||||
const inspire::Configurable& getConfiguration() const { \
|
||||
return m_configuration; \
|
||||
} \
|
||||
\
|
||||
void setConfiguration(const inspire::Configurable& param) { \
|
||||
m_configuration = param; \
|
||||
} \
|
||||
\
|
||||
bool hasData(const std::string& name) const noexcept { \
|
||||
return m_configuration.has(name); \
|
||||
} \
|
||||
\
|
||||
template <typename ValueType> \
|
||||
void setData(const std::string& name, const ValueType& value) { \
|
||||
m_configuration.set<ValueType>(name, value); \
|
||||
} \
|
||||
\
|
||||
template <typename ValueType> \
|
||||
ValueType getData(const std::string& name) const { \
|
||||
return m_configuration.get<ValueType>(name); \
|
||||
} \
|
||||
\
|
||||
template <typename ValueType> \
|
||||
void pushData(const inspire::Configurable& param, const std::string& name, \
|
||||
const ValueType& default_value) { \
|
||||
if (param.has(name)) { \
|
||||
setData<ValueType>(name, param.get<ValueType>(name)); \
|
||||
} else { \
|
||||
setData<ValueType>(name, default_value); \
|
||||
} \
|
||||
} \
|
||||
void loadData(const nlohmann::json& j) { \
|
||||
m_configuration.load(j); \
|
||||
} \
|
||||
std::string toStr(int indent = 4) { \
|
||||
return m_configuration.toString(indent); \
|
||||
}
|
||||
|
||||
} // namespace hyper
|
||||
#endif //HYPERAI_PARAMETER_H
|
||||
37
cpp-package/inspireface/cpp/inspireface/middleware/costman.h
Normal file
37
cpp-package/inspireface/cpp/inspireface/middleware/costman.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Created by Tunm-Air13 on 2023/9/21.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef HYPERFACEREPO_TIMER_H
|
||||
#define HYPERFACEREPO_TIMER_H
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
namespace inspire {
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
|
||||
Timer() {
|
||||
current_time = (double) cv::getTickCount();
|
||||
}
|
||||
|
||||
double GetCostTime() const {
|
||||
return ((double) cv::getTickCount() - current_time) / cv::getTickFrequency() * 1000;
|
||||
}
|
||||
|
||||
double GetCostTimeUpdate() {
|
||||
auto cost = ((double) cv::getTickCount() - current_time) / cv::getTickFrequency() * 1000;
|
||||
current_time = (double) cv::getTickCount();
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
double current_time;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //HYPERFACEREPO_TIMER_H
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace YAML {
|
||||
typedef std::size_t anchor_t;
|
||||
const anchor_t NullAnchor = 0;
|
||||
}
|
||||
|
||||
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
namespace YAML {
|
||||
YAML_CPP_API std::string EncodeBase64(const unsigned char *data,
|
||||
std::size_t size);
|
||||
YAML_CPP_API std::vector<unsigned char> DecodeBase64(const std::string &input);
|
||||
|
||||
class YAML_CPP_API Binary {
|
||||
public:
|
||||
Binary() : m_unownedData(0), m_unownedSize(0) {}
|
||||
Binary(const unsigned char *data_, std::size_t size_)
|
||||
: m_unownedData(data_), m_unownedSize(size_) {}
|
||||
|
||||
bool owned() const { return !m_unownedData; }
|
||||
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
|
||||
const unsigned char *data() const {
|
||||
return owned() ? &m_data[0] : m_unownedData;
|
||||
}
|
||||
|
||||
void swap(std::vector<unsigned char> &rhs) {
|
||||
if (m_unownedData) {
|
||||
m_data.swap(rhs);
|
||||
rhs.clear();
|
||||
rhs.resize(m_unownedSize);
|
||||
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
|
||||
m_unownedData = 0;
|
||||
m_unownedSize = 0;
|
||||
} else {
|
||||
m_data.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Binary &rhs) const {
|
||||
const std::size_t s = size();
|
||||
if (s != rhs.size())
|
||||
return false;
|
||||
const unsigned char *d1 = data();
|
||||
const unsigned char *d2 = rhs.data();
|
||||
for (std::size_t i = 0; i < s; i++) {
|
||||
if (*d1++ != *d2++)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const Binary &rhs) const { return !(*this == rhs); }
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> m_data;
|
||||
const unsigned char *m_unownedData;
|
||||
std::size_t m_unownedSize;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../anchor.h"
|
||||
|
||||
namespace YAML {
|
||||
/**
|
||||
* An object that stores and retrieves values correlating to {@link anchor_t}
|
||||
* values.
|
||||
*
|
||||
* <p>Efficient implementation that can make assumptions about how
|
||||
* {@code anchor_t} values are assigned by the {@link Parser} class.
|
||||
*/
|
||||
template <class T>
|
||||
class AnchorDict {
|
||||
public:
|
||||
void Register(anchor_t anchor, T value) {
|
||||
if (anchor > m_data.size()) {
|
||||
m_data.resize(anchor);
|
||||
}
|
||||
m_data[anchor - 1] = value;
|
||||
}
|
||||
|
||||
T Get(anchor_t anchor) const { return m_data[anchor - 1]; }
|
||||
|
||||
private:
|
||||
std::vector<T> m_data;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,149 @@
|
||||
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/mark.h"
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
class Parser;
|
||||
|
||||
// GraphBuilderInterface
|
||||
// . Abstraction of node creation
|
||||
// . pParentNode is always NULL or the return value of one of the NewXXX()
|
||||
// functions.
|
||||
class GraphBuilderInterface {
|
||||
public:
|
||||
virtual ~GraphBuilderInterface() = 0;
|
||||
|
||||
// Create and return a new node with a null value.
|
||||
virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
|
||||
|
||||
// Create and return a new node with the given tag and value.
|
||||
virtual void *NewScalar(const Mark &mark, const std::string &tag,
|
||||
void *pParentNode, const std::string &value) = 0;
|
||||
|
||||
// Create and return a new sequence node
|
||||
virtual void *NewSequence(const Mark &mark, const std::string &tag,
|
||||
void *pParentNode) = 0;
|
||||
|
||||
// Add pNode to pSequence. pNode was created with one of the NewXxx()
|
||||
// functions and pSequence with NewSequence().
|
||||
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
|
||||
|
||||
// Note that no moew entries will be added to pSequence
|
||||
virtual void SequenceComplete(void *pSequence) { (void)pSequence; }
|
||||
|
||||
// Create and return a new map node
|
||||
virtual void *NewMap(const Mark &mark, const std::string &tag,
|
||||
void *pParentNode) = 0;
|
||||
|
||||
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
|
||||
// were created with one of the NewXxx() methods and pMap with NewMap().
|
||||
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
|
||||
|
||||
// Note that no more assignments will be made in pMap
|
||||
virtual void MapComplete(void *pMap) { (void)pMap; }
|
||||
|
||||
// Return the node that should be used in place of an alias referencing
|
||||
// pNode (pNode by default)
|
||||
virtual void *AnchorReference(const Mark &mark, void *pNode) {
|
||||
(void)mark;
|
||||
return pNode;
|
||||
}
|
||||
};
|
||||
|
||||
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
|
||||
// Node, Sequence, and Map types. Sequence and Map must derive from Node
|
||||
// (unless Node is defined as void). Impl must also implement function with
|
||||
// all of the same names as the virtual functions in GraphBuilderInterface
|
||||
// -- including the ones with default implementations -- but with the
|
||||
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
|
||||
// appropriate.
|
||||
template <class Impl>
|
||||
class GraphBuilder : public GraphBuilderInterface {
|
||||
public:
|
||||
typedef typename Impl::Node Node;
|
||||
typedef typename Impl::Sequence Sequence;
|
||||
typedef typename Impl::Map Map;
|
||||
|
||||
GraphBuilder(Impl &impl) : m_impl(impl) {
|
||||
Map *pMap = NULL;
|
||||
Sequence *pSeq = NULL;
|
||||
Node *pNode = NULL;
|
||||
|
||||
// Type consistency checks
|
||||
pNode = pMap;
|
||||
pNode = pSeq;
|
||||
}
|
||||
|
||||
GraphBuilderInterface &AsBuilderInterface() { return *this; }
|
||||
|
||||
virtual void *NewNull(const Mark &mark, void *pParentNode) {
|
||||
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
|
||||
}
|
||||
|
||||
virtual void *NewScalar(const Mark &mark, const std::string &tag,
|
||||
void *pParentNode, const std::string &value) {
|
||||
return CheckType<Node>(
|
||||
m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
|
||||
}
|
||||
|
||||
virtual void *NewSequence(const Mark &mark, const std::string &tag,
|
||||
void *pParentNode) {
|
||||
return CheckType<Sequence>(
|
||||
m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
|
||||
}
|
||||
virtual void AppendToSequence(void *pSequence, void *pNode) {
|
||||
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
|
||||
}
|
||||
virtual void SequenceComplete(void *pSequence) {
|
||||
m_impl.SequenceComplete(AsSequence(pSequence));
|
||||
}
|
||||
|
||||
virtual void *NewMap(const Mark &mark, const std::string &tag,
|
||||
void *pParentNode) {
|
||||
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
|
||||
}
|
||||
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
|
||||
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
|
||||
}
|
||||
virtual void MapComplete(void *pMap) { m_impl.MapComplete(AsMap(pMap)); }
|
||||
|
||||
virtual void *AnchorReference(const Mark &mark, void *pNode) {
|
||||
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
|
||||
}
|
||||
|
||||
private:
|
||||
Impl &m_impl;
|
||||
|
||||
// Static check for pointer to T
|
||||
template <class T, class U>
|
||||
static T *CheckType(U *p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
static Node *AsNode(void *pNode) { return static_cast<Node *>(pNode); }
|
||||
static Sequence *AsSequence(void *pSeq) {
|
||||
return static_cast<Sequence *>(pSeq);
|
||||
}
|
||||
static Map *AsMap(void *pMap) { return static_cast<Map *>(pMap); }
|
||||
};
|
||||
|
||||
void *BuildGraphOfNextDocument(Parser &parser,
|
||||
GraphBuilderInterface &graphBuilder);
|
||||
|
||||
template <class Impl>
|
||||
typename Impl::Node *BuildGraphOfNextDocument(Parser &parser, Impl &impl) {
|
||||
GraphBuilder<Impl> graphBuilder(impl);
|
||||
return static_cast<typename Impl::Node *>(
|
||||
BuildGraphOfNextDocument(parser, graphBuilder));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// The following ifdef block is the standard way of creating macros which make
|
||||
// exporting from a DLL simpler. All files within this DLL are compiled with the
|
||||
// yaml_cpp_EXPORTS symbol defined on the command line. This symbol should not
|
||||
// be defined on any project that uses this DLL. This way any other project
|
||||
// whose source files include this file see YAML_CPP_API functions as being
|
||||
// imported from a DLL, whereas this DLL sees symbols defined with this macro as
|
||||
// being exported.
|
||||
#undef YAML_CPP_API
|
||||
|
||||
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
|
||||
// manually)
|
||||
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
|
||||
// or defined manually)
|
||||
// #pragma message( "Defining YAML_CPP_API for DLL export" )
|
||||
#define YAML_CPP_API __declspec(dllexport)
|
||||
#else // yaml_cpp_EXPORTS
|
||||
// #pragma message( "Defining YAML_CPP_API for DLL import" )
|
||||
#define YAML_CPP_API __declspec(dllimport)
|
||||
#endif // yaml_cpp_EXPORTS
|
||||
#else // YAML_CPP_DLL
|
||||
#define YAML_CPP_API
|
||||
#endif // YAML_CPP_DLL
|
||||
|
||||
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class Emitter;
|
||||
|
||||
class EmitFromEvents : public EventHandler {
|
||||
public:
|
||||
EmitFromEvents(Emitter& emitter);
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark);
|
||||
virtual void OnDocumentEnd();
|
||||
|
||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value);
|
||||
|
||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnSequenceEnd();
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnMapEnd();
|
||||
|
||||
private:
|
||||
void BeginNode();
|
||||
void EmitProps(const std::string& tag, anchor_t anchor);
|
||||
|
||||
private:
|
||||
Emitter& m_emitter;
|
||||
|
||||
struct State {
|
||||
enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue };
|
||||
};
|
||||
std::stack<State::value> m_stateStack;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,254 @@
|
||||
#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "yaml-cpp/binary.h"
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/emitterdef.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include "yaml-cpp/noncopyable.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
struct _Null;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class EmitterState;
|
||||
|
||||
class YAML_CPP_API Emitter : private noncopyable {
|
||||
public:
|
||||
Emitter();
|
||||
explicit Emitter(std::ostream& stream);
|
||||
~Emitter();
|
||||
|
||||
// output
|
||||
const char* c_str() const;
|
||||
std::size_t size() const;
|
||||
|
||||
// state checking
|
||||
bool good() const;
|
||||
const std::string GetLastError() const;
|
||||
|
||||
// global setters
|
||||
bool SetOutputCharset(EMITTER_MANIP value);
|
||||
bool SetStringFormat(EMITTER_MANIP value);
|
||||
bool SetBoolFormat(EMITTER_MANIP value);
|
||||
bool SetIntBase(EMITTER_MANIP value);
|
||||
bool SetSeqFormat(EMITTER_MANIP value);
|
||||
bool SetMapFormat(EMITTER_MANIP value);
|
||||
bool SetIndent(std::size_t n);
|
||||
bool SetPreCommentIndent(std::size_t n);
|
||||
bool SetPostCommentIndent(std::size_t n);
|
||||
bool SetFloatPrecision(std::size_t n);
|
||||
bool SetDoublePrecision(std::size_t n);
|
||||
|
||||
// local setters
|
||||
Emitter& SetLocalValue(EMITTER_MANIP value);
|
||||
Emitter& SetLocalIndent(const _Indent& indent);
|
||||
Emitter& SetLocalPrecision(const _Precision& precision);
|
||||
|
||||
// overloads of write
|
||||
Emitter& Write(const std::string& str);
|
||||
Emitter& Write(bool b);
|
||||
Emitter& Write(char ch);
|
||||
Emitter& Write(const _Alias& alias);
|
||||
Emitter& Write(const _Anchor& anchor);
|
||||
Emitter& Write(const _Tag& tag);
|
||||
Emitter& Write(const _Comment& comment);
|
||||
Emitter& Write(const _Null& n);
|
||||
Emitter& Write(const Binary& binary);
|
||||
|
||||
template <typename T>
|
||||
Emitter& WriteIntegralType(T value);
|
||||
|
||||
template <typename T>
|
||||
Emitter& WriteStreamable(T value);
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void SetStreamablePrecision(std::stringstream&) {}
|
||||
std::size_t GetFloatPrecision() const;
|
||||
std::size_t GetDoublePrecision() const;
|
||||
|
||||
void PrepareIntegralStream(std::stringstream& stream) const;
|
||||
void StartedScalar();
|
||||
|
||||
private:
|
||||
void EmitBeginDoc();
|
||||
void EmitEndDoc();
|
||||
void EmitBeginSeq();
|
||||
void EmitEndSeq();
|
||||
void EmitBeginMap();
|
||||
void EmitEndMap();
|
||||
void EmitNewline();
|
||||
void EmitKindTag();
|
||||
void EmitTag(bool verbatim, const _Tag& tag);
|
||||
|
||||
void PrepareNode(EmitterNodeType::value child);
|
||||
void PrepareTopNode(EmitterNodeType::value child);
|
||||
void FlowSeqPrepareNode(EmitterNodeType::value child);
|
||||
void BlockSeqPrepareNode(EmitterNodeType::value child);
|
||||
|
||||
void FlowMapPrepareNode(EmitterNodeType::value child);
|
||||
|
||||
void FlowMapPrepareLongKey(EmitterNodeType::value child);
|
||||
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
|
||||
void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
|
||||
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
|
||||
|
||||
void BlockMapPrepareNode(EmitterNodeType::value child);
|
||||
|
||||
void BlockMapPrepareLongKey(EmitterNodeType::value child);
|
||||
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
|
||||
void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
|
||||
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
|
||||
|
||||
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
|
||||
|
||||
const char* ComputeFullBoolName(bool b) const;
|
||||
bool CanEmitNewline() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<EmitterState> m_pState;
|
||||
ostream_wrapper m_stream;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline Emitter& Emitter::WriteIntegralType(T value) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
std::stringstream stream;
|
||||
PrepareIntegralStream(stream);
|
||||
stream << value;
|
||||
m_stream << stream.str();
|
||||
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Emitter& Emitter::WriteStreamable(T value) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
std::stringstream stream;
|
||||
SetStreamablePrecision<T>(stream);
|
||||
stream << value;
|
||||
m_stream << stream.str();
|
||||
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
|
||||
stream.precision(static_cast<std::streamsize>(GetFloatPrecision()));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
||||
stream.precision(static_cast<std::streamsize>(GetDoublePrecision()));
|
||||
}
|
||||
|
||||
// overloads of insertion
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, char v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, unsigned char v) {
|
||||
return emitter.Write(static_cast<char>(v));
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, const _Alias& v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, const _Anchor& v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, const _Tag& v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, const _Comment& v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, const _Null& v) {
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
|
||||
return emitter.Write(b);
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
||||
return emitter.Write(std::string(v));
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, int v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, unsigned int v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, short v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, unsigned short v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, long v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, unsigned long v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, long long v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, unsigned long long v) {
|
||||
return emitter.WriteIntegralType(v);
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, float v) {
|
||||
return emitter.WriteStreamable(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, double v) {
|
||||
return emitter.WriteStreamable(v);
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, EMITTER_MANIP value) {
|
||||
return emitter.SetLocalValue(value);
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
|
||||
return emitter.SetLocalIndent(indent);
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
|
||||
return emitter.SetLocalPrecision(precision);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
struct EmitterNodeType {
|
||||
enum value { NoType, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap };
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,137 @@
|
||||
#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
enum EMITTER_MANIP {
|
||||
// general manipulators
|
||||
Auto,
|
||||
TagByKind,
|
||||
Newline,
|
||||
|
||||
// output character set
|
||||
EmitNonAscii,
|
||||
EscapeNonAscii,
|
||||
|
||||
// string manipulators
|
||||
// Auto, // duplicate
|
||||
SingleQuoted,
|
||||
DoubleQuoted,
|
||||
Literal,
|
||||
|
||||
// bool manipulators
|
||||
YesNoBool, // yes, no
|
||||
TrueFalseBool, // true, false
|
||||
OnOffBool, // on, off
|
||||
UpperCase, // TRUE, N
|
||||
LowerCase, // f, yes
|
||||
CamelCase, // No, Off
|
||||
LongBool, // yes, On
|
||||
ShortBool, // y, t
|
||||
|
||||
// int manipulators
|
||||
Dec,
|
||||
Hex,
|
||||
Oct,
|
||||
|
||||
// document manipulators
|
||||
BeginDoc,
|
||||
EndDoc,
|
||||
|
||||
// sequence manipulators
|
||||
BeginSeq,
|
||||
EndSeq,
|
||||
Flow,
|
||||
Block,
|
||||
|
||||
// map manipulators
|
||||
BeginMap,
|
||||
EndMap,
|
||||
Key,
|
||||
Value,
|
||||
// Flow, // duplicate
|
||||
// Block, // duplicate
|
||||
// Auto, // duplicate
|
||||
LongKey
|
||||
};
|
||||
|
||||
struct _Indent {
|
||||
_Indent(int value_) : value(value_) {}
|
||||
int value;
|
||||
};
|
||||
|
||||
inline _Indent Indent(int value) { return _Indent(value); }
|
||||
|
||||
struct _Alias {
|
||||
_Alias(const std::string& content_) : content(content_) {}
|
||||
std::string content;
|
||||
};
|
||||
|
||||
inline _Alias Alias(const std::string content) { return _Alias(content); }
|
||||
|
||||
struct _Anchor {
|
||||
_Anchor(const std::string& content_) : content(content_) {}
|
||||
std::string content;
|
||||
};
|
||||
|
||||
inline _Anchor Anchor(const std::string content) { return _Anchor(content); }
|
||||
|
||||
struct _Tag {
|
||||
struct Type {
|
||||
enum value { Verbatim, PrimaryHandle, NamedHandle };
|
||||
};
|
||||
|
||||
explicit _Tag(const std::string& prefix_, const std::string& content_,
|
||||
Type::value type_)
|
||||
: prefix(prefix_), content(content_), type(type_) {}
|
||||
std::string prefix;
|
||||
std::string content;
|
||||
Type::value type;
|
||||
};
|
||||
|
||||
inline _Tag VerbatimTag(const std::string content) {
|
||||
return _Tag("", content, _Tag::Type::Verbatim);
|
||||
}
|
||||
|
||||
inline _Tag LocalTag(const std::string content) {
|
||||
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
||||
}
|
||||
|
||||
inline _Tag LocalTag(const std::string& prefix, const std::string content) {
|
||||
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
||||
}
|
||||
|
||||
inline _Tag SecondaryTag(const std::string content) {
|
||||
return _Tag("", content, _Tag::Type::NamedHandle);
|
||||
}
|
||||
|
||||
struct _Comment {
|
||||
_Comment(const std::string& content_) : content(content_) {}
|
||||
std::string content;
|
||||
};
|
||||
|
||||
inline _Comment Comment(const std::string content) { return _Comment(content); }
|
||||
|
||||
struct _Precision {
|
||||
_Precision(int floatPrecision_, int doublePrecision_)
|
||||
: floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
|
||||
|
||||
int floatPrecision;
|
||||
int doublePrecision;
|
||||
};
|
||||
|
||||
inline _Precision FloatPrecision(int n) { return _Precision(n, -1); }
|
||||
|
||||
inline _Precision DoublePrecision(int n) { return _Precision(-1, n); }
|
||||
|
||||
inline _Precision Precision(int n) { return _Precision(n, n); }
|
||||
}
|
||||
|
||||
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
struct EmitterStyle {
|
||||
enum value { Default, Block, Flow };
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
|
||||
class EventHandler {
|
||||
public:
|
||||
virtual ~EventHandler() {}
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark) = 0;
|
||||
virtual void OnDocumentEnd() = 0;
|
||||
|
||||
virtual void OnNull(const Mark& mark, anchor_t anchor) = 0;
|
||||
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
|
||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value) = 0;
|
||||
|
||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) = 0;
|
||||
virtual void OnSequenceEnd() = 0;
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) = 0;
|
||||
virtual void OnMapEnd() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,267 @@
|
||||
#ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/mark.h"
|
||||
#include "yaml-cpp/traits.h"
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
// This is here for compatibility with older versions of Visual Studio
|
||||
// which don't support noexcept
|
||||
#ifdef _MSC_VER
|
||||
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
||||
#else
|
||||
#define YAML_CPP_NOEXCEPT noexcept
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
// error messages
|
||||
namespace ErrorMsg {
|
||||
const char* const YAML_DIRECTIVE_ARGS =
|
||||
"YAML directives must have exactly one argument";
|
||||
const char* const YAML_VERSION = "bad YAML version: ";
|
||||
const char* const YAML_MAJOR_VERSION = "YAML major version too large";
|
||||
const char* const REPEATED_YAML_DIRECTIVE = "repeated YAML directive";
|
||||
const char* const TAG_DIRECTIVE_ARGS =
|
||||
"TAG directives must have exactly two arguments";
|
||||
const char* const REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
|
||||
const char* const CHAR_IN_TAG_HANDLE =
|
||||
"illegal character found while scanning tag handle";
|
||||
const char* const TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
|
||||
const char* const END_OF_VERBATIM_TAG = "end of verbatim tag not found";
|
||||
const char* const END_OF_MAP = "end of map not found";
|
||||
const char* const END_OF_MAP_FLOW = "end of map flow not found";
|
||||
const char* const END_OF_SEQ = "end of sequence not found";
|
||||
const char* const END_OF_SEQ_FLOW = "end of sequence flow not found";
|
||||
const char* const MULTIPLE_TAGS =
|
||||
"cannot assign multiple tags to the same node";
|
||||
const char* const MULTIPLE_ANCHORS =
|
||||
"cannot assign multiple anchors to the same node";
|
||||
const char* const MULTIPLE_ALIASES =
|
||||
"cannot assign multiple aliases to the same node";
|
||||
const char* const ALIAS_CONTENT =
|
||||
"aliases can't have any content, *including* tags";
|
||||
const char* const INVALID_HEX = "bad character found while scanning hex number";
|
||||
const char* const INVALID_UNICODE = "invalid unicode: ";
|
||||
const char* const INVALID_ESCAPE = "unknown escape character: ";
|
||||
const char* const UNKNOWN_TOKEN = "unknown token";
|
||||
const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
|
||||
const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
|
||||
const char* const CHAR_IN_SCALAR = "illegal character in scalar";
|
||||
const char* const TAB_IN_INDENTATION =
|
||||
"illegal tab when looking for indentation";
|
||||
const char* const FLOW_END = "illegal flow end";
|
||||
const char* const BLOCK_ENTRY = "illegal block entry";
|
||||
const char* const MAP_KEY = "illegal map key";
|
||||
const char* const MAP_VALUE = "illegal map value";
|
||||
const char* const ALIAS_NOT_FOUND = "alias not found after *";
|
||||
const char* const ANCHOR_NOT_FOUND = "anchor not found after &";
|
||||
const char* const CHAR_IN_ALIAS =
|
||||
"illegal character found while scanning alias";
|
||||
const char* const CHAR_IN_ANCHOR =
|
||||
"illegal character found while scanning anchor";
|
||||
const char* const ZERO_INDENT_IN_BLOCK =
|
||||
"cannot set zero indentation for a block scalar";
|
||||
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
|
||||
const char* const AMBIGUOUS_ANCHOR =
|
||||
"cannot assign the same alias to multiple nodes";
|
||||
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
|
||||
|
||||
const char* const INVALID_NODE =
|
||||
"invalid node; this may result from using a map iterator as a sequence "
|
||||
"iterator, or vice-versa";
|
||||
const char* const INVALID_SCALAR = "invalid scalar";
|
||||
const char* const KEY_NOT_FOUND = "key not found";
|
||||
const char* const BAD_CONVERSION = "bad conversion";
|
||||
const char* const BAD_DEREFERENCE = "bad dereference";
|
||||
const char* const BAD_SUBSCRIPT = "operator[] call on a scalar";
|
||||
const char* const BAD_PUSHBACK = "appending to a non-sequence";
|
||||
const char* const BAD_INSERT = "inserting in a non-convertible-to-map";
|
||||
|
||||
const char* const UNMATCHED_GROUP_TAG = "unmatched group tag";
|
||||
const char* const UNEXPECTED_END_SEQ = "unexpected end sequence token";
|
||||
const char* const UNEXPECTED_END_MAP = "unexpected end map token";
|
||||
const char* const SINGLE_QUOTED_CHAR =
|
||||
"invalid character in single-quoted string";
|
||||
const char* const INVALID_ANCHOR = "invalid anchor";
|
||||
const char* const INVALID_ALIAS = "invalid alias";
|
||||
const char* const INVALID_TAG = "invalid tag";
|
||||
const char* const BAD_FILE = "bad file";
|
||||
|
||||
template <typename T>
|
||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
||||
const T&, typename disable_if<is_numeric<T>>::type* = 0) {
|
||||
return KEY_NOT_FOUND;
|
||||
}
|
||||
|
||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
|
||||
std::stringstream stream;
|
||||
stream << KEY_NOT_FOUND << ": " << key;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
||||
const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
|
||||
std::stringstream stream;
|
||||
stream << KEY_NOT_FOUND << ": " << key;
|
||||
return stream.str();
|
||||
}
|
||||
}
|
||||
|
||||
class YAML_CPP_API Exception : public std::runtime_error {
|
||||
public:
|
||||
Exception(const Mark& mark_, const std::string& msg_)
|
||||
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
||||
virtual ~Exception() YAML_CPP_NOEXCEPT;
|
||||
|
||||
Exception(const Exception&) = default;
|
||||
|
||||
Mark mark;
|
||||
std::string msg;
|
||||
|
||||
private:
|
||||
static const std::string build_what(const Mark& mark,
|
||||
const std::string& msg) {
|
||||
if (mark.is_null()) {
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
std::stringstream output;
|
||||
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
|
||||
<< mark.column + 1 << ": " << msg;
|
||||
return output.str();
|
||||
}
|
||||
};
|
||||
|
||||
class YAML_CPP_API ParserException : public Exception {
|
||||
public:
|
||||
ParserException(const Mark& mark_, const std::string& msg_)
|
||||
: Exception(mark_, msg_) {}
|
||||
ParserException(const ParserException&) = default;
|
||||
virtual ~ParserException() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API RepresentationException : public Exception {
|
||||
public:
|
||||
RepresentationException(const Mark& mark_, const std::string& msg_)
|
||||
: Exception(mark_, msg_) {}
|
||||
RepresentationException(const RepresentationException&) = default;
|
||||
virtual ~RepresentationException() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
// representation exceptions
|
||||
class YAML_CPP_API InvalidScalar : public RepresentationException {
|
||||
public:
|
||||
InvalidScalar(const Mark& mark_)
|
||||
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
||||
InvalidScalar(const InvalidScalar&) = default;
|
||||
virtual ~InvalidScalar() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API KeyNotFound : public RepresentationException {
|
||||
public:
|
||||
template <typename T>
|
||||
KeyNotFound(const Mark& mark_, const T& key_)
|
||||
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
||||
}
|
||||
KeyNotFound(const KeyNotFound&) = default;
|
||||
virtual ~KeyNotFound() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
|
||||
public:
|
||||
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
||||
: KeyNotFound(mark_, key_), key(key_) {}
|
||||
virtual ~TypedKeyNotFound() YAML_CPP_NOEXCEPT {}
|
||||
|
||||
T key;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
|
||||
const T& key) {
|
||||
return TypedKeyNotFound<T>(mark, key);
|
||||
}
|
||||
|
||||
class YAML_CPP_API InvalidNode : public RepresentationException {
|
||||
public:
|
||||
InvalidNode()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {}
|
||||
InvalidNode(const InvalidNode&) = default;
|
||||
virtual ~InvalidNode() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadConversion : public RepresentationException {
|
||||
public:
|
||||
explicit BadConversion(const Mark& mark_)
|
||||
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
||||
BadConversion(const BadConversion&) = default;
|
||||
virtual ~BadConversion() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypedBadConversion : public BadConversion {
|
||||
public:
|
||||
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadDereference : public RepresentationException {
|
||||
public:
|
||||
BadDereference()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
||||
BadDereference(const BadDereference&) = default;
|
||||
virtual ~BadDereference() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadSubscript : public RepresentationException {
|
||||
public:
|
||||
BadSubscript()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
|
||||
BadSubscript(const BadSubscript&) = default;
|
||||
virtual ~BadSubscript() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadPushback : public RepresentationException {
|
||||
public:
|
||||
BadPushback()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
||||
BadPushback(const BadPushback&) = default;
|
||||
virtual ~BadPushback() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadInsert : public RepresentationException {
|
||||
public:
|
||||
BadInsert()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
||||
BadInsert(const BadInsert&) = default;
|
||||
virtual ~BadInsert() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API EmitterException : public Exception {
|
||||
public:
|
||||
EmitterException(const std::string& msg_)
|
||||
: Exception(Mark::null_mark(), msg_) {}
|
||||
EmitterException(const EmitterException&) = default;
|
||||
virtual ~EmitterException() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadFile : public Exception {
|
||||
public:
|
||||
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
||||
BadFile(const BadFile&) = default;
|
||||
virtual ~BadFile() YAML_CPP_NOEXCEPT;
|
||||
};
|
||||
}
|
||||
|
||||
#undef YAML_CPP_NOEXCEPT
|
||||
|
||||
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
namespace YAML {
|
||||
struct YAML_CPP_API Mark {
|
||||
Mark() : pos(0), line(0), column(0) {}
|
||||
|
||||
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
||||
|
||||
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
|
||||
|
||||
int pos;
|
||||
int line, column;
|
||||
|
||||
private:
|
||||
Mark(int pos_, int line_, int column_)
|
||||
: pos(pos_), line(line_), column(column_) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,331 @@
|
||||
#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/binary.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
struct _Null;
|
||||
template <typename T>
|
||||
struct convert;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
namespace conversion {
|
||||
inline bool IsInfinity(const std::string& input) {
|
||||
return input == ".inf" || input == ".Inf" || input == ".INF" ||
|
||||
input == "+.inf" || input == "+.Inf" || input == "+.INF";
|
||||
}
|
||||
|
||||
inline bool IsNegativeInfinity(const std::string& input) {
|
||||
return input == "-.inf" || input == "-.Inf" || input == "-.INF";
|
||||
}
|
||||
|
||||
inline bool IsNaN(const std::string& input) {
|
||||
return input == ".nan" || input == ".NaN" || input == ".NAN";
|
||||
}
|
||||
}
|
||||
|
||||
// Node
|
||||
template <>
|
||||
struct convert<Node> {
|
||||
static Node encode(const Node& rhs) { return rhs; }
|
||||
|
||||
static bool decode(const Node& node, Node& rhs) {
|
||||
rhs.reset(node);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::string
|
||||
template <>
|
||||
struct convert<std::string> {
|
||||
static Node encode(const std::string& rhs) { return Node(rhs); }
|
||||
|
||||
static bool decode(const Node& node, std::string& rhs) {
|
||||
if (!node.IsScalar())
|
||||
return false;
|
||||
rhs = node.Scalar();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// C-strings can only be encoded
|
||||
template <>
|
||||
struct convert<const char*> {
|
||||
static Node encode(const char*& rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct convert<const char[N]> {
|
||||
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convert<_Null> {
|
||||
static Node encode(const _Null& /* rhs */) { return Node(); }
|
||||
|
||||
static bool decode(const Node& node, _Null& /* rhs */) {
|
||||
return node.IsNull();
|
||||
}
|
||||
};
|
||||
|
||||
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
|
||||
template <> \
|
||||
struct convert<type> { \
|
||||
static Node encode(const type& rhs) { \
|
||||
std::stringstream stream; \
|
||||
stream.precision(std::numeric_limits<type>::digits10 + 1); \
|
||||
stream << rhs; \
|
||||
return Node(stream.str()); \
|
||||
} \
|
||||
\
|
||||
static bool decode(const Node& node, type& rhs) { \
|
||||
if (node.Type() != NodeType::Scalar) \
|
||||
return false; \
|
||||
const std::string& input = node.Scalar(); \
|
||||
std::stringstream stream(input); \
|
||||
stream.unsetf(std::ios::dec); \
|
||||
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \
|
||||
return true; \
|
||||
if (std::numeric_limits<type>::has_infinity) { \
|
||||
if (conversion::IsInfinity(input)) { \
|
||||
rhs = std::numeric_limits<type>::infinity(); \
|
||||
return true; \
|
||||
} else if (conversion::IsNegativeInfinity(input)) { \
|
||||
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (std::numeric_limits<type>::has_quiet_NaN && \
|
||||
conversion::IsNaN(input)) { \
|
||||
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
||||
YAML_DEFINE_CONVERT_STREAMABLE(type, -)
|
||||
|
||||
#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \
|
||||
YAML_DEFINE_CONVERT_STREAMABLE(type, +)
|
||||
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long);
|
||||
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char);
|
||||
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double);
|
||||
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double);
|
||||
|
||||
#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
|
||||
#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
|
||||
#undef YAML_DEFINE_CONVERT_STREAMABLE
|
||||
|
||||
// bool
|
||||
template <>
|
||||
struct convert<bool> {
|
||||
static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); }
|
||||
|
||||
YAML_CPP_API static bool decode(const Node& node, bool& rhs);
|
||||
};
|
||||
|
||||
// std::map
|
||||
template <typename K, typename V>
|
||||
struct convert<std::map<K, V>> {
|
||||
static Node encode(const std::map<K, V>& rhs) {
|
||||
Node node(NodeType::Map);
|
||||
for (typename std::map<K, V>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it)
|
||||
node.force_insert(it->first, it->second);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::map<K, V>& rhs) {
|
||||
if (!node.IsMap())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[it->first.template as<K>()] = it->second.template as<V>();
|
||||
#else
|
||||
rhs[it->first.as<K>()] = it->second.as<V>();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::vector
|
||||
template <typename T>
|
||||
struct convert<std::vector<T>> {
|
||||
static Node encode(const std::vector<T>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (typename std::vector<T>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it)
|
||||
node.push_back(*it);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::vector<T>& rhs) {
|
||||
if (!node.IsSequence())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs.push_back(it->template as<T>());
|
||||
#else
|
||||
rhs.push_back(it->as<T>());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::list
|
||||
template <typename T>
|
||||
struct convert<std::list<T>> {
|
||||
static Node encode(const std::list<T>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (typename std::list<T>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it)
|
||||
node.push_back(*it);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::list<T>& rhs) {
|
||||
if (!node.IsSequence())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs.push_back(it->template as<T>());
|
||||
#else
|
||||
rhs.push_back(it->as<T>());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::array
|
||||
template <typename T, std::size_t N>
|
||||
struct convert<std::array<T, N>> {
|
||||
static Node encode(const std::array<T, N>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (const auto& element : rhs) {
|
||||
node.push_back(element);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::array<T, N>& rhs) {
|
||||
if (!isNodeValid(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto i = 0u; i < node.size(); ++i) {
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[i] = node[i].template as<T>();
|
||||
#else
|
||||
rhs[i] = node[i].as<T>();
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool isNodeValid(const Node& node) {
|
||||
return node.IsSequence() && node.size() == N;
|
||||
}
|
||||
};
|
||||
|
||||
// std::pair
|
||||
template <typename T, typename U>
|
||||
struct convert<std::pair<T, U>> {
|
||||
static Node encode(const std::pair<T, U>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
node.push_back(rhs.first);
|
||||
node.push_back(rhs.second);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::pair<T, U>& rhs) {
|
||||
if (!node.IsSequence())
|
||||
return false;
|
||||
if (node.size() != 2)
|
||||
return false;
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs.first = node[0].template as<T>();
|
||||
#else
|
||||
rhs.first = node[0].as<T>();
|
||||
#endif
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs.second = node[1].template as<U>();
|
||||
#else
|
||||
rhs.second = node[1].as<U>();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// binary
|
||||
template <>
|
||||
struct convert<Binary> {
|
||||
static Node encode(const Binary& rhs) {
|
||||
return Node(EncodeBase64(rhs.data(), rhs.size()));
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, Binary& rhs) {
|
||||
if (!node.IsScalar())
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> data = DecodeBase64(node.Scalar());
|
||||
if (data.empty() && !node.Scalar().empty())
|
||||
return false;
|
||||
|
||||
rhs.swap(data);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
struct unspecified_bool {
|
||||
struct NOT_ALLOWED;
|
||||
static void true_value(NOT_ALLOWED*) {}
|
||||
};
|
||||
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
|
||||
}
|
||||
}
|
||||
|
||||
#define YAML_CPP_OPERATOR_BOOL() \
|
||||
operator YAML::detail::unspecified_bool_type() const { \
|
||||
return this->operator!() ? 0 \
|
||||
: &YAML::detail::unspecified_bool::true_value; \
|
||||
}
|
||||
|
||||
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,185 @@
|
||||
#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/node/detail/node.h"
|
||||
#include "yaml-cpp/node/detail/node_data.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
template <typename Key, typename Enable = void>
|
||||
struct get_idx {
|
||||
static node* get(const std::vector<node*>& /* sequence */,
|
||||
const Key& /* key */, shared_memory_holder /* pMemory */) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key>
|
||||
struct get_idx<Key,
|
||||
typename std::enable_if<std::is_unsigned<Key>::value &&
|
||||
!std::is_same<Key, bool>::value>::type> {
|
||||
static node* get(const std::vector<node*>& sequence, const Key& key,
|
||||
shared_memory_holder /* pMemory */) {
|
||||
return key < sequence.size() ? sequence[key] : 0;
|
||||
}
|
||||
|
||||
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||
shared_memory_holder pMemory) {
|
||||
if (key > sequence.size() || (key > 0 && !sequence[key-1]->is_defined()))
|
||||
return 0;
|
||||
if (key == sequence.size())
|
||||
sequence.push_back(&pMemory->create_node());
|
||||
return sequence[key];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key>
|
||||
struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
|
||||
static node* get(const std::vector<node*>& sequence, const Key& key,
|
||||
shared_memory_holder pMemory) {
|
||||
return key >= 0 ? get_idx<std::size_t>::get(
|
||||
sequence, static_cast<std::size_t>(key), pMemory)
|
||||
: 0;
|
||||
}
|
||||
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||
shared_memory_holder pMemory) {
|
||||
return key >= 0 ? get_idx<std::size_t>::get(
|
||||
sequence, static_cast<std::size_t>(key), pMemory)
|
||||
: 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
|
||||
T lhs;
|
||||
if (convert<T>::decode(Node(*this, pMemory), lhs)) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
|
||||
return equals<std::string>(rhs, pMemory);
|
||||
}
|
||||
|
||||
// indexing
|
||||
template <typename Key>
|
||||
inline node* node_data::get(const Key& key,
|
||||
shared_memory_holder pMemory) const {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
return NULL;
|
||||
case NodeType::Sequence:
|
||||
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
|
||||
return pNode;
|
||||
return NULL;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript();
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->equals(key, pMemory)) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
case NodeType::Sequence:
|
||||
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory)) {
|
||||
m_type = NodeType::Sequence;
|
||||
return *pNode;
|
||||
}
|
||||
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript();
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->equals(key, pMemory)) {
|
||||
return *it->second;
|
||||
}
|
||||
}
|
||||
|
||||
node& k = convert_to_node(key, pMemory);
|
||||
node& v = pMemory->create_node();
|
||||
insert_map_pair(k, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
||||
if (m_type != NodeType::Map)
|
||||
return false;
|
||||
|
||||
for (kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||
it != m_undefinedPairs.end();) {
|
||||
kv_pairs::iterator jt = std::next(it);
|
||||
if (it->first->equals(key, pMemory))
|
||||
m_undefinedPairs.erase(it);
|
||||
it = jt;
|
||||
}
|
||||
|
||||
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->equals(key, pMemory)) {
|
||||
m_map.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
inline void node_data::force_insert(const Key& key, const Value& value,
|
||||
shared_memory_holder pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
case NodeType::Sequence:
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadInsert();
|
||||
}
|
||||
|
||||
node& k = convert_to_node(key, pMemory);
|
||||
node& v = convert_to_node(value, pMemory);
|
||||
insert_map_pair(k, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline node& node_data::convert_to_node(const T& rhs,
|
||||
shared_memory_holder pMemory) {
|
||||
Node value = convert<T>::encode(rhs);
|
||||
value.EnsureNodeExists();
|
||||
pMemory->merge(*value.m_pMemory);
|
||||
return *value.m_pNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,92 @@
|
||||
#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
struct iterator_value;
|
||||
|
||||
template <typename V>
|
||||
class iterator_base : public std::iterator<std::forward_iterator_tag, V,
|
||||
std::ptrdiff_t, V*, V> {
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend class iterator_base;
|
||||
struct enabler {};
|
||||
typedef node_iterator base_type;
|
||||
|
||||
struct proxy {
|
||||
explicit proxy(const V& x) : m_ref(x) {}
|
||||
V* operator->() { return std::addressof(m_ref); }
|
||||
operator V*() { return std::addressof(m_ref); }
|
||||
|
||||
V m_ref;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename iterator_base::value_type value_type;
|
||||
|
||||
public:
|
||||
iterator_base() : m_iterator(), m_pMemory() {}
|
||||
explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
|
||||
: m_iterator(rhs), m_pMemory(pMemory) {}
|
||||
|
||||
template <class W>
|
||||
iterator_base(const iterator_base<W>& rhs,
|
||||
typename std::enable_if<std::is_convertible<W*, V*>::value,
|
||||
enabler>::type = enabler())
|
||||
: m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {}
|
||||
|
||||
iterator_base<V>& operator++() {
|
||||
++m_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base<V> operator++(int) {
|
||||
iterator_base<V> iterator_pre(*this);
|
||||
++(*this);
|
||||
return iterator_pre;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator==(const iterator_base<W>& rhs) const {
|
||||
return m_iterator == rhs.m_iterator;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator!=(const iterator_base<W>& rhs) const {
|
||||
return m_iterator != rhs.m_iterator;
|
||||
}
|
||||
|
||||
value_type operator*() const {
|
||||
const typename base_type::value_type& v = *m_iterator;
|
||||
if (v.pNode)
|
||||
return value_type(Node(*v, m_pMemory));
|
||||
if (v.first && v.second)
|
||||
return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory));
|
||||
return value_type();
|
||||
}
|
||||
|
||||
proxy operator->() const { return proxy(**this); }
|
||||
|
||||
private:
|
||||
base_type m_iterator;
|
||||
shared_memory_holder m_pMemory;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
|
||||
namespace detail {
|
||||
struct iterator_value;
|
||||
template <typename V>
|
||||
class iterator_base;
|
||||
}
|
||||
|
||||
typedef detail::iterator_base<detail::iterator_value> iterator;
|
||||
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node;
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class YAML_CPP_API memory {
|
||||
public:
|
||||
node& create_node();
|
||||
void merge(const memory& rhs);
|
||||
|
||||
private:
|
||||
typedef std::set<shared_node> Nodes;
|
||||
Nodes m_nodes;
|
||||
};
|
||||
|
||||
class YAML_CPP_API memory_holder {
|
||||
public:
|
||||
memory_holder() : m_pMemory(new memory) {}
|
||||
|
||||
node& create_node() { return m_pMemory->create_node(); }
|
||||
void merge(memory_holder& rhs);
|
||||
|
||||
private:
|
||||
shared_memory m_pMemory;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,169 @@
|
||||
#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include "yaml-cpp/node/detail/node_ref.h"
|
||||
#include <set>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node {
|
||||
public:
|
||||
node() : m_pRef(new node_ref) {}
|
||||
node(const node&) = delete;
|
||||
node& operator=(const node&) = delete;
|
||||
|
||||
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
|
||||
const node_ref* ref() const { return m_pRef.get(); }
|
||||
|
||||
bool is_defined() const { return m_pRef->is_defined(); }
|
||||
const Mark& mark() const { return m_pRef->mark(); }
|
||||
NodeType::value type() const { return m_pRef->type(); }
|
||||
|
||||
const std::string& scalar() const { return m_pRef->scalar(); }
|
||||
const std::string& tag() const { return m_pRef->tag(); }
|
||||
EmitterStyle::value style() const { return m_pRef->style(); }
|
||||
|
||||
template <typename T>
|
||||
bool equals(const T& rhs, shared_memory_holder pMemory);
|
||||
bool equals(const char* rhs, shared_memory_holder pMemory);
|
||||
|
||||
void mark_defined() {
|
||||
if (is_defined())
|
||||
return;
|
||||
|
||||
m_pRef->mark_defined();
|
||||
for (nodes::iterator it = m_dependencies.begin();
|
||||
it != m_dependencies.end(); ++it)
|
||||
(*it)->mark_defined();
|
||||
m_dependencies.clear();
|
||||
}
|
||||
|
||||
void add_dependency(node& rhs) {
|
||||
if (is_defined())
|
||||
rhs.mark_defined();
|
||||
else
|
||||
m_dependencies.insert(&rhs);
|
||||
}
|
||||
|
||||
void set_ref(const node& rhs) {
|
||||
if (rhs.is_defined())
|
||||
mark_defined();
|
||||
m_pRef = rhs.m_pRef;
|
||||
}
|
||||
void set_data(const node& rhs) {
|
||||
if (rhs.is_defined())
|
||||
mark_defined();
|
||||
m_pRef->set_data(*rhs.m_pRef);
|
||||
}
|
||||
|
||||
void set_mark(const Mark& mark) { m_pRef->set_mark(mark); }
|
||||
|
||||
void set_type(NodeType::value type) {
|
||||
if (type != NodeType::Undefined)
|
||||
mark_defined();
|
||||
m_pRef->set_type(type);
|
||||
}
|
||||
void set_null() {
|
||||
mark_defined();
|
||||
m_pRef->set_null();
|
||||
}
|
||||
void set_scalar(const std::string& scalar) {
|
||||
mark_defined();
|
||||
m_pRef->set_scalar(scalar);
|
||||
}
|
||||
void set_tag(const std::string& tag) {
|
||||
mark_defined();
|
||||
m_pRef->set_tag(tag);
|
||||
}
|
||||
|
||||
// style
|
||||
void set_style(EmitterStyle::value style) {
|
||||
mark_defined();
|
||||
m_pRef->set_style(style);
|
||||
}
|
||||
|
||||
// size/iterator
|
||||
std::size_t size() const { return m_pRef->size(); }
|
||||
|
||||
const_node_iterator begin() const {
|
||||
return static_cast<const node_ref&>(*m_pRef).begin();
|
||||
}
|
||||
node_iterator begin() { return m_pRef->begin(); }
|
||||
|
||||
const_node_iterator end() const {
|
||||
return static_cast<const node_ref&>(*m_pRef).end();
|
||||
}
|
||||
node_iterator end() { return m_pRef->end(); }
|
||||
|
||||
// sequence
|
||||
void push_back(node& input, shared_memory_holder pMemory) {
|
||||
m_pRef->push_back(input, pMemory);
|
||||
input.add_dependency(*this);
|
||||
}
|
||||
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||
m_pRef->insert(key, value, pMemory);
|
||||
key.add_dependency(*this);
|
||||
value.add_dependency(*this);
|
||||
}
|
||||
|
||||
// indexing
|
||||
template <typename Key>
|
||||
node* get(const Key& key, shared_memory_holder pMemory) const {
|
||||
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||
// it, and returns a pointer so that it can be NULL (if there is no such
|
||||
// key).
|
||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||
}
|
||||
template <typename Key>
|
||||
node& get(const Key& key, shared_memory_holder pMemory) {
|
||||
node& value = m_pRef->get(key, pMemory);
|
||||
value.add_dependency(*this);
|
||||
return value;
|
||||
}
|
||||
template <typename Key>
|
||||
bool remove(const Key& key, shared_memory_holder pMemory) {
|
||||
return m_pRef->remove(key, pMemory);
|
||||
}
|
||||
|
||||
node* get(node& key, shared_memory_holder pMemory) const {
|
||||
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||
// it, and returns a pointer so that it can be NULL (if there is no such
|
||||
// key).
|
||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||
}
|
||||
node& get(node& key, shared_memory_holder pMemory) {
|
||||
node& value = m_pRef->get(key, pMemory);
|
||||
key.add_dependency(*this);
|
||||
value.add_dependency(*this);
|
||||
return value;
|
||||
}
|
||||
bool remove(node& key, shared_memory_holder pMemory) {
|
||||
return m_pRef->remove(key, pMemory);
|
||||
}
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
void force_insert(const Key& key, const Value& value,
|
||||
shared_memory_holder pMemory) {
|
||||
m_pRef->force_insert(key, value, pMemory);
|
||||
}
|
||||
|
||||
private:
|
||||
shared_node_ref m_pRef;
|
||||
typedef std::set<node*> nodes;
|
||||
nodes m_dependencies;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,127 @@
|
||||
#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node;
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class YAML_CPP_API node_data {
|
||||
public:
|
||||
node_data();
|
||||
node_data(const node_data&) = delete;
|
||||
node_data& operator=(const node_data&) = delete;
|
||||
|
||||
void mark_defined();
|
||||
void set_mark(const Mark& mark);
|
||||
void set_type(NodeType::value type);
|
||||
void set_tag(const std::string& tag);
|
||||
void set_null();
|
||||
void set_scalar(const std::string& scalar);
|
||||
void set_style(EmitterStyle::value style);
|
||||
|
||||
bool is_defined() const { return m_isDefined; }
|
||||
const Mark& mark() const { return m_mark; }
|
||||
NodeType::value type() const {
|
||||
return m_isDefined ? m_type : NodeType::Undefined;
|
||||
}
|
||||
const std::string& scalar() const { return m_scalar; }
|
||||
const std::string& tag() const { return m_tag; }
|
||||
EmitterStyle::value style() const { return m_style; }
|
||||
|
||||
// size/iterator
|
||||
std::size_t size() const;
|
||||
|
||||
const_node_iterator begin() const;
|
||||
node_iterator begin();
|
||||
|
||||
const_node_iterator end() const;
|
||||
node_iterator end();
|
||||
|
||||
// sequence
|
||||
void push_back(node& node, shared_memory_holder pMemory);
|
||||
void insert(node& key, node& value, shared_memory_holder pMemory);
|
||||
|
||||
// indexing
|
||||
template <typename Key>
|
||||
node* get(const Key& key, shared_memory_holder pMemory) const;
|
||||
template <typename Key>
|
||||
node& get(const Key& key, shared_memory_holder pMemory);
|
||||
template <typename Key>
|
||||
bool remove(const Key& key, shared_memory_holder pMemory);
|
||||
|
||||
node* get(node& key, shared_memory_holder pMemory) const;
|
||||
node& get(node& key, shared_memory_holder pMemory);
|
||||
bool remove(node& key, shared_memory_holder pMemory);
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
void force_insert(const Key& key, const Value& value,
|
||||
shared_memory_holder pMemory);
|
||||
|
||||
public:
|
||||
static std::string empty_scalar;
|
||||
|
||||
private:
|
||||
void compute_seq_size() const;
|
||||
void compute_map_size() const;
|
||||
|
||||
void reset_sequence();
|
||||
void reset_map();
|
||||
|
||||
void insert_map_pair(node& key, node& value);
|
||||
void convert_to_map(shared_memory_holder pMemory);
|
||||
void convert_sequence_to_map(shared_memory_holder pMemory);
|
||||
|
||||
template <typename T>
|
||||
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
|
||||
|
||||
private:
|
||||
bool m_isDefined;
|
||||
Mark m_mark;
|
||||
NodeType::value m_type;
|
||||
std::string m_tag;
|
||||
EmitterStyle::value m_style;
|
||||
|
||||
// scalar
|
||||
std::string m_scalar;
|
||||
|
||||
// sequence
|
||||
typedef std::vector<node*> node_seq;
|
||||
node_seq m_sequence;
|
||||
|
||||
mutable std::size_t m_seqSize;
|
||||
|
||||
// map
|
||||
typedef std::vector<std::pair<node*, node*>> node_map;
|
||||
node_map m_map;
|
||||
|
||||
typedef std::pair<node*, node*> kv_pair;
|
||||
typedef std::list<kv_pair> kv_pairs;
|
||||
mutable kv_pairs m_undefinedPairs;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,180 @@
|
||||
#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
struct iterator_type {
|
||||
enum value { NoneType, Sequence, Map };
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
struct node_iterator_value : public std::pair<V*, V*> {
|
||||
typedef std::pair<V*, V*> kv;
|
||||
|
||||
node_iterator_value() : kv(), pNode(0) {}
|
||||
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
||||
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {}
|
||||
|
||||
V& operator*() const { return *pNode; }
|
||||
V& operator->() const { return *pNode; }
|
||||
|
||||
V* pNode;
|
||||
};
|
||||
|
||||
typedef std::vector<node*> node_seq;
|
||||
typedef std::vector<std::pair<node*, node*>> node_map;
|
||||
|
||||
template <typename V>
|
||||
struct node_iterator_type {
|
||||
typedef node_seq::iterator seq;
|
||||
typedef node_map::iterator map;
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
struct node_iterator_type<const V> {
|
||||
typedef node_seq::const_iterator seq;
|
||||
typedef node_map::const_iterator map;
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
class node_iterator_base
|
||||
: public std::iterator<std::forward_iterator_tag, node_iterator_value<V>,
|
||||
std::ptrdiff_t, node_iterator_value<V>*,
|
||||
node_iterator_value<V>> {
|
||||
private:
|
||||
struct enabler {};
|
||||
|
||||
struct proxy {
|
||||
explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {}
|
||||
node_iterator_value<V>* operator->() { return std::addressof(m_ref); }
|
||||
operator node_iterator_value<V>*() { return std::addressof(m_ref); }
|
||||
|
||||
node_iterator_value<V> m_ref;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename node_iterator_type<V>::seq SeqIter;
|
||||
typedef typename node_iterator_type<V>::map MapIter;
|
||||
typedef node_iterator_value<V> value_type;
|
||||
|
||||
node_iterator_base()
|
||||
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
||||
explicit node_iterator_base(SeqIter seqIt)
|
||||
: m_type(iterator_type::Sequence),
|
||||
m_seqIt(seqIt),
|
||||
m_mapIt(),
|
||||
m_mapEnd() {}
|
||||
explicit node_iterator_base(MapIter mapIt, MapIter mapEnd)
|
||||
: m_type(iterator_type::Map),
|
||||
m_seqIt(),
|
||||
m_mapIt(mapIt),
|
||||
m_mapEnd(mapEnd) {
|
||||
m_mapIt = increment_until_defined(m_mapIt);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
node_iterator_base(const node_iterator_base<W>& rhs,
|
||||
typename std::enable_if<std::is_convertible<W*, V*>::value,
|
||||
enabler>::type = enabler())
|
||||
: m_type(rhs.m_type),
|
||||
m_seqIt(rhs.m_seqIt),
|
||||
m_mapIt(rhs.m_mapIt),
|
||||
m_mapEnd(rhs.m_mapEnd) {}
|
||||
|
||||
template <typename>
|
||||
friend class node_iterator_base;
|
||||
|
||||
template <typename W>
|
||||
bool operator==(const node_iterator_base<W>& rhs) const {
|
||||
if (m_type != rhs.m_type)
|
||||
return false;
|
||||
|
||||
switch (m_type) {
|
||||
case iterator_type::NoneType:
|
||||
return true;
|
||||
case iterator_type::Sequence:
|
||||
return m_seqIt == rhs.m_seqIt;
|
||||
case iterator_type::Map:
|
||||
return m_mapIt == rhs.m_mapIt;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator!=(const node_iterator_base<W>& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
node_iterator_base<V>& operator++() {
|
||||
switch (m_type) {
|
||||
case iterator_type::NoneType:
|
||||
break;
|
||||
case iterator_type::Sequence:
|
||||
++m_seqIt;
|
||||
break;
|
||||
case iterator_type::Map:
|
||||
++m_mapIt;
|
||||
m_mapIt = increment_until_defined(m_mapIt);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_iterator_base<V> operator++(int) {
|
||||
node_iterator_base<V> iterator_pre(*this);
|
||||
++(*this);
|
||||
return iterator_pre;
|
||||
}
|
||||
|
||||
value_type operator*() const {
|
||||
switch (m_type) {
|
||||
case iterator_type::NoneType:
|
||||
return value_type();
|
||||
case iterator_type::Sequence:
|
||||
return value_type(**m_seqIt);
|
||||
case iterator_type::Map:
|
||||
return value_type(*m_mapIt->first, *m_mapIt->second);
|
||||
}
|
||||
return value_type();
|
||||
}
|
||||
|
||||
proxy operator->() const { return proxy(**this); }
|
||||
|
||||
MapIter increment_until_defined(MapIter it) {
|
||||
while (it != m_mapEnd && !is_defined(it))
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
|
||||
bool is_defined(MapIter it) const {
|
||||
return it->first->is_defined() && it->second->is_defined();
|
||||
}
|
||||
|
||||
private:
|
||||
typename iterator_type::value m_type;
|
||||
|
||||
SeqIter m_seqIt;
|
||||
MapIter m_mapIt, m_mapEnd;
|
||||
};
|
||||
|
||||
typedef node_iterator_base<node> node_iterator;
|
||||
typedef node_iterator_base<const node> const_node_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include "yaml-cpp/node/detail/node_data.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node_ref {
|
||||
public:
|
||||
node_ref() : m_pData(new node_data) {}
|
||||
node_ref(const node_ref&) = delete;
|
||||
node_ref& operator=(const node_ref&) = delete;
|
||||
|
||||
bool is_defined() const { return m_pData->is_defined(); }
|
||||
const Mark& mark() const { return m_pData->mark(); }
|
||||
NodeType::value type() const { return m_pData->type(); }
|
||||
const std::string& scalar() const { return m_pData->scalar(); }
|
||||
const std::string& tag() const { return m_pData->tag(); }
|
||||
EmitterStyle::value style() const { return m_pData->style(); }
|
||||
|
||||
void mark_defined() { m_pData->mark_defined(); }
|
||||
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
|
||||
|
||||
void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
|
||||
void set_type(NodeType::value type) { m_pData->set_type(type); }
|
||||
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
||||
void set_null() { m_pData->set_null(); }
|
||||
void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); }
|
||||
void set_style(EmitterStyle::value style) { m_pData->set_style(style); }
|
||||
|
||||
// size/iterator
|
||||
std::size_t size() const { return m_pData->size(); }
|
||||
|
||||
const_node_iterator begin() const {
|
||||
return static_cast<const node_data&>(*m_pData).begin();
|
||||
}
|
||||
node_iterator begin() { return m_pData->begin(); }
|
||||
|
||||
const_node_iterator end() const {
|
||||
return static_cast<const node_data&>(*m_pData).end();
|
||||
}
|
||||
node_iterator end() { return m_pData->end(); }
|
||||
|
||||
// sequence
|
||||
void push_back(node& node, shared_memory_holder pMemory) {
|
||||
m_pData->push_back(node, pMemory);
|
||||
}
|
||||
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||
m_pData->insert(key, value, pMemory);
|
||||
}
|
||||
|
||||
// indexing
|
||||
template <typename Key>
|
||||
node* get(const Key& key, shared_memory_holder pMemory) const {
|
||||
return static_cast<const node_data&>(*m_pData).get(key, pMemory);
|
||||
}
|
||||
template <typename Key>
|
||||
node& get(const Key& key, shared_memory_holder pMemory) {
|
||||
return m_pData->get(key, pMemory);
|
||||
}
|
||||
template <typename Key>
|
||||
bool remove(const Key& key, shared_memory_holder pMemory) {
|
||||
return m_pData->remove(key, pMemory);
|
||||
}
|
||||
|
||||
node* get(node& key, shared_memory_holder pMemory) const {
|
||||
return static_cast<const node_data&>(*m_pData).get(key, pMemory);
|
||||
}
|
||||
node& get(node& key, shared_memory_holder pMemory) {
|
||||
return m_pData->get(key, pMemory);
|
||||
}
|
||||
bool remove(node& key, shared_memory_holder pMemory) {
|
||||
return m_pData->remove(key, pMemory);
|
||||
}
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
void force_insert(const Key& key, const Value& value,
|
||||
shared_memory_holder pMemory) {
|
||||
m_pData->force_insert(key, value, pMemory);
|
||||
}
|
||||
|
||||
private:
|
||||
shared_node_data m_pData;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
namespace YAML {
|
||||
class Emitter;
|
||||
class Node;
|
||||
|
||||
/**
|
||||
* Emits the node to the given {@link Emitter}. If there is an error in writing,
|
||||
* {@link Emitter#good} will return false.
|
||||
*/
|
||||
YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
|
||||
|
||||
/** Emits the node to the given output stream. */
|
||||
YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
|
||||
|
||||
/** Converts the node to a YAML string. */
|
||||
YAML_CPP_API std::string Dump(const Node& node);
|
||||
} // namespace YAML
|
||||
|
||||
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,448 @@
|
||||
#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
#include "yaml-cpp/node/detail/memory.h"
|
||||
#include "yaml-cpp/node/detail/node.h"
|
||||
#include "yaml-cpp/exceptions.h"
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
inline Node::Node() : m_isValid(true), m_pNode(NULL) {}
|
||||
|
||||
inline Node::Node(NodeType::value type)
|
||||
: m_isValid(true),
|
||||
m_pMemory(new detail::memory_holder),
|
||||
m_pNode(&m_pMemory->create_node()) {
|
||||
m_pNode->set_type(type);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Node::Node(const T& rhs)
|
||||
: m_isValid(true),
|
||||
m_pMemory(new detail::memory_holder),
|
||||
m_pNode(&m_pMemory->create_node()) {
|
||||
Assign(rhs);
|
||||
}
|
||||
|
||||
inline Node::Node(const detail::iterator_value& rhs)
|
||||
: m_isValid(rhs.m_isValid),
|
||||
m_pMemory(rhs.m_pMemory),
|
||||
m_pNode(rhs.m_pNode) {}
|
||||
|
||||
inline Node::Node(const Node& rhs)
|
||||
: m_isValid(rhs.m_isValid),
|
||||
m_pMemory(rhs.m_pMemory),
|
||||
m_pNode(rhs.m_pNode) {}
|
||||
|
||||
inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {}
|
||||
|
||||
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
||||
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
|
||||
|
||||
inline Node::~Node() {}
|
||||
|
||||
inline void Node::EnsureNodeExists() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
if (!m_pNode) {
|
||||
m_pMemory.reset(new detail::memory_holder);
|
||||
m_pNode = &m_pMemory->create_node();
|
||||
m_pNode->set_null();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool Node::IsDefined() const {
|
||||
if (!m_isValid) {
|
||||
return false;
|
||||
}
|
||||
return m_pNode ? m_pNode->is_defined() : true;
|
||||
}
|
||||
|
||||
inline Mark Node::Mark() const {
|
||||
if (!m_isValid) {
|
||||
throw InvalidNode();
|
||||
}
|
||||
return m_pNode ? m_pNode->mark() : Mark::null_mark();
|
||||
}
|
||||
|
||||
inline NodeType::value Node::Type() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
return m_pNode ? m_pNode->type() : NodeType::Null;
|
||||
}
|
||||
|
||||
// access
|
||||
|
||||
// template helpers
|
||||
template <typename T, typename S>
|
||||
struct as_if {
|
||||
explicit as_if(const Node& node_) : node(node_) {}
|
||||
const Node& node;
|
||||
|
||||
T operator()(const S& fallback) const {
|
||||
if (!node.m_pNode)
|
||||
return fallback;
|
||||
|
||||
T t;
|
||||
if (convert<T>::decode(node, t))
|
||||
return t;
|
||||
return fallback;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct as_if<std::string, S> {
|
||||
explicit as_if(const Node& node_) : node(node_) {}
|
||||
const Node& node;
|
||||
|
||||
std::string operator()(const S& fallback) const {
|
||||
if (node.Type() != NodeType::Scalar)
|
||||
return fallback;
|
||||
return node.Scalar();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct as_if<T, void> {
|
||||
explicit as_if(const Node& node_) : node(node_) {}
|
||||
const Node& node;
|
||||
|
||||
T operator()() const {
|
||||
if (!node.m_pNode)
|
||||
throw TypedBadConversion<T>(node.Mark());
|
||||
|
||||
T t;
|
||||
if (convert<T>::decode(node, t))
|
||||
return t;
|
||||
throw TypedBadConversion<T>(node.Mark());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct as_if<std::string, void> {
|
||||
explicit as_if(const Node& node_) : node(node_) {}
|
||||
const Node& node;
|
||||
|
||||
std::string operator()() const {
|
||||
if (node.Type() != NodeType::Scalar)
|
||||
throw TypedBadConversion<std::string>(node.Mark());
|
||||
return node.Scalar();
|
||||
}
|
||||
};
|
||||
|
||||
// access functions
|
||||
template <typename T>
|
||||
inline T Node::as() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
return as_if<T, void>(*this)();
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
inline T Node::as(const S& fallback) const {
|
||||
if (!m_isValid)
|
||||
return fallback;
|
||||
return as_if<T, S>(*this)(fallback);
|
||||
}
|
||||
|
||||
inline const std::string& Node::Scalar() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
|
||||
}
|
||||
|
||||
inline const std::string& Node::Tag() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
|
||||
}
|
||||
|
||||
inline void Node::SetTag(const std::string& tag) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_tag(tag);
|
||||
}
|
||||
|
||||
inline EmitterStyle::value Node::Style() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
|
||||
}
|
||||
|
||||
inline void Node::SetStyle(EmitterStyle::value style) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_style(style);
|
||||
}
|
||||
|
||||
// assignment
|
||||
inline bool Node::is(const Node& rhs) const {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode();
|
||||
if (!m_pNode || !rhs.m_pNode)
|
||||
return false;
|
||||
return m_pNode->is(*rhs.m_pNode);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Node& Node::operator=(const T& rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
Assign(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void Node::reset(const YAML::Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode();
|
||||
m_pMemory = rhs.m_pMemory;
|
||||
m_pNode = rhs.m_pNode;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Node::Assign(const T& rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
AssignData(convert<T>::encode(rhs));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void Node::Assign(const std::string& rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_scalar(rhs);
|
||||
}
|
||||
|
||||
inline void Node::Assign(const char* rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_scalar(rhs);
|
||||
}
|
||||
|
||||
inline void Node::Assign(char* rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_scalar(rhs);
|
||||
}
|
||||
|
||||
inline Node& Node::operator=(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode();
|
||||
if (is(rhs))
|
||||
return *this;
|
||||
AssignNode(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void Node::AssignData(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
rhs.EnsureNodeExists();
|
||||
|
||||
m_pNode->set_data(*rhs.m_pNode);
|
||||
m_pMemory->merge(*rhs.m_pMemory);
|
||||
}
|
||||
|
||||
inline void Node::AssignNode(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode();
|
||||
rhs.EnsureNodeExists();
|
||||
|
||||
if (!m_pNode) {
|
||||
m_pNode = rhs.m_pNode;
|
||||
m_pMemory = rhs.m_pMemory;
|
||||
return;
|
||||
}
|
||||
|
||||
m_pNode->set_ref(*rhs.m_pNode);
|
||||
m_pMemory->merge(*rhs.m_pMemory);
|
||||
m_pNode = rhs.m_pNode;
|
||||
}
|
||||
|
||||
// size/iterator
|
||||
inline std::size_t Node::size() const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
return m_pNode ? m_pNode->size() : 0;
|
||||
}
|
||||
|
||||
inline const_iterator Node::begin() const {
|
||||
if (!m_isValid)
|
||||
return const_iterator();
|
||||
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
|
||||
: const_iterator();
|
||||
}
|
||||
|
||||
inline iterator Node::begin() {
|
||||
if (!m_isValid)
|
||||
return iterator();
|
||||
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
|
||||
}
|
||||
|
||||
inline const_iterator Node::end() const {
|
||||
if (!m_isValid)
|
||||
return const_iterator();
|
||||
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
|
||||
}
|
||||
|
||||
inline iterator Node::end() {
|
||||
if (!m_isValid)
|
||||
return iterator();
|
||||
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
|
||||
}
|
||||
|
||||
// sequence
|
||||
template <typename T>
|
||||
inline void Node::push_back(const T& rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
push_back(Node(rhs));
|
||||
}
|
||||
|
||||
inline void Node::push_back(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
rhs.EnsureNodeExists();
|
||||
|
||||
m_pNode->push_back(*rhs.m_pNode, m_pMemory);
|
||||
m_pMemory->merge(*rhs.m_pMemory);
|
||||
}
|
||||
|
||||
// helpers for indexing
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct to_value_t {
|
||||
explicit to_value_t(const T& t_) : t(t_) {}
|
||||
const T& t;
|
||||
typedef const T& return_type;
|
||||
|
||||
const T& operator()() const { return t; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct to_value_t<const char*> {
|
||||
explicit to_value_t(const char* t_) : t(t_) {}
|
||||
const char* t;
|
||||
typedef std::string return_type;
|
||||
|
||||
const std::string operator()() const { return t; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct to_value_t<char*> {
|
||||
explicit to_value_t(char* t_) : t(t_) {}
|
||||
const char* t;
|
||||
typedef std::string return_type;
|
||||
|
||||
const std::string operator()() const { return t; }
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct to_value_t<char[N]> {
|
||||
explicit to_value_t(const char* t_) : t(t_) {}
|
||||
const char* t;
|
||||
typedef std::string return_type;
|
||||
|
||||
const std::string operator()() const { return t; }
|
||||
};
|
||||
|
||||
// converts C-strings to std::strings so they can be copied
|
||||
template <typename T>
|
||||
inline typename to_value_t<T>::return_type to_value(const T& t) {
|
||||
return to_value_t<T>(t)();
|
||||
}
|
||||
}
|
||||
|
||||
// indexing
|
||||
template <typename Key>
|
||||
inline const Node Node::operator[](const Key& key) const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
detail::node* value = static_cast<const detail::node&>(*m_pNode)
|
||||
.get(detail::to_value(key), m_pMemory);
|
||||
if (!value) {
|
||||
return Node(ZombieNode);
|
||||
}
|
||||
return Node(*value, m_pMemory);
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
inline Node Node::operator[](const Key& key) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
||||
return Node(value, m_pMemory);
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
inline bool Node::remove(const Key& key) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
||||
}
|
||||
|
||||
inline const Node Node::operator[](const Node& key) const {
|
||||
if (!m_isValid || !key.m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
key.EnsureNodeExists();
|
||||
m_pMemory->merge(*key.m_pMemory);
|
||||
detail::node* value =
|
||||
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
|
||||
if (!value) {
|
||||
return Node(ZombieNode);
|
||||
}
|
||||
return Node(*value, m_pMemory);
|
||||
}
|
||||
|
||||
inline Node Node::operator[](const Node& key) {
|
||||
if (!m_isValid || !key.m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
key.EnsureNodeExists();
|
||||
m_pMemory->merge(*key.m_pMemory);
|
||||
detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory);
|
||||
return Node(value, m_pMemory);
|
||||
}
|
||||
|
||||
inline bool Node::remove(const Node& key) {
|
||||
if (!m_isValid || !key.m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
key.EnsureNodeExists();
|
||||
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
||||
}
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
inline void Node::force_insert(const Key& key, const Value& value) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode();
|
||||
EnsureNodeExists();
|
||||
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
|
||||
m_pMemory);
|
||||
}
|
||||
|
||||
// free functions
|
||||
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
|
||||
}
|
||||
|
||||
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||
#include "yaml-cpp/node/detail/iterator.h"
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
struct iterator_value : public Node, std::pair<Node, Node> {
|
||||
iterator_value() {}
|
||||
explicit iterator_value(const Node& rhs)
|
||||
: Node(rhs),
|
||||
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
||||
explicit iterator_value(const Node& key, const Node& value)
|
||||
: Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,145 @@
|
||||
#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/mark.h"
|
||||
#include "yaml-cpp/node/detail/bool_type.h"
|
||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node;
|
||||
class node_data;
|
||||
struct iterator_value;
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class YAML_CPP_API Node {
|
||||
public:
|
||||
friend class NodeBuilder;
|
||||
friend class NodeEvents;
|
||||
friend struct detail::iterator_value;
|
||||
friend class detail::node;
|
||||
friend class detail::node_data;
|
||||
template <typename>
|
||||
friend class detail::iterator_base;
|
||||
template <typename T, typename S>
|
||||
friend struct as_if;
|
||||
|
||||
typedef YAML::iterator iterator;
|
||||
typedef YAML::const_iterator const_iterator;
|
||||
|
||||
Node();
|
||||
explicit Node(NodeType::value type);
|
||||
template <typename T>
|
||||
explicit Node(const T& rhs);
|
||||
explicit Node(const detail::iterator_value& rhs);
|
||||
Node(const Node& rhs);
|
||||
~Node();
|
||||
|
||||
YAML::Mark Mark() const;
|
||||
NodeType::value Type() const;
|
||||
bool IsDefined() const;
|
||||
bool IsNull() const { return Type() == NodeType::Null; }
|
||||
bool IsScalar() const { return Type() == NodeType::Scalar; }
|
||||
bool IsSequence() const { return Type() == NodeType::Sequence; }
|
||||
bool IsMap() const { return Type() == NodeType::Map; }
|
||||
|
||||
// bool conversions
|
||||
YAML_CPP_OPERATOR_BOOL()
|
||||
bool operator!() const { return !IsDefined(); }
|
||||
|
||||
// access
|
||||
template <typename T>
|
||||
T as() const;
|
||||
template <typename T, typename S>
|
||||
T as(const S& fallback) const;
|
||||
const std::string& Scalar() const;
|
||||
|
||||
const std::string& Tag() const;
|
||||
void SetTag(const std::string& tag);
|
||||
|
||||
// style
|
||||
// WARNING: This API might change in future releases.
|
||||
EmitterStyle::value Style() const;
|
||||
void SetStyle(EmitterStyle::value style);
|
||||
|
||||
// assignment
|
||||
bool is(const Node& rhs) const;
|
||||
template <typename T>
|
||||
Node& operator=(const T& rhs);
|
||||
Node& operator=(const Node& rhs);
|
||||
void reset(const Node& rhs = Node());
|
||||
|
||||
// size/iterator
|
||||
std::size_t size() const;
|
||||
|
||||
const_iterator begin() const;
|
||||
iterator begin();
|
||||
|
||||
const_iterator end() const;
|
||||
iterator end();
|
||||
|
||||
// sequence
|
||||
template <typename T>
|
||||
void push_back(const T& rhs);
|
||||
void push_back(const Node& rhs);
|
||||
|
||||
// indexing
|
||||
template <typename Key>
|
||||
const Node operator[](const Key& key) const;
|
||||
template <typename Key>
|
||||
Node operator[](const Key& key);
|
||||
template <typename Key>
|
||||
bool remove(const Key& key);
|
||||
|
||||
const Node operator[](const Node& key) const;
|
||||
Node operator[](const Node& key);
|
||||
bool remove(const Node& key);
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
void force_insert(const Key& key, const Value& value);
|
||||
|
||||
private:
|
||||
enum Zombie { ZombieNode };
|
||||
explicit Node(Zombie);
|
||||
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
|
||||
|
||||
void EnsureNodeExists() const;
|
||||
|
||||
template <typename T>
|
||||
void Assign(const T& rhs);
|
||||
void Assign(const char* rhs);
|
||||
void Assign(char* rhs);
|
||||
|
||||
void AssignData(const Node& rhs);
|
||||
void AssignNode(const Node& rhs);
|
||||
|
||||
private:
|
||||
bool m_isValid;
|
||||
mutable detail::shared_memory_holder m_pMemory;
|
||||
mutable detail::node* m_pNode;
|
||||
};
|
||||
|
||||
YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs);
|
||||
|
||||
YAML_CPP_API Node Clone(const Node& node);
|
||||
|
||||
template <typename T>
|
||||
struct convert;
|
||||
}
|
||||
|
||||
#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
namespace YAML {
|
||||
class Node;
|
||||
|
||||
/**
|
||||
* Loads the input string as a single YAML document.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
*/
|
||||
YAML_CPP_API Node Load(const std::string& input);
|
||||
|
||||
/**
|
||||
* Loads the input string as a single YAML document.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
*/
|
||||
YAML_CPP_API Node Load(const char* input);
|
||||
|
||||
/**
|
||||
* Loads the input stream as a single YAML document.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
*/
|
||||
YAML_CPP_API Node Load(std::istream& input);
|
||||
|
||||
/**
|
||||
* Loads the input file as a single YAML document.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
* @throws {@link BadFile} if the file cannot be loaded.
|
||||
*/
|
||||
YAML_CPP_API Node LoadFile(const std::string& filename);
|
||||
|
||||
/**
|
||||
* Loads the input string as a list of YAML documents.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
*/
|
||||
YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
|
||||
|
||||
/**
|
||||
* Loads the input string as a list of YAML documents.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
*/
|
||||
YAML_CPP_API std::vector<Node> LoadAll(const char* input);
|
||||
|
||||
/**
|
||||
* Loads the input stream as a list of YAML documents.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
*/
|
||||
YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
|
||||
|
||||
/**
|
||||
* Loads the input file as a list of YAML documents.
|
||||
*
|
||||
* @throws {@link ParserException} if it is malformed.
|
||||
* @throws {@link BadFile} if the file cannot be loaded.
|
||||
*/
|
||||
YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
|
||||
} // namespace YAML
|
||||
|
||||
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <memory>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node;
|
||||
class node_ref;
|
||||
class node_data;
|
||||
class memory;
|
||||
class memory_holder;
|
||||
|
||||
typedef std::shared_ptr<node> shared_node;
|
||||
typedef std::shared_ptr<node_ref> shared_node_ref;
|
||||
typedef std::shared_ptr<node_data> shared_node_data;
|
||||
typedef std::shared_ptr<memory_holder> shared_memory_holder;
|
||||
typedef std::shared_ptr<memory> shared_memory;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
struct NodeType {
|
||||
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||
};
|
||||
}
|
||||
|
||||
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
namespace YAML {
|
||||
// this is basically boost::noncopyable
|
||||
class YAML_CPP_API noncopyable {
|
||||
protected:
|
||||
noncopyable() {}
|
||||
~noncopyable() {}
|
||||
|
||||
private:
|
||||
noncopyable(const noncopyable&);
|
||||
const noncopyable& operator=(const noncopyable&);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
class Node;
|
||||
|
||||
struct YAML_CPP_API _Null {};
|
||||
inline bool operator==(const _Null&, const _Null&) { return true; }
|
||||
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
||||
|
||||
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
||||
YAML_CPP_API bool IsNullString(const std::string& str);
|
||||
|
||||
extern YAML_CPP_API _Null Null;
|
||||
}
|
||||
|
||||
#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
namespace YAML {
|
||||
class YAML_CPP_API ostream_wrapper {
|
||||
public:
|
||||
ostream_wrapper();
|
||||
explicit ostream_wrapper(std::ostream& stream);
|
||||
~ostream_wrapper();
|
||||
|
||||
void write(const std::string& str);
|
||||
void write(const char* str, std::size_t size);
|
||||
|
||||
void set_comment() { m_comment = true; }
|
||||
|
||||
const char* str() const {
|
||||
if (m_pStream) {
|
||||
return 0;
|
||||
} else {
|
||||
m_buffer[m_pos] = '\0';
|
||||
return &m_buffer[0];
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t row() const { return m_row; }
|
||||
std::size_t col() const { return m_col; }
|
||||
std::size_t pos() const { return m_pos; }
|
||||
bool comment() const { return m_comment; }
|
||||
|
||||
private:
|
||||
void update_pos(char ch);
|
||||
|
||||
private:
|
||||
mutable std::vector<char> m_buffer;
|
||||
std::ostream* const m_pStream;
|
||||
|
||||
std::size_t m_pos;
|
||||
std::size_t m_row, m_col;
|
||||
bool m_comment;
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
|
||||
const char(&str)[N]) {
|
||||
stream.write(str, N - 1);
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
|
||||
const std::string& str) {
|
||||
stream.write(str);
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
|
||||
stream.write(&ch, 1);
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/noncopyable.h"
|
||||
|
||||
namespace YAML {
|
||||
class EventHandler;
|
||||
class Node;
|
||||
class Scanner;
|
||||
struct Directives;
|
||||
struct Token;
|
||||
|
||||
/**
|
||||
* A parser turns a stream of bytes into one stream of "events" per YAML
|
||||
* document in the input stream.
|
||||
*/
|
||||
class YAML_CPP_API Parser : private noncopyable {
|
||||
public:
|
||||
/** Constructs an empty parser (with no input. */
|
||||
Parser();
|
||||
|
||||
/**
|
||||
* Constructs a parser from the given input stream. The input stream must
|
||||
* live as long as the parser.
|
||||
*/
|
||||
explicit Parser(std::istream& in);
|
||||
|
||||
~Parser();
|
||||
|
||||
/** Evaluates to true if the parser has some valid input to be read. */
|
||||
explicit operator bool() const;
|
||||
|
||||
/**
|
||||
* Resets the parser with the given input stream. Any existing state is
|
||||
* erased.
|
||||
*/
|
||||
void Load(std::istream& in);
|
||||
|
||||
/**
|
||||
* Handles the next document by calling events on the {@code eventHandler}.
|
||||
*
|
||||
* @throw a ParserException on error.
|
||||
* @return false if there are no more documents
|
||||
*/
|
||||
bool HandleNextDocument(EventHandler& eventHandler);
|
||||
|
||||
void PrintTokens(std::ostream& out);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Reads any directives that are next in the queue, setting the internal
|
||||
* {@code m_pDirectives} state.
|
||||
*/
|
||||
void ParseDirectives();
|
||||
|
||||
void HandleDirective(const Token& token);
|
||||
|
||||
/**
|
||||
* Handles a "YAML" directive, which should be of the form 'major.minor' (like
|
||||
* a version number).
|
||||
*/
|
||||
void HandleYamlDirective(const Token& token);
|
||||
|
||||
/**
|
||||
* Handles a "TAG" directive, which should be of the form 'handle prefix',
|
||||
* where 'handle' is converted to 'prefix' in the file.
|
||||
*/
|
||||
void HandleTagDirective(const Token& token);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Scanner> m_pScanner;
|
||||
std::unique_ptr<Directives> m_pDirectives;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
namespace YAML {
|
||||
template <typename Seq>
|
||||
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
|
||||
emitter << BeginSeq;
|
||||
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
|
||||
emitter << *it;
|
||||
emitter << EndSeq;
|
||||
return emitter;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::vector<T>& v) {
|
||||
return EmitSeq(emitter, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::list<T>& v) {
|
||||
return EmitSeq(emitter, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
|
||||
return EmitSeq(emitter, v);
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
|
||||
typedef typename std::map<K, V> map;
|
||||
emitter << BeginMap;
|
||||
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
|
||||
emitter << Key << it->first << Value << it->second;
|
||||
emitter << EndMap;
|
||||
return emitter;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
template <typename>
|
||||
struct is_numeric {
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_numeric<char> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<unsigned char> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<int> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<unsigned int> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<long int> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<unsigned long int> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<short int> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<unsigned short int> {
|
||||
enum { value = true };
|
||||
};
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1310)
|
||||
template <>
|
||||
struct is_numeric<__int64> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<unsigned __int64> {
|
||||
enum { value = true };
|
||||
};
|
||||
#else
|
||||
template <>
|
||||
struct is_numeric<long long> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<unsigned long long> {
|
||||
enum { value = true };
|
||||
};
|
||||
#endif
|
||||
template <>
|
||||
struct is_numeric<float> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<double> {
|
||||
enum { value = true };
|
||||
};
|
||||
template <>
|
||||
struct is_numeric<long double> {
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template <bool, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
template <bool, class T = void>
|
||||
struct disable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct disable_if_c<true, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||
}
|
||||
|
||||
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/parser.h"
|
||||
#include "yaml-cpp/emitter.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/stlemitter.h"
|
||||
#include "yaml-cpp/exceptions.h"
|
||||
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/node/convert.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
#include "yaml-cpp/node/detail/impl.h"
|
||||
#include "yaml-cpp/node/parse.h"
|
||||
#include "yaml-cpp/node/emit.h"
|
||||
|
||||
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
93
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/binary.cpp
Executable file
93
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/binary.cpp
Executable file
@@ -0,0 +1,93 @@
|
||||
#include "yaml-cpp/binary.h"
|
||||
|
||||
namespace YAML {
|
||||
static const char encoding[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
std::string EncodeBase64(const unsigned char *data, std::size_t size) {
|
||||
const char PAD = '=';
|
||||
|
||||
std::string ret;
|
||||
ret.resize(4 * size / 3 + 3);
|
||||
char *out = &ret[0];
|
||||
|
||||
std::size_t chunks = size / 3;
|
||||
std::size_t remainder = size % 3;
|
||||
|
||||
for (std::size_t i = 0; i < chunks; i++, data += 3) {
|
||||
*out++ = encoding[data[0] >> 2];
|
||||
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
|
||||
*out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
|
||||
*out++ = encoding[data[2] & 0x3f];
|
||||
}
|
||||
|
||||
switch (remainder) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
*out++ = encoding[data[0] >> 2];
|
||||
*out++ = encoding[((data[0] & 0x3) << 4)];
|
||||
*out++ = PAD;
|
||||
*out++ = PAD;
|
||||
break;
|
||||
case 2:
|
||||
*out++ = encoding[data[0] >> 2];
|
||||
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
|
||||
*out++ = encoding[((data[1] & 0xf) << 2)];
|
||||
*out++ = PAD;
|
||||
break;
|
||||
}
|
||||
|
||||
ret.resize(out - &ret[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const unsigned char decoding[] = {
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
|
||||
255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
|
||||
255, 0, 255, 255, 255, 0, 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, 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255,
|
||||
};
|
||||
|
||||
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||
typedef std::vector<unsigned char> ret_type;
|
||||
if (input.empty())
|
||||
return ret_type();
|
||||
|
||||
ret_type ret(3 * input.size() / 4 + 1);
|
||||
unsigned char *out = &ret[0];
|
||||
|
||||
unsigned value = 0;
|
||||
for (std::size_t i = 0; i < input.size(); i++) {
|
||||
unsigned char d = decoding[static_cast<unsigned>(input[i])];
|
||||
if (d == 255)
|
||||
return ret_type();
|
||||
|
||||
value = (value << 6) | d;
|
||||
if (i % 4 == 3) {
|
||||
*out++ = value >> 16;
|
||||
if (i > 0 && input[i - 1] != '=')
|
||||
*out++ = value >> 8;
|
||||
if (input[i] != '=')
|
||||
*out++ = value;
|
||||
}
|
||||
}
|
||||
|
||||
ret.resize(out - &ret[0]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <stack>
|
||||
#include <cassert>
|
||||
|
||||
namespace YAML {
|
||||
struct CollectionType {
|
||||
enum value { NoCollection, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
|
||||
};
|
||||
|
||||
class CollectionStack {
|
||||
public:
|
||||
CollectionType::value GetCurCollectionType() const {
|
||||
if (collectionStack.empty())
|
||||
return CollectionType::NoCollection;
|
||||
return collectionStack.top();
|
||||
}
|
||||
|
||||
void PushCollectionType(CollectionType::value type) {
|
||||
collectionStack.push(type);
|
||||
}
|
||||
void PopCollectionType(CollectionType::value type) {
|
||||
assert(type == GetCurCollectionType());
|
||||
collectionStack.pop();
|
||||
}
|
||||
|
||||
private:
|
||||
std::stack<CollectionType::value> collectionStack;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "graphbuilderadapter.h"
|
||||
|
||||
#include "yaml-cpp/parser.h" // IWYU pragma: keep
|
||||
|
||||
namespace YAML {
|
||||
class GraphBuilderInterface;
|
||||
|
||||
void* BuildGraphOfNextDocument(Parser& parser,
|
||||
GraphBuilderInterface& graphBuilder) {
|
||||
GraphBuilderAdapter eventHandler(graphBuilder);
|
||||
if (parser.HandleNextDocument(eventHandler)) {
|
||||
return eventHandler.RootNode();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#include "graphbuilderadapter.h"
|
||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
|
||||
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
|
||||
|
||||
void GraphBuilderAdapter::OnNull(const Mark &mark, anchor_t anchor) {
|
||||
void *pParent = GetCurrentParent();
|
||||
void *pNode = m_builder.NewNull(mark, pParent);
|
||||
RegisterAnchor(anchor, pNode);
|
||||
|
||||
DispositionNode(pNode);
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::OnAlias(const Mark &mark, anchor_t anchor) {
|
||||
void *pReffedNode = m_anchors.Get(anchor);
|
||||
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::OnScalar(const Mark &mark, const std::string &tag,
|
||||
anchor_t anchor, const std::string &value) {
|
||||
void *pParent = GetCurrentParent();
|
||||
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
|
||||
RegisterAnchor(anchor, pNode);
|
||||
|
||||
DispositionNode(pNode);
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::OnSequenceStart(const Mark &mark,
|
||||
const std::string &tag,
|
||||
anchor_t anchor,
|
||||
EmitterStyle::value /* style */) {
|
||||
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
|
||||
m_containers.push(ContainerFrame(pNode));
|
||||
RegisterAnchor(anchor, pNode);
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::OnSequenceEnd() {
|
||||
void *pSequence = m_containers.top().pContainer;
|
||||
m_containers.pop();
|
||||
|
||||
DispositionNode(pSequence);
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
|
||||
anchor_t anchor,
|
||||
EmitterStyle::value /* style */) {
|
||||
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
|
||||
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
|
||||
m_pKeyNode = NULL;
|
||||
RegisterAnchor(anchor, pNode);
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::OnMapEnd() {
|
||||
void *pMap = m_containers.top().pContainer;
|
||||
m_pKeyNode = m_containers.top().pPrevKeyNode;
|
||||
m_containers.pop();
|
||||
DispositionNode(pMap);
|
||||
}
|
||||
|
||||
void *GraphBuilderAdapter::GetCurrentParent() const {
|
||||
if (m_containers.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_containers.top().pContainer;
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) {
|
||||
if (anchor) {
|
||||
m_anchors.Register(anchor, pNode);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphBuilderAdapter::DispositionNode(void *pNode) {
|
||||
if (m_containers.empty()) {
|
||||
m_pRootNode = pNode;
|
||||
return;
|
||||
}
|
||||
|
||||
void *pContainer = m_containers.top().pContainer;
|
||||
if (m_containers.top().isMap()) {
|
||||
if (m_pKeyNode) {
|
||||
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
|
||||
m_pKeyNode = NULL;
|
||||
} else {
|
||||
m_pKeyNode = pNode;
|
||||
}
|
||||
} else {
|
||||
m_builder.AppendToSequence(pContainer, pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/contrib/anchordict.h"
|
||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
|
||||
namespace YAML {
|
||||
class GraphBuilderInterface;
|
||||
struct Mark;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class GraphBuilderAdapter : public EventHandler {
|
||||
public:
|
||||
GraphBuilderAdapter(GraphBuilderInterface& builder)
|
||||
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) {}
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
|
||||
virtual void OnDocumentEnd() {}
|
||||
|
||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value);
|
||||
|
||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnSequenceEnd();
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnMapEnd();
|
||||
|
||||
void* RootNode() const { return m_pRootNode; }
|
||||
|
||||
private:
|
||||
struct ContainerFrame {
|
||||
ContainerFrame(void* pSequence)
|
||||
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
|
||||
ContainerFrame(void* pMap, void* pPrevKeyNode)
|
||||
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
|
||||
|
||||
void* pContainer;
|
||||
void* pPrevKeyNode;
|
||||
|
||||
bool isMap() const { return pPrevKeyNode != &sequenceMarker; }
|
||||
|
||||
private:
|
||||
static int sequenceMarker;
|
||||
};
|
||||
typedef std::stack<ContainerFrame> ContainerStack;
|
||||
typedef AnchorDict<void*> AnchorMap;
|
||||
|
||||
GraphBuilderInterface& m_builder;
|
||||
ContainerStack m_containers;
|
||||
AnchorMap m_anchors;
|
||||
void* m_pRootNode;
|
||||
void* m_pKeyNode;
|
||||
|
||||
void* GetCurrentParent() const;
|
||||
void RegisterAnchor(anchor_t anchor, void* pNode);
|
||||
void DispositionNode(void* pNode);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
75
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/convert.cpp
Executable file
75
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/convert.cpp
Executable file
@@ -0,0 +1,75 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "yaml-cpp/node/convert.h"
|
||||
|
||||
namespace {
|
||||
// we're not gonna mess with the mess that is all the isupper/etc. functions
|
||||
bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
|
||||
bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
|
||||
char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
|
||||
|
||||
std::string tolower(const std::string& str) {
|
||||
std::string s(str);
|
||||
std::transform(s.begin(), s.end(), s.begin(), ToLower);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool IsEntirely(const std::string& str, T func) {
|
||||
for (std::size_t i = 0; i < str.size(); i++)
|
||||
if (!func(str[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// IsFlexibleCase
|
||||
// . Returns true if 'str' is:
|
||||
// . UPPERCASE
|
||||
// . lowercase
|
||||
// . Capitalized
|
||||
bool IsFlexibleCase(const std::string& str) {
|
||||
if (str.empty())
|
||||
return true;
|
||||
|
||||
if (IsEntirely(str, IsLower))
|
||||
return true;
|
||||
|
||||
bool firstcaps = IsUpper(str[0]);
|
||||
std::string rest = str.substr(1);
|
||||
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
||||
}
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
||||
if (!node.IsScalar())
|
||||
return false;
|
||||
|
||||
// we can't use iostream bool extraction operators as they don't
|
||||
// recognize all possible values in the table below (taken from
|
||||
// http://yaml.org/type/bool.html)
|
||||
static const struct {
|
||||
std::string truename, falsename;
|
||||
} names[] = {
|
||||
{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
|
||||
};
|
||||
|
||||
if (!IsFlexibleCase(node.Scalar()))
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
||||
if (names[i].truename == tolower(node.Scalar())) {
|
||||
rhs = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (names[i].falsename == tolower(node.Scalar())) {
|
||||
rhs = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "directives.h"
|
||||
|
||||
namespace YAML {
|
||||
Directives::Directives() {
|
||||
// version
|
||||
version.isDefault = true;
|
||||
version.major = 1;
|
||||
version.minor = 2;
|
||||
}
|
||||
|
||||
const std::string Directives::TranslateTagHandle(
|
||||
const std::string& handle) const {
|
||||
std::map<std::string, std::string>::const_iterator it = tags.find(handle);
|
||||
if (it == tags.end()) {
|
||||
if (handle == "!!")
|
||||
return "tag:yaml.org,2002:";
|
||||
return handle;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
29
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/directives.h
Executable file
29
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/directives.h
Executable file
@@ -0,0 +1,29 @@
|
||||
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace YAML {
|
||||
struct Version {
|
||||
bool isDefault;
|
||||
int major, minor;
|
||||
};
|
||||
|
||||
struct Directives {
|
||||
Directives();
|
||||
|
||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||
|
||||
Version version;
|
||||
std::map<std::string, std::string> tags;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
25
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emit.cpp
Executable file
25
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emit.cpp
Executable file
@@ -0,0 +1,25 @@
|
||||
#include "yaml-cpp/node/emit.h"
|
||||
#include "yaml-cpp/emitfromevents.h"
|
||||
#include "yaml-cpp/emitter.h"
|
||||
#include "nodeevents.h"
|
||||
|
||||
namespace YAML {
|
||||
Emitter& operator<<(Emitter& out, const Node& node) {
|
||||
EmitFromEvents emitFromEvents(out);
|
||||
NodeEvents events(node);
|
||||
events.Emit(emitFromEvents);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Node& node) {
|
||||
Emitter emitter(out);
|
||||
emitter << node;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string Dump(const Node& node) {
|
||||
Emitter emitter;
|
||||
emitter << node;
|
||||
return emitter.c_str();
|
||||
}
|
||||
} // namespace YAML
|
||||
@@ -0,0 +1,119 @@
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
#include "yaml-cpp/emitfromevents.h"
|
||||
#include "yaml-cpp/emitter.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
} // namespace YAML
|
||||
|
||||
namespace {
|
||||
std::string ToString(YAML::anchor_t anchor) {
|
||||
std::stringstream stream;
|
||||
stream << anchor;
|
||||
return stream.str();
|
||||
}
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {}
|
||||
|
||||
void EmitFromEvents::OnDocumentStart(const Mark&) {}
|
||||
|
||||
void EmitFromEvents::OnDocumentEnd() {}
|
||||
|
||||
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) {
|
||||
BeginNode();
|
||||
EmitProps("", anchor);
|
||||
m_emitter << Null;
|
||||
}
|
||||
|
||||
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) {
|
||||
BeginNode();
|
||||
m_emitter << Alias(ToString(anchor));
|
||||
}
|
||||
|
||||
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value) {
|
||||
BeginNode();
|
||||
EmitProps(tag, anchor);
|
||||
m_emitter << value;
|
||||
}
|
||||
|
||||
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
|
||||
anchor_t anchor,
|
||||
EmitterStyle::value style) {
|
||||
BeginNode();
|
||||
EmitProps(tag, anchor);
|
||||
switch (style) {
|
||||
case EmitterStyle::Block:
|
||||
m_emitter << Block;
|
||||
break;
|
||||
case EmitterStyle::Flow:
|
||||
m_emitter << Flow;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_emitter << BeginSeq;
|
||||
m_stateStack.push(State::WaitingForSequenceEntry);
|
||||
}
|
||||
|
||||
void EmitFromEvents::OnSequenceEnd() {
|
||||
m_emitter << EndSeq;
|
||||
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
|
||||
m_stateStack.pop();
|
||||
}
|
||||
|
||||
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) {
|
||||
BeginNode();
|
||||
EmitProps(tag, anchor);
|
||||
switch (style) {
|
||||
case EmitterStyle::Block:
|
||||
m_emitter << Block;
|
||||
break;
|
||||
case EmitterStyle::Flow:
|
||||
m_emitter << Flow;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_emitter << BeginMap;
|
||||
m_stateStack.push(State::WaitingForKey);
|
||||
}
|
||||
|
||||
void EmitFromEvents::OnMapEnd() {
|
||||
m_emitter << EndMap;
|
||||
assert(m_stateStack.top() == State::WaitingForKey);
|
||||
m_stateStack.pop();
|
||||
}
|
||||
|
||||
void EmitFromEvents::BeginNode() {
|
||||
if (m_stateStack.empty())
|
||||
return;
|
||||
|
||||
switch (m_stateStack.top()) {
|
||||
case State::WaitingForKey:
|
||||
m_emitter << Key;
|
||||
m_stateStack.top() = State::WaitingForValue;
|
||||
break;
|
||||
case State::WaitingForValue:
|
||||
m_emitter << Value;
|
||||
m_stateStack.top() = State::WaitingForKey;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
|
||||
if (!tag.empty() && tag != "?" && tag != "!")
|
||||
m_emitter << VerbatimTag(tag);
|
||||
if (anchor)
|
||||
m_emitter << Anchor(ToString(anchor));
|
||||
}
|
||||
}
|
||||
911
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitter.cpp
Executable file
911
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitter.cpp
Executable file
@@ -0,0 +1,911 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "emitterutils.h"
|
||||
#include "indentation.h" // IWYU pragma: keep
|
||||
#include "yaml-cpp/emitter.h"
|
||||
#include "yaml-cpp/emitterdef.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
struct _Null;
|
||||
|
||||
Emitter::Emitter() : m_pState(new EmitterState) {}
|
||||
|
||||
Emitter::Emitter(std::ostream& stream)
|
||||
: m_pState(new EmitterState), m_stream(stream) {}
|
||||
|
||||
Emitter::~Emitter() {}
|
||||
|
||||
const char* Emitter::c_str() const { return m_stream.str(); }
|
||||
|
||||
std::size_t Emitter::size() const { return m_stream.pos(); }
|
||||
|
||||
// state checking
|
||||
bool Emitter::good() const { return m_pState->good(); }
|
||||
|
||||
const std::string Emitter::GetLastError() const {
|
||||
return m_pState->GetLastError();
|
||||
}
|
||||
|
||||
// global setters
|
||||
bool Emitter::SetOutputCharset(EMITTER_MANIP value) {
|
||||
return m_pState->SetOutputCharset(value, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetStringFormat(EMITTER_MANIP value) {
|
||||
return m_pState->SetStringFormat(value, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
|
||||
bool ok = false;
|
||||
if (m_pState->SetBoolFormat(value, FmtScope::Global))
|
||||
ok = true;
|
||||
if (m_pState->SetBoolCaseFormat(value, FmtScope::Global))
|
||||
ok = true;
|
||||
if (m_pState->SetBoolLengthFormat(value, FmtScope::Global))
|
||||
ok = true;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Emitter::SetIntBase(EMITTER_MANIP value) {
|
||||
return m_pState->SetIntFormat(value, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetSeqFormat(EMITTER_MANIP value) {
|
||||
return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetMapFormat(EMITTER_MANIP value) {
|
||||
bool ok = false;
|
||||
if (m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
|
||||
ok = true;
|
||||
if (m_pState->SetMapKeyFormat(value, FmtScope::Global))
|
||||
ok = true;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Emitter::SetIndent(std::size_t n) {
|
||||
return m_pState->SetIndent(n, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetPreCommentIndent(std::size_t n) {
|
||||
return m_pState->SetPreCommentIndent(n, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetPostCommentIndent(std::size_t n) {
|
||||
return m_pState->SetPostCommentIndent(n, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetFloatPrecision(std::size_t n) {
|
||||
return m_pState->SetFloatPrecision(n, FmtScope::Global);
|
||||
}
|
||||
|
||||
bool Emitter::SetDoublePrecision(std::size_t n) {
|
||||
return m_pState->SetDoublePrecision(n, FmtScope::Global);
|
||||
}
|
||||
|
||||
// SetLocalValue
|
||||
// . Either start/end a group, or set a modifier locally
|
||||
Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
switch (value) {
|
||||
case BeginDoc:
|
||||
EmitBeginDoc();
|
||||
break;
|
||||
case EndDoc:
|
||||
EmitEndDoc();
|
||||
break;
|
||||
case BeginSeq:
|
||||
EmitBeginSeq();
|
||||
break;
|
||||
case EndSeq:
|
||||
EmitEndSeq();
|
||||
break;
|
||||
case BeginMap:
|
||||
EmitBeginMap();
|
||||
break;
|
||||
case EndMap:
|
||||
EmitEndMap();
|
||||
break;
|
||||
case Key:
|
||||
case Value:
|
||||
// deprecated (these can be deduced by the parity of nodes in a map)
|
||||
break;
|
||||
case TagByKind:
|
||||
EmitKindTag();
|
||||
break;
|
||||
case Newline:
|
||||
EmitNewline();
|
||||
break;
|
||||
default:
|
||||
m_pState->SetLocalValue(value);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::SetLocalIndent(const _Indent& indent) {
|
||||
m_pState->SetIndent(indent.value, FmtScope::Local);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::SetLocalPrecision(const _Precision& precision) {
|
||||
if (precision.floatPrecision >= 0)
|
||||
m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
|
||||
if (precision.doublePrecision >= 0)
|
||||
m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// EmitBeginDoc
|
||||
void Emitter::EmitBeginDoc() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
if (m_pState->CurGroupType() != GroupType::NoType) {
|
||||
m_pState->SetError("Unexpected begin document");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pState->HasAnchor() || m_pState->HasTag()) {
|
||||
m_pState->SetError("Unexpected begin document");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_stream.col() > 0)
|
||||
m_stream << "\n";
|
||||
m_stream << "---\n";
|
||||
|
||||
m_pState->StartedDoc();
|
||||
}
|
||||
|
||||
// EmitEndDoc
|
||||
void Emitter::EmitEndDoc() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
if (m_pState->CurGroupType() != GroupType::NoType) {
|
||||
m_pState->SetError("Unexpected begin document");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pState->HasAnchor() || m_pState->HasTag()) {
|
||||
m_pState->SetError("Unexpected begin document");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_stream.col() > 0)
|
||||
m_stream << "\n";
|
||||
m_stream << "...\n";
|
||||
}
|
||||
|
||||
// EmitBeginSeq
|
||||
void Emitter::EmitBeginSeq() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
PrepareNode(m_pState->NextGroupType(GroupType::Seq));
|
||||
|
||||
m_pState->StartedGroup(GroupType::Seq);
|
||||
}
|
||||
|
||||
// EmitEndSeq
|
||||
void Emitter::EmitEndSeq() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_pState->ForceFlow();
|
||||
|
||||
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_stream << "[";
|
||||
m_stream << "]";
|
||||
}
|
||||
|
||||
m_pState->EndedGroup(GroupType::Seq);
|
||||
}
|
||||
|
||||
// EmitBeginMap
|
||||
void Emitter::EmitBeginMap() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
PrepareNode(m_pState->NextGroupType(GroupType::Map));
|
||||
|
||||
m_pState->StartedGroup(GroupType::Map);
|
||||
}
|
||||
|
||||
// EmitEndMap
|
||||
void Emitter::EmitEndMap() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_pState->ForceFlow();
|
||||
|
||||
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_stream << "{";
|
||||
m_stream << "}";
|
||||
}
|
||||
|
||||
m_pState->EndedGroup(GroupType::Map);
|
||||
}
|
||||
|
||||
// EmitNewline
|
||||
void Emitter::EmitNewline() {
|
||||
if (!good())
|
||||
return;
|
||||
|
||||
PrepareNode(EmitterNodeType::NoType);
|
||||
m_stream << "\n";
|
||||
m_pState->SetNonContent();
|
||||
}
|
||||
|
||||
bool Emitter::CanEmitNewline() const { return true; }
|
||||
|
||||
// Put the stream in a state so we can simply write the next node
|
||||
// E.g., if we're in a sequence, write the "- "
|
||||
void Emitter::PrepareNode(EmitterNodeType::value child) {
|
||||
switch (m_pState->CurGroupNodeType()) {
|
||||
case EmitterNodeType::NoType:
|
||||
PrepareTopNode(child);
|
||||
break;
|
||||
case EmitterNodeType::FlowSeq:
|
||||
FlowSeqPrepareNode(child);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
BlockSeqPrepareNode(child);
|
||||
break;
|
||||
case EmitterNodeType::FlowMap:
|
||||
FlowMapPrepareNode(child);
|
||||
break;
|
||||
case EmitterNodeType::BlockMap:
|
||||
BlockMapPrepareNode(child);
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::PrepareTopNode(EmitterNodeType::value child) {
|
||||
if (child == EmitterNodeType::NoType)
|
||||
return;
|
||||
|
||||
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) {
|
||||
if (child != EmitterNodeType::NoType)
|
||||
EmitBeginDoc();
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
// TODO: if we were writing null, and
|
||||
// we wanted it blank, we wouldn't want a space
|
||||
SpaceOrIndentTo(m_pState->HasBegunContent(), 0);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
if (m_pState->HasBegunNode())
|
||||
m_stream << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child) {
|
||||
const std::size_t lastIndent = m_pState->LastIndent();
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(lastIndent);
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_stream << "[";
|
||||
else
|
||||
m_stream << ",";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(
|
||||
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
|
||||
lastIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) {
|
||||
const std::size_t curIndent = m_pState->CurIndent();
|
||||
const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
|
||||
|
||||
if (child == EmitterNodeType::NoType)
|
||||
return;
|
||||
|
||||
if (!m_pState->HasBegunContent()) {
|
||||
if (m_pState->CurGroupChildCount() > 0 || m_stream.comment()) {
|
||||
m_stream << "\n";
|
||||
}
|
||||
m_stream << IndentTo(curIndent);
|
||||
m_stream << "-";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
m_stream << "\n";
|
||||
break;
|
||||
case EmitterNodeType::BlockMap:
|
||||
if (m_pState->HasBegunContent() || m_stream.comment())
|
||||
m_stream << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::FlowMapPrepareNode(EmitterNodeType::value child) {
|
||||
if (m_pState->CurGroupChildCount() % 2 == 0) {
|
||||
if (m_pState->GetMapKeyFormat() == LongKey)
|
||||
m_pState->SetLongKey();
|
||||
|
||||
if (m_pState->CurGroupLongKey())
|
||||
FlowMapPrepareLongKey(child);
|
||||
else
|
||||
FlowMapPrepareSimpleKey(child);
|
||||
} else {
|
||||
if (m_pState->CurGroupLongKey())
|
||||
FlowMapPrepareLongKeyValue(child);
|
||||
else
|
||||
FlowMapPrepareSimpleKeyValue(child);
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::FlowMapPrepareLongKey(EmitterNodeType::value child) {
|
||||
const std::size_t lastIndent = m_pState->LastIndent();
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(lastIndent);
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_stream << "{ ?";
|
||||
else
|
||||
m_stream << ", ?";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(
|
||||
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
|
||||
lastIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::FlowMapPrepareLongKeyValue(EmitterNodeType::value child) {
|
||||
const std::size_t lastIndent = m_pState->LastIndent();
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(lastIndent);
|
||||
m_stream << ":";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(
|
||||
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
|
||||
lastIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::FlowMapPrepareSimpleKey(EmitterNodeType::value child) {
|
||||
const std::size_t lastIndent = m_pState->LastIndent();
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(lastIndent);
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_stream << "{";
|
||||
else
|
||||
m_stream << ",";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(
|
||||
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
|
||||
lastIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
|
||||
const std::size_t lastIndent = m_pState->LastIndent();
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(lastIndent);
|
||||
m_stream << ":";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(
|
||||
m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
|
||||
lastIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
|
||||
if (m_pState->CurGroupChildCount() % 2 == 0) {
|
||||
if (m_pState->GetMapKeyFormat() == LongKey)
|
||||
m_pState->SetLongKey();
|
||||
if (child == EmitterNodeType::BlockSeq ||
|
||||
child == EmitterNodeType::BlockMap)
|
||||
m_pState->SetLongKey();
|
||||
|
||||
if (m_pState->CurGroupLongKey())
|
||||
BlockMapPrepareLongKey(child);
|
||||
else
|
||||
BlockMapPrepareSimpleKey(child);
|
||||
} else {
|
||||
if (m_pState->CurGroupLongKey())
|
||||
BlockMapPrepareLongKeyValue(child);
|
||||
else
|
||||
BlockMapPrepareSimpleKeyValue(child);
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
|
||||
const std::size_t curIndent = m_pState->CurIndent();
|
||||
const std::size_t childCount = m_pState->CurGroupChildCount();
|
||||
|
||||
if (child == EmitterNodeType::NoType)
|
||||
return;
|
||||
|
||||
if (!m_pState->HasBegunContent()) {
|
||||
if (childCount > 0) {
|
||||
m_stream << "\n";
|
||||
}
|
||||
if (m_stream.comment()) {
|
||||
m_stream << "\n";
|
||||
}
|
||||
m_stream << IndentTo(curIndent);
|
||||
m_stream << "?";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(true, curIndent + 1);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
|
||||
const std::size_t curIndent = m_pState->CurIndent();
|
||||
|
||||
if (child == EmitterNodeType::NoType)
|
||||
return;
|
||||
|
||||
if (!m_pState->HasBegunContent()) {
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(curIndent);
|
||||
m_stream << ":";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
SpaceOrIndentTo(true, curIndent + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::BlockMapPrepareSimpleKey(EmitterNodeType::value child) {
|
||||
const std::size_t curIndent = m_pState->CurIndent();
|
||||
const std::size_t childCount = m_pState->CurGroupChildCount();
|
||||
|
||||
if (child == EmitterNodeType::NoType)
|
||||
return;
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
if (childCount > 0) {
|
||||
m_stream << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(m_pState->HasBegunContent(), curIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
|
||||
const std::size_t curIndent = m_pState->CurIndent();
|
||||
const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
|
||||
|
||||
if (!m_pState->HasBegunNode()) {
|
||||
m_stream << ":";
|
||||
}
|
||||
|
||||
switch (child) {
|
||||
case EmitterNodeType::NoType:
|
||||
break;
|
||||
case EmitterNodeType::Property:
|
||||
case EmitterNodeType::Scalar:
|
||||
case EmitterNodeType::FlowSeq:
|
||||
case EmitterNodeType::FlowMap:
|
||||
SpaceOrIndentTo(true, nextIndent);
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
m_stream << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SpaceOrIndentTo
|
||||
// . Prepares for some more content by proper spacing
|
||||
void Emitter::SpaceOrIndentTo(bool requireSpace, std::size_t indent) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
if (m_stream.col() > 0 && requireSpace)
|
||||
m_stream << " ";
|
||||
m_stream << IndentTo(indent);
|
||||
}
|
||||
|
||||
void Emitter::PrepareIntegralStream(std::stringstream& stream) const {
|
||||
|
||||
switch (m_pState->GetIntFormat()) {
|
||||
case Dec:
|
||||
stream << std::dec;
|
||||
break;
|
||||
case Hex:
|
||||
stream << "0x";
|
||||
stream << std::hex;
|
||||
break;
|
||||
case Oct:
|
||||
stream << "0";
|
||||
stream << std::oct;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::StartedScalar() { m_pState->StartedScalar(); }
|
||||
|
||||
// *******************************************************************************************
|
||||
// overloads of Write
|
||||
|
||||
Emitter& Emitter::Write(const std::string& str) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
|
||||
const StringFormat::value strFormat =
|
||||
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
|
||||
m_pState->CurGroupFlowType(), escapeNonAscii);
|
||||
|
||||
if (strFormat == StringFormat::Literal)
|
||||
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
switch (strFormat) {
|
||||
case StringFormat::Plain:
|
||||
m_stream << str;
|
||||
break;
|
||||
case StringFormat::SingleQuoted:
|
||||
Utils::WriteSingleQuotedString(m_stream, str);
|
||||
break;
|
||||
case StringFormat::DoubleQuoted:
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
|
||||
break;
|
||||
case StringFormat::Literal:
|
||||
Utils::WriteLiteralString(m_stream, str,
|
||||
m_pState->CurIndent() + m_pState->GetIndent());
|
||||
break;
|
||||
}
|
||||
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t Emitter::GetFloatPrecision() const {
|
||||
return m_pState->GetFloatPrecision();
|
||||
}
|
||||
|
||||
std::size_t Emitter::GetDoublePrecision() const {
|
||||
return m_pState->GetDoublePrecision();
|
||||
}
|
||||
|
||||
const char* Emitter::ComputeFullBoolName(bool b) const {
|
||||
const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool
|
||||
? YesNoBool
|
||||
: m_pState->GetBoolFormat());
|
||||
const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
|
||||
switch (mainFmt) {
|
||||
case YesNoBool:
|
||||
switch (caseFmt) {
|
||||
case UpperCase:
|
||||
return b ? "YES" : "NO";
|
||||
case CamelCase:
|
||||
return b ? "Yes" : "No";
|
||||
case LowerCase:
|
||||
return b ? "yes" : "no";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OnOffBool:
|
||||
switch (caseFmt) {
|
||||
case UpperCase:
|
||||
return b ? "ON" : "OFF";
|
||||
case CamelCase:
|
||||
return b ? "On" : "Off";
|
||||
case LowerCase:
|
||||
return b ? "on" : "off";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TrueFalseBool:
|
||||
switch (caseFmt) {
|
||||
case UpperCase:
|
||||
return b ? "TRUE" : "FALSE";
|
||||
case CamelCase:
|
||||
return b ? "True" : "False";
|
||||
case LowerCase:
|
||||
return b ? "true" : "false";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return b ? "y" : "n"; // should never get here, but it can't hurt to give
|
||||
// these answers
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(bool b) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
const char* name = ComputeFullBoolName(b);
|
||||
if (m_pState->GetBoolLengthFormat() == ShortBool)
|
||||
m_stream << name[0];
|
||||
else
|
||||
m_stream << name;
|
||||
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(char ch) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
Utils::WriteChar(m_stream, ch);
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Alias& alias) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
if (m_pState->HasAnchor() || m_pState->HasTag()) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
if (!Utils::WriteAlias(m_stream, alias.content)) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Anchor& anchor) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
if (m_pState->HasAnchor()) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrepareNode(EmitterNodeType::Property);
|
||||
|
||||
if (!Utils::WriteAnchor(m_stream, anchor.content)) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_pState->SetAnchor();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Tag& tag) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
if (m_pState->HasTag()) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_TAG);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrepareNode(EmitterNodeType::Property);
|
||||
|
||||
bool success = false;
|
||||
if (tag.type == _Tag::Type::Verbatim)
|
||||
success = Utils::WriteTag(m_stream, tag.content, true);
|
||||
else if (tag.type == _Tag::Type::PrimaryHandle)
|
||||
success = Utils::WriteTag(m_stream, tag.content, false);
|
||||
else
|
||||
success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
|
||||
|
||||
if (!success) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_TAG);
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_pState->SetTag();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Emitter::EmitKindTag() { Write(LocalTag("")); }
|
||||
|
||||
Emitter& Emitter::Write(const _Comment& comment) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::NoType);
|
||||
|
||||
if (m_stream.col() > 0)
|
||||
m_stream << Indentation(m_pState->GetPreCommentIndent());
|
||||
Utils::WriteComment(m_stream, comment.content,
|
||||
m_pState->GetPostCommentIndent());
|
||||
|
||||
m_pState->SetNonContent();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Null& /*null*/) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
m_stream << "~";
|
||||
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const Binary& binary) {
|
||||
Write(SecondaryTag("binary"));
|
||||
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
Utils::WriteBinary(m_stream, binary);
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
365
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitterstate.cpp
Executable file
365
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitterstate.cpp
Executable file
@@ -0,0 +1,365 @@
|
||||
#include <limits>
|
||||
|
||||
#include "emitterstate.h"
|
||||
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||
|
||||
namespace YAML {
|
||||
EmitterState::EmitterState()
|
||||
: m_isGood(true),
|
||||
m_curIndent(0),
|
||||
m_hasAnchor(false),
|
||||
m_hasTag(false),
|
||||
m_hasNonContent(false),
|
||||
m_docCount(0) {
|
||||
// set default global manipulators
|
||||
m_charset.set(EmitNonAscii);
|
||||
m_strFmt.set(Auto);
|
||||
m_boolFmt.set(TrueFalseBool);
|
||||
m_boolLengthFmt.set(LongBool);
|
||||
m_boolCaseFmt.set(LowerCase);
|
||||
m_intFmt.set(Dec);
|
||||
m_indent.set(2);
|
||||
m_preCommentIndent.set(2);
|
||||
m_postCommentIndent.set(1);
|
||||
m_seqFmt.set(Block);
|
||||
m_mapFmt.set(Block);
|
||||
m_mapKeyFmt.set(Auto);
|
||||
m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
|
||||
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
|
||||
}
|
||||
|
||||
EmitterState::~EmitterState() {}
|
||||
|
||||
// SetLocalValue
|
||||
// . We blindly tries to set all possible formatters to this value
|
||||
// . Only the ones that make sense will be accepted
|
||||
void EmitterState::SetLocalValue(EMITTER_MANIP value) {
|
||||
SetOutputCharset(value, FmtScope::Local);
|
||||
SetStringFormat(value, FmtScope::Local);
|
||||
SetBoolFormat(value, FmtScope::Local);
|
||||
SetBoolCaseFormat(value, FmtScope::Local);
|
||||
SetBoolLengthFormat(value, FmtScope::Local);
|
||||
SetIntFormat(value, FmtScope::Local);
|
||||
SetFlowType(GroupType::Seq, value, FmtScope::Local);
|
||||
SetFlowType(GroupType::Map, value, FmtScope::Local);
|
||||
SetMapKeyFormat(value, FmtScope::Local);
|
||||
}
|
||||
|
||||
void EmitterState::SetAnchor() { m_hasAnchor = true; }
|
||||
|
||||
void EmitterState::SetTag() { m_hasTag = true; }
|
||||
|
||||
void EmitterState::SetNonContent() { m_hasNonContent = true; }
|
||||
|
||||
void EmitterState::SetLongKey() {
|
||||
assert(!m_groups.empty());
|
||||
if (m_groups.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_groups.back()->type == GroupType::Map);
|
||||
m_groups.back()->longKey = true;
|
||||
}
|
||||
|
||||
void EmitterState::ForceFlow() {
|
||||
assert(!m_groups.empty());
|
||||
if (m_groups.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_groups.back()->flowType = FlowType::Flow;
|
||||
}
|
||||
|
||||
void EmitterState::StartedNode() {
|
||||
if (m_groups.empty()) {
|
||||
m_docCount++;
|
||||
} else {
|
||||
m_groups.back()->childCount++;
|
||||
if (m_groups.back()->childCount % 2 == 0) {
|
||||
m_groups.back()->longKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_hasAnchor = false;
|
||||
m_hasTag = false;
|
||||
m_hasNonContent = false;
|
||||
}
|
||||
|
||||
EmitterNodeType::value EmitterState::NextGroupType(
|
||||
GroupType::value type) const {
|
||||
if (type == GroupType::Seq) {
|
||||
if (GetFlowType(type) == Block)
|
||||
return EmitterNodeType::BlockSeq;
|
||||
else
|
||||
return EmitterNodeType::FlowSeq;
|
||||
} else {
|
||||
if (GetFlowType(type) == Block)
|
||||
return EmitterNodeType::BlockMap;
|
||||
else
|
||||
return EmitterNodeType::FlowMap;
|
||||
}
|
||||
|
||||
// can't happen
|
||||
assert(false);
|
||||
return EmitterNodeType::NoType;
|
||||
}
|
||||
|
||||
void EmitterState::StartedDoc() {
|
||||
m_hasAnchor = false;
|
||||
m_hasTag = false;
|
||||
m_hasNonContent = false;
|
||||
}
|
||||
|
||||
void EmitterState::EndedDoc() {
|
||||
m_hasAnchor = false;
|
||||
m_hasTag = false;
|
||||
m_hasNonContent = false;
|
||||
}
|
||||
|
||||
void EmitterState::StartedScalar() {
|
||||
StartedNode();
|
||||
ClearModifiedSettings();
|
||||
}
|
||||
|
||||
void EmitterState::StartedGroup(GroupType::value type) {
|
||||
StartedNode();
|
||||
|
||||
const std::size_t lastGroupIndent =
|
||||
(m_groups.empty() ? 0 : m_groups.back()->indent);
|
||||
m_curIndent += lastGroupIndent;
|
||||
|
||||
// TODO: Create move constructors for settings types to simplify transfer
|
||||
std::unique_ptr<Group> pGroup(new Group(type));
|
||||
|
||||
// transfer settings (which last until this group is done)
|
||||
//
|
||||
// NB: if pGroup->modifiedSettings == m_modifiedSettings,
|
||||
// m_modifiedSettings is not changed!
|
||||
pGroup->modifiedSettings = std::move(m_modifiedSettings);
|
||||
|
||||
// set up group
|
||||
if (GetFlowType(type) == Block) {
|
||||
pGroup->flowType = FlowType::Block;
|
||||
} else {
|
||||
pGroup->flowType = FlowType::Flow;
|
||||
}
|
||||
pGroup->indent = GetIndent();
|
||||
|
||||
m_groups.push_back(std::move(pGroup));
|
||||
}
|
||||
|
||||
void EmitterState::EndedGroup(GroupType::value type) {
|
||||
if (m_groups.empty()) {
|
||||
if (type == GroupType::Seq) {
|
||||
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
|
||||
} else {
|
||||
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
// get rid of the current group
|
||||
{
|
||||
std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
|
||||
m_groups.pop_back();
|
||||
if (pFinishedGroup->type != type) {
|
||||
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
// reset old settings
|
||||
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
|
||||
assert(m_curIndent >= lastIndent);
|
||||
m_curIndent -= lastIndent;
|
||||
|
||||
// some global settings that we changed may have been overridden
|
||||
// by a local setting we just popped, so we need to restore them
|
||||
m_globalModifiedSettings.restore();
|
||||
|
||||
ClearModifiedSettings();
|
||||
}
|
||||
|
||||
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
|
||||
if (m_groups.empty()) {
|
||||
return EmitterNodeType::NoType;
|
||||
}
|
||||
|
||||
return m_groups.back()->NodeType();
|
||||
}
|
||||
|
||||
GroupType::value EmitterState::CurGroupType() const {
|
||||
return m_groups.empty() ? GroupType::NoType : m_groups.back()->type;
|
||||
}
|
||||
|
||||
FlowType::value EmitterState::CurGroupFlowType() const {
|
||||
return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
|
||||
}
|
||||
|
||||
std::size_t EmitterState::CurGroupIndent() const {
|
||||
return m_groups.empty() ? 0 : m_groups.back()->indent;
|
||||
}
|
||||
|
||||
std::size_t EmitterState::CurGroupChildCount() const {
|
||||
return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
|
||||
}
|
||||
|
||||
bool EmitterState::CurGroupLongKey() const {
|
||||
return m_groups.empty() ? false : m_groups.back()->longKey;
|
||||
}
|
||||
|
||||
std::size_t EmitterState::LastIndent() const {
|
||||
if (m_groups.size() <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_curIndent - m_groups[m_groups.size() - 2]->indent;
|
||||
}
|
||||
|
||||
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
|
||||
|
||||
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
|
||||
FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case EmitNonAscii:
|
||||
case EscapeNonAscii:
|
||||
_Set(m_charset, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case Auto:
|
||||
case SingleQuoted:
|
||||
case DoubleQuoted:
|
||||
case Literal:
|
||||
_Set(m_strFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case OnOffBool:
|
||||
case TrueFalseBool:
|
||||
case YesNoBool:
|
||||
_Set(m_boolFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value,
|
||||
FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case LongBool:
|
||||
case ShortBool:
|
||||
_Set(m_boolLengthFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
|
||||
FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case UpperCase:
|
||||
case LowerCase:
|
||||
case CamelCase:
|
||||
_Set(m_boolCaseFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case Dec:
|
||||
case Hex:
|
||||
case Oct:
|
||||
_Set(m_intFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetIndent(std::size_t value, FmtScope::value scope) {
|
||||
if (value <= 1)
|
||||
return false;
|
||||
|
||||
_Set(m_indent, value, scope);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitterState::SetPreCommentIndent(std::size_t value,
|
||||
FmtScope::value scope) {
|
||||
if (value == 0)
|
||||
return false;
|
||||
|
||||
_Set(m_preCommentIndent, value, scope);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitterState::SetPostCommentIndent(std::size_t value,
|
||||
FmtScope::value scope) {
|
||||
if (value == 0)
|
||||
return false;
|
||||
|
||||
_Set(m_postCommentIndent, value, scope);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
|
||||
FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case Block:
|
||||
case Flow:
|
||||
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const {
|
||||
// force flow style if we're currently in a flow
|
||||
if (CurGroupFlowType() == FlowType::Flow)
|
||||
return Flow;
|
||||
|
||||
// otherwise, go with what's asked of us
|
||||
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
|
||||
}
|
||||
|
||||
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case Auto:
|
||||
case LongKey:
|
||||
_Set(m_mapKeyFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
|
||||
if (value > std::numeric_limits<float>::digits10 + 1)
|
||||
return false;
|
||||
_Set(m_floatPrecision, value, scope);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitterState::SetDoublePrecision(std::size_t value,
|
||||
FmtScope::value scope) {
|
||||
if (value > std::numeric_limits<double>::digits10 + 1)
|
||||
return false;
|
||||
_Set(m_doublePrecision, value, scope);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
203
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitterstate.h
Executable file
203
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitterstate.h
Executable file
@@ -0,0 +1,203 @@
|
||||
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "setting.h"
|
||||
#include "yaml-cpp/emitterdef.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
struct FmtScope {
|
||||
enum value { Local, Global };
|
||||
};
|
||||
struct GroupType {
|
||||
enum value { NoType, Seq, Map };
|
||||
};
|
||||
struct FlowType {
|
||||
enum value { NoType, Flow, Block };
|
||||
};
|
||||
|
||||
class EmitterState {
|
||||
public:
|
||||
EmitterState();
|
||||
~EmitterState();
|
||||
|
||||
// basic state checking
|
||||
bool good() const { return m_isGood; }
|
||||
const std::string GetLastError() const { return m_lastError; }
|
||||
void SetError(const std::string& error) {
|
||||
m_isGood = false;
|
||||
m_lastError = error;
|
||||
}
|
||||
|
||||
// node handling
|
||||
void SetAnchor();
|
||||
void SetTag();
|
||||
void SetNonContent();
|
||||
void SetLongKey();
|
||||
void ForceFlow();
|
||||
void StartedDoc();
|
||||
void EndedDoc();
|
||||
void StartedScalar();
|
||||
void StartedGroup(GroupType::value type);
|
||||
void EndedGroup(GroupType::value type);
|
||||
|
||||
EmitterNodeType::value NextGroupType(GroupType::value type) const;
|
||||
EmitterNodeType::value CurGroupNodeType() const;
|
||||
|
||||
GroupType::value CurGroupType() const;
|
||||
FlowType::value CurGroupFlowType() const;
|
||||
std::size_t CurGroupIndent() const;
|
||||
std::size_t CurGroupChildCount() const;
|
||||
bool CurGroupLongKey() const;
|
||||
|
||||
std::size_t LastIndent() const;
|
||||
std::size_t CurIndent() const { return m_curIndent; }
|
||||
bool HasAnchor() const { return m_hasAnchor; }
|
||||
bool HasTag() const { return m_hasTag; }
|
||||
bool HasBegunNode() const {
|
||||
return m_hasAnchor || m_hasTag || m_hasNonContent;
|
||||
}
|
||||
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
|
||||
|
||||
void ClearModifiedSettings();
|
||||
|
||||
// formatters
|
||||
void SetLocalValue(EMITTER_MANIP value);
|
||||
|
||||
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
|
||||
|
||||
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
|
||||
|
||||
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
|
||||
|
||||
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
|
||||
|
||||
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
|
||||
|
||||
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
|
||||
|
||||
bool SetIndent(std::size_t value, FmtScope::value scope);
|
||||
std::size_t GetIndent() const { return m_indent.get(); }
|
||||
|
||||
bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
|
||||
std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); }
|
||||
bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
|
||||
std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
|
||||
|
||||
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
|
||||
FmtScope::value scope);
|
||||
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
|
||||
|
||||
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
|
||||
|
||||
bool SetFloatPrecision(std::size_t value, FmtScope::value scope);
|
||||
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
|
||||
bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
|
||||
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
|
||||
|
||||
void StartedNode();
|
||||
|
||||
private:
|
||||
// basic state ok?
|
||||
bool m_isGood;
|
||||
std::string m_lastError;
|
||||
|
||||
// other state
|
||||
Setting<EMITTER_MANIP> m_charset;
|
||||
Setting<EMITTER_MANIP> m_strFmt;
|
||||
Setting<EMITTER_MANIP> m_boolFmt;
|
||||
Setting<EMITTER_MANIP> m_boolLengthFmt;
|
||||
Setting<EMITTER_MANIP> m_boolCaseFmt;
|
||||
Setting<EMITTER_MANIP> m_intFmt;
|
||||
Setting<std::size_t> m_indent;
|
||||
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
|
||||
Setting<EMITTER_MANIP> m_seqFmt;
|
||||
Setting<EMITTER_MANIP> m_mapFmt;
|
||||
Setting<EMITTER_MANIP> m_mapKeyFmt;
|
||||
Setting<std::size_t> m_floatPrecision;
|
||||
Setting<std::size_t> m_doublePrecision;
|
||||
|
||||
SettingChanges m_modifiedSettings;
|
||||
SettingChanges m_globalModifiedSettings;
|
||||
|
||||
struct Group {
|
||||
explicit Group(GroupType::value type_)
|
||||
: type(type_), indent(0), childCount(0), longKey(false) {}
|
||||
|
||||
GroupType::value type;
|
||||
FlowType::value flowType;
|
||||
std::size_t indent;
|
||||
std::size_t childCount;
|
||||
bool longKey;
|
||||
|
||||
SettingChanges modifiedSettings;
|
||||
|
||||
EmitterNodeType::value NodeType() const {
|
||||
if (type == GroupType::Seq) {
|
||||
if (flowType == FlowType::Flow)
|
||||
return EmitterNodeType::FlowSeq;
|
||||
else
|
||||
return EmitterNodeType::BlockSeq;
|
||||
} else {
|
||||
if (flowType == FlowType::Flow)
|
||||
return EmitterNodeType::FlowMap;
|
||||
else
|
||||
return EmitterNodeType::BlockMap;
|
||||
}
|
||||
|
||||
// can't get here
|
||||
assert(false);
|
||||
return EmitterNodeType::NoType;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<Group>> m_groups;
|
||||
std::size_t m_curIndent;
|
||||
bool m_hasAnchor;
|
||||
bool m_hasTag;
|
||||
bool m_hasNonContent;
|
||||
std::size_t m_docCount;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
|
||||
switch (scope) {
|
||||
case FmtScope::Local:
|
||||
m_modifiedSettings.push(fmt.set(value));
|
||||
break;
|
||||
case FmtScope::Global:
|
||||
fmt.set(value);
|
||||
m_globalModifiedSettings.push(
|
||||
fmt.set(value)); // this pushes an identity set, so when we restore,
|
||||
// it restores to the value here, and not the previous one
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
483
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitterutils.cpp
Executable file
483
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/emitterutils.cpp
Executable file
@@ -0,0 +1,483 @@
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "emitterutils.h"
|
||||
#include "exp.h"
|
||||
#include "indentation.h"
|
||||
#include "regex_yaml.h"
|
||||
#include "regeximpl.h"
|
||||
#include "stringsource.h"
|
||||
#include "yaml-cpp/binary.h" // IWYU pragma: keep
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace Utils {
|
||||
namespace {
|
||||
enum { REPLACEMENT_CHARACTER = 0xFFFD };
|
||||
|
||||
bool IsAnchorChar(int ch) { // test for ns-anchor-char
|
||||
switch (ch) {
|
||||
case ',':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}': // c-flow-indicator
|
||||
case ' ':
|
||||
case '\t': // s-white
|
||||
case 0xFEFF: // c-byte-order-mark
|
||||
case 0xA:
|
||||
case 0xD: // b-char
|
||||
return false;
|
||||
case 0x85:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch < 0x20) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ch < 0x7E) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch < 0xA0) {
|
||||
return false;
|
||||
}
|
||||
if (ch >= 0xD800 && ch <= 0xDFFF) {
|
||||
return false;
|
||||
}
|
||||
if ((ch & 0xFFFE) == 0xFFFE) {
|
||||
return false;
|
||||
}
|
||||
if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) {
|
||||
return false;
|
||||
}
|
||||
if (ch > 0x10FFFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Utf8BytesIndicated(char ch) {
|
||||
int byteVal = static_cast<unsigned char>(ch);
|
||||
switch (byteVal >> 4) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
return 1;
|
||||
case 12:
|
||||
case 13:
|
||||
return 2;
|
||||
case 14:
|
||||
return 3;
|
||||
case 15:
|
||||
return 4;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
||||
|
||||
bool GetNextCodePointAndAdvance(int& codePoint,
|
||||
std::string::const_iterator& first,
|
||||
std::string::const_iterator last) {
|
||||
if (first == last)
|
||||
return false;
|
||||
|
||||
int nBytes = Utf8BytesIndicated(*first);
|
||||
if (nBytes < 1) {
|
||||
// Bad lead byte
|
||||
++first;
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nBytes == 1) {
|
||||
codePoint = *first++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Gather bits from trailing bytes
|
||||
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
|
||||
++first;
|
||||
--nBytes;
|
||||
for (; nBytes > 0; ++first, --nBytes) {
|
||||
if ((first == last) || !IsTrailingByte(*first)) {
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
break;
|
||||
}
|
||||
codePoint <<= 6;
|
||||
codePoint |= *first & 0x3F;
|
||||
}
|
||||
|
||||
// Check for illegal code points
|
||||
if (codePoint > 0x10FFFF)
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
else if ((codePoint & 0xFFFE) == 0xFFFE)
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
||||
if (codePoint < 0 || codePoint > 0x10FFFF) {
|
||||
codePoint = REPLACEMENT_CHARACTER;
|
||||
}
|
||||
if (codePoint < 0x7F) {
|
||||
out << static_cast<char>(codePoint);
|
||||
} else if (codePoint < 0x7FF) {
|
||||
out << static_cast<char>(0xC0 | (codePoint >> 6))
|
||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||
} else if (codePoint < 0xFFFF) {
|
||||
out << static_cast<char>(0xE0 | (codePoint >> 12))
|
||||
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||
} else {
|
||||
out << static_cast<char>(0xF0 | (codePoint >> 18))
|
||||
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
|
||||
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
||||
bool allowOnlyAscii) {
|
||||
// check against null
|
||||
if (IsNullString(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the start
|
||||
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
||||
: Exp::PlainScalar());
|
||||
if (!start.Matches(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// and check the end for plain whitespace (which can't be faithfully kept in a
|
||||
// plain scalar)
|
||||
if (!str.empty() && *str.rbegin() == ' ') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// then check until something is disallowed
|
||||
static const RegEx& disallowed_flow =
|
||||
Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) ||
|
||||
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
|
||||
Exp::Tab();
|
||||
static const RegEx& disallowed_block =
|
||||
Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) ||
|
||||
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
|
||||
Exp::Tab();
|
||||
const RegEx& disallowed =
|
||||
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||
|
||||
StringCharSource buffer(str.c_str(), str.size());
|
||||
while (buffer) {
|
||||
if (disallowed.Matches(buffer)) {
|
||||
return false;
|
||||
}
|
||||
if (allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0]))) {
|
||||
return false;
|
||||
}
|
||||
++buffer;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
||||
// TODO: check for non-printable characters?
|
||||
for (std::size_t i = 0; i < str.size(); i++) {
|
||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
||||
return false;
|
||||
}
|
||||
if (str[i] == '\n') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
||||
bool escapeNonAscii) {
|
||||
if (flowType == FlowType::Flow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: check for non-printable characters?
|
||||
for (std::size_t i = 0; i < str.size(); i++) {
|
||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
|
||||
static const char hexDigits[] = "0123456789abcdef";
|
||||
|
||||
out << "\\";
|
||||
int digits = 8;
|
||||
if (codePoint < 0xFF) {
|
||||
out << "x";
|
||||
digits = 2;
|
||||
} else if (codePoint < 0xFFFF) {
|
||||
out << "u";
|
||||
digits = 4;
|
||||
} else {
|
||||
out << "U";
|
||||
digits = 8;
|
||||
}
|
||||
|
||||
// Write digits into the escape sequence
|
||||
for (; digits > 0; --digits)
|
||||
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
||||
}
|
||||
|
||||
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (!IsAnchorChar(codePoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
EMITTER_MANIP strFormat,
|
||||
FlowType::value flowType,
|
||||
bool escapeNonAscii) {
|
||||
switch (strFormat) {
|
||||
case Auto:
|
||||
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
|
||||
return StringFormat::Plain;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
case SingleQuoted:
|
||||
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
|
||||
return StringFormat::SingleQuoted;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
case DoubleQuoted:
|
||||
return StringFormat::DoubleQuoted;
|
||||
case Literal:
|
||||
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
|
||||
return StringFormat::Literal;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return StringFormat::DoubleQuoted;
|
||||
}
|
||||
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
||||
out << "'";
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
return false; // We can't handle a new line and the attendant indentation
|
||||
// yet
|
||||
}
|
||||
|
||||
if (codePoint == '\'') {
|
||||
out << "''";
|
||||
} else {
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
}
|
||||
out << "'";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
bool escapeNonAscii) {
|
||||
out << "\"";
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
switch (codePoint) {
|
||||
case '\"':
|
||||
out << "\\\"";
|
||||
break;
|
||||
case '\\':
|
||||
out << "\\\\";
|
||||
break;
|
||||
case '\n':
|
||||
out << "\\n";
|
||||
break;
|
||||
case '\t':
|
||||
out << "\\t";
|
||||
break;
|
||||
case '\r':
|
||||
out << "\\r";
|
||||
break;
|
||||
case '\b':
|
||||
out << "\\b";
|
||||
break;
|
||||
default:
|
||||
if (codePoint < 0x20 ||
|
||||
(codePoint >= 0x80 &&
|
||||
codePoint <= 0xA0)) { // Control characters and non-breaking space
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
|
||||
// escaped (YAML 1.2, sec. 5.2)
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||
} else if (escapeNonAscii && codePoint > 0x7E) {
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||
} else {
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
out << "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t indent) {
|
||||
out << "|\n";
|
||||
out << IndentTo(indent);
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n" << IndentTo(indent);
|
||||
} else {
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteChar(ostream_wrapper& out, char ch) {
|
||||
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
|
||||
out << ch;
|
||||
} else if (ch == '\"') {
|
||||
out << "\"\\\"\"";
|
||||
} else if (ch == '\t') {
|
||||
out << "\"\\t\"";
|
||||
} else if (ch == '\n') {
|
||||
out << "\"\\n\"";
|
||||
} else if (ch == '\b') {
|
||||
out << "\"\\b\"";
|
||||
} else if (ch == '\\') {
|
||||
out << "\"\\\\\"";
|
||||
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
|
||||
out << "\"" << ch << "\"";
|
||||
} else {
|
||||
out << "\"";
|
||||
WriteDoubleQuoteEscapeSequence(out, ch);
|
||||
out << "\"";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t postCommentIndent) {
|
||||
const std::size_t curIndent = out.col();
|
||||
out << "#" << Indentation(postCommentIndent);
|
||||
out.set_comment();
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n" << IndentTo(curIndent) << "#"
|
||||
<< Indentation(postCommentIndent);
|
||||
out.set_comment();
|
||||
} else {
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
|
||||
out << "*";
|
||||
return WriteAliasName(out, str);
|
||||
}
|
||||
|
||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
|
||||
out << "&";
|
||||
return WriteAliasName(out, str);
|
||||
}
|
||||
|
||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
||||
out << (verbatim ? "!<" : "!");
|
||||
StringCharSource buffer(str.c_str(), str.size());
|
||||
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
|
||||
while (buffer) {
|
||||
int n = reValid.Match(buffer);
|
||||
if (n <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (--n >= 0) {
|
||||
out << buffer[0];
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
if (verbatim) {
|
||||
out << ">";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
const std::string& tag) {
|
||||
out << "!";
|
||||
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
|
||||
while (prefixBuffer) {
|
||||
int n = Exp::URI().Match(prefixBuffer);
|
||||
if (n <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (--n >= 0) {
|
||||
out << prefixBuffer[0];
|
||||
++prefixBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
out << "!";
|
||||
StringCharSource tagBuffer(tag.c_str(), tag.size());
|
||||
while (tagBuffer) {
|
||||
int n = Exp::Tag().Match(tagBuffer);
|
||||
if (n <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (--n >= 0) {
|
||||
out << tagBuffer[0];
|
||||
++tagBuffer;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
||||
false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "emitterstate.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
|
||||
namespace YAML {
|
||||
class ostream_wrapper;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
|
||||
struct StringFormat {
|
||||
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
|
||||
};
|
||||
|
||||
namespace Utils {
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
EMITTER_MANIP strFormat,
|
||||
FlowType::value flowType,
|
||||
bool escapeNonAscii);
|
||||
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
bool escapeNonAscii);
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t indent);
|
||||
bool WriteChar(ostream_wrapper& out, char ch);
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t postCommentIndent);
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
const std::string& tag);
|
||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "yaml-cpp/exceptions.h"
|
||||
|
||||
// This is here for compatibility with older versions of Visual Studio
|
||||
// which don't support noexcept
|
||||
#ifdef _MSC_VER
|
||||
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
||||
#else
|
||||
#define YAML_CPP_NOEXCEPT noexcept
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
|
||||
// These destructors are defined out-of-line so the vtable is only emitted once.
|
||||
Exception::~Exception() YAML_CPP_NOEXCEPT {}
|
||||
ParserException::~ParserException() YAML_CPP_NOEXCEPT {}
|
||||
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT {}
|
||||
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT {}
|
||||
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT {}
|
||||
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT {}
|
||||
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT {}
|
||||
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT {}
|
||||
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT {}
|
||||
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT {}
|
||||
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT {}
|
||||
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT {}
|
||||
BadFile::~BadFile() YAML_CPP_NOEXCEPT {}
|
||||
}
|
||||
|
||||
#undef YAML_CPP_NOEXCEPT
|
||||
|
||||
|
||||
136
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/exp.cpp
Executable file
136
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/exp.cpp
Executable file
@@ -0,0 +1,136 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "exp.h"
|
||||
#include "stream.h"
|
||||
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
namespace Exp {
|
||||
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
||||
unsigned value = 0;
|
||||
for (std::size_t i = 0; i < str.size(); i++) {
|
||||
char ch = str[i];
|
||||
int digit = 0;
|
||||
if ('a' <= ch && ch <= 'f')
|
||||
digit = ch - 'a' + 10;
|
||||
else if ('A' <= ch && ch <= 'F')
|
||||
digit = ch - 'A' + 10;
|
||||
else if ('0' <= ch && ch <= '9')
|
||||
digit = ch - '0';
|
||||
else
|
||||
throw ParserException(mark, ErrorMsg::INVALID_HEX);
|
||||
|
||||
value = (value << 4) + digit;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string Str(unsigned ch) { return std::string(1, static_cast<char>(ch)); }
|
||||
|
||||
// Escape
|
||||
// . Translates the next 'codeLength' characters into a hex number and returns
|
||||
// the result.
|
||||
// . Throws if it's not actually hex.
|
||||
std::string Escape(Stream& in, int codeLength) {
|
||||
// grab string
|
||||
std::string str;
|
||||
for (int i = 0; i < codeLength; i++)
|
||||
str += in.get();
|
||||
|
||||
// get the value
|
||||
unsigned value = ParseHex(str, in.mark());
|
||||
|
||||
// legal unicode?
|
||||
if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
|
||||
std::stringstream msg;
|
||||
msg << ErrorMsg::INVALID_UNICODE << value;
|
||||
throw ParserException(in.mark(), msg.str());
|
||||
}
|
||||
|
||||
// now break it up into chars
|
||||
if (value <= 0x7F)
|
||||
return Str(value);
|
||||
else if (value <= 0x7FF)
|
||||
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
|
||||
else if (value <= 0xFFFF)
|
||||
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
|
||||
Str(0x80 + (value & 0x3F));
|
||||
else
|
||||
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
|
||||
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
|
||||
}
|
||||
|
||||
// Escape
|
||||
// . Escapes the sequence starting 'in' (it must begin with a '\' or single
|
||||
// quote)
|
||||
// and returns the result.
|
||||
// . Throws if it's an unknown escape character.
|
||||
std::string Escape(Stream& in) {
|
||||
// eat slash
|
||||
char escape = in.get();
|
||||
|
||||
// switch on escape character
|
||||
char ch = in.get();
|
||||
|
||||
// first do single quote, since it's easier
|
||||
if (escape == '\'' && ch == '\'')
|
||||
return "\'";
|
||||
|
||||
// now do the slash (we're not gonna check if it's a slash - you better pass
|
||||
// one!)
|
||||
switch (ch) {
|
||||
case '0':
|
||||
return std::string(1, '\x00');
|
||||
case 'a':
|
||||
return "\x07";
|
||||
case 'b':
|
||||
return "\x08";
|
||||
case 't':
|
||||
case '\t':
|
||||
return "\x09";
|
||||
case 'n':
|
||||
return "\x0A";
|
||||
case 'v':
|
||||
return "\x0B";
|
||||
case 'f':
|
||||
return "\x0C";
|
||||
case 'r':
|
||||
return "\x0D";
|
||||
case 'e':
|
||||
return "\x1B";
|
||||
case ' ':
|
||||
return "\x20";
|
||||
case '\"':
|
||||
return "\"";
|
||||
case '\'':
|
||||
return "\'";
|
||||
case '\\':
|
||||
return "\\";
|
||||
case '/':
|
||||
return "/";
|
||||
case 'N':
|
||||
return "\x85";
|
||||
case '_':
|
||||
return "\xA0";
|
||||
case 'L':
|
||||
return "\xE2\x80\xA8"; // LS (#x2028)
|
||||
case 'P':
|
||||
return "\xE2\x80\xA9"; // PS (#x2029)
|
||||
case 'x':
|
||||
return Escape(in, 2);
|
||||
case 'u':
|
||||
return Escape(in, 4);
|
||||
case 'U':
|
||||
return Escape(in, 8);
|
||||
}
|
||||
|
||||
std::stringstream msg;
|
||||
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
222
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/exp.h
Executable file
222
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/exp.h
Executable file
@@ -0,0 +1,222 @@
|
||||
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <ios>
|
||||
#include <string>
|
||||
|
||||
#include "regex_yaml.h"
|
||||
#include "stream.h"
|
||||
|
||||
namespace YAML {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Here we store a bunch of expressions for matching different parts of the
|
||||
// file.
|
||||
|
||||
namespace Exp {
|
||||
// misc
|
||||
inline const RegEx& Empty() {
|
||||
static const RegEx e;
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Space() {
|
||||
static const RegEx e = RegEx(' ');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Tab() {
|
||||
static const RegEx e = RegEx('\t');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Blank() {
|
||||
static const RegEx e = Space() || Tab();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Break() {
|
||||
static const RegEx e = RegEx('\n') || RegEx("\r\n");
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& BlankOrBreak() {
|
||||
static const RegEx e = Blank() || Break();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Digit() {
|
||||
static const RegEx e = RegEx('0', '9');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Alpha() {
|
||||
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& AlphaNumeric() {
|
||||
static const RegEx e = Alpha() || Digit();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Word() {
|
||||
static const RegEx e = AlphaNumeric() || RegEx('-');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Hex() {
|
||||
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
|
||||
return e;
|
||||
}
|
||||
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
|
||||
// 5.1)
|
||||
inline const RegEx& NotPrintable() {
|
||||
static const RegEx e =
|
||||
RegEx(0) ||
|
||||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
|
||||
RegEx(0x0E, 0x1F) ||
|
||||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Utf8_ByteOrderMark() {
|
||||
static const RegEx e = RegEx("\xEF\xBB\xBF");
|
||||
return e;
|
||||
}
|
||||
|
||||
// actual tags
|
||||
|
||||
inline const RegEx& DocStart() {
|
||||
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& DocEnd() {
|
||||
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& DocIndicator() {
|
||||
static const RegEx e = DocStart() || DocEnd();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& BlockEntry() {
|
||||
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Key() {
|
||||
static const RegEx e = RegEx('?') + BlankOrBreak();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& KeyInFlow() {
|
||||
static const RegEx e = RegEx('?') + BlankOrBreak();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Value() {
|
||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& ValueInFlow() {
|
||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& ValueInJSONFlow() {
|
||||
static const RegEx e = RegEx(':');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx Comment() {
|
||||
static const RegEx e = RegEx('#');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Anchor() {
|
||||
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& AnchorEnd() {
|
||||
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& URI() {
|
||||
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) ||
|
||||
(RegEx('%') + Hex() + Hex());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Tag() {
|
||||
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) ||
|
||||
(RegEx('%') + Hex() + Hex());
|
||||
return e;
|
||||
}
|
||||
|
||||
// Plain scalar rules:
|
||||
// . Cannot start with a blank.
|
||||
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
|
||||
// . In the block context - ? : must be not be followed with a space.
|
||||
// . In the flow context ? is illegal and : and - must not be followed with a
|
||||
// space.
|
||||
inline const RegEx& PlainScalar() {
|
||||
static const RegEx e =
|
||||
!(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) ||
|
||||
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& PlainScalarInFlow() {
|
||||
static const RegEx e =
|
||||
!(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) ||
|
||||
(RegEx("-:", REGEX_OR) + Blank()));
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& EndScalar() {
|
||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& EndScalarInFlow() {
|
||||
static const RegEx e =
|
||||
(RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) ||
|
||||
RegEx(",?[]{}", REGEX_OR);
|
||||
return e;
|
||||
}
|
||||
|
||||
inline const RegEx& ScanScalarEndInFlow() {
|
||||
static const RegEx e = (EndScalarInFlow() || (BlankOrBreak() + Comment()));
|
||||
return e;
|
||||
}
|
||||
|
||||
inline const RegEx& ScanScalarEnd() {
|
||||
static const RegEx e = EndScalar() || (BlankOrBreak() + Comment());
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& EscSingleQuote() {
|
||||
static const RegEx e = RegEx("\'\'");
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& EscBreak() {
|
||||
static const RegEx e = RegEx('\\') + Break();
|
||||
return e;
|
||||
}
|
||||
|
||||
inline const RegEx& ChompIndicator() {
|
||||
static const RegEx e = RegEx("+-", REGEX_OR);
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Chomp() {
|
||||
static const RegEx e = (ChompIndicator() + Digit()) ||
|
||||
(Digit() + ChompIndicator()) || ChompIndicator() ||
|
||||
Digit();
|
||||
return e;
|
||||
}
|
||||
|
||||
// and some functions
|
||||
std::string Escape(Stream& in);
|
||||
} // namespace Exp
|
||||
|
||||
namespace Keys {
|
||||
const char Directive = '%';
|
||||
const char FlowSeqStart = '[';
|
||||
const char FlowSeqEnd = ']';
|
||||
const char FlowMapStart = '{';
|
||||
const char FlowMapEnd = '}';
|
||||
const char FlowEntry = ',';
|
||||
const char Alias = '*';
|
||||
const char Anchor = '&';
|
||||
const char Tag = '!';
|
||||
const char LiteralScalar = '|';
|
||||
const char FoldedScalar = '>';
|
||||
const char VerbatimTagStart = '<';
|
||||
const char VerbatimTagEnd = '>';
|
||||
} // namespace Keys
|
||||
} // namespace YAML
|
||||
|
||||
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
|
||||
namespace YAML {
|
||||
struct Indentation {
|
||||
Indentation(std::size_t n_) : n(n_) {}
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
inline ostream_wrapper& operator<<(ostream_wrapper& out,
|
||||
const Indentation& indent) {
|
||||
for (std::size_t i = 0; i < indent.n; i++)
|
||||
out << ' ';
|
||||
return out;
|
||||
}
|
||||
|
||||
struct IndentTo {
|
||||
IndentTo(std::size_t n_) : n(n_) {}
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
inline ostream_wrapper& operator<<(ostream_wrapper& out,
|
||||
const IndentTo& indent) {
|
||||
while (out.col() < indent.n)
|
||||
out << ' ';
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
26
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/memory.cpp
Executable file
26
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/memory.cpp
Executable file
@@ -0,0 +1,26 @@
|
||||
#include "yaml-cpp/node/detail/memory.h"
|
||||
#include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
|
||||
void memory_holder::merge(memory_holder& rhs) {
|
||||
if (m_pMemory == rhs.m_pMemory)
|
||||
return;
|
||||
|
||||
m_pMemory->merge(*rhs.m_pMemory);
|
||||
rhs.m_pMemory = m_pMemory;
|
||||
}
|
||||
|
||||
node& memory::create_node() {
|
||||
shared_node pNode(new node);
|
||||
m_nodes.insert(pNode);
|
||||
return *pNode;
|
||||
}
|
||||
|
||||
void memory::merge(const memory& rhs) {
|
||||
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
12
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/node.cpp
Executable file
12
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/node.cpp
Executable file
@@ -0,0 +1,12 @@
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "nodebuilder.h"
|
||||
#include "nodeevents.h"
|
||||
|
||||
namespace YAML {
|
||||
Node Clone(const Node& node) {
|
||||
NodeEvents events(node);
|
||||
NodeBuilder builder;
|
||||
events.Emit(builder);
|
||||
return builder.Root();
|
||||
}
|
||||
}
|
||||
300
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/node_data.cpp
Executable file
300
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/node_data.cpp
Executable file
@@ -0,0 +1,300 @@
|
||||
#include <assert.h>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
#include "yaml-cpp/exceptions.h"
|
||||
#include "yaml-cpp/node/detail/memory.h"
|
||||
#include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
|
||||
#include "yaml-cpp/node/detail/node_data.h"
|
||||
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
|
||||
std::string node_data::empty_scalar;
|
||||
|
||||
node_data::node_data()
|
||||
: m_isDefined(false),
|
||||
m_mark(Mark::null_mark()),
|
||||
m_type(NodeType::Null),
|
||||
m_style(EmitterStyle::Default),
|
||||
m_seqSize(0) {}
|
||||
|
||||
void node_data::mark_defined() {
|
||||
if (m_type == NodeType::Undefined)
|
||||
m_type = NodeType::Null;
|
||||
m_isDefined = true;
|
||||
}
|
||||
|
||||
void node_data::set_mark(const Mark& mark) { m_mark = mark; }
|
||||
|
||||
void node_data::set_type(NodeType::value type) {
|
||||
if (type == NodeType::Undefined) {
|
||||
m_type = type;
|
||||
m_isDefined = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_isDefined = true;
|
||||
if (type == m_type)
|
||||
return;
|
||||
|
||||
m_type = type;
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Null:
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
m_scalar.clear();
|
||||
break;
|
||||
case NodeType::Sequence:
|
||||
reset_sequence();
|
||||
break;
|
||||
case NodeType::Map:
|
||||
reset_map();
|
||||
break;
|
||||
case NodeType::Undefined:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void node_data::set_tag(const std::string& tag) { m_tag = tag; }
|
||||
|
||||
void node_data::set_style(EmitterStyle::value style) { m_style = style; }
|
||||
|
||||
void node_data::set_null() {
|
||||
m_isDefined = true;
|
||||
m_type = NodeType::Null;
|
||||
}
|
||||
|
||||
void node_data::set_scalar(const std::string& scalar) {
|
||||
m_isDefined = true;
|
||||
m_type = NodeType::Scalar;
|
||||
m_scalar = scalar;
|
||||
}
|
||||
|
||||
// size/iterator
|
||||
std::size_t node_data::size() const {
|
||||
if (!m_isDefined)
|
||||
return 0;
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
compute_seq_size();
|
||||
return m_seqSize;
|
||||
case NodeType::Map:
|
||||
compute_map_size();
|
||||
return m_map.size() - m_undefinedPairs.size();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void node_data::compute_seq_size() const {
|
||||
while (m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
|
||||
m_seqSize++;
|
||||
}
|
||||
|
||||
void node_data::compute_map_size() const {
|
||||
kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||
while (it != m_undefinedPairs.end()) {
|
||||
kv_pairs::iterator jt = std::next(it);
|
||||
if (it->first->is_defined() && it->second->is_defined())
|
||||
m_undefinedPairs.erase(it);
|
||||
it = jt;
|
||||
}
|
||||
}
|
||||
|
||||
const_node_iterator node_data::begin() const {
|
||||
if (!m_isDefined)
|
||||
return const_node_iterator();
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
return const_node_iterator(m_sequence.begin());
|
||||
case NodeType::Map:
|
||||
return const_node_iterator(m_map.begin(), m_map.end());
|
||||
default:
|
||||
return const_node_iterator();
|
||||
}
|
||||
}
|
||||
|
||||
node_iterator node_data::begin() {
|
||||
if (!m_isDefined)
|
||||
return node_iterator();
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
return node_iterator(m_sequence.begin());
|
||||
case NodeType::Map:
|
||||
return node_iterator(m_map.begin(), m_map.end());
|
||||
default:
|
||||
return node_iterator();
|
||||
}
|
||||
}
|
||||
|
||||
const_node_iterator node_data::end() const {
|
||||
if (!m_isDefined)
|
||||
return const_node_iterator();
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
return const_node_iterator(m_sequence.end());
|
||||
case NodeType::Map:
|
||||
return const_node_iterator(m_map.end(), m_map.end());
|
||||
default:
|
||||
return const_node_iterator();
|
||||
}
|
||||
}
|
||||
|
||||
node_iterator node_data::end() {
|
||||
if (!m_isDefined)
|
||||
return node_iterator();
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
return node_iterator(m_sequence.end());
|
||||
case NodeType::Map:
|
||||
return node_iterator(m_map.end(), m_map.end());
|
||||
default:
|
||||
return node_iterator();
|
||||
}
|
||||
}
|
||||
|
||||
// sequence
|
||||
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
|
||||
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
|
||||
m_type = NodeType::Sequence;
|
||||
reset_sequence();
|
||||
}
|
||||
|
||||
if (m_type != NodeType::Sequence)
|
||||
throw BadPushback();
|
||||
|
||||
m_sequence.push_back(&node);
|
||||
}
|
||||
|
||||
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
case NodeType::Sequence:
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript();
|
||||
}
|
||||
|
||||
insert_map_pair(key, value);
|
||||
}
|
||||
|
||||
// indexing
|
||||
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
|
||||
if (m_type != NodeType::Map) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->is(key))
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node& node_data::get(node& key, shared_memory_holder pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
case NodeType::Sequence:
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript();
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->is(key))
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
node& value = pMemory->create_node();
|
||||
insert_map_pair(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
|
||||
if (m_type != NodeType::Map)
|
||||
return false;
|
||||
|
||||
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->is(key)) {
|
||||
m_map.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void node_data::reset_sequence() {
|
||||
m_sequence.clear();
|
||||
m_seqSize = 0;
|
||||
}
|
||||
|
||||
void node_data::reset_map() {
|
||||
m_map.clear();
|
||||
m_undefinedPairs.clear();
|
||||
}
|
||||
|
||||
void node_data::insert_map_pair(node& key, node& value) {
|
||||
m_map.emplace_back(&key, &value);
|
||||
|
||||
if (!key.is_defined() || !value.is_defined())
|
||||
m_undefinedPairs.emplace_back(&key, &value);
|
||||
}
|
||||
|
||||
void node_data::convert_to_map(shared_memory_holder pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
reset_map();
|
||||
m_type = NodeType::Map;
|
||||
break;
|
||||
case NodeType::Sequence:
|
||||
convert_sequence_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Map:
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
|
||||
assert(m_type == NodeType::Sequence);
|
||||
|
||||
reset_map();
|
||||
for (std::size_t i = 0; i < m_sequence.size(); i++) {
|
||||
std::stringstream stream;
|
||||
stream << i;
|
||||
|
||||
node& key = pMemory->create_node();
|
||||
key.set_scalar(stream.str());
|
||||
insert_map_pair(key, *m_sequence[i]);
|
||||
}
|
||||
|
||||
reset_sequence();
|
||||
m_type = NodeType::Map;
|
||||
}
|
||||
}
|
||||
}
|
||||
130
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/nodebuilder.cpp
Executable file
130
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/nodebuilder.cpp
Executable file
@@ -0,0 +1,130 @@
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "nodebuilder.h"
|
||||
#include "yaml-cpp/node/detail/node.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
|
||||
namespace YAML {
|
||||
struct Mark;
|
||||
|
||||
NodeBuilder::NodeBuilder()
|
||||
: m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) {
|
||||
m_anchors.push_back(0); // since the anchors start at 1
|
||||
}
|
||||
|
||||
NodeBuilder::~NodeBuilder() {}
|
||||
|
||||
Node NodeBuilder::Root() {
|
||||
if (!m_pRoot)
|
||||
return Node();
|
||||
|
||||
return Node(*m_pRoot, m_pMemory);
|
||||
}
|
||||
|
||||
void NodeBuilder::OnDocumentStart(const Mark&) {}
|
||||
|
||||
void NodeBuilder::OnDocumentEnd() {}
|
||||
|
||||
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
|
||||
detail::node& node = Push(mark, anchor);
|
||||
node.set_null();
|
||||
Pop();
|
||||
}
|
||||
|
||||
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
|
||||
detail::node& node = *m_anchors[anchor];
|
||||
Push(node);
|
||||
Pop();
|
||||
}
|
||||
|
||||
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value) {
|
||||
detail::node& node = Push(mark, anchor);
|
||||
node.set_scalar(value);
|
||||
node.set_tag(tag);
|
||||
Pop();
|
||||
}
|
||||
|
||||
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) {
|
||||
detail::node& node = Push(mark, anchor);
|
||||
node.set_tag(tag);
|
||||
node.set_type(NodeType::Sequence);
|
||||
node.set_style(style);
|
||||
}
|
||||
|
||||
void NodeBuilder::OnSequenceEnd() { Pop(); }
|
||||
|
||||
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) {
|
||||
detail::node& node = Push(mark, anchor);
|
||||
node.set_type(NodeType::Map);
|
||||
node.set_tag(tag);
|
||||
node.set_style(style);
|
||||
m_mapDepth++;
|
||||
}
|
||||
|
||||
void NodeBuilder::OnMapEnd() {
|
||||
assert(m_mapDepth > 0);
|
||||
m_mapDepth--;
|
||||
Pop();
|
||||
}
|
||||
|
||||
detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
|
||||
detail::node& node = m_pMemory->create_node();
|
||||
node.set_mark(mark);
|
||||
RegisterAnchor(anchor, node);
|
||||
Push(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
void NodeBuilder::Push(detail::node& node) {
|
||||
const bool needsKey =
|
||||
(!m_stack.empty() && m_stack.back()->type() == NodeType::Map &&
|
||||
m_keys.size() < m_mapDepth);
|
||||
|
||||
m_stack.push_back(&node);
|
||||
if (needsKey)
|
||||
m_keys.push_back(PushedKey(&node, false));
|
||||
}
|
||||
|
||||
void NodeBuilder::Pop() {
|
||||
assert(!m_stack.empty());
|
||||
if (m_stack.size() == 1) {
|
||||
m_pRoot = m_stack[0];
|
||||
m_stack.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
detail::node& node = *m_stack.back();
|
||||
m_stack.pop_back();
|
||||
|
||||
detail::node& collection = *m_stack.back();
|
||||
|
||||
if (collection.type() == NodeType::Sequence) {
|
||||
collection.push_back(node, m_pMemory);
|
||||
} else if (collection.type() == NodeType::Map) {
|
||||
assert(!m_keys.empty());
|
||||
PushedKey& key = m_keys.back();
|
||||
if (key.second) {
|
||||
collection.insert(*key.first, node, m_pMemory);
|
||||
m_keys.pop_back();
|
||||
} else {
|
||||
key.second = true;
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
m_stack.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
|
||||
if (anchor) {
|
||||
assert(anchor == m_anchors.size());
|
||||
m_anchors.push_back(&node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node;
|
||||
} // namespace detail
|
||||
struct Mark;
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class Node;
|
||||
|
||||
class NodeBuilder : public EventHandler {
|
||||
public:
|
||||
NodeBuilder();
|
||||
virtual ~NodeBuilder();
|
||||
|
||||
Node Root();
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark);
|
||||
virtual void OnDocumentEnd();
|
||||
|
||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, const std::string& value);
|
||||
|
||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnSequenceEnd();
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnMapEnd();
|
||||
|
||||
private:
|
||||
detail::node& Push(const Mark& mark, anchor_t anchor);
|
||||
void Push(detail::node& node);
|
||||
void Pop();
|
||||
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
||||
|
||||
private:
|
||||
detail::shared_memory_holder m_pMemory;
|
||||
detail::node* m_pRoot;
|
||||
|
||||
typedef std::vector<detail::node*> Nodes;
|
||||
Nodes m_stack;
|
||||
Nodes m_anchors;
|
||||
|
||||
typedef std::pair<detail::node*, bool> PushedKey;
|
||||
std::vector<PushedKey> m_keys;
|
||||
std::size_t m_mapDepth;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
101
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/nodeevents.cpp
Executable file
101
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/nodeevents.cpp
Executable file
@@ -0,0 +1,101 @@
|
||||
#include "nodeevents.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
#include "yaml-cpp/mark.h"
|
||||
#include "yaml-cpp/node/detail/node.h"
|
||||
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
|
||||
namespace YAML {
|
||||
void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
|
||||
m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
|
||||
}
|
||||
|
||||
anchor_t NodeEvents::AliasManager::LookupAnchor(
|
||||
const detail::node& node) const {
|
||||
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
|
||||
if (it == m_anchorByIdentity.end())
|
||||
return 0;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
NodeEvents::NodeEvents(const Node& node)
|
||||
: m_pMemory(node.m_pMemory), m_root(node.m_pNode) {
|
||||
if (m_root)
|
||||
Setup(*m_root);
|
||||
}
|
||||
|
||||
void NodeEvents::Setup(const detail::node& node) {
|
||||
int& refCount = m_refCount[node.ref()];
|
||||
refCount++;
|
||||
if (refCount > 1)
|
||||
return;
|
||||
|
||||
if (node.type() == NodeType::Sequence) {
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
|
||||
Setup(**it);
|
||||
} else if (node.type() == NodeType::Map) {
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||
++it) {
|
||||
Setup(*it->first);
|
||||
Setup(*it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeEvents::Emit(EventHandler& handler) {
|
||||
AliasManager am;
|
||||
|
||||
handler.OnDocumentStart(Mark());
|
||||
if (m_root)
|
||||
Emit(*m_root, handler, am);
|
||||
handler.OnDocumentEnd();
|
||||
}
|
||||
|
||||
void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
|
||||
AliasManager& am) const {
|
||||
anchor_t anchor = NullAnchor;
|
||||
if (IsAliased(node)) {
|
||||
anchor = am.LookupAnchor(node);
|
||||
if (anchor) {
|
||||
handler.OnAlias(Mark(), anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
am.RegisterReference(node);
|
||||
anchor = am.LookupAnchor(node);
|
||||
}
|
||||
|
||||
switch (node.type()) {
|
||||
case NodeType::Undefined:
|
||||
break;
|
||||
case NodeType::Null:
|
||||
handler.OnNull(Mark(), anchor);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
|
||||
break;
|
||||
case NodeType::Sequence:
|
||||
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||
++it)
|
||||
Emit(**it, handler, am);
|
||||
handler.OnSequenceEnd();
|
||||
break;
|
||||
case NodeType::Map:
|
||||
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||
++it) {
|
||||
Emit(*it->first, handler, am);
|
||||
Emit(*it->second, handler, am);
|
||||
}
|
||||
handler.OnMapEnd();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeEvents::IsAliased(const detail::node& node) const {
|
||||
RefCount::const_iterator it = m_refCount.find(node.ref());
|
||||
return it != m_refCount.end() && it->second > 1;
|
||||
}
|
||||
}
|
||||
64
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/nodeevents.h
Executable file
64
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/nodeevents.h
Executable file
@@ -0,0 +1,64 @@
|
||||
#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/node/ptr.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
class node;
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
||||
namespace YAML {
|
||||
class EventHandler;
|
||||
class Node;
|
||||
|
||||
class NodeEvents {
|
||||
public:
|
||||
explicit NodeEvents(const Node& node);
|
||||
|
||||
void Emit(EventHandler& handler);
|
||||
|
||||
private:
|
||||
class AliasManager {
|
||||
public:
|
||||
AliasManager() : m_curAnchor(0) {}
|
||||
|
||||
void RegisterReference(const detail::node& node);
|
||||
anchor_t LookupAnchor(const detail::node& node) const;
|
||||
|
||||
private:
|
||||
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
||||
|
||||
private:
|
||||
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
||||
AnchorByIdentity m_anchorByIdentity;
|
||||
|
||||
anchor_t m_curAnchor;
|
||||
};
|
||||
|
||||
void Setup(const detail::node& node);
|
||||
void Emit(const detail::node& node, EventHandler& handler,
|
||||
AliasManager& am) const;
|
||||
bool IsAliased(const detail::node& node) const;
|
||||
|
||||
private:
|
||||
detail::shared_memory_holder m_pMemory;
|
||||
detail::node* m_root;
|
||||
|
||||
typedef std::map<const detail::node_ref*, int> RefCount;
|
||||
RefCount m_refCount;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
10
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/null.cpp
Executable file
10
cpp-package/inspireface/cpp/inspireface/middleware/cpp_yaml/src/null.cpp
Executable file
@@ -0,0 +1,10 @@
|
||||
#include "yaml-cpp/null.h"
|
||||
|
||||
namespace YAML {
|
||||
_Null Null;
|
||||
|
||||
bool IsNullString(const std::string& str) {
|
||||
return str.empty() || str == "~" || str == "null" || str == "Null" ||
|
||||
str == "NULL";
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user