├── .clang-format ├── .clang-tidy ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── build_options.cmake ├── doc └── publisher_and_subscriber.gif ├── examples ├── CMakeLists.txt ├── hello_world_idl │ ├── CMakeLists.txt │ ├── hello_world.cxx │ ├── hello_world.h │ ├── hello_world.idl │ ├── hello_worldPubSubTypes.cxx │ ├── hello_worldPubSubTypes.h │ ├── pub.cpp │ └── sub.cpp ├── hello_world_proto │ ├── CMakeLists.txt │ ├── hello_wrold.pb.cc │ ├── hello_wrold.pb.h │ ├── hello_wrold.proto │ ├── pub.cpp │ └── sub.cpp └── hello_world_zero_copy │ ├── CMakeLists.txt │ ├── hello_world.h │ ├── pub.cpp │ ├── serializer_hello_world.h │ └── sub.cpp ├── package.xml ├── project_settings.cmake ├── smw.repos ├── smw_core ├── CMakeLists.txt ├── include │ ├── publisher.h │ ├── runtime.h │ ├── runtime_option.h │ ├── serializer │ │ ├── serializer_idl.h │ │ └── serializer_protobuf.h │ ├── service_description.h │ ├── service_proxy.h │ ├── service_registry.h │ ├── service_skeleton.h │ ├── service_status.h │ ├── subscriber.h │ └── transport │ │ ├── dds │ │ ├── dds_factory.h │ │ ├── fastdds_data_type.h │ │ ├── fastdds_participant.h │ │ ├── fastdds_reader.h │ │ └── fastdds_writer.h │ │ ├── iceoryx │ │ ├── iceoryx_reader.h │ │ ├── iceoryx_runtime.h │ │ └── iceoryx_writer.h │ │ ├── transport_reader.h │ │ └── transport_writer.h ├── proto │ ├── service_discovery.pb.cc │ ├── service_discovery.pb.h │ └── service_discovery.proto ├── src │ ├── runtime.cpp │ ├── service_proxy.cpp │ ├── service_registry.cpp │ ├── service_skeleton.cpp │ └── transport │ │ ├── dds │ │ └── fastdds_participant.cpp │ │ └── iceoryx │ │ └── iceoryx_runtime.cpp └── test │ ├── CMakeLists.txt │ ├── main.cpp │ ├── run_test.sh │ ├── test.h │ ├── test_data.pb.cc │ ├── test_data.pb.h │ ├── test_data.proto │ ├── test_fastdds_data_type_protobuf.cpp │ ├── test_fastdds_writer_reader.cpp │ ├── test_iceoryx_writer_reader.cpp │ ├── test_publisher.cpp │ ├── test_publisher_and_subscriber.cpp │ ├── test_runtime.cpp │ ├── test_service_registry.cpp │ └── test_subscriber.cpp ├── smw_types ├── CMakeLists.txt ├── include │ ├── result.h │ └── sample_ptr.h └── test │ ├── CMakeLists.txt │ ├── main.cpp │ ├── test.h │ └── test_result.cpp ├── smw_utils ├── CMakeLists.txt ├── include │ └── host_id.h ├── src │ └── host_id.cpp └── test │ ├── CMakeLists.txt │ ├── main.cpp │ ├── test.h │ └── test_host_id.cpp └── third_party └── spdlog ├── .clang-format ├── .clang-tidy ├── .gitattributes ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── INSTALL ├── LICENSE ├── README.md ├── appveyor.yml ├── bench ├── CMakeLists.txt ├── async_bench.cpp ├── bench.cpp ├── formatter-bench.cpp ├── latency.cpp └── utils.h ├── cmake ├── ide.cmake ├── pch.h.in ├── spdlog.pc.in ├── spdlogCPack.cmake ├── spdlogConfig.cmake.in ├── utils.cmake └── version.rc.in ├── example ├── CMakeLists.txt └── example.cpp ├── include └── spdlog │ ├── async.h │ ├── async_logger-inl.h │ ├── async_logger.h │ ├── cfg │ ├── argv.h │ ├── env.h │ ├── helpers-inl.h │ └── helpers.h │ ├── common-inl.h │ ├── common.h │ ├── details │ ├── backtracer-inl.h │ ├── backtracer.h │ ├── circular_q.h │ ├── console_globals.h │ ├── file_helper-inl.h │ ├── file_helper.h │ ├── fmt_helper.h │ ├── log_msg-inl.h │ ├── log_msg.h │ ├── log_msg_buffer-inl.h │ ├── log_msg_buffer.h │ ├── mpmc_blocking_q.h │ ├── null_mutex.h │ ├── os-inl.h │ ├── os.h │ ├── periodic_worker-inl.h │ ├── periodic_worker.h │ ├── registry-inl.h │ ├── registry.h │ ├── synchronous_factory.h │ ├── tcp_client-windows.h │ ├── tcp_client.h │ ├── thread_pool-inl.h │ ├── thread_pool.h │ ├── udp_client-windows.h │ ├── udp_client.h │ └── windows_include.h │ ├── fmt │ ├── bin_to_hex.h │ ├── bundled │ │ ├── args.h │ │ ├── chrono.h │ │ ├── color.h │ │ ├── compile.h │ │ ├── core.h │ │ ├── fmt.license.rst │ │ ├── format-inl.h │ │ ├── format.h │ │ ├── locale.h │ │ ├── os.h │ │ ├── ostream.h │ │ ├── printf.h │ │ ├── ranges.h │ │ └── xchar.h │ ├── chrono.h │ ├── compile.h │ ├── fmt.h │ ├── ostr.h │ └── xchar.h │ ├── formatter.h │ ├── fwd.h │ ├── logger-inl.h │ ├── logger.h │ ├── pattern_formatter-inl.h │ ├── pattern_formatter.h │ ├── sinks │ ├── android_sink.h │ ├── ansicolor_sink-inl.h │ ├── ansicolor_sink.h │ ├── base_sink-inl.h │ ├── base_sink.h │ ├── basic_file_sink-inl.h │ ├── basic_file_sink.h │ ├── daily_file_sink.h │ ├── dist_sink.h │ ├── dup_filter_sink.h │ ├── hourly_file_sink.h │ ├── mongo_sink.h │ ├── msvc_sink.h │ ├── null_sink.h │ ├── ostream_sink.h │ ├── qt_sinks.h │ ├── ringbuffer_sink.h │ ├── rotating_file_sink-inl.h │ ├── rotating_file_sink.h │ ├── sink-inl.h │ ├── sink.h │ ├── stdout_color_sinks-inl.h │ ├── stdout_color_sinks.h │ ├── stdout_sinks-inl.h │ ├── stdout_sinks.h │ ├── syslog_sink.h │ ├── systemd_sink.h │ ├── tcp_sink.h │ ├── udp_sink.h │ ├── win_eventlog_sink.h │ ├── wincolor_sink-inl.h │ └── wincolor_sink.h │ ├── spdlog-inl.h │ ├── spdlog.h │ ├── stopwatch.h │ ├── tweakme.h │ └── version.h ├── logos └── jetbrains-variant-4.svg ├── scripts ├── extract_version.py └── format.sh ├── src ├── async.cpp ├── cfg.cpp ├── color_sinks.cpp ├── file_sinks.cpp ├── fmt.cpp ├── spdlog.cpp └── stdout_sinks.cpp └── tests ├── CMakeLists.txt ├── catch.hpp ├── catch.license ├── includes.h ├── main.cpp ├── test_async.cpp ├── test_backtrace.cpp ├── test_cfg.cpp ├── test_create_dir.cpp ├── test_daily_logger.cpp ├── test_dup_filter.cpp ├── test_errors.cpp ├── test_eventlog.cpp ├── test_file_helper.cpp ├── test_file_logging.cpp ├── test_fmt_helper.cpp ├── test_macros.cpp ├── test_misc.cpp ├── test_mpmc_q.cpp ├── test_pattern_formatter.cpp ├── test_registry.cpp ├── test_sink.h ├── test_stdout_api.cpp ├── test_stopwatch.cpp ├── test_systemd.cpp ├── test_time_point.cpp ├── utils.cpp └── utils.h /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | # for complete code formatting of codebase please type: 3 | # "find . -type f -regex '.*\.\(inl\|cpp\|h\|hpp\|cc\|c\|cxx\)' -exec clang-format-10 -style=file -i {} \;" 4 | Language: Cpp 5 | AccessModifierOffset: -2 6 | AlignAfterOpenBracket: Align 7 | AlignConsecutiveAssignments: None 8 | AlignConsecutiveDeclarations: None 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: Empty 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: None 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: Yes 21 | BinPackArguments: false 22 | BinPackParameters: false # If false, a function declaration's or function definition's parameters will either all be on the same line or will have one line each. 23 | BreakBeforeBraces: Custom 24 | BraceWrapping: 25 | AfterCaseLabel: true 26 | AfterClass: true 27 | AfterControlStatement: "true" 28 | AfterEnum: true 29 | AfterFunction: true 30 | AfterNamespace: true 31 | AfterObjCDeclaration: true 32 | AfterStruct: true 33 | AfterUnion: true 34 | BeforeCatch: true 35 | BeforeElse: true 36 | IndentBraces: false 37 | BreakBeforeBinaryOperators: NonAssignment 38 | BreakBeforeTernaryOperators: true 39 | BreakConstructorInitializersBeforeComma: true 40 | ColumnLimit: 120 41 | CompactNamespaces: true 42 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 43 | ConstructorInitializerIndentWidth: 4 44 | ContinuationIndentWidth: 4 45 | Cpp11BracedListStyle: true 46 | DerivePointerAlignment: false 47 | DisableFormat: false 48 | ExperimentalAutoDetectBinPacking: false 49 | FixNamespaceComments: true 50 | IndentCaseLabels: false 51 | IndentWidth: 4 52 | IndentWrappedFunctionNames: false 53 | KeepEmptyLinesAtTheStartOfBlocks: false 54 | MacroBlockBegin: '' 55 | MacroBlockEnd: '' 56 | MaxEmptyLinesToKeep: 2 57 | NamespaceIndentation: None 58 | PenaltyBreakBeforeFirstCallParameter: 19 59 | PenaltyBreakComment: 300 60 | PenaltyBreakFirstLessLess: 120 61 | PenaltyBreakString: 1000 62 | PenaltyExcessCharacter: 1000000 63 | PenaltyReturnTypeOnItsOwnLine: 60 64 | PointerAlignment: Left 65 | ReflowComments: true 66 | SortIncludes: CaseSensitive 67 | SpaceAfterCStyleCast: false 68 | SpaceBeforeAssignmentOperators: true 69 | SpaceBeforeParens: ControlStatements 70 | SpaceInEmptyParentheses: false 71 | SpacesBeforeTrailingComments: 1 72 | SpacesInAngles: false 73 | SpacesInContainerLiterals: false 74 | SpacesInCStyleCastParentheses: false 75 | SpacesInParentheses: false 76 | SpacesInSquareBrackets: false 77 | Standard: c++17 78 | TabWidth: 4 79 | UseTab: Never 80 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # NOTE: following checks are disabled, because they have duplicates in other group: 2 | # 3 | # - readability-magic-numbers (duplicate of cppcoreguidelines-avoid-magic-numbers) 4 | # - hicpp-no-malloc (duplicate of cppcoreguidelines-no-malloc) 5 | # - hicpp-member-init (duplicate of cppcoreguidelines-pro-type-member-init) 6 | # - performance-move-const-arg (duplicate of hicpp-move-const-arg) 7 | # - bugprone-use-after-move (duplicate of hicpp-move-const-arg) 8 | 9 | Checks: ' 10 | -*, 11 | readability-*, 12 | clang-analyzer-*, 13 | cert-*, 14 | bugprone-*, 15 | -readability-named-parameter, 16 | -readability-avoid-const-params-in-decls, 17 | -readability-else-after-return,performance-*, 18 | -readability-redundant-access-specifiers,hicpp-*, 19 | -readability-magic-numbers, 20 | -hicpp-named-parameter, 21 | -hicpp-avoid-c-arrays,cppcoreguidelines-*, 22 | -hicpp-no-array-decay,-hicpp-signed-bitwise, 23 | -hicpp-vararg, 24 | -hicpp-no-malloc, 25 | -hicpp-member-init, 26 | -performance-move-const-arg, 27 | -cppcoreguidelines-avoid-c-arrays, 28 | -cppcoreguidelines-pro-bounds-constant-array-index, 29 | -cppcoreguidelines-pro-bounds-array-to-pointer-decay, 30 | -cppcoreguidelines-pro-type-vararg,concurrency-*, 31 | -cppcoreguidelines-macro-usage, 32 | -cppcoreguidelines-avoid-non-const-global-variables, 33 | -cppcoreguidelines-pro-type-reinterpret-cast, 34 | -bugprone-use-after-move, 35 | -hicpp-move-const-arg, 36 | -hicpp-invalid-access-moved' 37 | 38 | CheckOptions: 39 | - { key: readability-identifier-naming.ClassCase, value: CamelCase } 40 | - { key: readability-identifier-naming.EnumCase, value: CamelCase } 41 | - { key: readability-identifier-naming.StructCase, value: CamelCase } 42 | - { key: readability-identifier-naming.UnionCase, value: CamelCase } 43 | - { key: readability-identifier-naming.MethodCase, value: camelBack } 44 | - { key: readability-identifier-naming.FunctionCase, value: camelBack } 45 | - { key: readability-identifier-naming.NamespaceCase, value: lower_case } 46 | - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ } 47 | - { key: readability-identifier-naming.ProtectedMemberPrefix, value: m_ } 48 | - { key: readability-identifier-naming.MemberCase, value: camelBack } 49 | - { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE } 50 | - { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE } 51 | - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE } 52 | - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } 53 | - { key: readability-function-size.LineThreshold, value: 200 } 54 | - { key: readability-function-size.StatementThreshold, value: 200 } 55 | - { key: readability-function-size.BranchThreshold, value: 10 } 56 | - { key: readability-function-size.ParameterThreshold, value: 3 } 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # IDE configuarions 35 | /.idea/ 36 | /.vscode/ 37 | /cmake-build-*/ 38 | /build/ 39 | /install/ -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | project(smw) 4 | 5 | if (NOT CMAKE_BUILD_TYPE) 6 | set(CMAKE_BUILD_TYPE Release) 7 | endif (NOT CMAKE_BUILD_TYPE) 8 | 9 | include(${CMAKE_CURRENT_SOURCE_DIR}/build_options.cmake) 10 | include(${CMAKE_CURRENT_SOURCE_DIR}/project_settings.cmake) 11 | 12 | add_subdirectory(third_party/spdlog) 13 | add_subdirectory(smw_types) 14 | add_subdirectory(smw_core) 15 | add_subdirectory(smw_utils) 16 | add_subdirectory(examples) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # smw 2 | 3 | ## Genernal 4 | 5 | A Scalable Middleware,integration Eclipse iceoryx and Fast-DDS. 6 | 7 | The main aim is to encapsulate an adaptive middleware,it can deal with relation of communication partners automatically. 8 | 9 | Communication on same "Host" will use iceoryx,benefit from it's zero-copy ability. 10 | 11 | Communication on different "Host" will use Fast-DDS,benefit from flexible DDS protocol. 12 | 13 | Maybe I would support SOME/IP protocol for interoperating with AUTOSAR AP... 14 | 15 | ## Example 16 | ![image](https://github.com/yooouxin/smw/blob/main/doc/publisher_and_subscriber.gif) 17 | 18 | ## Dependencies 19 | 20 | ### fmt 21 | 22 | https://github.com/fmtlib/fmt 23 | 24 | ### Fast-DDS 25 | 26 | https://github.com/eProsima/Fast-DDS 27 | 28 | ### Eclipse iceoryx 29 | 30 | https://github.com/eclipse-iceoryx/iceoryx 31 | 32 | ### Google Protobuf 33 | 34 | https://developers.google.com/protocol-buffers 35 | 36 | ## TODO 37 | ... 38 | -------------------------------------------------------------------------------- /build_options.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | 6 | option(BUILD_SHARED_LIBS "Build smw as shared libraries" OFF) 7 | option(BUILD_TEST "Build all tests" OFF) -------------------------------------------------------------------------------- /doc/publisher_and_subscriber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yooouxin/smw/564831a573f3c31444c6a9b34865310a9b87e08f/doc/publisher_and_subscriber.gif -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | add_subdirectory(hello_world_proto) 4 | add_subdirectory(hello_world_idl) 5 | add_subdirectory(hello_world_zero_copy) -------------------------------------------------------------------------------- /examples/hello_world_idl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(EXAMPLE_NAME smw_example_hello_world_idl) 4 | 5 | add_executable(${EXAMPLE_NAME}_pub pub.cpp hello_world.cxx hello_worldPubSubTypes.cxx) 6 | 7 | target_link_libraries(${EXAMPLE_NAME}_pub 8 | PRIVATE 9 | smw_core 10 | ) 11 | 12 | set_target_properties(${EXAMPLE_NAME}_pub PROPERTIES 13 | CXX_STANDARD_REQUIRED ON 14 | CXX_STANDARD ${SMW_CXX_STANDARD} 15 | POSITION_INDEPENDENT_CODE ON 16 | ) 17 | 18 | add_executable(${EXAMPLE_NAME}_sub sub.cpp hello_world.cxx hello_worldPubSubTypes.cxx) 19 | 20 | target_link_libraries(${EXAMPLE_NAME}_sub 21 | PRIVATE 22 | smw_core 23 | ) 24 | 25 | set_target_properties(${EXAMPLE_NAME}_sub PROPERTIES 26 | CXX_STANDARD_REQUIRED ON 27 | CXX_STANDARD ${SMW_CXX_STANDARD} 28 | POSITION_INDEPENDENT_CODE ON 29 | ) -------------------------------------------------------------------------------- /examples/hello_world_idl/hello_world.idl: -------------------------------------------------------------------------------- 1 | struct HelloWorld 2 | { 3 | unsigned long index; 4 | string message; 5 | }; 6 | -------------------------------------------------------------------------------- /examples/hello_world_idl/pub.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/8. 3 | // 4 | 5 | #include "hello_worldPubSubTypes.h" 6 | #include "runtime.h" 7 | #include "serializer/serializer_idl.h" 8 | constexpr static uint32_t TEST_SERVICE = 10; 9 | constexpr static uint32_t TEST_INSTANCE = 1; 10 | constexpr static uint32_t TEST_EVENT = 2; 11 | 12 | static bool exit_request = false; 13 | 14 | using namespace smw::core; 15 | 16 | void signalHandler(int signum) 17 | { 18 | (void)signum; 19 | exit_request = true; 20 | } 21 | 22 | int main() 23 | { 24 | eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); 25 | spdlog::set_level(spdlog::level::level_enum::err); 26 | signal(SIGINT, signalHandler); 27 | signal(SIGTERM, signalHandler); 28 | 29 | RuntimeOption option{"smw_example_hello_world_idl_pub"}; 30 | auto& runtime = Runtime::initRuntime(option); 31 | ServiceDescription serviceDescription; 32 | serviceDescription.service_id = TEST_SERVICE; 33 | serviceDescription.instance_id = TEST_INSTANCE; 34 | 35 | auto service_skeleton = runtime.getInstance().createServiceSkeleton(serviceDescription); 36 | 37 | std::unique_ptr>> publisher{nullptr}; 38 | publisher = std::move(service_skeleton->createPublisher>(TEST_EVENT) 39 | .orElse([](auto& error) { return error; }) 40 | .getValue()); 41 | 42 | assert(publisher); 43 | 44 | HelloWorld message; 45 | int32_t index = 0; 46 | while (!exit_request) 47 | { 48 | message.index(index++); 49 | message.message("Hello"); 50 | publisher->publish(message).orElse( 51 | [](auto& error) { std::cout << static_cast(error) << std::endl; }); 52 | using namespace std::chrono_literals; 53 | std::this_thread::sleep_for(1s); 54 | } 55 | 56 | 57 | return 0; 58 | } -------------------------------------------------------------------------------- /examples/hello_world_idl/sub.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/4. 3 | // 4 | #include "hello_worldPubSubTypes.h" 5 | #include "runtime.h" 6 | #include "serializer/serializer_idl.h" 7 | #include 8 | 9 | using namespace smw::core; 10 | 11 | constexpr static uint32_t TEST_SERVICE = 10; 12 | constexpr static uint32_t TEST_INSTANCE = 1; 13 | constexpr static uint32_t TEST_EVENT = 2; 14 | 15 | static bool exit_request = false; 16 | 17 | 18 | void signalHandler(int signum) 19 | { 20 | (void)signum; 21 | exit_request = true; 22 | } 23 | 24 | int main() 25 | { 26 | eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); 27 | spdlog::set_level(spdlog::level::level_enum::err); 28 | signal(SIGINT, signalHandler); 29 | signal(SIGTERM, signalHandler); 30 | 31 | RuntimeOption option{"smw_example_hello_world_idl_sub"}; 32 | auto& runtime = Runtime::initRuntime(option); 33 | ServiceDescription serviceDescription; 34 | serviceDescription.service_id = TEST_SERVICE; 35 | serviceDescription.instance_id = TEST_INSTANCE; 36 | 37 | 38 | auto service_proxy = runtime.getInstance().createServiceProxy(serviceDescription); 39 | 40 | auto subscriber = 41 | std::move(service_proxy->createSubscriber>(TEST_EVENT) 42 | .orElse([](auto& error) { return error; }) 43 | .getValue()); 44 | 45 | assert(subscriber); 46 | 47 | /// print debug string received 48 | auto callback = [](SamplePtr sample_ptr) { 49 | std::cout << sample_ptr->index() << std::endl; 50 | std::cout << sample_ptr->message() << std::endl; 51 | }; 52 | subscriber->registerReceiveHandler(callback); 53 | 54 | while (!exit_request) 55 | { 56 | using namespace std::chrono_literals; 57 | std::this_thread::sleep_for(1s); 58 | } 59 | return 0; 60 | } -------------------------------------------------------------------------------- /examples/hello_world_proto/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(EXAMPLE_NAME smw_example_hello_world_proto) 4 | 5 | add_executable(${EXAMPLE_NAME}_pub pub.cpp hello_wrold.pb.cc) 6 | 7 | target_link_libraries(${EXAMPLE_NAME}_pub 8 | PRIVATE 9 | smw_core 10 | ) 11 | 12 | set_target_properties(${EXAMPLE_NAME}_pub PROPERTIES 13 | CXX_STANDARD_REQUIRED ON 14 | CXX_STANDARD ${SMW_CXX_STANDARD} 15 | POSITION_INDEPENDENT_CODE ON 16 | ) 17 | 18 | add_executable(${EXAMPLE_NAME}_sub sub.cpp hello_wrold.pb.cc) 19 | 20 | target_link_libraries(${EXAMPLE_NAME}_sub 21 | PRIVATE 22 | smw_core 23 | ) 24 | 25 | set_target_properties(${EXAMPLE_NAME}_sub PROPERTIES 26 | CXX_STANDARD_REQUIRED ON 27 | CXX_STANDARD ${SMW_CXX_STANDARD} 28 | POSITION_INDEPENDENT_CODE ON 29 | ) -------------------------------------------------------------------------------- /examples/hello_world_proto/hello_wrold.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package smw.example.proto; 4 | 5 | message HelloWorld{ 6 | int32 index = 1; 7 | string message = 2; 8 | } -------------------------------------------------------------------------------- /examples/hello_world_proto/pub.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/4. 3 | // 4 | #include "hello_wrold.pb.h" 5 | #include "runtime.h" 6 | #include 7 | #include 8 | 9 | using namespace smw::core; 10 | using namespace smw::example::proto; 11 | 12 | constexpr static uint32_t TEST_SERVICE = 10; 13 | constexpr static uint32_t TEST_INSTANCE = 1; 14 | constexpr static uint32_t TEST_EVENT = 2; 15 | 16 | static bool exit_request = false; 17 | 18 | 19 | void signalHandler(int signum) 20 | { 21 | (void)signum; 22 | exit_request = true; 23 | } 24 | 25 | int main() 26 | { 27 | eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); 28 | spdlog::set_level(spdlog::level::level_enum::err); 29 | signal(SIGINT, signalHandler); 30 | signal(SIGTERM, signalHandler); 31 | 32 | RuntimeOption option{"smw_example_hello_world_pub"}; 33 | auto& runtime = Runtime::initRuntime(option); 34 | ServiceDescription serviceDescription; 35 | serviceDescription.service_id = TEST_SERVICE; 36 | serviceDescription.instance_id = TEST_INSTANCE; 37 | 38 | auto service_skeleton = runtime.getInstance().createServiceSkeleton(serviceDescription); 39 | 40 | std::unique_ptr> publisher{nullptr}; 41 | publisher = std::move( 42 | service_skeleton->createPublisher(TEST_EVENT).orElse([](auto& error) { return error; }).getValue()); 43 | 44 | assert(publisher); 45 | 46 | HelloWorld message; 47 | int32_t index = 0; 48 | while (!exit_request) 49 | { 50 | message.set_index(index++); 51 | message.set_message("Hello"); 52 | publisher->publish(message).orElse( 53 | [](auto& error) { std::cout << static_cast(error) << std::endl; }); 54 | using namespace std::chrono_literals; 55 | std::this_thread::sleep_for(1s); 56 | } 57 | 58 | 59 | return 0; 60 | } -------------------------------------------------------------------------------- /examples/hello_world_proto/sub.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/4. 3 | // 4 | #include "hello_wrold.pb.h" 5 | #include "runtime.h" 6 | #include 7 | 8 | using namespace smw::core; 9 | using namespace smw::example::proto; 10 | 11 | constexpr static uint32_t TEST_SERVICE = 10; 12 | constexpr static uint32_t TEST_INSTANCE = 1; 13 | constexpr static uint32_t TEST_EVENT = 2; 14 | 15 | static bool exit_request = false; 16 | 17 | 18 | void signalHandler(int signum) 19 | { 20 | (void)signum; 21 | exit_request = true; 22 | } 23 | 24 | int main() 25 | { 26 | eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); 27 | spdlog::set_level(spdlog::level::level_enum::err); 28 | signal(SIGINT, signalHandler); 29 | signal(SIGTERM, signalHandler); 30 | 31 | RuntimeOption option{"smw_example_hello_world_sub1"}; 32 | auto& runtime = Runtime::initRuntime(option); 33 | ServiceDescription serviceDescription; 34 | serviceDescription.service_id = TEST_SERVICE; 35 | serviceDescription.instance_id = TEST_INSTANCE; 36 | 37 | 38 | auto service_proxy = runtime.getInstance().createServiceProxy(serviceDescription); 39 | 40 | std::unique_ptr> subscriber{nullptr}; 41 | subscriber = std::move( 42 | service_proxy->createSubscriber(TEST_EVENT).orElse([](auto& error) { return error; }).getValue()); 43 | 44 | assert(subscriber); 45 | 46 | /// print debug string received 47 | subscriber->registerReceiveHandler([](auto sample_ptr) { std::cout << sample_ptr->DebugString() << std::endl; }); 48 | 49 | while (!exit_request) 50 | { 51 | using namespace std::chrono_literals; 52 | std::this_thread::sleep_for(1s); 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/hello_world_zero_copy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(EXAMPLE_NAME smw_example_hello_world_zero_copy) 4 | 5 | add_executable(${EXAMPLE_NAME}_pub pub.cpp) 6 | 7 | target_link_libraries(${EXAMPLE_NAME}_pub 8 | PRIVATE 9 | smw_core 10 | ) 11 | 12 | set_target_properties(${EXAMPLE_NAME}_pub PROPERTIES 13 | CXX_STANDARD_REQUIRED ON 14 | CXX_STANDARD ${SMW_CXX_STANDARD} 15 | POSITION_INDEPENDENT_CODE ON 16 | ) 17 | 18 | add_executable(${EXAMPLE_NAME}_sub sub.cpp) 19 | 20 | target_link_libraries(${EXAMPLE_NAME}_sub 21 | PRIVATE 22 | smw_core 23 | ) 24 | 25 | set_target_properties(${EXAMPLE_NAME}_sub PROPERTIES 26 | CXX_STANDARD_REQUIRED ON 27 | CXX_STANDARD ${SMW_CXX_STANDARD} 28 | POSITION_INDEPENDENT_CODE ON 29 | ) -------------------------------------------------------------------------------- /examples/hello_world_zero_copy/hello_world.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/8. 3 | // 4 | 5 | #ifndef SMW_HELLO_WORLD_H 6 | #define SMW_HELLO_WORLD_H 7 | #include 8 | #include 9 | 10 | namespace smw::examples::zero_copy 11 | { 12 | struct HelloWorld 13 | { 14 | uint32_t index; 15 | std::array message; 16 | }; 17 | } // namespace smw::examples::zero_copy 18 | #endif // SMW_HELLO_WORLD_H 19 | -------------------------------------------------------------------------------- /examples/hello_world_zero_copy/pub.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/8. 3 | // 4 | 5 | 6 | #include "runtime.h" 7 | #include "serializer_hello_world.h" 8 | constexpr static uint32_t TEST_SERVICE = 10; 9 | constexpr static uint32_t TEST_INSTANCE = 1; 10 | constexpr static uint32_t TEST_EVENT = 2; 11 | 12 | static bool exit_request = false; 13 | 14 | using namespace smw::core; 15 | using smw::examples::zero_copy::HelloWorld; 16 | using smw::examples::zero_copy::SerializerHelloworld; 17 | void signalHandler(int signum) 18 | { 19 | (void)signum; 20 | exit_request = true; 21 | } 22 | 23 | int main() 24 | { 25 | static_assert(std::is_trivial_v); 26 | eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); 27 | spdlog::set_level(spdlog::level::level_enum::err); 28 | signal(SIGINT, signalHandler); 29 | signal(SIGTERM, signalHandler); 30 | 31 | RuntimeOption option{"smw_example_hello_world_idl_pub"}; 32 | auto& runtime = Runtime::initRuntime(option); 33 | ServiceDescription serviceDescription; 34 | serviceDescription.service_id = TEST_SERVICE; 35 | serviceDescription.instance_id = TEST_INSTANCE; 36 | 37 | auto service_skeleton = runtime.getInstance().createServiceSkeleton(serviceDescription); 38 | 39 | auto publisher = std::move(service_skeleton->createPublisher(TEST_EVENT) 40 | .orElse([](auto& error) { return error; }) 41 | .getValue()); 42 | 43 | assert(publisher); 44 | 45 | 46 | int32_t index = 0; 47 | while (!exit_request) 48 | { 49 | auto sample_ptr = 50 | std::move(publisher->loanSample() 51 | .orElse([](auto&& error) { std::cout << static_cast(error) << std::endl; }) 52 | .getValue()); 53 | if (!sample_ptr) 54 | { 55 | break; 56 | } 57 | sample_ptr->index = index++; 58 | sample_ptr->message = {'H', 'e', 'l', 'l', 'o'}; 59 | publisher->publish(std::move(sample_ptr)).orElse([](auto& error) { 60 | std::cout << static_cast(error) << std::endl; 61 | }); 62 | using namespace std::chrono_literals; 63 | std::this_thread::sleep_for(1s); 64 | } 65 | 66 | 67 | return 0; 68 | } -------------------------------------------------------------------------------- /examples/hello_world_zero_copy/serializer_hello_world.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/8. 3 | // 4 | 5 | #ifndef SMW_SERIALIZER_HELLO_WORLD_H 6 | #define SMW_SERIALIZER_HELLO_WORLD_H 7 | #include "hello_world.h" 8 | #include 9 | #include 10 | #include 11 | 12 | namespace smw::examples::zero_copy 13 | { 14 | class SerializerHelloworld 15 | { 16 | public: 17 | inline std::size_t getMaxSize() noexcept 18 | { 19 | return sizeof(HelloWorld); 20 | } 21 | 22 | inline std::string getTypeName() noexcept 23 | { 24 | return "smw::examples::zero_copy::Helloworld"; 25 | } 26 | 27 | inline std::size_t getSize(const void* data) noexcept 28 | { 29 | const HelloWorld* real_type = reinterpret_cast(data); 30 | return sizeof(real_type->index) + sizeof(real_type->message); 31 | } 32 | 33 | inline bool serialize(const void* from_data, void* dest_buffer, std::size_t* dest_len) noexcept 34 | { 35 | const HelloWorld* real_type = reinterpret_cast(from_data); 36 | std::byte* byte_buffer_pointer = reinterpret_cast(dest_buffer); 37 | 38 | *dest_len = getSize(from_data); 39 | 40 | /// Just a sample 41 | std::memcpy(byte_buffer_pointer, &real_type->index, sizeof(real_type->index)); 42 | std::memcpy(byte_buffer_pointer + sizeof(real_type->index), &real_type->message, sizeof(real_type->message)); 43 | return true; 44 | } 45 | 46 | inline bool deserialize(const void* from_buffer, std::size_t from_len, void* dest_data) noexcept 47 | { 48 | HelloWorld* real_type = reinterpret_cast(dest_data); 49 | const std::byte* byte_buffer_pointer = reinterpret_cast(from_buffer); 50 | 51 | std::memcpy(&real_type->index, byte_buffer_pointer, sizeof(real_type->index)); 52 | std::memcpy(&real_type->message, byte_buffer_pointer + sizeof(real_type->index), sizeof(real_type->message)); 53 | return true; 54 | } 55 | 56 | inline void* createData() noexcept 57 | { 58 | return reinterpret_cast(new HelloWorld()); 59 | } 60 | 61 | inline void deleteData(void* data) noexcept 62 | { 63 | delete (reinterpret_cast(data)); 64 | } 65 | }; 66 | } // namespace smw::examples::zero_copy 67 | #endif // SMW_SERIALIZER_HELLO_WORLD_H 68 | -------------------------------------------------------------------------------- /examples/hello_world_zero_copy/sub.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/4. 3 | // 4 | 5 | #include "runtime.h" 6 | #include "serializer_hello_world.h" 7 | #include 8 | 9 | using namespace smw::core; 10 | using smw::examples::zero_copy::HelloWorld; 11 | using smw::examples::zero_copy::SerializerHelloworld; 12 | constexpr static uint32_t TEST_SERVICE = 10; 13 | constexpr static uint32_t TEST_INSTANCE = 1; 14 | constexpr static uint32_t TEST_EVENT = 2; 15 | 16 | static bool exit_request = false; 17 | 18 | 19 | void signalHandler(int signum) 20 | { 21 | (void)signum; 22 | exit_request = true; 23 | } 24 | 25 | int main() 26 | { 27 | static_assert(std::is_trivial_v); 28 | eprosima::fastdds::dds::Log::SetVerbosity(eprosima::fastdds::dds::Log::Kind::Error); 29 | spdlog::set_level(spdlog::level::level_enum::err); 30 | signal(SIGINT, signalHandler); 31 | signal(SIGTERM, signalHandler); 32 | 33 | RuntimeOption option{"smw_example_hello_world_idl_sub"}; 34 | auto& runtime = Runtime::initRuntime(option); 35 | ServiceDescription serviceDescription; 36 | serviceDescription.service_id = TEST_SERVICE; 37 | serviceDescription.instance_id = TEST_INSTANCE; 38 | 39 | 40 | auto service_proxy = runtime.getInstance().createServiceProxy(serviceDescription); 41 | 42 | auto subscriber = std::move(service_proxy->createSubscriber(TEST_EVENT) 43 | .orElse([](auto& error) { return error; }) 44 | .getValue()); 45 | 46 | assert(subscriber); 47 | 48 | /// print debug string received 49 | auto callback = [](SamplePtr sample_ptr) { 50 | std::cout << sample_ptr->index << std::endl; 51 | /// convert std::array to std::string 52 | std::string string_message{sample_ptr->message.begin(), sample_ptr->message.end()}; 53 | std::cout << string_message << std::endl; 54 | }; 55 | subscriber->registerReceiveHandler(callback); 56 | 57 | while (!exit_request) 58 | { 59 | using namespace std::chrono_literals; 60 | std::this_thread::sleep_for(1s); 61 | } 62 | return 0; 63 | } -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | smw 5 | 0.0.1 6 | A Scalable Middleware,integration Eclipse iceoryx and Fast-DDS. 7 | youxinxin 8 | Apache 2.0 9 | 10 | cmake 11 | git 12 | 13 | fastrtps 14 | iceoryx_posh 15 | 16 | doxygen 17 | 18 | 19 | cmake 20 | 21 | 22 | -------------------------------------------------------------------------------- /project_settings.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_CXX_STANDARD 17) 3 | set(SMW_CXX_STANDARD 17) -------------------------------------------------------------------------------- /smw.repos: -------------------------------------------------------------------------------- 1 | repositories: 2 | smw: 3 | type: git 4 | url: https://github.com/yooouxin/smw.git 5 | version: master 6 | iceoryx: 7 | type:git 8 | url: https://github.com/eclipse-iceoryx/iceoryx.git 9 | version: master 10 | foonathan_memory_vendor: 11 | type: git 12 | url: https://github.com/eProsima/foonathan_memory_vendor.git 13 | version: master 14 | fastcdr: 15 | type: git 16 | url: https://github.com/eProsima/Fast-CDR.git 17 | version: master 18 | fastrtps: 19 | type: git 20 | url: https://github.com/eProsima/Fast-DDS.git 21 | version: master 22 | fastddsgen: 23 | type: git 24 | url: https://github.com/eProsima/Fast-DDS-Gen.git 25 | version: master 26 | fastddsgen/thirdparty/idl-parser: 27 | type: git 28 | url: https://github.com/eProsima/IDL-Parser.git 29 | version: master 30 | -------------------------------------------------------------------------------- /smw_core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | find_package(fastrtps 2.5.0 CONFIG REQUIRED) 5 | find_package(Protobuf 3.5.0 REQUIRED) 6 | find_package(iceoryx_posh 1.90.0 CONFIG REQUIRED) 7 | 8 | set(LIBRARY_NAME smw_core) 9 | 10 | add_library(${LIBRARY_NAME} 11 | src/runtime.cpp 12 | src/service_skeleton.cpp 13 | src/transport/dds/fastdds_participant.cpp 14 | src/transport/iceoryx/iceoryx_runtime.cpp 15 | src/service_registry.cpp 16 | proto/service_discovery.pb.cc 17 | src/service_proxy.cpp) 18 | 19 | target_link_libraries(${LIBRARY_NAME} 20 | PUBLIC 21 | spdlog::spdlog 22 | smw_types 23 | smw_utils 24 | fastrtps 25 | ${PROTOBUF_LIBRARIES} 26 | iceoryx_posh::iceoryx_posh 27 | ) 28 | 29 | target_include_directories(${LIBRARY_NAME} 30 | PUBLIC 31 | include 32 | proto 33 | include/transport 34 | ) 35 | 36 | 37 | set_target_properties(${LIBRARY_NAME} PROPERTIES 38 | CXX_STANDARD_REQUIRED ON 39 | CXX_STANDARD ${SMW_CXX_STANDARD} 40 | POSITION_INDEPENDENT_CODE ON 41 | ) 42 | # 43 | ########## build test executables ########## 44 | # 45 | if (BUILD_TEST) 46 | add_subdirectory(test) 47 | endif () -------------------------------------------------------------------------------- /smw_core/include/runtime.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | 5 | #ifndef SMW_RUNTIME_H 6 | #define SMW_RUNTIME_H 7 | 8 | #include "runtime_option.h" 9 | #include "service_proxy.h" 10 | #include "service_skeleton.h" 11 | #include "transport/transport_writer.h" 12 | #include 13 | #include 14 | 15 | namespace smw::core 16 | { 17 | class Runtime 18 | { 19 | public: 20 | /// @brief return runtime instance 21 | /// @param option options for initialize runtime 22 | /// @return runtime instance 23 | static Runtime& initRuntime(const std::optional& option) noexcept; 24 | 25 | /// @brief get initialized instance 26 | /// @return runtime instance 27 | static Runtime& getInstance() noexcept; 28 | 29 | Runtime(Runtime&&) = delete; 30 | Runtime& operator=(Runtime&&) = delete; 31 | 32 | Runtime(const Runtime&) = delete; 33 | Runtime& operator=(const Runtime&) = delete; 34 | 35 | 36 | ~Runtime() noexcept = default; 37 | 38 | 39 | /// @brief return runtime options 40 | /// @return runtime options 41 | const RuntimeOption& getOption() const noexcept; 42 | 43 | static std::unique_ptr 44 | createServiceSkeleton(const ServiceDescription& service_description) noexcept; 45 | 46 | static std::unique_ptr createServiceProxy(const ServiceDescription& service_description) noexcept; 47 | 48 | private: 49 | /// @brief Construct of runtime 50 | /// @param[in] option option for initialize runtime 51 | explicit Runtime(const RuntimeOption& option) noexcept; 52 | RuntimeOption m_option; 53 | }; 54 | } // namespace smw::core 55 | #endif // SMW_RUNTIME_H 56 | -------------------------------------------------------------------------------- /smw_core/include/runtime_option.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | 5 | #ifndef SMW_RUNTIME_OPTION_H 6 | #define SMW_RUNTIME_OPTION_H 7 | 8 | #include 9 | 10 | namespace smw::core 11 | { 12 | struct RuntimeOption 13 | { 14 | std::string name{"no-name"}; 15 | std::uint32_t domain_id{0}; 16 | }; 17 | } // namespace smw::core 18 | #endif // SMW_RUNTIME_OPTION_H 19 | -------------------------------------------------------------------------------- /smw_core/include/serializer/serializer_idl.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/8. 3 | // 4 | 5 | #ifndef SMW_SERIALIZER_IDL_H 6 | #define SMW_SERIALIZER_IDL_H 7 | #include 8 | #include 9 | namespace smw::core 10 | { 11 | template 12 | class SerializerIdl 13 | { 14 | static_assert(std::is_base_of_v); 15 | 16 | public: 17 | std::size_t getMaxSize() noexcept 18 | { 19 | return m_delegate.m_typeSize; 20 | } 21 | 22 | std::string getTypeName() noexcept 23 | { 24 | return m_delegate.getName(); 25 | } 26 | 27 | std::size_t getSize(const void* data) noexcept 28 | { 29 | return m_delegate.getSerializedSizeProvider(const_cast(data))(); 30 | } 31 | 32 | bool serialize(const void* from_data, void* dest_buffer, std::size_t* dest_len) noexcept 33 | { 34 | /// IMPROVE : too much copy here 35 | eprosima::fastrtps::rtps::SerializedPayload_t payload{static_cast(getMaxSize())}; 36 | 37 | bool result = m_delegate.serialize(const_cast(from_data), &payload); 38 | std::memcpy(dest_buffer, payload.data, payload.length); 39 | *dest_len = payload.length; 40 | return result; 41 | } 42 | 43 | bool deserialize(const void* from_buffer, std::size_t from_len, void* dest_data) noexcept 44 | { 45 | /// IMPROVE : too much copy here 46 | eprosima::fastrtps::rtps::SerializedPayload_t payload{static_cast(from_len)}; 47 | payload.length = from_len; 48 | std::memcpy(payload.data, from_buffer, from_len); 49 | 50 | bool result = m_delegate.deserialize(&payload, dest_data); 51 | 52 | return result; 53 | } 54 | 55 | void* createData() noexcept 56 | { 57 | return m_delegate.createData(); 58 | } 59 | 60 | void deleteData(void* data) noexcept 61 | { 62 | m_delegate.deleteData(data); 63 | } 64 | 65 | private: 66 | inline static PubSubType m_delegate; 67 | }; 68 | } // namespace smw::core 69 | #endif // SMW_SERIALIZER_IDL_H 70 | -------------------------------------------------------------------------------- /smw_core/include/serializer/serializer_protobuf.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/4. 3 | // 4 | 5 | #ifndef SMW_SERIALIZER_PROTOBUF_H 6 | #define SMW_SERIALIZER_PROTOBUF_H 7 | #include "google/protobuf/message.h" 8 | #include "type_traits" 9 | 10 | namespace smw::core 11 | { 12 | 13 | /// @brief 14 | /// @tparam T 15 | template 16 | class SerializerProtobuf 17 | { 18 | /// ensure a protobuf type 19 | static_assert(std::is_base_of_v); 20 | 21 | public: 22 | std::size_t getMaxSize() noexcept 23 | { 24 | return PB_DEFAULT_MAX_SIZE; /// just a sample 25 | } 26 | 27 | std::string getTypeName() noexcept 28 | { 29 | return T().GetTypeName(); 30 | } 31 | 32 | std::size_t getSize(const void* data) noexcept 33 | { 34 | return static_cast((reinterpret_cast(data))->ByteSizeLong()); 35 | } 36 | 37 | bool serialize(const void* from_data, void* dest_buffer, std::size_t* dest_len) noexcept 38 | { 39 | *dest_len = getSize(from_data); 40 | 41 | bool result = reinterpret_cast(from_data)->SerializeToArray(dest_buffer, *dest_len); 42 | 43 | return result; 44 | } 45 | 46 | bool deserialize(const void* from_buffer, std::size_t from_len, void* dest_data) noexcept 47 | { 48 | bool result = reinterpret_cast(dest_data)->ParseFromArray(from_buffer, from_len); 49 | 50 | return result; 51 | } 52 | 53 | void* createData() noexcept 54 | { 55 | return reinterpret_cast(new T()); 56 | } 57 | 58 | void deleteData(void* data) noexcept 59 | { 60 | delete (reinterpret_cast(data)); 61 | } 62 | 63 | private: 64 | constexpr static std::size_t PB_DEFAULT_MAX_SIZE = 256; 65 | }; 66 | } // namespace smw::core 67 | #endif // SMW_SERIALIZER_PROTOBUF_H 68 | -------------------------------------------------------------------------------- /smw_core/include/service_description.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | 5 | #ifndef SMW_SERVICE_DESCRIPTION_H 6 | #define SMW_SERVICE_DESCRIPTION_H 7 | 8 | #include 9 | 10 | namespace smw::core 11 | { 12 | struct ServiceDescription 13 | { 14 | std::uint32_t service_id{0}; 15 | std::uint32_t instance_id{0}; 16 | 17 | /// @brief Uses the underlying service_id and instance_id compare method to provide an order. 18 | /// This is needed to use ServiceDescription in sorted containers like map or set. 19 | inline bool operator<(const ServiceDescription& rhs) const noexcept 20 | { 21 | bool result = false; 22 | if (service_id < rhs.service_id) 23 | { 24 | result = true; 25 | } 26 | else 27 | { 28 | result = ((service_id == rhs.service_id) && (instance_id < rhs.instance_id)); 29 | } 30 | return result; 31 | } 32 | }; 33 | } // namespace smw::core 34 | #endif // SMW_SERVICE_DESCRIPTION_H 35 | -------------------------------------------------------------------------------- /smw_core/include/service_proxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/5. 3 | // 4 | 5 | #ifndef SMW_SERVICE_PROXY_H 6 | #define SMW_SERVICE_PROXY_H 7 | #include "result.h" 8 | #include "service_description.h" 9 | #include "service_registry.h" 10 | #include "subscriber.h" 11 | #include 12 | 13 | namespace smw::core 14 | { 15 | enum class ServiceProxyError 16 | { 17 | NO_IMPLEMENT = -1 18 | }; 19 | 20 | class ServiceProxy 21 | { 22 | public: 23 | /// @brief ctor of service skeleton 24 | /// @param service_id service id 25 | /// @param instance_id instance id 26 | explicit ServiceProxy(const ServiceDescription& service_description) noexcept; 27 | 28 | /// @brief dtor of service skeleton 29 | ~ServiceProxy() noexcept; 30 | 31 | /// @brief disable copy because we could not deal with service state of another instance 32 | ServiceProxy(const ServiceProxy&) = delete; 33 | ServiceProxy& operator=(const ServiceProxy&) = delete; 34 | 35 | /// @brief disable move because we could not deal with service state of another instance 36 | ServiceProxy(ServiceProxy&&) = delete; 37 | ServiceProxy& operator=(ServiceProxy&&) = delete; 38 | 39 | /// @brief create a event publisher 40 | /// @tparam T data type of event 41 | /// @param event_id id of event 42 | /// @return created publisher 43 | template > 44 | Result>, ServiceProxyError> 45 | createSubscriber(std::uint16_t event_id) noexcept 46 | { 47 | return Ok(std::make_unique>(m_service_description, event_id)); 48 | } 49 | 50 | private: 51 | ServiceDescription m_service_description; 52 | }; 53 | } // namespace smw::core 54 | #endif // SMW_SERVICE_PROXY_H 55 | -------------------------------------------------------------------------------- /smw_core/include/service_skeleton.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | 5 | #ifndef SMW_SERVICE_SKELETON_H 6 | #define SMW_SERVICE_SKELETON_H 7 | 8 | #include "publisher.h" 9 | #include "result.h" 10 | #include "service_description.h" 11 | #include "service_registry.h" 12 | #include 13 | 14 | namespace smw::core 15 | { 16 | using namespace types; 17 | 18 | enum class ServiceSkeletonError 19 | { 20 | NO_IMPLEMENT = -1, 21 | NOT_OFFER_SERVICE = -2 22 | }; 23 | 24 | class ServiceSkeleton 25 | { 26 | public: 27 | /// @brief ctor of service skeleton 28 | /// @param service_id service id 29 | /// @param instance_id instance id 30 | explicit ServiceSkeleton(const ServiceDescription& service_description) noexcept; 31 | 32 | /// @brief dtor of service skeleton 33 | ~ServiceSkeleton() noexcept; 34 | 35 | /// @brief disable copy because we could not deal with service state of another instance 36 | ServiceSkeleton(const ServiceSkeleton&) = delete; 37 | ServiceSkeleton& operator=(const ServiceSkeleton&) = delete; 38 | 39 | /// @brief disable move because we could not deal with service state of another instance 40 | ServiceSkeleton(ServiceSkeleton&&) = delete; 41 | ServiceSkeleton& operator=(ServiceSkeleton&&) = delete; 42 | 43 | /// @brief offer this service 44 | void offerService() noexcept; 45 | 46 | /// @brief stop offer this service 47 | void stopOfferService() noexcept; 48 | 49 | /// @brief return if this service has been offered 50 | bool isOffered() const noexcept; 51 | 52 | /// @brief create a event publisher 53 | /// @tparam T data type of event 54 | /// @param event_id id of event 55 | /// @return created publisher 56 | template > 57 | Result>, ServiceSkeletonError> 58 | createPublisher(std::uint16_t event_id) noexcept 59 | { 60 | if (!isOffered()) 61 | { 62 | return Err(ServiceSkeletonError::NOT_OFFER_SERVICE); 63 | } 64 | 65 | return Ok(std::make_unique>(m_service_description, event_id)); 66 | } 67 | 68 | private: 69 | std::atomic_bool m_is_offered; 70 | ServiceDescription m_service_description; 71 | }; 72 | 73 | } // namespace smw::core 74 | #endif // SMW_SERVICE_SKELETON_H 75 | -------------------------------------------------------------------------------- /smw_core/include/service_status.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/4. 3 | // 4 | 5 | #ifndef SMW_SERVICE_STATUS_H 6 | #define SMW_SERVICE_STATUS_H 7 | #include "service_discovery.pb.h" 8 | #include 9 | namespace smw::core 10 | { 11 | 12 | struct ServiceEntityInfo 13 | { 14 | std::string hostId; 15 | std::string processId; 16 | 17 | inline bool operator<(const ServiceEntityInfo& rhs) const noexcept 18 | { 19 | bool result = false; 20 | if (hostId < rhs.hostId) 21 | { 22 | result = true; 23 | } 24 | else 25 | { 26 | result = ((hostId == rhs.hostId) && (processId < rhs.processId)); 27 | } 28 | 29 | return result; 30 | } 31 | }; 32 | 33 | 34 | struct ServiceStatus 35 | { 36 | std::set localProviders{}; 37 | std::set remoteProviders{}; 38 | std::set localConsumers{}; 39 | std::set remoteConsumers{}; 40 | 41 | /// @brief a helper to get if there's exist local consumer 42 | inline bool hasLocalConsumer() const noexcept 43 | { 44 | return localConsumers.size() > 0; 45 | } 46 | 47 | /// @brief a helper to get if there's exist remote consumer 48 | inline bool hasRemoteConsumer() const noexcept 49 | { 50 | return remoteConsumers.size() > 0; 51 | } 52 | 53 | /// @brief a helper to get if there's exist local provider 54 | inline bool hasLocalProvider() const noexcept 55 | { 56 | return localProviders.size() > 0; 57 | } 58 | 59 | /// @brief a helper to get if there's exist remote provider 60 | inline bool hasRemoteProvider() const noexcept 61 | { 62 | return remoteProviders.size() > 0; 63 | } 64 | }; 65 | 66 | } // namespace smw::core 67 | #endif // SMW_SERVICE_STATUS_H 68 | -------------------------------------------------------------------------------- /smw_core/include/transport/dds/dds_factory.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/3. 3 | // 4 | 5 | #ifndef SMW_DDS_FACTORY_H 6 | #define SMW_DDS_FACTORY_H 7 | #include "fastdds_reader.h" 8 | #include "fastdds_writer.h" 9 | #include 10 | 11 | namespace smw::core 12 | { 13 | class DDSFactory 14 | { 15 | public: 16 | template 17 | static std::unique_ptr> createWriter(const std::string& topic_name) noexcept 18 | { 19 | /// TODO just return Fast-DDS writer 20 | return std::make_unique>(topic_name); 21 | } 22 | 23 | template 24 | static std::unique_ptr> createReader(const std::string& topic_name) noexcept 25 | { 26 | /// TODO just return Fast-DDS writer 27 | return std::make_unique>(topic_name); 28 | } 29 | }; 30 | 31 | } // namespace smw::core 32 | #endif // SMW_DDS_FACTORY_H 33 | -------------------------------------------------------------------------------- /smw_core/include/transport/dds/fastdds_participant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | 5 | #ifndef SMW_FASTDDS_PARTICIPANT_H 6 | #define SMW_FASTDDS_PARTICIPANT_H 7 | 8 | #include "fastdds_data_type.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | namespace smw::core 16 | { 17 | 18 | class FastDDSParticipant 19 | { 20 | public: 21 | static FastDDSParticipant& getInstance() noexcept; 22 | eprosima::fastdds::dds::DomainParticipant* getParticipant() noexcept; 23 | 24 | FastDDSParticipant(const FastDDSParticipant&) = delete; 25 | FastDDSParticipant& operator=(const FastDDSParticipant&) = delete; 26 | 27 | FastDDSParticipant(FastDDSParticipant&&) = delete; 28 | FastDDSParticipant& operator=(FastDDSParticipant&&) = delete; 29 | 30 | ~FastDDSParticipant() noexcept; 31 | 32 | /// @brief get a Fast-DDS topic 33 | /// @tparam T data type of this topic 34 | /// @param topic_name 35 | template 36 | eprosima::fastdds::dds::Topic* getTopic(const std::string& topic_name) noexcept 37 | { 38 | std::unique_lock lock(m_topics_mutex); 39 | eprosima::fastdds::dds::Topic* result = nullptr; 40 | if (m_topics.find(topic_name) != m_topics.end()) 41 | { 42 | result = m_topics[topic_name].topic; 43 | } 44 | else 45 | { 46 | eprosima::fastdds::dds::TypeSupport type_support{new FastDDSDataType()}; 47 | type_support.register_type(m_participant); 48 | result = FastDDSParticipant::getInstance().getParticipant()->create_topic( 49 | topic_name, type_support.get_type_name(), eprosima::fastdds::dds::TOPIC_QOS_DEFAULT); 50 | TopicWithRefCount topic_with_ref_count{result, 0}; 51 | 52 | m_topics[topic_name] = topic_with_ref_count; 53 | } 54 | 55 | m_topics[topic_name].refCount++; 56 | return result; 57 | } 58 | 59 | /// @brief delete topic created by getTopic,but not real delete,it depends on reference count 60 | /// @param topic_name 61 | void deleteTopic(const std::string& topic_name) noexcept; 62 | 63 | private: 64 | FastDDSParticipant() noexcept; 65 | 66 | eprosima::fastdds::dds::DomainParticipant* m_participant; 67 | 68 | /// @brief wrapper for Fast-DDS topic with reference count 69 | struct TopicWithRefCount 70 | { 71 | eprosima::fastdds::dds::Topic* topic{nullptr}; 72 | std::int16_t refCount{0}; 73 | }; 74 | 75 | std::map m_topics; 76 | std::mutex m_topics_mutex; 77 | static constexpr std::uint32_t DEFAULT_UDP_BUFFER_SIZE = 8 * 1024 * 1024; 78 | }; 79 | } // namespace smw::core 80 | #endif // SMW_FASTDDS_PARTICIPANT_H 81 | -------------------------------------------------------------------------------- /smw_core/include/transport/dds/fastdds_writer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | 5 | #ifndef SMW_FASTDDS_WRITER_H 6 | #define SMW_FASTDDS_WRITER_H 7 | #include "fastdds_participant.h" 8 | #include "transport/transport_writer.h" 9 | #include 10 | #include 11 | #include 12 | namespace smw::core 13 | { 14 | template 15 | class FastDDSWriter : public TransportWriter 16 | { 17 | public: 18 | FastDDSWriter(const std::string& topic_name) noexcept 19 | : m_publisher(nullptr) 20 | , m_data_writer(nullptr) 21 | , m_topic_name(topic_name) 22 | , m_topic(nullptr) 23 | { 24 | init(); 25 | } 26 | 27 | ~FastDDSWriter() noexcept 28 | { 29 | eprosima::fastrtps::types::ReturnCode_t return_code = eprosima::fastrtps::types::ReturnCode_t::RETCODE_ERROR; 30 | m_data_writer->close(); 31 | return_code = m_publisher->delete_contained_entities(); 32 | assert(return_code == eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK); 33 | FastDDSParticipant::getInstance().deleteTopic(m_topic_name); 34 | } 35 | 36 | bool write(const T& data) noexcept override 37 | { 38 | return m_data_writer->write(const_cast(&data)); 39 | } 40 | 41 | bool write(SamplePtr&& data) noexcept override 42 | { 43 | return write(*data); 44 | } 45 | 46 | SamplePtr loan() noexcept override 47 | { 48 | void* user_payload; 49 | m_data_writer->loan_sample(user_payload); 50 | return SamplePtr(new (user_payload) T{}); 51 | } 52 | 53 | void enable() noexcept override 54 | { 55 | m_data_writer->enable(); 56 | } 57 | 58 | void disable() noexcept override 59 | { 60 | m_data_writer->close(); 61 | } 62 | 63 | private: 64 | eprosima::fastdds::dds::Publisher* m_publisher; 65 | eprosima::fastdds::dds::DataWriter* m_data_writer; 66 | eprosima::fastdds::dds::Topic* m_topic; 67 | std::string m_topic_name; 68 | 69 | static constexpr int32_t DEFAULT_HISTORY_DEPTH = 100; 70 | 71 | void init() noexcept 72 | { 73 | /// create a publisher and data writer 74 | m_publisher = FastDDSParticipant::getInstance().getParticipant()->create_publisher( 75 | eprosima::fastdds::dds::PUBLISHER_QOS_DEFAULT); 76 | 77 | assert(m_publisher != nullptr); 78 | 79 | m_topic = FastDDSParticipant::getInstance().template getTopic(m_topic_name); 80 | assert(m_topic != nullptr); 81 | 82 | eprosima::fastdds::dds::DataWriterQos writer_qos = eprosima::fastdds::dds::DATAWRITER_QOS_DEFAULT; 83 | writer_qos.endpoint().history_memory_policy = 84 | eprosima::fastrtps::rtps::MemoryManagementPolicy_t::PREALLOCATED_WITH_REALLOC_MEMORY_MODE; 85 | 86 | writer_qos.history().kind = eprosima::fastrtps::KEEP_LAST_HISTORY_QOS; 87 | writer_qos.history().depth = DEFAULT_HISTORY_DEPTH; 88 | 89 | m_data_writer = m_publisher->create_datawriter(m_topic, writer_qos); 90 | assert(m_data_writer != nullptr); 91 | } 92 | }; 93 | 94 | 95 | } // namespace smw::core 96 | #endif // SMW_FASTDDS_WRITER_H 97 | -------------------------------------------------------------------------------- /smw_core/include/transport/iceoryx/iceoryx_runtime.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/5. 3 | // 4 | 5 | #ifndef SMW_ICEORYX_RUNTIME_H 6 | #define SMW_ICEORYX_RUNTIME_H 7 | #include "iceoryx_posh/runtime/posh_runtime.hpp" 8 | 9 | namespace smw::core 10 | { 11 | class IceoryxRuntime 12 | { 13 | public: 14 | static IceoryxRuntime& getInstance() noexcept; 15 | static void initRuntime() noexcept; 16 | 17 | IceoryxRuntime(const IceoryxRuntime&) = delete; 18 | IceoryxRuntime& operator=(const IceoryxRuntime&) = delete; 19 | 20 | IceoryxRuntime(IceoryxRuntime&&) = delete; 21 | IceoryxRuntime& operator=(IceoryxRuntime&&) = delete; 22 | 23 | ~IceoryxRuntime() noexcept; 24 | 25 | private: 26 | IceoryxRuntime() noexcept; 27 | }; 28 | } // namespace smw::core 29 | #endif // SMW_ICEORYX_RUNTIME_H 30 | -------------------------------------------------------------------------------- /smw_core/include/transport/transport_reader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | 5 | #ifndef SMW_TRANSPORT_READER_H 6 | #define SMW_TRANSPORT_READER_H 7 | #include "sample_ptr.h" 8 | #include 9 | 10 | namespace smw::core 11 | { 12 | template 13 | class TransportReader 14 | { 15 | public: 16 | using data_callback_t = std::function)>; 17 | virtual void setDataCallback(const data_callback_t& callback) noexcept = 0; 18 | virtual void enable() noexcept = 0; 19 | virtual void disable() noexcept = 0; 20 | }; 21 | } // namespace smw::core 22 | #endif // SMW_TRANSPORT_READER_H 23 | -------------------------------------------------------------------------------- /smw_core/include/transport/transport_writer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | 5 | #ifndef SMW_TRANSPORT_WRITER_H 6 | #define SMW_TRANSPORT_WRITER_H 7 | 8 | #include "sample_ptr.h" 9 | 10 | namespace smw::core 11 | { 12 | template 13 | class TransportWriter 14 | { 15 | public: 16 | virtual SamplePtr loan() noexcept = 0; 17 | virtual bool write(const T&) noexcept = 0; 18 | virtual bool write(SamplePtr&&) noexcept = 0; 19 | virtual void enable() noexcept = 0; 20 | virtual void disable() noexcept = 0; 21 | }; 22 | } // namespace smw::core 23 | #endif // SMW_TRANSPORT_WRITER_H 24 | -------------------------------------------------------------------------------- /smw_core/proto/service_discovery.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package smw.core.proto; 4 | 5 | message ServiceInfo { 6 | uint32 service_id = 1; 7 | uint32 instance_id = 2; 8 | string host_id = 4; 9 | string process_id = 5; 10 | } 11 | 12 | message ServiceDiscovery{ 13 | enum ServiceDiscoveryOperation{ 14 | OFFER = 0; 15 | STOP_OFFER = 1; 16 | FIND = 2; 17 | STOP_FIND = 3; 18 | } 19 | ServiceDiscoveryOperation operation = 1; 20 | ServiceInfo service_info = 2; 21 | } -------------------------------------------------------------------------------- /smw_core/src/runtime.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | #include "runtime.h" 5 | 6 | 7 | namespace smw::core 8 | { 9 | Runtime& Runtime::initRuntime(const std::optional& option) noexcept 10 | { 11 | static Runtime instance{option.value()}; 12 | return instance; 13 | } 14 | 15 | Runtime::Runtime(const RuntimeOption& option) noexcept 16 | : m_option(option) 17 | { 18 | } 19 | 20 | 21 | const RuntimeOption& Runtime::getOption() const noexcept 22 | { 23 | return m_option; 24 | } 25 | 26 | Runtime& Runtime::getInstance() noexcept 27 | { 28 | return initRuntime(std::nullopt); 29 | } 30 | 31 | std::unique_ptr Runtime::createServiceSkeleton(const ServiceDescription& service_description) noexcept 32 | { 33 | return std::make_unique(service_description); 34 | } 35 | std::unique_ptr Runtime::createServiceProxy(const ServiceDescription& service_description) noexcept 36 | { 37 | return std::make_unique(service_description); 38 | } 39 | 40 | 41 | } // namespace smw::core -------------------------------------------------------------------------------- /smw_core/src/service_proxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/5. 3 | // 4 | #include "service_proxy.h" 5 | 6 | namespace smw::core 7 | { 8 | 9 | ServiceProxy::ServiceProxy(const ServiceDescription& service_description) noexcept 10 | : m_service_description(service_description) 11 | { 12 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::FIND, m_service_description); 13 | } 14 | 15 | ServiceProxy::~ServiceProxy() noexcept 16 | { 17 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::STOP_FIND, m_service_description); 18 | } 19 | } // namespace smw::core 20 | -------------------------------------------------------------------------------- /smw_core/src/service_skeleton.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "service_skeleton.h" 5 | #include "runtime.h" 6 | 7 | namespace smw::core 8 | { 9 | 10 | ServiceSkeleton::ServiceSkeleton(const ServiceDescription& service_description) noexcept 11 | : m_is_offered(false) 12 | , m_service_description(service_description) 13 | { 14 | offerService(); 15 | } 16 | 17 | void ServiceSkeleton::offerService() noexcept 18 | { 19 | /// notify service registry 20 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::OFFER, m_service_description); 21 | m_is_offered.store(true); 22 | } 23 | 24 | bool ServiceSkeleton::isOffered() const noexcept 25 | { 26 | return m_is_offered.load(); 27 | } 28 | 29 | 30 | void ServiceSkeleton::stopOfferService() noexcept 31 | { 32 | /// notify service registry 33 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::STOP_OFFER, 34 | m_service_description); 35 | m_is_offered.store(false); 36 | } 37 | 38 | ServiceSkeleton::~ServiceSkeleton() noexcept 39 | { 40 | if (isOffered()) 41 | { 42 | stopOfferService(); 43 | } 44 | } 45 | } // namespace smw::core -------------------------------------------------------------------------------- /smw_core/src/transport/dds/fastdds_participant.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "dds/fastdds_participant.h" 5 | #include "runtime.h" 6 | 7 | namespace smw::core 8 | { 9 | FastDDSParticipant& FastDDSParticipant::getInstance() noexcept 10 | { 11 | static FastDDSParticipant instance{}; 12 | return instance; 13 | } 14 | 15 | FastDDSParticipant::FastDDSParticipant() noexcept 16 | : m_participant(nullptr) 17 | { 18 | auto* factory = eprosima::fastdds::dds::DomainParticipantFactory::get_instance(); 19 | eprosima::fastdds::dds::DomainParticipantQos pqos; 20 | pqos.name(Runtime::getInstance().getOption().name); 21 | /// use udp as default transport 22 | auto udp_transport = std::make_shared(); 23 | udp_transport->sendBufferSize = DEFAULT_UDP_BUFFER_SIZE; 24 | udp_transport->receiveBufferSize = DEFAULT_UDP_BUFFER_SIZE; 25 | udp_transport->non_blocking_send = true; 26 | 27 | // Link the Transport Layer to the Participant. 28 | pqos.transport().user_transports.push_back(udp_transport); 29 | 30 | // Avoid using the default transport 31 | pqos.transport().use_builtin_transports = false; 32 | 33 | m_participant = factory->create_participant(Runtime::getInstance().getOption().domain_id, 34 | eprosima::fastdds::dds::PARTICIPANT_QOS_DEFAULT); 35 | } 36 | 37 | FastDDSParticipant::~FastDDSParticipant() noexcept 38 | { 39 | auto* factory = eprosima::fastdds::dds::DomainParticipantFactory::get_instance(); 40 | if (m_participant != nullptr) 41 | { 42 | eprosima::fastrtps::types::ReturnCode_t return_code = eprosima::fastrtps::types::ReturnCode_t::RETCODE_ERROR; 43 | return_code = m_participant->delete_contained_entities(); 44 | assert(return_code == eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK); 45 | 46 | return_code = m_participant->set_listener(nullptr); 47 | assert(return_code == eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK); 48 | 49 | m_participant->close(); 50 | 51 | factory->delete_participant(m_participant); 52 | assert(return_code == eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK); 53 | } 54 | } 55 | 56 | eprosima::fastdds::dds::DomainParticipant* FastDDSParticipant::getParticipant() noexcept 57 | { 58 | return m_participant; 59 | } 60 | 61 | void FastDDSParticipant::deleteTopic(const std::string& topic_name) noexcept 62 | { 63 | std::unique_lock lock(m_topics_mutex); 64 | if (m_topics.find(topic_name) != m_topics.end()) 65 | { 66 | m_topics[topic_name].refCount--; 67 | if (m_topics[topic_name].refCount <= 0) 68 | { 69 | eprosima::fastrtps::types::ReturnCode_t return_code; 70 | 71 | return_code = m_participant->delete_topic(m_topics[topic_name].topic); 72 | assert(return_code == eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK); 73 | 74 | m_topics.erase(topic_name); 75 | } 76 | } 77 | } 78 | 79 | 80 | } // namespace smw::core 81 | -------------------------------------------------------------------------------- /smw_core/src/transport/iceoryx/iceoryx_runtime.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/5. 3 | // 4 | #include "iceoryx/iceoryx_runtime.h" 5 | #include "runtime.h" 6 | 7 | namespace smw::core 8 | { 9 | 10 | IceoryxRuntime& IceoryxRuntime::getInstance() noexcept 11 | { 12 | static IceoryxRuntime instance{}; 13 | return instance; 14 | } 15 | 16 | IceoryxRuntime::IceoryxRuntime() noexcept 17 | { 18 | /// init iceoryx runtime 19 | iox::RuntimeName_t posh_runtime_name{iox::cxx::TruncateToCapacity, Runtime::getInstance().getOption().name}; 20 | iox::runtime::PoshRuntime::initRuntime(posh_runtime_name); 21 | } 22 | 23 | IceoryxRuntime::~IceoryxRuntime() noexcept 24 | { 25 | iox::runtime::PoshRuntime::getInstance().shutdown(); 26 | } 27 | 28 | void IceoryxRuntime::initRuntime() noexcept 29 | { 30 | (void)getInstance(); 31 | } 32 | 33 | } // namespace smw::core -------------------------------------------------------------------------------- /smw_core/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | if (BUILD_TEST AND NOT GTest_FOUND) 4 | find_package(GTest CONFIG REQUIRED) 5 | endif (BUILD_TEST AND NOT GTest_FOUND) 6 | 7 | 8 | set(TEST_NAME test_smw_core) 9 | 10 | 11 | add_executable(${TEST_NAME} 12 | main.cpp 13 | test_runtime.cpp 14 | test_publisher.cpp 15 | test_subscriber.cpp 16 | test_fastdds_data_type_protobuf.cpp 17 | test_data.pb.cc 18 | test_fastdds_writer_reader.cpp 19 | test_iceoryx_writer_reader.cpp 20 | test_service_registry.cpp test_publisher_and_subscriber.cpp) 21 | 22 | target_link_libraries(${TEST_NAME} 23 | PRIVATE 24 | smw_core 25 | GTest::gtest 26 | GTest::gmock 27 | ) 28 | 29 | set_target_properties(${TEST_NAME} PROPERTIES 30 | CXX_STANDARD_REQUIRED ON 31 | CXX_STANDARD ${SMW_CXX_STANDARD} 32 | POSITION_INDEPENDENT_CODE ON 33 | ) 34 | 35 | -------------------------------------------------------------------------------- /smw_core/test/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/11/30. 3 | // 4 | #include "spdlog/spdlog.h" 5 | #include "test.h" 6 | #include 7 | int main(int argc, char* argv[]) 8 | { 9 | ::testing::InitGoogleTest(&argc, argv); 10 | return RUN_ALL_TESTS(); 11 | } -------------------------------------------------------------------------------- /smw_core/test/run_test.sh: -------------------------------------------------------------------------------- 1 | 2 | for n in $(seq $1); do 3 | $2 4 | done -------------------------------------------------------------------------------- /smw_core/test/test.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | 5 | #ifndef SMW_TEST_H 6 | #define SMW_TEST_H 7 | 8 | #include "test_data.pb.h" 9 | #include 10 | #include 11 | #include 12 | 13 | #endif // SMW_TEST_H 14 | -------------------------------------------------------------------------------- /smw_core/test/test_data.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message SearchRequest { 4 | string query = 1; 5 | int32 page_number = 2; 6 | int32 result_per_page = 3; 7 | } -------------------------------------------------------------------------------- /smw_core/test/test_fastdds_data_type_protobuf.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "dds/fastdds_data_type.h" 5 | #include "serializer/serializer_protobuf.h" 6 | #include "test.h" 7 | #include "test_data.pb.h" 8 | #include 9 | 10 | using namespace smw::core; 11 | 12 | TEST(fastdds_data_type_protobuf, construct) 13 | { 14 | FastDDSDataType> test; 15 | EXPECT_EQ(test.getName(), SearchRequest().GetTypeName()); 16 | 17 | SearchRequest proto_data; 18 | proto_data.set_page_number(1); 19 | proto_data.set_query("HHH"); 20 | auto proto_size = proto_data.ByteSizeLong(); 21 | 22 | std::vector proto_buffer(test.getSerializedSizeProvider(&proto_data)()); 23 | 24 | EXPECT_TRUE(proto_data.SerializePartialToArray(proto_buffer.data(), proto_buffer.size())); 25 | 26 | eprosima::fastrtps::rtps::SerializedPayload_t payload(proto_buffer.size()); 27 | EXPECT_TRUE(test.serialize(&proto_data, &payload)); 28 | /// actual dds payload length has added 4 bytes filed to indicate length of actual data 29 | // EXPECT_EQ(payload.length, proto_size + 4); 30 | 31 | auto* dds_data = test.createData(); 32 | EXPECT_TRUE(test.deserialize(&payload, dds_data)); 33 | EXPECT_TRUE( 34 | google::protobuf::util::MessageDifferencer::Equals(proto_data, *(reinterpret_cast(dds_data)))); 35 | 36 | test.deleteData(dds_data); 37 | } -------------------------------------------------------------------------------- /smw_core/test/test_fastdds_writer_reader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "dds/fastdds_reader.h" 5 | #include "dds/fastdds_writer.h" 6 | #include "serializer/serializer_protobuf.h" 7 | #include "test.h" 8 | #include "test_data.pb.h" 9 | #include 10 | 11 | using namespace smw::core; 12 | using namespace std::chrono_literals; 13 | static constexpr std::chrono::duration WAIT_TIME_MS = 10ms; 14 | 15 | TEST(fastdds_writer, write) 16 | { 17 | FastDDSWriter> writer("testTopic"); 18 | 19 | SearchRequest proto_data; 20 | proto_data.set_page_number(10); 21 | proto_data.set_query("2"); 22 | EXPECT_TRUE(writer.write(proto_data)); 23 | } 24 | 25 | TEST(fastdds_writer_reader, write_and_read) 26 | { 27 | FastDDSWriter> writer("testTopic"); 28 | FastDDSReader> reader("testTopic"); 29 | 30 | SearchRequest input_data; 31 | reader.setDataCallback([&input_data](auto&& value) { input_data = *value; }); 32 | SearchRequest output_data; 33 | output_data.set_page_number(10); 34 | output_data.set_query("2"); 35 | EXPECT_TRUE(writer.write(output_data)); 36 | std::this_thread::sleep_for(WAIT_TIME_MS); 37 | 38 | EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(input_data, output_data)); 39 | } -------------------------------------------------------------------------------- /smw_core/test/test_iceoryx_writer_reader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/5. 3 | // 4 | #include "iceoryx/iceoryx_reader.h" 5 | #include "iceoryx/iceoryx_writer.h" 6 | #include "serializer/serializer_protobuf.h" 7 | #include "test.h" 8 | #include "test_data.pb.h" 9 | #include 10 | 11 | using namespace smw::core; 12 | 13 | 14 | constexpr static uint32_t TEST_SERVICE = 10; 15 | constexpr static uint32_t TEST_INSTANCE = 1; 16 | constexpr static uint32_t TEST_EVENT = 2; 17 | using namespace std::chrono_literals; 18 | static constexpr std::chrono::duration WAIT_TIME_MS = 10ms; 19 | 20 | TEST(iceoryx_test, write_and_read) 21 | { 22 | ServiceDescription serviceDescription; 23 | serviceDescription.service_id = TEST_SERVICE; 24 | serviceDescription.instance_id = TEST_INSTANCE; 25 | 26 | IceoryxWriter> writer(serviceDescription, TEST_EVENT); 27 | IceoryxReader> reader(serviceDescription, TEST_EVENT); 28 | 29 | SearchRequest input_data; 30 | reader.setDataCallback([&input_data](auto&& value) { input_data = *value; }); 31 | auto output_data = writer.loan(); 32 | output_data->set_page_number(10); 33 | output_data->set_query("2"); 34 | EXPECT_TRUE(writer.write(std::move(output_data))); 35 | std::this_thread::sleep_for(WAIT_TIME_MS); 36 | 37 | EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(input_data, *output_data)); 38 | } -------------------------------------------------------------------------------- /smw_core/test/test_publisher.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "publisher.h" 5 | #include "service_description.h" 6 | #include "test.h" 7 | 8 | using namespace smw::core; 9 | constexpr static uint32_t TEST_SERVICE = 10; 10 | constexpr static uint32_t TEST_INSTANCE = 1; 11 | constexpr static uint32_t TEST_EVENT = 2; 12 | TEST(publisher_test, construct) 13 | { 14 | ServiceDescription serviceDescription; 15 | serviceDescription.service_id = TEST_SERVICE; 16 | serviceDescription.instance_id = TEST_INSTANCE; 17 | smw::core::Publisher publisher_service{serviceDescription, TEST_EVENT}; 18 | EXPECT_EQ(publisher_service.getTopicName(), fmt::format("/{}/{}/{}", TEST_SERVICE, TEST_INSTANCE, TEST_EVENT)); 19 | } 20 | 21 | TEST(publisher_test, loan) 22 | { 23 | ServiceDescription serviceDescription; 24 | serviceDescription.service_id = TEST_SERVICE; 25 | serviceDescription.instance_id = TEST_INSTANCE; 26 | smw::core::Publisher publisher_service{serviceDescription, TEST_EVENT}; 27 | 28 | EXPECT_FALSE(publisher_service.loanSample().hasError()); 29 | SearchRequest request; 30 | EXPECT_FALSE(publisher_service.publish(request).hasError()); 31 | } -------------------------------------------------------------------------------- /smw_core/test/test_publisher_and_subscriber.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/5. 3 | // 4 | #include "publisher.h" 5 | #include "service_skeleton.h" 6 | #include "subscriber.h" 7 | #include "test.h" 8 | 9 | using namespace smw::core; 10 | 11 | constexpr static uint32_t TEST_SERVICE = 10; 12 | constexpr static uint32_t TEST_INSTANCE = 1; 13 | constexpr static uint32_t TEST_EVENT = 2; 14 | using namespace std::chrono_literals; 15 | static constexpr std::chrono::duration WAIT_TIME_MS = 10ms; 16 | 17 | TEST(pub_sub, by_ref) 18 | { 19 | ServiceDescription serviceDescription; 20 | serviceDescription.service_id = TEST_SERVICE; 21 | serviceDescription.instance_id = TEST_INSTANCE; 22 | 23 | /// request and find service by myself 24 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::OFFER, serviceDescription); 25 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::FIND, serviceDescription); 26 | 27 | Publisher publisher{serviceDescription, TEST_EVENT}; 28 | Subscriber subscriber{serviceDescription, TEST_EVENT}; 29 | 30 | SearchRequest input_data; 31 | subscriber.registerReceiveHandler( 32 | [&input_data](SamplePtr sample_ptr) { input_data = *sample_ptr; }); 33 | 34 | SearchRequest output_data; 35 | output_data.set_page_number(10); 36 | output_data.set_query("Hello"); 37 | EXPECT_FALSE(publisher.publish(output_data).hasError()); 38 | 39 | std::this_thread::sleep_for(WAIT_TIME_MS); 40 | 41 | EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(input_data, output_data)); 42 | } 43 | 44 | 45 | TEST(pub_sub, by_loan) 46 | { 47 | ServiceDescription serviceDescription; 48 | serviceDescription.service_id = TEST_SERVICE; 49 | serviceDescription.instance_id = TEST_INSTANCE; 50 | 51 | /// request and find service by myself 52 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::OFFER, serviceDescription); 53 | ServiceRegistry::getInstance().requestDiscoveryOperation(proto::ServiceDiscovery::FIND, serviceDescription); 54 | 55 | Publisher publisher{serviceDescription, TEST_EVENT}; 56 | Subscriber subscriber{serviceDescription, TEST_EVENT}; 57 | 58 | SearchRequest input_data; 59 | subscriber.registerReceiveHandler( 60 | [&input_data](SamplePtr sample_ptr) { input_data = *sample_ptr; }); 61 | 62 | 63 | SearchRequest output_data; 64 | output_data.set_page_number(10); 65 | output_data.set_query("2"); 66 | 67 | auto output_sample_result = publisher.loanSample(); 68 | auto output_sample = std::move(output_sample_result.getValue()); 69 | *output_sample = output_data; 70 | EXPECT_FALSE(publisher.publish(std::move(output_sample)).hasError()); 71 | 72 | std::this_thread::sleep_for(WAIT_TIME_MS); 73 | 74 | EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(input_data, output_data)); 75 | } -------------------------------------------------------------------------------- /smw_core/test/test_runtime.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | #include "runtime.h" 5 | #include "test.h" 6 | 7 | using namespace smw::core; 8 | 9 | TEST(runtime_test, construct) 10 | { 11 | RuntimeOption option{"test"}; 12 | auto& instance = Runtime::initRuntime(option); 13 | EXPECT_EQ(instance.getOption().name, "test"); 14 | EXPECT_EQ(Runtime::getInstance().getOption().name,"test"); 15 | EXPECT_EQ(&(Runtime::getInstance()), &instance); 16 | } 17 | -------------------------------------------------------------------------------- /smw_core/test/test_subscriber.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "service_description.h" 5 | #include "subscriber.h" 6 | #include "test.h" 7 | 8 | using namespace smw::core; 9 | constexpr static uint32_t TEST_SERVICE = 10; 10 | constexpr static uint32_t TEST_INSTANCE = 1; 11 | constexpr static uint32_t TEST_EVENT = 2; 12 | 13 | 14 | TEST(subscriber_test, constrcut) 15 | { 16 | ServiceDescription serviceDescription; 17 | serviceDescription.service_id = TEST_SERVICE; 18 | serviceDescription.instance_id = TEST_INSTANCE; 19 | smw::core::Subscriber subscriber{serviceDescription, TEST_EVENT}; 20 | EXPECT_EQ(subscriber.getTopicName(), fmt::format("/{}/{}/{}", TEST_SERVICE, TEST_INSTANCE, TEST_EVENT)); 21 | } 22 | -------------------------------------------------------------------------------- /smw_types/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(LIBRARY_NAME smw_types) 3 | 4 | add_library(${LIBRARY_NAME} INTERFACE) 5 | target_include_directories(${LIBRARY_NAME} 6 | INTERFACE 7 | include) 8 | 9 | ########## build test executables ########## 10 | # 11 | if (BUILD_TEST) 12 | add_subdirectory(test) 13 | endif () -------------------------------------------------------------------------------- /smw_types/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | if (BUILD_TEST AND NOT GTest_FOUND) 4 | find_package(GTest CONFIG REQUIRED) 5 | endif (BUILD_TEST AND NOT GTest_FOUND) 6 | 7 | 8 | set(TEST_NAME test_smw_types) 9 | 10 | 11 | add_executable(${TEST_NAME} 12 | main.cpp 13 | test_result.cpp) 14 | 15 | target_link_libraries(${TEST_NAME} 16 | PRIVATE 17 | GTest::gtest 18 | GTest::gmock 19 | smw_types 20 | ) 21 | 22 | set_target_properties(${TEST_NAME} PROPERTIES 23 | CXX_STANDARD_REQUIRED ON 24 | CXX_STANDARD ${SMW_CXX_STANDARD} 25 | POSITION_INDEPENDENT_CODE ON 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /smw_types/test/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/11/30. 3 | // 4 | #include "test.h" 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | ::testing::InitGoogleTest(&argc, argv); 9 | return RUN_ALL_TESTS(); 10 | } -------------------------------------------------------------------------------- /smw_types/test/test.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | 5 | #ifndef SMW_TEST_H 6 | #define SMW_TEST_H 7 | 8 | #include 9 | #include 10 | 11 | #endif // SMW_TEST_H 12 | -------------------------------------------------------------------------------- /smw_types/test/test_result.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/2. 3 | // 4 | #include "result.h" 5 | #include "test.h" 6 | 7 | enum TestError 8 | { 9 | TEST_ERROR, 10 | TEST_ERROR2 11 | }; 12 | 13 | TEST(Result, Ok) 14 | { 15 | smw::types::Result result(smw::types::Ok(1)); 16 | EXPECT_DEATH(result.getError(), ""); 17 | 18 | EXPECT_EQ(result.getValue(), 1); 19 | int val = -1; 20 | result.andThen([&](auto& value) { val = value; }); 21 | 22 | EXPECT_EQ(val, 1); 23 | } 24 | 25 | TEST(Result, Err) 26 | { 27 | smw::types::Result result{smw::types::Err(TEST_ERROR)}; 28 | EXPECT_DEATH(result.getValue(), ""); 29 | 30 | EXPECT_EQ(result.getError(), TEST_ERROR); 31 | TestError err = TEST_ERROR2; 32 | result.orElse([&](auto& error) { err = error; }); 33 | 34 | EXPECT_EQ(err, TEST_ERROR); 35 | } 36 | -------------------------------------------------------------------------------- /smw_utils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(LIBRARY_NAME smw_utils) 3 | 4 | add_library(${LIBRARY_NAME} 5 | src/host_id.cpp 6 | ) 7 | 8 | 9 | target_include_directories(${LIBRARY_NAME} 10 | PUBLIC 11 | include 12 | ) 13 | 14 | 15 | set_target_properties(${LIBRARY_NAME} PROPERTIES 16 | CXX_STANDARD_REQUIRED ON 17 | CXX_STANDARD ${SMW_CXX_STANDARD} 18 | POSITION_INDEPENDENT_CODE ON 19 | ) 20 | # 21 | ########## build test executables ########## 22 | # 23 | if (BUILD_TEST) 24 | add_subdirectory(test) 25 | endif () -------------------------------------------------------------------------------- /smw_utils/include/host_id.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/3. 3 | // 4 | 5 | #ifndef SMW_UTILS_H 6 | #define SMW_UTILS_H 7 | 8 | #include 9 | 10 | namespace smw::utils 11 | { 12 | extern const char SMW_HOST_ID_FILE[]; 13 | 14 | const std::string& getHostId() noexcept; 15 | const std::string& getProcessId() noexcept; 16 | } // namespace smw::utils 17 | #endif // SMW_UTILS_H 18 | -------------------------------------------------------------------------------- /smw_utils/src/host_id.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/3. 3 | // 4 | #include "host_id.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace smw::utils 19 | { 20 | 21 | static constexpr std::size_t DEFAULT_BUFF_SIZE = 512; 22 | 23 | std::string getMangledIp() noexcept 24 | { 25 | std::string result; 26 | std::set sorted_ips; 27 | int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); 28 | assert(sock_fd > 0); 29 | char buf[DEFAULT_BUFF_SIZE]; 30 | struct ifconf if_config 31 | { 32 | }; 33 | if_config.ifc_len = DEFAULT_BUFF_SIZE; 34 | if_config.ifc_ifcu.ifcu_buf = buf; 35 | 36 | int return_code = ::ioctl(sock_fd, SIOCGIFCONF, &if_config); 37 | assert(return_code == 0); 38 | 39 | 40 | /// get all devices ip 41 | struct ifreq* if_req = (struct ifreq*)if_config.ifc_buf; 42 | 43 | for (auto i = (if_config.ifc_len / sizeof(struct ifreq)); i > 0; i--) 44 | { 45 | if (if_req->ifr_flags == AF_INET) 46 | { // for ipv4 47 | 48 | sorted_ips.emplace(inet_ntoa(((struct sockaddr_in*)&(if_req->ifr_addr))->sin_addr)); 49 | if_req++; 50 | } 51 | } 52 | 53 | for (auto& ip : sorted_ips) 54 | { 55 | result += ip + "/"; 56 | } 57 | return result; 58 | } 59 | 60 | 61 | const std::string& getHostId() noexcept 62 | { 63 | static std::string result = getMangledIp(); 64 | return result; 65 | } 66 | 67 | const std::string& getProcessId() noexcept 68 | { 69 | static std::string result = std::to_string(::getpid()); 70 | return result; 71 | } 72 | } // namespace smw::utils -------------------------------------------------------------------------------- /smw_utils/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | if (BUILD_TEST AND NOT GTest_FOUND) 4 | find_package(GTest CONFIG REQUIRED) 5 | endif (BUILD_TEST AND NOT GTest_FOUND) 6 | 7 | 8 | set(TEST_NAME test_smw_utils) 9 | 10 | 11 | add_executable(${TEST_NAME} 12 | main.cpp 13 | test_host_id.cpp) 14 | 15 | target_link_libraries(${TEST_NAME} 16 | PRIVATE 17 | smw_utils 18 | GTest::gtest 19 | GTest::gmock 20 | ) 21 | 22 | set_target_properties(${TEST_NAME} PROPERTIES 23 | CXX_STANDARD_REQUIRED ON 24 | CXX_STANDARD ${SMW_CXX_STANDARD} 25 | POSITION_INDEPENDENT_CODE ON 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /smw_utils/test/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/3. 3 | // 4 | #include "test.h" 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | ::testing::InitGoogleTest(&argc, argv); 9 | return RUN_ALL_TESTS(); 10 | } -------------------------------------------------------------------------------- /smw_utils/test/test.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/1. 3 | // 4 | 5 | #ifndef SMW_TEST_H 6 | #define SMW_TEST_H 7 | 8 | #include 9 | #include 10 | 11 | #endif // SMW_TEST_H 12 | -------------------------------------------------------------------------------- /smw_utils/test/test_host_id.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by youxinxin on 2021/12/3. 3 | // 4 | #include "host_id.h" 5 | #include "test.h" 6 | #include 7 | 8 | using namespace smw::utils; 9 | 10 | TEST(utils, host_id) 11 | { 12 | auto id1 = getHostId(); 13 | auto id2 = getHostId(); 14 | EXPECT_EQ(id1, id2); 15 | } 16 | -------------------------------------------------------------------------------- /third_party/spdlog/.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: 'cppcoreguidelines-*, 2 | performance-*, 3 | modernize-*, 4 | google-*, 5 | misc-* 6 | cert-*, 7 | readability-*, 8 | clang-analyzer-*, 9 | -performance-unnecessary-value-param, 10 | -modernize-use-trailing-return-type, 11 | -google-runtime-references, 12 | -misc-non-private-member-variables-in-classes, 13 | -readability-braces-around-statements, 14 | -google-readability-braces-around-statements, 15 | -cppcoreguidelines-avoid-magic-numbers, 16 | -readability-magic-numbers, 17 | -readability-magic-numbers, 18 | -cppcoreguidelines-pro-type-vararg, 19 | -cppcoreguidelines-pro-bounds-pointer-arithmetic, 20 | -cppcoreguidelines-avoid-c-arrays, 21 | -modernize-avoid-c-arrays, 22 | -cppcoreguidelines-pro-bounds-array-to-pointer-decay, 23 | -readability-named-parameter, 24 | -cert-env33-c 25 | ' 26 | 27 | 28 | WarningsAsErrors: '' 29 | HeaderFilterRegex: '*spdlog/[^f].*' 30 | AnalyzeTemporaryDtors: false 31 | FormatStyle: none 32 | 33 | CheckOptions: 34 | - key: google-readability-braces-around-statements.ShortStatementLines 35 | value: '1' 36 | - key: google-readability-function-size.StatementThreshold 37 | value: '800' 38 | - key: google-readability-namespace-comments.ShortNamespaceLines 39 | value: '10' 40 | - key: google-readability-namespace-comments.SpacesBeforeComments 41 | value: '2' 42 | - key: modernize-loop-convert.MaxCopySize 43 | value: '16' 44 | - key: modernize-loop-convert.MinConfidence 45 | value: reasonable 46 | - key: modernize-loop-convert.NamingStyle 47 | value: CamelCase 48 | - key: modernize-pass-by-value.IncludeStyle 49 | value: llvm 50 | - key: modernize-replace-auto-ptr.IncludeStyle 51 | value: llvm 52 | - key: modernize-use-nullptr.NullMacros 53 | value: 'NULL' 54 | 55 | -------------------------------------------------------------------------------- /third_party/spdlog/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=false 2 | -------------------------------------------------------------------------------- /third_party/spdlog/.gitignore: -------------------------------------------------------------------------------- 1 | # Auto generated files 2 | build/* 3 | *.slo 4 | *.lo 5 | *.o 6 | *.obj 7 | *.suo 8 | *.tlog 9 | *.ilk 10 | *.log 11 | *.pdb 12 | *.idb 13 | *.iobj 14 | *.ipdb 15 | *.opensdf 16 | *.sdf 17 | 18 | # Compiled Dynamic libraries 19 | *.so 20 | *.dylib 21 | *.dll 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Codelite 35 | .codelite 36 | 37 | # KDevelop 38 | *.kdev4 39 | 40 | # .orig files 41 | *.orig 42 | 43 | # example files 44 | example/* 45 | !example/example.cpp 46 | !example/bench.cpp 47 | !example/utils.h 48 | !example/Makefile* 49 | !example/example.sln 50 | !example/example.vcxproj 51 | !example/CMakeLists.txt 52 | !example/meson.build 53 | !example/multisink.cpp 54 | !example/jni 55 | 56 | # generated files 57 | generated 58 | 59 | # Cmake 60 | CMakeCache.txt 61 | CMakeFiles 62 | CMakeScripts 63 | Makefile 64 | cmake_install.cmake 65 | install_manifest.txt 66 | /tests/tests.VC.VC.opendb 67 | /tests/tests.VC.db 68 | /tests/tests 69 | /tests/logs/* 70 | 71 | # idea 72 | .idea/ 73 | cmake-build-*/ 74 | *.db 75 | *.ipch 76 | *.filters 77 | *.db-wal 78 | *.opendb 79 | *.db-shm 80 | *.vcxproj 81 | *.tcl 82 | *.user 83 | *.sln 84 | -------------------------------------------------------------------------------- /third_party/spdlog/INSTALL: -------------------------------------------------------------------------------- 1 | Header only version: 2 | ================================================================== 3 | Just copy the files to your build tree and use a C++11 compiler. 4 | Or use CMake: 5 | add_executable(example_header_only example.cpp) 6 | target_link_libraries(example_header_only spdlog::spdlog_header_only) 7 | 8 | 9 | Compiled library version: 10 | ================================================================== 11 | CMake: 12 | add_executable(example example.cpp) 13 | target_link_libraries(example spdlog::spdlog) 14 | 15 | Or copy src/spdlog.cpp to your build tree and pass the -DSPDLOG_COMPILED_LIB to the compiler. 16 | 17 | Tested on: 18 | gcc 4.8.1 and above 19 | clang 3.5 20 | Visual Studio 2013 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /third_party/spdlog/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Gabi Melman. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -- NOTE: Third party dependency used by this software -- 24 | This software depends on the fmt lib (MIT License), 25 | and users must comply to its license: https://github.com/fmtlib/fmt/blob/master/LICENSE.rst 26 | 27 | -------------------------------------------------------------------------------- /third_party/spdlog/bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT) 2 | 3 | cmake_minimum_required(VERSION 3.10) 4 | project(spdlog_bench CXX) 5 | 6 | if(NOT TARGET spdlog) 7 | # Stand-alone build 8 | find_package(spdlog CONFIG REQUIRED) 9 | endif() 10 | 11 | find_package(Threads REQUIRED) 12 | find_package(benchmark CONFIG) 13 | if(NOT benchmark_FOUND) 14 | message(STATUS "Using CMake Version ${CMAKE_VERSION}") 15 | if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.11.0") 16 | # User can fetch googlebenchmark 17 | message(STATUS "Downloading GoogleBenchmark") 18 | include(FetchContent) 19 | set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE INTERNAL "") 20 | # Do not build and run googlebenchmark tests 21 | FetchContent_Declare(googlebenchmark GIT_REPOSITORY https://github.com/google/benchmark.git GIT_TAG v1.5.2) 22 | 23 | FetchContent_MakeAvailable(googlebenchmark) 24 | else() 25 | message(FATAL_ERROR "GoogleBenchmark is missing. Use CMake >= 3.11 or download it") 26 | endif() 27 | endif() 28 | 29 | add_executable(bench bench.cpp) 30 | spdlog_enable_warnings(bench) 31 | target_link_libraries(bench PRIVATE spdlog::spdlog) 32 | 33 | add_executable(async_bench async_bench.cpp) 34 | target_link_libraries(async_bench PRIVATE spdlog::spdlog) 35 | 36 | add_executable(latency latency.cpp) 37 | target_link_libraries(latency PRIVATE benchmark::benchmark spdlog::spdlog) 38 | 39 | add_executable(formatter-bench formatter-bench.cpp) 40 | target_link_libraries(formatter-bench PRIVATE benchmark::benchmark spdlog::spdlog) 41 | -------------------------------------------------------------------------------- /third_party/spdlog/bench/formatter-bench.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2018 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #include "benchmark/benchmark.h" 7 | 8 | #include "spdlog/spdlog.h" 9 | #include "spdlog/pattern_formatter.h" 10 | 11 | void bench_formatter(benchmark::State &state, std::string pattern) 12 | { 13 | auto formatter = spdlog::details::make_unique(pattern); 14 | spdlog::memory_buf_t dest; 15 | std::string logger_name = "logger-name"; 16 | const char *text = "Hello. This is some message with length of 80 "; 17 | 18 | spdlog::source_loc source_loc{"a/b/c/d/myfile.cpp", 123, "some_func()"}; 19 | spdlog::details::log_msg msg(source_loc, logger_name, spdlog::level::info, text); 20 | 21 | for (auto _ : state) 22 | { 23 | dest.clear(); 24 | formatter->format(msg, dest); 25 | benchmark::DoNotOptimize(dest); 26 | } 27 | } 28 | 29 | void bench_formatters() 30 | { 31 | // basic patterns(single flag) 32 | std::string all_flags = "+vtPnlLaAbBcCYDmdHIMSefFprRTXzEisg@luioO%"; 33 | std::vector basic_patterns; 34 | for (auto &flag : all_flags) 35 | { 36 | auto pattern = std::string("%") + flag; 37 | benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern); 38 | 39 | // pattern = std::string("%16") + flag; 40 | // benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern); 41 | // 42 | // // bench center padding 43 | // pattern = std::string("%=16") + flag; 44 | // benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern); 45 | } 46 | 47 | // complex patterns 48 | std::vector patterns = { 49 | "[%D %X] [%l] [%n] %v", 50 | "[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] %v", 51 | "[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] [%t] %v", 52 | }; 53 | for (auto &pattern : patterns) 54 | { 55 | benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern)->Iterations(2500000); 56 | } 57 | } 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | 62 | spdlog::set_pattern("[%^%l%$] %v"); 63 | if (argc != 2) 64 | { 65 | spdlog::error("Usage: {} (or \"all\" to bench all)", argv[0]); 66 | exit(1); 67 | } 68 | 69 | std::string pattern = argv[1]; 70 | if (pattern == "all") 71 | { 72 | bench_formatters(); 73 | } 74 | else 75 | { 76 | benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern); 77 | } 78 | benchmark::Initialize(&argc, argv); 79 | benchmark::RunSpecifiedBenchmarks(); 80 | } 81 | -------------------------------------------------------------------------------- /third_party/spdlog/bench/utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2015 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace utils { 13 | 14 | template 15 | inline std::string format(const T &value) 16 | { 17 | static std::locale loc(""); 18 | std::stringstream ss; 19 | ss.imbue(loc); 20 | ss << value; 21 | return ss.str(); 22 | } 23 | 24 | template<> 25 | inline std::string format(const double &value) 26 | { 27 | static std::locale loc(""); 28 | std::stringstream ss; 29 | ss.imbue(loc); 30 | ss << std::fixed << std::setprecision(1) << value; 31 | return ss.str(); 32 | } 33 | 34 | } // namespace utils 35 | -------------------------------------------------------------------------------- /third_party/spdlog/cmake/ide.cmake: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------- 2 | # IDE support for headers 3 | # --------------------------------------------------------------------------------------- 4 | set(SPDLOG_HEADERS_DIR "${CMAKE_CURRENT_LIST_DIR}/../include") 5 | 6 | file(GLOB SPDLOG_TOP_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/*.h") 7 | file(GLOB SPDLOG_DETAILS_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/details/*.h") 8 | file(GLOB SPDLOG_SINKS_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/sinks/*.h") 9 | file(GLOB SPDLOG_FMT_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/fmt/*.h") 10 | file(GLOB SPDLOG_FMT_BUNDELED_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/fmt/bundled/*.h") 11 | set(SPDLOG_ALL_HEADERS ${SPDLOG_TOP_HEADERS} ${SPDLOG_DETAILS_HEADERS} ${SPDLOG_SINKS_HEADERS} ${SPDLOG_FMT_HEADERS} 12 | ${SPDLOG_FMT_BUNDELED_HEADERS}) 13 | 14 | source_group("Header Files\\spdlog" FILES ${SPDLOG_TOP_HEADERS}) 15 | source_group("Header Files\\spdlog\\details" FILES ${SPDLOG_DETAILS_HEADERS}) 16 | source_group("Header Files\\spdlog\\sinks" FILES ${SPDLOG_SINKS_HEADERS}) 17 | source_group("Header Files\\spdlog\\fmt" FILES ${SPDLOG_FMT_HEADERS}) 18 | source_group("Header Files\\spdlog\\fmt\\bundled\\" FILES ${SPDLOG_FMT_BUNDELED_HEADERS}) 19 | -------------------------------------------------------------------------------- /third_party/spdlog/cmake/spdlog.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=${prefix}/include 4 | libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ 5 | 6 | Name: lib@PROJECT_NAME@ 7 | Description: Fast C++ logging library. 8 | URL: https://github.com/gabime/@PROJECT_NAME@ 9 | Version: @SPDLOG_VERSION@ 10 | CFlags: -I${includedir} @PKG_CONFIG_DEFINES@ 11 | Libs: -L${libdir} -lspdlog -pthread 12 | Requires: @PKG_CONFIG_REQUIRES@ 13 | 14 | -------------------------------------------------------------------------------- /third_party/spdlog/cmake/spdlogCPack.cmake: -------------------------------------------------------------------------------- 1 | set(CPACK_GENERATOR "TGZ;ZIP" CACHE STRING "Semicolon separated list of generators") 2 | 3 | set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) 4 | set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR}" "${PROJECT_NAME}" ALL .) 5 | 6 | set(CPACK_PROJECT_URL "https://github.com/gabime/spdlog") 7 | set(CPACK_PACKAGE_VENDOR "Gabi Melman") 8 | set(CPACK_PACKAGE_CONTACT "Gabi Melman ") 9 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Fast C++ logging library") 10 | set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) 11 | set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) 12 | set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) 13 | set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) 14 | if(PROJECT_VERSION_TWEAK) 15 | set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}.${PROJECT_VERSION_TWEAK}) 16 | endif() 17 | set(CPACK_PACKAGE_RELOCATABLE ON CACHE BOOL "Build relocatable package") 18 | 19 | set(CPACK_RPM_PACKAGE_LICENSE "MIT") 20 | set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries") 21 | set(CPACK_DEBIAN_PACKAGE_SECTION "libs") 22 | set(CPACK_RPM_PACKAGE_URL ${CPACK_PROJECT_URL}) 23 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${CPACK_PROJECT_URL}) 24 | set(CPACK_RPM_PACKAGE_DESCRIPTION "Very fast, header-only/compiled, C++ logging library.") 25 | set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Very fast, header-only/compiled, C++ logging library.") 26 | 27 | if(CPACK_PACKAGE_NAME) 28 | set(CPACK_RPM_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") 29 | set(CPACK_DEBIAN_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") 30 | else() 31 | set(CPACK_RPM_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}") 32 | set(CPACK_DEBIAN_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}") 33 | set(CPACK_RPM_PACKAGE_NAME "${PROJECT_NAME}") 34 | set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}") 35 | endif() 36 | 37 | if(CPACK_RPM_PACKAGE_RELEASE) 38 | set(CPACK_RPM_FILE_NAME "${CPACK_RPM_FILE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}") 39 | endif() 40 | if(CPACK_DEBIAN_PACKAGE_RELEASE) 41 | set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}-${CPACK_DEBIAN_PACKAGE_RELEASE}") 42 | endif() 43 | 44 | if(CPACK_RPM_PACKAGE_ARCHITECTURE) 45 | set(CPACK_RPM_FILE_NAME "${CPACK_RPM_FILE_NAME}.${CPACK_RPM_PACKAGE_ARCHITECTURE}") 46 | endif() 47 | if(CPACK_DEBIAN_PACKAGE_ARCHITECTURE) 48 | set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") 49 | endif() 50 | set(CPACK_RPM_FILE_NAME "${CPACK_RPM_FILE_NAME}.rpm") 51 | set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.deb") 52 | 53 | if(NOT CPACK_PACKAGE_RELOCATABLE) 54 | # Depend on pkgconfig rpm to create the system pkgconfig folder 55 | set(CPACK_RPM_PACKAGE_REQUIRES pkgconfig) 56 | set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION 57 | "${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig") 58 | endif() 59 | 60 | include(CPack) 61 | -------------------------------------------------------------------------------- /third_party/spdlog/cmake/spdlogConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright(c) 2019 spdlog authors 2 | # Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | @PACKAGE_INIT@ 5 | 6 | find_package(Threads REQUIRED) 7 | 8 | set(SPDLOG_FMT_EXTERNAL @SPDLOG_FMT_EXTERNAL@) 9 | set(config_targets_file @config_targets_file@) 10 | 11 | if(SPDLOG_FMT_EXTERNAL) 12 | include(CMakeFindDependencyMacro) 13 | find_dependency(fmt CONFIG) 14 | endif() 15 | 16 | 17 | include("${CMAKE_CURRENT_LIST_DIR}/${config_targets_file}") 18 | 19 | check_required_components(spdlog) -------------------------------------------------------------------------------- /third_party/spdlog/cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | # Get spdlog version from include/spdlog/version.h and put it in SPDLOG_VERSION 2 | function(spdlog_extract_version) 3 | file(READ "${CMAKE_CURRENT_LIST_DIR}/include/spdlog/version.h" file_contents) 4 | string(REGEX MATCH "SPDLOG_VER_MAJOR ([0-9]+)" _ "${file_contents}") 5 | if(NOT CMAKE_MATCH_COUNT EQUAL 1) 6 | message(FATAL_ERROR "Could not extract major version number from spdlog/version.h") 7 | endif() 8 | set(ver_major ${CMAKE_MATCH_1}) 9 | 10 | string(REGEX MATCH "SPDLOG_VER_MINOR ([0-9]+)" _ "${file_contents}") 11 | if(NOT CMAKE_MATCH_COUNT EQUAL 1) 12 | message(FATAL_ERROR "Could not extract minor version number from spdlog/version.h") 13 | endif() 14 | 15 | set(ver_minor ${CMAKE_MATCH_1}) 16 | string(REGEX MATCH "SPDLOG_VER_PATCH ([0-9]+)" _ "${file_contents}") 17 | if(NOT CMAKE_MATCH_COUNT EQUAL 1) 18 | message(FATAL_ERROR "Could not extract patch version number from spdlog/version.h") 19 | endif() 20 | set(ver_patch ${CMAKE_MATCH_1}) 21 | 22 | set(SPDLOG_VERSION_MAJOR ${ver_major} PARENT_SCOPE) 23 | set(SPDLOG_VERSION_MINOR ${ver_minor} PARENT_SCOPE) 24 | set(SPDLOG_VERSION_PATCH ${ver_patch} PARENT_SCOPE) 25 | set(SPDLOG_VERSION "${ver_major}.${ver_minor}.${ver_patch}" PARENT_SCOPE) 26 | endfunction() 27 | 28 | # Turn on warnings on the given target 29 | function(spdlog_enable_warnings target_name) 30 | if(SPDLOG_BUILD_WARNINGS) 31 | if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 32 | list(APPEND MSVC_OPTIONS "/W3") 33 | if(MSVC_VERSION GREATER 1900) # Allow non fatal security warnings for msvc 2015 34 | list(APPEND MSVC_OPTIONS "/WX") 35 | endif() 36 | endif() 37 | 38 | target_compile_options( 39 | ${target_name} 40 | PRIVATE $<$,$,$>: 41 | -Wall 42 | -Wextra 43 | -Wconversion 44 | -pedantic 45 | -Werror 46 | -Wfatal-errors> 47 | $<$:${MSVC_OPTIONS}>) 48 | endif() 49 | endfunction() 50 | 51 | # Enable address sanitizer (gcc/clang only) 52 | function(spdlog_enable_sanitizer target_name) 53 | if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") 54 | message(FATAL_ERROR "Sanitizer supported only for gcc/clang") 55 | endif() 56 | message(STATUS "Address sanitizer enabled") 57 | target_compile_options(${target_name} PRIVATE -fsanitize=address,undefined) 58 | target_compile_options(${target_name} PRIVATE -fno-sanitize=signed-integer-overflow) 59 | target_compile_options(${target_name} PRIVATE -fno-sanitize-recover=all) 60 | target_compile_options(${target_name} PRIVATE -fno-omit-frame-pointer) 61 | target_link_libraries(${target_name} PRIVATE -fsanitize=address,undefined -fuse-ld=gold) 62 | endfunction() 63 | -------------------------------------------------------------------------------- /third_party/spdlog/cmake/version.rc.in: -------------------------------------------------------------------------------- 1 | #define APSTUDIO_READONLY_SYMBOLS 2 | #include 3 | #undef APSTUDIO_READONLY_SYMBOLS 4 | 5 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 6 | 7 | 8 | VS_VERSION_INFO VERSIONINFO 9 | FILEVERSION @SPDLOG_VERSION_MAJOR@,@SPDLOG_VERSION_MINOR@,@SPDLOG_VERSION_PATCH@,0 10 | PRODUCTVERSION @SPDLOG_VERSION_MAJOR@,@SPDLOG_VERSION_MINOR@,@SPDLOG_VERSION_PATCH@,0 11 | FILEFLAGSMASK 0x3fL 12 | #ifdef _DEBUG 13 | FILEFLAGS 0x1L 14 | #else 15 | FILEFLAGS 0x0L 16 | #endif 17 | FILEOS 0x40004L 18 | FILETYPE 0x2L 19 | FILESUBTYPE 0x0L 20 | BEGIN 21 | BLOCK "StringFileInfo" 22 | BEGIN 23 | BLOCK "040904b0" 24 | BEGIN 25 | VALUE "FileDescription", "spdlog dll\0" 26 | VALUE "FileVersion", "@SPDLOG_VERSION@.0\0" 27 | VALUE "InternalName", "spdlog.dll\0" 28 | VALUE "LegalCopyright", "Copyright (C) spdlog\0" 29 | VALUE "ProductName", "spdlog\0" 30 | VALUE "ProductVersion", "@SPDLOG_VERSION@.0\0" 31 | END 32 | END 33 | BLOCK "VarFileInfo" 34 | BEGIN 35 | VALUE "Translation", 0x409, 1200 36 | END 37 | END 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /third_party/spdlog/example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT) 2 | 3 | cmake_minimum_required(VERSION 3.10) 4 | project(spdlog_examples CXX) 5 | 6 | if(NOT TARGET spdlog) 7 | # Stand-alone build 8 | find_package(spdlog REQUIRED) 9 | endif() 10 | 11 | # --------------------------------------------------------------------------------------- 12 | # Example of using pre-compiled library 13 | # --------------------------------------------------------------------------------------- 14 | add_executable(example example.cpp) 15 | target_link_libraries(example PRIVATE spdlog::spdlog) 16 | 17 | # --------------------------------------------------------------------------------------- 18 | # Example of using header-only library 19 | # --------------------------------------------------------------------------------------- 20 | if(SPDLOG_BUILD_EXAMPLE_HO) 21 | add_executable(example_header_only example.cpp) 22 | target_link_libraries(example_header_only PRIVATE spdlog::spdlog_header_only) 23 | endif() 24 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/async_logger-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | SPDLOG_INLINE spdlog::async_logger::async_logger( 17 | std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, async_overflow_policy overflow_policy) 18 | : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy) 19 | {} 20 | 21 | SPDLOG_INLINE spdlog::async_logger::async_logger( 22 | std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy) 23 | : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) 24 | {} 25 | 26 | // send the log message to the thread pool 27 | SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg) 28 | { 29 | if (auto pool_ptr = thread_pool_.lock()) 30 | { 31 | pool_ptr->post_log(shared_from_this(), msg, overflow_policy_); 32 | } 33 | else 34 | { 35 | throw_spdlog_ex("async log: thread pool doesn't exist anymore"); 36 | } 37 | } 38 | 39 | // send flush request to the thread pool 40 | SPDLOG_INLINE void spdlog::async_logger::flush_() 41 | { 42 | if (auto pool_ptr = thread_pool_.lock()) 43 | { 44 | pool_ptr->post_flush(shared_from_this(), overflow_policy_); 45 | } 46 | else 47 | { 48 | throw_spdlog_ex("async flush: thread pool doesn't exist anymore"); 49 | } 50 | } 51 | 52 | // 53 | // backend functions - called from the thread pool to do the actual job 54 | // 55 | SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) 56 | { 57 | for (auto &sink : sinks_) 58 | { 59 | if (sink->should_log(msg.level)) 60 | { 61 | SPDLOG_TRY 62 | { 63 | sink->log(msg); 64 | } 65 | SPDLOG_LOGGER_CATCH(msg.source) 66 | } 67 | } 68 | 69 | if (should_flush_(msg)) 70 | { 71 | backend_flush_(); 72 | } 73 | } 74 | 75 | SPDLOG_INLINE void spdlog::async_logger::backend_flush_() 76 | { 77 | for (auto &sink : sinks_) 78 | { 79 | SPDLOG_TRY 80 | { 81 | sink->flush(); 82 | } 83 | SPDLOG_LOGGER_CATCH(source_loc()) 84 | } 85 | } 86 | 87 | SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::string new_name) 88 | { 89 | auto cloned = std::make_shared(*this); 90 | cloned->name_ = std::move(new_name); 91 | return cloned; 92 | } 93 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/async_logger.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Fast asynchronous logger. 7 | // Uses pre allocated queue. 8 | // Creates a single back thread to pop messages from the queue and log them. 9 | // 10 | // Upon each log write the logger: 11 | // 1. Checks if its log level is enough to log the message 12 | // 2. Push a new copy of the message to a queue (or block the caller until 13 | // space is available in the queue) 14 | // Upon destruction, logs all remaining messages in the queue before 15 | // destructing.. 16 | 17 | #include 18 | 19 | namespace spdlog { 20 | 21 | // Async overflow policy - block by default. 22 | enum class async_overflow_policy 23 | { 24 | block, // Block until message can be enqueued 25 | overrun_oldest // Discard oldest message in the queue if full when trying to 26 | // add new item. 27 | }; 28 | 29 | namespace details { 30 | class thread_pool; 31 | } 32 | 33 | class SPDLOG_API async_logger final : public std::enable_shared_from_this, public logger 34 | { 35 | friend class details::thread_pool; 36 | 37 | public: 38 | template 39 | async_logger(std::string logger_name, It begin, It end, std::weak_ptr tp, 40 | async_overflow_policy overflow_policy = async_overflow_policy::block) 41 | : logger(std::move(logger_name), begin, end) 42 | , thread_pool_(std::move(tp)) 43 | , overflow_policy_(overflow_policy) 44 | {} 45 | 46 | async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, 47 | async_overflow_policy overflow_policy = async_overflow_policy::block); 48 | 49 | async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, 50 | async_overflow_policy overflow_policy = async_overflow_policy::block); 51 | 52 | std::shared_ptr clone(std::string new_name) override; 53 | 54 | protected: 55 | void sink_it_(const details::log_msg &msg) override; 56 | void flush_() override; 57 | void backend_sink_it_(const details::log_msg &incoming_log_msg); 58 | void backend_flush_(); 59 | 60 | private: 61 | std::weak_ptr thread_pool_; 62 | async_overflow_policy overflow_policy_; 63 | }; 64 | } // namespace spdlog 65 | 66 | #ifdef SPDLOG_HEADER_ONLY 67 | # include "async_logger-inl.h" 68 | #endif 69 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/cfg/argv.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | #include 6 | #include 7 | 8 | // 9 | // Init log levels using each argv entry that starts with "SPDLOG_LEVEL=" 10 | // 11 | // set all loggers to debug level: 12 | // example.exe "SPDLOG_LEVEL=debug" 13 | 14 | // set logger1 to trace level 15 | // example.exe "SPDLOG_LEVEL=logger1=trace" 16 | 17 | // turn off all logging except for logger1 and logger2: 18 | // example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info" 19 | 20 | namespace spdlog { 21 | namespace cfg { 22 | 23 | // search for SPDLOG_LEVEL= in the args and use it to init the levels 24 | inline void load_argv_levels(int argc, const char **argv) 25 | { 26 | const std::string spdlog_level_prefix = "SPDLOG_LEVEL="; 27 | for (int i = 1; i < argc; i++) 28 | { 29 | std::string arg = argv[i]; 30 | if (arg.find(spdlog_level_prefix) == 0) 31 | { 32 | auto levels_string = arg.substr(spdlog_level_prefix.size()); 33 | helpers::load_levels(levels_string); 34 | } 35 | } 36 | } 37 | 38 | inline void load_argv_levels(int argc, char **argv) 39 | { 40 | load_argv_levels(argc, const_cast(argv)); 41 | } 42 | 43 | } // namespace cfg 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/cfg/env.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | #include 6 | #include 7 | #include 8 | 9 | // 10 | // Init levels and patterns from env variables SPDLOG_LEVEL 11 | // Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger). 12 | // Note - fallback to "info" level on unrecognized levels 13 | // 14 | // Examples: 15 | // 16 | // set global level to debug: 17 | // export SPDLOG_LEVEL=debug 18 | // 19 | // turn off all logging except for logger1: 20 | // export SPDLOG_LEVEL="*=off,logger1=debug" 21 | // 22 | 23 | // turn off all logging except for logger1 and logger2: 24 | // export SPDLOG_LEVEL="off,logger1=debug,logger2=info" 25 | 26 | namespace spdlog { 27 | namespace cfg { 28 | inline void load_env_levels() 29 | { 30 | auto env_val = details::os::getenv("SPDLOG_LEVEL"); 31 | if (!env_val.empty()) 32 | { 33 | helpers::load_levels(env_val); 34 | } 35 | } 36 | 37 | } // namespace cfg 38 | } // namespace spdlog 39 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/cfg/helpers.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace cfg { 11 | namespace helpers { 12 | // 13 | // Init levels from given string 14 | // 15 | // Examples: 16 | // 17 | // set global level to debug: "debug" 18 | // turn off all logging except for logger1: "off,logger1=debug" 19 | // turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" 20 | // 21 | SPDLOG_API void load_levels(const std::string &txt); 22 | } // namespace helpers 23 | 24 | } // namespace cfg 25 | } // namespace spdlog 26 | 27 | #ifdef SPDLOG_HEADER_ONLY 28 | # include "helpers-inl.h" 29 | #endif // SPDLOG_HEADER_ONLY 30 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/common-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | namespace level { 15 | 16 | #if __cplusplus >= 201703L 17 | constexpr 18 | #endif 19 | static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES; 20 | 21 | static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES; 22 | 23 | SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT 24 | { 25 | return level_string_views[l]; 26 | } 27 | 28 | SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT 29 | { 30 | return short_level_names[l]; 31 | } 32 | 33 | SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT 34 | { 35 | auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name); 36 | if (it != std::end(level_string_views)) 37 | return static_cast(it - std::begin(level_string_views)); 38 | 39 | // check also for "warn" and "err" before giving up.. 40 | if (name == "warn") 41 | { 42 | return level::warn; 43 | } 44 | if (name == "err") 45 | { 46 | return level::err; 47 | } 48 | return level::off; 49 | } 50 | } // namespace level 51 | 52 | SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg) 53 | : msg_(std::move(msg)) 54 | {} 55 | 56 | SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) 57 | { 58 | #ifdef SPDLOG_USE_STD_FORMAT 59 | msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what(); 60 | #else 61 | memory_buf_t outbuf; 62 | fmt::format_system_error(outbuf, last_errno, msg.c_str()); 63 | msg_ = fmt::to_string(outbuf); 64 | #endif 65 | } 66 | 67 | SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT 68 | { 69 | return msg_.c_str(); 70 | } 71 | 72 | SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno) 73 | { 74 | SPDLOG_THROW(spdlog_ex(msg, last_errno)); 75 | } 76 | 77 | SPDLOG_INLINE void throw_spdlog_ex(std::string msg) 78 | { 79 | SPDLOG_THROW(spdlog_ex(std::move(msg))); 80 | } 81 | 82 | } // namespace spdlog 83 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/backtracer-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | namespace spdlog { 10 | namespace details { 11 | SPDLOG_INLINE backtracer::backtracer(const backtracer &other) 12 | { 13 | std::lock_guard lock(other.mutex_); 14 | enabled_ = other.enabled(); 15 | messages_ = other.messages_; 16 | } 17 | 18 | SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT 19 | { 20 | std::lock_guard lock(other.mutex_); 21 | enabled_ = other.enabled(); 22 | messages_ = std::move(other.messages_); 23 | } 24 | 25 | SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) 26 | { 27 | std::lock_guard lock(mutex_); 28 | enabled_ = other.enabled(); 29 | messages_ = std::move(other.messages_); 30 | return *this; 31 | } 32 | 33 | SPDLOG_INLINE void backtracer::enable(size_t size) 34 | { 35 | std::lock_guard lock{mutex_}; 36 | enabled_.store(true, std::memory_order_relaxed); 37 | messages_ = circular_q{size}; 38 | } 39 | 40 | SPDLOG_INLINE void backtracer::disable() 41 | { 42 | std::lock_guard lock{mutex_}; 43 | enabled_.store(false, std::memory_order_relaxed); 44 | } 45 | 46 | SPDLOG_INLINE bool backtracer::enabled() const 47 | { 48 | return enabled_.load(std::memory_order_relaxed); 49 | } 50 | 51 | SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) 52 | { 53 | std::lock_guard lock{mutex_}; 54 | messages_.push_back(log_msg_buffer{msg}); 55 | } 56 | 57 | // pop all items in the q and apply the given fun on each of them. 58 | SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) 59 | { 60 | std::lock_guard lock{mutex_}; 61 | while (!messages_.empty()) 62 | { 63 | auto &front_msg = messages_.front(); 64 | fun(front_msg); 65 | messages_.pop_front(); 66 | } 67 | } 68 | } // namespace details 69 | } // namespace spdlog 70 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/backtracer.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // Store log messages in circular buffer. 14 | // Useful for storing debug data in case of error/warning happens. 15 | 16 | namespace spdlog { 17 | namespace details { 18 | class SPDLOG_API backtracer 19 | { 20 | mutable std::mutex mutex_; 21 | std::atomic enabled_{false}; 22 | circular_q messages_; 23 | 24 | public: 25 | backtracer() = default; 26 | backtracer(const backtracer &other); 27 | 28 | backtracer(backtracer &&other) SPDLOG_NOEXCEPT; 29 | backtracer &operator=(backtracer other); 30 | 31 | void enable(size_t size); 32 | void disable(); 33 | bool enabled() const; 34 | void push_back(const log_msg &msg); 35 | 36 | // pop all items in the q and apply the given fun on each of them. 37 | void foreach_pop(std::function fun); 38 | }; 39 | 40 | } // namespace details 41 | } // namespace spdlog 42 | 43 | #ifdef SPDLOG_HEADER_ONLY 44 | # include "backtracer-inl.h" 45 | #endif 46 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/console_globals.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | 12 | struct console_mutex 13 | { 14 | using mutex_t = std::mutex; 15 | static mutex_t &mutex() 16 | { 17 | static mutex_t s_mutex; 18 | return s_mutex; 19 | } 20 | }; 21 | 22 | struct console_nullmutex 23 | { 24 | using mutex_t = null_mutex; 25 | static mutex_t &mutex() 26 | { 27 | static mutex_t s_mutex; 28 | return s_mutex; 29 | } 30 | }; 31 | } // namespace details 32 | } // namespace spdlog 33 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/file_helper.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | 12 | // Helper class for file sinks. 13 | // When failing to open a file, retry several times(5) with a delay interval(10 ms). 14 | // Throw spdlog_ex exception on errors. 15 | 16 | class SPDLOG_API file_helper 17 | { 18 | public: 19 | file_helper() = default; 20 | explicit file_helper(const file_event_handlers &event_handlers); 21 | 22 | file_helper(const file_helper &) = delete; 23 | file_helper &operator=(const file_helper &) = delete; 24 | ~file_helper(); 25 | 26 | void open(const filename_t &fname, bool truncate = false); 27 | void reopen(bool truncate); 28 | void flush(); 29 | void close(); 30 | void write(const memory_buf_t &buf); 31 | size_t size() const; 32 | const filename_t &filename() const; 33 | 34 | // 35 | // return file path and its extension: 36 | // 37 | // "mylog.txt" => ("mylog", ".txt") 38 | // "mylog" => ("mylog", "") 39 | // "mylog." => ("mylog.", "") 40 | // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") 41 | // 42 | // the starting dot in filenames is ignored (hidden files): 43 | // 44 | // ".mylog" => (".mylog". "") 45 | // "my_folder/.mylog" => ("my_folder/.mylog", "") 46 | // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") 47 | static std::tuple split_by_extension(const filename_t &fname); 48 | 49 | private: 50 | const int open_tries_ = 5; 51 | const unsigned int open_interval_ = 10; 52 | std::FILE *fd_{nullptr}; 53 | filename_t filename_; 54 | file_event_handlers event_handlers_; 55 | }; 56 | } // namespace details 57 | } // namespace spdlog 58 | 59 | #ifdef SPDLOG_HEADER_ONLY 60 | # include "file_helper-inl.h" 61 | #endif 62 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/log_msg-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | 12 | namespace spdlog { 13 | namespace details { 14 | 15 | SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::source_loc loc, string_view_t a_logger_name, 16 | spdlog::level::level_enum lvl, spdlog::string_view_t msg) 17 | : logger_name(a_logger_name) 18 | , level(lvl) 19 | , time(log_time) 20 | #ifndef SPDLOG_NO_THREAD_ID 21 | , thread_id(os::thread_id()) 22 | #endif 23 | , source(loc) 24 | , payload(msg) 25 | {} 26 | 27 | SPDLOG_INLINE log_msg::log_msg( 28 | spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) 29 | : log_msg(os::now(), loc, a_logger_name, lvl, msg) 30 | {} 31 | 32 | SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) 33 | : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) 34 | {} 35 | 36 | } // namespace details 37 | } // namespace spdlog 38 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/log_msg.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | namespace details { 11 | struct SPDLOG_API log_msg 12 | { 13 | log_msg() = default; 14 | log_msg(log_clock::time_point log_time, source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); 15 | log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); 16 | log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg); 17 | log_msg(const log_msg &other) = default; 18 | log_msg &operator=(const log_msg &other) = default; 19 | 20 | string_view_t logger_name; 21 | level::level_enum level{level::off}; 22 | log_clock::time_point time; 23 | size_t thread_id{0}; 24 | 25 | // wrapping the formatted text with color (updated by pattern_formatter). 26 | mutable size_t color_range_start{0}; 27 | mutable size_t color_range_end{0}; 28 | 29 | source_loc source; 30 | string_view_t payload; 31 | }; 32 | } // namespace details 33 | } // namespace spdlog 34 | 35 | #ifdef SPDLOG_HEADER_ONLY 36 | # include "log_msg-inl.h" 37 | #endif 38 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/log_msg_buffer-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace details { 12 | 13 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg &orig_msg) 14 | : log_msg{orig_msg} 15 | { 16 | buffer.append(logger_name.begin(), logger_name.end()); 17 | buffer.append(payload.begin(), payload.end()); 18 | update_string_views(); 19 | } 20 | 21 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(const log_msg_buffer &other) 22 | : log_msg{other} 23 | { 24 | buffer.append(logger_name.begin(), logger_name.end()); 25 | buffer.append(payload.begin(), payload.end()); 26 | update_string_views(); 27 | } 28 | 29 | SPDLOG_INLINE log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT : log_msg{other}, buffer{std::move(other.buffer)} 30 | { 31 | update_string_views(); 32 | } 33 | 34 | SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) 35 | { 36 | log_msg::operator=(other); 37 | buffer.clear(); 38 | buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size()); 39 | update_string_views(); 40 | return *this; 41 | } 42 | 43 | SPDLOG_INLINE log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT 44 | { 45 | log_msg::operator=(other); 46 | buffer = std::move(other.buffer); 47 | update_string_views(); 48 | return *this; 49 | } 50 | 51 | SPDLOG_INLINE void log_msg_buffer::update_string_views() 52 | { 53 | logger_name = string_view_t{buffer.data(), logger_name.size()}; 54 | payload = string_view_t{buffer.data() + logger_name.size(), payload.size()}; 55 | } 56 | 57 | } // namespace details 58 | } // namespace spdlog 59 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/log_msg_buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace spdlog { 9 | namespace details { 10 | 11 | // Extend log_msg with internal buffer to store its payload. 12 | // This is needed since log_msg holds string_views that points to stack data. 13 | 14 | class SPDLOG_API log_msg_buffer : public log_msg 15 | { 16 | memory_buf_t buffer; 17 | void update_string_views(); 18 | 19 | public: 20 | log_msg_buffer() = default; 21 | explicit log_msg_buffer(const log_msg &orig_msg); 22 | log_msg_buffer(const log_msg_buffer &other); 23 | log_msg_buffer(log_msg_buffer &&other) SPDLOG_NOEXCEPT; 24 | log_msg_buffer &operator=(const log_msg_buffer &other); 25 | log_msg_buffer &operator=(log_msg_buffer &&other) SPDLOG_NOEXCEPT; 26 | }; 27 | 28 | } // namespace details 29 | } // namespace spdlog 30 | 31 | #ifdef SPDLOG_HEADER_ONLY 32 | # include "log_msg_buffer-inl.h" 33 | #endif 34 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/null_mutex.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | // null, no cost dummy "mutex" and dummy "atomic" int 9 | 10 | namespace spdlog { 11 | namespace details { 12 | struct null_mutex 13 | { 14 | void lock() const {} 15 | void unlock() const {} 16 | bool try_lock() const 17 | { 18 | return true; 19 | } 20 | }; 21 | 22 | struct null_atomic_int 23 | { 24 | int value; 25 | null_atomic_int() = default; 26 | 27 | explicit null_atomic_int(int new_value) 28 | : value(new_value) 29 | {} 30 | 31 | int load(std::memory_order = std::memory_order_relaxed) const 32 | { 33 | return value; 34 | } 35 | 36 | void store(int new_value, std::memory_order = std::memory_order_relaxed) 37 | { 38 | value = new_value; 39 | } 40 | 41 | int exchange(int new_value, std::memory_order = std::memory_order_relaxed) 42 | { 43 | std::swap(new_value, value); 44 | return new_value; // return value before the call 45 | } 46 | }; 47 | 48 | } // namespace details 49 | } // namespace spdlog 50 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/periodic_worker-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | namespace spdlog { 11 | namespace details { 12 | 13 | SPDLOG_INLINE periodic_worker::periodic_worker(const std::function &callback_fun, std::chrono::seconds interval) 14 | { 15 | active_ = (interval > std::chrono::seconds::zero()); 16 | if (!active_) 17 | { 18 | return; 19 | } 20 | 21 | worker_thread_ = std::thread([this, callback_fun, interval]() { 22 | for (;;) 23 | { 24 | std::unique_lock lock(this->mutex_); 25 | if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) 26 | { 27 | return; // active_ == false, so exit this thread 28 | } 29 | callback_fun(); 30 | } 31 | }); 32 | } 33 | 34 | // stop the worker thread and join it 35 | SPDLOG_INLINE periodic_worker::~periodic_worker() 36 | { 37 | if (worker_thread_.joinable()) 38 | { 39 | { 40 | std::lock_guard lock(mutex_); 41 | active_ = false; 42 | } 43 | cv_.notify_one(); 44 | worker_thread_.join(); 45 | } 46 | } 47 | 48 | } // namespace details 49 | } // namespace spdlog 50 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/periodic_worker.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // periodic worker thread - periodically executes the given callback function. 7 | // 8 | // RAII over the owned thread: 9 | // creates the thread on construction. 10 | // stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first). 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | namespace spdlog { 18 | namespace details { 19 | 20 | class SPDLOG_API periodic_worker 21 | { 22 | public: 23 | periodic_worker(const std::function &callback_fun, std::chrono::seconds interval); 24 | periodic_worker(const periodic_worker &) = delete; 25 | periodic_worker &operator=(const periodic_worker &) = delete; 26 | // stop the worker thread and join it 27 | ~periodic_worker(); 28 | 29 | private: 30 | bool active_; 31 | std::thread worker_thread_; 32 | std::mutex mutex_; 33 | std::condition_variable cv_; 34 | }; 35 | } // namespace details 36 | } // namespace spdlog 37 | 38 | #ifdef SPDLOG_HEADER_ONLY 39 | # include "periodic_worker-inl.h" 40 | #endif 41 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/synchronous_factory.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "registry.h" 7 | 8 | namespace spdlog { 9 | 10 | // Default logger factory- creates synchronous loggers 11 | class logger; 12 | 13 | struct synchronous_factory 14 | { 15 | template 16 | static std::shared_ptr create(std::string logger_name, SinkArgs &&... args) 17 | { 18 | auto sink = std::make_shared(std::forward(args)...); 19 | auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); 20 | details::registry::instance().initialize_logger(new_logger); 21 | return new_logger; 22 | } 23 | }; 24 | } // namespace spdlog 25 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/udp_client.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | // Helper RAII over unix udp client socket. 7 | // Will throw on construction if the socket creation failed. 8 | 9 | #ifdef _WIN32 10 | # error "include udp_client-windows.h instead" 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | namespace spdlog { 26 | namespace details { 27 | 28 | class udp_client 29 | { 30 | static constexpr int TX_BUFFER_SIZE = 1024 * 10; 31 | int socket_ = -1; 32 | struct sockaddr_in sockAddr_; 33 | 34 | void cleanup_() 35 | { 36 | if (socket_ != -1) 37 | { 38 | ::close(socket_); 39 | socket_ = -1; 40 | } 41 | } 42 | 43 | public: 44 | udp_client(const std::string &host, uint16_t port) 45 | { 46 | socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); 47 | if (socket_ < 0) 48 | { 49 | throw_spdlog_ex("error: Create Socket Failed!"); 50 | } 51 | 52 | int option_value = TX_BUFFER_SIZE; 53 | if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option_value), sizeof(option_value)) < 0) 54 | { 55 | cleanup_(); 56 | throw_spdlog_ex("error: setsockopt(SO_SNDBUF) Failed!"); 57 | } 58 | 59 | sockAddr_.sin_family = AF_INET; 60 | sockAddr_.sin_port = htons(port); 61 | 62 | if (::inet_aton(host.c_str(), &sockAddr_.sin_addr) == 0) 63 | { 64 | cleanup_(); 65 | throw_spdlog_ex("error: Invalid address!"); 66 | } 67 | 68 | ::memset(sockAddr_.sin_zero, 0x00, sizeof(sockAddr_.sin_zero)); 69 | } 70 | 71 | ~udp_client() 72 | { 73 | cleanup_(); 74 | } 75 | 76 | int fd() const 77 | { 78 | return socket_; 79 | } 80 | 81 | // Send exactly n_bytes of the given data. 82 | // On error close the connection and throw. 83 | void send(const char *data, size_t n_bytes) 84 | { 85 | ssize_t toslen = 0; 86 | socklen_t tolen = sizeof(struct sockaddr); 87 | if ((toslen = ::sendto(socket_, data, n_bytes, 0, (struct sockaddr *)&sockAddr_, tolen)) == -1) 88 | { 89 | throw_spdlog_ex("sendto(2) failed", errno); 90 | } 91 | } 92 | }; 93 | } // namespace details 94 | } // namespace spdlog 95 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/details/windows_include.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NOMINMAX 4 | # define NOMINMAX // prevent windows redefining min/max 5 | #endif 6 | 7 | #ifndef WIN32_LEAN_AND_MEAN 8 | # define WIN32_LEAN_AND_MEAN 9 | #endif 10 | 11 | #include 12 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/bundled/fmt.license.rst: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - present, Victor Zverovich 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | --- Optional exception to the license --- 23 | 24 | As an exception, if, as a result of your compiling your source code, portions 25 | of this Software are embedded into a machine-executable object form of such 26 | source code, you may redistribute such embedded portions in such object form 27 | without including the above copyright and permission notices. 28 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/bundled/locale.h: -------------------------------------------------------------------------------- 1 | #include "xchar.h" 2 | #warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead 3 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/chrono.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's chrono support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/compile.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's compile-time support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/fmt.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016-2018 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | // 9 | // Include a bundled header-only copy of fmtlib or an external one. 10 | // By default spdlog include its own copy. 11 | // 12 | 13 | #if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format 14 | # include 15 | #elif !defined(SPDLOG_FMT_EXTERNAL) 16 | # if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY) 17 | # define FMT_HEADER_ONLY 18 | # endif 19 | # ifndef FMT_USE_WINDOWS_H 20 | # define FMT_USE_WINDOWS_H 0 21 | # endif 22 | // enable the 'n' flag in for backward compatibility with fmt 6.x 23 | # define FMT_DEPRECATED_N_SPECIFIER 24 | # include 25 | # include 26 | #else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib 27 | # include 28 | # include 29 | #endif 30 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/ostr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's ostream support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fmt/xchar.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2016 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | // 8 | // include bundled or external copy of fmtlib's xchar support 9 | // 10 | 11 | #if !defined(SPDLOG_USE_STD_FORMAT) 12 | # if !defined(SPDLOG_FMT_EXTERNAL) 13 | # ifdef SPDLOG_HEADER_ONLY 14 | # ifndef FMT_HEADER_ONLY 15 | # define FMT_HEADER_ONLY 16 | # endif 17 | # endif 18 | # include 19 | # else 20 | # include 21 | # endif 22 | #endif 23 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/formatter.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | 11 | class formatter 12 | { 13 | public: 14 | virtual ~formatter() = default; 15 | virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0; 16 | virtual std::unique_ptr clone() const = 0; 17 | }; 18 | } // namespace spdlog 19 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/fwd.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | namespace spdlog { 7 | class logger; 8 | class formatter; 9 | 10 | namespace sinks { 11 | class sink; 12 | } 13 | 14 | } // namespace spdlog 15 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/base_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | template 16 | SPDLOG_INLINE spdlog::sinks::base_sink::base_sink() 17 | : formatter_{details::make_unique()} 18 | {} 19 | 20 | template 21 | SPDLOG_INLINE spdlog::sinks::base_sink::base_sink(std::unique_ptr formatter) 22 | : formatter_{std::move(formatter)} 23 | {} 24 | 25 | template 26 | void SPDLOG_INLINE spdlog::sinks::base_sink::log(const details::log_msg &msg) 27 | { 28 | std::lock_guard lock(mutex_); 29 | sink_it_(msg); 30 | } 31 | 32 | template 33 | void SPDLOG_INLINE spdlog::sinks::base_sink::flush() 34 | { 35 | std::lock_guard lock(mutex_); 36 | flush_(); 37 | } 38 | 39 | template 40 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern(const std::string &pattern) 41 | { 42 | std::lock_guard lock(mutex_); 43 | set_pattern_(pattern); 44 | } 45 | 46 | template 47 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_formatter(std::unique_ptr sink_formatter) 48 | { 49 | std::lock_guard lock(mutex_); 50 | set_formatter_(std::move(sink_formatter)); 51 | } 52 | 53 | template 54 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_pattern_(const std::string &pattern) 55 | { 56 | set_formatter_(details::make_unique(pattern)); 57 | } 58 | 59 | template 60 | void SPDLOG_INLINE spdlog::sinks::base_sink::set_formatter_(std::unique_ptr sink_formatter) 61 | { 62 | formatter_ = std::move(sink_formatter); 63 | } 64 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/base_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | // 6 | // base sink templated over a mutex (either dummy or real) 7 | // concrete implementation should override the sink_it_() and flush_() methods. 8 | // locking is taken care of in this class - no locking needed by the 9 | // implementers.. 10 | // 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace spdlog { 17 | namespace sinks { 18 | template 19 | class SPDLOG_API base_sink : public sink 20 | { 21 | public: 22 | base_sink(); 23 | explicit base_sink(std::unique_ptr formatter); 24 | ~base_sink() override = default; 25 | 26 | base_sink(const base_sink &) = delete; 27 | base_sink(base_sink &&) = delete; 28 | 29 | base_sink &operator=(const base_sink &) = delete; 30 | base_sink &operator=(base_sink &&) = delete; 31 | 32 | void log(const details::log_msg &msg) final; 33 | void flush() final; 34 | void set_pattern(const std::string &pattern) final; 35 | void set_formatter(std::unique_ptr sink_formatter) final; 36 | 37 | protected: 38 | // sink formatter 39 | std::unique_ptr formatter_; 40 | Mutex mutex_; 41 | 42 | virtual void sink_it_(const details::log_msg &msg) = 0; 43 | virtual void flush_() = 0; 44 | virtual void set_pattern_(const std::string &pattern); 45 | virtual void set_formatter_(std::unique_ptr sink_formatter); 46 | }; 47 | } // namespace sinks 48 | } // namespace spdlog 49 | 50 | #ifdef SPDLOG_HEADER_ONLY 51 | # include "base_sink-inl.h" 52 | #endif 53 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/basic_file_sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | namespace sinks { 15 | 16 | template 17 | SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate, const file_event_handlers &event_handlers) 18 | : file_helper_{event_handlers} 19 | { 20 | file_helper_.open(filename, truncate); 21 | } 22 | 23 | template 24 | SPDLOG_INLINE const filename_t &basic_file_sink::filename() const 25 | { 26 | return file_helper_.filename(); 27 | } 28 | 29 | template 30 | SPDLOG_INLINE void basic_file_sink::sink_it_(const details::log_msg &msg) 31 | { 32 | memory_buf_t formatted; 33 | base_sink::formatter_->format(msg, formatted); 34 | file_helper_.write(formatted); 35 | } 36 | 37 | template 38 | SPDLOG_INLINE void basic_file_sink::flush_() 39 | { 40 | file_helper_.flush(); 41 | } 42 | 43 | } // namespace sinks 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/basic_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | /* 17 | * Trivial file sink with single file as target 18 | */ 19 | template 20 | class basic_file_sink final : public base_sink 21 | { 22 | public: 23 | explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}); 24 | const filename_t &filename() const; 25 | 26 | protected: 27 | void sink_it_(const details::log_msg &msg) override; 28 | void flush_() override; 29 | 30 | private: 31 | details::file_helper file_helper_; 32 | }; 33 | 34 | using basic_file_sink_mt = basic_file_sink; 35 | using basic_file_sink_st = basic_file_sink; 36 | 37 | } // namespace sinks 38 | 39 | // 40 | // factory functions 41 | // 42 | template 43 | inline std::shared_ptr basic_logger_mt( 44 | const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}) 45 | { 46 | return Factory::template create(logger_name, filename, truncate, event_handlers); 47 | } 48 | 49 | template 50 | inline std::shared_ptr basic_logger_st( 51 | const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}) 52 | { 53 | return Factory::template create(logger_name, filename, truncate, event_handlers); 54 | } 55 | 56 | } // namespace spdlog 57 | 58 | #ifdef SPDLOG_HEADER_ONLY 59 | # include "basic_file_sink-inl.h" 60 | #endif 61 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/dist_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "base_sink.h" 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | // Distribution sink (mux). Stores a vector of sinks which get called when log 17 | // is called 18 | 19 | namespace spdlog { 20 | namespace sinks { 21 | 22 | template 23 | class dist_sink : public base_sink 24 | { 25 | public: 26 | dist_sink() = default; 27 | explicit dist_sink(std::vector> sinks) 28 | : sinks_(sinks) 29 | {} 30 | 31 | dist_sink(const dist_sink &) = delete; 32 | dist_sink &operator=(const dist_sink &) = delete; 33 | 34 | void add_sink(std::shared_ptr sink) 35 | { 36 | std::lock_guard lock(base_sink::mutex_); 37 | sinks_.push_back(sink); 38 | } 39 | 40 | void remove_sink(std::shared_ptr sink) 41 | { 42 | std::lock_guard lock(base_sink::mutex_); 43 | sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end()); 44 | } 45 | 46 | void set_sinks(std::vector> sinks) 47 | { 48 | std::lock_guard lock(base_sink::mutex_); 49 | sinks_ = std::move(sinks); 50 | } 51 | 52 | std::vector> &sinks() 53 | { 54 | return sinks_; 55 | } 56 | 57 | protected: 58 | void sink_it_(const details::log_msg &msg) override 59 | { 60 | for (auto &sink : sinks_) 61 | { 62 | if (sink->should_log(msg.level)) 63 | { 64 | sink->log(msg); 65 | } 66 | } 67 | } 68 | 69 | void flush_() override 70 | { 71 | for (auto &sink : sinks_) 72 | { 73 | sink->flush(); 74 | } 75 | } 76 | 77 | void set_pattern_(const std::string &pattern) override 78 | { 79 | set_formatter_(details::make_unique(pattern)); 80 | } 81 | 82 | void set_formatter_(std::unique_ptr sink_formatter) override 83 | { 84 | base_sink::formatter_ = std::move(sink_formatter); 85 | for (auto &sink : sinks_) 86 | { 87 | sink->set_formatter(base_sink::formatter_->clone()); 88 | } 89 | } 90 | std::vector> sinks_; 91 | }; 92 | 93 | using dist_sink_mt = dist_sink; 94 | using dist_sink_st = dist_sink; 95 | 96 | } // namespace sinks 97 | } // namespace spdlog 98 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/msvc_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2016 Alexander Dalshov. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #if defined(_WIN32) 7 | 8 | # include 9 | # include 10 | 11 | # include 12 | # include 13 | 14 | // Avoid including windows.h (https://stackoverflow.com/a/30741042) 15 | extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString); 16 | 17 | namespace spdlog { 18 | namespace sinks { 19 | /* 20 | * MSVC sink (logging using OutputDebugStringA) 21 | */ 22 | template 23 | class msvc_sink : public base_sink 24 | { 25 | public: 26 | msvc_sink() = default; 27 | 28 | protected: 29 | void sink_it_(const details::log_msg &msg) override 30 | { 31 | memory_buf_t formatted; 32 | base_sink::formatter_->format(msg, formatted); 33 | # ifdef SPDLOG_USE_STD_FORMAT 34 | OutputDebugStringA(formatted.c_str()); 35 | # else 36 | OutputDebugStringA(fmt::to_string(formatted).c_str()); 37 | # endif 38 | } 39 | 40 | void flush_() override {} 41 | }; 42 | 43 | using msvc_sink_mt = msvc_sink; 44 | using msvc_sink_st = msvc_sink; 45 | 46 | using windebug_sink_mt = msvc_sink_mt; 47 | using windebug_sink_st = msvc_sink_st; 48 | 49 | } // namespace sinks 50 | } // namespace spdlog 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/null_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | 15 | template 16 | class null_sink : public base_sink 17 | { 18 | protected: 19 | void sink_it_(const details::log_msg &) override {} 20 | void flush_() override {} 21 | }; 22 | 23 | using null_sink_mt = null_sink; 24 | using null_sink_st = null_sink; 25 | 26 | } // namespace sinks 27 | 28 | template 29 | inline std::shared_ptr null_logger_mt(const std::string &logger_name) 30 | { 31 | auto null_logger = Factory::template create(logger_name); 32 | null_logger->set_level(level::off); 33 | return null_logger; 34 | } 35 | 36 | template 37 | inline std::shared_ptr null_logger_st(const std::string &logger_name) 38 | { 39 | auto null_logger = Factory::template create(logger_name); 40 | null_logger->set_level(level::off); 41 | return null_logger; 42 | } 43 | 44 | } // namespace spdlog 45 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/ostream_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace spdlog { 13 | namespace sinks { 14 | template 15 | class ostream_sink final : public base_sink 16 | { 17 | public: 18 | explicit ostream_sink(std::ostream &os, bool force_flush = false) 19 | : ostream_(os) 20 | , force_flush_(force_flush) 21 | {} 22 | ostream_sink(const ostream_sink &) = delete; 23 | ostream_sink &operator=(const ostream_sink &) = delete; 24 | 25 | protected: 26 | void sink_it_(const details::log_msg &msg) override 27 | { 28 | memory_buf_t formatted; 29 | base_sink::formatter_->format(msg, formatted); 30 | ostream_.write(formatted.data(), static_cast(formatted.size())); 31 | if (force_flush_) 32 | { 33 | ostream_.flush(); 34 | } 35 | } 36 | 37 | void flush_() override 38 | { 39 | ostream_.flush(); 40 | } 41 | 42 | std::ostream &ostream_; 43 | bool force_flush_; 44 | }; 45 | 46 | using ostream_sink_mt = ostream_sink; 47 | using ostream_sink_st = ostream_sink; 48 | 49 | } // namespace sinks 50 | } // namespace spdlog 51 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/ringbuffer_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include "spdlog/sinks/base_sink.h" 7 | #include "spdlog/details/circular_q.h" 8 | #include "spdlog/details/log_msg_buffer.h" 9 | #include "spdlog/details/null_mutex.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog { 16 | namespace sinks { 17 | /* 18 | * Ring buffer sink 19 | */ 20 | template 21 | class ringbuffer_sink final : public base_sink 22 | { 23 | public: 24 | explicit ringbuffer_sink(size_t n_items) 25 | : q_{n_items} 26 | {} 27 | 28 | std::vector last_raw(size_t lim = 0) 29 | { 30 | std::lock_guard lock(base_sink::mutex_); 31 | auto items_available = q_.size(); 32 | auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; 33 | std::vector ret; 34 | ret.reserve(n_items); 35 | for (size_t i = (items_available - n_items); i < items_available; i++) 36 | { 37 | ret.push_back(q_.at(i)); 38 | } 39 | return ret; 40 | } 41 | 42 | std::vector last_formatted(size_t lim = 0) 43 | { 44 | std::lock_guard lock(base_sink::mutex_); 45 | auto items_available = q_.size(); 46 | auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; 47 | std::vector ret; 48 | ret.reserve(n_items); 49 | for (size_t i = (items_available - n_items); i < items_available; i++) 50 | { 51 | memory_buf_t formatted; 52 | base_sink::formatter_->format(q_.at(i), formatted); 53 | #ifdef SPDLOG_USE_STD_FORMAT 54 | ret.push_back(std::move(formatted)); 55 | #else 56 | ret.push_back(fmt::to_string(formatted)); 57 | #endif 58 | } 59 | return ret; 60 | } 61 | 62 | protected: 63 | void sink_it_(const details::log_msg &msg) override 64 | { 65 | q_.push_back(details::log_msg_buffer{msg}); 66 | } 67 | void flush_() override {} 68 | 69 | private: 70 | details::circular_q q_; 71 | }; 72 | 73 | using ringbuffer_sink_mt = ringbuffer_sink; 74 | using ringbuffer_sink_st = ringbuffer_sink; 75 | 76 | } // namespace sinks 77 | 78 | } // namespace spdlog 79 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/rotating_file_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog { 16 | namespace sinks { 17 | 18 | // 19 | // Rotating file sink based on size 20 | // 21 | template 22 | class rotating_file_sink final : public base_sink 23 | { 24 | public: 25 | rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false, 26 | const file_event_handlers &event_handlers = {}); 27 | static filename_t calc_filename(const filename_t &filename, std::size_t index); 28 | filename_t filename(); 29 | 30 | protected: 31 | void sink_it_(const details::log_msg &msg) override; 32 | void flush_() override; 33 | 34 | private: 35 | // Rotate files: 36 | // log.txt -> log.1.txt 37 | // log.1.txt -> log.2.txt 38 | // log.2.txt -> log.3.txt 39 | // log.3.txt -> delete 40 | void rotate_(); 41 | 42 | // delete the target if exists, and rename the src file to target 43 | // return true on success, false otherwise. 44 | bool rename_file_(const filename_t &src_filename, const filename_t &target_filename); 45 | 46 | filename_t base_filename_; 47 | std::size_t max_size_; 48 | std::size_t max_files_; 49 | std::size_t current_size_; 50 | details::file_helper file_helper_; 51 | }; 52 | 53 | using rotating_file_sink_mt = rotating_file_sink; 54 | using rotating_file_sink_st = rotating_file_sink; 55 | 56 | } // namespace sinks 57 | 58 | // 59 | // factory functions 60 | // 61 | 62 | template 63 | inline std::shared_ptr rotating_logger_mt(const std::string &logger_name, const filename_t &filename, size_t max_file_size, 64 | size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {}) 65 | { 66 | return Factory::template create( 67 | logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); 68 | } 69 | 70 | template 71 | inline std::shared_ptr rotating_logger_st(const std::string &logger_name, const filename_t &filename, size_t max_file_size, 72 | size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {}) 73 | { 74 | return Factory::template create( 75 | logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); 76 | } 77 | } // namespace spdlog 78 | 79 | #ifdef SPDLOG_HEADER_ONLY 80 | # include "rotating_file_sink-inl.h" 81 | #endif 82 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/sink-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | 12 | SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const 13 | { 14 | return msg_level >= level_.load(std::memory_order_relaxed); 15 | } 16 | 17 | SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) 18 | { 19 | level_.store(log_level, std::memory_order_relaxed); 20 | } 21 | 22 | SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const 23 | { 24 | return static_cast(level_.load(std::memory_order_relaxed)); 25 | } 26 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | namespace spdlog { 10 | 11 | namespace sinks { 12 | class SPDLOG_API sink 13 | { 14 | public: 15 | virtual ~sink() = default; 16 | virtual void log(const details::log_msg &msg) = 0; 17 | virtual void flush() = 0; 18 | virtual void set_pattern(const std::string &pattern) = 0; 19 | virtual void set_formatter(std::unique_ptr sink_formatter) = 0; 20 | 21 | void set_level(level::level_enum log_level); 22 | level::level_enum level() const; 23 | bool should_log(level::level_enum msg_level) const; 24 | 25 | protected: 26 | // sink log level - default is all 27 | level_t level_{level::trace}; 28 | }; 29 | 30 | } // namespace sinks 31 | } // namespace spdlog 32 | 33 | #ifdef SPDLOG_HEADER_ONLY 34 | # include "sink-inl.h" 35 | #endif 36 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/stdout_color_sinks-inl.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifndef SPDLOG_HEADER_ONLY 7 | # include 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | namespace spdlog { 14 | 15 | template 16 | SPDLOG_INLINE std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode) 17 | { 18 | return Factory::template create(logger_name, mode); 19 | } 20 | 21 | template 22 | SPDLOG_INLINE std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode) 23 | { 24 | return Factory::template create(logger_name, mode); 25 | } 26 | 27 | template 28 | SPDLOG_INLINE std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode) 29 | { 30 | return Factory::template create(logger_name, mode); 31 | } 32 | 33 | template 34 | SPDLOG_INLINE std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode) 35 | { 36 | return Factory::template create(logger_name, mode); 37 | } 38 | } // namespace spdlog 39 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/stdout_color_sinks.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #ifdef _WIN32 7 | # include 8 | #else 9 | # include 10 | #endif 11 | 12 | #include 13 | 14 | namespace spdlog { 15 | namespace sinks { 16 | #ifdef _WIN32 17 | using stdout_color_sink_mt = wincolor_stdout_sink_mt; 18 | using stdout_color_sink_st = wincolor_stdout_sink_st; 19 | using stderr_color_sink_mt = wincolor_stderr_sink_mt; 20 | using stderr_color_sink_st = wincolor_stderr_sink_st; 21 | #else 22 | using stdout_color_sink_mt = ansicolor_stdout_sink_mt; 23 | using stdout_color_sink_st = ansicolor_stdout_sink_st; 24 | using stderr_color_sink_mt = ansicolor_stderr_sink_mt; 25 | using stderr_color_sink_st = ansicolor_stderr_sink_st; 26 | #endif 27 | } // namespace sinks 28 | 29 | template 30 | std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); 31 | 32 | template 33 | std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); 34 | 35 | template 36 | std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); 37 | 38 | template 39 | std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); 40 | 41 | } // namespace spdlog 42 | 43 | #ifdef SPDLOG_HEADER_ONLY 44 | # include "stdout_color_sinks-inl.h" 45 | #endif 46 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/stdout_sinks.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef _WIN32 12 | # include 13 | #endif 14 | 15 | namespace spdlog { 16 | 17 | namespace sinks { 18 | 19 | template 20 | class stdout_sink_base : public sink 21 | { 22 | public: 23 | using mutex_t = typename ConsoleMutex::mutex_t; 24 | explicit stdout_sink_base(FILE *file); 25 | ~stdout_sink_base() override = default; 26 | 27 | stdout_sink_base(const stdout_sink_base &other) = delete; 28 | stdout_sink_base(stdout_sink_base &&other) = delete; 29 | 30 | stdout_sink_base &operator=(const stdout_sink_base &other) = delete; 31 | stdout_sink_base &operator=(stdout_sink_base &&other) = delete; 32 | 33 | void log(const details::log_msg &msg) override; 34 | void flush() override; 35 | void set_pattern(const std::string &pattern) override; 36 | 37 | void set_formatter(std::unique_ptr sink_formatter) override; 38 | 39 | protected: 40 | mutex_t &mutex_; 41 | FILE *file_; 42 | std::unique_ptr formatter_; 43 | #ifdef _WIN32 44 | HANDLE handle_; 45 | #endif // WIN32 46 | }; 47 | 48 | template 49 | class stdout_sink : public stdout_sink_base 50 | { 51 | public: 52 | stdout_sink(); 53 | }; 54 | 55 | template 56 | class stderr_sink : public stdout_sink_base 57 | { 58 | public: 59 | stderr_sink(); 60 | }; 61 | 62 | using stdout_sink_mt = stdout_sink; 63 | using stdout_sink_st = stdout_sink; 64 | 65 | using stderr_sink_mt = stderr_sink; 66 | using stderr_sink_st = stderr_sink; 67 | 68 | } // namespace sinks 69 | 70 | // factory methods 71 | template 72 | std::shared_ptr stdout_logger_mt(const std::string &logger_name); 73 | 74 | template 75 | std::shared_ptr stdout_logger_st(const std::string &logger_name); 76 | 77 | template 78 | std::shared_ptr stderr_logger_mt(const std::string &logger_name); 79 | 80 | template 81 | std::shared_ptr stderr_logger_st(const std::string &logger_name); 82 | 83 | } // namespace spdlog 84 | 85 | #ifdef SPDLOG_HEADER_ONLY 86 | # include "stdout_sinks-inl.h" 87 | #endif 88 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/tcp_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #ifdef _WIN32 10 | # include 11 | #else 12 | # include 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #pragma once 21 | 22 | // Simple tcp client sink 23 | // Connects to remote address and send the formatted log. 24 | // Will attempt to reconnect if connection drops. 25 | // If more complicated behaviour is needed (i.e get responses), you can inherit it and override the sink_it_ method. 26 | 27 | namespace spdlog { 28 | namespace sinks { 29 | 30 | struct tcp_sink_config 31 | { 32 | std::string server_host; 33 | int server_port; 34 | bool lazy_connect = false; // if true connect on first log call instead of on construction 35 | 36 | tcp_sink_config(std::string host, int port) 37 | : server_host{std::move(host)} 38 | , server_port{port} 39 | {} 40 | }; 41 | 42 | template 43 | class tcp_sink : public spdlog::sinks::base_sink 44 | { 45 | public: 46 | // connect to tcp host/port or throw if failed 47 | // host can be hostname or ip address 48 | 49 | explicit tcp_sink(tcp_sink_config sink_config) 50 | : config_{std::move(sink_config)} 51 | { 52 | if (!config_.lazy_connect) 53 | { 54 | this->client_.connect(config_.server_host, config_.server_port); 55 | } 56 | } 57 | 58 | ~tcp_sink() override = default; 59 | 60 | protected: 61 | void sink_it_(const spdlog::details::log_msg &msg) override 62 | { 63 | spdlog::memory_buf_t formatted; 64 | spdlog::sinks::base_sink::formatter_->format(msg, formatted); 65 | if (!client_.is_connected()) 66 | { 67 | client_.connect(config_.server_host, config_.server_port); 68 | } 69 | client_.send(formatted.data(), formatted.size()); 70 | } 71 | 72 | void flush_() override {} 73 | tcp_sink_config config_; 74 | details::tcp_client client_; 75 | }; 76 | 77 | using tcp_sink_mt = tcp_sink; 78 | using tcp_sink_st = tcp_sink; 79 | 80 | } // namespace sinks 81 | } // namespace spdlog 82 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/udp_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #ifdef _WIN32 10 | # include 11 | #else 12 | # include 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // Simple udp client sink 21 | // Sends formatted log via udp 22 | 23 | namespace spdlog { 24 | namespace sinks { 25 | 26 | struct udp_sink_config 27 | { 28 | std::string server_host; 29 | uint16_t server_port; 30 | 31 | udp_sink_config(std::string host, uint16_t port) 32 | : server_host{std::move(host)} 33 | , server_port{port} 34 | {} 35 | }; 36 | 37 | template 38 | class udp_sink : public spdlog::sinks::base_sink 39 | { 40 | public: 41 | // host can be hostname or ip address 42 | explicit udp_sink(udp_sink_config sink_config) 43 | : client_{sink_config.server_host, sink_config.server_port} 44 | {} 45 | 46 | ~udp_sink() override = default; 47 | 48 | protected: 49 | void sink_it_(const spdlog::details::log_msg &msg) override 50 | { 51 | spdlog::memory_buf_t formatted; 52 | spdlog::sinks::base_sink::formatter_->format(msg, formatted); 53 | client_.send(formatted.data(), formatted.size()); 54 | } 55 | 56 | void flush_() override {} 57 | details::udp_client client_; 58 | }; 59 | 60 | using udp_sink_mt = udp_sink; 61 | using udp_sink_st = udp_sink; 62 | 63 | } // namespace sinks 64 | 65 | // 66 | // factory functions 67 | // 68 | template 69 | inline std::shared_ptr udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config) 70 | { 71 | return Factory::template create(logger_name, skin_config); 72 | } 73 | 74 | } // namespace spdlog 75 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/sinks/wincolor_sink.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace spdlog { 18 | namespace sinks { 19 | /* 20 | * Windows color console sink. Uses WriteConsoleA to write to the console with 21 | * colors 22 | */ 23 | template 24 | class wincolor_sink : public sink 25 | { 26 | public: 27 | wincolor_sink(void *out_handle, color_mode mode); 28 | ~wincolor_sink() override; 29 | 30 | wincolor_sink(const wincolor_sink &other) = delete; 31 | wincolor_sink &operator=(const wincolor_sink &other) = delete; 32 | 33 | // change the color for the given level 34 | void set_color(level::level_enum level, std::uint16_t color); 35 | void log(const details::log_msg &msg) final override; 36 | void flush() final override; 37 | void set_pattern(const std::string &pattern) override final; 38 | void set_formatter(std::unique_ptr sink_formatter) override final; 39 | void set_color_mode(color_mode mode); 40 | 41 | protected: 42 | using mutex_t = typename ConsoleMutex::mutex_t; 43 | void *out_handle_; 44 | mutex_t &mutex_; 45 | bool should_do_colors_; 46 | std::unique_ptr formatter_; 47 | std::array colors_; 48 | 49 | // set foreground color and return the orig console attributes (for resetting later) 50 | std::uint16_t set_foreground_color_(std::uint16_t attribs); 51 | 52 | // print a range of formatted message to console 53 | void print_range_(const memory_buf_t &formatted, size_t start, size_t end); 54 | 55 | // in case we are redirected to file (not in console mode) 56 | void write_to_file_(const memory_buf_t &formatted); 57 | 58 | void set_color_mode_impl(color_mode mode); 59 | }; 60 | 61 | template 62 | class wincolor_stdout_sink : public wincolor_sink 63 | { 64 | public: 65 | explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic); 66 | }; 67 | 68 | template 69 | class wincolor_stderr_sink : public wincolor_sink 70 | { 71 | public: 72 | explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic); 73 | }; 74 | 75 | using wincolor_stdout_sink_mt = wincolor_stdout_sink; 76 | using wincolor_stdout_sink_st = wincolor_stdout_sink; 77 | 78 | using wincolor_stderr_sink_mt = wincolor_stderr_sink; 79 | using wincolor_stderr_sink_st = wincolor_stderr_sink; 80 | } // namespace sinks 81 | } // namespace spdlog 82 | 83 | #ifdef SPDLOG_HEADER_ONLY 84 | # include "wincolor_sink-inl.h" 85 | #endif 86 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/stopwatch.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | // Stopwatch support for spdlog (using std::chrono::steady_clock). 9 | // Displays elapsed seconds since construction as double. 10 | // 11 | // Usage: 12 | // 13 | // spdlog::stopwatch sw; 14 | // ... 15 | // spdlog::debug("Elapsed: {} seconds", sw); => "Elapsed 0.005116733 seconds" 16 | // spdlog::info("Elapsed: {:.6} seconds", sw); => "Elapsed 0.005163 seconds" 17 | // 18 | // 19 | // If other units are needed (e.g. millis instead of double), include "fmt/chrono.h" and use "duration_cast<..>(sw.elapsed())": 20 | // 21 | // #include 22 | //.. 23 | // using std::chrono::duration_cast; 24 | // using std::chrono::milliseconds; 25 | // spdlog::info("Elapsed {}", duration_cast(sw.elapsed())); => "Elapsed 5ms" 26 | 27 | namespace spdlog { 28 | class stopwatch 29 | { 30 | using clock = std::chrono::steady_clock; 31 | std::chrono::time_point start_tp_; 32 | 33 | public: 34 | stopwatch() 35 | : start_tp_{clock::now()} 36 | {} 37 | 38 | std::chrono::duration elapsed() const 39 | { 40 | return std::chrono::duration(clock::now() - start_tp_); 41 | } 42 | 43 | void reset() 44 | { 45 | start_tp_ = clock::now(); 46 | } 47 | }; 48 | } // namespace spdlog 49 | 50 | // Support for fmt formatting (e.g. "{:012.9}" or just "{}") 51 | namespace 52 | #ifdef SPDLOG_USE_STD_FORMAT 53 | std 54 | #else 55 | fmt 56 | #endif 57 | { 58 | 59 | template<> 60 | struct formatter : formatter 61 | { 62 | template 63 | auto format(const spdlog::stopwatch &sw, FormatContext &ctx) -> decltype(ctx.out()) 64 | { 65 | return formatter::format(sw.elapsed().count(), ctx); 66 | } 67 | }; 68 | } // namespace std 69 | -------------------------------------------------------------------------------- /third_party/spdlog/include/spdlog/version.h: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #pragma once 5 | 6 | #define SPDLOG_VER_MAJOR 1 7 | #define SPDLOG_VER_MINOR 9 8 | #define SPDLOG_VER_PATCH 2 9 | 10 | #define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) 11 | -------------------------------------------------------------------------------- /third_party/spdlog/scripts/extract_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import re 5 | 6 | base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) 7 | config_h = os.path.join(base_path, 'include', 'spdlog', 'version.h') 8 | data = {'MAJOR': 0, 'MINOR': 0, 'PATCH': 0} 9 | reg = re.compile(r'^\s*#define\s+SPDLOG_VER_([A-Z]+)\s+([0-9]+).*$') 10 | 11 | with open(config_h, 'r') as fp: 12 | for l in fp: 13 | m = reg.match(l) 14 | if m: 15 | data[m.group(1)] = int(m.group(2)) 16 | 17 | print(f"{data['MAJOR']}.{data['MINOR']}.{data['PATCH']}") 18 | -------------------------------------------------------------------------------- /third_party/spdlog/scripts/format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")"/.. 4 | pwd 5 | echo -n "Running dos2unix " 6 | find . -name "*\.h" -o -name "*\.cpp"|grep -v bundled|xargs -I {} sh -c "dos2unix '{}' 2>/dev/null; echo -n '.'" 7 | echo 8 | echo -n "Running clang-format " 9 | find . -name "*\.h" -o -name "*\.cpp"|grep -v bundled|xargs -I {} sh -c "clang-format -i {}; echo -n '.'" 10 | echo 11 | echo -n "Running cmake-format " 12 | find . -name "CMakeLists.txt" -o -name "*\.cmake"|grep -v bundled|xargs -I {} sh -c "cmake-format --line-width 120 --tab-size 4 --max-subgroups-hwrap 4 -i {}; echo -n '.'" 13 | echo 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /third_party/spdlog/src/async.cpp: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #ifndef SPDLOG_COMPILED_LIB 5 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | template class SPDLOG_API spdlog::details::mpmc_blocking_queue; 14 | -------------------------------------------------------------------------------- /third_party/spdlog/src/cfg.cpp: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #ifndef SPDLOG_COMPILED_LIB 5 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 6 | #endif 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /third_party/spdlog/src/color_sinks.cpp: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #ifndef SPDLOG_COMPILED_LIB 5 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 6 | #endif 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | // 13 | // color sinks 14 | // 15 | #ifdef _WIN32 16 | # include 17 | template class SPDLOG_API spdlog::sinks::wincolor_sink; 18 | template class SPDLOG_API spdlog::sinks::wincolor_sink; 19 | template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink; 20 | template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink; 21 | template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink; 22 | template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink; 23 | #else 24 | # include "spdlog/sinks/ansicolor_sink-inl.h" 25 | template class SPDLOG_API spdlog::sinks::ansicolor_sink; 26 | template class SPDLOG_API spdlog::sinks::ansicolor_sink; 27 | template class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink; 28 | template class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink; 29 | template class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink; 30 | template class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink; 31 | #endif 32 | 33 | // factory methods for color loggers 34 | #include "spdlog/sinks/stdout_color_sinks-inl.h" 35 | template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( 36 | const std::string &logger_name, color_mode mode); 37 | template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( 38 | const std::string &logger_name, color_mode mode); 39 | template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( 40 | const std::string &logger_name, color_mode mode); 41 | template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( 42 | const std::string &logger_name, color_mode mode); 43 | 44 | template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( 45 | const std::string &logger_name, color_mode mode); 46 | template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( 47 | const std::string &logger_name, color_mode mode); 48 | template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( 49 | const std::string &logger_name, color_mode mode); 50 | template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( 51 | const std::string &logger_name, color_mode mode); 52 | -------------------------------------------------------------------------------- /third_party/spdlog/src/file_sinks.cpp: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #ifndef SPDLOG_COMPILED_LIB 5 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | template class SPDLOG_API spdlog::sinks::basic_file_sink; 16 | template class SPDLOG_API spdlog::sinks::basic_file_sink; 17 | 18 | #include 19 | template class SPDLOG_API spdlog::sinks::rotating_file_sink; 20 | template class SPDLOG_API spdlog::sinks::rotating_file_sink; 21 | -------------------------------------------------------------------------------- /third_party/spdlog/src/fmt.cpp: -------------------------------------------------------------------------------- 1 | // Slightly modified version of fmt lib's format.cc source file. 2 | // Copyright (c) 2012 - 2016, Victor Zverovich 3 | // All rights reserved. 4 | 5 | #ifndef SPDLOG_COMPILED_LIB 6 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 7 | #endif 8 | 9 | #if !defined(SPDLOG_FMT_EXTERNAL) && !defined(SPDLOG_USE_STD_FORMAT) 10 | # include 11 | 12 | FMT_BEGIN_NAMESPACE 13 | namespace detail { 14 | 15 | template 16 | int format_float(char *buf, std::size_t size, const char *format, int precision, T value) 17 | { 18 | # ifdef FMT_FUZZ 19 | if (precision > 100000) 20 | throw std::runtime_error("fuzz mode - avoid large allocation inside snprintf"); 21 | # endif 22 | // Suppress the warning about nonliteral format string. 23 | int (*snprintf_ptr)(char *, size_t, const char *, ...) = FMT_SNPRINTF; 24 | return precision < 0 ? snprintf_ptr(buf, size, format, value) : snprintf_ptr(buf, size, format, precision, value); 25 | } 26 | 27 | template FMT_API dragonbox::decimal_fp dragonbox::to_decimal(float x) FMT_NOEXCEPT; 28 | template FMT_API dragonbox::decimal_fp dragonbox::to_decimal(double x) FMT_NOEXCEPT; 29 | } // namespace detail 30 | 31 | // Workaround a bug in MSVC2013 that prevents instantiation of format_float. 32 | int (*instantiate_format_float)(double, int, detail::float_specs, detail::buffer &) = detail::format_float; 33 | 34 | # ifndef FMT_STATIC_THOUSANDS_SEPARATOR 35 | template FMT_API detail::locale_ref::locale_ref(const std::locale &loc); 36 | template FMT_API std::locale detail::locale_ref::get() const; 37 | # endif 38 | 39 | // Explicit instantiations for char. 40 | 41 | template FMT_API auto detail::thousands_sep_impl(locale_ref) -> thousands_sep_result; 42 | template FMT_API char detail::decimal_point_impl(locale_ref); 43 | 44 | template FMT_API void detail::buffer::append(const char *, const char *); 45 | 46 | // DEPRECATED! 47 | // There is no correspondent extern template in format.h because of 48 | // incompatibility between clang and gcc (#2377). 49 | template FMT_API void detail::vformat_to( 50 | detail::buffer &, string_view, basic_format_args, detail::locale_ref); 51 | 52 | template FMT_API int detail::snprintf_float(double, int, detail::float_specs, detail::buffer &); 53 | template FMT_API int detail::snprintf_float(long double, int, detail::float_specs, detail::buffer &); 54 | template FMT_API int detail::format_float(double, int, detail::float_specs, detail::buffer &); 55 | template FMT_API int detail::format_float(long double, int, detail::float_specs, detail::buffer &); 56 | 57 | // Explicit instantiations for wchar_t. 58 | 59 | template FMT_API auto detail::thousands_sep_impl(locale_ref) -> thousands_sep_result; 60 | template FMT_API wchar_t detail::decimal_point_impl(locale_ref); 61 | 62 | template FMT_API void detail::buffer::append(const wchar_t *, const wchar_t *); 63 | 64 | template struct detail::basic_data; 65 | 66 | FMT_END_NAMESPACE 67 | 68 | #endif // !SPDLOG_FMT_EXTERNAL 69 | -------------------------------------------------------------------------------- /third_party/spdlog/src/spdlog.cpp: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #ifndef SPDLOG_COMPILED_LIB 5 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | // template instantiate logger constructor with sinks init list 24 | template SPDLOG_API spdlog::logger::logger(std::string name, sinks_init_list::iterator begin, sinks_init_list::iterator end); 25 | template class SPDLOG_API spdlog::sinks::base_sink; 26 | template class SPDLOG_API spdlog::sinks::base_sink; 27 | -------------------------------------------------------------------------------- /third_party/spdlog/src/stdout_sinks.cpp: -------------------------------------------------------------------------------- 1 | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. 2 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 3 | 4 | #ifndef SPDLOG_COMPILED_LIB 5 | # error Please define SPDLOG_COMPILED_LIB to compile this file. 6 | #endif 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | template class SPDLOG_API spdlog::sinks::stdout_sink_base; 15 | template class SPDLOG_API spdlog::sinks::stdout_sink_base; 16 | template class SPDLOG_API spdlog::sinks::stdout_sink; 17 | template class SPDLOG_API spdlog::sinks::stdout_sink; 18 | template class SPDLOG_API spdlog::sinks::stderr_sink; 19 | template class SPDLOG_API spdlog::sinks::stderr_sink; 20 | 21 | template SPDLOG_API std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); 22 | template SPDLOG_API std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); 23 | template SPDLOG_API std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); 24 | template SPDLOG_API std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); 25 | 26 | template SPDLOG_API std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); 27 | template SPDLOG_API std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); 28 | template SPDLOG_API std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); 29 | template SPDLOG_API std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); 30 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(spdlog_utests CXX) 3 | 4 | if(NOT TARGET spdlog) 5 | # Stand-alone build 6 | find_package(spdlog REQUIRED) 7 | endif() 8 | 9 | include(../cmake/utils.cmake) 10 | 11 | find_package(PkgConfig) 12 | if(PkgConfig_FOUND) 13 | pkg_check_modules(systemd libsystemd) 14 | endif() 15 | 16 | set(SPDLOG_UTESTS_SOURCES 17 | test_file_helper.cpp 18 | test_file_logging.cpp 19 | test_daily_logger.cpp 20 | test_misc.cpp 21 | test_eventlog.cpp 22 | test_pattern_formatter.cpp 23 | test_async.cpp 24 | test_registry.cpp 25 | test_macros.cpp 26 | utils.cpp 27 | main.cpp 28 | test_mpmc_q.cpp 29 | test_dup_filter.cpp 30 | test_fmt_helper.cpp 31 | test_stdout_api.cpp 32 | test_backtrace.cpp 33 | test_create_dir.cpp 34 | test_cfg.cpp 35 | test_time_point.cpp 36 | test_stopwatch.cpp) 37 | 38 | if(NOT SPDLOG_NO_EXCEPTIONS) 39 | list(APPEND SPDLOG_UTESTS_SOURCES test_errors.cpp) 40 | endif() 41 | 42 | if(systemd_FOUND) 43 | list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp) 44 | endif() 45 | 46 | enable_testing() 47 | 48 | function(spdlog_prepare_test test_target spdlog_lib) 49 | add_executable(${test_target} ${SPDLOG_UTESTS_SOURCES}) 50 | spdlog_enable_warnings(${test_target}) 51 | target_link_libraries(${test_target} PRIVATE ${spdlog_lib}) 52 | if(systemd_FOUND) 53 | target_link_libraries(${test_target} PRIVATE ${systemd_LIBRARIES}) 54 | endif() 55 | if(SPDLOG_SANITIZE_ADDRESS) 56 | spdlog_enable_sanitizer(${test_target}) 57 | endif() 58 | add_test(NAME ${test_target} COMMAND ${test_target}) 59 | set_tests_properties(${test_target} PROPERTIES RUN_SERIAL ON) 60 | endfunction() 61 | 62 | # The compiled library tests 63 | if(SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_ALL) 64 | spdlog_prepare_test(spdlog-utests spdlog::spdlog) 65 | endif() 66 | 67 | # The header-only library version tests 68 | if(SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL) 69 | spdlog_prepare_test(spdlog-utests-ho spdlog::spdlog_header_only) 70 | endif() 71 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/catch.license: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/includes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "catch.hpp" 4 | #include "utils.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG 17 | 18 | #include "spdlog/spdlog.h" 19 | #include "spdlog/async.h" 20 | #include "spdlog/sinks/basic_file_sink.h" 21 | #include "spdlog/sinks/daily_file_sink.h" 22 | #include "spdlog/sinks/null_sink.h" 23 | #include "spdlog/sinks/ostream_sink.h" 24 | #include "spdlog/sinks/rotating_file_sink.h" 25 | #include "spdlog/sinks/stdout_color_sinks.h" 26 | #include "spdlog/pattern_formatter.h" -------------------------------------------------------------------------------- /third_party/spdlog/tests/main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "catch.hpp" -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_backtrace.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "test_sink.h" 3 | #include "spdlog/async.h" 4 | 5 | TEST_CASE("bactrace1", "[bactrace]") 6 | { 7 | 8 | using spdlog::sinks::test_sink_st; 9 | auto test_sink = std::make_shared(); 10 | size_t backtrace_size = 5; 11 | 12 | spdlog::logger logger("test-backtrace", test_sink); 13 | logger.set_pattern("%v"); 14 | logger.enable_backtrace(backtrace_size); 15 | 16 | logger.info("info message"); 17 | for (int i = 0; i < 100; i++) 18 | logger.debug("debug message {}", i); 19 | 20 | REQUIRE(test_sink->lines().size() == 1); 21 | REQUIRE(test_sink->lines()[0] == "info message"); 22 | 23 | logger.dump_backtrace(); 24 | REQUIRE(test_sink->lines().size() == backtrace_size + 3); 25 | REQUIRE(test_sink->lines()[1] == "****************** Backtrace Start ******************"); 26 | REQUIRE(test_sink->lines()[2] == "debug message 95"); 27 | REQUIRE(test_sink->lines()[3] == "debug message 96"); 28 | REQUIRE(test_sink->lines()[4] == "debug message 97"); 29 | REQUIRE(test_sink->lines()[5] == "debug message 98"); 30 | REQUIRE(test_sink->lines()[6] == "debug message 99"); 31 | REQUIRE(test_sink->lines()[7] == "****************** Backtrace End ********************"); 32 | } 33 | 34 | TEST_CASE("bactrace-async", "[bactrace]") 35 | { 36 | using spdlog::sinks::test_sink_mt; 37 | auto test_sink = std::make_shared(); 38 | using spdlog::details::os::sleep_for_millis; 39 | 40 | size_t backtrace_size = 5; 41 | 42 | spdlog::init_thread_pool(120, 1); 43 | auto logger = std::make_shared("test-bactrace-async", test_sink, spdlog::thread_pool()); 44 | logger->set_pattern("%v"); 45 | logger->enable_backtrace(backtrace_size); 46 | 47 | logger->info("info message"); 48 | for (int i = 0; i < 100; i++) 49 | logger->debug("debug message {}", i); 50 | 51 | sleep_for_millis(100); 52 | REQUIRE(test_sink->lines().size() == 1); 53 | REQUIRE(test_sink->lines()[0] == "info message"); 54 | 55 | logger->dump_backtrace(); 56 | sleep_for_millis(100); // give time for the async dump to complete 57 | REQUIRE(test_sink->lines().size() == backtrace_size + 3); 58 | REQUIRE(test_sink->lines()[1] == "****************** Backtrace Start ******************"); 59 | REQUIRE(test_sink->lines()[2] == "debug message 95"); 60 | REQUIRE(test_sink->lines()[3] == "debug message 96"); 61 | REQUIRE(test_sink->lines()[4] == "debug message 97"); 62 | REQUIRE(test_sink->lines()[5] == "debug message 98"); 63 | REQUIRE(test_sink->lines()[6] == "debug message 99"); 64 | REQUIRE(test_sink->lines()[7] == "****************** Backtrace End ********************"); 65 | } 66 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_eventlog.cpp: -------------------------------------------------------------------------------- 1 | #if _WIN32 2 | 3 | # include "includes.h" 4 | # include "test_sink.h" 5 | 6 | # include "spdlog/sinks/win_eventlog_sink.h" 7 | 8 | static const LPCSTR TEST_SOURCE = "spdlog_test"; 9 | 10 | static void test_single_print(std::function do_log, std::string const &expected_contents, WORD expected_ev_type) 11 | { 12 | using namespace std::chrono; 13 | do_log(expected_contents); 14 | const auto expected_time_generated = duration_cast(system_clock::now().time_since_epoch()).count(); 15 | 16 | struct handle_t 17 | { 18 | HANDLE handle_; 19 | 20 | ~handle_t() 21 | { 22 | if (handle_) 23 | { 24 | REQUIRE(CloseEventLog(handle_)); 25 | } 26 | } 27 | } event_log{::OpenEventLogA(nullptr, TEST_SOURCE)}; 28 | 29 | REQUIRE(event_log.handle_); 30 | 31 | DWORD read_bytes{}, size_needed{}; 32 | auto ok = ::ReadEventLogA( 33 | event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, &read_bytes, 0, &read_bytes, &size_needed); 34 | REQUIRE(!ok); 35 | REQUIRE(::GetLastError() == ERROR_INSUFFICIENT_BUFFER); 36 | 37 | std::vector record_buffer(size_needed); 38 | PEVENTLOGRECORD record = (PEVENTLOGRECORD)record_buffer.data(); 39 | 40 | ok = ::ReadEventLogA( 41 | event_log.handle_, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, record, size_needed, &read_bytes, &size_needed); 42 | REQUIRE(ok); 43 | 44 | REQUIRE(record->NumStrings == 1); 45 | REQUIRE(record->EventType == expected_ev_type); 46 | REQUIRE((expected_time_generated - record->TimeGenerated) <= 3u); 47 | 48 | std::string message_in_log(((char *)record + record->StringOffset)); 49 | REQUIRE(message_in_log == expected_contents + spdlog::details::os::default_eol); 50 | } 51 | 52 | TEST_CASE("eventlog", "[eventlog]") 53 | { 54 | using namespace spdlog; 55 | 56 | auto test_sink = std::make_shared(TEST_SOURCE); 57 | 58 | spdlog::logger test_logger("eventlog", test_sink); 59 | test_logger.set_level(level::trace); 60 | 61 | test_sink->set_pattern("%v"); 62 | 63 | test_single_print([&test_logger](std::string const &msg) { test_logger.trace(msg); }, "my trace message", EVENTLOG_SUCCESS); 64 | test_single_print([&test_logger](std::string const &msg) { test_logger.debug(msg); }, "my debug message", EVENTLOG_SUCCESS); 65 | test_single_print([&test_logger](std::string const &msg) { test_logger.info(msg); }, "my info message", EVENTLOG_INFORMATION_TYPE); 66 | test_single_print([&test_logger](std::string const &msg) { test_logger.warn(msg); }, "my warn message", EVENTLOG_WARNING_TYPE); 67 | test_single_print([&test_logger](std::string const &msg) { test_logger.error(msg); }, "my error message", EVENTLOG_ERROR_TYPE); 68 | test_single_print([&test_logger](std::string const &msg) { test_logger.critical(msg); }, "my critical message", EVENTLOG_ERROR_TYPE); 69 | } 70 | 71 | #endif //_WIN32 72 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_fmt_helper.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "includes.h" 3 | #include "spdlog/details/fmt_helper.h" 4 | 5 | using spdlog::memory_buf_t; 6 | 7 | void test_pad2(int n, const char *expected) 8 | { 9 | memory_buf_t buf; 10 | spdlog::details::fmt_helper::pad2(n, buf); 11 | 12 | #ifdef SPDLOG_USE_STD_FORMAT 13 | REQUIRE(buf == expected); 14 | #else 15 | REQUIRE(fmt::to_string(buf) == expected); 16 | #endif 17 | } 18 | 19 | void test_pad3(uint32_t n, const char *expected) 20 | { 21 | memory_buf_t buf; 22 | spdlog::details::fmt_helper::pad3(n, buf); 23 | 24 | #ifdef SPDLOG_USE_STD_FORMAT 25 | REQUIRE(buf == expected); 26 | #else 27 | REQUIRE(fmt::to_string(buf) == expected); 28 | #endif 29 | } 30 | 31 | void test_pad6(std::size_t n, const char *expected) 32 | { 33 | memory_buf_t buf; 34 | spdlog::details::fmt_helper::pad6(n, buf); 35 | 36 | #ifdef SPDLOG_USE_STD_FORMAT 37 | REQUIRE(buf == expected); 38 | #else 39 | REQUIRE(fmt::to_string(buf) == expected); 40 | #endif 41 | } 42 | 43 | void test_pad9(std::size_t n, const char *expected) 44 | { 45 | memory_buf_t buf; 46 | spdlog::details::fmt_helper::pad9(n, buf); 47 | 48 | #ifdef SPDLOG_USE_STD_FORMAT 49 | REQUIRE(buf == expected); 50 | #else 51 | REQUIRE(fmt::to_string(buf) == expected); 52 | #endif 53 | } 54 | 55 | TEST_CASE("pad2", "[fmt_helper]") 56 | { 57 | test_pad2(0, "00"); 58 | test_pad2(3, "03"); 59 | test_pad2(10, "10"); 60 | test_pad2(23, "23"); 61 | test_pad2(99, "99"); 62 | test_pad2(100, "100"); 63 | test_pad2(123, "123"); 64 | test_pad2(1234, "1234"); 65 | test_pad2(-5, "-5"); 66 | } 67 | 68 | TEST_CASE("pad3", "[fmt_helper]") 69 | { 70 | test_pad3(0, "000"); 71 | test_pad3(3, "003"); 72 | test_pad3(10, "010"); 73 | test_pad3(23, "023"); 74 | test_pad3(99, "099"); 75 | test_pad3(100, "100"); 76 | test_pad3(123, "123"); 77 | test_pad3(999, "999"); 78 | test_pad3(1000, "1000"); 79 | test_pad3(1234, "1234"); 80 | } 81 | 82 | TEST_CASE("pad6", "[fmt_helper]") 83 | { 84 | test_pad6(0, "000000"); 85 | test_pad6(3, "000003"); 86 | test_pad6(23, "000023"); 87 | test_pad6(123, "000123"); 88 | test_pad6(1234, "001234"); 89 | test_pad6(12345, "012345"); 90 | test_pad6(123456, "123456"); 91 | } 92 | 93 | TEST_CASE("pad9", "[fmt_helper]") 94 | { 95 | test_pad9(0, "000000000"); 96 | test_pad9(3, "000000003"); 97 | test_pad9(23, "000000023"); 98 | test_pad9(123, "000000123"); 99 | test_pad9(1234, "000001234"); 100 | test_pad9(12345, "000012345"); 101 | test_pad9(123456, "000123456"); 102 | test_pad9(1234567, "001234567"); 103 | test_pad9(12345678, "012345678"); 104 | test_pad9(123456789, "123456789"); 105 | test_pad9(1234567891, "1234567891"); 106 | } 107 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_macros.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE 3 | */ 4 | 5 | #include "includes.h" 6 | 7 | #if SPDLOG_ACTIVE_LEVEL != SPDLOG_LEVEL_DEBUG 8 | # error "Invalid SPDLOG_ACTIVE_LEVEL in test. Should be SPDLOG_LEVEL_DEBUG" 9 | #endif 10 | 11 | #define TEST_FILENAME "test_logs/simple_log" 12 | 13 | TEST_CASE("debug and trace w/o format string", "[macros]]") 14 | { 15 | 16 | prepare_logdir(); 17 | spdlog::filename_t filename = SPDLOG_FILENAME_T(TEST_FILENAME); 18 | 19 | auto logger = spdlog::create("logger", filename); 20 | logger->set_pattern("%v"); 21 | logger->set_level(spdlog::level::trace); 22 | 23 | SPDLOG_LOGGER_TRACE(logger, "Test message 1"); 24 | SPDLOG_LOGGER_DEBUG(logger, "Test message 2"); 25 | logger->flush(); 26 | 27 | using spdlog::details::os::default_eol; 28 | REQUIRE(ends_with(file_contents(TEST_FILENAME), spdlog::fmt_lib::format("Test message 2{}", default_eol))); 29 | REQUIRE(count_lines(TEST_FILENAME) == 1); 30 | 31 | spdlog::set_default_logger(logger); 32 | 33 | SPDLOG_TRACE("Test message 3"); 34 | SPDLOG_DEBUG("Test message {}", 4); 35 | logger->flush(); 36 | 37 | require_message_count(TEST_FILENAME, 2); 38 | REQUIRE(ends_with(file_contents(TEST_FILENAME), spdlog::fmt_lib::format("Test message 4{}", default_eol))); 39 | } 40 | 41 | TEST_CASE("disable param evaluation", "[macros]") 42 | { 43 | SPDLOG_TRACE("Test message {}", throw std::runtime_error("Should not be evaluated")); 44 | } 45 | 46 | TEST_CASE("pass logger pointer", "[macros]") 47 | { 48 | auto logger = spdlog::create("refmacro"); 49 | auto &ref = *logger; 50 | SPDLOG_LOGGER_TRACE(&ref, "Test message 1"); 51 | SPDLOG_LOGGER_DEBUG(&ref, "Test message 2"); 52 | } 53 | 54 | // ensure that even if right macro level is on- don't evaluate if the logger's level is not high enough 55 | // TEST_CASE("disable param evaluation2", "[macros]") 56 | //{ 57 | // auto logger = std::make_shared("test-macro"); 58 | // logger->set_level(spdlog::level::off); 59 | // int x = 0; 60 | // SPDLOG_LOGGER_DEBUG(logger, "Test message {}", ++x); 61 | // REQUIRE(x == 0); 62 | //} 63 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_sink.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright(c) 2018 Gabi Melman. 3 | // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 | // 5 | 6 | #pragma once 7 | 8 | #include "spdlog/details/null_mutex.h" 9 | #include "spdlog/sinks/base_sink.h" 10 | #include "spdlog/fmt/fmt.h" 11 | #include 12 | #include 13 | #include 14 | 15 | namespace spdlog { 16 | namespace sinks { 17 | 18 | template 19 | class test_sink : public base_sink 20 | { 21 | const size_t lines_to_save = 100; 22 | 23 | public: 24 | size_t msg_counter() 25 | { 26 | std::lock_guard lock(base_sink::mutex_); 27 | return msg_counter_; 28 | } 29 | 30 | size_t flush_counter() 31 | { 32 | std::lock_guard lock(base_sink::mutex_); 33 | return flush_counter_; 34 | } 35 | 36 | void set_delay(std::chrono::milliseconds delay) 37 | { 38 | std::lock_guard lock(base_sink::mutex_); 39 | delay_ = delay; 40 | } 41 | 42 | // return last output without the eol 43 | std::vector lines() 44 | { 45 | std::lock_guard lock(base_sink::mutex_); 46 | return lines_; 47 | } 48 | 49 | protected: 50 | void sink_it_(const details::log_msg &msg) override 51 | { 52 | memory_buf_t formatted; 53 | base_sink::formatter_->format(msg, formatted); 54 | // save the line without the eol 55 | auto eol_len = strlen(details::os::default_eol); 56 | if (lines_.size() < lines_to_save) 57 | { 58 | lines_.emplace_back(formatted.begin(), formatted.end() - eol_len); 59 | } 60 | msg_counter_++; 61 | std::this_thread::sleep_for(delay_); 62 | } 63 | 64 | void flush_() override 65 | { 66 | flush_counter_++; 67 | } 68 | 69 | size_t msg_counter_{0}; 70 | size_t flush_counter_{0}; 71 | std::chrono::milliseconds delay_{std::chrono::milliseconds::zero()}; 72 | std::vector lines_; 73 | }; 74 | 75 | using test_sink_mt = test_sink; 76 | using test_sink_st = test_sink; 77 | 78 | } // namespace sinks 79 | } // namespace spdlog 80 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_stdout_api.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE 3 | */ 4 | #include "includes.h" 5 | #include "spdlog/sinks/stdout_sinks.h" 6 | #include "spdlog/sinks/stdout_color_sinks.h" 7 | TEST_CASE("stdout_st", "[stdout]") 8 | { 9 | auto l = spdlog::stdout_logger_st("test"); 10 | l->set_pattern("%+"); 11 | l->set_level(spdlog::level::trace); 12 | l->trace("Test stdout_st"); 13 | spdlog::drop_all(); 14 | } 15 | 16 | TEST_CASE("stdout_mt", "[stdout]") 17 | { 18 | auto l = spdlog::stdout_logger_mt("test"); 19 | l->set_pattern("%+"); 20 | l->set_level(spdlog::level::debug); 21 | l->debug("Test stdout_mt"); 22 | spdlog::drop_all(); 23 | } 24 | 25 | TEST_CASE("stderr_st", "[stderr]") 26 | { 27 | auto l = spdlog::stderr_logger_st("test"); 28 | l->set_pattern("%+"); 29 | l->info("Test stderr_st"); 30 | spdlog::drop_all(); 31 | } 32 | 33 | TEST_CASE("stderr_mt", "[stderr]") 34 | { 35 | auto l = spdlog::stderr_logger_mt("test"); 36 | l->set_pattern("%+"); 37 | l->info("Test stderr_mt"); 38 | l->warn("Test stderr_mt"); 39 | l->error("Test stderr_mt"); 40 | l->critical("Test stderr_mt"); 41 | spdlog::drop_all(); 42 | } 43 | 44 | // color loggers 45 | TEST_CASE("stdout_color_st", "[stdout]") 46 | { 47 | auto l = spdlog::stdout_color_st("test"); 48 | l->set_pattern("%+"); 49 | l->info("Test stdout_color_st"); 50 | spdlog::drop_all(); 51 | } 52 | 53 | TEST_CASE("stdout_color_mt", "[stdout]") 54 | { 55 | auto l = spdlog::stdout_color_mt("test"); 56 | l->set_pattern("%+"); 57 | l->set_level(spdlog::level::trace); 58 | l->trace("Test stdout_color_mt"); 59 | spdlog::drop_all(); 60 | } 61 | 62 | TEST_CASE("stderr_color_st", "[stderr]") 63 | { 64 | auto l = spdlog::stderr_color_st("test"); 65 | l->set_pattern("%+"); 66 | l->set_level(spdlog::level::debug); 67 | l->debug("Test stderr_color_st"); 68 | spdlog::drop_all(); 69 | } 70 | 71 | TEST_CASE("stderr_color_mt", "[stderr]") 72 | { 73 | auto l = spdlog::stderr_color_mt("test"); 74 | l->set_pattern("%+"); 75 | l->info("Test stderr_color_mt"); 76 | l->warn("Test stderr_color_mt"); 77 | l->error("Test stderr_color_mt"); 78 | l->critical("Test stderr_color_mt"); 79 | spdlog::drop_all(); 80 | } 81 | 82 | #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT 83 | 84 | TEST_CASE("wchar_api", "[stdout]") 85 | { 86 | auto l = spdlog::stdout_logger_st("wchar_logger"); 87 | l->set_pattern("%+"); 88 | l->set_level(spdlog::level::trace); 89 | l->trace(L"Test wchar_api"); 90 | l->trace(L"Test wchar_api {}", L"param"); 91 | l->trace(L"Test wchar_api {}", 1); 92 | l->trace(L"Test wchar_api {}", std::wstring{L"wstring param"}); 93 | l->trace(std::wstring{L"Test wchar_api wstring"}); 94 | SPDLOG_LOGGER_DEBUG(l, L"Test SPDLOG_LOGGER_DEBUG {}", L"param"); 95 | spdlog::drop_all(); 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_stopwatch.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "test_sink.h" 3 | #include "spdlog/stopwatch.h" 4 | 5 | TEST_CASE("stopwatch1", "[stopwatch]") 6 | { 7 | using std::chrono::milliseconds; 8 | milliseconds wait_ms(250); 9 | milliseconds tolerance_ms(250); 10 | 11 | spdlog::stopwatch sw; 12 | std::this_thread::sleep_for(wait_ms); 13 | REQUIRE(sw.elapsed() >= wait_ms); 14 | REQUIRE(sw.elapsed() <= wait_ms + tolerance_ms); 15 | } 16 | 17 | TEST_CASE("stopwatch2", "[stopwatch]") 18 | { 19 | using spdlog::sinks::test_sink_st; 20 | 21 | std::chrono::duration wait_duration(0.250); 22 | std::chrono::duration tolerance_duration(0.250); 23 | 24 | auto test_sink = std::make_shared(); 25 | 26 | spdlog::stopwatch sw; 27 | spdlog::logger logger("test-stopwatch", test_sink); 28 | logger.set_pattern("%v"); 29 | std::this_thread::sleep_for(wait_duration); 30 | logger.info("{}", sw); 31 | auto val = std::stod(test_sink->lines()[0]); 32 | 33 | REQUIRE(val >= wait_duration.count()); 34 | REQUIRE(val <= (wait_duration + tolerance_duration).count()); 35 | } 36 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_systemd.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "spdlog/sinks/systemd_sink.h" 3 | 4 | TEST_CASE("systemd", "[all]") 5 | { 6 | auto systemd_sink = std::make_shared(); 7 | spdlog::logger logger("spdlog_systemd_test", systemd_sink); 8 | logger.set_level(spdlog::level::trace); 9 | logger.trace("test spdlog trace"); 10 | logger.debug("test spdlog debug"); 11 | SPDLOG_LOGGER_INFO((&logger), "test spdlog info"); 12 | SPDLOG_LOGGER_WARN((&logger), "test spdlog warn"); 13 | SPDLOG_LOGGER_ERROR((&logger), "test spdlog error"); 14 | SPDLOG_LOGGER_CRITICAL((&logger), "test spdlog critical"); 15 | } 16 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/test_time_point.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "test_sink.h" 3 | #include "spdlog/async.h" 4 | 5 | TEST_CASE("time_point1", "[time_point log_msg]") 6 | { 7 | std::shared_ptr test_sink(new spdlog::sinks::test_sink_st); 8 | spdlog::logger logger("test-time_point", test_sink); 9 | 10 | spdlog::source_loc source{}; 11 | std::chrono::system_clock::time_point tp{std::chrono::system_clock::now()}; 12 | test_sink->set_pattern("%T.%F"); // interested in the time_point 13 | 14 | // all the following should have the same time 15 | test_sink->set_delay(std::chrono::milliseconds(10)); 16 | for (int i = 0; i < 5; i++) 17 | { 18 | spdlog::details::log_msg msg{tp, source, "test_logger", spdlog::level::info, "message"}; 19 | test_sink->log(msg); 20 | } 21 | 22 | logger.log(tp, source, spdlog::level::info, "formatted message"); 23 | logger.log(tp, source, spdlog::level::info, "formatted message"); 24 | logger.log(tp, source, spdlog::level::info, "formatted message"); 25 | logger.log(tp, source, spdlog::level::info, "formatted message"); 26 | logger.log(source, spdlog::level::info, "formatted message"); // last line has different time_point 27 | 28 | // now the real test... that the times are the same. 29 | std::vector lines = test_sink->lines(); 30 | REQUIRE(lines[0] == lines[1]); 31 | REQUIRE(lines[2] == lines[3]); 32 | REQUIRE(lines[4] == lines[5]); 33 | REQUIRE(lines[6] == lines[7]); 34 | REQUIRE(lines[8] != lines[9]); 35 | spdlog::drop_all(); 36 | } 37 | -------------------------------------------------------------------------------- /third_party/spdlog/tests/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | std::size_t count_files(const std::string &folder); 7 | 8 | void prepare_logdir(); 9 | 10 | std::string file_contents(const std::string &filename); 11 | 12 | std::size_t count_lines(const std::string &filename); 13 | 14 | void require_message_count(const std::string &filename, const std::size_t messages); 15 | 16 | std::size_t get_filesize(const std::string &filename); 17 | 18 | bool ends_with(std::string const &value, std::string const &ending); --------------------------------------------------------------------------------