diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8e6a24fa..e0fd1391 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,40 +10,10 @@ cmake_minimum_required(VERSION 3.20)
project(Lithium VERSION 1.0.0 LANGUAGES C CXX)
# Set project options
-option(ENABLE_ASYNC "Enable Async Server Mode" ON)
-option(ENABLE_NATIVE_SERVER "Enable to use INDI native server" OFF)
-option(ENABLE_DEBUG "Enable Debug Mode" OFF)
-option(ENABLE_FASHHASH "Enable Using emhash8 as fast hash map" OFF)
-option(ENABLE_WEB_SERVER "Enable Web Server" ON)
-option(ENABLE_WEB_CLIENT "Enable Web Client" ON)
-
-# Set compile definitions based on options
-if(ENABLE_ASYNC)
- add_compile_definitions(ENABLE_ASYNC_FLAG=1)
-endif()
-if(ENABLE_DEBUG)
- add_compile_definitions(ENABLE_DEBUG_FLAG=1)
-endif()
-if(ENABLE_NATIVE_SERVER)
- add_compile_definitions(ENABLE_NATIVE_SERVER_FLAG=1)
-endif()
-if(ENABLE_FASHHASH)
- add_compile_definitions(ENABLE_FASHHASH_FLAG=1)
-endif()
-if(ENABLE_WEB_SERVER)
- add_compile_definitions(ENABLE_WEB_SERVER_FLAG=1)
-endif()
-if(ENABLE_WEB_CLIENT)
- add_compile_definitions(ENABLE_WEB_CLIENT_FLAG=1)
-endif()
+include(cmake/options.cmake)
# Set policies
-if(POLICY CMP0003)
- cmake_policy(SET CMP0003 NEW)
-endif()
-if(POLICY CMP0043)
- cmake_policy(SET CMP0043 NEW)
-endif()
+include(cmake/policies.cmake)
# Set project directories
set(Lithium_PROJECT_ROOT_DIR ${CMAKE_SOURCE_DIR})
@@ -55,15 +25,15 @@ set(lithium_task_dir ${lithium_src_dir}/task)
add_custom_target(CmakeAdditionalFiles
SOURCES
- ${lithium_src_dir}/../cmake_modules/compiler_options.cmake)
-LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/")
-LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake_modules/")
-include(cmake_modules/compiler_options.cmake)
+ ${lithium_src_dir}/../cmake/compiler_options.cmake)
+LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
+LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/")
+include(cmake/compiler_options.cmake)
# ------------------ CPM Begin ------------------
set(CPM_DOWNLOAD_VERSION 0.35.6)
-set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake_modules/CPM.cmake")
+set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM.cmake")
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
message(STATUS "Downloading CPM.cmake")
@@ -137,131 +107,10 @@ include_directories(${CMAKE_SOURCE_DIR}/libs/oatpp-websocket/oatpp-websocket)
include_directories(${CMAKE_SOURCE_DIR}/libs/oatpp-openssl/oatpp-openssl)
# Find packages
-find_package(OpenSSL REQUIRED)
-find_package(ZLIB REQUIRED)
-find_package(SQLite3 REQUIRED)
-find_package(fmt REQUIRED)
-find_package(Readline REQUIRED)
-
-find_package(Python COMPONENTS Interpreter REQUIRED)
-
-# Specify the path to requirements.txt
-set(REQUIREMENTS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
-
-# Define a function to check if a Python package is installed
-function(check_python_package package version)
- # Replace hyphens with underscores for the import statement
- string(REPLACE "-" "_" import_name ${package})
-
- # Check if the package can be imported
- execute_process(
- COMMAND ${Python_EXECUTABLE} -c "import ${import_name}"
- RESULT_VARIABLE result
- )
-
- if(NOT result EQUAL 0)
- set(result FALSE PARENT_SCOPE)
- return()
- endif()
-
- # Get the installed package version
- execute_process(
- COMMAND ${Python_EXECUTABLE} -m pip show ${package}
- OUTPUT_VARIABLE package_info
- )
-
- # Extract version information from the output
- string(FIND "${package_info}" "Version:" version_pos)
-
- if(version_pos EQUAL -1)
- set(result FALSE PARENT_SCOPE)
- return() # Return false if version not found
- endif()
-
- # Extract the version string
- string(SUBSTRING "${package_info}" ${version_pos} 1000 version_string)
- string(REGEX REPLACE "Version: ([^ ]+).*" "\\1" installed_version "${version_string}")
-
- # Compare versions
- if("${installed_version}" VERSION_LESS "${version}")
- set(result FALSE PARENT_SCOPE) # Return false if installed version is less than required
- return()
- endif()
-
- set(result TRUE PARENT_SCOPE)
-endfunction()
-
-if (EXISTS "${CMAKE_BINARY_DIR}/check_marker.txt")
- message(STATUS "Check marker file found, skipping the checks.")
-else()
-# Create a virtual environment
-set(VENV_DIR "${CMAKE_BINARY_DIR}/venv")
-execute_process(
- COMMAND ${Python_EXECUTABLE} -m venv ${VENV_DIR}
-)
-
-set(PYTHON_EXECUTABLE "${VENV_DIR}/bin/python")
-set(PIP_EXECUTABLE "${VENV_DIR}/bin/pip")
-
-# Upgrade pip in the virtual environment
-execute_process(
- COMMAND ${PIP_EXECUTABLE} install --upgrade pip
-)
-
-# Read the requirements.txt file and install missing packages
-file(READ ${REQUIREMENTS_FILE} requirements_content)
-
-# Split the requirements file content into lines
-string(REPLACE "\n" ";" requirements_list "${requirements_content}")
+include(cmake/find_packages.cmake)
-# Check and install each package
-foreach(requirement ${requirements_list})
- # Skip empty lines
- string(STRIP ${requirement} trimmed_requirement)
- if(trimmed_requirement STREQUAL "")
- continue()
- endif()
-
- # Get the package name and version (without the version number)
- if(${trimmed_requirement} MATCHES "==")
- string(REPLACE "==" ";" parts ${trimmed_requirement})
- elseif(${trimmed_requirement} MATCHES ">=")
- string(REPLACE ">=" ";" parts ${trimmed_requirement})
- else()
- message(WARNING "Could not parse requirement '${trimmed_requirement}'. Skipping...")
- continue()
- endif()
-
- list(GET parts 0 package_name)
- list(GET parts 1 package_version)
-
- # If the package name or version could not be parsed, output a warning and skip
- if(NOT package_name OR NOT package_version)
- message(WARNING "Could not parse requirement '${trimmed_requirement}'. Skipping...")
- continue()
- endif()
-
- # Check if the package is installed
- message(STATUS "Checking if Python package '${package_name}' is installed...")
- check_python_package(${package_name} ${package_version})
- if(NOT result)
- message(STATUS "Package '${package_name}' is not installed or needs an upgrade. Installing...")
- execute_process(
- COMMAND ${PIP_EXECUTABLE} install ${trimmed_requirement}
- RESULT_VARIABLE install_result
- )
- if(NOT install_result EQUAL 0)
- message(FATAL_ERROR "Failed to install Python package '${package_name}'.")
- endif()
- else()
- message(STATUS "Package '${package_name}' is already installed with a suitable version.")
- endif()
-endforeach()
-execute_process(
- COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/check_marker.txt"
- RESULT_VARIABLE result
-)
-endif()
+# Configure Python environment
+include(cmake/python_environment.cmake)
# Configure config.h
configure_file(${lithium_src_dir}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
@@ -271,13 +120,16 @@ set(BUILD_SHARED_LIBS ON)
# Add subdirectories
add_subdirectory(libs)
add_subdirectory(modules)
+
add_subdirectory(${lithium_module_dir})
+
add_subdirectory(${lithium_src_dir}/config)
add_subdirectory(${lithium_src_dir}/task)
add_subdirectory(${lithium_src_dir}/server)
add_subdirectory(${lithium_src_dir}/utils)
add_subdirectory(${lithium_src_dir}/addon)
add_subdirectory(${lithium_src_dir}/client)
+add_subdirectory(${lithium_src_dir}/target)
add_subdirectory(${lithium_src_dir}/device)
add_subdirectory(tests)
@@ -308,12 +160,13 @@ set(debug_module
set(device_module
${lithium_src_dir}/device/manager.cpp
-
${lithium_src_dir}/device/template/device.cpp
)
set(script_module
${lithium_src_dir}/script/manager.cpp
+ ${lithium_src_dir}/script/pycaller.cpp
+ ${lithium_src_dir}/script/pycaller.hpp
${lithium_src_dir}/script/sheller.cpp
)
@@ -364,6 +217,7 @@ target_link_libraries(lithium_server
tinyxml2
pocketpy
${Readline_LIBRARIES}
+ pybind11::embed
)
if(WIN32)
@@ -395,17 +249,7 @@ target_compile_definitions(lithium_server PRIVATE LOGURU_DEBUG_LOGGING)
set_target_properties(lithium_server PROPERTIES OUTPUT_NAME lithium_server)
# Set install paths
-if(UNIX AND NOT APPLE)
- if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- set(CMAKE_INSTALL_PREFIX /usr CACHE PATH "Lithium install path" FORCE)
- endif()
-endif()
-
-if(WIN32)
- set(CMAKE_INSTALL_PREFIX "C:/Program Files/LithiumServer")
-elseif(LINUX)
- set(CMAKE_INSTALL_PREFIX "/usr/lithium")
-endif()
+include(cmake/install_paths.cmake)
# Enable folder grouping in IDEs
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
diff --git a/README.md b/README.md
index aabeeabe..0e9d1703 100644
--- a/README.md
+++ b/README.md
@@ -69,3 +69,6 @@ Alternatively, utilize the provided quick-build scripts to streamline the proces
### Intellectual Inspiration
Embarking on the journey with Lithium, we embrace curiosity and an unwavering pursuit of knowledge, echoing the adapted verse which reminds us that every attempt, though fraught with challenges and setbacks, is a necessary step toward wisdom and understanding. Together, let us navigate the vast cosmos of astronomical imaging, our technology the vessel, innovation our sail, advancing relentlessly forward.
+
+
+
diff --git a/cmake_modules/CPM.cmake b/cmake/CPM.cmake
similarity index 100%
rename from cmake_modules/CPM.cmake
rename to cmake/CPM.cmake
diff --git a/cmake_modules/FindASCOM.cmake b/cmake/FindASCOM.cmake
similarity index 100%
rename from cmake_modules/FindASCOM.cmake
rename to cmake/FindASCOM.cmake
diff --git a/cmake_modules/FindCFITSIO.cmake b/cmake/FindCFITSIO.cmake
similarity index 100%
rename from cmake_modules/FindCFITSIO.cmake
rename to cmake/FindCFITSIO.cmake
diff --git a/cmake_modules/FindGMock.cmake b/cmake/FindGMock.cmake
similarity index 100%
rename from cmake_modules/FindGMock.cmake
rename to cmake/FindGMock.cmake
diff --git a/cmake/FindGlib.cmake b/cmake/FindGlib.cmake
new file mode 100644
index 00000000..3a7866d4
--- /dev/null
+++ b/cmake/FindGlib.cmake
@@ -0,0 +1,62 @@
+# - Try to find Glib-2.0 (with gobject)
+# Once done, this will define
+#
+# Glib_FOUND - system has Glib
+# Glib_INCLUDE_DIRS - the Glib include directories
+# Glib_LIBRARIES - link these to use Glib
+
+include(LibFindMacros)
+
+# Use pkg-config to get hints about paths
+libfind_pkg_check_modules(Glib_PKGCONF glib-2.0>=2.16)
+
+# Main include dir
+find_path(Glib_INCLUDE_DIR
+ NAMES glib.h
+ PATHS ${Glib_PKGCONF_INCLUDE_DIRS}
+ PATH_SUFFIXES glib-2.0
+)
+
+# Glib-related libraries also use a separate config header, which is in lib dir
+find_path(GlibConfig_INCLUDE_DIR
+ NAMES glibconfig.h
+ PATHS ${Glib_PKGCONF_INCLUDE_DIRS} /usr
+ PATH_SUFFIXES lib/glib-2.0/include
+)
+
+# Finally the library itself
+find_library(Glib_LIBRARY
+ NAMES glib-2.0
+ PATHS ${Glib_PKGCONF_LIBRARY_DIRS}
+)
+
+# Find gobject library
+find_library(GObject_LIBRARY
+ NAMES gobject-2.0
+ PATHS ${Glib_PKGCONF_LIBRARY_DIRS}
+)
+
+# Find gthread library
+find_library(GThread_LIBRARY
+ NAMES gthread-2.0
+ PATHS ${Glib_PKGCONF_LIBRARY_DIRS}
+)
+
+# Set the include dir variables and the libraries and let libfind_process do the rest.
+# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
+set(Glib_PROCESS_INCLUDES Glib_INCLUDE_DIR GlibConfig_INCLUDE_DIR)
+set(Glib_PROCESS_LIBS Glib_LIBRARY GObject_LIBRARY GThread_LIBRARY)
+libfind_process(Glib)
+
+# Redefine variables for backward compatibility
+set(GLIB_INCLUDE_DIRS ${Glib_INCLUDE_DIRS})
+set(GLIB_LIBRARIES ${Glib_LIBRARIES})
+set(GLIB_FOUND ${Glib_FOUND})
+
+# Provide a summary of the found libraries
+if(Glib_FOUND)
+ message(STATUS "Found Glib: ${Glib_LIBRARIES}")
+ message(STATUS "Glib include directories: ${Glib_INCLUDE_DIRS}")
+else()
+ message(WARNING "Glib not found")
+endif()
diff --git a/cmake_modules/FindINDI.cmake b/cmake/FindINDI.cmake
similarity index 100%
rename from cmake_modules/FindINDI.cmake
rename to cmake/FindINDI.cmake
diff --git a/cmake_modules/FindJPEG.cmake b/cmake/FindJPEG.cmake
similarity index 100%
rename from cmake_modules/FindJPEG.cmake
rename to cmake/FindJPEG.cmake
diff --git a/cmake/FindLibSecret.cmake b/cmake/FindLibSecret.cmake
new file mode 100644
index 00000000..16b13da0
--- /dev/null
+++ b/cmake/FindLibSecret.cmake
@@ -0,0 +1,29 @@
+# - Try to find LIBSECRET-1
+# Once done, this will define
+#
+# LIBSECRET_FOUND - system has LIBSECRET
+# LIBSECRET_INCLUDE_DIRS - the LIBSECRET include directories
+# LIBSECRET_LIBRARIES - link these to use LIBSECRET
+
+include(LibFindMacros)
+
+# Use pkg-config to get hints about paths
+libfind_pkg_check_modules(LIBSECRET_PKGCONF LIBSECRET-1)
+
+# Main include dir
+find_path(LIBSECRET_INCLUDE_DIR
+ NAMES LIBSECRET/secret.h
+ PATHS ${LIBSECRET_PKGCONF_INCLUDE_DIRS}
+)
+
+# Finally the library itself
+find_library(LIBSECRET_LIBRARY
+ NAMES secret-1
+ PATHS ${LIBSECRET_PKGCONF_LIBRARY_DIRS}
+)
+
+# Set the include dir variables and the libraries and let libfind_process do the rest.
+# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
+set(LIBSECRET_PROCESS_INCLUDES LIBSECRET_INCLUDE_DIR)
+set(LIBSECRET_PROCESS_LIBS LIBSECRET_LIBRARY)
+libfind_process(LIBSECRET)
diff --git a/cmake_modules/FindNova.cmake b/cmake/FindNova.cmake
similarity index 100%
rename from cmake_modules/FindNova.cmake
rename to cmake/FindNova.cmake
diff --git a/cmake_modules/FindReadline.cmake b/cmake/FindReadline.cmake
similarity index 100%
rename from cmake_modules/FindReadline.cmake
rename to cmake/FindReadline.cmake
diff --git a/cmake_modules/FindSeccomp.cmake b/cmake/FindSeccomp.cmake
similarity index 100%
rename from cmake_modules/FindSeccomp.cmake
rename to cmake/FindSeccomp.cmake
diff --git a/cmake_modules/FindYamlCpp.cmake b/cmake/FindYamlCpp.cmake
similarity index 100%
rename from cmake_modules/FindYamlCpp.cmake
rename to cmake/FindYamlCpp.cmake
diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake
new file mode 100644
index 00000000..ff9233a6
--- /dev/null
+++ b/cmake/LibFindMacros.cmake
@@ -0,0 +1,98 @@
+# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
+# used for the current package. For this to work, the first parameter must be the
+# prefix of the current package, then the prefix of the new package etc, which are
+# passed to find_package.
+macro (libfind_package PREFIX)
+ set (LIBFIND_PACKAGE_ARGS ${ARGN})
+ if (${PREFIX}_FIND_QUIETLY)
+ set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET)
+ endif (${PREFIX}_FIND_QUIETLY)
+ if (${PREFIX}_FIND_REQUIRED)
+ set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED)
+ endif (${PREFIX}_FIND_REQUIRED)
+ find_package(${LIBFIND_PACKAGE_ARGS})
+endmacro (libfind_package)
+
+# CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
+# where they added pkg_check_modules. Consequently I need to support both in my scripts
+# to avoid those deprecated warnings. Here's a helper that does just that.
+# Works identically to pkg_check_modules, except that no checks are needed prior to use.
+macro (libfind_pkg_check_modules PREFIX PKGNAME)
+ if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ include(UsePkgConfig)
+ pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
+ else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(${PREFIX} ${PKGNAME})
+ endif (PKG_CONFIG_FOUND)
+ endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+endmacro (libfind_pkg_check_modules)
+
+# Do the final processing once the paths have been detected.
+# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
+# all the variables, each of which contain one include directory.
+# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
+# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
+# Also handles errors in case library detection was required, etc.
+macro (libfind_process PREFIX)
+ # Skip processing if already processed during this run
+ if (NOT ${PREFIX}_FOUND)
+ # Start with the assumption that the library was found
+ set (${PREFIX}_FOUND TRUE)
+
+ # Process all includes and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES})
+ if (${i})
+ set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+ # Process all libraries and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_LIBS})
+ if (${i})
+ set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+ # Print message and/or exit on fatal error
+ if (${PREFIX}_FOUND)
+ if (NOT ${PREFIX}_FIND_QUIETLY)
+ message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
+ endif (NOT ${PREFIX}_FIND_QUIETLY)
+ else (${PREFIX}_FOUND)
+ if (${PREFIX}_FIND_REQUIRED)
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
+ message("${i}=${${i}}")
+ endforeach (i)
+ message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
+ endif (${PREFIX}_FIND_REQUIRED)
+ endif (${PREFIX}_FOUND)
+ endif (NOT ${PREFIX}_FOUND)
+endmacro (libfind_process)
+
+macro(libfind_library PREFIX basename)
+ set(TMP "")
+ if(MSVC80)
+ set(TMP -vc80)
+ endif(MSVC80)
+ if(MSVC90)
+ set(TMP -vc90)
+ endif(MSVC90)
+ set(${PREFIX}_LIBNAMES ${basename}${TMP})
+ if(${ARGC} GREATER 2)
+ set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
+ string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
+ set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
+ endif(${ARGC} GREATER 2)
+ find_library(${PREFIX}_LIBRARY
+ NAMES ${${PREFIX}_LIBNAMES}
+ PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}
+ )
+endmacro(libfind_library)
diff --git a/cmake_modules/ScanModule.cmake b/cmake/ScanModule.cmake
similarity index 100%
rename from cmake_modules/ScanModule.cmake
rename to cmake/ScanModule.cmake
diff --git a/cmake_modules/compiler_options.cmake b/cmake/compiler_options.cmake
similarity index 100%
rename from cmake_modules/compiler_options.cmake
rename to cmake/compiler_options.cmake
diff --git a/cmake/find_packages.cmake b/cmake/find_packages.cmake
new file mode 100644
index 00000000..80a769d4
--- /dev/null
+++ b/cmake/find_packages.cmake
@@ -0,0 +1,8 @@
+find_package(OpenSSL REQUIRED)
+find_package(ZLIB REQUIRED)
+find_package(SQLite3 REQUIRED)
+find_package(fmt REQUIRED)
+find_package(Readline REQUIRED)
+find_package(pybind11 CONFIG REQUIRED)
+find_package(Python COMPONENTS Interpreter REQUIRED)
+include_directories(${pybind11_INCLUDE_DIRS} ${Python_INCLUDE_DIRS})
diff --git a/cmake/install_paths.cmake b/cmake/install_paths.cmake
new file mode 100644
index 00000000..d2d6b05c
--- /dev/null
+++ b/cmake/install_paths.cmake
@@ -0,0 +1,11 @@
+if(UNIX AND NOT APPLE)
+ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX /usr CACHE PATH "Lithium install path" FORCE)
+ endif()
+endif()
+
+if(WIN32)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files/LithiumServer")
+elseif(LINUX)
+ set(CMAKE_INSTALL_PREFIX "/usr/lithium")
+endif()
diff --git a/cmake/options.cmake b/cmake/options.cmake
new file mode 100644
index 00000000..dfc90e64
--- /dev/null
+++ b/cmake/options.cmake
@@ -0,0 +1,25 @@
+option(ENABLE_ASYNC "Enable Async Server Mode" ON)
+option(ENABLE_NATIVE_SERVER "Enable to use INDI native server" OFF)
+option(ENABLE_DEBUG "Enable Debug Mode" OFF)
+option(ENABLE_FASHHASH "Enable Using emhash8 as fast hash map" OFF)
+option(ENABLE_WEB_SERVER "Enable Web Server" ON)
+option(ENABLE_WEB_CLIENT "Enable Web Client" ON)
+
+if(ENABLE_ASYNC)
+ add_compile_definitions(ENABLE_ASYNC_FLAG=1)
+endif()
+if(ENABLE_DEBUG)
+ add_compile_definitions(ENABLE_DEBUG_FLAG=1)
+endif()
+if(ENABLE_NATIVE_SERVER)
+ add_compile_definitions(ENABLE_NATIVE_SERVER_FLAG=1)
+endif()
+if(ENABLE_FASHHASH)
+ add_compile_definitions(ENABLE_FASHHASH_FLAG=1)
+endif()
+if(ENABLE_WEB_SERVER)
+ add_compile_definitions(ENABLE_WEB_SERVER_FLAG=1)
+endif()
+if(ENABLE_WEB_CLIENT)
+ add_compile_definitions(ENABLE_WEB_CLIENT_FLAG=1)
+endif()
diff --git a/cmake/policies.cmake b/cmake/policies.cmake
new file mode 100644
index 00000000..48ed312c
--- /dev/null
+++ b/cmake/policies.cmake
@@ -0,0 +1,6 @@
+if(POLICY CMP0003)
+ cmake_policy(SET CMP0003 NEW)
+endif()
+if(POLICY CMP0043)
+ cmake_policy(SET CMP0043 NEW)
+endif()
diff --git a/cmake/python_environment.cmake b/cmake/python_environment.cmake
new file mode 100644
index 00000000..4eec3678
--- /dev/null
+++ b/cmake/python_environment.cmake
@@ -0,0 +1,117 @@
+# Specify the path to requirements.txt
+set(REQUIREMENTS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+
+# Define a function to check if a Python package is installed
+function(check_python_package package version)
+ # Replace hyphens with underscores for the import statement
+ string(REPLACE "-" "_" import_name ${package})
+
+ # Check if the package can be imported
+ execute_process(
+ COMMAND ${Python_EXECUTABLE} -c "import ${import_name}"
+ RESULT_VARIABLE result
+ )
+
+ if(NOT result EQUAL 0)
+ set(result FALSE PARENT_SCOPE)
+ return()
+ endif()
+
+ # Get the installed package version
+ execute_process(
+ COMMAND ${Python_EXECUTABLE} -m pip show ${package}
+ OUTPUT_VARIABLE package_info
+ )
+
+ # Extract version information from the output
+ string(FIND "${package_info}" "Version:" version_pos)
+
+ if(version_pos EQUAL -1)
+ set(result FALSE PARENT_SCOPE)
+ return() # Return false if version not found
+ endif()
+
+ # Extract the version string
+ string(SUBSTRING "${package_info}" ${version_pos} 1000 version_string)
+ string(REGEX REPLACE "Version: ([^ ]+).*" "\\1" installed_version "${version_string}")
+
+ # Compare versions
+ if("${installed_version}" VERSION_LESS "${version}")
+ set(result FALSE PARENT_SCOPE) # Return false if installed version is less than required
+ return()
+ endif()
+
+ set(result TRUE PARENT_SCOPE)
+endfunction()
+
+if (EXISTS "${CMAKE_BINARY_DIR}/check_marker.txt")
+ message(STATUS "Check marker file found, skipping the checks.")
+else()
+# Create a virtual environment
+set(VENV_DIR "${CMAKE_BINARY_DIR}/venv")
+execute_process(
+ COMMAND ${Python_EXECUTABLE} -m venv ${VENV_DIR}
+)
+
+set(PYTHON_EXECUTABLE "${VENV_DIR}/bin/python")
+set(PIP_EXECUTABLE "${VENV_DIR}/bin/pip")
+
+# Upgrade pip in the virtual environment
+execute_process(
+ COMMAND ${PIP_EXECUTABLE} install --upgrade pip
+)
+
+# Read the requirements.txt file and install missing packages
+file(READ ${REQUIREMENTS_FILE} requirements_content)
+
+# Split the requirements file content into lines
+string(REPLACE "\n" ";" requirements_list "${requirements_content}")
+
+# Check and install each package
+foreach(requirement ${requirements_list})
+ # Skip empty lines
+ string(STRIP ${requirement} trimmed_requirement)
+ if(trimmed_requirement STREQUAL "")
+ continue()
+ endif()
+
+ # Get the package name and version (without the version number)
+ if(${trimmed_requirement} MATCHES "==")
+ string(REPLACE "==" ";" parts ${trimmed_requirement})
+ elseif(${trimmed_requirement} MATCHES ">=")
+ string(REPLACE ">=" ";" parts ${trimmed_requirement})
+ else()
+ message(WARNING "Could not parse requirement '${trimmed_requirement}'. Skipping...")
+ continue()
+ endif()
+
+ list(GET parts 0 package_name)
+ list(GET parts 1 package_version)
+
+ # If the package name or version could not be parsed, output a warning and skip
+ if(NOT package_name OR NOT package_version)
+ message(WARNING "Could not parse requirement '${trimmed_requirement}'. Skipping...")
+ continue()
+ endif()
+
+ # Check if the package is installed
+ message(STATUS "Checking if Python package '${package_name}' is installed...")
+ check_python_package(${package_name} ${package_version})
+ if(NOT result)
+ message(STATUS "Package '${package_name}' is not installed or needs an upgrade. Installing...")
+ execute_process(
+ COMMAND ${PIP_EXECUTABLE} install ${trimmed_requirement}
+ RESULT_VARIABLE install_result
+ )
+ if(NOT install_result EQUAL 0)
+ message(FATAL_ERROR "Failed to install Python package '${package_name}'.")
+ endif()
+ else()
+ message(STATUS "Package '${package_name}' is already installed with a suitable version.")
+ endif()
+endforeach()
+execute_process(
+ COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/check_marker.txt"
+ RESULT_VARIABLE result
+)
+endif()
diff --git a/config/script/check.json b/config/script/check.json
index 4353c796..f724bfdf 100644
--- a/config/script/check.json
+++ b/config/script/check.json
@@ -1,116 +1,80 @@
{
- "danger_patterns": [
+ "powershell_danger_patterns": [
{
- "pattern": "\\brm\\s+-rf\\b",
- "reason": "Potentially destructive operation"
+ "pattern": "Remove-Item -Recurse -Force",
+ "reason": "Potentially dangerous command that can delete files recursively and forcefully."
},
{
- "pattern": "\\bsudo\\b",
- "reason": "Elevated permissions, dangerous"
- },
- {
- "pattern": "\\bmkfs\\b",
- "reason": "Filesystem creation, dangerous operation"
- },
- {
- "pattern": "\\|",
- "reason": "Pipeline usage might lead to unintended consequences"
- },
- {
- "pattern": "2>&1\\s*>\\s*/dev/null",
- "reason": "Redirection might hide errors"
- },
- {
- "pattern": "\\bkill\\s+-9\\b",
- "reason": "Forcefully killing processes, consider using safer signal"
- },
- {
- "pattern": "eval\\s+",
- "reason": "Using eval can lead to security vulnerabilities"
- },
- {
- "pattern": "\\bshutdown\\b",
- "reason": "Potentially shuts down or restarts the system"
- },
- {
- "pattern": "\\bdd\\s+iflag=fullblock",
- "reason": "Low-level data copying can lead to data loss or corruption"
- },
- {
- "pattern": "\\bchmod\\s+([0-7]{3,4}|[ugoa]+\\+?)\\s+[^/].*",
- "reason": "Changing file permissions may lead to security issues"
- },
- {
- "pattern": "\\bchown\\s+[^:]+:[^/]+\\s+[^/].*",
- "reason": "Changing file ownership may lead to access issues"
- },
- {
- "pattern": "\\bssh\\s+root@[^\\s]+",
- "reason": "SSH access as root user can be risky"
- },
- {
- "pattern": "\\bwget\\s+[^\\s]+",
- "reason": "Downloading files might lead to unintended consequences"
- },
- {
- "pattern": "\\bcurl\\s+[^\\s]+",
- "reason": "Fetching data from the internet can be risky"
+ "pattern": "Stop-Process -Force",
+ "reason": "Forcefully stopping a process can lead to data loss."
}
],
- "sensitive_patterns": [
- {
- "pattern": "password\\s*=\\s*['\"].*['\"]",
- "reason": "Possible plaintext password"
- },
- {
- "pattern": "AWS_SECRET_ACCESS_KEY",
- "reason": "AWS secret key detected"
- },
- {
- "pattern": "GITHUB_TOKEN",
- "reason": "GitHub token detected"
- },
- {
- "pattern": "PRIVATE_KEY",
- "reason": "Private key detected"
- },
- {
- "pattern": "DB_PASSWORD\\s*=\\s*['\"].*['\"]",
- "reason": "Database password detected"
- },
+ "windows_cmd_danger_patterns": [
{
- "pattern": "SECRET_KEY\\s*=\\s*['\"].*['\"]",
- "reason": "Application secret key detected"
+ "pattern": "del /s /q",
+ "reason": "Potentially dangerous command that can delete files recursively and quietly."
},
{
- "pattern": "API_KEY\\s*=\\s*['\"].*['\"]",
- "reason": "API key detected"
- },
+ "pattern": "taskkill /F",
+ "reason": "Forcefully killing a task can lead to data loss."
+ }
+ ],
+ "bash_danger_patterns": [
{
- "pattern": "TOKEN\\s*=\\s*['\"].*['\"]",
- "reason": "Authorization token detected"
+ "pattern": "rm -rf /",
+ "reason": "Potentially dangerous command that can delete all files recursively and forcefully."
},
{
- "pattern": "PASSWORD\\s*=\\s*['\"].*['\"]",
- "reason": "Password detected"
+ "pattern": "kill -9",
+ "reason": "Forcefully killing a process can lead to data loss."
}
],
- "environment_patterns": [
+ "python_danger_patterns": [
{
- "pattern": "\\$\\{?\\w+\\}?",
- "reason": "Environment variable dependency detected"
+ "pattern": "os.system",
+ "reason": "Using os.system can be dangerous as it allows execution of arbitrary commands."
},
{
- "pattern": "\\$\\{[^\\}]+\\}",
- "reason": "Environment variable with braces detected"
- },
+ "pattern": "subprocess.call",
+ "reason": "Using subprocess.call can be dangerous as it allows execution of arbitrary commands."
+ }
+ ],
+ "ruby_danger_patterns": [
{
- "pattern": "\\$\\w+",
- "reason": "Environment variable placeholder detected"
+ "pattern": "system",
+ "reason": "Using system can be dangerous as it allows execution of arbitrary commands."
},
{
- "pattern": "\\${HOME|USER|SHELL|PATH}",
- "reason": "Common environment variables detected"
+ "pattern": "exec",
+ "reason": "Using exec can be dangerous as it allows execution of arbitrary commands."
}
- ]
+ ],
+ "replacements": {
+ "Remove-Item -Recurse -Force": "Remove-Item -Recurse",
+ "Stop-Process -Force": "Stop-Process",
+ "rm -rf /": "find . -type f -delete",
+ "kill -9": "kill -TERM"
+ },
+ "external_commands": {
+ "powershell": [
+ "Invoke-WebRequest",
+ "Invoke-RestMethod"
+ ],
+ "cmd": [
+ "curl",
+ "wget"
+ ],
+ "bash": [
+ "curl",
+ "wget"
+ ],
+ "python": [
+ "os.system",
+ "subprocess.call"
+ ],
+ "ruby": [
+ "system",
+ "exec"
+ ]
+ }
}
diff --git a/doc/platesolver/astap.md b/doc/platesolver/astap.md
new file mode 100644
index 00000000..55cff192
--- /dev/null
+++ b/doc/platesolver/astap.md
@@ -0,0 +1,237 @@
+# ASTAP 命令行
+
+该程序可以通过命令行选项执行以解决图像的天文测量问题。例如:
+
+```bash
+ASTAP -f home/test/2.fits -r 30
+```
+
+可以输入 FITS、TIFF、PNG、JPG、BMP 和未压缩的 XISF 文件。
+
+## ASTAP 命令行
+
+**FOV、RA、DEC 选项**适用于非 FITS 文件。对于在头文件中包含这些值的 FITS 文件,这些选项不是必需的。
+
+### 命令
+
+| 参数 | 单位 | 备注 |
+| ----- | ---- | -------- |
+| -h | | 帮助信息 |
+| -help | | 帮助信息 |
+
+### 求解器选项
+
+| 命令 | 参数 | 单位 | 备注 |
+| ------- | ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------- |
+| -f | 文件名 | | 需要解析的文件。 |
+| -r | 搜索半径 | 度 | 将在起始位置周围的方形螺旋中搜索,直到此半径 \* |
+| -fov | 图像高度 | 度 | 可选。通常从 FITS 头文件中计算。使用值 0 进行自动计算。如果指定 0,求解后找到的 fov 将保存以供下次使用。(学习模式) \* |
+| -ra | 中心赤经 | 小时 | 可选起始值。通常从 FITS 头文件中计算。 |
+| -spd | 南极距离 (dec+90) | 度 | 通常从 FITS 头文件中计算 \* 赤纬以南极距离给出,因此总是正值。 |
+| -z | 降采样因子 | 0,1,2,3,4 | 求解前降采样。也称为分箱。值 "0" 将导致自动选择降采样。 \* |
+| -s | 最大星数 | | 限制用于求解的星数。典型值 500。 \* |
+| -t | 容差 | | 用于比较四边形的容差。典型值 0.007。 \* |
+| -m | 最小星大小 | 角秒 | 可用于过滤掉热点像素。 |
+| -check | 应用 | y/n | 求解前应用检查模式过滤器。仅在分箱为 1x1 时用于原始 OSC 图像 \* |
+| -d | 路径 | | 指定星数据库的路径 |
+| -D | 缩写 | | 指定星数据库 [d80, d50, ..] |
+| -o | 文件 | | 使用此基本路径和文件名命名输出文件 |
+| -sip | 添加 | y/n | 添加 SIP(简单图像多项式)系数。注意,该参数仅在需要停用 SIP 时才需要。 |
+| -speed | 模式 | 慢 / 自动 | "慢" 模式强制从星数据库中读取更大区域(更多重叠)以提高检测率。 \* |
+| -wcs | | | WCS 文件 以类似 Astrometry.net 的格式写入。否则为文本样式 |
+| -update | | | 使用找到的解决方案更新 fits/tiff 头文件。Jpeg、png 将写为 fits。 |
+| -log | | | 将求解器日志写入扩展名为 .log 的文件 |
+
+### 分析选项
+
+| 命令 | 参数 | 单位 | 备注 |
+| --------- | ---------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| -analyse | 最小信噪比 | | 仅分析并报告 HFD。Windows:errorlevel 是中值 HFD \* 100M + 使用的星数。因此 HFD 是 trunc(errorlevel/1M)/100。对于 Linux 和 macOS,信息仅发送到 stdout。 |
+| -extract | 最小信噪比 | | 如分析选项,但另外将所有可检测星的信息导出到 .csv 文件。小数分隔符始终为点。 |
+| -extract2 | 最小信噪比 | | 求解图像并将所有可检测星的信息导出到 .csv 文件,包括每次检测的 α, δ。将使用 SIP 多项式以获得高精度位置。小数分隔符始终为点。 |
+
+### 额外选项(仅适用于标准 GUI 版本)
+
+| 命令 | 参数 | 单位 | 备注 |
+| --------- | ---- | ------- | ------------------------------------------------------------------------------ |
+| -annotate | | | 生成一个带有深空注释的 jpeg 文件,文件名与输入文件相同,扩展名为 \_annotated。 |
+| -debug | | | 显示 GUI 并在求解前停止 |
+| -tofits | 分箱 | 1,2,3,4 | 从输入的 png/jpg 生成分箱的 FITS 文件 |
+
+### 作为分析器/堆栈器
+
+| 命令 | 参数 | 单位 | 备注 |
+| ------- | ----------------------------------------------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------- |
+| -sqm | 基座 | | 测量相对于星的天空背景值,单位为 magn/arcsec2。基座是暗场的平均值。还将写入 centalt 和 airmass 到头文件。 |
+| -focus1 | file1.fits -focus2 file2.fits -focus3 file3.fits ................ | | 使用曲线拟合为四个或更多图像找到最佳焦点。Windows:errorlevel 是 focuspos*1E4 + rem.error*1E3。Linux:查看 stdout |
+| -stack | | | 启动 ASTAP 并显示可见的实时堆栈标签和选定的路径。 |
+
+### 命令行参数优先级
+
+命令行参数优先于 fits 头文件值。前端程序应提供对 -z 和 -r 选项的访问。-z 的默认值应为 0(自动)。
+
+### 典型命令行
+
+```bash
+astap.exe -f image.fits -r 50
+astap.exe -f c:\images\image.png -ra 23.000 -spd 179.000 -fov 1.3 -r 50
+```
+
+对于大多数 FITS 文件,命令行可以很短,因为望远镜位置和视场可以从 FITS 头文件中检索。如果没有 FITS 文件,首选是非无损图像格式,如 .PNG 或 .TIFF 或 RAW 格式,如 .CR2。如果可能,使用 16 位或原始 12 位格式。不要拉伸或饱和,尽可能原始。对于非 FITS 格式,应添加 RA、DEC 位置和 -fov(图像高度,单位为度!!)。
+
+如果在 RAW、PNG、TIFF 文件的命令行中未指定 FOV(图像高度,单位为度),ASTAP 将使用程序、堆栈菜单、对齐标签中设置的 FOV。此设置可以通过参数 -fov 0 自动学习和更新。ASTAP 将尝试所有 FOV 在 10 度和 0.3 度之间。例如:
+
+```bash
+astap.exe -f c:\images\image.png -ra 23.000 -spd 179.000 -r 30 -fov 0
+```
+
+成功求解后,正确的 FOV 将存储在 ASTAP 设置中。对于下次使用相同来源的图像求解,可以省略 -fov 0 参数,求解将更快。
+
+### 调试选项
+
+调试选项允许在 GUI(图形用户界面)中设置一些求解参数并测试命令行。在调试模式下,所有命令行参数都已设置,指定的图像显示在查看器中。只需手动给出求解命令:
+
+```bash
+astap.exe -f c:\images\image.png -ra 23.000 -spd 179.000 -r 30 -debug
+```
+
+或
+
+```bash
+astap.exe -debug
+```
+
+### 命令行,输出文件
+
+在命令行模式下,程序在与输入图像相同的位置生成两个输出文件。如果找到解决方案,它将写入一个 .wcs 文件 1),仅包含已解决的 FITS 头文件。在任何情况下,它将使用标准 FITS 关键字写入一个 INI 文件。
+
+#### 成功求解后的 INI 输出文件示例
+
+```ini
+PLTSOLVD=T // T=true, F=false
+CRPIX1= 1.1645000000000000E+003 // 参考和中心像素的 X
+CRPIX2= 8.8050000000000000E+002 // 参考和中心像素的 Y
+CRVAL1= 1.5463033992314939E+002 // 参考像素的 RA (J2000) [度]
+CRVAL2= 2.2039358425145043E+001 // 参考像素的 DEC (J2000) [度]
+CDELT1=-7.4798001762187193E-004 // X 像素大小 [度]
+CDELT2= 7.4845252983311850E-004 // Y 像素大小 [度]
+CROTA1=-1.1668387329628058E+000 // X 轴图像扭曲 [度]
+CROTA2=-1.1900321176194073E+000 // Y 轴图像扭曲 [度]
+CD1_1=-7.4781868711882519E-004 // CD 矩阵将 (x,y) 转换为 (Ra, Dec)
+CD1_2= 1.5241315209850368E-005 // CD 矩阵将 (x,y) 转换为 (Ra, Dec)
+CD2_1= 1.5534412042060001E-005 // CD 矩阵将 (x,y) 转换为 (Ra, Dec)
+CD2_2= 7.4829732842251226E-004 // CD 矩阵将 (x,y) 转换为 (Ra, Dec)
+CMDLINE=...... // 包含使用的命令行的文本消息
+WARNING=...... // 包含警告的文本消息
+```
+
+#### 求解失败时的 INI 输出文件示例
+
+```ini
+PLTSOLVD=F // T=true, F=false
+CMDLINE=...... // 包含使用的命令行的文本消息
+ERROR= ..... // 包含任何错误的文本消息。与退出代码错误相同
+WARNING= ..... // 包含任何警告的文本消息
+```
+
+.wcs 文件包含原始 FITS 头文件,并添加了解决方案。没有数据,只有头文件。任何警告都使用关键字 WARNING 添加到 .wcs 文件中。此警告可以向用户显示以供信息。
+
+1. 注意 wcs 文件默认写为文本文件,每行使用回车和换行,不符合 FITS 标准。要使 .wcs 文件符合 FITS 标准,请添加命令行选项 -wcs。
+
+### 命令行,错误代码
+
+在命令行模式下,错误通过错误代码 / errorlevel {%errorlevel%} 报告。这与失败时在 .ini 文件中报告的错误相同。
+
+| 错误代码 | 描述 |
+| -------- | ------------------ |
+| 0 | 无错误 |
+| 1 | 无解决方案 |
+| 2 | 检测到的星数不足 |
+| 16 | 读取图像文件时出错 |
+| 32 | 未找到星数据库 |
+| 33 | 读取星数据库时出错 |
+| 34 | 更新输入文件时出错 |
+
+### 分析 FITS 文件
+
+要分析 FITS 文件,可以在 Windows 批处理文件中执行以下操作:
+
+```bash
+c:\astap.fpc\astap.exe -f c:\astap.fpc\test_files\command_line_test\m16.fit -analyse 30
+echo Exit Code is %errorlevel%
+pause
+```
+
+你将得到
+
+```bash
+Exit Code is 326000666
+```
+
+其中 HFD 为 3.26,使用 666 颗星
+
+对于 Linux 和 Mac,stdout 报告如下:
+
+```bash
+HFD_MEDIAN=3.3
+STARS=666
+```
+
+### -analyse 功能
+
+| 程序 | Windows | Linux | macOS |
+| --------- | ----------------- | ------ | ------ |
+| astap | 退出代码 | stdout | stdout |
+| astap_cli | 退出代码 & stdout | stdout | stdout |
+
+### 基于四个或更多输入图像找到最佳焦点
+
+```bash
+c:\astap.fpc\astap -focus1 D:\temp\FocusSample\FOCUS04689.fit -focus2 D:\temp\FocusSample\FOCUS05039.fit -focus3 D:\temp\FocusSample\FOCUS05389.fit -focus4 D:\temp\FocusSample\FOCUS05739.fit -focus5 D:\temp\FocusSample\FOCUS06089.fit -focus6 D:\temp\FocusSample\FOCUS06439.fit -focus7 D:\temp\FocusSample\FOCUS06789.fit -focus8 D:\temp\FocusSample\FOCUS07139.fit
+echo Exit Code is %errorlevel%
+pause
+```
+
+或使用 -debug 选项
+
+```bash
+astap.exe -debug -focus1 D:\temp\FocusSample\FOCUS04689.fit -focus2 D:\temp\FocusSample\FOCUS05039.fit -focus3 D:\temp\FocusSample\FOCUS05389.fit -focus4 D:\temp\FocusSample\FOCUS05739.fit -focus5 D:\temp\FocusSample\FOCUS06089.fit -focus6 D:\temp\FocusSample\FOCUS06439.fit -focus7 D:\temp\FocusSample\FOCUS06789.fit -focus8 D:\temp\FocusSample\FOCUS07139.fit
+```
+
+然后选择 "inspector" 标签并点击 "hyperbola curve fitting button" 以测试功能。
+
+以下是命令行输出的示例:
+
+此选项不适用于 astap_cli 版本。
+
+### 命令行弹出通知器
+
+如果 ASTAP 在 MS-Windows 中通过命令行执行,它将显示在状态栏右侧的小 ASTAP 托盘图标。如果将鼠标移到 ASTAP 托盘图标上,提示将显示搜索半径。要刷新值,请将鼠标移开再移回。
+
+如果搜索螺旋已从起始位置达到 2 度以上的距离,则弹出通知器将显示实际搜索距离和求解器设置:
+
+第一行指示从起始位置的搜索螺旋距离(8º)和最大搜索半径(90º)
+图像高度,单位为度。
+降采样设置和输入图像的尺寸以进行求解。
+起始位置的 α 和 δ。
+速度正常(▶▶)或小步(▶)
+
+查看解决求解失败所需的条件。或测试图像是否可求解。
+在最新的 Win10 版本中,托盘图标默认关闭。要设置 ASTAP 托盘图标,请通过成像程序启动求解,转到 Windows "设置","任务栏","打开或关闭系统图标",并将 ASTAP 托盘图标永久设置为 "打开",如下所示:
+
+### 盲求解性能
+
+90 度偏移的盲求解性能:
+
+ASTAP 盲求解器性能,90 度偏移。
+
+求解曝光 50 秒的 M16 单色图像,2328x1760 像素,覆盖 1.75 x 1.32° 的视场,起始位置偏北 90 度。使用的数据库为 D50
+
+| 最大星数 | 天文测量求解时间 |
+| -------- | ---------------- |
+| 500 | 23.8 秒 |
+| 300 | 9.8 秒 |
+| 200 | 6.7 秒 |
+| 100 | 4.8 秒 |
+
+减少 "最大星数" 将导致求解更快,但也会增加求解失败的风险。
diff --git a/doc/server/oatpp_coroutine.md b/doc/server/oatpp_coroutine.md
new file mode 100644
index 00000000..a367ed6d
--- /dev/null
+++ b/doc/server/oatpp_coroutine.md
@@ -0,0 +1,235 @@
+# Oat++ 中的协程
+
+Oat++ 中的协程不是普通的协程。
+Oat++ 实现了自定义的无状态协程,并带有调度功能。调度提供了优化的空间,并更好地利用了 CPU 资源。
+
+Oat++ 中的协程通过 [oatpp::async::Executor](/api/latest/oatpp/core/async/Executor/) 执行。在每次迭代中,协程返回一个 [oatpp::async::Action](/api/latest/oatpp/core/async/Coroutine/#action),告诉执行器下一步该做什么。
+根据 Action,Oat++ 异步处理器将协程重新调度到相应的 worker。
+
+## 异步执行器
+
+[oatpp::async::Executor](/api/latest/oatpp/core/async/Executor/) 分配了三组 worker,每组指定数量的线程。
+
+```cpp
+oatpp::async::Executor executor(
+ 1 /* 数据处理 worker */,
+ 1 /* I/O worker */,
+ 1 /* 定时器 worker */
+);
+```
+
+所有协程最初都被放置在“数据处理” worker 组中,并可能根据协程迭代中返回的 [oatpp::async::Action](/api/latest/oatpp/core/async/Coroutine/#action) 重新调度到 I/O 或定时器 worker。
+
+
+
+::: tip
+尽管 Oat++ 异步处理器可能会将协程重新调度到不同的线程,但协程保证会在创建它的同一线程上被销毁。
+:::
+
+### I/O Worker
+
+对于 I/O,`oatpp::async::Executor` 使用基于事件的 I/O 实现 [IOEventWorker](/api/latest/oatpp/core/async/worker/IOEventWorker/):
+
+- kqueue 实现 - 适用于 Mac/BSD 系统。
+- epoll 实现 - 适用于 Linux 系统。
+
+当协程返回类型为 [TYPE_IO_WAIT](/api/latest/oatpp/core/async/Coroutine/#action-type-io-wait) 的 Action 时,它将被重新调度到 I/O worker,并将文件描述符提供的 Action 放置到 kqueue/epoll 中。
+**因此,oatpp 协程不会浪费 CPU 资源来旋转和轮询长时间等待的连接。**
+
+## API
+
+在 oatpp 中,协程是从 [oatpp::async::Coroutine](/api/latest/oatpp/core/async/Coroutine/#coroutine) 或 [oatpp::async::CoroutineWithResult](/api/latest/oatpp/core/async/Coroutine/#coroutinewithresult) 扩展的类。
+协程在 [oatpp::async::Executor](/api/latest/oatpp/core/async/Executor/) 中处理。
+
+```cpp
+class MyCoroutine : public oatpp::async::Coroutine {
+public:
+
+ /*
+ * act() - 协程的入口点
+ * 返回 Action - 下一步该做什么
+ */
+ Action act() override {
+ OATPP_LOGD("MyCoroutine", "act()");
+ return yieldTo(&MyCoroutine::step2);
+ }
+
+ Action step2() {
+ OATPP_LOGD("MyCoroutine", "step2");
+ return yieldTo(&MyCoroutine::step3);
+ }
+
+ Action step3() {
+ OATPP_LOGD("MyCoroutine", "step3");
+ return finish();
+ }
+
+};
+
+oatpp::async::Executor executor();
+
+executor.execute();
+
+executor.waitTasksFinished();
+executor.stop();
+executor.join();
+```
+
+输出:
+
+```
+MyCoroutine:act()
+MyCoroutine:step2
+MyCoroutine:step3
+```
+
+## 从协程调用协程
+
+```cpp
+class OtherCoroutine : public oatpp::async::Coroutine {
+public:
+ Action act() override {
+ OATPP_LOGD("OtherCoroutine", "act()");
+ return finish();
+ }
+};
+
+class MyCoroutine : public oatpp::async::Coroutine {
+public:
+
+ Action act() override {
+ OATPP_LOGD("MyCoroutine", "act()");
+ return OtherCoroutine::start().next(finish()); /* 在 OtherCoroutine 完成后执行的 Action */);
+ }
+
+};
+
+oatpp::async::Executor executor();
+
+executor.execute();
+
+executor.waitTasksFinished();
+executor.stop();
+executor.join();
+```
+
+输出:
+
+```
+MyCoroutine:act()
+OtherCoroutine:act()
+```
+
+## 调用协程并返回结果
+
+```cpp
+class CoroutineWithResult : public oatpp::async::CoroutineWithResult {
+public:
+ Action act() override {
+ OATPP_LOGD("CoroutineWithResult", "act()");
+ return _return("");
+ }
+};
+
+class MyCoroutine : public oatpp::async::Coroutine {
+public:
+
+ Action act() override {
+ OATPP_LOGD("MyCoroutine", "act()");
+ return CoroutineWithResult::startForResult().callbackTo(&MyCoroutine::onResult);
+ }
+
+ Action onResult(const char* result) {
+ OATPP_LOGD("MyCoroutine", "result='%s'", result);
+ return finish();
+ }
+
+};
+
+oatpp::async::Executor executor();
+
+executor.execute();
+
+executor.waitTasksFinished();
+executor.stop();
+executor.join();
+```
+
+输出:
+
+```
+MyCoroutine:act()
+CoroutineWithResult:act()
+MyCoroutine:result=''
+```
+
+## 计数器
+
+```cpp
+class MyCoroutineCounter : public oatpp::async::Coroutine {
+private:
+ const char* m_name;
+ v_int32 m_counter = 0;
+public:
+
+ MyCoroutineCounter(const char* name) : m_name(name) {}
+
+ Action act() override {
+ OATPP_LOGD(m_name, "counter=%d", m_counter);
+ if(m_counter < 10) {
+ m_counter ++;
+ return repeat();
+ }
+ return finish();
+ }
+
+};
+
+oatpp::async::Executor executor();
+
+executor.execute("A");
+executor.execute("B");
+executor.execute("C");
+
+executor.waitTasksFinished();
+executor.stop();
+executor.join();
+```
+
+可能的输出:
+
+```
+A:counter=0
+B:counter=0
+C:counter=0
+A:counter=1
+B:counter=1
+C:counter=1
+A:counter=2
+B:counter=2
+C:counter=2
+A:counter=3
+B:counter=3
+C:counter=3
+A:counter=4
+B:counter=4
+C:counter=4
+A:counter=5
+B:counter=5
+C:counter=5
+A:counter=6
+B:counter=6
+C:counter=6
+A:counter=7
+B:counter=7
+C:counter=7
+A:counter=8
+B:counter=8
+C:counter=8
+A:counter=9
+B:counter=9
+C:counter=9
+A:counter=10
+B:counter=10
+C:counter=10
+```
diff --git a/example/atom/algorithm/CMakeLists.txt b/example/atom/algorithm/CMakeLists.txt
deleted file mode 100644
index 6d3af3bc..00000000
--- a/example/atom/algorithm/CMakeLists.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-
-# 项目名称
-project(AutoTargets VERSION 1.0 LANGUAGES CXX)
-
-# 设置目标源文件路径
-set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-
-# 递归查找当前目录及其子目录下的所有 .cpp 文件
-file(GLOB_RECURSE cpp_files "${SOURCE_DIR}/*.cpp")
-
-# 设置编译选项
-set(CMAKE_CXX_STANDARD 17) # 设置C++标准
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-set(CMAKE_CXX_EXTENSIONS OFF)
-
-# 创建一个用于存放所有目标的输出目录
-set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/bin)
-
-# 创建一个包含目录,用于存储头文件
-include_directories(${SOURCE_DIR}/include)
-
-# 遍历所有的cpp文件,为每个生成一个可执行文件目标
-foreach(cpp_file ${cpp_files})
- # 获取文件名(不带路径和后缀)
- get_filename_component(target_name ${cpp_file} NAME_WE)
-
- # 为每个 .cpp 文件生成一个可执行文件目标
- add_executable(${target_name} ${cpp_file})
-
- # 设置每个目标的输出目录
- set_target_properties(${target_name} PROPERTIES
- RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}
- )
-
- # 为每个目标设置不同的编译选项
- target_compile_options(${target_name} PRIVATE
- $<$:-g> # Debug 模式下的编译选项
- $<$:-O3> # Release 模式下的编译选项
- -Wall -Wextra # 所有模式的编译警告
- )
-
- # 如果需要链接一些外部库,可以通过 target_link_libraries
- # target_link_libraries(${target_name} PRIVATE some_library)
-
- # 打印每个目标的生成情况
- message(STATUS "Added target: ${target_name} from source: ${cpp_file}")
-endforeach()
-
-# 打印输出目录信息
-message(STATUS "All binaries will be output to: ${OUTPUT_DIR}")
diff --git a/example/atom/algorithm/algorithm.cpp b/example/atom/algorithm/algorithm.cpp
deleted file mode 100644
index b1d0cb7d..00000000
--- a/example/atom/algorithm/algorithm.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#include "atom/algorithm/algorithm.hpp"
-
-#include
-
-int main() {
- // Example 1: Using the KMP algorithm
- std::string text = "ababcabcababcabc";
- std::string pattern = "abc";
-
- // Create a KMP object with the pattern
- atom::algorithm::KMP kmp(pattern);
-
- // Search for the pattern in the text
- std::vector kmpResults = kmp.search(text);
-
- std::cout << "KMP search results for pattern \"" << pattern
- << "\" in text \"" << text << "\":" << std::endl;
- for (int position : kmpResults) {
- std::cout << "Pattern found at position: " << position << std::endl;
- }
-
- // Example 2: Using the Boyer-Moore algorithm
- std::string bmText = "HERE IS A SIMPLE EXAMPLE";
- std::string bmPattern = "EXAMPLE";
-
- // Create a BoyerMoore object with the pattern
- atom::algorithm::BoyerMoore boyerMoore(bmPattern);
-
- // Search for the pattern in the text
- std::vector bmResults = boyerMoore.search(bmText);
-
- std::cout << "Boyer-Moore search results for pattern \"" << bmPattern
- << "\" in text \"" << bmText << "\":" << std::endl;
- for (int position : bmResults) {
- std::cout << "Pattern found at position: " << position << std::endl;
- }
-
- // Example 3: Using the Bloom Filter
- const std::size_t BLOOM_FILTER_SIZE = 100;
- const std::size_t NUM_HASH_FUNCTIONS = 3;
-
- // Create a BloomFilter object with specified size and number of hash
- // functions
- atom::algorithm::BloomFilter bloomFilter(
- NUM_HASH_FUNCTIONS);
-
- // Insert elements into the Bloom filter
- bloomFilter.insert("apple");
- bloomFilter.insert("banana");
- bloomFilter.insert("cherry");
-
- // Check for the presence of elements
- std::string element1 = "apple";
- std::string element2 = "grape";
-
- std::cout << "Checking presence of \"" << element1
- << "\" in the Bloom filter: "
- << (bloomFilter.contains(element1) ? "Possibly present"
- : "Definitely not present")
- << std::endl;
-
- std::cout << "Checking presence of \"" << element2
- << "\" in the Bloom filter: "
- << (bloomFilter.contains(element2) ? "Possibly present"
- : "Definitely not present")
- << std::endl;
-
- return 0;
-}
diff --git a/example/atom/algorithm/base.cpp b/example/atom/algorithm/base.cpp
deleted file mode 100644
index 6b85db69..00000000
--- a/example/atom/algorithm/base.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "atom/algorithm/base.hpp"
-
-#include
-
-int main() {
- {
- std::string originalText = "Hello, World!";
- std::string encodedText = atom::algorithm::base64Encode(originalText);
-
- std::cout << "Original: " << originalText << std::endl;
- std::cout << "Encoded: " << encodedText << std::endl;
- }
- {
- std::string encodedText = "SGVsbG8sIFdvcmxkIQ==";
- std::string decodedText = atom::algorithm::base64Decode(encodedText);
-
- std::cout << "Encoded: " << encodedText << std::endl;
- std::cout << "Decoded: " << decodedText << std::endl;
- }
- {
- std::vector data = {'H', 'e', 'l', 'l', 'o'};
- std::string encodedText = atom::algorithm::fbase64Encode(data);
-
- std::cout << "Encoded: " << encodedText << std::endl;
- }
- {
- std::string encodedText = "SGVsbG8=";
- std::vector decodedData =
- atom::algorithm::fbase64Decode(encodedText);
-
- std::cout << "Decoded: ";
- for (unsigned char c : decodedData) {
- std::cout << c;
- }
- std::cout << std::endl;
- }
- {
- std::string plaintext = "EncryptMe";
- uint8_t key = 0xAA;
- std::string encryptedText = atom::algorithm::xorEncrypt(plaintext, key);
-
- std::cout << "Plaintext: " << plaintext << std::endl;
- std::cout << "Encrypted: " << encryptedText << std::endl;
- }
- {
- std::string encryptedText = "EncryptedStringHere";
- uint8_t key = 0xAA;
- std::string decryptedText =
- atom::algorithm::xorDecrypt(encryptedText, key);
-
- std::cout << "Encrypted: " << encryptedText << std::endl;
- std::cout << "Decrypted: " << decryptedText << std::endl;
- }
- {
- constexpr StaticString<5> INPUT = "Hello";
- constexpr auto ENCODED = atom::algorithm::cbase64Encode(INPUT);
-
- std::cout << "Compile-time Encoded: " << ENCODED.cStr() << std::endl;
- }
- {
- constexpr StaticString<8> INPUT = "SGVsbG8=";
- constexpr auto DECODED = atom::algorithm::cbase64Decode(INPUT);
-
- std::cout << "Compile-time Decoded: " << DECODED.cStr() << std::endl;
- }
- return 0;
-}
diff --git a/example/atom/algorithm/bignumber.cpp b/example/atom/algorithm/bignumber.cpp
deleted file mode 100644
index b0408654..00000000
--- a/example/atom/algorithm/bignumber.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-#include "atom/algorithm/bignumber.hpp"
-
-#include
-
-int main() {
- {
- atom::algorithm::BigNumber num1("12345678901234567890");
- atom::algorithm::BigNumber num2(9876543210LL);
-
- std::cout << "num1: " << num1 << std::endl;
- std::cout << "num2: " << num2 << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("12345678901234567890");
- atom::algorithm::BigNumber num2("98765432109876543210");
-
- atom::algorithm::BigNumber sum = num1 + num2;
- atom::algorithm::BigNumber difference = num2 - num1;
-
- std::cout << "Sum: " << sum << std::endl;
- std::cout << "Difference: " << difference << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("123456789");
- atom::algorithm::BigNumber num2("1000");
-
- atom::algorithm::BigNumber product = num1 * num2;
- atom::algorithm::BigNumber quotient = num1 / num2;
-
- std::cout << "Product: " << product << std::endl;
- std::cout << "Quotient: " << quotient << std::endl;
- }
-
- {
- atom::algorithm::BigNumber base("2");
-
- atom::algorithm::BigNumber result = base ^ 10;
-
- std::cout << "2^10: " << result << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("123456789");
- atom::algorithm::BigNumber num2("123456789");
- atom::algorithm::BigNumber num3("987654321");
-
- std::cout << std::boolalpha;
- std::cout << "num1 == num2: " << (num1 == num2) << std::endl;
- std::cout << "num1 != num3: " << (num1 != num3) << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("123456789");
- atom::algorithm::BigNumber num2("987654321");
-
- std::cout << std::boolalpha;
- std::cout << "num1 < num2: " << (num1 < num2) << std::endl;
- std::cout << "num2 > num1: " << (num2 > num1) << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("123456789");
-
- atom::algorithm::BigNumber negated = num1.negate();
-
- std::cout << "Negated: " << negated << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("999");
-
- std::cout << "Before increment: " << num1 << std::endl;
- ++num1;
- std::cout << "After increment: " << num1 << std::endl;
-
- --num1;
- std::cout << "After decrement: " << num1 << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("123456789");
- atom::algorithm::BigNumber num2("123456788");
-
- std::cout << "num1 is odd: " << std::boolalpha << num1.isOdd()
- << std::endl;
- std::cout << "num2 is even: " << std::boolalpha << num2.isEven()
- << std::endl;
- }
-
- {
- atom::algorithm::BigNumber num1("0000123456789");
-
- std::cout << "Before trimming: " << num1 << std::endl;
- num1 = num1.trimLeadingZeros();
- std::cout << "After trimming: " << num1 << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/convolve.cpp b/example/atom/algorithm/convolve.cpp
deleted file mode 100644
index ac8ef3e8..00000000
--- a/example/atom/algorithm/convolve.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-#include "atom/algorithm/convolve.hpp"
-
-#include
-
-int main() {
- {
- std::vector signal = {1, 2, 3, 4, 5};
- std::vector kernel = {0.2, 0.5, 0.2};
-
- std::vector result = atom::algorithm::convolve(signal, kernel);
-
- std::cout << "1D Convolution result: ";
- for (double val : result) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
-
- {
- std::vector signal = {0.2, 0.9, 2.0, 3.1, 2.8, 1.0};
- std::vector kernel = {0.2, 0.5, 0.2};
-
- std::vector result =
- atom::algorithm::deconvolve(signal, kernel);
-
- std::cout << "1D Deconvolution result: ";
- for (double val : result) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
-
- {
- std::vector> image = {
- {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
- std::vector> kernel = {
- {1, 0, -1}, {1, 0, -1}, {1, 0, -1}};
-
- std::vector> result =
- atom::algorithm::convolve2D(image, kernel);
-
- std::cout << "2D Convolution result:" << std::endl;
- for (const auto& row : result) {
- for (double val : row) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
- }
-
- {
- std::vector> image = {
- {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
- std::vector> kernel = {
- {1, 0, -1}, {1, 0, -1}, {1, 0, -1}};
-
- std::vector> result =
- atom::algorithm::deconvolve2D(image, kernel);
-
- std::cout << "2D Deconvolution result:" << std::endl;
- for (const auto& row : result) {
- for (double val : row) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
- }
-
- {
- std::vector> image = {
- {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
-
- std::vector>> result =
- atom::algorithm::dfT2D(image);
-
- std::cout << "2D DFT result:" << std::endl;
- for (const auto& row : result) {
- for (const auto& val : row) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
- }
-
- {
- std::vector>> spectrum = {
- {std::complex(45, 0),
- std::complex(-4.5, 2.598076211353316)},
- {std::complex(-13.5, 7.794228634059948),
- std::complex(0, 0)},
- {std::complex(-13.5, -7.794228634059948),
- std::complex(-4.5, -2.598076211353316)}};
-
- std::vector> result =
- atom::algorithm::idfT2D(spectrum);
-
- std::cout << "2D IDFT result:" << std::endl;
- for (const auto& row : result) {
- for (double val : row) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
- }
-
- {
- int size = 5;
- double sigma = 1.0;
-
- std::vector> kernel =
- atom::algorithm::generateGaussianKernel(size, sigma);
-
- std::cout << "Gaussian Kernel:" << std::endl;
- for (const auto& row : kernel) {
- for (double val : row) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
- }
-
- {
- std::vector> image = {
- {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
-
- int size = 3;
- double sigma = 1.0;
- std::vector> kernel =
- atom::algorithm::generateGaussianKernel(size, sigma);
-
- std::vector> result =
- atom::algorithm::applyGaussianFilter(image, kernel);
-
- std::cout << "Gaussian Filter result:" << std::endl;
- for (const auto& row : result) {
- for (double val : row) {
- std::cout << val << " ";
- }
- std::cout << std::endl;
- }
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/fnmatch.cpp b/example/atom/algorithm/fnmatch.cpp
deleted file mode 100644
index 6a1b1eca..00000000
--- a/example/atom/algorithm/fnmatch.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "atom/algorithm/fnmatch.hpp"
-
-#include
-
-int main() {
- {
- std::string pattern = "*.cpp";
- std::string filename = "main.cpp";
-
- bool match = atom::algorithm::fnmatch(pattern, filename);
- if (match) {
- std::cout << filename << " matches the pattern " << pattern
- << std::endl;
- } else {
- std::cout << filename << " does not match the pattern " << pattern
- << std::endl;
- }
- }
-
- {
- std::vector filenames = {"main.cpp", "README.md",
- "fnmatch.hpp"};
- std::string pattern = "*.hpp";
-
- [[maybe_unused]] auto matches =
- atom::algorithm::filter(filenames, pattern);
-
- std::cout << "Files matching pattern:\n";
- }
-
- {
- std::vector filenames = {"main.cpp", "README.md",
- "fnmatch.hpp", "CMakeLists.txt"};
- std::vector patterns = {"*.cpp", "*.hpp"};
-
- std::vector matches =
- atom::algorithm::filter(filenames, patterns);
-
- std::cout << "Files matching patterns:\n";
- for (const auto& file : matches) {
- std::cout << file << std::endl;
- }
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/fraction.cpp b/example/atom/algorithm/fraction.cpp
deleted file mode 100644
index b25d9a34..00000000
--- a/example/atom/algorithm/fraction.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "atom/algorithm/fraction.hpp"
-
-#include
-#include
-
-int main() {
- {
- // Default constructor
- atom::algorithm::Fraction f1; // Represents 0/1
-
- // Parameterized constructor
- atom::algorithm::Fraction f2(3, 4); // Represents 3/4
-
- // Printing fractions
- std::cout << "Fraction f1: " << f1.toString()
- << std::endl; // Output: "0/1"
- std::cout << "Fraction f2: " << f2.toString()
- << std::endl; // Output: "3/4"
- }
-
- {
- atom::algorithm::Fraction f1(1, 2); // Represents 1/2
- atom::algorithm::Fraction f2(3, 4); // Represents 3/4
-
- // Addition
- auto resultAdd = f1 + f2; // 1/2 + 3/4 = 5/4
- std::cout << "Addition result: " << resultAdd.toString()
- << std::endl; // Output: "5/4"
-
- // Subtraction
- auto resultSub = f1 - f2; // 1/2 - 3/4 = -1/4
- std::cout << "Subtraction result: " << resultSub.toString()
- << std::endl; // Output: "-1/4"
-
- // Multiplication
- auto resultMul = f1 * f2; // 1/2 * 3/4 = 3/8
- std::cout << "Multiplication result: " << resultMul.toString()
- << std::endl; // Output: "3/8"
-
- // Division
- auto resultDiv = f1 / f2; // 1/2 / 3/4 = 2/3
- std::cout << "Division result: " << resultDiv.toString()
- << std::endl; // Output: "2/3"
- }
-
- {
- atom::algorithm::Fraction f1(1, 2); // Represents 1/2
- atom::algorithm::Fraction f2(3, 4); // Represents 3/4
-
- f1 += f2; // f1 now represents 5/4
- std::cout << "After addition assignment: " << f1.toString()
- << std::endl; // Output: "5/4"
-
- f1 -= f2; // f1 now represents 1/2
- std::cout << "After subtraction assignment: " << f1.toString()
- << std::endl; // Output: "1/2"
-
- f1 *= f2; // f1 now represents 3/8
- std::cout << "After multiplication assignment: " << f1.toString()
- << std::endl; // Output: "3/8"
-
- f1 /= f2; // f1 now represents 1/2
- std::cout << "After division assignment: " << f1.toString()
- << std::endl; // Output: "1/2"
- }
-
- {
- atom::algorithm::Fraction f(3, 4); // Represents 3/4
-
- double d = static_cast(f); // Converts to double
- std::cout << "Fraction as double: " << d << std::endl; // Output: 0.75
-
- float fl = static_cast(f); // Converts to float
- std::cout << "Fraction as float: " << fl << std::endl; // Output: 0.75
-
- int i = static_cast(f); // Converts to int (truncates to 0)
- std::cout << "Fraction as int: " << i << std::endl; // Output: 0
- }
-
- {
- // Output to stream
- atom::algorithm::Fraction f(5, 6); // Represents 5/6
- std::ostringstream oss;
- oss << f;
- std::cout << "Fraction as stream output: " << oss.str()
- << std::endl; // Output: "5/6"
-
- // Input from stream
- atom::algorithm::Fraction fInput;
- std::istringstream iss("7 8"); // Represents 7/8
- iss >> fInput;
- std::cout << "Fraction after input: " << fInput.toString()
- << std::endl; // Output: "7/8"
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/hash.cpp b/example/atom/algorithm/hash.cpp
deleted file mode 100644
index c267b0d1..00000000
--- a/example/atom/algorithm/hash.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include "atom/algorithm/hash.hpp"
-
-#include
-
-int main() {
- {
- int number = 42;
- std::size_t numberHash = atom::algorithm::computeHash(number);
-
- std::cout << "Hash of integer 42: " << numberHash << std::endl;
- }
-
- {
- std::string text = "Hello, World!";
- std::size_t textHash = atom::algorithm::computeHash(text);
-
- std::cout << "Hash of string \"Hello, World!\": " << textHash
- << std::endl;
- }
-
- {
- std::vector values = {1, 2, 3, 4, 5};
- std::size_t vectorHash = atom::algorithm::computeHash(values);
-
- std::cout << "Hash of vector {1, 2, 3, 4, 5}: " << vectorHash
- << std::endl;
- }
-
- {
- auto myTuple = std::make_tuple(1, 2.5, "text");
- std::size_t tupleHash = atom::algorithm::computeHash(myTuple);
-
- std::cout << "Hash of tuple (1, 2.5, \"text\"): " << tupleHash
- << std::endl;
- }
-
- {
- std::array myArray = {10, 20, 30};
- std::size_t arrayHash = atom::algorithm::computeHash(myArray);
-
- std::cout << "Hash of array {10, 20, 30}: " << arrayHash << std::endl;
- }
-
- {
- const char* cstr = "example";
- unsigned int hashValue = hash(cstr);
-
- std::cout << "Hash of C-string \"example\": " << hashValue << std::endl;
- }
-
- {
- constexpr unsigned int literalHash = "example"_hash;
-
- std::cout << "Hash of string literal \"example\": " << literalHash
- << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/huffman.cpp b/example/atom/algorithm/huffman.cpp
deleted file mode 100644
index 3e1545c1..00000000
--- a/example/atom/algorithm/huffman.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "atom/algorithm/huffman.hpp"
-
-#include
-#include
-
-int main() {
- {
- // Frequency map for characters
- std::unordered_map frequencies = {
- {'a', 5}, {'b', 9}, {'c', 12}, {'d', 13}, {'e', 16}, {'f', 45}};
-
- // Create Huffman Tree
- auto huffmanTree = atom::algorithm::createHuffmanTree(frequencies);
-
- if (huffmanTree) {
- std::cout << "Huffman tree created successfully." << std::endl;
- }
- }
-
- {
- // Example frequency map
- std::unordered_map frequencies = {
- {'a', 5}, {'b', 9}, {'c', 12}, {'d', 13}, {'e', 16}, {'f', 45}};
-
- // Create Huffman Tree
- auto huffmanTree = atom::algorithm::createHuffmanTree(frequencies);
-
- // Generate Huffman Codes
- std::unordered_map huffmanCodes;
- atom::algorithm::generateHuffmanCodes(huffmanTree.get(), "",
- huffmanCodes);
-
- // Print Huffman Codes
- for (const auto& pair : huffmanCodes) {
- std::cout << "Character: " << pair.first
- << ", Code: " << pair.second << std::endl;
- }
- }
-
- {
- // Example frequency map
- std::unordered_map frequencies = {
- {'a', 5}, {'b', 9}, {'c', 12}, {'d', 13}, {'e', 16}, {'f', 45}};
-
- // Create Huffman Tree
- auto huffmanTree = atom::algorithm::createHuffmanTree(frequencies);
-
- // Generate Huffman Codes
- std::unordered_map huffmanCodes;
- atom::algorithm::generateHuffmanCodes(huffmanTree.get(), "",
- huffmanCodes);
-
- // Example text
- std::string text = "abcdef";
-
- // Compress Text
- std::string compressedText =
- atom::algorithm::compressText(text, huffmanCodes);
-
- std::cout << "Compressed Text: " << compressedText << std::endl;
- }
-
- {
- // Example frequency map
- std::unordered_map frequencies = {
- {'a', 5}, {'b', 9}, {'c', 12}, {'d', 13}, {'e', 16}, {'f', 45}};
-
- // Create Huffman Tree
- auto huffmanTree = atom::algorithm::createHuffmanTree(frequencies);
-
- // Generate Huffman Codes
- std::unordered_map huffmanCodes;
- atom::algorithm::generateHuffmanCodes(huffmanTree.get(), "",
- huffmanCodes);
-
- // Example text
- std::string text = "abcdef";
-
- // Compress Text
- std::string compressedText =
- atom::algorithm::compressText(text, huffmanCodes);
-
- // Decompress Text
- std::string decompressedText =
- atom::algorithm::decompressText(compressedText, huffmanTree.get());
-
- std::cout << "Decompressed Text: " << decompressedText << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/math.cpp b/example/atom/algorithm/math.cpp
deleted file mode 100644
index 2a2fd15d..00000000
--- a/example/atom/algorithm/math.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#include "atom/algorithm/math.hpp"
-
-#include
-
-int main() {
- {
- uint64_t a = 100000000000ULL;
- uint64_t b = 200000000000ULL;
- uint64_t result = atom::algorithm::safeAdd(a, b);
-
- std::cout << "Safe Addition Result: " << result << std::endl;
- }
-
- {
- uint64_t a = 300000000000ULL;
- uint64_t b = 100000000000ULL;
- uint64_t result = atom::algorithm::safeSub(a, b);
-
- std::cout << "Safe Subtraction Result: " << result << std::endl;
- }
-
- {
- uint64_t a = 300000ULL;
- uint64_t b = 100000ULL;
- uint64_t result = atom::algorithm::safeMul(a, b);
-
- std::cout << "Safe Multiplication Result: " << result << std::endl;
- }
-
- {
- uint64_t a = 100ULL;
- uint64_t b = 4ULL;
- uint64_t result = atom::algorithm::safeDiv(a, b);
-
- std::cout << "Safe Division Result: " << result << std::endl;
- }
-
- {
- uint64_t operant = 10;
- uint64_t multiplier = 20;
- uint64_t divider = 5;
-
- uint64_t result =
- atom::algorithm::mulDiv64(operant, multiplier, divider);
-
- std::cout << "Result of (10 * 20) / 5: " << result << std::endl;
- }
-
- {
- uint64_t n = 0x1234567890ABCDEF;
- unsigned int c = 8; // Rotate left by 8 bits
-
- uint64_t result = atom::algorithm::rotl64(n, c);
-
- std::cout << "Rotate Left Result: " << std::hex << result << std::endl;
- }
-
- {
- uint64_t n = 0x1234567890ABCDEF;
- unsigned int c = 8; // Rotate right by 8 bits
-
- uint64_t result = atom::algorithm::rotr64(n, c);
-
- std::cout << "Rotate Right Result: " << std::hex << result << std::endl;
- }
-
- {
- uint64_t x = 0x00F0;
-
- int leadingZeros = atom::algorithm::clz64(x);
-
- std::cout << "Leading Zeros in 0x00F0: " << leadingZeros << std::endl;
- }
-
- {
- uint64_t a = 48;
- uint64_t b = 180;
-
- uint64_t gcdResult = atom::algorithm::gcd64(a, b);
- uint64_t lcmResult = atom::algorithm::lcm64(a, b);
-
- std::cout << "GCD of 48 and 180: " << gcdResult << std::endl;
- std::cout << "LCM of 48 and 180: " << lcmResult << std::endl;
- }
-
- {
- uint64_t n = 16; // Power of two
- bool result = atom::algorithm::isPowerOfTwo(n);
-
- std::cout << n << " is a power of two: " << (result ? "true" : "false")
- << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/md5.cpp b/example/atom/algorithm/md5.cpp
deleted file mode 100644
index da08fad8..00000000
--- a/example/atom/algorithm/md5.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "atom/algorithm/md5.hpp"
-
-#include
-
-int main() {
- {
- // Example strings to hash
- std::string test1 = "Hello, World!";
- std::string test2 = "The quick brown fox jumps over the lazy dog";
- std::string test3 = "MD5 Hash Example";
-
- // Call the encrypt method and output the result
- std::string hash1 = atom::algorithm::MD5::encrypt(test1);
- std::string hash2 = atom::algorithm::MD5::encrypt(test2);
- std::string hash3 = atom::algorithm::MD5::encrypt(test3);
-
- // Output the results
- std::cout << "MD5(\"" << test1 << "\") = " << hash1 << std::endl;
- std::cout << "MD5(\"" << test2 << "\") = " << hash2 << std::endl;
- std::cout << "MD5(\"" << test3 << "\") = " << hash3 << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/algorithm/mhash.cpp b/example/atom/algorithm/mhash.cpp
deleted file mode 100644
index afaf9ed3..00000000
--- a/example/atom/algorithm/mhash.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "atom/algorithm/mhash.hpp"
-
-int main() {
- // Create some example sets for which we want to compute MinHash signatures.
- std::set set1 = {"apple", "banana", "cherry"};
- std::set set2 = {"banana", "cherry", "date", "fig"};
-
- // Specify the number of hash functions to use
- size_t numHashes = 100;
-
- // Create MinHash instance
- atom::algorithm::MinHash minHash(numHashes);
-
- // Compute MinHash signatures for both sets
- auto signature1 = minHash.computeSignature(set1);
- auto signature2 = minHash.computeSignature(set2);
-
- // Output the MinHash signatures
- std::cout << "MinHash Signature for Set 1: ";
- for (const auto& hash : signature1) {
- std::cout << hash << " ";
- }
- std::cout << std::endl;
-
- std::cout << "MinHash Signature for Set 2: ";
- for (const auto& hash : signature2) {
- std::cout << hash << " ";
- }
- std::cout << std::endl;
-
- // Compute the Jaccard index between the two sets
- double jaccardIdx =
- atom::algorithm::MinHash::jaccardIndex(signature1, signature2);
- std::cout << "Estimated Jaccard Index between Set 1 and Set 2: "
- << jaccardIdx << std::endl;
-
- return 0;
-}
diff --git a/example/atom/algorithm/perlin.cpp b/example/atom/algorithm/perlin.cpp
deleted file mode 100644
index 592ecdfb..00000000
--- a/example/atom/algorithm/perlin.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include
-#include
-
-#include "atom/algorithm/perlin.hpp"
-
-int main() {
- // Create a PerlinNoise object with a default seed
- atom::algorithm::PerlinNoise perlin;
-
- // Generate a noise value at a specific point (x, y, z)
- double x = 10.5, y = 20.5, z = 30.5;
- double noiseValue = perlin.noise(x, y, z);
- std::cout << "Noise Value at (" << x << ", " << y << ", " << z
- << "): " << noiseValue << std::endl;
-
- // Generate a noise map
- int width = 100; // Width of the noise map
- int height = 100; // Height of the noise map
- double scale = 50.0; // Scale for the noise
- int octaves = 4; // Number of octaves for the noise
- double persistence = 0.5; // Persistence for the noise
-
- auto noiseMap = perlin.generateNoiseMap(width, height, scale, octaves,
- persistence, 0.5);
-
- // Output the first row of the noise map as an example
- std::cout << "Noise Map (first row):" << std::endl;
- for (const auto& value : noiseMap[0]) {
- std::cout << value << " ";
- }
- std::cout << std::endl;
-
- return 0;
-}
diff --git a/example/atom/algorithm/weight.cpp b/example/atom/algorithm/weight.cpp
deleted file mode 100644
index aca52747..00000000
--- a/example/atom/algorithm/weight.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "atom/algorithm/weight.hpp"
-
-#include
-#include
-#include
-#include
-
-int main() {
- // Sample weights
- std::vector weights = {1.0, 2.0, 3.0, 4.0, 5.0};
-
- // Create a WeightSelector instance with default selection strategy
- atom::algorithm::WeightSelector selector(weights);
-
- // Select a single weight based on the defined strategy
- size_t selectedIndex = selector.select();
- std::cout << "Selected index (default strategy): " << selectedIndex
- << " with weight: " << weights[selectedIndex] << std::endl;
-
- // Select multiple weights
- size_t n = 3; // Number of selections
- auto chosenIndices = selector.selectMultiple(n);
- std::cout << "Selected indices for " << n << " selections: ";
- for (size_t index : chosenIndices) {
- std::cout << index << " (weight: " << weights[index] << "), ";
- }
- std::cout << std::endl;
-
- // Update a weight
- size_t updateIndex = 2; // Change weight at index 2
- selector.updateWeight(updateIndex, 10.0);
- std::cout << "Updated weight at index " << updateIndex << " to 10.0."
- << std::endl;
-
- // Print current weights
- std::cout << "Current weights: ";
- selector.printWeights(std::cout);
-
- // Normalize weights
- selector.normalizeWeights();
- std::cout << "Normalized weights: ";
- selector.printWeights(std::cout);
-
- // Use TopHeavySelectionStrategy
- selector.setSelectionStrategy(
- std::make_unique>());
- size_t heavySelectedIndex = selector.select();
- std::cout << "Selected index (TopHeavy strategy): " << heavySelectedIndex
- << " with weight: " << weights[heavySelectedIndex] << std::endl;
-
- // Add a new weight
- selector.addWeight(6.0);
- std::cout << "Added weight 6.0. New weights: ";
- selector.printWeights(std::cout);
-
- // Remove weight
- selector.removeWeight(0); // remove the weight at index 0
- std::cout << "Removed weight at index 0. New weights: ";
- selector.printWeights(std::cout);
-
- // Get max and min weight indices
- size_t maxWeightIndex = selector.getMaxWeightIndex();
- size_t minWeightIndex = selector.getMinWeightIndex();
- std::cout << "Max weight index: " << maxWeightIndex
- << " (weight: " << weights[maxWeightIndex] << "), "
- << "Min weight index: " << minWeightIndex
- << " (weight: " << weights[minWeightIndex] << ")" << std::endl;
-
- return 0;
-}
diff --git a/example/atom/argsview.cpp b/example/atom/argsview.cpp
deleted file mode 100644
index 99bbc492..00000000
--- a/example/atom/argsview.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include
-#include
-
-#include "atom/type/argsview.hpp"
-
-int main() {
- // Example 1: Creating an ArgsView and accessing elements
- ArgsView argsView(42, 3.14, "Hello, World!");
- std::cout << "First element: " << argsView.get<0>() << "\n";
- std::cout << "Second element: " << argsView.get<1>() << "\n";
- std::cout << "Third element: " << argsView.get<2>() << "\n";
-
- // Example 2: Using forEach to print all elements
- std::cout << "All elements: ";
- argsView.forEach([](const auto& arg) { std::cout << arg << " "; });
- std::cout << "\n";
-
- // Example 3: Transforming elements
- auto transformedView = argsView.transform([](const auto& arg) {
- if constexpr (std::is_same_v) {
- return arg * 2;
- } else if constexpr (std::is_same_v) {
- return arg + 1.0;
- } else if constexpr (std::is_same_v) {
- return arg + "!!!";
- }
- });
-
- std::cout << "Transformed elements: ";
- transformedView.forEach([](const auto& arg) { std::cout << arg << " "; });
- std::cout << "\n";
-
- // Example 4: Accumulating elements
- int sum = argsView.accumulate(
- [](int acc, const auto& arg) {
- if constexpr (std::is_arithmetic_v) {
- return acc + arg;
- } else {
- return acc;
- }
- },
- 0);
- std::cout << "Sum of numeric elements: " << sum << "\n";
-
- // Example 5: Using apply to call a function with all elements
- auto concatenated = std::apply(
- [](const auto&... args) { return (std::to_string(args) + ...); },
- argsView.toTuple());
- std::cout << "Concatenated elements: " << concatenated << "\n";
-
- // Example 6: Using makeArgsView to create an ArgsView
- auto argsView2 = makeArgsView(1, 2.5, "Test");
- std::cout << "ArgsView2 elements: ";
- argsView2.forEach([](const auto& arg) { std::cout << arg << " "; });
- std::cout << "\n";
-
- // Example 7: Using sum and concat helper functions
- int total = sum(1, 2, 3, 4, 5);
- std::cout << "Sum of 1, 2, 3, 4, 5: " << total << "\n";
-
- std::string concatenatedStr = concat("Hello", " ", "ArgsView", "!");
- std::cout << "Concatenated string: " << concatenatedStr << "\n";
-
- return 0;
-}
diff --git a/example/atom/async/async.cpp b/example/atom/async/async.cpp
deleted file mode 100644
index fa70a114..00000000
--- a/example/atom/async/async.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "atom/async/async.hpp"
-
-// Sample function to be run asynchronously
-int sampleTask(int duration) {
- std::this_thread::sleep_for(std::chrono::seconds(duration));
- return duration; // Return the duration as result
-}
-
-int main() {
- // Create an AsyncWorker object for managing asynchronous tasks
- atom::async::AsyncWorker worker;
-
- // Start an asynchronous task
- worker.startAsync(sampleTask, 3); // This will sleep for 3 seconds
-
- // Set a callback to handle the result when the task is done
- worker.setCallback([](int result) {
- std::cout << "Task completed with result: " << result << std::endl;
- });
-
- // Set a timeout of 5 seconds
- worker.setTimeout(std::chrono::seconds(5));
-
- // Wait for completion
- std::cout << "Waiting for task completion...\n";
- worker.waitForCompletion();
-
- // Get the result (this will work since we know the task completed)
- try {
- int result = worker.getResult();
- std::cout << "Result retrieved successfully: " << result << std::endl;
- } catch (const std::exception &e) {
- std::cerr << "Error retrieving result: " << e.what() << std::endl;
- }
-
- // Using AsyncWorkerManager to manage multiple workers
- atom::async::AsyncWorkerManager manager;
-
- // Create multiple async workers
- manager.createWorker(sampleTask, 1); // 1 second task
- manager.createWorker(sampleTask, 2); // 2 seconds task
- manager.createWorker(sampleTask, 3); // 3 seconds task
-
- // Wait for all created tasks to complete
- std::cout << "Waiting for all tasks to complete...\n";
- manager.waitForAll();
-
- // Check if all tasks are done
- if (manager.allDone()) {
- std::cout << "All tasks have completed successfully.\n";
- } else {
- std::cout << "Some tasks are still running.\n";
- }
-
- // Retry logic using asyncRetry for a task that may fail
- auto retryExample = [](int x) {
- static int attempt = 0;
- attempt++;
- if (attempt < 3) {
- std::cerr << "Attempt " << attempt << " failed, retrying...\n";
- throw std::runtime_error("Simulated failure");
- }
- return x * 2; // Successful result
- };
-
- // Execute with retry
- std::future futureResult = atom::async::asyncRetry(
- retryExample, 3, std::chrono::milliseconds(500), 5);
- try {
- int finalResult = futureResult.get();
- std::cout << "Final result after retrying: " << finalResult
- << std::endl;
- } catch (const std::exception &e) {
- std::cerr << "Error after retries: " << e.what() << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/async/daemon.cpp b/example/atom/async/daemon.cpp
deleted file mode 100644
index 7abefd90..00000000
--- a/example/atom/async/daemon.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/async/daemon.hpp"
-
-int mainCallback(int argc, char **argv) {
- std::cout << "Daemon process running...\n";
-
- // Simulate some work in the daemon
- for (int i = 0; i < 10; ++i) {
- std::cout << "Daemon is working: " << i + 1 << "/10" << std::endl;
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
-
- return 0; // Indicate success
-}
-
-int main(int argc, char **argv) {
- atom::async::DaemonGuard daemonGuard;
-
- // Set up signal handling
- signal(SIGTERM, atom::async::signalHandler);
- signal(SIGINT, atom::async::signalHandler);
-
- // Start the daemon
- daemonGuard.startDaemon(argc, argv, mainCallback, true);
-
- return 0;
-}
diff --git a/example/atom/async/eventloop.c b/example/atom/async/eventloop.c
deleted file mode 100644
index e98ee791..00000000
--- a/example/atom/async/eventloop.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "atom/async/eventloop.h"
-
-#include
-
-// Example callback function for file descriptors
-void onFdReady(int fd, void *userData) {
- printf("File descriptor %d is ready. User Data: %s\n", fd, (char *)userData);
-}
-
-// Example work procedure
-void workProc(void *userData) {
- printf("Executing work procedure. User Data: %s\n", (char *)userData);
-}
-
-// Example timer callback function
-void onTimer(void *userData) {
- printf("Timer fired. User Data: %s\n", (char *)userData);
-}
-
-int main() {
- // Starting the event loop
- printf("Starting Event Loop\n");
-
- // Adding file descriptor callback example
- int fd_example = /* Assume you have a valid file descriptor */;
- int callbackId = addCallback(fd_example, onFdReady, "File Descriptor User Data");
-
- // Adding a work procedure
- int workProcId = addWorkProc(workProc, "Work Procedure User Data");
-
- // Adding a one-shot timer
- int timerId = addTimer(1000 /* ms */, onTimer, "One-Shot Timer");
-
- // Adding a periodic timer
- int periodicTimerId = addPeriodicTimer(2000 /* ms */, onTimer, "Periodic Timer");
-
- // Run the event loop
- eventLoop();
-
- // Cleanup
- rmCallback(callbackId);
- rmWorkProc(workProcId);
- rmTimer(timerId);
- rmTimer(periodicTimerId);
-
- printf("Ending Event Loop\n");
- return 0;
-}
diff --git a/example/atom/async/eventstack.cpp b/example/atom/async/eventstack.cpp
deleted file mode 100644
index 4b6121eb..00000000
--- a/example/atom/async/eventstack.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-#include
-#include
-
-#include "atom/async/eventstack.hpp"
-
-// Define a simple event type (in this case, a string)
-using EventType = std::string;
-
-void exampleUsage() {
- // Create an EventStack for managing string events
- atom::async::EventStack eventStack;
-
- // Push some events onto the stack
- eventStack.pushEvent("Event 1: Start processing data");
- eventStack.pushEvent("Event 2: Load configuration");
- eventStack.pushEvent("Event 3: Connect to database");
- eventStack.pushEvent("Event 4: Process user input");
-
- // Print size of the stack
- std::cout << "Current stack size: " << eventStack.size() << std::endl;
-
- // Peek at the top event
- auto topEvent = eventStack.peekTopEvent();
- if (topEvent) {
- std::cout << "Top event: " << *topEvent << std::endl;
- } else {
- std::cout << "Stack is empty!" << std::endl;
- }
-
- // Pop an event from the stack
- auto poppedEvent = eventStack.popEvent();
- if (poppedEvent) {
- std::cout << "Popped event: " << *poppedEvent << std::endl;
- } else {
- std::cout << "Stack is empty!" << std::endl;
- }
-
- // Filter events that contain the word "data"
- eventStack.filterEvents([](const EventType& event) {
- return event.find("data") != std::string::npos;
- });
-
- std::cout << "After filtering, stack size: " << eventStack.size()
- << std::endl;
-
-#if ENABLE_DEBUG
- // Print remaining events
- eventStack.printEvents();
-#endif
-
- // Serialize the stack to a string
- std::string serializedData = eventStack.serializeStack();
- std::cout << "Serialized stack: " << serializedData << std::endl;
-
- // Clear the stack, and then deserialize the serialized data back into the
- // stack
- eventStack.clearEvents();
- std::cout << "Stack cleared." << std::endl;
-
- eventStack.deserializeStack(serializedData);
- std::cout << "Deserialized stack size: " << eventStack.size() << std::endl;
-
- // Remove duplicates (if any)
- eventStack.removeDuplicates();
-
- // Sort events in the stack (lexicographical order)
- eventStack.sortEvents(
- [](const EventType& a, const EventType& b) { return a < b; });
- std::cout << "Sorted stack size: " << eventStack.size() << std::endl;
-
- // Check if any event contains the word "input"
- bool hasInputEvent = eventStack.anyEvent([](const EventType& event) {
- return event.find("input") != std::string::npos;
- });
-
- std::cout << (hasInputEvent ? "There is an event containing 'input'.\n"
- : "No events contain 'input'.\n");
-}
-
-int main() {
- // Run the event stack example
- exampleUsage();
- return 0;
-}
diff --git a/example/atom/async/limiter.cpp b/example/atom/async/limiter.cpp
deleted file mode 100644
index 743a6c8c..00000000
--- a/example/atom/async/limiter.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/async/limiter.hpp"
-
-// Function to be rate limited
-void criticalFunction() {
- std::cout << "Critical function executed at "
- << std::chrono::steady_clock::now().time_since_epoch().count()
- << std::endl;
-}
-
-// Function to demonstrate debouncing
-void debouncedFunction() {
- std::cout << "Debounced function executed at "
- << std::chrono::steady_clock::now().time_since_epoch().count()
- << std::endl;
-}
-
-// Function to demonstrate throttling
-void throttledFunction() {
- std::cout << "Throttled function executed at "
- << std::chrono::steady_clock::now().time_since_epoch().count()
- << std::endl;
-}
-
-int main() {
- // Rate Limiter Example
- atom::async::RateLimiter rateLimiter;
- rateLimiter.setFunctionLimit("criticalFunction", 3,
- std::chrono::seconds(5));
-
- // Simulate requests to the critical function
- for (int i = 0; i < 5; ++i) {
- auto awaiter = rateLimiter.acquire("criticalFunction");
- awaiter.await_suspend({});
- criticalFunction();
- std::this_thread::sleep_for(
- std::chrono::seconds(1)); // Simulate time between function calls
- }
-
- // Debounce Example
- atom::async::Debounce debouncer(debouncedFunction,
- std::chrono::milliseconds(500), true);
-
- // Simulate rapid calls
- for (int i = 0; i < 5; ++i) {
- debouncer(); // Calls will be debounced
- std::this_thread::sleep_for(
- std::chrono::milliseconds(200)); // Calls within the debounce delay
- }
-
- std::this_thread::sleep_for(
- std::chrono::milliseconds(600)); // Wait for debounced call to execute
-
- // Throttle Example
- atom::async::Throttle throttler(throttledFunction,
- std::chrono::milliseconds(1000), true);
-
- // Simulate rapid throttled calls
- for (int i = 0; i < 5; ++i) {
- throttler(); // Throttled function calls
- std::this_thread::sleep_for(
- std::chrono::milliseconds(300)); // Calls within the throttle time
- }
-
- std::this_thread::sleep_for(
- std::chrono::milliseconds(2000)); // Wait to ensure throttling works
-
- return 0;
-}
diff --git a/example/atom/async/lock.cpp b/example/atom/async/lock.cpp
deleted file mode 100644
index 4df2f31b..00000000
--- a/example/atom/async/lock.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/async/lock.hpp"
-
-// Global shared variable
-int sharedCounter = 0;
-const int NUM_INCREMENTS = 1000;
-
-// Example using Spinlock
-atom::async::Spinlock spinlock;
-
-void incrementCounterWithSpinlock() {
- for (int i = 0; i < NUM_INCREMENTS; ++i) {
- spinlock.lock();
- ++sharedCounter; // Critical section
- spinlock.unlock();
- }
-}
-
-// Example using TicketSpinlock
-atom::async::TicketSpinlock ticketSpinlock;
-
-void incrementCounterWithTicketSpinlock() {
- for (int i = 0; i < NUM_INCREMENTS; ++i) {
- ticketSpinlock.lock();
- ++sharedCounter; // Critical section
- ticketSpinlock.unlock(
- 0); // Unlock with ticket 0 (not optimal for brevity)
- }
-}
-
-// Example using UnfairSpinlock
-atom::async::UnfairSpinlock unfairSpinlock;
-
-void incrementCounterWithUnfairSpinlock() {
- for (int i = 0; i < NUM_INCREMENTS; ++i) {
- unfairSpinlock.lock();
- ++sharedCounter; // Critical section
- unfairSpinlock.unlock();
- }
-}
-
-int main() {
- sharedCounter = 0; // Reset shared counter
-
- // Using Spinlock
- std::vector threads;
- std::cout << "Using Spinlock:\n";
- for (int i = 0; i < 5; ++i) {
- threads.emplace_back(incrementCounterWithSpinlock);
- }
- for (auto &t : threads) {
- t.join();
- }
- std::cout << "Final counter value (Spinlock): " << sharedCounter << "\n";
-
- // Reset shared counter for next demo
- sharedCounter = 0;
- threads.clear();
-
- // Using TicketSpinlock
- std::cout << "Using TicketSpinlock:\n";
- for (int i = 0; i < 5; ++i) {
- threads.emplace_back(incrementCounterWithTicketSpinlock);
- }
- for (auto &t : threads) {
- t.join();
- }
- std::cout << "Final counter value (TicketSpinlock): " << sharedCounter
- << "\n";
-
- // Reset shared counter for next demo
- sharedCounter = 0;
- threads.clear();
-
- // Using UnfairSpinlock
- std::cout << "Using UnfairSpinlock:\n";
- for (int i = 0; i < 5; ++i) {
- threads.emplace_back(incrementCounterWithUnfairSpinlock);
- }
- for (auto &t : threads) {
- t.join();
- }
- std::cout << "Final counter value (UnfairSpinlock): " << sharedCounter
- << "\n";
-
- return 0;
-}
diff --git a/example/atom/async/message_bus.cpp b/example/atom/async/message_bus.cpp
deleted file mode 100644
index f3d7eb7c..00000000
--- a/example/atom/async/message_bus.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/async/message_bus.hpp"
-
-// Message structure
-struct MyMessage {
- std::string content;
-};
-
-void subscriberFunction(const MyMessage &msg) {
- std::cout << "Received message: " << msg.content << std::endl;
-}
-
-void globalSubscriberFunction(const MyMessage &msg) {
- std::cout << "Global subscriber received: " << msg.content << std::endl;
-}
-
-int main() {
- // Create a MessageBus instance
- auto bus = atom::async::MessageBus::createShared();
-
- // Subscribe to a specific topic
- bus->subscribe("my_topic", subscriberFunction);
-
- // Subscribe to a global topic
- bus->globalSubscribe(globalSubscriberFunction);
-
- // Publish messages to the topic
- for (int i = 0; i < 5; ++i) {
- MyMessage msg{"Hello World " + std::to_string(i)};
- bus->publish("my_topic", msg);
- std::this_thread::sleep_for(std::chrono::milliseconds(
- 200)); // Simulate some delay between messages
- }
-
- // Publish a message after a delay
- std::this_thread::sleep_for(std::chrono::seconds(1));
- MyMessage globalMsg{"This is a global message!"};
- bus->publish("global_topic", globalMsg);
-
- // Delay to allow global subscribers to process messages
- std::this_thread::sleep_for(std::chrono::seconds(2));
-
- // Unsubscribe from the topic
- bus->unsubscribe("my_topic", subscriberFunction);
-
- // Publish another message to see if the subscriber still receives it
- MyMessage msg{"This should NOT be received by the local subscriber!"};
- bus->publish("my_topic", msg);
-
- // Wait for a moment to observe potential output
- std::this_thread::sleep_for(std::chrono::seconds(1));
-
- // Stop all processing threads if any (not implemented here, just caution)
- // bus->stopAllProcessingThreads();
-
- return 0;
-}
diff --git a/example/atom/async/message_queue.cpp b/example/atom/async/message_queue.cpp
deleted file mode 100644
index 4380dee0..00000000
--- a/example/atom/async/message_queue.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "atom/async/message_queue.hpp"
-
-#include
-#include
-#include
-
-// Message structure
-struct MyMessage {
- std::string content;
-};
-
-// Subscriber function to handle incoming messages
-void messageHandler(const MyMessage &msg) {
- std::cout << "Received message: " << msg.content << std::endl;
-}
-
-int main() {
- // Create a MessageQueue instance for MyMessage
- atom::async::MessageQueue messageQueue;
-
- // Subscribe to the message queue
- messageQueue.subscribe(messageHandler, "MessageHandler");
-
- // Start the processing thread
- messageQueue.startProcessingThread();
-
- // Publish some messages to the queue
- for (int i = 0; i < 5; ++i) {
- MyMessage msg{"Hello World " + std::to_string(i)};
- messageQueue.publish(msg);
- std::this_thread::sleep_for(std::chrono::milliseconds(
- 200)); // Simulate some delay between messages
- }
-
- // Allow some time for processing before stopping
- std::this_thread::sleep_for(std::chrono::seconds(1));
-
- // Stop the processing thread
- messageQueue.stopProcessingThread();
-
- return 0;
-}
diff --git a/example/atom/async/pool.cpp b/example/atom/async/pool.cpp
deleted file mode 100644
index 892d96b2..00000000
--- a/example/atom/async/pool.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "atom/async/pool.hpp"
-
-// A sample task function that simulates work
-void sampleTask(int id) {
- std::cout << "Task " << id << " is starting on thread "
- << std::this_thread::get_id() << std::endl;
- std::this_thread::sleep_for(std::chrono::seconds(1)); // Simulate work
- std::cout << "Task " << id << " completed on thread "
- << std::this_thread::get_id() << std::endl;
-}
-
-int main() {
- const unsigned int numThreads = 4; // Number of threads in the pool
- atom::async::ThreadPool<> threadPool(
- numThreads); // Create ThreadPool instance
-
- std::vector>
- futures; // To hold futures for result checking
-
- // Enqueue multiple tasks into the thread pool
- for (int i = 0; i < 10; ++i) {
- futures.push_back(threadPool.enqueue(sampleTask, i));
- }
-
- // Wait for all tasks to complete
- for (auto &future : futures) {
- future.wait();
- }
-
- std::cout << "All tasks completed." << std::endl;
-
- return 0;
-}
diff --git a/example/atom/async/queue.cpp b/example/atom/async/queue.cpp
deleted file mode 100644
index 9a71c9dd..00000000
--- a/example/atom/async/queue.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "atom/async/queue.hpp"
-
-// Function to simulate a producer that adds messages to the queue
-void producer(atom::async::ThreadSafeQueue &queue) {
- for (int i = 0; i < 10; ++i) {
- std::string message = "Message " + std::to_string(i);
- queue.put(message);
- std::cout << "Produced: " << message << std::endl;
- std::this_thread::sleep_for(
- std::chrono::milliseconds(200)); // Simulate work
- }
-}
-
-// Function to simulate a consumer that takes messages from the queue
-void consumer(atom::async::ThreadSafeQueue &queue) {
- for (int i = 0; i < 10; ++i) {
- auto message = queue.take();
- if (message) {
- std::cout << "Consumed: " << *message << std::endl;
- } else {
- std::cout << "No message taken!" << std::endl;
- }
- std::this_thread::sleep_for(
- std::chrono::milliseconds(300)); // Simulate processing delay
- }
-}
-
-int main() {
- atom::async::ThreadSafeQueue messageQueue;
-
- // Create producer and consumer threads
- std::thread producerThread(producer, std::ref(messageQueue));
- std::thread consumerThread(consumer, std::ref(messageQueue));
-
- // Wait for both threads to finish
- producerThread.join();
- consumerThread.join();
-
- std::cout << "Processing complete." << std::endl;
-
- return 0;
-}
diff --git a/example/atom/async/safetype.cpp b/example/atom/async/safetype.cpp
deleted file mode 100644
index 0d344c30..00000000
--- a/example/atom/async/safetype.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "atom/async/safetype.hpp"
-
-// Function to simulate pushing elements to the stack
-template
-void pushToStack(atom::async::LockFreeStack& stack, T value) {
- stack.push(value);
- std::cout << "Pushed: " << value << std::endl;
-}
-
-// Function to simulate popping elements from the stack
-template
-void popFromStack(atom::async::LockFreeStack& stack) {
- auto value = stack.pop();
- if (value) {
- std::cout << "Popped: " << *value << std::endl;
- } else {
- std::cout << "Stack is empty." << std::endl;
- }
-}
-
-int main() {
- // Create a LockFreeStack for integers
- atom::async::LockFreeStack stack;
-
- // Create a vector for threads
- std::vector threads;
-
- // Start threads to push elements onto the stack
- for (int i = 0; i < 10; ++i) {
- threads.emplace_back(pushToStack, std::ref(stack), i);
- }
-
- // Allow some time for all pushes to complete
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
-
- // Start threads to pop elements from the stack
- for (int i = 0; i < 5; ++i) {
- threads.emplace_back(popFromStack, std::ref(stack));
- }
-
- // Wait for all threads to finish
- for (auto& thread : threads) {
- thread.join();
- }
-
- // Final stack state checks
- if (stack.empty()) {
- std::cout << "The stack is empty at the end." << std::endl;
- } else {
- std::cout << "The stack is not empty at the end." << std::endl;
- }
-
- return 0;
-}
diff --git a/example/atom/async/slot.cpp b/example/atom/async/slot.cpp
deleted file mode 100644
index 3fbc415c..00000000
--- a/example/atom/async/slot.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/async/limiter.hpp"
-#include "atom/async/slot.hpp"
-
-// Example function to be called on signal emission
-void exampleHandler(int value) {
- std::cout << "Signal received with value: " << value << " on thread "
- << std::this_thread::get_id() << std::endl;
-}
-
-void exampleAsyncHandler(int value) {
- std::cout << "Async signal received with value: " << value << " on thread "
- << std::this_thread::get_id() << std::endl;
-}
-
-int main() {
- // Create a signal instance
- atom::async::Signal mySignal;
-
- // Subscribe to the signal with a handler
- mySignal.connect(exampleHandler);
-
- // Emit some signals
- for (int i = 0; i < 5; ++i) {
- mySignal.emit(i);
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
- }
-
- // Create an AsyncSignal instance
- atom::async::AsyncSignal myAsyncSignal;
-
- // Subscribe to the async signal
- myAsyncSignal.connect(exampleAsyncHandler);
-
- // Emit some async signals
- for (int i = 5; i < 10; ++i) {
- myAsyncSignal.emit(i);
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
- }
-
- // Demonstrating Debounce
- atom::async::Debounce debouncedSignal(
- []() { std::cout << "Debounced function executed.\n"; },
- std::chrono::milliseconds(500), false);
-
- // Simulating rapid calls to the debounced function
- std::cout << "Simulating rapid calls to debounced function...\n";
- for (int i = 0; i < 10; ++i) {
- debouncedSignal();
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
- }
-
- // Give some time for the debounced function to execute
- std::this_thread::sleep_for(std::chrono::milliseconds(700));
-
- // Demonstrating Throttle
- atom::async::Throttle throttledSignal(
- []() { std::cout << "Throttled function executed.\n"; },
- std::chrono::milliseconds(1000), true);
-
- // Simulating rapid calls to the throttled function
- std::cout << "Simulating rapid calls to throttled function...\n";
- for (int i = 0; i < 5; ++i) {
- throttledSignal();
- std::this_thread::sleep_for(std::chrono::milliseconds(300));
- }
-
- // Wait some time to ensure throttled function executes
- std::this_thread::sleep_for(std::chrono::milliseconds(1500));
-
- return 0;
-}
diff --git a/example/atom/async/thread_wrapper.cpp b/example/atom/async/thread_wrapper.cpp
deleted file mode 100644
index d71827e8..00000000
--- a/example/atom/async/thread_wrapper.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/async/thread_wrapper.hpp"
-
-// A sample function to be executed in a thread
-void threadFunction(int id, std::chrono::milliseconds duration) {
- std::cout << "Thread " << id << " started. Sleeping for "
- << duration.count() << "ms.\n";
- std::this_thread::sleep_for(duration);
- std::cout << "Thread " << id << " finished processing!\n";
-}
-
-// A sample function that supports stopping
-void stoppableThreadFunction(std::stop_token stopToken) {
- for (int i = 0; i < 5; ++i) {
- if (stopToken.stop_requested()) {
- std::cout << "Thread is stopping early!\n";
- return;
- }
- std::cout << "Working... " << i + 1 << "\n";
- std::this_thread::sleep_for(
- std::chrono::milliseconds(500)); // Simulate work
- }
-}
-
-int main() {
- // Create a Thread for normal execution
- atom::async::Thread normalThread;
- normalThread.start(threadFunction, 1, std::chrono::milliseconds(2000));
- normalThread.join(); // Wait for it to finish
-
- // Create a Thread that can be stopped
- atom::async::Thread stoppableThread;
- stoppableThread.start(stoppableThreadFunction); // Start a stoppable thread
-
- // Give it some time to work
- std::this_thread::sleep_for(std::chrono::seconds(1));
- std::cout << "Requesting the stoppable thread to stop...\n";
- stoppableThread.requestStop(); // Request it to stop
-
- stoppableThread.join(); // Wait for it to finish
-
- return 0;
-}
diff --git a/example/atom/async/threadlocal.cpp b/example/atom/async/threadlocal.cpp
deleted file mode 100644
index ed369ef9..00000000
--- a/example/atom/async/threadlocal.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "atom/async/threadlocal.hpp"
-
-#include
-#include
-
-void threadFunction(atom::async::ThreadLocal& threadLocal) {
- // Initialize thread-local value
- threadLocal.reset(42);
- std::cout << "Thread ID: " << std::this_thread::get_id()
- << ", Value: " << *threadLocal << std::endl;
-}
-
-int initialize() {
- return 100; // Example initialization value
-}
-
-int main() {
- {
- atom::async::ThreadLocal threadLocal; // No initializer
-
- std::thread t1(threadFunction, std::ref(threadLocal));
- std::thread t2(threadFunction, std::ref(threadLocal));
-
- t1.join();
- t2.join();
- }
-
- {
- atom::async::ThreadLocal threadLocal(
- initialize); // With initializer
-
- std::thread t1(threadFunction, std::ref(threadLocal));
- std::thread t2(threadFunction, std::ref(threadLocal));
-
- t1.join();
- t2.join();
- }
- return 0;
-}
diff --git a/example/atom/async/timer.cpp b/example/atom/async/timer.cpp
deleted file mode 100644
index 47b62617..00000000
--- a/example/atom/async/timer.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "atom/async/timer.hpp"
-
-#include
-#include
-
-void task1() { std::cout << "Task 1 executed!" << std::endl; }
-
-void task2(int value) {
- std::cout << "Task 2 executed with value: " << value << std::endl;
-}
-
-int main() {
- // 创建一个Timer对象
- atom::async::Timer timer;
-
- // 设置一个延迟执行的任务(一次性任务)
- auto future1 = timer.setTimeout(task1, 2000); // 2秒后执行task1
- future1.get(); // 获取任务的结果(等待执行完成)
-
- // 设置一个定时重复任务(每3秒执行一次,重复5次)
- timer.setInterval(task2, 3000, 5, 1, 42); // 任务优先级为1,参数为42
-
- // 设置一个匿名函数任务(lambda表达式)
- auto future2 = timer.setTimeout(
- []() {
- std::cout << "Lambda task executed after 1 second!" << std::endl;
- },
- 1000); // 1秒后执行
-
- future2.get(); // 获取lambda任务的结果(等待执行完成)
-
- // 模拟暂停定时器
- std::this_thread::sleep_for(std::chrono::seconds(5));
- std::cout << "Pausing timer..." << std::endl;
- timer.pause();
-
- // 暂停2秒
- std::this_thread::sleep_for(std::chrono::seconds(2));
-
- // 恢复定时器
- std::cout << "Resuming timer..." << std::endl;
- timer.resume();
-
- // 等待一段时间后取消所有任务
- std::this_thread::sleep_for(std::chrono::seconds(10));
- std::cout << "Cancelling all tasks..." << std::endl;
- timer.cancelAllTasks();
-
- // 停止定时器
- timer.stop();
-
- return 0;
-}
diff --git a/example/atom/async/trigger.cpp b/example/atom/async/trigger.cpp
deleted file mode 100644
index 0b588362..00000000
--- a/example/atom/async/trigger.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include
-
-#include "atom/async/trigger.hpp"
-
-int main() {
- atom::async::Trigger trigger;
-
- // Registering callbacks
- trigger.registerCallback(
- "onEvent", [](int x) { std::cout << "Callback 1: " << x << std::endl; },
- atom::async::Trigger::CallbackPriority::High);
- trigger.registerCallback("onEvent", [](int x) {
- std::cout << "Callback 2: " << x << std::endl;
- });
-
- // Triggering event
- trigger.trigger("onEvent", 42);
-
- // Scheduling a delayed trigger
- trigger.scheduleTrigger("onEvent", 84, std::chrono::milliseconds(500));
-
- // Scheduling async trigger
- auto future = trigger.scheduleAsyncTrigger("onEvent", 126);
- future.get(); // Waiting for async trigger to complete
-
- // Cancel an event
- trigger.cancelTrigger("onEvent");
-
- // Cancel all events
- trigger.cancelAllTriggers();
-}
diff --git a/example/atom/connection/fifoclient.cpp b/example/atom/connection/fifoclient.cpp
deleted file mode 100644
index f24b1123..00000000
--- a/example/atom/connection/fifoclient.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/connection/fifoclient.hpp"
-
-#if __linux
-#include
-#endif
-
-// Function to simulate the FIFO server
-void fifoServer(const std::string& fifoPath) {
- // Open the FIFO for writing. If it does not exist, create it.
- mkfifo(fifoPath.c_str(),
- 0666); // Create the named pipe if it doesn't exist
-
- // Simulate a server writing to the FIFO
- atom::connection::FifoClient fifoClient(fifoPath);
- if (!fifoClient.isOpen()) {
- std::cerr << "Failed to open FIFO for writing." << std::endl;
- return;
- }
-
- std::string message = "Hello from FIFO Server!";
- fifoClient.write(message,
- std::chrono::milliseconds(1000)); // Write with timeout
- std::cout << "Server wrote: " << message << std::endl;
-
- fifoClient.close(); // Close FIFO after writing
-}
-
-// Function to simulate the FIFO client
-void fifoClient(const std::string& fifoPath) {
- // Create a FifoClient to read from the FIFO
- atom::connection::FifoClient fifoClient(fifoPath);
- if (!fifoClient.isOpen()) {
- std::cerr << "Failed to open FIFO for reading." << std::endl;
- return;
- }
-
- // Read from FIFO with a timeout
- auto data = fifoClient.read(std::chrono::milliseconds(5000));
- if (data) {
- std::cout << "Client read: " << *data << std::endl;
- } else {
- std::cerr << "Client failed to read data from FIFO." << std::endl;
- }
-
- fifoClient.close(); // Close FIFO after reading
-}
-
-int main() {
- const std::string fifoPath = "/tmp/myfifo"; // FIFO path
-
- // Create threads to simulate server and client
- std::thread serverThread(fifoServer, fifoPath);
- std::this_thread::sleep_for(std::chrono::milliseconds(
- 100)); // Small delay to ensure server starts first
- std::thread clientThread(fifoClient, fifoPath);
-
- // Wait for both threads to finish
- serverThread.join();
- clientThread.join();
-
- return 0;
-}
diff --git a/example/atom/connection/fifoserver.cpp b/example/atom/connection/fifoserver.cpp
deleted file mode 100644
index 58c85ff2..00000000
--- a/example/atom/connection/fifoserver.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "atom/connection/fifoserver.hpp"
-
-// Function to run the FIFO server
-void runFifoServer(const std::string& fifoPath) {
- atom::connection::FIFOServer server(fifoPath);
-
- // Start the server
- server.start();
- std::cout << "FIFO Server started." << std::endl;
-
- // Simulate sending messages
- for (int i = 0; i < 5; ++i) {
- std::string message = "Message " + std::to_string(i);
- server.sendMessage(message);
- std::cout << "Sent: " << message << std::endl;
-
- // Sleep for a while to simulate some processing time
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
-
- // Stop the server
- server.stop();
- std::cout << "FIFO Server stopped." << std::endl;
-}
-
-int main() {
- const std::string fifoPath = "/tmp/my_fifo"; // Path for the FIFO
-
- // Create a thread to run the FIFO server
- std::thread serverThread(runFifoServer, fifoPath);
-
- // Wait for the server thread to finish
- serverThread.join();
-
- return 0;
-}
diff --git a/example/atom/connection/sockethub.cpp b/example/atom/connection/sockethub.cpp
deleted file mode 100644
index 048e5581..00000000
--- a/example/atom/connection/sockethub.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include
-#include
-
-#include "atom/connection/sockethub.hpp"
-
-// Function to handle incoming messages
-void messageHandler(std::string message) {
- std::cout << "Received message: " << message << std::endl;
-}
-
-// Function to run the socket server
-void runSocketServer(int port) {
- atom::connection::SocketHub socketHub;
-
- // Add a custom message handler
- socketHub.addHandler(messageHandler);
-
- // Start the socket server
- socketHub.start(port);
- std::cout << "Socket server running on port " << port << std::endl;
-
- // Run for a specific duration and then stop the server
- std::this_thread::sleep_for(std::chrono::seconds(30));
- socketHub.stop();
- std::cout << "Socket server stopped." << std::endl;
-}
-
-int main() {
- const int port = 8080; // Define the port to listen on
-
- // Start the socket server in a separate thread
- std::thread serverThread(runSocketServer, port);
-
- // Wait for the server thread to finish
- serverThread.join();
-
- return 0;
-}
diff --git a/example/atom/connection/sshserver.cpp b/example/atom/connection/sshserver.cpp
deleted file mode 100644
index 984ab0b3..00000000
--- a/example/atom/connection/sshserver.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include "atom/connection/sshserver.hpp"
-
-#include
-#include
-#include
-
-// Function to run the SSH server
-void runSshServer(const std::filesystem::path& configFile) {
- atom::connection::SshServer sshServer(configFile);
-
- // Configure the SSH server
- sshServer.setPort(22); // Set port for SSH
- sshServer.setListenAddress("0.0.0.0"); // Listen on all interfaces
- sshServer.setHostKey("/etc/ssh/ssh_host_rsa_key"); // Set the host key file
-
- // Allow password authentication
- sshServer.setPasswordAuthentication(true);
-
- // Allow root login (not recommended in production)
- sshServer.allowRootLogin(true);
-
- // Start the SSH server
- sshServer.start();
- std::cout << "SSH Server started on port " << sshServer.getPort()
- << std::endl;
-
- // Keep the server running for a while
- std::this_thread::sleep_for(std::chrono::seconds(60));
-
- // Stop the SSH server
- sshServer.stop();
- std::cout << "SSH Server stopped." << std::endl;
-}
-
-int main() {
- const std::filesystem::path configFile =
- "/path/to/your/sshconfig.file"; // Update this path to your
- // configuration file
-
- // Start the SSH server in a separate thread
- std::thread serverThread(runSshServer, configFile);
-
- // Wait for the server thread to finish
- serverThread.join();
-
- return 0;
-}
diff --git a/example/atom/connection/tcpclient.cpp b/example/atom/connection/tcpclient.cpp
deleted file mode 100644
index 6ce6f095..00000000
--- a/example/atom/connection/tcpclient.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/connection/tcpclient.hpp"
-
-// Function to handle connection success
-void onConnected() {
- std::cout << "Successfully connected to the server." << std::endl;
-}
-
-// Function to handle disconnection
-void onDisconnected() {
- std::cout << "Disconnected from the server." << std::endl;
-}
-
-// Function to handle incoming data
-void onDataReceived(const std::vector& data) {
- std::string received(data.begin(), data.end());
- std::cout << "Received data: " << received << std::endl;
-}
-
-// Function to handle errors
-void onError(const std::string& errorMessage) {
- std::cerr << "Error: " << errorMessage << std::endl;
-}
-
-// Function to run the TCP client
-void runTcpClient(const std::string& host, int port) {
- atom::connection::TcpClient tcpClient;
-
- // Set callbacks for various events
- tcpClient.setOnConnectedCallback(onConnected);
- tcpClient.setOnDisconnectedCallback(onDisconnected);
- tcpClient.setOnDataReceivedCallback(onDataReceived);
- tcpClient.setOnErrorCallback(onError);
-
- // Try to connect to the server
- if (!tcpClient.connect(host, port, std::chrono::milliseconds(5000))) {
- std::cerr << "Failed to connect to the server." << std::endl;
- return;
- }
-
- // Sending a message to the server
- std::string message = "Hello, Server!";
- if (tcpClient.send(std::vector(message.begin(), message.end()))) {
- std::cout << "Sent message: " << message << std::endl;
- } else {
- std::cerr << "Failed to send message." << std::endl;
- }
-
- // Start receiving data in a separate thread
- tcpClient.startReceiving(
- 1024); // Start receiving with buffer size of 1024 bytes
-
- // Wait for some time to receive data from server
- std::this_thread::sleep_for(std::chrono::seconds(10));
-
- // Stop receiving before disconnecting
- tcpClient.stopReceiving();
-
- // Disconnect from the server
- tcpClient.disconnect();
-}
-
-int main() {
- const std::string host =
- "127.0.0.1"; // Replace with the server's IP address or hostname
- const int port = 8080; // Replace with the server's port
-
- // Run the TCP client
- runTcpClient(host, port);
-
- return 0;
-}
diff --git a/example/atom/connection/ttybase.cpp b/example/atom/connection/ttybase.cpp
deleted file mode 100644
index 4ad60d44..00000000
--- a/example/atom/connection/ttybase.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include
-#include
-#include
-
-#include "atom/connection/ttybase.hpp"
-
-// Derived class implementation for demonstration purposes
-class MyTtyClient : public TTYBase {
-public:
- explicit MyTtyClient(std::string_view driverName) : TTYBase(driverName) {}
-
- // Example of connecting to a TTY device
- void exampleConnect(const std::string& device) {
- uint32_t baudRate = 9600; // Set baud rate
- uint8_t wordSize = 8; // 8 data bits
- uint8_t parity = 0; // No parity
- uint8_t stopBits = 1; // 1 stop bit
-
- auto response = connect(device, baudRate, wordSize, parity, stopBits);
- if (response == TTYResponse::OK) {
- std::cout << "Connected to " << device << " successfully."
- << std::endl;
- } else {
- std::cerr << "Failed to connect: " << getErrorMessage(response)
- << std::endl;
- }
- }
-
- // Example of sending data
- void exampleSendData(const std::string& data) {
- uint32_t nbytesWritten = 0;
- auto response = writeString(data, nbytesWritten);
- if (response == TTYResponse::OK) {
- std::cout << "Sent: " << data << " (" << nbytesWritten << " bytes)"
- << std::endl;
- } else {
- std::cerr << "Failed to send data: " << getErrorMessage(response)
- << std::endl;
- }
- }
-
- // Example of receiving data
- void exampleReceiveData(size_t size) {
- std::vector buffer(size);
- uint32_t nbytesRead = 0;
- auto response = read(buffer.data(), size, 5, nbytesRead);
- if (response == TTYResponse::OK) {
- std::string receivedData(buffer.begin(),
- buffer.begin() + nbytesRead);
- std::cout << "Received: " << receivedData << " (" << nbytesRead
- << " bytes)" << std::endl;
- } else {
- std::cerr << "Failed to receive data: " << getErrorMessage(response)
- << std::endl;
- }
- }
-};
-
-int main() {
- // Create an instance of the TTY client
- MyTtyClient ttyClient("MyTTYDriver");
-
- // Example device name (update it to your actual device)
- const std::string device = "/dev/ttyUSB0";
-
- // Connect to the TTY device
- ttyClient.exampleConnect(device);
-
- // Send some data
- ttyClient.exampleSendData("Hello TTY!");
-
- // Receive some data
- ttyClient.exampleReceiveData(100);
-
- // Disconnect from the device if needed
- ttyClient.disconnect();
-
- return 0;
-}
diff --git a/example/atom/connection/udp_server.cpp b/example/atom/connection/udp_server.cpp
deleted file mode 100644
index 9c6003bf..00000000
--- a/example/atom/connection/udp_server.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "atom/connection/udp_server.hpp"
-
-#include
-#include
-
-// Function to handle incoming messages
-void onMessageReceived(const std::string& message, const std::string& senderIp,
- int senderPort) {
- std::cout << "Received message: " << message << " from " << senderIp << ":"
- << senderPort << std::endl;
-}
-
-// Function to run the UDP server
-void runUdpServer(int port) {
- atom::connection::UdpSocketHub udpServer;
-
- // Add message handler
- udpServer.addMessageHandler(onMessageReceived);
-
- // Start the UDP server
- udpServer.start(port);
- std::cout << "UDP server started on port " << port << std::endl;
-
- // Keep the server running for a while to receive messages
- std::this_thread::sleep_for(std::chrono::seconds(30));
-
- // Stop the UDP server
- udpServer.stop();
- std::cout << "UDP server stopped." << std::endl;
-}
-
-int main() {
- const int port = 8080; // Port to listen for incoming messages
-
- // Run the UDP server in a thread
- std::thread serverThread(runUdpServer, port);
-
- // Wait for the server thread to finish
- serverThread.join();
-
- return 0;
-}
diff --git a/example/atom/connection/updclient.cpp b/example/atom/connection/updclient.cpp
deleted file mode 100644
index 310f84ce..00000000
--- a/example/atom/connection/updclient.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * main.cpp
- *
- * Copyright (C) 2023-2024 Max Qian
- */
-
-/*************************************************
-
-Date: 2024-10-01
-
-Description: Example usage of the UdpClient class.
-
-**************************************************/
-
-#include
-#include
-
-#include "atom/connection/udpclient.hpp"
-
-// Function to handle incoming data
-void onDataReceived(const std::vector& data, const std::string& senderIp,
- int senderPort) {
- std::string receivedData(data.begin(), data.end());
- std::cout << "Received data: '" << receivedData << "' from " << senderIp
- << ":" << senderPort << std::endl;
-}
-
-// Function to handle errors
-void onError(const std::string& errorMessage) {
- std::cerr << "Error: " << errorMessage << std::endl;
-}
-
-// Function to run the UDP client
-void runUdpClient(const std::string& host, int port) {
- atom::connection::UdpClient udpClient;
-
- // Set up callbacks
- udpClient.setOnDataReceivedCallback(onDataReceived);
- udpClient.setOnErrorCallback(onError);
-
- // Bind to a port for receiving
- if (!udpClient.bind(8080)) { // Using port 8080 for receiving
- std::cerr << "Failed to bind UDP client to port 8080." << std::endl;
- return;
- }
-
- // Start receiving data
- udpClient.startReceiving(
- 1024); // Start receiving with a buffer size of 1024
-
- // Simulate sending a message to the server
- std::string message = "Hello, UDP Server!";
- if (udpClient.send(host, port,
- std::vector(message.begin(), message.end()))) {
- std::cout << "Sent message: " << message << std::endl;
- } else {
- std::cerr << "Failed to send message." << std::endl;
- }
-
- // Let it run for some time to receive responses
- std::this_thread::sleep_for(std::chrono::seconds(10));
-
- // Stop receiving data
- udpClient.stopReceiving();
-}
-
-int main() {
- const std::string host =
- "127.0.0.1"; // Replace with the server's IP address or hostname
- const int port = 8080; // Replace with the server's port
-
- // Run the UDP client
- runUdpClient(host, port);
-
- return 0;
-}
diff --git a/example/atom/error/eventstack.cpp b/example/atom/error/eventstack.cpp
deleted file mode 100644
index a54cf838..00000000
--- a/example/atom/error/eventstack.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include
-#include
-
-#include "atom/error/error_stack.hpp"
-
-// Function to simulate error insertion
-void simulateErrors(atom::error::ErrorStack& errorStack) {
- errorStack.insertError("Failed to connect to the database",
- "DatabaseModule", "connect", 25, "database.cpp");
- errorStack.insertError("Invalid user input", "UserInputModule",
- "validateInput", 42, "user_input.cpp");
- errorStack.insertError("Connection timeout", "NetworkModule", "sendRequest",
- 15, "network.cpp");
- errorStack.insertError("Failed to read configuration file", "ConfigModule",
- "loadConfig", 33, "config.cpp");
-}
-
-// Function to demonstrate error filtering and printing
-void demonstrateErrorStack() {
- // Create an instance of ErrorStack
- atom::error::ErrorStack errorStack;
-
- // Simulate error occurrences
- simulateErrors(errorStack);
-
- // Set modules to filter out (e.g., filter out errors from the
- // DatabaseModule)
- errorStack.setFilteredModules({"DatabaseModule"});
-
- // Print the filtered error stack
- std::cout << "Filtered error stack (excluding DatabaseModule):"
- << std::endl;
- errorStack.printFilteredErrorStack();
-
- // Clear the filtered modules for future prints
- errorStack.clearFilteredModules();
-
- // Print all errors
- std::cout << "\nAll errors in the stack:" << std::endl;
- errorStack.printFilteredErrorStack();
-}
-
-int main() {
- demonstrateErrorStack();
- return 0;
-}
diff --git a/example/atom/function/abi.cpp b/example/atom/function/abi.cpp
deleted file mode 100644
index 98dc415f..00000000
--- a/example/atom/function/abi.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include
-#include
-
-#include "atom/function/abi.hpp"
-
-// Example structures and classes to test demangling
-struct MyStruct {
- int a;
- double b;
-};
-
-class MyClass {
-public:
- void myMethod(int x) {}
-};
-
-int main() {
- // Demangle a simple type
- std::cout << "Demangled type for int: "
- << atom::meta::DemangleHelper::demangleType() << std::endl;
-
- // Demangle a struct
- std::cout << "Demangled type for MyStruct: "
- << atom::meta::DemangleHelper::demangleType()
- << std::endl;
-
- // Demangle a class
- std::cout << "Demangled type for MyClass: "
- << atom::meta::DemangleHelper::demangleType()
- << std::endl;
-
- // Use an instance to demangle
- MyClass myClassInstance;
- std::cout << "Demangled type for instance of MyClass: "
- << atom::meta::DemangleHelper::demangleType(myClassInstance)
- << std::endl;
-
- // Demangle multiple types
- std::vector typesToDemangle = {
- "std::vector", "std::map>",
- "MyClass::myMethod(int)"};
-
- auto demangledTypes =
- atom::meta::DemangleHelper::demangleMany(typesToDemangle);
- std::cout << "Demangled multiple types:\n";
- for (const auto& type : demangledTypes) {
- std::cout << " - " << type << std::endl;
- }
- return 0;
-}
diff --git a/example/atom/function/any.cpp b/example/atom/function/any.cpp
deleted file mode 100644
index 62ecc47d..00000000
--- a/example/atom/function/any.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#include
-
-#include "atom/function/any.hpp"
-
-int main() {
- // Create a BoxedValue containing an integer
- atom::meta::BoxedValue intValue = atom::meta::makeBoxedValue(42);
- std::cout << "Boxed integer: " << intValue.debugString() << std::endl;
-
- // Create a BoxedValue containing a string
- std::string testString = "Hello, BoxedValue!";
- atom::meta::BoxedValue stringValue = atom::meta::makeBoxedValue(testString);
- std::cout << "Boxed string: " << stringValue.debugString() << std::endl;
-
- // Create a BoxedValue containing a vector
- std::vector numbers{1, 2, 3, 4, 5};
- atom::meta::BoxedValue vectorValue = atom::meta::makeBoxedValue(numbers);
- std::cout << "Boxed vector: " << vectorValue.debugString() << std::endl;
-
- // Demonstrate type casting
- if (auto intPtr = intValue.tryCast()) {
- std::cout << "Casted integer value: " << *intPtr << std::endl;
- } else {
- std::cout << "Failed to cast to integer." << std::endl;
- }
-
- if (auto stringPtr = stringValue.tryCast()) {
- std::cout << "Casted string value: " << *stringPtr << std::endl;
- } else {
- std::cout << "Failed to cast to string." << std::endl;
- }
-
- // Attempt to cast to an incorrect type
- if (auto doublePtr = intValue.tryCast()) {
- std::cout << "Casted double value: " << *doublePtr << std::endl;
- } else {
- std::cout << "Failed to cast integer to double." << std::endl;
- }
-
- // Set an attribute
- stringValue.setAttr("greeting", atom::meta::makeBoxedValue("Hi there!"));
- if (auto greeting = stringValue.getAttr("greeting"); !greeting.isNull()) {
- std::cout << "Retrieved greeting: " << greeting.debugString()
- << std::endl;
- }
-
- // List all attributes
- auto attributes = stringValue.listAttrs();
- std::cout << "Attributes in stringValue:" << std::endl;
- for (const auto& attr : attributes) {
- std::cout << " - " << attr << std::endl;
- }
-
- // Remove the attribute
- stringValue.removeAttr("greeting");
- std::cout << "Removed 'greeting' attribute." << std::endl;
-
- // Checking if the attribute still exists
- if (!stringValue.hasAttr("greeting")) {
- std::cout << "Attribute 'greeting' no longer exists." << std::endl;
- }
- return 0;
-}
diff --git a/example/atom/function/anymeta.cpp b/example/atom/function/anymeta.cpp
deleted file mode 100644
index d3fafad6..00000000
--- a/example/atom/function/anymeta.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include
-
-#include "atom/function/anymeta.hpp"
-
-// Sample class to demonstrate the functionality
-class Sample {
-public:
- Sample(int initialValue) : value(initialValue) {}
-
- int getValue() const { return value; }
-
- void setValue(int newValue) { value = newValue; }
-
- void display() const {
- std::cout << "Current value: " << value << std::endl;
- }
-
-private:
- int value;
-};
-
-// Register the Sample class in the TypeRegistry
-void registerSampleType() {
- atom::meta::TypeMetadata metadata;
-
- // Adding methods
- metadata.addMethod(
- "display",
- [](std::vector args) -> atom::meta::BoxedValue {
- auto& obj = std::any_cast(args[0].get());
- obj.display();
- return {};
- });
-
- // Adding properties
- metadata.addProperty(
- "value",
- [](const atom::meta::BoxedValue& obj) -> atom::meta::BoxedValue {
- const Sample& sample = std::any_cast(obj.get());
- return atom::meta::makeBoxedValue(sample.getValue());
- },
- [](atom::meta::BoxedValue& obj, const atom::meta::BoxedValue& value) {
- Sample& sample = std::any_cast(obj.get());
- sample.setValue(std::any_cast(value.get()));
- });
-
- // Registering the type
- atom::meta::TypeRegistry::instance().registerType("Sample", metadata);
-}
-
-int main() {
- // Register the Sample type with its metadata
- registerSampleType();
-
- // Create an instance of Sample and box it
- Sample sampleObj(10);
- atom::meta::BoxedValue boxedSample = atom::meta::makeBoxedValue(sampleObj);
-
- // Call the display method dynamically
- callMethod(boxedSample, "display", {});
-
- // Get the value property
- auto value = getProperty(boxedSample, "value");
- std::cout << "Value from property: " << std::any_cast(value.get())
- << std::endl;
-
- // Set a new value using the setter property
- setProperty(boxedSample, "value", atom::meta::makeBoxedValue(42));
- std::cout << "Updated value." << std::endl;
-
- // Call the display method again to show updated value
- callMethod(boxedSample, "display", {});
-
- return 0;
-}
diff --git a/example/atom/function/bind_first.cpp b/example/atom/function/bind_first.cpp
deleted file mode 100644
index f4ce96d0..00000000
--- a/example/atom/function/bind_first.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * main.cpp
- *
- * Copyright (C) 2023-2024 Max Qian
- */
-
-/*************************************************
-
-Date: 2024-10-01
-
-Description: Example usage of the bindFirst function.
-
-**************************************************/
-
-#include "atom/function/bind_first.hpp"
-
-#include
-
-// A simple example class
-class MyClass {
-public:
- void display(int x, const std::string& message) {
- std::cout << "MyClass::display called with x: " << x
- << " and message: " << message << std::endl;
- }
-
- int add(int a, int b) { return a + b; }
-};
-
-// A simple free function
-void printMessage(float number, const std::string& message) {
- std::cout << "Message: " << message << " with number: " << number
- << std::endl;
-}
-
-int main() {
- MyClass myObj;
-
- // Bind a member function of MyClass
- auto boundDisplay = atom::meta::bindFirst(&MyClass::display, myObj);
-
- // Call the bound function
- boundDisplay(10, "Hello, World!");
-
- // Bind a free function
- auto boundPrintMessage = atom::meta::bindFirst(printMessage, 3.14f);
-
- // Call the bound free function
- boundPrintMessage("This is a test message");
-
- // Binding with a member function that returns a value
- auto boundAdd = atom::meta::bindFirst(&MyClass::add, myObj);
-
- // Call the bound add function and get the result
- int result = boundAdd(5, 7);
- std::cout << "Result of add: " << result << std::endl;
-
- return 0;
-}
diff --git a/example/atom/function/constructor.cpp b/example/atom/function/constructor.cpp
deleted file mode 100644
index eb289a92..00000000
--- a/example/atom/function/constructor.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "atom/function/constructor.hpp"
-#include
-#include
-#include
-
-class Example {
-public:
- Example() { std::cout << "Default constructor called." << std::endl; }
-
- Example(int a, double b, const std::string& c) : a_(a), b_(b), c_(c) {
- std::cout << "Parameterized constructor called: " << a_ << ", " << b_
- << ", " << c_ << std::endl;
- }
-
- Example(const Example& other) : a_(other.a_), b_(other.b_), c_(other.c_) {
- std::cout << "Copy constructor called." << std::endl;
- }
-
- void print() const {
- std::cout << "Values: " << a_ << ", " << b_ << ", " << c_ << std::endl;
- }
-
-private:
- int a_ = 0;
- double b_ = 0.0;
- std::string c_ = "default";
-};
-
-int main() {
- // 使用默认构造函数
- auto default_constructor = atom::meta::defaultConstructor();
- Example example1 = default_constructor();
-
- // 使用带参数的构造函数
- auto param_constructor =
- atom::meta::constructorWithArgs();
- std::shared_ptr example2 =
- param_constructor(42, 3.14, "Hello, world!");
-
- example2->print();
-
- /*
- // 使用复制构造函数
- auto copy_constructor = atom::meta::constructor();
- Example example3 = copy_constructor(*example2);
-
- example3.print();
- */
-
- return 0;
-}
diff --git a/example/atom/function/conversion.cpp b/example/atom/function/conversion.cpp
deleted file mode 100644
index 003a2afc..00000000
--- a/example/atom/function/conversion.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-
-#include "atom/function/conversion.hpp" // Include your conversion header file
-
-// Define some sample classes and types
-class Base {
-public:
- virtual ~Base() = default;
- virtual void print() const { std::cout << "Base class\n"; }
-};
-
-class Derived : public Base {
-public:
- void print() const override { std::cout << "Derived class\n"; }
-};
-
-class AnotherBase {
-public:
- virtual ~AnotherBase() = default;
- virtual void print() const { std::cout << "AnotherBase class\n"; }
-};
-
-class AnotherDerived : public AnotherBase {
-public:
- void print() const override { std::cout << "AnotherDerived class\n"; }
-};
-
-// Define some sample conversion functions
-void setupConversions() {
- // Create a shared instance of TypeConversions
- auto typeConversions = atom::meta::TypeConversions::createShared();
-
- // Add base and derived class conversions
- typeConversions->addBaseClass();
- typeConversions->addBaseClass();
-
- // Add vector conversions
- typeConversions->addVectorConversion();
-
- // Add map conversions (for demonstration purposes)
- typeConversions->addMapConversion, std::string,
- std::shared_ptr>();
-
- // Add sequence conversions
- typeConversions->addSequenceConversion();
-}
-
-void conversionExamples() {
- // Create the conversions setup
- setupConversions();
-
- // Create a TypeConversions instance
- auto typeConversions = atom::meta::TypeConversions::createShared();
-
- // Sample objects for conversion
- std::shared_ptr derived = std::make_shared();
- std::shared_ptr base;
-
- // Perform conversions
- try {
- // Convert from Derived* to Base*
- base = std::any_cast>(
- typeConversions->convert,
- std::shared_ptr>(derived));
- base->print(); // Should output: Derived class
-
- // Convert a vector of Derived to vector of Base
- std::vector> derivedVec = {derived};
- std::vector> baseVec =
- std::any_cast>>(
- typeConversions->convert>,
- std::vector>>(
- derivedVec));
- for (const auto& b : baseVec) {
- b->print(); // Should output: Derived class
- }
-
- // Convert a map from > to >
- std::unordered_map> baseMap;
- baseMap["key"] = derived;
- auto convertedMap = std::any_cast<
- std::unordered_map>>(
- typeConversions->convert<
- std::unordered_map>,
- std::unordered_map