From 21bf8f67c4c9be2c62756a1b4300974d11bdf914 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 23 May 2024 23:52:56 +0300 Subject: [PATCH 001/178] [EN-7587] Implement FetchDailyCandles sample --- CMakeLists.txt | 1 + samples/cpp/FetchDailyCandles/CMakeLists.txt | 56 +++++++++++++++++++ .../cpp/FetchDailyCandles/dxfeed.properties | 5 ++ samples/cpp/FetchDailyCandles/src/main.cpp | 56 +++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 samples/cpp/FetchDailyCandles/CMakeLists.txt create mode 100644 samples/cpp/FetchDailyCandles/dxfeed.properties create mode 100644 samples/cpp/FetchDailyCandles/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 16422d2ae..8152c3339 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -468,6 +468,7 @@ if (DXFCXX_BUILD_SAMPLES) add_subdirectory(samples/cpp/PrintQuoteEvents) add_subdirectory(samples/cpp/PublishProfiles) add_subdirectory(samples/cpp/DxFeedSample) + add_subdirectory(samples/cpp/FetchDailyCandles) add_subdirectory(samples/cpp/WriteTapeFile) add_subdirectory(samples/cpp/ConvertTapeFile) add_subdirectory(samples/cpp/DxFeedFileParser) diff --git a/samples/cpp/FetchDailyCandles/CMakeLists.txt b/samples/cpp/FetchDailyCandles/CMakeLists.txt new file mode 100644 index 000000000..e934ceab0 --- /dev/null +++ b/samples/cpp/FetchDailyCandles/CMakeLists.txt @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Devexperts LLC. +# SPDX-License-Identifier: MPL-2.0 + +cmake_minimum_required(VERSION 3.21) + +if (POLICY CMP0092) + cmake_policy(SET CMP0092 NEW) +endif () + +if (POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) +endif () + +project(FetchDailyCandles LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_C_STANDARD 11) +set(CXX_EXTENSIONS OFF) +set(C_EXTENSIONS OFF) + +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_MACOSX_RPATH ON) + set(CMAKE_SKIP_BUILD_RPATH ON) + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF) + set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) + set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path;@executable_path;@executable_path/../Frameworks") +elseif (UNIX) + set(CMAKE_SKIP_BUILD_RPATH ON) + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF) + set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN/../lib64:$ORIGIN/../lib:$ORIGIN") +endif () + +add_executable(${PROJECT_NAME} src/main.cpp) + +target_link_libraries(${PROJECT_NAME} PRIVATE dxfcxx::static) + +if (DXFCXX_FEATURE_STACKTRACE) + LinkStacktrace(${PROJECT_NAME}) +endif () + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + ${CMAKE_CURRENT_SOURCE_DIR}/dxfeed.properties + $) + +if (DXFCXX_INSTALL AND DXFCXX_INSTALL_SAMPLES) + install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}) + install(FILES "dxfeed.properties" DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}) + + if (WIN32) + install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}) + endif () +endif () \ No newline at end of file diff --git a/samples/cpp/FetchDailyCandles/dxfeed.properties b/samples/cpp/FetchDailyCandles/dxfeed.properties new file mode 100644 index 000000000..6d1f9e30b --- /dev/null +++ b/samples/cpp/FetchDailyCandles/dxfeed.properties @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Devexperts LLC. +# SPDX-License-Identifier: MPL-2.0 + +# Connection address for an endpoint with role Feed and OnDemandFeed. +dxfeed.address=demo.dxfeed.com:7300 diff --git a/samples/cpp/FetchDailyCandles/src/main.cpp b/samples/cpp/FetchDailyCandles/src/main.cpp new file mode 100644 index 000000000..9ef1f6726 --- /dev/null +++ b/samples/cpp/FetchDailyCandles/src/main.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +void fetchAndPrint(const dxfcpp::CandleSymbol &candleSymbol, std::int64_t toTime, std::int64_t fromTime) { + // Use default DXFeed instance for that data feed address is defined by dxfeed.properties file + // auto result = dxfcpp::DXFeed::getInstance() + // ->getTimeSeriesPromise(candleSymbol, fromTime, toTime) + // ->await(std::chrono::seconds(5)); + // + // for (auto candle : result) { + // std::cout << candle->toString(); + // } +} + +// Fetches last 20 days of candles for a specified symbol, prints them, and exits. +int main(int argc, char *argv[]) { + static const auto DAYS = 20; + + using namespace dxfcpp; + using namespace std::string_literals; + + try { + if (argc < 2) { + std::cout << R"( +Usage: +FetchDailyCandles + +Where: + baseSymbol - Is security symbol (e.g. IBM, AAPL, SPX etc.) +)"; + return 0; + } + + // Specified instrument name, for example AAPL, IBM, MSFT, etc. + auto baseSymbol = argv[1]; + + auto candleSymbol = CandleSymbol::valueOf(baseSymbol, CandlePeriod::DAY); + auto toTime = dxfcpp::now(); + auto fromTime = toTime - std::chrono::duration_cast(std::chrono::days(DAYS)).count(); + + std::cout << "Fetching last " << DAYS << " days of candles for " << baseSymbol << "\n"; + + fetchAndPrint(candleSymbol, toTime, fromTime); + } catch (const JavaException &e) { + std::cerr << e.what() << '\n'; + std::cerr << e.getStackTrace() << '\n'; + } catch (const GraalException &e) { + std::cerr << e.what() << '\n'; + std::cerr << e.getStackTrace() << '\n'; + } +} From 28d66167e8094e8696c1dc32f015e2cd40408c57 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 27 May 2024 02:28:25 +0300 Subject: [PATCH 002/178] [EN-7587] Implement FetchDailyCandles sample --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 79174fa86..d55754ae9 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -4,6 +4,7 @@ #pragma once #include "../internal/Conf.hpp" +#include "osub/ObservableSubscription.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) @@ -34,7 +35,7 @@ struct LastingEvent; /** * Subscription for a set of symbols and event types. */ -class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity { +class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableSubscription { friend struct DXFeed; std::unordered_set eventTypes_; From 77fe5b149a2cf80fe690c11a5354ed05ef4c12db Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 27 May 2024 18:10:55 +0300 Subject: [PATCH 003/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- CMakeLists.txt | 1 + .../api/DXFeedSubscription.hpp | 53 ++++++------ .../api/DXPublisherObservableSubscription.hpp | 2 +- .../ObservableSubscriptionChangeListener.hpp | 1 + .../api/IsolatedDXFeedSubscription.hpp | 81 +++++++++++++++++++ src/api/DXFeedSubscription.cpp | 38 ++++++++- src/api/DXPublisherObservableSubscription.cpp | 6 +- .../api/IsolatedDXFeedSubscription.cpp | 14 ++++ 8 files changed, 163 insertions(+), 33 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp create mode 100644 src/isolated/api/IsolatedDXFeedSubscription.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8152c3339..80efdc7fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,7 @@ set(dxFeedGraalCxxApi_Exceptions_Sources set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/IsolatedDXEndpoint.cpp + src/isolated/api/IsolatedDXFeedSubscription.cpp src/isolated/api/IsolatedDXPublisher.cpp src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index d55754ae9..9a3716154 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -35,17 +35,25 @@ struct LastingEvent; /** * Subscription for a set of symbols and event types. */ -class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableSubscription { +class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared, public ObservableSubscription { +public: + static constexpr std::size_t FAKE_CHANGE_LISTENER_ID{static_cast(-1)}; + +private: friend struct DXFeed; + inline static std::atomic lastChangeListenerId_{}; + std::unordered_set eventTypes_; JavaObjectHandle handle_; - std::mutex listenerMutex_{}; + std::mutex eventListenerMutex_{}; JavaObjectHandle eventListenerHandle_; SimpleHandler> &)> onEvent_{}; + std::unordered_map> changeListeners_; + std::recursive_mutex changeListenersMutex_{}; - explicit DXFeedSubscription(const EventTypeEnum &eventType); + DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); static JavaObjectHandle createSubscriptionHandleFromEventClassList(const std::unique_ptr &list); @@ -60,7 +68,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS { *iter } -> dxfcpp::ConvertibleTo; } #endif - DXFeedSubscription(EventTypeIt begin, EventTypeIt end) + DXFeedSubscription(LockExternalConstructionTag, EventTypeIt begin, EventTypeIt end) : eventTypes_(begin, end), handle_{}, eventListenerHandle_{}, onEvent_{} { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeedSubscription(eventTypes = " + namesToString(begin, end) + ")"); @@ -71,21 +79,21 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS handle_ = createSubscriptionHandleFromEventClassList(list); } - DXFeedSubscription(std::initializer_list eventTypes) - : DXFeedSubscription(eventTypes.begin(), eventTypes.end()) { + DXFeedSubscription(LockExternalConstructionTag tag, std::initializer_list eventTypes) + : DXFeedSubscription(tag, eventTypes.begin(), eventTypes.end()) { } template - explicit DXFeedSubscription(EventTypesCollection &&eventTypes) + explicit DXFeedSubscription(LockExternalConstructionTag tag, EventTypesCollection &&eventTypes) #if __cpp_concepts requires requires { { - DXFeedSubscription(std::begin(std::forward(eventTypes)), + DXFeedSubscription(tag, std::begin(std::forward(eventTypes)), std::end(std::forward(eventTypes))) }; } #endif - : DXFeedSubscription(std::begin(std::forward(eventTypes)), + : DXFeedSubscription(tag, std::begin(std::forward(eventTypes)), std::end(std::forward(eventTypes))) { } @@ -93,7 +101,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS void clearImpl() const noexcept; - bool isClosedImpl() const noexcept; + bool isClosedImpl() const; void addSymbolImpl(void *graalSymbol) const noexcept; @@ -142,7 +150,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); } - auto sub = std::shared_ptr(new DXFeedSubscription(eventType)); + auto sub = createShared(eventType); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -182,7 +190,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS Debugger::debug("DXFeedSubscription::create(eventTypes = " + namesToString(begin, end) + ")"); } - auto sub = std::shared_ptr(new DXFeedSubscription(begin, end)); + auto sub = createShared(begin, end); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -202,7 +210,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * @return The new detached subscription for the given collection of event types. */ static std::shared_ptr create(std::initializer_list eventTypes) { - auto sub = std::shared_ptr(new DXFeedSubscription(eventTypes)); + auto sub = createShared(eventTypes); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -230,8 +238,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS */ template static std::shared_ptr create(EventTypesCollection &&eventTypes) { - auto sub = - std::shared_ptr(new DXFeedSubscription(std::forward(eventTypes))); + auto sub = createShared(std::forward(eventTypes)); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -672,7 +679,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * * @see DXFeedSubscription::close() */ - bool isClosed() const noexcept { + bool isClosed() override { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::isClosed()"); } @@ -685,7 +692,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * * @return A set of subscribed event types. */ - const std::unordered_set &getEventTypes() const noexcept { + std::unordered_set getEventTypes() override { return eventTypes_; } @@ -697,7 +704,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * * @see DXFeedSubscription::getEventTypes() */ - bool containsEventType(const EventTypeEnum &eventType) const noexcept { + bool containsEventType(const EventTypeEnum &eventType) override { return eventTypes_.contains(eventType); } @@ -737,15 +744,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS template void setExecutor(Executor &&executor) noexcept; - template std::size_t addChangeListener(ChangeListener &&changeListener) noexcept; - - void removeChangeListener(std::size_t changeListenerId) noexcept; - - auto onSymbolsAdded() noexcept; - - auto onSymbolsRemoved() noexcept; + std::size_t addChangeListener(std::shared_ptr listener) override; - auto onSubscriptionClosed() noexcept; + void removeChangeListener(std::size_t changeListenerId) override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp index 01f5b5d36..756d941f7 100644 --- a/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp @@ -40,7 +40,7 @@ struct DXFCPP_EXPORT DXPublisherObservableSubscription : RequireMakeShared getEventTypes() override; bool containsEventType(const EventTypeEnum &eventType) override; std::size_t addChangeListener(std::shared_ptr listener) override; - void removeChangeListener(std::size_t id) override; + void removeChangeListener(std::size_t changeListenerId) override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp index d28974ebd..e04315a2e 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp @@ -8,6 +8,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../symbols/SymbolWrapper.hpp" +#include "../entity/SharedEntity.hpp" #include #include diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp new file mode 100644 index 000000000..adf9e64e6 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -0,0 +1,81 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include + +#include "../../api/DXFeedSubscription.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeedSubscription { + +/* +dxfg_subscription_t* dxfg_DXFeedSubscription_new(graal_isolatethread_t *thread, dxfg_event_clazz_t eventClazz); + +dxfg_subscription_t* dxfg_DXFeedSubscription_new2(graal_isolatethread_t *thread, dxfg_event_clazz_list_t *eventClazzes); + +int32_t dxfg_DXFeedSubscription_close(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_addEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); + +int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); + +int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); + +int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); + +int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_event_clazz_t eventClazz); + +dxfg_symbol_list* dxfg_DXFeedSubscription_getSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); + +dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); + +int32_t dxfg_DXFeedSubscription_addChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); + +int32_t dxfg_DXFeedSubscription_removeChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); + +*/ + +// dxfg_DXFeedSubscription_new +JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); + +namespace DXFeedEventListener { + +// dxfg_feed_event_listener_t* dxfg_DXFeedEventListener_new(graal_isolatethread_t *thread, dxfg_feed_event_listener_function user_func, void *user_data); + +} + +} + +DXFCPP_END_NAMESPACE + + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 98bda917c..e13df7751 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -31,6 +31,38 @@ void DXFeedSubscription::detach(std::shared_ptr feed) noexcept { feed->detachSubscription(sharedAs()); } +std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { + isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); + + std::lock_guard guard{changeListenersMutex_}; + + if (lastChangeListenerId_ >= FAKE_CHANGE_LISTENER_ID - 1) { + return FAKE_CHANGE_LISTENER_ID; + } + + auto id = ++lastChangeListenerId_; + + changeListeners_.emplace(id, listener); + + return id; +} + +void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { + std::lock_guard guard{changeListenersMutex_}; + + if (changeListenerId == FAKE_CHANGE_LISTENER_ID) { + return; + } + + if (auto found = changeListeners_.find(changeListenerId); found != changeListeners_.end()) { + auto listener = found->second; + + isolated::api::IsolatedDXFeedSubscription::removeChangeListener(handle_, listener->getHandle()); + + changeListeners_.erase(found); + } +} + void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const noexcept { if (!handle_) { return; @@ -165,7 +197,7 @@ void DXFeedSubscription::clearImpl() const noexcept { false); } -bool DXFeedSubscription::isClosedImpl() const noexcept { +bool DXFeedSubscription::isClosedImpl() const { if (!handle_) { return false; } @@ -177,7 +209,7 @@ bool DXFeedSubscription::isClosedImpl() const noexcept { false); } -DXFeedSubscription::DXFeedSubscription(const EventTypeEnum &eventType) +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType) : eventTypes_{eventType}, handle_{}, eventListenerHandle_{}, onEvent_{} { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); @@ -236,7 +268,7 @@ void DXFeedSubscription::setEventListenerHandle(Id id) { } bool DXFeedSubscription::tryToSetEventListenerHandle() noexcept { - std::lock_guard lock{listenerMutex_}; + std::lock_guard lock{eventListenerMutex_}; if (!eventListenerHandle_) { auto idOpt = diff --git a/src/api/DXPublisherObservableSubscription.cpp b/src/api/DXPublisherObservableSubscription.cpp index 77b2b972c..b1abfd70a 100644 --- a/src/api/DXPublisherObservableSubscription.cpp +++ b/src/api/DXPublisherObservableSubscription.cpp @@ -52,14 +52,14 @@ DXPublisherObservableSubscription::addChangeListener(std::shared_ptrsecond; isolated::api::IsolatedDXPublisherObservableSubscription::removeChangeListener(handle_, listener->getHandle()); diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp new file mode 100644 index 000000000..e6fb61735 --- /dev/null +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeedSubscription { +} + +DXFCPP_END_NAMESPACE From 3089348e2dbfb273e3c1890e4b2080e49eee9179 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 30 May 2024 00:49:35 +0300 Subject: [PATCH 004/178] [EN-7587] Implement FetchDailyCandles sample Mute some false positive warnings and fix the typos. --- .../api/DXFeedSubscription.hpp | 18 ++++++++++++++++-- .../api/osub/ObservableSubscription.hpp | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 9a3716154..3e933def3 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -71,6 +71,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared create(const EventTypeEnum &eventType) { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); } @@ -187,6 +190,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared create(EventTypeIt begin, EventTypeIt end) { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription::create(eventTypes = " + namesToString(begin, end) + ")"); } @@ -267,8 +271,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void addSymbols(SymbolIt begin, SymbolIt end) const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::addSymbols(symbols = " + elementsToString(begin, end) + ")"); } @@ -559,6 +567,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void removeSymbols(SymbolIt begin, SymbolIt end) const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::removeSymbols(symbols = " + elementsToString(begin, end) + ")"); } @@ -618,6 +627,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void setSymbols(SymbolIt begin, SymbolIt end) const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::setSymbols(symbols = " + elementsToString(begin, end) + ")"); } @@ -666,6 +676,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbols() const noexcept { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::getSymbols()"); } @@ -732,8 +745,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getDecoratedSymbols() noexcept { + std::vector getDecoratedSymbols() const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::getDecoratedSymbols()"); } diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp index 39e973473..b18018c2e 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp @@ -61,7 +61,7 @@ struct DXFCPP_EXPORT ObservableSubscription { /** * Removes subscription change listener by id. This method does nothing if the listener with the given id was not - * installed or was already removed as subscription change listener for this subscription. Otherwise it removes the + * installed or was already removed as subscription change listener for this subscription. Otherwise, it removes the * corresponding listener and immediately invokes ObservableSubscriptionChangeListener::subscriptionClosed() on the * given listener while holding the lock for this subscription. * From 2623e20aa20a7e53aa356d2604bc615d0eb3c5f6 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 2 Jun 2024 21:52:17 +0300 Subject: [PATCH 005/178] [EN-7587] Implement FetchDailyCandles sample DXFeedSubscription::addChangeListener DXFeedSubscription::removeChangeListener --- include/dxfeed_graal_cpp_api/api.hpp | 1 + .../api/DXFeedSubscription.hpp | 62 +++++++++---------- .../api/osub/ObservableSubscription.hpp | 1 + .../api/IsolatedDXFeedSubscription.hpp | 36 +++++++++-- .../api/IsolatedDXFeedSubscription.cpp | 39 ++++++++++++ 5 files changed, 104 insertions(+), 35 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index f38bc16a9..6db5ba345 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -53,6 +53,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "exceptions/GraalException.hpp" #include "isolated/api/IsolatedDXEndpoint.hpp" +#include "isolated/api/IsolatedDXFeedSubscription.hpp" #include "isolated/api/IsolatedDXPublisher.hpp" #include "isolated/api/IsolatedDXPublisherObservableSubscription.hpp" #include "isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 3e933def3..07072d460 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -36,10 +36,10 @@ struct LastingEvent; * Subscription for a set of symbols and event types. */ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared, public ObservableSubscription { -public: + public: static constexpr std::size_t FAKE_CHANGE_LISTENER_ID{static_cast(-1)}; -private: + private: friend struct DXFeed; inline static std::atomic lastChangeListenerId_{}; @@ -53,8 +53,6 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared> changeListeners_; std::recursive_mutex changeListenersMutex_{}; - DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); - static JavaObjectHandle createSubscriptionHandleFromEventClassList(const std::unique_ptr &list); @@ -62,6 +60,35 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbolsImpl() const; + + std::vector getDecoratedSymbolsImpl() const; + + public: + /// The alias to a type of shared pointer to the DXFeedSubscription object + using Ptr = std::shared_ptr; + + /// The alias to a type of unique pointer to the DXFeedSubscription object + using Unique = std::unique_ptr; + + DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); + template #if __cpp_concepts requires requires(EventTypeIt iter) { @@ -98,33 +125,6 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared(eventTypes))) { } - void closeImpl() const noexcept; - - void clearImpl() const noexcept; - - bool isClosedImpl() const; - - void addSymbolImpl(void *graalSymbol) const noexcept; - - void addSymbolsImpl(void *graalSymbolList) const noexcept; - - void removeSymbolImpl(void *graalSymbol) const noexcept; - - void removeSymbolsImpl(void *graalSymbolList) const noexcept; - - void setSymbolsImpl(void *graalSymbolList) const noexcept; - - std::vector getSymbolsImpl() const; - - std::vector getDecoratedSymbolsImpl() const; - - public: - /// The alias to a type of shared pointer to the DXFeedSubscription object - using Ptr = std::shared_ptr; - - /// The alias to a type of unique pointer to the DXFeedSubscription object - using Unique = std::unique_ptr; - /// std::string toString() const noexcept override; diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp index b18018c2e..b3cb47758 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp @@ -9,6 +9,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../event/IndexedEventSource.hpp" #include "../../symbols/SymbolWrapper.hpp" +#include "../../event/EventTypeEnum.hpp" #include "ObservableSubscriptionChangeListener.hpp" #include diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index adf9e64e6..7f6d93dd5 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -58,15 +58,43 @@ dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethrea int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); -int32_t dxfg_DXFeedSubscription_addChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); - -int32_t dxfg_DXFeedSubscription_removeChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); - */ + // dxfg_DXFeedSubscription_new JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. + * + * @param sub The subscription's handle. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or ObservableSubscriptionChangeListener's handle + * is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ addChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeChangeListener` in isolation. + * + * @param sub The subscription's handle. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or ObservableSubscriptionChangeListener's handle + * is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ removeChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener); + + namespace DXFeedEventListener { // dxfg_feed_event_listener_t* dxfg_DXFeedEventListener_new(graal_isolatethread_t *thread, dxfg_feed_event_listener_function user_func, void *user_data); diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index e6fb61735..968e2214c 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -9,6 +9,45 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { + +void /* int32_t */ addChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The `sub` handle is invalid"); + } + + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The " + "`listener` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero( + dxfg_DXFeedSubscription_addChangeListener, static_cast(sub.get()), + static_cast(listener.get())); +} + +void /* int32_t */ removeChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener) { + if (!sub) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. " + "The `sub` handle is invalid"); + } + + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. The " + "`listener` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero( + dxfg_DXFeedSubscription_removeChangeListener, static_cast(sub.get()), + static_cast(listener.get())); } +} // namespace isolated::api::IsolatedDXFeedSubscription + DXFCPP_END_NAMESPACE From 0692dc1507daed7730644896d8086592932b3053 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 9 Jun 2024 17:08:33 +0300 Subject: [PATCH 006/178] [EN-7587] Implement FetchDailyCandles sample Fix ObservableSubscriptionChangeListener build --- .../api/osub/ObservableSubscriptionChangeListener.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp index e04315a2e..5599f4d1c 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp @@ -8,7 +8,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../symbols/SymbolWrapper.hpp" -#include "../entity/SharedEntity.hpp" +#include "../../entity/SharedEntity.hpp" #include #include From b590882fc8058e46addd9876db7f8d587c18528c Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 10 Jun 2024 00:21:58 +0300 Subject: [PATCH 007/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- .../api/DXFeedSubscription.hpp | 73 ++++++------ .../api/IsolatedDXFeedSubscription.hpp | 108 ++++++++++++++---- src/api/DXEndpoint.cpp | 2 +- src/api/DXFeedSubscription.cpp | 108 ++++++++---------- .../api/IsolatedDXFeedSubscription.cpp | 58 ++++++++++ 5 files changed, 224 insertions(+), 125 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 07072d460..c1c21d3d7 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -44,6 +44,10 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared lastChangeListenerId_{}; + struct Impl; + + std::unique_ptr impl_; + std::unordered_set eventTypes_; JavaObjectHandle handle_; @@ -58,23 +62,23 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared id); - bool tryToSetEventListenerHandle() noexcept; + bool tryToSetEventListenerHandle(); - void closeImpl() const noexcept; + void closeImpl() const; - void clearImpl() const noexcept; + void clearImpl() const; bool isClosedImpl() const; - void addSymbolImpl(void *graalSymbol) const noexcept; + void addSymbolImpl(void *graalSymbol) const; - void addSymbolsImpl(void *graalSymbolList) const noexcept; + void addSymbolsImpl(void *graalSymbolList) const; - void removeSymbolImpl(void *graalSymbol) const noexcept; + void removeSymbolImpl(void *graalSymbol) const; - void removeSymbolsImpl(void *graalSymbolList) const noexcept; + void removeSymbolsImpl(void *graalSymbolList) const; - void setSymbolsImpl(void *graalSymbolList) const noexcept; + void setSymbolsImpl(void *graalSymbolList) const; std::vector getSymbolsImpl() const; @@ -87,6 +91,8 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared; + DXFeedSubscription(LockExternalConstructionTag); + DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); template @@ -95,13 +101,15 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared dxfcpp::ConvertibleTo; } #endif - DXFeedSubscription(LockExternalConstructionTag, EventTypeIt begin, EventTypeIt end) - : eventTypes_(begin, end), handle_{}, eventListenerHandle_{}, onEvent_{} { + DXFeedSubscription(LockExternalConstructionTag tag, EventTypeIt begin, EventTypeIt end) + : DXFeedSubscription{tag} { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription(eventTypes = " + namesToString(begin, end) + ")"); } + eventTypes_ = {begin, end}; + auto list = EventClassList::create(eventTypes_.begin(), eventTypes_.end()); handle_ = createSubscriptionHandleFromEventClassList(list); @@ -128,14 +136,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShareddetached subscription for a single event type. @@ -255,14 +256,14 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared feed) noexcept; + void attach(std::shared_ptr feed); /** * Detaches subscription from the specified feed. * * @param feed The feed to detach from. */ - void detach(std::shared_ptr feed) noexcept; + void detach(std::shared_ptr feed); /** * Closes this subscription and makes it permanently detached. @@ -312,7 +313,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - std::size_t addEventListener(EventListener &&listener) noexcept + std::size_t addEventListener(EventListener &&listener) #if __cpp_concepts requires requires { { listener(std::vector>{}) } -> std::same_as; @@ -367,7 +368,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - std::size_t addEventListener(std::function> &)> &&listener) noexcept + std::size_t addEventListener(std::function> &)> &&listener) #if __cpp_concepts requires std::is_base_of_v && (requires { @@ -407,7 +408,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - void addSymbols(const SymbolsCollection &collection) const noexcept { + void addSymbols(const SymbolsCollection &collection) const { addSymbols(std::begin(collection), std::end(collection)); } @@ -547,7 +548,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const noexcept { + void addSymbols(std::initializer_list collection) const { addSymbols(collection.begin(), collection.end()); } @@ -592,7 +593,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - void removeSymbols(SymbolsCollection &&collection) const noexcept { + void removeSymbols(SymbolsCollection &&collection) const { removeSymbols(std::begin(collection), std::end(collection)); } @@ -606,7 +607,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const noexcept { + void removeSymbols(std::initializer_list collection) const { removeSymbols(collection.begin(), collection.end()); } @@ -652,7 +653,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - void setSymbols(SymbolsCollection &&collection) const noexcept { + void setSymbols(SymbolsCollection &&collection) const { setSymbols(std::begin(collection), std::end(collection)); } @@ -667,14 +668,14 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const noexcept { + void setSymbols(std::initializer_list collection) const { setSymbols(collection.begin(), collection.end()); } /** * Clears the set of subscribed symbols. */ - void clear() const noexcept { + void clear() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::clear()"); @@ -728,7 +729,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbols() const noexcept { + std::vector getSymbols() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::getSymbols()"); @@ -754,9 +755,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void setExecutor(Executor &&executor) noexcept; + template void setExecutor(Executor &&executor); std::size_t addChangeListener(std::shared_ptr listener) override; diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 7f6d93dd5..b55c76621 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -16,43 +16,51 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { /* -dxfg_subscription_t* dxfg_DXFeedSubscription_new(graal_isolatethread_t *thread, dxfg_event_clazz_t eventClazz); -dxfg_subscription_t* dxfg_DXFeedSubscription_new2(graal_isolatethread_t *thread, dxfg_event_clazz_list_t *eventClazzes); +int32_t dxfg_DXFeedSubscription_addEventListener(graal_isolatethread_t *thread, dxfg_subscription_t +*sub, dxfg_feed_event_listener_t *listener); -int32_t dxfg_DXFeedSubscription_close(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t +*sub, dxfg_feed_event_listener_t *listener); -int32_t dxfg_DXFeedSubscription_addEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); +int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_t *symbol); -int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); +int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_list *symbols); -int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); +int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_t *symbol); -int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); - -int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); +int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_list *symbols); int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); +int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_feed_t *feed); -int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); +int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_feed_t *feed); int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t +*sub); -int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_event_clazz_t eventClazz); +int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t +*sub, dxfg_event_clazz_t eventClazz); dxfg_symbol_list* dxfg_DXFeedSubscription_getSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); +int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_t *symbol); -int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); +int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_list *symbols); -dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t +*sub); dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); @@ -60,9 +68,50 @@ int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethrea */ +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_new` in isolation. + * + * @param eventType The subscription's event type. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); -// dxfg_DXFeedSubscription_new -JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_new2` in isolation. + * + * @param eventClassList The subscription's event types. + * + * @throws std::invalid_argument if eventClassList is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &eventClassList); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_close` in isolation. + * + * @param sub The subscription's handle. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addEventListener` in isolation. + * + * @param sub The subscription's handle. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or DXFeedEventListener's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ +addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. @@ -94,16 +143,25 @@ void /* int32_t */ removeChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener); - namespace DXFeedEventListener { -// dxfg_feed_event_listener_t* dxfg_DXFeedEventListener_new(graal_isolatethread_t *thread, dxfg_feed_event_listener_function user_func, void *user_data); +/** + * Calls the Graal SDK function `dxfg_DXFeedEventListener_new` in isolation. + * @param userFunc A user function that is used as a callback for the listener. + * @param userData User data, which is placed each time as a callback parameter when called from listener. + * @return The DXFeedEventListener's handle. + * + * @throws std::invalid_argument if userFunc is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaObjectHandle /* dxfg_feed_event_listener_t* */ +create(/* dxfg_feed_event_listener_function */ void *userFunc, void *userData); -} +} // namespace DXFeedEventListener -} +} // namespace isolated::api::IsolatedDXFeedSubscription DXFCPP_END_NAMESPACE - DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/api/DXEndpoint.cpp b/src/api/DXEndpoint.cpp index 440d78204..b494b7cf3 100644 --- a/src/api/DXEndpoint.cpp +++ b/src/api/DXEndpoint.cpp @@ -140,7 +140,7 @@ std::shared_ptr DXEndpoint::create(void *endpointHandle, DXEndpoint: auto id = ApiContext::getInstance()->getManager()->registerEntity(endpoint); endpoint->stateChangeListenerHandle_ = isolated::api::IsolatedDXEndpoint::StateChangeListener::create( - dxfcpp::bit_cast(&DXEndpoint::Impl::onPropertyChange), dxfcpp::bit_cast(id.getValue())); + dxfcpp::bit_cast(&Impl::onPropertyChange), dxfcpp::bit_cast(id.getValue())); isolated::api::IsolatedDXEndpoint::addStateChangeListener(endpoint->handle_, endpoint->stateChangeListenerHandle_); return endpoint; diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index e13df7751..441692831 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -15,7 +15,20 @@ DXFCPP_BEGIN_NAMESPACE -void DXFeedSubscription::attach(std::shared_ptr feed) noexcept { +struct DXFeedSubscription::Impl { + static void onEvents(graal_isolatethread_t * /*thread*/, dxfg_event_type_list *graalNativeEvents, void *userData) { + auto id = Id::from(dxfcpp::bit_cast::ValueType>(userData)); + auto sub = ApiContext::getInstance()->getManager()->getEntity(id); + + if (sub) { + auto &&events = EventMapper::fromGraalList(static_cast(graalNativeEvents)); + + sub->onEvent_(events); + } + }; +}; + +void DXFeedSubscription::attach(std::shared_ptr feed) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::attach(feed = " + feed->toString() + ")"); } @@ -23,7 +36,7 @@ void DXFeedSubscription::attach(std::shared_ptr feed) noexcept { feed->attachSubscription(sharedAs()); } -void DXFeedSubscription::detach(std::shared_ptr feed) noexcept { +void DXFeedSubscription::detach(std::shared_ptr feed) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::detach(feed = " + feed->toString() + ")"); } @@ -63,7 +76,7 @@ void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { } } -void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const noexcept { +void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { if (!handle_) { return; } @@ -76,7 +89,7 @@ void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const noexcept { false); } -void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const noexcept { +void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { if (!handle_) { return; } @@ -89,7 +102,7 @@ void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const noexcept { false); } -void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const noexcept { +void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { if (!handle_) { return; } @@ -102,7 +115,7 @@ void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const noexcept { false); } -void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const noexcept { +void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { if (!handle_) { return; } @@ -115,7 +128,7 @@ void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const noexcept false); } -void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const noexcept { +void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { if (!handle_) { return; } @@ -173,19 +186,11 @@ std::vector DXFeedSubscription::getDecoratedSymbolsImpl() const { return result; } -void DXFeedSubscription::closeImpl() const noexcept { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_close(static_cast(threadHandle), handle) == 0; - }, - false); +void DXFeedSubscription::closeImpl() const { + isolated::api::IsolatedDXFeedSubscription::close(handle_); } -void DXFeedSubscription::clearImpl() const noexcept { +void DXFeedSubscription::clearImpl() const { if (!handle_) { return; } @@ -209,65 +214,33 @@ bool DXFeedSubscription::isClosedImpl() const { false); } -DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType) - : eventTypes_{eventType}, handle_{}, eventListenerHandle_{}, onEvent_{} { +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) + : impl_(std::make_unique()) { +} + +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const EventTypeEnum &eventType) + : DXFeedSubscription{tag} { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); } - handle_ = JavaObjectHandle(runIsolatedOrElse( - [eventType](auto threadHandle) { - return dxfg_DXFeedSubscription_new(static_cast(threadHandle), - static_cast(eventType.getId())); - }, - nullptr)); + eventTypes_ = {eventType}; + handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); } JavaObjectHandle DXFeedSubscription::createSubscriptionHandleFromEventClassList(const std::unique_ptr &list) { - if (!list) { - throw std::invalid_argument("EventClassList is nullptr"); - } - - return JavaObjectHandle(runIsolatedOrElse( - [listHandle = static_cast(list->getHandle())](auto threadHandle) { - return dxfg_DXFeedSubscription_new2(static_cast(threadHandle), listHandle); - }, - nullptr)); + return isolated::api::IsolatedDXFeedSubscription::create(list); } void DXFeedSubscription::setEventListenerHandle(Id id) { - auto onEvents = [](graal_isolatethread_t * /*thread*/, dxfg_event_type_list *graalNativeEvents, void *userData) { - auto id = Id::from(dxfcpp::bit_cast::ValueType>(userData)); - auto sub = ApiContext::getInstance()->getManager()->getEntity(id); - - if (sub) { - auto &&events = EventMapper::fromGraalList(static_cast(graalNativeEvents)); - - sub->onEvent_(events); - } - }; + eventListenerHandle_ = isolated::api::IsolatedDXFeedSubscription::DXFeedEventListener::create( + dxfcpp::bit_cast(&Impl::onEvents), dxfcpp::bit_cast(id.getValue())); - eventListenerHandle_ = JavaObjectHandle(runIsolatedOrElse( - [idValue = id.getValue(), onEvents](auto threadHandle) { - return dxfg_DXFeedEventListener_new(static_cast(threadHandle), onEvents, - dxfcpp::bit_cast(idValue)); - }, - nullptr)); - - if (handle_ && eventListenerHandle_) { - runIsolatedOrElse( - [handle = static_cast(handle_.get()), - eventListenerHandle = - static_cast(eventListenerHandle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_addEventListener(static_cast(threadHandle), - handle, eventListenerHandle) == 0; - }, - false); - } + isolated::api::IsolatedDXFeedSubscription::addEventListener(handle_, eventListenerHandle_); } -bool DXFeedSubscription::tryToSetEventListenerHandle() noexcept { +bool DXFeedSubscription::tryToSetEventListenerHandle() { std::lock_guard lock{eventListenerMutex_}; if (!eventListenerHandle_) { @@ -288,4 +261,13 @@ std::string DXFeedSubscription::toString() const noexcept { return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); } +DXFeedSubscription::~DXFeedSubscription() { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug("DXFeedSubscription{" + handle_.toString() + "}::~DXFeedSubscription()"); + } + + closeImpl(); +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 968e2214c..aeb9b845e 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -10,6 +10,50 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_new, dxfcpp::bit_cast(eventType.getId()))); +} + +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &eventClassList) { + if (!eventClassList) { + throw std::invalid_argument("The eventClassList is nullptr"); + } + + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_new2, static_cast(eventClassList->getHandle()))); +} + +void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_close`. The `sub` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_close, + static_cast(sub.get())); +} + +void /* int32_t */ +addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The `sub` handle is invalid"); + } + + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The " + "`listener` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addEventListener, + static_cast(sub.get()), + static_cast(listener.get())); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle @@ -48,6 +92,20 @@ void /* int32_t */ removeChangeListener( static_cast(listener.get())); } +namespace DXFeedEventListener { + +JavaObjectHandle /* dxfg_feed_event_listener_t* */ +create(/* dxfg_feed_event_listener_function */ void *userFunc, void *userData) { + if (!userFunc) { + throw std::invalid_argument("Unable to create DXFeedEventListener. The `userFunc` parameter is nullptr"); + } + + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedEventListener_new, dxfcpp::bit_cast(userFunc), userData)); +} + +} // namespace DXFeedEventListener + } // namespace isolated::api::IsolatedDXFeedSubscription DXFCPP_END_NAMESPACE From 70eb5e6a19117e5761e6d5b00786efffcc34b24d Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 10 Jun 2024 00:26:50 +0300 Subject: [PATCH 008/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 2 +- src/api/DXFeedSubscription.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index c1c21d3d7..246e184d9 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -108,7 +108,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared Date: Mon, 10 Jun 2024 01:07:08 +0300 Subject: [PATCH 009/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 246e184d9..af56ba90c 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -108,7 +108,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared{begin, end}; auto list = EventClassList::create(eventTypes_.begin(), eventTypes_.end()); From c2f8ebd9f14994995d32c04b642de4732975449a Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 18:22:38 +0300 Subject: [PATCH 010/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::addSymbol --- .../api/DXFeedSubscription.hpp | 9 +------- .../api/IsolatedDXFeedSubscription.hpp | 18 ++++++++++++--- src/api/DXFeedSubscription.cpp | 22 +++++++++---------- .../api/IsolatedDXFeedSubscription.cpp | 17 ++++++++++++++ 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index af56ba90c..ce0e99944 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -272,14 +272,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared &sub, /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); +// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); + +// int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. + * + * @param sub The subscription's handle. + * @param symbol The symbol. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbol is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void* symbol); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 05072525c..e6b626336 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -25,7 +25,7 @@ struct DXFeedSubscription::Impl { sub->onEvent_(events); } - }; + } }; void DXFeedSubscription::attach(std::shared_ptr feed) { @@ -44,6 +44,15 @@ void DXFeedSubscription::detach(std::shared_ptr feed) { feed->detachSubscription(sharedAs()); } +void DXFeedSubscription::close() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::close()"); + } + + closeImpl(); +} + std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); @@ -77,16 +86,7 @@ void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { } void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbol](auto threadHandle) { - return dxfg_DXFeedSubscription_addSymbol(static_cast(threadHandle), handle, - static_cast(graalSymbol)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graalSymbol); } void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index aeb9b845e..f4d37317a 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -54,6 +54,23 @@ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle(listener.get())); } +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The `sub` handle is invalid"); + } + + if (!symbol) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The " + "`symbol` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addSymbol, + static_cast(sub.get()), + static_cast(symbol)); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From 94d54218e812b27719f9cc55bd2c4ecb8795e110 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 18:35:50 +0300 Subject: [PATCH 011/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::addSymbols --- .../api/IsolatedDXFeedSubscription.hpp | 28 +++++++++++-------- src/api/DXFeedSubscription.cpp | 11 +------- .../api/IsolatedDXFeedSubscription.cpp | 16 +++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 45bd494f9..d127b828f 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -17,15 +17,6 @@ namespace isolated::api::IsolatedDXFeedSubscription { /* -int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t -*sub, dxfg_feed_event_listener_t *listener); - -int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_list *symbols); - int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); @@ -112,19 +103,32 @@ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void* symbol); +// int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_symbol_list *symbols); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbols` in isolation. + * + * @param sub The subscription's handle. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); + + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index e6b626336..a68fead3c 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -90,16 +90,7 @@ void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { } void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbolList](auto threadHandle) { - return dxfg_DXFeedSubscription_addSymbols(static_cast(threadHandle), handle, - static_cast(graalSymbolList)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); } void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index f4d37317a..749bc9dc7 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -71,6 +71,22 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< static_cast(symbol)); } +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addSymbols, + static_cast(sub.get()), + static_cast(symbols)); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From dfe8fe21f4119a7467b702af65f45962fad09f73 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 18:50:32 +0300 Subject: [PATCH 012/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::removeSymbol IsolatedDXFeedSubscription::removeSymbols --- .../api/IsolatedDXFeedSubscription.hpp | 41 +++++++++++++------ src/api/DXFeedSubscription.cpp | 22 +--------- .../api/IsolatedDXFeedSubscription.cpp | 37 ++++++++++++++++- 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index d127b828f..bd41414f3 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -17,12 +17,6 @@ namespace isolated::api::IsolatedDXFeedSubscription { /* -int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_list *symbols); - int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, @@ -101,7 +95,8 @@ void /* int32_t */ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); -// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); +// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_feed_event_listener_t *listener); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. @@ -112,10 +107,8 @@ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void* symbol); - -// int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -// dxfg_symbol_list *symbols); +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbols` in isolation. @@ -126,8 +119,32 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbol` in isolation. + * + * @param sub The subscription's handle. + * @param symbol The subscription's symbol. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbol is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbols` in isolation. + * + * @param sub The subscription's handle. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index a68fead3c..39c2aa6fb 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -94,29 +94,11 @@ void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { } void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbol](auto threadHandle) { - return dxfg_DXFeedSubscription_removeSymbol(static_cast(threadHandle), handle, - static_cast(graalSymbol)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graalSymbol); } void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbolList](auto threadHandle) { - return dxfg_DXFeedSubscription_removeSymbols(static_cast(threadHandle), handle, - static_cast(graalSymbolList)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); } void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 749bc9dc7..9e89ab1a4 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -71,7 +71,8 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< static_cast(symbol)); } -void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols) { if (!sub) { throw std::invalid_argument( "Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The `sub` handle is invalid"); @@ -87,6 +88,40 @@ void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle static_cast(symbols)); } +void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The `sub` handle is invalid"); + } + + if (!symbol) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The " + "`symbol` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_removeSymbol, + static_cast(sub.get()), + static_cast(symbol)); +} + +void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_removeSymbols, + static_cast(sub.get()), + static_cast(symbols)); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From c59fd0267ae35364738db108d7aad29cb7b0f722 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 19:05:38 +0300 Subject: [PATCH 013/178] [EN-7587] Implement FetchDailyCandles sample RelWithDebInfo --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2784a6154..67793e0c0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: xcode: '15.0' cc: 'clang' cxx: 'clang++' - buildType: [ Release, Debug ] + buildType: [ Release, Debug, RelWithDebInfo ] name: "${{ matrix.config.name }}-${{matrix.buildType}}" runs-on: ${{ matrix.config.image }} From 5d4c1c41dd5f0e722c7e0531d8073edb1304e1fe Mon Sep 17 00:00:00 2001 From: ttldtor Date: Tue, 11 Jun 2024 01:16:34 +0300 Subject: [PATCH 014/178] [EN-7587] Implement FetchDailyCandles sample _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80efdc7fe..151bf03dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,6 +373,14 @@ set(DXFCXX_GCC_LIKE_LINK_OPTIONS "-fPIC") #A workaround to fix 'relocation truncated to fit: IMAGE_REL_AMD64_SECREL' error (MinGW + Debug) set(DXFCXX_MINGW_DEBUG_LINK_OPTIONS "-Wl,--disable-dynamicbase,--disable-high-entropy-va,--default-image-base-low") +# https://developercommunity.visualstudio.com/t/Invalid-code-generation-in-release-1940/10678572?sort=newest&viewtype=all +# https://github.com/microsoft/STL/wiki/Changelog#vs-2022-1710 +# https://github.com/actions/runner-images/issues/10004 +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_definitions(${PROJECT_NAME} PUBLIC _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR) + target_compile_definitions(${PROJECT_NAME}_static PUBLIC _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR) +endif () + target_compile_options(${PROJECT_NAME} PUBLIC $<$:${DXFCXX_MSVC_COMPILE_OPTIONS}> From 4b48f6e2910c70588584fc54da6206d9ea42493a Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 17 Jun 2024 17:16:46 +0300 Subject: [PATCH 015/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::clear IsolatedDXFeedSubscription::isClosed --- .../api/IsolatedDXFeedSubscription.hpp | 33 +++++++++++++++---- src/api/DXFeedSubscription.cpp | 20 ++--------- .../api/IsolatedDXFeedSubscription.cpp | 20 +++++++++++ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index bd41414f3..589e51957 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -17,13 +17,6 @@ namespace isolated::api::IsolatedDXFeedSubscription { /* -int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_feed_t *feed); - -int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_feed_t *feed); int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); @@ -146,6 +139,32 @@ void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHand void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void *symbols); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_clear` in isolation. + * + * @param sub The subscription's handle. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +// int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +// int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_clear` in isolation. + * + * @param sub The subscription's handle. + * @return `true` if subscription is closed. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 39c2aa6fb..b69b5a08e 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -164,27 +164,11 @@ void DXFeedSubscription::closeImpl() const { } void DXFeedSubscription::clearImpl() const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_clear(static_cast(threadHandle), handle) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::clear(handle_); } bool DXFeedSubscription::isClosedImpl() const { - if (!handle_) { - return false; - } - - return runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_isClosed(static_cast(threadHandle), handle) != 0; - }, - false); + return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); } DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 9e89ab1a4..c8748dc4f 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -122,6 +122,26 @@ void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHan static_cast(symbols)); } +void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_clear`. The `sub` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_clear, + static_cast(sub.get())); +} + +bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_isClosed`. The `sub` handle is invalid"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_isClosed, + static_cast(sub.get())) == 1; +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From 6d8b0e81a06326a84785abb8b70405b6873f2be5 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 17 Jun 2024 18:06:21 +0300 Subject: [PATCH 016/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::getSymbols IsolatedDXFeedSubscription::setSymbols IsolatedDXFeedSubscription::getDecoratedSymbols --- .../api/IsolatedDXFeedSubscription.hpp | 76 +++++++++++-------- src/api/DXFeedSubscription.cpp | 52 +------------ .../api/IsolatedDXFeedSubscription.cpp | 48 ++++++++++++ 3 files changed, 97 insertions(+), 79 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 589e51957..1bd18a5e0 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -15,34 +15,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { -/* - - -int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t -*sub); - -int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t -*sub, dxfg_event_clazz_t eventClazz); - -dxfg_symbol_list* dxfg_DXFeedSubscription_getSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_list *symbols); - -dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t -*sub); - -dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); - -*/ - /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_new` in isolation. * @@ -153,9 +125,8 @@ void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +// dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t +// *sub); + +// int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_event_clazz_t eventClazz); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getSymbols` in isolation. + * + * @param sub The subscription's handle. + * @return The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_setSymbols` in isolation. + * + * @param sub The subscription's handle. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getDecoratedSymbols` in isolation. + * + * @param sub The subscription's handle. + * @return The subscription's decorated symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +// int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index b69b5a08e..303f65e33 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -102,61 +102,15 @@ void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { } void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbolList](auto threadHandle) { - return dxfg_DXFeedSubscription_setSymbols(static_cast(threadHandle), handle, - static_cast(graalSymbolList)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); } std::vector DXFeedSubscription::getSymbolsImpl() const { - if (!handle_) { - return {}; - } - - dxfg_symbol_list *list = runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_getSymbols(static_cast(threadHandle), handle); - }, - nullptr); - - auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); - - runIsolatedOrElse( - [list](auto threadHandle) { - return dxfg_CList_symbol_release(static_cast(threadHandle), list) == 0; - }, - false); - - return result; + return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); } std::vector DXFeedSubscription::getDecoratedSymbolsImpl() const { - if (!handle_) { - return {}; - } - - dxfg_symbol_list *list = runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_getDecoratedSymbols(static_cast(threadHandle), - handle); - }, - nullptr); - - auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); - - runIsolatedOrElse( - [list](auto threadHandle) { - return dxfg_CList_symbol_release(static_cast(threadHandle), list) == 0; - }, - false); - - return result; + return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); } void DXFeedSubscription::closeImpl() const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index c8748dc4f..a76c818d4 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -142,6 +142,54 @@ bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle(sub.get())) == 1; } +std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_getSymbols`. The `sub` handle is invalid"); + } + + dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_getSymbols, static_cast(sub.get())); + + auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); + + return result; +} + +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_setSymbols, + static_cast(sub.get()), + static_cast(symbols)); +} + +std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_getDecoratedSymbols`. The `sub` handle is invalid"); + } + + dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_getDecoratedSymbols, static_cast(sub.get())); + + auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); + + return result; +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From 852515082b6e6ecc89703da040946aed8cc0f410 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 17 Jun 2024 19:07:51 +0300 Subject: [PATCH 017/178] [EN-7587] Implement FetchDailyCandles sample Tools: set default properties. --- tools/Tools/src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/Tools/src/main.cpp b/tools/Tools/src/main.cpp index b90cd72df..70661a07c 100644 --- a/tools/Tools/src/main.cpp +++ b/tools/Tools/src/main.cpp @@ -28,6 +28,12 @@ using namespace dxfcpp::literals; int main(int argc, char *argv[]) { try { + System::setProperty(DXEndpoint::DXFEED_WILDCARD_ENABLE_PROPERTY, "true"); + // Enable experimental feature. + System::setProperty("dxfeed.experimental.dxlink.enable", "true"); + // Set scheme for dxLink. + System::setProperty("scheme", "ext:opt:sysprops,resource:dxlink.xml"); + const auto usage = tools::HelpTool::generateToolHelpScreen(); std::vector args{}; @@ -97,7 +103,7 @@ int main(int argc, char *argv[]) { } catch (const GraalException &e) { std::cerr << e.what() << '\n'; std::cerr << e.getStackTrace() << '\n'; - } catch (const std::runtime_error& e) { + } catch (const std::runtime_error &e) { std::cerr << e.what() << '\n'; } catch (...) { std::cerr << "Error!\n"; From 723de08e33c276e8149023b871185016c54ed372 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 19 Jun 2024 12:47:26 +0300 Subject: [PATCH 018/178] [EN-7587] Implement FetchDailyCandles sample Move implementations to TU. --- .../api/DXFeedSubscription.hpp | 139 ++-------- src/api/DXFeedSubscription.cpp | 243 ++++++++++++------ 2 files changed, 184 insertions(+), 198 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index ce0e99944..ce23424ad 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -39,6 +39,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared(-1)}; + /// + using OnEventHandler = SimpleHandler> &)>; + private: friend struct DXFeed; @@ -53,7 +56,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared eventListenerHandle_; - SimpleHandler> &)> onEvent_{}; + OnEventHandler onEvent_{}; std::unordered_map> changeListeners_; std::recursive_mutex changeListenersMutex_{}; @@ -64,26 +67,12 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbolsImpl() const; - - std::vector getDecoratedSymbolsImpl() const; - public: /// The alias to a type of shared pointer to the DXFeedSubscription object using Ptr = std::shared_ptr; @@ -101,8 +90,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared dxfcpp::ConvertibleTo; } #endif - DXFeedSubscription(LockExternalConstructionTag tag, EventTypeIt begin, EventTypeIt end) - : DXFeedSubscription{tag} { + DXFeedSubscription(LockExternalConstructionTag tag, EventTypeIt begin, EventTypeIt end) : DXFeedSubscription{tag} { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription(eventTypes = " + namesToString(begin, end) + ")"); @@ -148,19 +136,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared create(const EventTypeEnum &eventType) { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); - } - - auto sub = createShared(eventType); - auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); - - dxfcpp::ignore_unused(id); - - return sub; - } + static std::shared_ptr create(const EventTypeEnum &eventType); /** * Creates detached subscription for the given collection of event types. @@ -214,14 +190,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShareddetached subscription for the given collection of event types. */ - static std::shared_ptr create(std::initializer_list eventTypes) { - auto sub = createShared(eventTypes); - auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); - - dxfcpp::ignore_unused(id); - - return sub; - } + static std::shared_ptr create(std::initializer_list eventTypes); /** * Creates detached subscription for the given collection of event types. @@ -314,7 +283,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared> &)>::FAKE_ID; + return OnEventHandler::FAKE_ID; } return onEvent_ += listener; @@ -401,9 +370,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const { - addSymbols(collection.begin(), collection.end()); - } + void addSymbols(std::initializer_list collection) const; /** * Removes the specified collection (using iterators) of symbols from the set of subscribed symbols. @@ -600,9 +543,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const { - removeSymbols(collection.begin(), collection.end()); - } + void removeSymbols(std::initializer_list collection) const; /** * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection (using @@ -661,21 +602,12 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const { - setSymbols(collection.begin(), collection.end()); - } + void setSymbols(std::initializer_list collection) const; /** * Clears the set of subscribed symbols. */ - void clear() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::clear()"); - } - - clearImpl(); - } + void clear() const; /** * Returns `true` if this subscription is closed. @@ -684,23 +616,14 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getEventTypes() override { - return eventTypes_; - } + std::unordered_set getEventTypes() override; /** * Returns `true` if this subscription contains the corresponding event type. @@ -710,9 +633,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbols() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::getSymbols()"); - } - - return getSymbolsImpl(); - } + std::vector getSymbols() const; /** * Returns a set of decorated symbols (depending on the actual implementation of subscription). @@ -739,18 +653,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getDecoratedSymbols() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::getDecoratedSymbols()"); - } - - return getDecoratedSymbolsImpl(); - } - - auto getExecutor(); - - template void setExecutor(Executor &&executor); + std::vector getDecoratedSymbols() const; std::size_t addChangeListener(std::shared_ptr listener) override; diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 303f65e33..55702bf67 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -28,6 +28,97 @@ struct DXFeedSubscription::Impl { } }; +JavaObjectHandle +DXFeedSubscription::createSubscriptionHandleFromEventClassList(const std::unique_ptr &list) { + return isolated::api::IsolatedDXFeedSubscription::create(list); +} + +void DXFeedSubscription::setEventListenerHandle(Id id) { + eventListenerHandle_ = isolated::api::IsolatedDXFeedSubscription::DXFeedEventListener::create( + dxfcpp::bit_cast(&Impl::onEvents), dxfcpp::bit_cast(id.getValue())); + + isolated::api::IsolatedDXFeedSubscription::addEventListener(handle_, eventListenerHandle_); +} + +bool DXFeedSubscription::tryToSetEventListenerHandle() { + std::lock_guard lock{eventListenerMutex_}; + + if (!eventListenerHandle_) { + auto idOpt = + ApiContext::getInstance()->getManager()->getId(sharedAs()); + + if (!idOpt) { + return false; + } + + setEventListenerHandle(idOpt.value()); + } + + return true; +} + +void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); +} + +void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); +} + +void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); +} + +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) + : impl_(std::make_unique()) { +} + +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const EventTypeEnum &eventType) + : DXFeedSubscription{tag} { + if constexpr (Debugger::isDebug) { + Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); + } + + eventTypes_ = std::unordered_set{eventType}; + handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); +} + +std::string DXFeedSubscription::toString() const noexcept { + return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); +} + +DXFeedSubscription::~DXFeedSubscription() { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug("DXFeedSubscription{" + handle_.toString() + "}::~DXFeedSubscription()"); + } + + close(); +} + +std::shared_ptr DXFeedSubscription::create(const EventTypeEnum &eventType) { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); + } + + auto sub = createShared(eventType); + auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); + + dxfcpp::ignore_unused(id); + + return sub; +} + +std::shared_ptr DXFeedSubscription::create(std::initializer_list eventTypes) { + auto sub = createShared(eventTypes); + auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); + + dxfcpp::ignore_unused(id); + + return sub; +} + void DXFeedSubscription::attach(std::shared_ptr feed) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::attach(feed = " + feed->toString() + ")"); @@ -50,135 +141,127 @@ void DXFeedSubscription::close() const { Debugger::debug(toString() + "::close()"); } - closeImpl(); + isolated::api::IsolatedDXFeedSubscription::close(handle_); } -std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { - isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); +void DXFeedSubscription::removeEventListener(std::size_t listenerId) { + onEvent_ -= listenerId; +} - std::lock_guard guard{changeListenersMutex_}; +DXFeedSubscription::OnEventHandler &DXFeedSubscription::onEvent() { + tryToSetEventListenerHandle(); - if (lastChangeListenerId_ >= FAKE_CHANGE_LISTENER_ID - 1) { - return FAKE_CHANGE_LISTENER_ID; - } + return onEvent_; +} - auto id = ++lastChangeListenerId_; +void DXFeedSubscription::addSymbols(const SymbolWrapper &symbolWrapper) const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::addSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); + } - changeListeners_.emplace(id, listener); + auto graal = symbolWrapper.toGraalUnique(); - return id; + isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graal.get()); } -void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { - std::lock_guard guard{changeListenersMutex_}; - - if (changeListenerId == FAKE_CHANGE_LISTENER_ID) { - return; +void DXFeedSubscription::removeSymbols(const SymbolWrapper &symbolWrapper) const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::removeSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); } - if (auto found = changeListeners_.find(changeListenerId); found != changeListeners_.end()) { - auto listener = found->second; - - isolated::api::IsolatedDXFeedSubscription::removeChangeListener(handle_, listener->getHandle()); + auto graal = symbolWrapper.toGraalUnique(); - changeListeners_.erase(found); - } + isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graal.get()); } -void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { - isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graalSymbol); +void DXFeedSubscription::addSymbols(std::initializer_list collection) const { + addSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); +void DXFeedSubscription::removeSymbols(std::initializer_list collection) const { + removeSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { - isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graalSymbol); +void DXFeedSubscription::setSymbols(std::initializer_list collection) const { + setSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); -} +void DXFeedSubscription::clear() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::clear()"); + } -void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); + isolated::api::IsolatedDXFeedSubscription::clear(handle_); } -std::vector DXFeedSubscription::getSymbolsImpl() const { - return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); -} +bool DXFeedSubscription::isClosed() override { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::isClosed()"); + } -std::vector DXFeedSubscription::getDecoratedSymbolsImpl() const { - return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); + return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); } -void DXFeedSubscription::closeImpl() const { - isolated::api::IsolatedDXFeedSubscription::close(handle_); +std::unordered_set DXFeedSubscription::getEventTypes() override { + return eventTypes_; } -void DXFeedSubscription::clearImpl() const { - isolated::api::IsolatedDXFeedSubscription::clear(handle_); +bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) override { + return eventTypes_.contains(eventType); } -bool DXFeedSubscription::isClosedImpl() const { - return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); -} +std::vector DXFeedSubscription::getSymbols() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::getSymbols()"); + } -DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) - : impl_(std::make_unique()) { + return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); } -DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const EventTypeEnum &eventType) - : DXFeedSubscription{tag} { +std::vector DXFeedSubscription::getDecoratedSymbols() const { if constexpr (Debugger::isDebug) { - Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::getDecoratedSymbols()"); } - eventTypes_ = std::unordered_set{eventType}; - handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); + return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); } -JavaObjectHandle -DXFeedSubscription::createSubscriptionHandleFromEventClassList(const std::unique_ptr &list) { - return isolated::api::IsolatedDXFeedSubscription::create(list); -} +std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { + isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); -void DXFeedSubscription::setEventListenerHandle(Id id) { - eventListenerHandle_ = isolated::api::IsolatedDXFeedSubscription::DXFeedEventListener::create( - dxfcpp::bit_cast(&Impl::onEvents), dxfcpp::bit_cast(id.getValue())); + std::lock_guard guard{changeListenersMutex_}; - isolated::api::IsolatedDXFeedSubscription::addEventListener(handle_, eventListenerHandle_); -} + if (lastChangeListenerId_ >= FAKE_CHANGE_LISTENER_ID - 1) { + return FAKE_CHANGE_LISTENER_ID; + } -bool DXFeedSubscription::tryToSetEventListenerHandle() { - std::lock_guard lock{eventListenerMutex_}; + auto id = ++lastChangeListenerId_; - if (!eventListenerHandle_) { - auto idOpt = - ApiContext::getInstance()->getManager()->getId(sharedAs()); + changeListeners_.emplace(id, listener); - if (!idOpt) { - return false; - } + return id; +} - setEventListenerHandle(idOpt.value()); +void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { + std::lock_guard guard{changeListenersMutex_}; + + if (changeListenerId == FAKE_CHANGE_LISTENER_ID) { + return; } - return true; -} + if (auto found = changeListeners_.find(changeListenerId); found != changeListeners_.end()) { + auto listener = found->second; -std::string DXFeedSubscription::toString() const noexcept { - return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); -} + isolated::api::IsolatedDXFeedSubscription::removeChangeListener(handle_, listener->getHandle()); -DXFeedSubscription::~DXFeedSubscription() { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug("DXFeedSubscription{" + handle_.toString() + "}::~DXFeedSubscription()"); + changeListeners_.erase(found); } - - closeImpl(); } DXFCPP_END_NAMESPACE \ No newline at end of file From 11dfa2685e989d80ffdcdcabd8a54a94ba1762b8 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 19 Jun 2024 13:00:45 +0300 Subject: [PATCH 019/178] [EN-7587] Implement FetchDailyCandles sample Move implementations to TU: fix build --- src/api/DXFeedSubscription.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 55702bf67..3ce0dc80d 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -197,7 +197,7 @@ void DXFeedSubscription::clear() const { isolated::api::IsolatedDXFeedSubscription::clear(handle_); } -bool DXFeedSubscription::isClosed() override { +bool DXFeedSubscription::isClosed() { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::isClosed()"); @@ -206,11 +206,11 @@ bool DXFeedSubscription::isClosed() override { return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); } -std::unordered_set DXFeedSubscription::getEventTypes() override { +std::unordered_set DXFeedSubscription::getEventTypes() { return eventTypes_; } -bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) override { +bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) { return eventTypes_.contains(eventType); } From b9fc0794ea3070993610a02be5d19d523452d495 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 23 Jun 2024 22:55:27 +0300 Subject: [PATCH 020/178] [EN-7587] Implement FetchDailyCandles sample Promise --- include/dxfeed_graal_cpp_api/api.hpp | 2 + .../isolated/promise/IsolatedPromise.hpp | 84 +++++++++++++++++++ .../dxfeed_graal_cpp_api/promise/Promise.hpp | 22 +++++ 3 files changed, 108 insertions(+) create mode 100644 include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp create mode 100644 include/dxfeed_graal_cpp_api/promise/Promise.hpp diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 6db5ba345..a9e7c98b6 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -63,4 +63,6 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "ondemand/OnDemandService.hpp" +#include "promise/Promise.hpp" + DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp new file mode 100644 index 000000000..13fa2192e --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -0,0 +1,84 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedPromise { + +/* + +dxfg_event_type_t* dxfg_Promise_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_event_t *promise); +dxfg_event_type_list* dxfg_Promise_List_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_events_t *promise); +dxfg_exception_t* dxfg_Promise_getException(graal_isolatethread_t *thread, dxfg_promise_t *promise); +int32_t dxfg_Promise_await(graal_isolatethread_t *thread, dxfg_promise_t *promise); +int32_t dxfg_Promise_await2(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); +int32_t dxfg_Promise_awaitWithoutException(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); +int32_t dxfg_Promise_cancel(graal_isolatethread_t *thread, dxfg_promise_t *promise); +int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); +int32_t dxfg_Promise_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_t* event); +int32_t dxfg_Promise_completeExceptionally(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); +int32_t dxfg_Promise_whenDone(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data); +int32_t dxfg_Promise_whenDoneAsync(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data, dxfg_executor_t* executor); +dxfg_promise_t* dxfg_Promise_completed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_java_object_handler *handler); +dxfg_promise_t* dxfg_Promise_failed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); + +dxfg_promise_t* dxfg_Promises_allOf(graal_isolatethread_t *thread, dxfg_promise_list *promises); + +*/ + +/** + * Calls the Graal SDK function `dxfg_Promise_isDone` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation has completed normally or exceptionally or was cancelled. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_hasResult` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation has completed normally + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_hasException` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation has completed exceptionally or was cancelled. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_isCancelled` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation was cancelled. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise); + + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp new file mode 100644 index 000000000..09ff4bb58 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -0,0 +1,22 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +template +struct Promise {}; + +template <> +struct Promise> { + +}; + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file From 5e2f52c7dee5ace16719359b2fbc6a94e2b6c22e Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 24 Jun 2024 19:17:20 +0300 Subject: [PATCH 021/178] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- CMakeLists.txt | 1 + .../exceptions/JavaException.hpp | 8 +++ .../isolated/promise/IsolatedPromise.hpp | 67 +++++++++++++++++-- src/exceptions/JavaException.cpp | 16 +++-- src/isolated/promise/IsolatedPromise.cpp | 47 +++++++++++++ 5 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 src/isolated/promise/IsolatedPromise.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 151bf03dc..f100aee1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/IsolatedDXPublisher.cpp src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp + src/isolated/promise/IsolatedPromise.cpp src/isolated/internal/IsolatedString.cpp src/isolated/internal/IsolatedTimeFormat.cpp ) diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index 7679731ba..0b46f2e77 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -27,6 +27,14 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { */ JavaException(const std::string &message, const std::string &className, std::string stackTrace); + /** + * Creates an exception using native (GraalVM) Java exception handle + * + * @param exceptionHandle The native Java exception handle. + * @return An exception. + */ + static JavaException create(void* exceptionHandle); + /// Throws a JavaException if it exists (i.e. intercepted by Graal SDK) static void throwIfJavaThreadExceptionExists(); diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp index 13fa2192e..9a32dea42 100644 --- a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -7,17 +7,18 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include "../../event/EventType.hpp" +#include "../../exceptions/JavaException.hpp" + +#include +#include + DXFCPP_BEGIN_NAMESPACE -namespace isolated::api::IsolatedPromise { +namespace isolated::promise::IsolatedPromise { /* -dxfg_event_type_t* dxfg_Promise_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_event_t *promise); -dxfg_event_type_list* dxfg_Promise_List_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_events_t *promise); -dxfg_exception_t* dxfg_Promise_getException(graal_isolatethread_t *thread, dxfg_promise_t *promise); -int32_t dxfg_Promise_await(graal_isolatethread_t *thread, dxfg_promise_t *promise); -int32_t dxfg_Promise_await2(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); int32_t dxfg_Promise_awaitWithoutException(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); int32_t dxfg_Promise_cancel(graal_isolatethread_t *thread, dxfg_promise_t *promise); int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); @@ -76,6 +77,60 @@ bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise); */ bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise); +/** + * Calls the Graal SDK function `dxfg_Promise_EventType_getResult` in isolation. + * + * @param promise The promise's handle. + * @return event by promise + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_List_EventType_getResult` in isolation. + * + * @param promise The promise's handle. + * @return events by promise + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_getException` in isolation. + * + * @param promise The promise's handle. + * @return exception by promise + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_await` in isolation. + * + * @param promise The promise's handle. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_await2` in isolation. + * + * @param promise The promise's handle. + * @param timeoutInMilliseconds The promise's timeout. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds); + } diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 6988fb8b1..647e98411 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -19,9 +19,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { return; } - auto message = toString(exception->message); - auto className = toString(exception->class_name); - auto stackTrace = toString(exception->print_stack_trace); + auto javaException = create(exception); runIsolatedThrow( [](auto threadHandle, auto &&...params) { @@ -29,7 +27,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { }, exception); - throw JavaException(message, className, stackTrace); + throw javaException; } void JavaException::throwException() { @@ -98,6 +96,16 @@ JavaException::JavaException(const std::string &message, const std::string &clas stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { } +JavaException create(void* exceptionHandle) { + if (exceptionHandle == nullptr) { + return JavaException("", "", ""); + } + + dxfg_exception_t *exception = dxfcpp::bit_cast(exceptionHandle); + + return JavaException(toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)); +} + const std::string &JavaException::getStackTrace() const & { return stackTrace_; } diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp new file mode 100644 index 000000000..bcfc5f1e9 --- /dev/null +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::promise::IsolatedPromise { + +bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise) { + return {}; +} + +bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise) { + return {}; +} + +bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise) { + return {}; +} + +std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise) { + return {}; +} + +std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise) { + return {}; +} + +JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise) { + return {"", "", ""}; +} + +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise) { + +} + +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { + +} + +} + +DXFCPP_END_NAMESPACE From 04c38dadee400caee73532c28a106d0b2308c076 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 24 Jun 2024 19:20:51 +0300 Subject: [PATCH 022/178] [EN-7587] Implement FetchDailyCandles sample JavaException::create --- src/exceptions/JavaException.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 647e98411..ff0d172e8 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -96,7 +96,7 @@ JavaException::JavaException(const std::string &message, const std::string &clas stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { } -JavaException create(void* exceptionHandle) { +JavaException JavaException::create(void* exceptionHandle) { if (exceptionHandle == nullptr) { return JavaException("", "", ""); } From a1cf71f4476bd7a3fc787c34d42e59c11ff6e1e6 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Tue, 25 Jun 2024 16:49:06 +0300 Subject: [PATCH 023/178] [EN-7587] Implement FetchDailyCandles sample JavaException::create --- src/exceptions/JavaException.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index ff0d172e8..7ee697f33 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -27,7 +27,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { }, exception); - throw javaException; + throw javaException; // NOLINT(*-throw-by-value-catch-by-reference) } void JavaException::throwException() { @@ -96,14 +96,14 @@ JavaException::JavaException(const std::string &message, const std::string &clas stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { } -JavaException JavaException::create(void* exceptionHandle) { +JavaException JavaException::create(void *exceptionHandle) { if (exceptionHandle == nullptr) { - return JavaException("", "", ""); + return {"", "", ""}; } - dxfg_exception_t *exception = dxfcpp::bit_cast(exceptionHandle); + auto *exception = dxfcpp::bit_cast(exceptionHandle); - return JavaException(toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)); + return {toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)}; } const std::string &JavaException::getStackTrace() const & { From 2e23a3001a94bf7b67c539c337fc294d7de63874 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Tue, 25 Jun 2024 19:11:38 +0300 Subject: [PATCH 024/178] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- .../isolated/promise/IsolatedPromise.hpp | 52 ++++++++++----- src/isolated/promise/IsolatedPromise.cpp | 63 +++++++++++++++++++ 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp index 9a32dea42..6ad680278 100644 --- a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -17,22 +17,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::promise::IsolatedPromise { -/* - -int32_t dxfg_Promise_awaitWithoutException(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); -int32_t dxfg_Promise_cancel(graal_isolatethread_t *thread, dxfg_promise_t *promise); -int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); -int32_t dxfg_Promise_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_t* event); -int32_t dxfg_Promise_completeExceptionally(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); -int32_t dxfg_Promise_whenDone(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data); -int32_t dxfg_Promise_whenDoneAsync(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data, dxfg_executor_t* executor); -dxfg_promise_t* dxfg_Promise_completed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_java_object_handler *handler); -dxfg_promise_t* dxfg_Promise_failed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); - -dxfg_promise_t* dxfg_Promises_allOf(graal_isolatethread_t *thread, dxfg_promise_list *promises); - -*/ - /** * Calls the Graal SDK function `dxfg_Promise_isDone` in isolation. * @@ -131,6 +115,42 @@ void /* int32_t */ await(/* dxfg_promise_t * */ void* promise); */ void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds); +/** + * Calls the Graal SDK function `dxfg_Promise_awaitWithoutException` in isolation. + * + * @param promise The promise's handle. + * @param timeoutInMilliseconds The promise's timeout. + * @return `true` if the computation has completed normally; `false` when wait timed out. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds); + +/** + * Calls the Graal SDK function `dxfg_Promise_cancel` in isolation. + * + * @param promise The promise's handle. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ cancel(/* dxfg_promise_t * */ void* promise); + +/* + +int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); +int32_t dxfg_Promise_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_t* event); +int32_t dxfg_Promise_completeExceptionally(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); +int32_t dxfg_Promise_whenDone(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data); +int32_t dxfg_Promise_whenDoneAsync(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data, dxfg_executor_t* executor); +dxfg_promise_t* dxfg_Promise_completed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_java_object_handler *handler); +dxfg_promise_t* dxfg_Promise_failed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); + +dxfg_promise_t* dxfg_Promises_allOf(graal_isolatethread_t *thread, dxfg_promise_list *promises); + +*/ + } diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index bcfc5f1e9..1c27fd2a6 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -11,35 +11,98 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::promise::IsolatedPromise { bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); + } + return {}; } bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); + } + return {}; } bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); + } + + return {}; +} + +bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); + } + return {}; } std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); + } + return {}; } std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); + } + return {}; } JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); + } + return {"", "", ""}; } void /* int32_t */ await(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); + } } void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); + } + +} + +bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); + } + + return {}; +} +void /* int32_t */ cancel(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); + } } } From 009f8d89096a0e00712905657d3d60a2a423d736 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 28 Jun 2024 14:23:01 +0300 Subject: [PATCH 025/178] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- .../event/EventMapper.hpp | 4 + src/event/EventMapper.cpp | 400 +++++++----------- src/isolated/promise/IsolatedPromise.cpp | 101 +++-- 3 files changed, 213 insertions(+), 292 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/EventMapper.hpp b/include/dxfeed_graal_cpp_api/event/EventMapper.hpp index 9ad6531ef..3879ca98a 100644 --- a/include/dxfeed_graal_cpp_api/event/EventMapper.hpp +++ b/include/dxfeed_graal_cpp_api/event/EventMapper.hpp @@ -15,8 +15,12 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE struct DXFCPP_EXPORT EventMapper { + static std::shared_ptr fromGraal(void* graalNativeEvent); + static std::vector> fromGraalList(void *graalNativeList); + static void freeGraal(void *graalNativeEvent); + template static void *toGraalList(EventIt begin, EventIt end) { if constexpr (Debugger::isDebug) { Debugger::debug("EventMapper::toGraalList(symbols = " + elementsToString(begin, end) + ")"); diff --git a/src/event/EventMapper.cpp b/src/event/EventMapper.cpp index f0dc7a486..32add654a 100644 --- a/src/event/EventMapper.cpp +++ b/src/event/EventMapper.cpp @@ -16,6 +16,58 @@ DXFCPP_BEGIN_NAMESPACE +std::shared_ptr EventMapper::fromGraal(void *graalNativeEvent) { + if (!graalNativeEvent) { + throw std::invalid_argument("The `graalNativeEvent` is nullptr"); + } + + // TODO: implement other types [EN-8235] + switch (auto *e = dxfcpp::bit_cast(graalNativeEvent); e->clazz) { + case DXFG_EVENT_QUOTE: + return Quote::fromGraal(e); + case DXFG_EVENT_PROFILE: + return Profile::fromGraal(e); + case DXFG_EVENT_SUMMARY: + return Summary::fromGraal(e); + case DXFG_EVENT_GREEKS: + return Greeks::fromGraal(e); + case DXFG_EVENT_CANDLE: + return Candle::fromGraal(e); + case DXFG_EVENT_DAILY_CANDLE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + case DXFG_EVENT_UNDERLYING: + return Underlying::fromGraal(e); + case DXFG_EVENT_THEO_PRICE: + return TheoPrice::fromGraal(e); + case DXFG_EVENT_TRADE: + return Trade::fromGraal(e); + case DXFG_EVENT_TRADE_ETH: + return TradeETH::fromGraal(e); + case DXFG_EVENT_CONFIGURATION: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + case DXFG_EVENT_MESSAGE: + return Message::fromGraal(e); + case DXFG_EVENT_TIME_AND_SALE: + return TimeAndSale::fromGraal(e); + case DXFG_EVENT_ORDER_BASE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + case DXFG_EVENT_ORDER: + return Order::fromGraal(e); + case DXFG_EVENT_ANALYTIC_ORDER: + return AnalyticOrder::fromGraal(e); + case DXFG_EVENT_OTC_MARKETS_ORDER: + return OtcMarketsOrder::fromGraal(e); + case DXFG_EVENT_SPREAD_ORDER: + return SpreadOrder::fromGraal(e); + case DXFG_EVENT_SERIES: + return Series::fromGraal(e); + case DXFG_EVENT_OPTION_SALE: + return OptionSale::fromGraal(e); + default: + throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); + } +} + std::vector> EventMapper::fromGraalList(void *graalNativeList) { auto list = static_cast(graalNativeList); @@ -27,89 +79,7 @@ std::vector> EventMapper::fromGraalList(void *graalNa result.reserve(static_cast(list->size)); for (std::size_t i = 0; i < static_cast(list->size); i++) { - auto *e = list->elements[i]; - - // TODO: implement other types [EN-8235] - // TODO: type traits - switch (e->clazz) { - case DXFG_EVENT_QUOTE: - result.emplace_back(Quote::fromGraal(e)); - - break; - case DXFG_EVENT_PROFILE: - result.emplace_back(Profile::fromGraal(e)); - - break; - case DXFG_EVENT_SUMMARY: - result.emplace_back(Summary::fromGraal(e)); - - break; - case DXFG_EVENT_GREEKS: - result.emplace_back(Greeks::fromGraal(e)); - - break; - case DXFG_EVENT_CANDLE: - result.emplace_back(Candle::fromGraal(e)); - - break; - case DXFG_EVENT_DAILY_CANDLE: - break; - case DXFG_EVENT_UNDERLYING: - result.emplace_back(Underlying::fromGraal(e)); - - break; - case DXFG_EVENT_THEO_PRICE: - result.emplace_back(TheoPrice::fromGraal(e)); - - break; - case DXFG_EVENT_TRADE: - result.emplace_back(Trade::fromGraal(e)); - - break; - case DXFG_EVENT_TRADE_ETH: - result.emplace_back(TradeETH::fromGraal(e)); - - break; - case DXFG_EVENT_CONFIGURATION: - break; - case DXFG_EVENT_MESSAGE: - result.emplace_back(Message::fromGraal(e)); - - break; - case DXFG_EVENT_TIME_AND_SALE: - result.emplace_back(TimeAndSale::fromGraal(e)); - - break; - case DXFG_EVENT_ORDER_BASE: - break; - case DXFG_EVENT_ORDER: - result.emplace_back(Order::fromGraal(e)); - - break; - case DXFG_EVENT_ANALYTIC_ORDER: - result.emplace_back(AnalyticOrder::fromGraal(e)); - - break; - case DXFG_EVENT_OTC_MARKETS_ORDER: - result.emplace_back(OtcMarketsOrder::fromGraal(e)); - - break; - case DXFG_EVENT_SPREAD_ORDER: - result.emplace_back(SpreadOrder::fromGraal(e)); - - break; - case DXFG_EVENT_SERIES: - result.emplace_back(Series::fromGraal(e)); - - break; - case DXFG_EVENT_OPTION_SALE: - result.emplace_back(OptionSale::fromGraal(e)); - - break; - - default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); - } + result.emplace_back(fromGraal(list->elements[i])); } result.shrink_to_fit(); @@ -117,6 +87,95 @@ std::vector> EventMapper::fromGraalList(void *graalNa return result; } +void EventMapper::freeGraal(void *graalNativeEvent) { + if (!graalNativeEvent) { + return; + } + + // TODO: implement other types [EN-8235] + switch (auto *e = dxfcpp::bit_cast(graalNativeEvent); e->clazz) { + case DXFG_EVENT_QUOTE: + Quote::freeGraal(e); + + break; + case DXFG_EVENT_PROFILE: + Profile::freeGraal(e); + + break; + case DXFG_EVENT_SUMMARY: + Summary::freeGraal(e); + + break; + case DXFG_EVENT_GREEKS: + Greeks::freeGraal(e); + + break; + case DXFG_EVENT_CANDLE: + Candle::freeGraal(e); + + break; + case DXFG_EVENT_DAILY_CANDLE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + + case DXFG_EVENT_UNDERLYING: + Underlying::freeGraal(e); + + break; + case DXFG_EVENT_THEO_PRICE: + TheoPrice::freeGraal(e); + + break; + case DXFG_EVENT_TRADE: + Trade::freeGraal(e); + + break; + case DXFG_EVENT_TRADE_ETH: + TradeETH::freeGraal(e); + + break; + case DXFG_EVENT_CONFIGURATION: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + + case DXFG_EVENT_MESSAGE: + Message::freeGraal(e); + + break; + case DXFG_EVENT_TIME_AND_SALE: + TimeAndSale::freeGraal(e); + + break; + case DXFG_EVENT_ORDER_BASE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + + case DXFG_EVENT_ORDER: + Order::freeGraal(e); + + break; + case DXFG_EVENT_ANALYTIC_ORDER: + AnalyticOrder::freeGraal(e); + + break; + case DXFG_EVENT_OTC_MARKETS_ORDER: + OtcMarketsOrder::freeGraal(e); + + break; + case DXFG_EVENT_SPREAD_ORDER: + SpreadOrder::freeGraal(e); + + break; + case DXFG_EVENT_SERIES: + Series::freeGraal(e); + + break; + case DXFG_EVENT_OPTION_SALE: + OptionSale::freeGraal(e); + + break; + default: + throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); + } +} + void EventMapper::freeGraalList(void *graalList) { if constexpr (Debugger::isDebug) { Debugger::debug("EventMapper::freeGraalList(graalList = " + toStringAny(graalList) + ")"); @@ -133,90 +192,7 @@ void EventMapper::freeGraalList(void *graalList) { if (list->size > 0 && list->elements != nullptr) { for (SizeType elementIndex = 0; elementIndex < list->size; elementIndex++) { - if (list->elements[elementIndex]) { - auto *e = list->elements[elementIndex]; - - // TODO: implement other types [EN-8235] - // TODO: type traits - switch (e->clazz) { - case DXFG_EVENT_QUOTE: - Quote::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_PROFILE: - Profile::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SUMMARY: - Summary::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_GREEKS: - Greeks::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CANDLE: - Candle::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_DAILY_CANDLE: - break; - case DXFG_EVENT_UNDERLYING: - Underlying::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_THEO_PRICE: - TheoPrice::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE: - Trade::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE_ETH: - TradeETH::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CONFIGURATION: - break; - case DXFG_EVENT_MESSAGE: - Message::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TIME_AND_SALE: - TimeAndSale::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ORDER_BASE: - break; - case DXFG_EVENT_ORDER: - Order::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ANALYTIC_ORDER: - AnalyticOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OTC_MARKETS_ORDER: - OtcMarketsOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SPREAD_ORDER: - SpreadOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SERIES: - Series::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OPTION_SALE: - OptionSale::freeGraal(static_cast(e)); - - break; - default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); - } - } + freeGraal(list->elements[elementIndex]); } delete[] list->elements; @@ -231,7 +207,9 @@ std::ptrdiff_t EventMapper::calculateGraalListSize(std::ptrdiff_t initSize) noex if (initSize < 0) { return 0; - } else if (initSize > std::numeric_limits::max()) { + } + + if (initSize > std::numeric_limits::max()) { return std::numeric_limits::max(); } @@ -282,91 +260,7 @@ bool EventMapper::freeGraalListElements(void *graalList, std::ptrdiff_t count) { auto *list = static_cast(graalList); for (SizeType i = 0; i < count; i++) { - if (list->elements[i]) { - auto *e = list->elements[i]; - - // TODO: implement other types [EN-8235] - // TODO: type traits - switch (e->clazz) { - case DXFG_EVENT_QUOTE: - Quote::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_PROFILE: - Profile::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SUMMARY: - Summary::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_GREEKS: - Greeks::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CANDLE: - Candle::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_DAILY_CANDLE: - break; - case DXFG_EVENT_UNDERLYING: - Underlying::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_THEO_PRICE: - TheoPrice::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE: - Trade::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE_ETH: - TradeETH::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CONFIGURATION: - break; - case DXFG_EVENT_MESSAGE: - Message::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TIME_AND_SALE: - TimeAndSale::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ORDER_BASE: - break; - case DXFG_EVENT_ORDER: - Order::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ANALYTIC_ORDER: - AnalyticOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OTC_MARKETS_ORDER: - OtcMarketsOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SPREAD_ORDER: - SpreadOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SERIES: - Series::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OPTION_SALE: - OptionSale::freeGraal(static_cast(e)); - - break; - - default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); - } - } + freeGraal(list->elements[i]); } delete[] list->elements; diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index 1c27fd2a6..a3049a084 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -3,6 +3,7 @@ #include +#include #include #include @@ -10,101 +11,123 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::promise::IsolatedPromise { -bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ isDone(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_isDone, static_cast(promise)) == 1; } -bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_hasResult, static_cast(promise)) == 1; } -bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ hasException(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_hasException, static_cast(promise)) == + 1; } -bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_isCancelled, static_cast(promise)) == + 1; } -std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise) { +std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void *promise) { if (!promise) { throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); + "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); } - return {}; + auto *graalEvent = + runGraalFunctionAndThrowIfNullptr(dxfg_Promise_EventType_getResult, static_cast(promise)); + + auto result = dxfcpp::EventMapper::fromGraal(graalEvent); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_EventType_release, graalEvent); + + return result; } -std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise) { +std::vector> /* dxfg_event_type_list* */ +getResults(/* dxfg_promise_events_t * */ void *promise) { if (!promise) { throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); + "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); } - return {}; + auto *graalEvents = runGraalFunctionAndThrowIfNullptr(dxfg_Promise_List_EventType_getResult, + static_cast(promise)); + + auto result = dxfcpp::EventMapper::fromGraalList(graalEvents); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_EventType_release, graalEvents); + + return result; } -JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise) { +JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); } - return {"", "", ""}; + auto *graalException = + runGraalFunctionAndThrowIfNullptr(dxfg_Promise_getException, static_cast(promise)); + + auto result = JavaException::create(graalException); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_Exception_release, graalException); + + return result; } -void /* int32_t */ await(/* dxfg_promise_t * */ void* promise) { +void /* int32_t */ await(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); } + runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_await, static_cast(promise)); } -void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { +void /* int32_t */ await(/* dxfg_promise_t * */ void *promise, std::int32_t timeoutInMilliseconds) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); } + runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_await2, static_cast(promise), + timeoutInMilliseconds); } -bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { +bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void *promise, std::int32_t timeoutInMilliseconds) { if (!promise) { throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); + "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_awaitWithoutException, + static_cast(promise), timeoutInMilliseconds) == 1; } -void /* int32_t */ cancel(/* dxfg_promise_t * */ void* promise) { +void /* int32_t */ cancel(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); } -} + runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_cancel, static_cast(promise)); } +} // namespace isolated::promise::IsolatedPromise + DXFCPP_END_NAMESPACE From 349dd21b0e9e71a8fbd1848f32d0f4216e5a3b56 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 28 Jun 2024 15:24:21 +0300 Subject: [PATCH 026/178] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp | 8 ++++++++ src/isolated/promise/IsolatedPromise.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp index 7e6aaeb5a..e5c8a501b 100644 --- a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp @@ -46,6 +46,14 @@ constexpr auto throwIfMinusOne = [](auto v) { return JavaException::throwIfMinusOne(v); }; +constexpr auto runGraalFunction(auto graalFunction, auto &&...params) { + return runIsolatedThrow( + [](auto threadHandle, auto &&graalFunction, auto &&...params) { + return graalFunction(static_cast(threadHandle), params...); + }, + graalFunction, params...); +} + constexpr auto runGraalFunctionAndThrow(auto resultCheckerConverter, auto graalFunction, auto &&...params) { return runIsolatedThrow( [](auto threadHandle, auto &&resultCheckerConverter, auto &&graalFunction, auto &&...params) { diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index a3049a084..b88776ab2 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -51,8 +51,8 @@ std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_ev "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); } - auto *graalEvent = - runGraalFunctionAndThrowIfNullptr(dxfg_Promise_EventType_getResult, static_cast(promise)); + auto *graalEvent = runGraalFunctionAndThrowIfNullptr(dxfg_Promise_EventType_getResult, + static_cast(promise)); auto result = dxfcpp::EventMapper::fromGraal(graalEvent); @@ -69,7 +69,7 @@ getResults(/* dxfg_promise_events_t * */ void *promise) { } auto *graalEvents = runGraalFunctionAndThrowIfNullptr(dxfg_Promise_List_EventType_getResult, - static_cast(promise)); + static_cast(promise)); auto result = dxfcpp::EventMapper::fromGraalList(graalEvents); @@ -88,7 +88,7 @@ JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void * auto result = JavaException::create(graalException); - runGraalFunctionAndThrowIfLessThanZero(dxfg_Exception_release, graalException); + runGraalFunction(dxfg_Exception_release, graalException); return result; } From 46378433960daf774c8635cbc7717fa967d8d6d1 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 30 Jun 2024 01:00:46 +0300 Subject: [PATCH 027/178] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeed --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 21 +++++--- .../internal/JavaObjectHandle.hpp | 41 ++++++++++++++++ .../isolated/api/IsolatedDXFeed.hpp | 48 ++++++++++++++++++ .../dxfeed_graal_cpp_api/promise/Promise.hpp | 49 +++++++++++++++++-- src/api/DXFeed.cpp | 23 ++++++--- src/internal/JavaObjectHandle.cpp | 26 +++++++++- src/isolated/api/IsolatedDXFeed.cpp | 36 ++++++++++++++ 9 files changed, 226 insertions(+), 20 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp create mode 100644 src/isolated/api/IsolatedDXFeed.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f100aee1e..45f75ded4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,7 @@ set(dxFeedGraalCxxApi_Exceptions_Sources ) set(dxFeedGraalCxxApi_Isolated_Sources + src/isolated/api/IsolatedDXFeed.cpp src/isolated/api/IsolatedDXEndpoint.cpp src/isolated/api/IsolatedDXFeedSubscription.cpp src/isolated/api/IsolatedDXPublisher.cpp diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index a9e7c98b6..343660403 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -52,6 +52,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "exceptions/JavaException.hpp" #include "exceptions/GraalException.hpp" +#include "isolated/api/IsolatedDXFeed.hpp" #include "isolated/api/IsolatedDXEndpoint.hpp" #include "isolated/api/IsolatedDXFeedSubscription.hpp" #include "isolated/api/IsolatedDXPublisher.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index c264d79ea..a17650624 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -12,6 +12,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../internal/Handler.hpp" #include "../internal/Isolate.hpp" #include "../internal/JavaObjectHandle.hpp" +#include "../promise/Promise.hpp" #include "DXFeedSubscription.hpp" @@ -146,7 +147,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * * @return The DXFeed instance */ - static std::shared_ptr getInstance() noexcept; + static std::shared_ptr getInstance(); /** * Attaches the given subscription to this feed. This method does nothing if the @@ -164,7 +165,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param subscription The subscription. * @see DXFeedSubscription */ - void attachSubscription(std::shared_ptr subscription) noexcept; + void attachSubscription(std::shared_ptr subscription); /** * Detaches the given subscription from this feed. This method does nothing if the @@ -178,7 +179,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param subscription The subscription. * @see DXFeedSubscription */ - void detachSubscription(std::shared_ptr subscription) noexcept; + void detachSubscription(std::shared_ptr subscription); /** * Detaches the given subscription from this feed and clears data delivered to this subscription @@ -188,7 +189,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param subscription The subscription. * @see DXFeed::detachSubscription() */ - void detachSubscriptionAndClear(std::shared_ptr subscription) noexcept; + void detachSubscriptionAndClear(std::shared_ptr subscription); /** * Creates new subscription for a single event type that is attached to this feed. @@ -202,7 +203,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param eventType The type of event * @return The new subscription */ - std::shared_ptr createSubscription(const EventTypeEnum &eventType) noexcept; + std::shared_ptr createSubscription(const EventTypeEnum &eventType); /** * Creates new subscription for multiple event types that is attached to this feed. @@ -235,7 +236,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @return The new subscription */ template - std::shared_ptr createSubscription(EventTypeIt begin, EventTypeIt end) noexcept { + std::shared_ptr createSubscription(EventTypeIt begin, EventTypeIt end) { if constexpr (Debugger::isDebug) { Debugger::debug("{}::createSubscription(eventTypes = " + namesToString(begin, end) + ")"); } @@ -259,7 +260,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param eventTypes The initializer list of event types * @return The new subscription */ - std::shared_ptr createSubscription(std::initializer_list eventTypes) noexcept; + std::shared_ptr createSubscription(std::initializer_list eventTypes); /** * Creates new subscription for multiple event types that is attached to this feed. @@ -281,7 +282,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @return The new subscription */ template - std::shared_ptr createSubscription(EventTypesCollection &&eventTypes) noexcept { + std::shared_ptr createSubscription(EventTypesCollection &&eventTypes) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventTypes = " + namesToString(std::begin(eventTypes), std::end(eventTypes)) + ")"); @@ -294,6 +295,10 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return sub; } + Promise>> getTimeSeriesPromise(const EventTypeEnum &eventType, + const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime); + std::string toString() const noexcept override; }; diff --git a/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp b/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp index 7474193c6..7dd5b613f 100644 --- a/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp +++ b/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp @@ -55,6 +55,47 @@ template struct JavaObjectHandle { std::unique_ptr impl_; }; +template struct JavaObjectHandleList { +#if DXFCPP_DEBUG == 1 + static auto getDebugName() { + return std::string("JavaObjectHandleList<") + typeid(T).name() + ">"; + } +#endif + + using Type = T; + + static DXFCPP_EXPORT void deleter(void *handle) noexcept; + explicit JavaObjectHandleList(void *handle = nullptr) noexcept : impl_{handle, &deleter} { + if constexpr (Debugger::isDebug) { + Debugger::debug(getDebugName() + "(handle = " + dxfcpp::toString(handle) + ")"); + } + } + + JavaObjectHandleList(const JavaObjectHandleList &) = delete; + JavaObjectHandleList(JavaObjectHandleList &&) noexcept = default; + JavaObjectHandleList &operator=(const JavaObjectHandleList &) = delete; + JavaObjectHandleList &operator=(JavaObjectHandleList &&) noexcept = default; + virtual ~JavaObjectHandleList() noexcept = default; + + [[nodiscard]] std::string toString() const noexcept { + if (impl_) + return dxfcpp::toString(impl_.get()); + else + return "nullptr"; + } + + [[nodiscard]] void *get() const noexcept { + return impl_.get(); + } + + explicit operator bool() const noexcept { + return static_cast(impl_); + } + + private: + std::unique_ptr impl_; +}; + DXFCPP_END_NAMESPACE DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp new file mode 100644 index 000000000..8fe95894e --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include "../../api/DXFeed.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeed { + +/* + +dxfg_feed_t* dxfg_DXFeed_getInstance(graal_isolatethread_t *thread); +dxfg_subscription_t* dxfg_DXFeed_createSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz); +dxfg_subscription_t* dxfg_DXFeed_createSubscription2(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); +dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz); +dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription2(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); +int32_t dxfg_DXFeed_attachSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +int32_t dxfg_DXFeed_detachSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +int32_t dxfg_DXFeed_detachSubscriptionAndClear(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +dxfg_event_type_t* dxfg_DXFeed_getLastEventIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); +dxfg_event_type_list* dxfg_DXFeed_getIndexedEventsIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, const char *source); +dxfg_event_type_list* dxfg_DXFeed_getTimeSeriesIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, int64_t from_time, int64_t to_time); +// use dxfg_EventType_new to create an empty structure so that java tries to free up memory when replacing subjects +int32_t dxfg_DXFeed_getLastEvent(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_t *event); +int32_t dxfg_DXFeed_getLastEvents(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_list *events); +dxfg_promise_event_t* dxfg_DXFeed_getLastEventPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); +dxfg_promise_list* dxfg_DXFeed_getLastEventsPromises(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_list *symbols); +dxfg_promise_events_t* dxfg_DXFeed_getIndexedEventsPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, dxfg_indexed_event_source_t* source); +dxfg_promise_events_t* dxfg_DXFeed_getTimeSeriesPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t clazz, dxfg_symbol_t *symbol, int64_t fromTime, int64_t toTime); + +*/ + + +/* dxfg_promise_events_t* */ void* getTimeSeriesPromise(/* dxfg_feed_t * */ const JavaObjectHandle& feed, /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, /* dxfg_symbol_t * */ const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime); + + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp index 09ff4bb58..738480fba 100644 --- a/include/dxfeed_graal_cpp_api/promise/Promise.hpp +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -7,16 +7,57 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include +#include + DXFCPP_BEGIN_NAMESPACE -template -struct Promise {}; +struct TimeSeriesEvent; +struct LastingEvent; + +struct PromiseImpl { + +}; + +template struct Promise { +}; + +template +concept Derived = std::is_base_of_v; -template <> -struct Promise> { +template T> struct Promise> { }; +template T> struct Promise> { + +}; + +template T> struct Promise>> { + +}; + + +// +// Promise> x{}; +// auto _ = x.z(); +// +// template struct PromiseSFINAE { +// int x() { +// return {}; +// } +// }; +// +// template +// struct PromiseSFINAE::value>::type> { +// int z() { +// return 0; +// } +// }; +// +// PromiseSFINAE> xx{}; +// auto __ = xx.z(); + DXFCPP_END_NAMESPACE DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 087c05fc3..170f95c35 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -16,7 +16,7 @@ DXFCPP_BEGIN_NAMESPACE -std::shared_ptr DXFeed::getInstance() noexcept { +std::shared_ptr DXFeed::getInstance() { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeed::getInstance()"); } @@ -24,7 +24,7 @@ std::shared_ptr DXFeed::getInstance() noexcept { return DXEndpoint::getInstance()->getFeed(); } -void DXFeed::attachSubscription(std::shared_ptr subscription) noexcept { +void DXFeed::attachSubscription(std::shared_ptr subscription) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::attachSubscription(" + subscription->toString() + ")"); } @@ -43,7 +43,7 @@ void DXFeed::attachSubscription(std::shared_ptr subscription } } -void DXFeed::detachSubscription(std::shared_ptr subscription) noexcept { +void DXFeed::detachSubscription(std::shared_ptr subscription) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::detachSubscription(" + subscription->toString() + ")"); } @@ -62,7 +62,7 @@ void DXFeed::detachSubscription(std::shared_ptr subscription } } -void DXFeed::detachSubscriptionAndClear(std::shared_ptr subscription) noexcept { +void DXFeed::detachSubscriptionAndClear(std::shared_ptr subscription) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::detachSubscriptionAndClear(" + subscription->toString() + ")"); } @@ -81,7 +81,7 @@ void DXFeed::detachSubscriptionAndClear(std::shared_ptr subs } } -std::shared_ptr DXFeed::createSubscription(const EventTypeEnum &eventType) noexcept { +std::shared_ptr DXFeed::createSubscription(const EventTypeEnum &eventType) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventType = " + eventType.getName() + ")"); } @@ -93,8 +93,7 @@ std::shared_ptr DXFeed::createSubscription(const EventTypeEn return sub; } -std::shared_ptr -DXFeed::createSubscription(std::initializer_list eventTypes) noexcept { +std::shared_ptr DXFeed::createSubscription(std::initializer_list eventTypes) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventTypes = " + namesToString(eventTypes.begin(), eventTypes.end()) + ")"); @@ -122,6 +121,16 @@ std::shared_ptr DXFeed::create(void *feedHandle) { return feed; } +Promise>> DXFeed::getTimeSeriesPromise(const EventTypeEnum &eventType, + const SymbolWrapper &symbol, + std::int64_t fromTime, + std::int64_t toTime) { + + // TODO: impelement + + return {}; +} + std::string DXFeed::toString() const noexcept { return fmt::format("DXFeed{{{}}}", handle_.toString()); } diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index 21893ddc0..87e84284e 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -26,7 +26,31 @@ template void JavaObjectHandle::deleter(void *handle) noexcept { dxfcpp::ignore_unused(result); if constexpr (Debugger::isDebug) { - Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ") -> " + dxfcpp::toString(result)); + Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ") -> " + + dxfcpp::toString(result)); + } +} + +template void JavaObjectHandleList::deleter(void *handle) noexcept { + auto result = runIsolatedOrElse( + [handle = handle](auto threadHandle) { + if constexpr (Debugger::isDebug) { + Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ")"); + } + + if (handle) { + return dxfg_CList_JavaObjectHandler_release(static_cast(threadHandle), + static_cast(handle)) == 0; + } + + return true; + }, + false); + dxfcpp::ignore_unused(result); + + if constexpr (Debugger::isDebug) { + Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ") -> " + + dxfcpp::toString(result)); } } diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp new file mode 100644 index 000000000..1358bd752 --- /dev/null +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeed { + +/* dxfg_promise_events_t* */ void *getTimeSeriesPromise(/* dxfg_feed_t * */ const JavaObjectHandle &feed, + /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, + /* dxfg_symbol_t * */ const SymbolWrapper &symbol, + std::int64_t fromTime, std::int64_t toTime) { + if (!feed) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeed_getTimeSeriesPromise`. The `feed` handle is invalid"); + } + + auto graalSymbol = symbol.toGraal(); + + auto result = dxfcpp::bit_cast( + runGraalFunctionAndThrowIfNullptr(dxfg_DXFeed_getTimeSeriesPromise, static_cast(feed.get()), + static_cast(eventType.getId()), + static_cast(graalSymbol), fromTime, toTime)); + + SymbolWrapper::freeGraal(graalSymbol); + + return result; +} + +} // namespace isolated::api::IsolatedDXFeed + +DXFCPP_END_NAMESPACE \ No newline at end of file From 20ccd9fb9aaf22b7543f53eb76bb09848f5aeef8 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 1 Jul 2024 00:38:21 +0300 Subject: [PATCH 028/178] [EN-7587] Implement FetchDailyCandles sample --- CMakeLists.txt | 5 + README.md | 2 + include/dxfeed_graal_cpp_api/api.hpp | 1 + include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 21 +- .../dxfeed_graal_cpp_api/promise/Promise.hpp | 343 ++++++++++++++++-- samples/cpp/FetchDailyCandles/src/main.cpp | 14 +- src/api/DXFeed.cpp | 11 +- src/exceptions/JavaException.cpp | 2 +- src/internal/JavaObjectHandle.cpp | 4 + src/promise/Promise.cpp | 80 ++++ 10 files changed, 437 insertions(+), 46 deletions(-) create mode 100644 src/promise/Promise.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f75ded4..154d73136 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,10 @@ set(dxFeedGraalCxxApi_OnDemand_Sources src/ondemand/OnDemandService.cpp ) +set(dxFeedGraalCxxApi_Promise_Sources + src/promise/Promise.cpp +) + set(dxFeedGraalCxxApi_Symbols_Sources src/symbols/StringSymbol.cpp src/symbols/SymbolWrapper.cpp @@ -317,6 +321,7 @@ set(dxFeedGraalCxxApi_Sources ${dxFeedGraalCxxApi_ApiOsub_Sources} ${dxFeedGraalCxxApi_Ipf_Sources} ${dxFeedGraalCxxApi_OnDemand_Sources} + ${dxFeedGraalCxxApi_Promise_Sources} ${dxFeedGraalCxxApi_Symbols_Sources} ${dxFeedGraalCxxApi_System_Sources} ${dxFeedGraalCxxApi_Event_Sources} diff --git a/README.md b/README.md index 7e65d43ad..e8e09ffd1 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,8 @@ versions): is a simple demonstration of how to get various scheduling information for instruments - [x] [OnDemandSample](https://github.com/dxFeed/dxfeed-graal-cxx-api/blob/main/samples/cpp/OnDemandSample/src/main.cpp) a sample that demonstrates how to use the dxFeed on-demand history data replay service API +- [x] [FetchDailyCandles](https://github.com/dxFeed/dxfeed-graal-cxx-api/blob/main/samples/cpp/FetchDailyCandles/src/main.cpp) + a sample that demonstrates how to fetch last 20 days of candles for a specified symbol and print them. ## Current State diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 343660403..26a9222fb 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -58,6 +58,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/api/IsolatedDXPublisher.hpp" #include "isolated/api/IsolatedDXPublisherObservableSubscription.hpp" #include "isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp" +#include "isolated/promise/IsolatedPromise.hpp" #include "isolated/internal/IsolatedString.hpp" #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index a17650624..acce0eae5 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -125,6 +125,9 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { JavaObjectHandle handle_; static std::shared_ptr create(void *feedHandle); + void *getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime) const; + protected: DXFeed() noexcept : handle_{} { if constexpr (Debugger::isDebug) { @@ -295,9 +298,21 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return sub; } - Promise>> getTimeSeriesPromise(const EventTypeEnum &eventType, - const SymbolWrapper &symbol, std::int64_t fromTime, - std::int64_t toTime); + /** + * Requests time series of events for the specified event type, symbol, and a range of time. + * @tparam E The type of event. + * @param symbol The symbol. + * @param fromTime The time, inclusive, to request events from (see TimeSeriesEvent::getTime()). + * @param toTime The time, inclusive, to request events to (see TimeSeriesEvent::getTime()). + * Use `std::numeric_limits::max()` or `LLONG_MAX` macro to retrieve events without an + * upper limit on time. + * @return The promise for the result of the request. + */ + template E> + Promise>> getTimeSeriesPromise(const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime) const { + return Promise>>(getTimeSeriesPromiseImpl(E::TYPE, symbol, fromTime, toTime)); + } std::string toString() const noexcept override; }; diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp index 738480fba..5bfc5c809 100644 --- a/include/dxfeed_graal_cpp_api/promise/Promise.hpp +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -3,60 +3,349 @@ #pragma once +#include "../exceptions/JavaException.hpp" #include "../internal/Conf.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include #include #include DXFCPP_BEGIN_NAMESPACE -struct TimeSeriesEvent; -struct LastingEvent; +struct EventType; +struct JavaException; + +template +concept Derived = std::is_base_of_v; + +template EDerived> +std::shared_ptr convertEvent(const std::shared_ptr &source) { + return source->template sharedAs(); +} + +template EDerived> +std::vector> convertEvents(const std::vector> &source) { + std::vector> result{}; + + result.reserve(source.size()); + + for (const auto &e : source) { + result.emplace_back(e->template sharedAs()); + } + + return result; +} struct PromiseImpl { + protected: + void *handle = nullptr; + + public: + explicit PromiseImpl(void *handle); + bool isDone() const; + bool hasResult() const; + bool hasException() const; + bool isCancelled() const; + JavaException getException() const; + void await() const; + void await(std::int32_t timeoutInMilliseconds) const; + bool awaitWithoutException(std::int32_t timeoutInMilliseconds) const; + void cancel() const; }; -template struct Promise { +struct EventPromiseImpl : PromiseImpl { + void *handle = nullptr; + + explicit EventPromiseImpl(void *handle); + ~EventPromiseImpl(); + std::shared_ptr getResult() const; }; -template -concept Derived = std::is_base_of_v; +struct EventsPromiseImpl : PromiseImpl { + void *handle = nullptr; + + explicit EventsPromiseImpl(void *handle); + ~EventsPromiseImpl(); + std::vector> getResult() const; +}; + +/** + * Mixin for wrapping calls to common promise methods. + * + * @tparam P The promise type + */ +template struct CommonPromiseMixin { + /** + * Returns `true` when computation has completed normally, or exceptionally, or was cancelled. + * + * @return `true` when computation has completed. + */ + bool isDone() const { + return static_cast(this)->impl.isDone(); + } + + /** + * Returns `true` when computation has completed normally. + * Use ::getResult() method to get the result of the computation. + * @return `true` when computation has completed normally. + * @see ::getResult() + */ + bool hasResult() const { + return static_cast(this)->impl.hasResult(); + } + + /** + * Returns `true` when computation has completed exceptionally or was cancelled. + * Use ::getException() method to get the exceptional outcome of the computation. + * @return `true` when computation has completed exceptionally or was cancelled. + */ + bool hasException() const { + return static_cast(this)->impl.hasException(); + } + + /** + * Returns `true` when computation was cancelled. + * Use ::getException() method to get the corresponding CancellationException. + * @return `true` when computation was cancelled. + * @see ::getException() + */ + bool isCancelled() const { + return static_cast(this)->impl.isCancelled(); + } + + /** + * Returns exceptional outcome of computation. If computation has no ::hasException() exception, + * then this method returns an exception with a message "null". If computation has completed exceptionally or was + * cancelled, then the result of this method is not an exception with a message "null". If computation was @ref + * ::isCancelled() "cancelled", then this method returns "an instance of CancellationException". + * + * @return exceptional outcome of computation. + * @see ::hasException() + */ + JavaException getException() const { + return static_cast(this)->impl.getException(); + } + + /** + * Wait for computation to complete or timeout or throw an exception in case of exceptional completion. + * If the wait is interrupted, then the computation is @ref ::cancel() "cancelled", + * the interruption flag on the current thread is set, and "CancellationException" is thrown. + * + *

If the wait times out, then the computation is @ref ::cancel() "cancelled" and this method returns `false`. + * Use this method in the code that shall continue normal execution in case of timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return `true` if the computation has completed normally; `false` when wait timed out. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + bool awaitWithoutException(std::int32_t timeoutInMilliseconds) const { + return static_cast(this)->impl.awaitWithoutException(timeoutInMilliseconds); + } + + /** + * Wait for computation to complete or timeout or throw an exception in case of exceptional completion. + * If the wait is interrupted, then the computation is @ref ::cancel() "cancelled", + * the interruption flag on the current thread is set, and "CancellationException" is thrown. + * + *

If the wait times out, then the computation is @ref ::cancel() "cancelled" and this method returns `false`. + * Use this method in the code that shall continue normal execution in case of timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return `true` if the computation has completed normally; `false` when wait timed out. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + bool awaitWithoutException(const std::chrono::milliseconds &timeoutInMilliseconds) const { + auto timeout = timeoutInMilliseconds.count(); + + if (timeout > std::numeric_limits::max()) { + timeout = std::numeric_limits::max(); + } -template T> struct Promise> { + return static_cast(this)->impl.awaitWithoutException(timeout); + } + /** + * Cancels computation. This method does nothing if computation has already @ref ::isDone() "completed". + * + *

If cancelled, then ::getException() will return "CancellationException", + * @ref ::isDone() "isDone", @ref ::isCancelled() "isCancelled", and @ref ::hasException() "hasException" will + * return `true`, all handlers that were installed with `whenDone` method are notified by invoking their + * `promiseDone` method, and all waiters on @ref ::await() "join" method throw "CancellationException". + */ + void cancel() const { + static_cast(this)->impl.cancel(); + } }; -template T> struct Promise> { +/** + * Mixin for wrapping Promise method calls for a single event. + * @tparam E The event type. + * @tparam P The promise type. + */ +template struct EventPromiseMixin { + /** + * Returns result of computation. If computation has no @ref CommonPromiseMixin::hasResult() "result", then + * this method returns `std::shared_ptr(nullptr)`. + * + * @return The result of computation. + * @see CommonPromiseMixin::hasResult() + */ + std::shared_ptr getResult() const { + return convertEvent(static_cast(this)->impl.getResult()); + } + /** + * Wait for computation to complete and return its result or throw an exception in case of exceptional completion. + * @return result of computation. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + std::shared_ptr await() const { + static_cast(this)->impl.await(); + + return getResult(); + } + + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::shared_ptr await(std::int32_t timeoutInMilliseconds) const & { + static_cast(this)->impl.await(timeoutInMilliseconds); + + return getResult(); + } + + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::shared_ptr await(const std::chrono::milliseconds &timeoutInMilliseconds) const & { + auto timeout = timeoutInMilliseconds.count(); + + if (timeout > std::numeric_limits::max()) { + timeout = std::numeric_limits::max(); + } + + static_cast(this)->impl.await(timeout); + + return getResult(); + } }; -template T> struct Promise>> { +template struct EventsPromiseMixin { + /** + * Returns result of computation. If computation has no @ref CommonPromiseMixin::hasResult() "result", then + * this method returns an empty ollection. + * + * @return The result of computation. + * @see CommonPromiseMixin::hasResult() + */ + std::vector> getResult() const { + return convertEvents(static_cast(this)->impl.getResult()); + } + + /** + * Wait for computation to complete and return its result or throw an exception in case of exceptional completion. + * @return result of computation. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + std::vector> await() const { + static_cast(this)->impl.await(); + + return getResult(); + } + + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::vector> await(std::int32_t timeoutInMilliseconds) const & { + static_cast(this)->impl.await(timeoutInMilliseconds); + + return getResult(); + } + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::vector> await(const std::chrono::milliseconds &timeoutInMilliseconds) const & { + auto timeout = timeoutInMilliseconds.count(); + + if (timeout > std::numeric_limits::max()) { + timeout = std::numeric_limits::max(); + } + + static_cast(this)->impl.await(timeout); + + return getResult(); + } +}; + +/** + * Result of a computation that will be completed normally or exceptionally in the future. + * @tparam T The result type. + */ +template struct Promise {}; + +/** + * Result of an event receiving that will be completed normally or exceptionally in the future. + * @tparam E The event type. + */ +template +struct Promise> : CommonPromiseMixin>>, + EventPromiseMixin>> { + friend struct CommonPromiseMixin; + friend struct EventPromiseMixin; + + EventsPromiseImpl impl; + + explicit Promise(void *handle) : impl(handle) { + } }; +/** + * Result of an collection of events receiving that will be completed normally or exceptionally in the future. + * @tparam E The event type. + */ +template +struct Promise>> : CommonPromiseMixin>>>, + EventsPromiseMixin>>> { + friend struct CommonPromiseMixin; + friend struct EventsPromiseMixin; -// -// Promise> x{}; -// auto _ = x.z(); -// -// template struct PromiseSFINAE { -// int x() { -// return {}; -// } -// }; -// -// template -// struct PromiseSFINAE::value>::type> { -// int z() { -// return 0; -// } -// }; -// -// PromiseSFINAE> xx{}; -// auto __ = xx.z(); + EventsPromiseImpl impl; + + explicit Promise(void *handle) : impl(handle) { + } +}; DXFCPP_END_NAMESPACE diff --git a/samples/cpp/FetchDailyCandles/src/main.cpp b/samples/cpp/FetchDailyCandles/src/main.cpp index 9ef1f6726..a2d653922 100644 --- a/samples/cpp/FetchDailyCandles/src/main.cpp +++ b/samples/cpp/FetchDailyCandles/src/main.cpp @@ -8,13 +8,13 @@ void fetchAndPrint(const dxfcpp::CandleSymbol &candleSymbol, std::int64_t toTime, std::int64_t fromTime) { // Use default DXFeed instance for that data feed address is defined by dxfeed.properties file - // auto result = dxfcpp::DXFeed::getInstance() - // ->getTimeSeriesPromise(candleSymbol, fromTime, toTime) - // ->await(std::chrono::seconds(5)); - // - // for (auto candle : result) { - // std::cout << candle->toString(); - // } + auto result = dxfcpp::DXFeed::getInstance() + ->getTimeSeriesPromise(candleSymbol, fromTime, toTime) + .await(std::chrono::seconds(5)); + + for (const auto &candle : result) { + std::cout << candle->toString() << "\n"; + } } // Fetches last 20 days of candles for a specified symbol, prints them, and exits. diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 170f95c35..1925bd97e 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -121,14 +121,9 @@ std::shared_ptr DXFeed::create(void *feedHandle) { return feed; } -Promise>> DXFeed::getTimeSeriesPromise(const EventTypeEnum &eventType, - const SymbolWrapper &symbol, - std::int64_t fromTime, - std::int64_t toTime) { - - // TODO: impelement - - return {}; +void *DXFeed::getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol, + std::int64_t fromTime, std::int64_t toTime) const { + return isolated::api::IsolatedDXFeed::getTimeSeriesPromise(handle_, eventType, symbol, fromTime, toTime); } std::string DXFeed::toString() const noexcept { diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 7ee697f33..b3ee9a5a8 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -98,7 +98,7 @@ JavaException::JavaException(const std::string &message, const std::string &clas JavaException JavaException::create(void *exceptionHandle) { if (exceptionHandle == nullptr) { - return {"", "", ""}; + return {"null", "", ""}; } auto *exception = dxfcpp::bit_cast(exceptionHandle); diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index 87e84284e..d45ac45a6 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -83,4 +83,8 @@ template struct JavaObjectHandle; template struct JavaObjectHandle; template struct JavaObjectHandle; +template struct JavaObjectHandle; +template struct JavaObjectHandle; +template struct JavaObjectHandle; + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/promise/Promise.cpp b/src/promise/Promise.cpp new file mode 100644 index 000000000..f36d0ef72 --- /dev/null +++ b/src/promise/Promise.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +PromiseImpl::PromiseImpl(void *handle) : handle(handle) { +} + +bool PromiseImpl::isDone() const { + return isolated::promise::IsolatedPromise::isDone(handle); +} + +bool PromiseImpl::hasResult() const { + return isolated::promise::IsolatedPromise::hasResult(handle); +} + +bool PromiseImpl::hasException() const { + return isolated::promise::IsolatedPromise::hasException(handle); +} + +bool PromiseImpl::isCancelled() const { + return isolated::promise::IsolatedPromise::isCancelled(handle); +} + +JavaException PromiseImpl::getException() const { + return isolated::promise::IsolatedPromise::getException(handle); +} + +void PromiseImpl::await() const { + isolated::promise::IsolatedPromise::await(handle); +} + +void PromiseImpl::await(std::int32_t timeoutInMilliseconds) const { + isolated::promise::IsolatedPromise::await(handle, timeoutInMilliseconds); +} + +bool PromiseImpl::awaitWithoutException(std::int32_t timeoutInMilliseconds) const { + return isolated::promise::IsolatedPromise::awaitWithoutException(handle, timeoutInMilliseconds); +} + +void PromiseImpl::cancel() const { + isolated::promise::IsolatedPromise::cancel(handle); +} + +EventPromiseImpl::EventPromiseImpl(void *handle) : PromiseImpl(handle), handle(handle) { +} + +EventPromiseImpl::~EventPromiseImpl() { + JavaObjectHandle::deleter(handle); +} + +std::shared_ptr EventPromiseImpl::getResult() const { + return isolated::promise::IsolatedPromise::getResult(handle); +} + +EventsPromiseImpl::EventsPromiseImpl(void *handle) : PromiseImpl(handle), handle(handle) { +} + +EventsPromiseImpl::~EventsPromiseImpl() { + JavaObjectHandle::deleter(handle); +} + +std::vector> EventsPromiseImpl::getResult() const { + return isolated::promise::IsolatedPromise::getResults(handle); +} + +DXFCPP_END_NAMESPACE \ No newline at end of file From 7bf504db7e2e7c13192f1bc1351a0f5313fc50d2 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 1 Jul 2024 18:04:38 +0300 Subject: [PATCH 029/178] [MDAPI-26] Update Graal SDK to v1.1.21 Day::getSessions --- CMakeLists.txt | 3 +- .../dxfeed_graal_cpp_api/internal/Common.hpp | 11 +- .../isolated/Isolated.hpp | 1 + include/dxfeed_graal_cpp_api/schedule/Day.hpp | 6 + src/internal/Isolate.cpp | 13 ++ src/schedule/Day.cpp | 29 +++ tests/CMakeLists.txt | 3 +- tests/schedule/ScheduleTest.cpp | 192 ++++++++++++++++++ tools/Tools/src/Args/Args.hpp | 6 +- 9 files changed, 258 insertions(+), 6 deletions(-) create mode 100644 tests/schedule/ScheduleTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 337bfe0ef..7098425a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,12 +17,13 @@ project(dxFeedGraalCxxApi) set(DXFCXX_VERSION "v2.0.0" CACHE STRING "The dxFeed Graal CXX API package version") -set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.16" CACHE STRING "") +set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.21" CACHE STRING "") set(FMTLIB_VERSION "10.2.1") set(BOOST_VERSION "1.84.0") set(UTFCPP_VERSION "3.2.3") set(DATE_VERSION "3.0.1") set(RANGE_VERSION "0.12") +set(DOCTEST_VERSION "2.4.11") set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index e672160fe..65fa9a8a4 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -184,7 +184,16 @@ static constexpr std::int32_t getNanoPartFromNanos(std::int64_t timeNanos) { namespace time_util { /// Number of milliseconds in a second. -static const std::int64_t SECOND = 1000LL; +static constexpr std::int64_t SECOND = 1000LL; + +/// Number of milliseconds in a minute. +static constexpr std::int64_t MINUTE = 60LL * SECOND; + +/// Number of milliseconds in an hour. +static constexpr std::int64_t HOUR = 60LL * MINUTE; + +/// Number of milliseconds in an day. +static constexpr std::int64_t DAY = 24LL * HOUR; /** * Returns correct number of milliseconds with proper handling negative values. diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 064b5315f..cd471eb0a 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -146,6 +146,7 @@ struct Day { static std::int64_t getEndTime(/* dxfg_day_t* */ void *day) noexcept; static bool containsTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept; static std::int64_t getResetTime(/* dxfg_day_t* */ void *day) noexcept; + static /* dxfg_session_list* */ void* getSessions(/* dxfg_day_t* */ void *day); static /* dxfg_session_t* */ void *getSessionByTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept; static /* dxfg_session_t* */ void *getFirstSession(/* dxfg_day_t* */ void *day, /* dxfg_session_filter_t* */ void *filter) noexcept; diff --git a/include/dxfeed_graal_cpp_api/schedule/Day.hpp b/include/dxfeed_graal_cpp_api/schedule/Day.hpp index c0e3ca5e3..8db375629 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Day.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Day.hpp @@ -137,6 +137,12 @@ struct DXFCPP_EXPORT Day { */ std::int64_t getResetTime() const noexcept; + /** + * @return collection of sessions that constitute this day. + * The list is ordered according to natural order of sessions - how they occur one after another. + */ + std::vector> getSessions() const; + /** * Returns session belonging to this day that contains specified time. * If no such session was found within this day this method will return Session::Ptr{nullptr} diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 6f6c870c1..7ede41b8a 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -957,6 +957,19 @@ std::int64_t Day::getResetTime(/* dxfg_day_t* */ void *day) noexcept { 0, static_cast(day)); } +/* dxfg_session_list* */ void *Day::getSessions(/* dxfg_day_t* */ void *day) { + if (!day) { + // TODO: Improve error handling + return nullptr; + } + + return static_cast(runIsolatedOrElse( + [](auto threadHandle, auto &&day) { + return dxfg_Day_getSessions(static_cast(threadHandle), day); + }, + nullptr, static_cast(day))); +} + /* dxfg_session_t* */ void *Day::getSessionByTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept { if (!day) { // TODO: Improve error handling diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index fcc59767f..5dda74cee 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -5,6 +5,7 @@ #include #include +#include DXFCPP_BEGIN_NAMESPACE @@ -132,6 +133,34 @@ std::int64_t Day::getResetTime() const noexcept { return isolated::schedule::Day::getResetTime(handle_.get()); } +std::vector> Day::getSessions() const { + if (!handle_) { + return {}; + } + + auto* graalSessionList = isolated::schedule::Day::getSessions(handle_.get()); + + if (!graalSessionList) { + return {}; + } + + auto* sessionList = dxfcpp::bit_cast(graalSessionList); + std::vector> result; + + if (sessionList->size > 0 && sessionList->elements) { + result.reserve(static_cast(sessionList->size)); + + for (std::int32_t i = 0; i < sessionList->size; i++) { + result.emplace_back(Session::create(sessionList->elements[i])); + } + } + + isolated::runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, + sessionList); + + return result; +} + std::shared_ptr Day::getSessionByTime(std::int64_t time) const noexcept { if (!handle_) { return {}; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 12672f471..15e910142 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -17,7 +17,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_C_STANDARD 11) set(CXX_EXTENSIONS OFF) -set(DXFC_TEST_INCLUDE_DIRS ../include ../third_party/doctest-2.4.11) +set(DXFC_TEST_INCLUDE_DIRS ../include ../third_party/doctest-${DOCTEST_VERSION} ../third_party/range-v3-${RANGE_VERSION}/include) set(DXFC_TEST_SOURCES exceptions/ExceptionsTest.cpp @@ -28,6 +28,7 @@ set(DXFC_TEST_SOURCES api/EventsTest.cpp api/MarketEventSymbolsTest.cpp api/OrderSourceTest.cpp + schedule/ScheduleTest.cpp system/SystemTest.cpp) #add_definitions(-DDXFCPP_DEBUG -DDXFCPP_DEBUG_ISOLATES) diff --git a/tests/schedule/ScheduleTest.cpp b/tests/schedule/ScheduleTest.cpp new file mode 100644 index 000000000..39973c6b4 --- /dev/null +++ b/tests/schedule/ScheduleTest.cpp @@ -0,0 +1,192 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +using namespace dxfcpp; +using namespace dxfcpp::literals; +using namespace std::literals; + +decltype(ranges::views::filter([](const auto &s) { + return !s.empty(); +})) filterNonEmpty{}; + +decltype(ranges::views::transform([](auto &&s) { + return s | ranges::to(); +})) transformToString{}; + +decltype(ranges::views::transform([](const std::string &s) { + return trimStr(s); +})) trim{}; + +auto splitAndTrim = [](auto &&string, char sep = ',') noexcept { + return string | ranges::views::split(sep) | filterNonEmpty | transformToString | trim; +}; + +std::shared_ptr gmt(const std::string &extra) { + return Schedule::getInstance("(tz=GMT;" + extra + ")"); +} + +void check(const std::string &extra, const std::string ×, const std::string &types) { + auto sessions = gmt(extra)->getDayById(42)->getSessions(); + auto timeArray = splitAndTrim(times) | ranges::to>(); + auto typeArray = splitAndTrim(types) | ranges::to>(); + + REQUIRE(timeArray.size() == sessions.size()); + REQUIRE(typeArray.size() == sessions.size()); + + for (std::size_t i = 0; i < sessions.size(); i++) { + auto s = sessions[i]; + auto time = std::stoll(timeArray[i]); + + time = time / 10000 * time_util::HOUR + time / 100 % 100 * time_util::MINUTE + time % 100 * time_util::SECOND; + + REQUIRE(time == s->getStartTime() % time_util::DAY); + REQUIRE(typeArray[i] == s->getType().getName()); + } +} + +TEST_CASE("Test Parsing") { + REQUIRE(0 == gmt("0=")->getDayById(42)->getStartTime() % time_util::DAY); + REQUIRE(23LL * time_util::HOUR == gmt("de=2300;0=")->getDayById(42)->getStartTime() % time_util::DAY); + REQUIRE(0 == + gmt("0=01000200")->getDayById(42)->getNextDay(DayFilter::NON_TRADING)->getStartTime() % time_util::DAY); + REQUIRE(1 == gmt("0=01000200")->getDayById(42)->getNextDay(DayFilter::NON_TRADING)->getSessions().size()); + REQUIRE(time_util::HOUR == + gmt("0=01000200")->getNearestSessionByTime(now(), SessionFilter::TRADING)->getStartTime() % time_util::DAY); + + check("0=", "000000", "NO_TRADING"); + check("0=01000200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=0100/0200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=+-0100-+0200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=+-0100/-+0200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r01000200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r0100/0200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r+-0100-+0200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r+-0100/-+0200", "000000,010000,020000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=010002000300040005000600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING"); + check("0=0100/02000300/04000500/0600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING"); + check("0=+-0100-+0200+-0300-+0400+-0500-+0600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING"); + check("0=+-0100/-+0200+-0300/-+0400+-0500/-+0600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING,REGULAR,NO_TRADING"); + check("0=p01000200r03000400a05000600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + check("0=p0100/0200r0300/0400a0500/0600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + check("0=p+-0100-+0200r+-0300-+0400a+-0500-+0600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + check("0=p+-0100/-+0200r+-0300/-+0400a+-0500/-+0600", "000000,010000,020000,030000,040000,050000,060000", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + + check("0=010203020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=010203/020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=+-010203-+020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=+-010203/-+020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r010203020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r010203/020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r+-010203-+020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r+-010203/-+020406", "000000,010203,020406", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=p010203020406r030507040608a050709060810", "000000,010203,020406,030507,040608,050709,060810", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + check("0=p010203/020406r030507/040608a050709/060810", "000000,010203,020406,030507,040608,050709,060810", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + check("0=p+-010203-+020406r+-030507-+040608a+-050709-+060810", "000000,010203,020406,030507,040608,050709,060810", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + check("0=p+-010203/-+020406r+-030507/-+040608a+-050709/-+060810", + "000000,010203,020406,030507,040608,050709,060810", + "NO_TRADING,PRE_MARKET,NO_TRADING,REGULAR,NO_TRADING,AFTER_MARKET,NO_TRADING"); + + check("0=rt0300r05000600", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=rt+-0300r-+0500-+0600", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r05000600rt0300", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=r+-0500/0600rt+-0300", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=05000600rt0300", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=0500/0600rt-+0300", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=rt030405r05000600", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=05000600rt030405", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + check("0=0500/0600rt-+030405", "000000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); + + check("0=d0100230005000600rt0300", "010000,050000,060000", "NO_TRADING,REGULAR,NO_TRADING"); +} + +TEST_CASE("Test hd sets union with default syntax") { + auto def = "hd=US,CA;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); +} + +TEST_CASE("Test hd sets and days union with default syntax") { + auto def = "hd=US,CA,20211010;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20211010)->isHoliday(), "Custom Holiday"); +} + +TEST_CASE("Test hd sets difference") { + auto def = "hd=US,-CA;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Only Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); +} + +TEST_CASE("Test hd sets and days difference") { + auto def = "hd=US,-CA,-20210531;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Only Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210531)->isHoliday(), "Custom removed holiday"); +} + +TEST_CASE("Test hd sets intersection") { + auto def = "hd=US,*CA;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Only Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); +} + +TEST_CASE("Test hd sets and days intersect") { + auto def = "hd=20210101,*US,*CA;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Only Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210101)->isHoliday(), "Only one remain holiday"); +} + +TEST_CASE("Test hd sets and days intersect with wrong syntax") { + auto def = "hd=US,CA,*20210101;0=08001800;td=1234567"; + + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210606)->isHoliday(), "US and CA not holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210118)->isHoliday(), "US Only Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210524)->isHoliday(), "CA Holiday"); + REQUIRE_FALSE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210215)->isHoliday(), "US and CA Holiday"); + REQUIRE_MESSAGE(gmt(def)->getDayByYearMonthDay(20210101)->isHoliday(), "Only one remain holiday"); +} \ No newline at end of file diff --git a/tools/Tools/src/Args/Args.hpp b/tools/Tools/src/Args/Args.hpp index 597e83123..a4ebb32f4 100644 --- a/tools/Tools/src/Args/Args.hpp +++ b/tools/Tools/src/Args/Args.hpp @@ -21,15 +21,15 @@ namespace dxfcpp::tools { -decltype(ranges::views::filter([](const auto &s) { +inline decltype(ranges::views::filter([](const auto &s) { return !s.empty(); })) filterNonEmpty{}; -decltype(ranges::views::transform([](auto &&s) { +inline decltype(ranges::views::transform([](auto &&s) { return s | ranges::to(); })) transformToString{}; -decltype(ranges::views::transform([](const std::string &s) { +inline decltype(ranges::views::transform([](const std::string &s) { return trimStr(s); })) trim{}; From 4457e13f0a920ce8aadb21ca0d1da0e76a7528a9 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 1 Jul 2024 18:15:23 +0300 Subject: [PATCH 030/178] [MDAPI-26] Update Graal SDK to v1.1.21 IsolatedTimeFormat::format --- .../exceptions/JavaException.hpp | 20 ------------------- .../isolated/IsolatedCommon.hpp | 8 -------- src/isolated/internal/IsolatedTimeFormat.cpp | 2 +- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index 0b46f2e77..3eac60a5f 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -64,26 +64,6 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { return v; } - // Legacy - template static constexpr T *throwIfMinusOne(T *v) { - if (dxfcpp::bit_cast(v) == -1LL || - dxfcpp::bit_cast(v) == 0x00000000FFFFFFFFLL) { - throwIfJavaThreadExceptionExists(); - } - - return v; - } - - // Legacy - template static constexpr const T *throwIfMinusOne(const T *v) { - if (dxfcpp::bit_cast(v) == -1LL || - dxfcpp::bit_cast(v) == 0x00000000FFFFFFFFLL) { - throwIfJavaThreadExceptionExists(); - } - - return v; - } - /** * @return dxFeed Graal CXX API stack trace + Java (GraalVM) exception's stack trace. */ diff --git a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp index e5c8a501b..217d17e33 100644 --- a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp @@ -42,10 +42,6 @@ constexpr auto throwIfLessThanZero = [](auto v) { return JavaException::throwIfLessThanZero(v); }; -constexpr auto throwIfMinusOne = [](auto v) { - return JavaException::throwIfMinusOne(v); -}; - constexpr auto runGraalFunction(auto graalFunction, auto &&...params) { return runIsolatedThrow( [](auto threadHandle, auto &&graalFunction, auto &&...params) { @@ -70,10 +66,6 @@ constexpr auto runGraalFunctionAndThrowIfLessThanZero(auto graalFunction, auto & return runGraalFunctionAndThrow(throwIfLessThanZero, graalFunction, params...); } -constexpr auto runGraalFunctionAndThrowIfMinusOne(auto graalFunction, auto &&...params) { - return runGraalFunctionAndThrow(throwIfMinusOne, graalFunction, params...); -} - } // namespace isolated DXFCPP_END_NAMESPACE diff --git a/src/isolated/internal/IsolatedTimeFormat.cpp b/src/isolated/internal/IsolatedTimeFormat.cpp index c5c035853..b07cae28f 100644 --- a/src/isolated/internal/IsolatedTimeFormat.cpp +++ b/src/isolated/internal/IsolatedTimeFormat.cpp @@ -61,7 +61,7 @@ std::string format(/* dxfg_time_format_t* */ const JavaObjectHandle(timeFormat.get()), value); auto result = dxfcpp::toString(format); From 5f5bb423187da378c4a55a525563bab2d744dc16 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 1 Jul 2024 18:39:41 +0300 Subject: [PATCH 031/178] [MDAPI-26] Update Graal SDK to v1.1.21 OrderSource::CEDX OrderSource::cedx --- .../event/market/OrderSource.hpp | 16 ++++++++++++++++ src/event/market/OrderSource.cpp | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp index 07bd08df9..41a34497f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp @@ -488,6 +488,22 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { */ static const OrderSource arca; + /** + * Cboe European Derivatives. + * + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource CEDX; + + /** + * Cboe European Derivatives. Record for price level book. + * + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource cedx; + /** * Determines whether specified source identifier refers to special order source. * Special order sources are used for wrapping non-order events into order events. diff --git a/src/event/market/OrderSource.cpp b/src/event/market/OrderSource.cpp index 2ed6ff7cc..28e4b3885 100644 --- a/src/event/market/OrderSource.cpp +++ b/src/event/market/OrderSource.cpp @@ -55,6 +55,8 @@ const OrderSource OrderSource::OCEA("OCEA", PUB_ORDER); const OrderSource OrderSource::pink("pink", PUB_ORDER | PUB_OTC_MARKETS_ORDER); const OrderSource OrderSource::ARCA("ARCA", PUB_ORDER); const OrderSource OrderSource::arca("arca", PUB_ORDER); +const OrderSource OrderSource::CEDX("CEDX", PUB_ORDER); +const OrderSource OrderSource::cedx("cedx", PUB_ORDER); const std::unordered_map, std::reference_wrapper> OrderSource::PREDEFINED_SOURCES = @@ -74,7 +76,8 @@ const std::unordered_map, std::reference DEFAULT, // NTV, ntv, NFX, ESPD, XNFI, ICE, ISE, DEA, DEX, dex, BYX, BZX, bzx, BATE, CHIX, CEUX, BXTR, IST, BI20, ABE, - FAIR, GLBX, glbx, ERIS, XEUR, xeur, CFE, C2OX, SMFE, smfe, iex, MEMX, memx, OCEA, pink, ARCA, arca}); + FAIR, GLBX, glbx, ERIS, XEUR, xeur, CFE, C2OX, SMFE, smfe, iex, MEMX, memx, OCEA, pink, ARCA, arca, CEDX, + cedx}); std::unordered_map OrderSource::USER_SOURCES_{}; From f2b646988aa3886371b88de7be5209c614501430 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 1 Jul 2024 19:21:15 +0300 Subject: [PATCH 032/178] [MDAPI-26] Update Graal SDK to v1.1.21 IsolatedTools --- CMakeLists.txt | 1 + .../isolated/internal/IsolatedTools.hpp | 12 ++++++------ src/isolated/internal/IsolatedTools.cpp | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 src/isolated/internal/IsolatedTools.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7098425a4..457aed78d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,6 +200,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/promise/IsolatedPromise.cpp src/isolated/internal/IsolatedString.cpp src/isolated/internal/IsolatedTimeFormat.cpp + src/isolated/internal/IsolatedTools.cpp ) set(dxFeedGraalCxxApi_Api_Sources diff --git a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp index d29d9ced1..e15245a0c 100644 --- a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp @@ -13,12 +13,12 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE -namespace isolated::internal { -// namespace IsolatedTools { -// std::unordered_set /* dxfg_string_list* */ parseSymbols(std::string_view symbolList); -// -// void /* int32_t */ runTool(/* dxfg_string_list* */ const std::vector& args); -// } +namespace isolated::internal::IsolatedTools { + +std::unordered_set /* dxfg_string_list* */ parseSymbols(std::string_view symbolList); + +void /* int32_t */ runTool(/* dxfg_string_list* */ const std::vector& args); + } diff --git a/src/isolated/internal/IsolatedTools.cpp b/src/isolated/internal/IsolatedTools.cpp new file mode 100644 index 000000000..b9e613213 --- /dev/null +++ b/src/isolated/internal/IsolatedTools.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::internal::IsolatedTools { +} + +DXFCPP_END_NAMESPACE \ No newline at end of file From 5e7b7188e19d1f608dd48fe6b16b048154649329 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Tue, 2 Jul 2024 18:26:38 +0300 Subject: [PATCH 033/178] [MDAPI-26] Update Graal SDK to v1.1.21 internal::IsolatedTools --- DEPENDENCIES.md | 2 +- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 1 + .../isolated/Isolated.hpp | 6 ----- .../isolated/internal/IsolatedTools.hpp | 20 +++++++++++++--- src/internal/Isolate.cpp | 21 ----------------- src/internal/utils/CmdArgsUtils.cpp | 4 ++-- src/isolated/internal/IsolatedTools.cpp | 23 +++++++++++++++++++ tools/Tools/src/Qds/QdsTool.hpp | 2 +- 8 files changed, 45 insertions(+), 34 deletions(-) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index b3f352268..875162037 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -2,7 +2,7 @@ ## Compile-time -- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.16 +- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.21 - [Boost](https://github.com/boostorg/boost) v1.84.0 - Boost.Stacktrace 1.0 - [utfcpp](https://github.com/nemtrif/utfcpp) v3.2.3 diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index acce0eae5..6e77b835d 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -300,6 +300,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { /** * Requests time series of events for the specified event type, symbol, and a range of time. + * * @tparam E The type of event. * @param symbol The symbol. * @param fromTime The time, inclusive, to request events from (see TimeSeriesEvent::getTime()). diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index cd471eb0a..0e5d016d4 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -23,12 +23,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { -struct Tools { - static std::unordered_set /* dxfg_string_list* */ parseSymbols(std::string_view symbolList); - - static void /* int32_t */ runTool(/* dxfg_string_list* */ const std::vector& args); -}; - namespace ipf { struct InstrumentProfileReader { static /* dxfg_instrument_profile_reader_t* */ JavaObjectHandle create(); diff --git a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp index e15245a0c..3bcc478da 100644 --- a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedTools.hpp @@ -15,12 +15,26 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::internal::IsolatedTools { +/** + * Calls the Graal SDK function `dxfg_Tools_parseSymbols` in isolation. + * + * @param symbolList The symbol list + * @return parsed symbols. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ std::unordered_set /* dxfg_string_list* */ parseSymbols(std::string_view symbolList); -void /* int32_t */ runTool(/* dxfg_string_list* */ const std::vector& args); - -} +/** + * Calls the Graal SDK function `dxfg_Tools_main` in isolation. + * + * @param args The tool's arguments + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ runTool(/* dxfg_string_list* */ const std::vector &args); +} // namespace isolated::internal::IsolatedTools DXFCPP_END_NAMESPACE diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 7ede41b8a..d3971cf97 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -154,29 +154,8 @@ constexpr auto runGraalFunction(auto resultCheckerConverter, auto graalFunction, defaultValue, resultCheckerConverter, graalFunction, params...); } -std::unordered_set /* dxfg_string_list* */ -Tools::parseSymbols(std::string_view symbolList) { - std::unordered_set result{}; - - auto graalStringList = runGraalFunctionAndThrowIfNullptr(dxfg_Tools_parseSymbols, symbolList.data()); - - for (auto i = 0; i < graalStringList->size; i++) { - result.emplace(dxfcpp::toString(graalStringList->elements[i])); - } - - isolated::internal::IsolatedStringList::release(graalStringList); - - return result; -} - using NativeStringList = typename isolated::internal::NativeStringListWrapper; -void /* int32_t */ Tools::runTool(/* dxfg_string_list* */ const std::vector &args) { - NativeStringList l{args}; - - runGraalFunctionAndThrowIfLessThanZero(dxfg_Tools_main, l.list); -} - namespace ipf { /* dxfg_instrument_profile_reader_t* */ dxfcpp::JavaObjectHandle diff --git a/src/internal/utils/CmdArgsUtils.cpp b/src/internal/utils/CmdArgsUtils.cpp index 9d43a0384..bed73cb00 100644 --- a/src/internal/utils/CmdArgsUtils.cpp +++ b/src/internal/utils/CmdArgsUtils.cpp @@ -131,7 +131,7 @@ std::unordered_set CmdArgsUtils::parseSymbols(const std::string & return {}; } - auto parsed = isolated::Tools::parseSymbols(trimmedSymbols); + auto parsed = isolated::internal::IsolatedTools::parseSymbols(trimmedSymbols); if (parsed.contains("*") || parsed.contains("all") || parsed.contains("All") || parsed.contains("ALL")) { return {WildcardSymbol::ALL}; @@ -155,7 +155,7 @@ std::unordered_set CmdArgsUtils::parseCandleSymbols(const std::str return {}; } - auto parsed = isolated::Tools::parseSymbols(trimmedSymbols); + auto parsed = isolated::internal::IsolatedTools::parseSymbols(trimmedSymbols); return parsed | ranges::views::transform([](auto &&s) { return CandleSymbol::valueOf(s); diff --git a/src/isolated/internal/IsolatedTools.cpp b/src/isolated/internal/IsolatedTools.cpp index b9e613213..4126a73e4 100644 --- a/src/isolated/internal/IsolatedTools.cpp +++ b/src/isolated/internal/IsolatedTools.cpp @@ -4,11 +4,34 @@ #include #include +#include #include DXFCPP_BEGIN_NAMESPACE namespace isolated::internal::IsolatedTools { +std::unordered_set /* dxfg_string_list* */ +parseSymbols(std::string_view symbolList) { + std::unordered_set result{}; + + auto graalStringList = runGraalFunctionAndThrowIfNullptr(dxfg_Tools_parseSymbols, symbolList.data()); + + for (auto i = 0; i < graalStringList->size; i++) { + result.emplace(dxfcpp::toString(graalStringList->elements[i])); + } + + IsolatedStringList::release(graalStringList); + + return result; +} + +using NativeStringList = NativeStringListWrapper; + +void /* int32_t */ runTool(/* dxfg_string_list* */ const std::vector &args) { + NativeStringList l{args}; + + runGraalFunctionAndThrowIfLessThanZero(dxfg_Tools_main, l.list); } +} // namespace isolated::internal::IsolatedTools DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/tools/Tools/src/Qds/QdsTool.hpp b/tools/Tools/src/Qds/QdsTool.hpp index 56c9dacac..2ce3fc789 100644 --- a/tools/Tools/src/Qds/QdsTool.hpp +++ b/tools/Tools/src/Qds/QdsTool.hpp @@ -77,7 +77,7 @@ struct QdsTool { auto parsedProperties = CmdArgsUtils::parseProperties(args.properties); System::setProperties(parsedProperties); - dxfcpp::isolated::Tools::runTool(qdsArgs); + dxfcpp::isolated::internal::IsolatedTools::runTool(qdsArgs); } }; From c561094be57ed052b168b34e6d41c311f8cd8852 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 3 Jul 2024 11:31:11 +0300 Subject: [PATCH 034/178] Change CPACK_PACKAGE_VERSION --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 337bfe0ef..59cd814b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -507,7 +507,7 @@ if (DXFCXX_INSTALL) set(CPACK_SOURCE_GENERATOR ZIP) set(CPACK_PACKAGE_VENDOR "Devexperts LLC") set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") - set(CPACK_PACKAGE_VERSION "${DXFCXX_PACKAGE_VERSION}") + set(CPACK_PACKAGE_VERSION "${DXFCXX_VERSION}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${DXFCXX_VERSION}-${DXFCXX_TARGET_PLATFORM}${DXFCXX_PACKAGE_SUFFIX}") include(CPack) From 8abed3d7148562d3099ba96357e2af2d9a9aa3b2 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 3 Jul 2024 23:24:16 +0300 Subject: [PATCH 035/178] Fix platform detection. Add the ability to build API, samples & tools with stub (any CPU\OS) --- CMakeLists.txt | 47 ++++++++++++++++++----------- cmake/ParseAndDetectPlatforms.cmake | 5 +-- scripts/buildWithStub.cmd | 46 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 scripts/buildWithStub.cmd diff --git a/CMakeLists.txt b/CMakeLists.txt index 457aed78d..715f49d6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,9 @@ option(DXFCXX_INSTALL_TOOLS "Prepare install the tools" ${DXFCXX_IS_ROOT_PROJECT option(DXFCXX_USE_DXFEED_GRAAL_NATIVE_SDK_JFROG "" ON) set(DXFEED_GRAAL_NATIVE_SDK_JFROG_BASE_URL "https://dxfeed.jfrog.io/artifactory/maven-open/com/dxfeed/graal-native-sdk/" CACHE STRING "") +option(DXFCXX_USE_DXFG_STUB "Use dxFeed Graal SDK stub" OFF) +set(DXFG_STUB_REPO "https://github.com/ttldtor/DxFeedGraalNativeSdkStub" CACHE STRING "") + option(DXFCXX_ENABLE_ASAN_UBSAN "Enable address, UB sanitizers etc" OFF) option(DXFCXX_ENABLE_VS_ASAN "Enable VS address sanitizer" OFF) option(DXFCXX_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) @@ -72,32 +75,42 @@ set(DXFCXX_GRAAL_TARGET_CPU "unknown" CACHE STRING "") include(cmake/ParseAndDetectPlatforms.cmake) include(cmake/LinkStacktrace.cmake) -if (DEFINED ENV{DXFEED_GRAAL_NATIVE_SDK_URL}) +if (DXFCXX_USE_DXFG_STUB) FetchContent_Declare( DxFeedGraalNativeSdk - URL $ENV{DXFEED_GRAAL_NATIVE_SDK_URL} + GIT_REPOSITORY "${DXFG_STUB_REPO}.git" GIT_TAG "v${DXFEED_GRAAL_NATIVE_SDK_VERSION}" USES_TERMINAL_DOWNLOAD TRUE GIT_PROGRESS TRUE DOWNLOAD_NO_EXTRACT FALSE ) else () - if (DXFCXX_USE_DXFEED_GRAAL_NATIVE_SDK_JFROG) - set(DXFEED_GRAAL_NATIVE_SDK_URL "${DXFEED_GRAAL_NATIVE_SDK_JFROG_BASE_URL}${DXFEED_GRAAL_NATIVE_SDK_VERSION}/graal-native-sdk-${DXFEED_GRAAL_NATIVE_SDK_VERSION}") - endif () - - if (DXFCXX_GRAAL_TARGET_PLATFORM STREQUAL "unknown-unknown") - message(ERROR "Unsupported platform!") + if (DEFINED ENV{DXFEED_GRAAL_NATIVE_SDK_URL}) + FetchContent_Declare( + DxFeedGraalNativeSdk + URL $ENV{DXFEED_GRAAL_NATIVE_SDK_URL} + USES_TERMINAL_DOWNLOAD TRUE + GIT_PROGRESS TRUE + DOWNLOAD_NO_EXTRACT FALSE + ) else () - set(DXFEED_GRAAL_NATIVE_SDK_URL ${DXFEED_GRAAL_NATIVE_SDK_URL}-${DXFCXX_GRAAL_TARGET_PLATFORM}.zip) + if (DXFCXX_USE_DXFEED_GRAAL_NATIVE_SDK_JFROG) + set(DXFEED_GRAAL_NATIVE_SDK_URL "${DXFEED_GRAAL_NATIVE_SDK_JFROG_BASE_URL}${DXFEED_GRAAL_NATIVE_SDK_VERSION}/graal-native-sdk-${DXFEED_GRAAL_NATIVE_SDK_VERSION}") + endif () + + if (DXFCXX_GRAAL_TARGET_PLATFORM STREQUAL "unknown-unknown") + message(ERROR "Unsupported platform!") + else () + set(DXFEED_GRAAL_NATIVE_SDK_URL ${DXFEED_GRAAL_NATIVE_SDK_URL}-${DXFCXX_GRAAL_TARGET_PLATFORM}.zip) + endif () + + FetchContent_Declare( + DxFeedGraalNativeSdk + URL ${DXFEED_GRAAL_NATIVE_SDK_URL} + USES_TERMINAL_DOWNLOAD TRUE + GIT_PROGRESS TRUE + DOWNLOAD_NO_EXTRACT FALSE + ) endif () - - FetchContent_Declare( - DxFeedGraalNativeSdk - URL ${DXFEED_GRAAL_NATIVE_SDK_URL} - USES_TERMINAL_DOWNLOAD TRUE - GIT_PROGRESS TRUE - DOWNLOAD_NO_EXTRACT FALSE - ) endif () FetchContent_MakeAvailable(DxFeedGraalNativeSdk) diff --git a/cmake/ParseAndDetectPlatforms.cmake b/cmake/ParseAndDetectPlatforms.cmake index f8d6d610e..178d1aef2 100644 --- a/cmake/ParseAndDetectPlatforms.cmake +++ b/cmake/ParseAndDetectPlatforms.cmake @@ -7,9 +7,10 @@ #MESSAGE(STATUS "DXFCXX_TARGET_PLATFORM: ${DXFCXX_TARGET_PLATFORM}") #MESSAGE(STATUS "DXFCXX_TARGET_OS: ${DXFCXX_TARGET_OS}") #MESSAGE(STATUS "DXFCXX_TARGET_CPU: ${DXFCXX_TARGET_CPU}") +#MESSAGE(STATUS "DXFCXX_CUSTOM_CPU: $ENV{DXFCXX_CUSTOM_CPU}") if ((DXFCXX_GRAAL_TARGET_PLATFORM STREQUAL "unknown-unknown") AND (DXFCXX_TARGET_PLATFORM STREQUAL "unknown-unknown")) - if ((DEFINED $ENV{DXFCXX_CUSTOM_OS}) AND (DXFCXX_TARGET_OS STREQUAL "unknown")) + if ((DEFINED ENV{DXFCXX_CUSTOM_OS}) AND (DXFCXX_TARGET_OS STREQUAL "unknown")) if ($ENV{DXFCXX_CUSTOM_OS} MATCHES "win") set(DXFCXX_TARGET_OS "windows") set(DXFCXX_GRAAL_TARGET_OS "windows") @@ -25,7 +26,7 @@ if ((DXFCXX_GRAAL_TARGET_PLATFORM STREQUAL "unknown-unknown") AND (DXFCXX_TARGET endif () endif () - if ((DEFINED $ENV{DXFCXX_CUSTOM_CPU}) AND (${DXFCXX_TARGET_CPU} STREQUAL "unknown")) + if ((DEFINED ENV{DXFCXX_CUSTOM_CPU}) AND (${DXFCXX_TARGET_CPU} STREQUAL "unknown")) if (($ENV{DXFCXX_CUSTOM_CPU} MATCHES "amd64") OR ($ENV{DXFCXX_CUSTOM_CPU} MATCHES "x86_64")) set(DXFCXX_TARGET_CPU "x86_64") set(DXFCXX_GRAAL_TARGET_CPU "amd64") diff --git a/scripts/buildWithStub.cmd b/scripts/buildWithStub.cmd new file mode 100644 index 000000000..9365c83d3 --- /dev/null +++ b/scripts/buildWithStub.cmd @@ -0,0 +1,46 @@ +set CUR_DIR=%CD% + +set CURRENT_BUILD_TYPE= +set BUILD_DIR= +set DXFCXX_CUSTOM_CPU=x86_32 +set DXFCXX_PARALLEL=30 + +set CURRENT_BUILD_TYPE=Release +set BUILD_DIR=%CUR_DIR%\build-win-%CURRENT_BUILD_TYPE% +rmdir "%BUILD_DIR%" /s /q +mkdir "%BUILD_DIR%" +cmake -G "Ninja" -B "%BUILD_DIR%" -DCMAKE_BUILD_TYPE=%CURRENT_BUILD_TYPE% -DDXFCXX_PACKAGE_SUFFIX=-%CURRENT_BUILD_TYPE% -DDXFCXX_BUILD_UNIT_TESTS=OFF -DDXFCXX_BUILD_SAMPLES=OFF -DDXFCXX_BUILD_TOOLS=OFF -DDXFCXX_INSTALL_SAMPLES=OFF -DDXFCXX_INSTALL_TOOLS=OFF -DDXFCXX_BUILD_DOC=OFF -DDXFCXX_USE_DXFG_STUB:BOOL=ON +cmake --build "%BUILD_DIR%" --config %CURRENT_BUILD_TYPE% --parallel %DXFCXX_PARALLEL% +cd "%BUILD_DIR%" +cpack -G ZIP -C %CURRENT_BUILD_TYPE% --config dxFeedGraalCxxApiPackConfig.cmake +cd "%CUR_DIR%" + +set CURRENT_BUILD_TYPE=Debug +set BUILD_DIR=%CUR_DIR%\build-win-%CURRENT_BUILD_TYPE% +rmdir "%BUILD_DIR%" /s /q +mkdir "%BUILD_DIR%" +cmake -G "Ninja" -B "%BUILD_DIR%" -DCMAKE_BUILD_TYPE=%CURRENT_BUILD_TYPE% -DDXFCXX_PACKAGE_SUFFIX=-%CURRENT_BUILD_TYPE% -DDXFCXX_BUILD_UNIT_TESTS=OFF -DDXFCXX_BUILD_SAMPLES=OFF -DDXFCXX_BUILD_TOOLS=OFF -DDXFCXX_INSTALL_SAMPLES=OFF -DDXFCXX_INSTALL_TOOLS=OFF -DDXFCXX_BUILD_DOC=OFF -DDXFCXX_USE_DXFG_STUB:BOOL=ON +cmake --build "%BUILD_DIR%" --config %CURRENT_BUILD_TYPE% --parallel %DXFCXX_PARALLEL% +cd "%BUILD_DIR%" +cpack -G ZIP -C %CURRENT_BUILD_TYPE% --config dxFeedGraalCxxApiPackConfig.cmake +cd "%CUR_DIR%" + +set CURRENT_BUILD_TYPE=Release +set BUILD_DIR=%CUR_DIR%\build-win-Samples +rmdir "%BUILD_DIR%" /s /q +mkdir "%BUILD_DIR%" +cmake -G "Ninja" -B "%BUILD_DIR%" -DCMAKE_BUILD_TYPE=%CURRENT_BUILD_TYPE% -DDXFCXX_PACKAGE_SUFFIX=-Samples -DDXFCXX_BUILD_UNIT_TESTS=OFF -DDXFCXX_BUILD_TOOLS=OFF -DDXFCXX_INSTALL_LIB=OFF -DDXFCXX_INSTALL_TOOLS=OFF -DDXFCXX_BUILD_DOC=OFF -DDXFCXX_USE_DXFG_STUB:BOOL=ON +cmake --build "%BUILD_DIR%" --config %CURRENT_BUILD_TYPE% --parallel %DXFCXX_PARALLEL% +cd "%BUILD_DIR%" +cpack -G ZIP -C %CURRENT_BUILD_TYPE% --config dxFeedGraalCxxApiPackConfig.cmake +cd "%CUR_DIR%" + +set CURRENT_BUILD_TYPE=Release +set BUILD_DIR=%CUR_DIR%\build-win-Tools +rmdir "%BUILD_DIR%" /s /q +mkdir "%BUILD_DIR%" +cmake -G "Ninja" -B "%BUILD_DIR%" -DCMAKE_BUILD_TYPE=%CURRENT_BUILD_TYPE% -DDXFCXX_PACKAGE_SUFFIX=-Tools -DDXFCXX_BUILD_UNIT_TESTS=OFF -DDXFCXX_BUILD_SAMPLES=OFF -DDXFCXX_INSTALL_LIB=OFF -DDXFCXX_INSTALL_SAMPLES=OFF -DDXFCXX_BUILD_DOC=OFF -DDXFCXX_USE_DXFG_STUB:BOOL=ON +cmake --build "%BUILD_DIR%" --config %CURRENT_BUILD_TYPE% --parallel %DXFCXX_PARALLEL% +cd "%BUILD_DIR%" +cpack -G ZIP -C %CURRENT_BUILD_TYPE% --config dxFeedGraalCxxApiPackConfig.cmake +cd "%CUR_DIR%" \ No newline at end of file From 781a909e737cf964a78ca690b75fbb2ce84f4233 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Wed, 10 Jul 2024 17:49:50 +0300 Subject: [PATCH 036/178] [MDAPI-26] Update Graal SDK to v1.1.21 TimePeriod --- CMakeLists.txt | 6 ++ include/dxfeed_graal_cpp_api/api.hpp | 3 + .../exceptions/JavaException.hpp | 8 ++ .../internal/TimeFormat.hpp | 6 +- .../isolated/IsolatedCommon.hpp | 8 ++ .../isolated/util/IsolatedTimePeriod.hpp | 45 +++++++++ .../dxfeed_graal_cpp_api/util/TimePeriod.hpp | 96 +++++++++++++++++++ src/internal/JavaObjectHandle.cpp | 2 + src/internal/TimeFormat.cpp | 8 +- src/isolated/internal/IsolatedTimeFormat.cpp | 6 +- src/isolated/util/IsolatedTimePeriod.cpp | 60 ++++++++++++ src/util/TimePeriod.cpp | 46 +++++++++ 12 files changed, 283 insertions(+), 11 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/util/IsolatedTimePeriod.hpp create mode 100644 include/dxfeed_graal_cpp_api/util/TimePeriod.hpp create mode 100644 src/isolated/util/IsolatedTimePeriod.cpp create mode 100644 src/util/TimePeriod.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f30add7cb..4d317e56c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/internal/IsolatedString.cpp src/isolated/internal/IsolatedTimeFormat.cpp src/isolated/internal/IsolatedTools.cpp + src/isolated/util/IsolatedTimePeriod.cpp ) set(dxFeedGraalCxxApi_Api_Sources @@ -326,6 +327,10 @@ set(dxFeedGraalCxxApi_Schedule_Sources src/schedule/Schedule.cpp ) +set(dxFeedGraalCxxApi_Util_Sources + src/util/TimePeriod.cpp +) + set(dxFeedGraalCxxApi_Sources ${dxFeedGraalCxxApi_Internal_Sources} ${dxFeedGraalCxxApi_InternalUtils_Sources} @@ -345,6 +350,7 @@ set(dxFeedGraalCxxApi_Sources ${dxFeedGraalCxxApi_EventOption_Sources} ${dxFeedGraalCxxApi_EventMisc_Sources} ${dxFeedGraalCxxApi_Schedule_Sources} + ${dxFeedGraalCxxApi_Util_Sources} ) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 26a9222fb..4bda7b535 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -38,6 +38,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "internal/utils/StringUtils.hpp" #include "internal/utils/debug/Debug.hpp" +#include "util/TimePeriod.hpp" + #include "api/ApiModule.hpp" #include "ipf/IpfModule.hpp" #include "entity/EntityModule.hpp" @@ -62,6 +64,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/internal/IsolatedString.hpp" #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" +#include "isolated/util/IsolatedTimePeriod.hpp" #include "ondemand/OnDemandService.hpp" diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index 3eac60a5f..2e0543dec 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -64,6 +64,14 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { return v; } + template static constexpr T throwIfMinusOne(T v) { + if (v == T(-1)) { + throwIfJavaThreadExceptionExists(); + } + + return v; + } + /** * @return dxFeed Graal CXX API stack trace + Java (GraalVM) exception's stack trace. */ diff --git a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp index 010e7e682..74c5d5b00 100644 --- a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp +++ b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp @@ -40,9 +40,9 @@ struct DXFCPP_EXPORT TimeFormat { private: JavaObjectHandle handle_; + explicit TimeFormat(JavaObjectHandle &&handle); + public: - explicit TimeFormat(void* handle = nullptr); - explicit TimeFormat(JavaObjectHandle&& handle); virtual ~TimeFormat() noexcept = default; TimeFormat(const TimeFormat &) = delete; @@ -111,7 +111,7 @@ struct DXFCPP_EXPORT TimeFormat { * @param value String value to parse. * @return Date's timestamp parsed from value or `0` if value has wrong format. */ - std::int64_t parse(const std::string& value) const; + std::int64_t parse(const StringLikeWrapper &value) const; /** * Converts timestamp into string according to the format diff --git a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp index 217d17e33..e5c8a501b 100644 --- a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp @@ -42,6 +42,10 @@ constexpr auto throwIfLessThanZero = [](auto v) { return JavaException::throwIfLessThanZero(v); }; +constexpr auto throwIfMinusOne = [](auto v) { + return JavaException::throwIfMinusOne(v); +}; + constexpr auto runGraalFunction(auto graalFunction, auto &&...params) { return runIsolatedThrow( [](auto threadHandle, auto &&graalFunction, auto &&...params) { @@ -66,6 +70,10 @@ constexpr auto runGraalFunctionAndThrowIfLessThanZero(auto graalFunction, auto & return runGraalFunctionAndThrow(throwIfLessThanZero, graalFunction, params...); } +constexpr auto runGraalFunctionAndThrowIfMinusOne(auto graalFunction, auto &&...params) { + return runGraalFunctionAndThrow(throwIfMinusOne, graalFunction, params...); +} + } // namespace isolated DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/util/IsolatedTimePeriod.hpp b/include/dxfeed_graal_cpp_api/isolated/util/IsolatedTimePeriod.hpp new file mode 100644 index 000000000..4a5967a53 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/util/IsolatedTimePeriod.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include +#include +#include + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include "../../util/TimePeriod.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::util::IsolatedTimePeriod { + +/* + +dxfg_time_period_t* dxfg_TimePeriod_ZERO(graal_isolatethread_t *thread); +dxfg_time_period_t* dxfg_TimePeriod_UNLIMITED(graal_isolatethread_t *thread); +dxfg_time_period_t* dxfg_TimePeriod_valueOf(graal_isolatethread_t *thread, int64_t value); +dxfg_time_period_t* dxfg_TimePeriod_valueOf2(graal_isolatethread_t *thread, const char* value); +int64_t dxfg_TimePeriod_getTime(graal_isolatethread_t *thread, dxfg_time_period_t* timePeriod); +int32_t dxfg_TimePeriod_getSeconds(graal_isolatethread_t *thread, dxfg_time_period_t* timePeriod); +int64_t dxfg_TimePeriod_getNanos(graal_isolatethread_t *thread, dxfg_time_period_t* timePeriod); + +*/ + +/* dxfg_time_period_t* */ JavaObjectHandle ZERO(); +/* dxfg_time_period_t* */ JavaObjectHandle UNLIMITED(); +/* dxfg_time_period_t* */ JavaObjectHandle valueOf(std::int64_t value); +/* dxfg_time_period_t* */ JavaObjectHandle valueOf(std::string_view value); +std::int64_t getTime(/* dxfg_time_period_t* */ const JavaObjectHandle& timePeriod); +std::int32_t getSeconds(/* dxfg_time_period_t* */ const JavaObjectHandle& timePeriod); +std::int64_t getNanos(/* dxfg_time_period_t* */ const JavaObjectHandle& timePeriod); + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() + diff --git a/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp b/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp new file mode 100644 index 000000000..70380a927 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp @@ -0,0 +1,96 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include + +DXFCPP_BEGIN_NAMESPACE + +/** + * Value class for period of time with support for ISO8601 duration format. + */ +struct DXFCPP_EXPORT TimePeriod { + /// Time-period of zero. + static const TimePeriod ZERO; + + /// Time-period of "infinity" (time of `std::numeric_limits::max()` or `LLONG_MAX`). + static const TimePeriod UNLIMITED; + + /** + * Returns TimePeriod with value milliseconds. + * + * @param value value in milliseconds + * @return TimePeriod with value milliseconds. + */ + static TimePeriod valueOf(std::int64_t value); + + /** + * Returns TimePeriod with value milliseconds. + * + * @param value value in milliseconds + * @return TimePeriod with value milliseconds. + */ + static TimePeriod valueOf(std::chrono::milliseconds value) { + return valueOf(value.count()); + } + + /** + * Returns TimePeriod represented with a given string. + * + * Allowable format is ISO8601 duration, but there are some simplifications and modifications available: + *

    + *
  • Letters are case insensitive. + *
  • Letters "P" and "T" can be omitted. + *
  • Letter "S" can be also omitted. In this case last number will be supposed to be seconds. + *
  • Number of seconds can be fractional. So it is possible to define duration accurate within milliseconds. + *
  • Every part can be omitted. It is supposed that it's value is zero then. + *
  • String "inf" recognized as unlimited period. + *
+ * + * @param value The string representation + * @return TimePeriod represented with a given string. + */ + static TimePeriod valueOf(const StringLikeWrapper &value); + + /** + * Returns value in milliseconds. + * + * @return value in milliseconds + */ + std::int64_t getTime() const; + + /** + * Returns value in seconds. + * + * @return value in seconds + */ + std::int32_t getSeconds() const; + + /** + * Returns value in nanoseconds. + * + * @return value in nanoseconds + */ + std::int64_t getNanos() const; + + virtual ~TimePeriod() noexcept = default; + + TimePeriod(const TimePeriod &) = delete; + TimePeriod(TimePeriod &&) noexcept = delete; + TimePeriod &operator=(const TimePeriod &) = delete; + TimePeriod &operator=(const TimePeriod &&) noexcept = delete; + + private: + JavaObjectHandle handle_; + + explicit TimePeriod(JavaObjectHandle &&handle); +}; + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index d45ac45a6..daa059153 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -87,4 +87,6 @@ template struct JavaObjectHandle; template struct JavaObjectHandle; template struct JavaObjectHandle; +template struct JavaObjectHandle; + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/internal/TimeFormat.cpp b/src/internal/TimeFormat.cpp index 6c233e206..c2057b7ad 100644 --- a/src/internal/TimeFormat.cpp +++ b/src/internal/TimeFormat.cpp @@ -9,10 +9,6 @@ DXFCPP_BEGIN_NAMESPACE -TimeFormat::TimeFormat(void *handle) : handle_(handle){}; - -TimeFormat::TimeFormat(JavaObjectHandle &&handle) : handle_(std::move(handle)){}; - const TimeFormat TimeFormat::DEFAULT(isolated::internal::IsolatedTimeFormat::getDefault()); const TimeFormat TimeFormat::DEFAULT_WITH_MILLIS(DEFAULT.handle_ @@ -23,7 +19,9 @@ const TimeFormat TimeFormat::DEFAULT_WITH_MILLIS_WITH_TIMEZONE( : JavaObjectHandle{nullptr}); const TimeFormat TimeFormat::GMT(isolated::internal::IsolatedTimeFormat::getGmt()); -std::int64_t TimeFormat::parse(const std::string &value) const { +TimeFormat::TimeFormat(JavaObjectHandle &&handle) : handle_(std::move(handle)){}; + +std::int64_t TimeFormat::parse(const StringLikeWrapper &value) const { return isolated::internal::IsolatedTimeFormat::parse(handle_, value); } diff --git a/src/isolated/internal/IsolatedTimeFormat.cpp b/src/isolated/internal/IsolatedTimeFormat.cpp index b07cae28f..e09ccdb7e 100644 --- a/src/isolated/internal/IsolatedTimeFormat.cpp +++ b/src/isolated/internal/IsolatedTimeFormat.cpp @@ -50,8 +50,8 @@ std::int64_t parse(/* dxfg_time_format_t* */ const JavaObjectHandle(timeFormat.get()), value.data()); + return runGraalFunctionAndThrowIfMinusOne(dxfg_TimeFormat_parse, + static_cast(timeFormat.get()), value.data()); } std::string format(/* dxfg_time_format_t* */ const JavaObjectHandle &timeFormat, @@ -62,7 +62,7 @@ std::string format(/* dxfg_time_format_t* */ const JavaObjectHandle(timeFormat.get()), value); + static_cast(timeFormat.get()), value); auto result = dxfcpp::toString(format); isolated::internal::IsolatedString::release(format); diff --git a/src/isolated/util/IsolatedTimePeriod.cpp b/src/isolated/util/IsolatedTimePeriod.cpp new file mode 100644 index 000000000..4aa3d3f0d --- /dev/null +++ b/src/isolated/util/IsolatedTimePeriod.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::util::IsolatedTimePeriod { +/* dxfg_time_period_t* */ JavaObjectHandle ZERO() { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_TimePeriod_ZERO)); +} + +/* dxfg_time_period_t* */ JavaObjectHandle UNLIMITED() { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_TimePeriod_UNLIMITED)); +} + +/* dxfg_time_period_t* */ JavaObjectHandle valueOf(std::int64_t value) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_TimePeriod_valueOf, value)); +} + +/* dxfg_time_period_t* */ JavaObjectHandle valueOf(std::string_view value) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_TimePeriod_valueOf2, value.data())); +} + +std::int64_t getTime(/* dxfg_time_period_t* */ const JavaObjectHandle &timePeriod) { + if (!timePeriod) { + throw std::invalid_argument( + "Unable to execute function `dxfg_TimePeriod_getTime`. The `timePeriod` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_TimePeriod_getTime, + static_cast(timePeriod.get())); +} + +std::int32_t getSeconds(/* dxfg_time_period_t* */ const JavaObjectHandle &timePeriod) { + if (!timePeriod) { + throw std::invalid_argument( + "Unable to execute function `dxfg_TimePeriod_getSeconds`. The `timePeriod` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_TimePeriod_getSeconds, + static_cast(timePeriod.get())); +} + +std::int64_t getNanos(/* dxfg_time_period_t* */ const JavaObjectHandle &timePeriod) { + if (!timePeriod) { + throw std::invalid_argument( + "Unable to execute function `dxfg_TimePeriod_getNanos`. The `timePeriod` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_TimePeriod_getNanos, + static_cast(timePeriod.get())); +} + +} // namespace isolated::util::IsolatedTimePeriod + +DXFCPP_END_NAMESPACE diff --git a/src/util/TimePeriod.cpp b/src/util/TimePeriod.cpp new file mode 100644 index 000000000..1a9cfeed5 --- /dev/null +++ b/src/util/TimePeriod.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +const TimePeriod TimePeriod::ZERO(isolated::util::IsolatedTimePeriod::ZERO()); + +const TimePeriod TimePeriod::UNLIMITED(isolated::util::IsolatedTimePeriod::UNLIMITED()); + +TimePeriod TimePeriod::valueOf(std::int64_t value) { + return TimePeriod(isolated::util::IsolatedTimePeriod::valueOf(value)); +} + +TimePeriod TimePeriod::valueOf(const StringLikeWrapper &value) { + return TimePeriod(isolated::util::IsolatedTimePeriod::valueOf(value)); +} + +std::int64_t TimePeriod::getTime() const { + return isolated::util::IsolatedTimePeriod::getTime(handle_); +} + +std::int32_t TimePeriod::getSeconds() const { + return isolated::util::IsolatedTimePeriod::getSeconds(handle_); +} + +std::int64_t TimePeriod::getNanos() const { + return isolated::util::IsolatedTimePeriod::getNanos(handle_); +} + +TimePeriod::TimePeriod(JavaObjectHandle &&handle) : handle_(std::move(handle)) { +} + +DXFCPP_END_NAMESPACE From b8888c72aded3a92150c013ff6b77d6f3431aab6 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Wed, 10 Jul 2024 18:59:09 +0300 Subject: [PATCH 037/178] [MDAPI-26] Update Graal SDK to v1.1.21 DXFeedSubscription::getAggregationPeriod DXFeedSubscription::setAggregationPeriod --- .../api/DXFeedSubscription.hpp | 452 ++++++++++-------- .../api/IsolatedDXFeedSubscription.hpp | 131 ++--- .../dxfeed_graal_cpp_api/util/TimePeriod.hpp | 4 + src/api/DXFeedSubscription.cpp | 102 ++-- .../api/IsolatedDXFeedSubscription.cpp | 140 +++--- 5 files changed, 468 insertions(+), 361 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index ce23424ad..3b939a724 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -19,6 +19,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../internal/JavaObjectHandle.hpp" #include "../symbols/SymbolWrapper.hpp" +#include "../util/TimePeriod.hpp" + #include #include #include @@ -67,12 +69,10 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared; @@ -234,6 +234,15 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared feed); + /** + * Returns `true` if this subscription is closed. + * + * @return `true` if this subscription is closed. + * + * @see DXFeedSubscription::close() + */ + bool isClosed() override; + /** * Closes this subscription and makes it permanently detached. * This method notifies all installed instances of subscription change listeners by invoking `subscriptionClosed` @@ -244,158 +253,105 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeSharedgetFeed()->createSubscription({dxfcpp::Quote::TYPE, dxfcpp::TimeAndSale::TYPE}); + * Returns a set of subscribed event types. * - * sub->addEventListener([](auto &&events) { - * for (const auto &e : events) { - * if (auto quote = e->template sharedAs(); quote) { - * std::cout << "Q : " + quote->toString() << std::endl; - * } else if (auto tns = e->template sharedAs(); tns) { - * std::cout << "TnS : " + tns->toString() << std::endl; - * } - * } - * }); + * @return A set of subscribed event types. + */ + std::unordered_set getEventTypes() override; + + /** + * Returns `true` if this subscription contains the corresponding event type. * - * sub->addSymbols({"$TOP10L/Q", "$SP500#45", "$TICK", "SPX"}); - * ``` + * @param eventType The type of event that is checked. + * @return `true` if this subscription contains the corresponding event type. * - * @tparam EventListener The listener type. Listener can be callable with signature: `void(const - * std::vector&)` - * @param listener The event listener - * @return The listener id + * @see DXFeedSubscription::getEventTypes() */ - template - std::size_t addEventListener(EventListener &&listener) -#if __cpp_concepts - requires requires { - { listener(std::vector>{}) } -> std::same_as; - } -#endif - { - if (!tryToSetEventListenerHandle()) { - return OnEventHandler::FAKE_ID; - } + bool containsEventType(const EventTypeEnum &eventType) override; - return onEvent_ += listener; - } + /** + * Clears the set of subscribed symbols. + */ + void clear() const; /** - * Adds typed listener for events. - * Event lister can be added only when subscription is not producing any events. - * The subscription must be either empty - * (its set of @ref DXFeedSubscription::getSymbols() "symbols" is empty or not @ref DXFeedSubscription::attach() - * "attached" to any feed (its set of change listeners is empty). + * Returns a set of subscribed symbols (depending on the actual implementation of subscription). * - * This method does nothing if this subscription is closed. + * The resulting set maybe either a snapshot of the set of the subscribed symbols at the time of invocation or a + * weakly consistent view of the set. * - * Example: - * ```cpp - * auto sub = endpoint->getFeed()->createSubscription({dxfcpp::Quote::TYPE, dxfcpp::TimeAndSale::TYPE}); + * @return A set of subscribed symbols. + */ + std::vector getSymbols() const; + + /** + * Returns a set of decorated symbols (depending on the actual implementation of subscription). * - * sub->addEventListener(std::function([](const std::vector> "es) -> void { - * for (const auto &q : quotes) { - * std::cout << "Q : " + q->toString() << std::endl; - * } - * })); + * The resulting set maybe either a snapshot of the set of the subscribed symbols at the time of invocation or a + * weakly consistent view of the set. * - * sub->addEventListener([](const auto &timeAndSales) -> void { - * for (const auto &tns : timeAndSales) { - * std::cout << "TnS : " + tns->toString() << std::endl; - * } - * }); + * @return A set of decorated subscribed symbols. + */ + std::vector getDecoratedSymbols() const; + + /** + * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection (using + * iterators). * - * sub->addEventListener([](const auto &marketEvents) -> void { - * for (const auto &me : marketEvents) { - * std::cout << "Market Event's symbol: " + me->getEventSymbol() << std::endl; - * } - * }); + * Example: + * ```cpp + * auto v = std::vector{"XBT/USD:GDAX"s, "BTC/EUR:CXBITF"sv, "TSLA", "GOOG"_s}; * - * sub->addSymbols({"$TOP10L/Q", "AAPL", "$TICK", "SPX"}); + * sub->setSymbols(v.begin(), v.end()); * ``` * - * @tparam EventT The event type (EventType's child with field TYPE, convertible to EventTypeEnum or MarketEvent or - * LastingEvent or TimeSeriesEvent or IndexedEvent) - * @param listener The listener. Listener can be callable with signature: `void(const - * std::vector&)` - * @return The listener id + * @tparam SymbolIt The collection's iterator type + * @param begin The beginning of the collection of symbols. + * @param end The end of symbol collection. */ - template - std::size_t addEventListener(std::function> &)> &&listener) -#if __cpp_concepts - requires std::is_base_of_v && - (requires { - { EventT::TYPE } -> dxfcpp::ConvertibleTo; - } || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v) -#endif - { - if (!tryToSetEventListenerHandle()) { - return SimpleHandler> &)>::FAKE_ID; + template void setSymbols(SymbolIt begin, SymbolIt end) const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::setSymbols(symbols = " + elementsToString(begin, end) + ")"); } - return onEvent_ += [l = listener](auto &&events) { - std::vector> filteredEvents{}; - - filteredEvents.reserve(events.size()); - - for (const auto &e : events) { - if (auto expected = e->template sharedAs(); expected) { - filteredEvents.emplace_back(expected); - } - } + auto *list = SymbolWrapper::SymbolListUtils::toGraalList(begin, end); - l(filteredEvents); - }; + setSymbolsImpl(list); + SymbolWrapper::SymbolListUtils::freeGraalList(list); } /** - * Removes listener for events. + * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection. * * Example: * ```cpp - * auto id = sub->addEventListener([](auto){}); + * auto v = std::vector{"XBT/USD:GDAX"s, "BTC/EUR:CXBITF"sv, "TSLA", "GOOG"_s}; * - * sub->removeEventListener(id); + * sub->setSymbols(std::vector{"AAPL", "IBM"}); + * sub->setSymbols(v); * ``` * - * @param listenerId The listener id + * @tparam SymbolsCollection The symbols collection's type + * @param collection The symbols collection */ - void removeEventListener(std::size_t listenerId); + template + void setSymbols(SymbolsCollection &&collection) const { + setSymbols(std::begin(collection), std::end(collection)); + } /** - * Returns a reference to an incoming events' handler (delegate), to which listeners can be added and removed. - * Listener can be callable with signature: `void(const std::vector&)` + * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection + * (initializer list). * * Example: * ```cpp - * auto sub = endpoint->getFeed()->createSubscription({dxfcpp::Quote::TYPE, dxfcpp::TimeAndSale::TYPE}); - * auto id = sub->onEvent() += [](auto &&events) { - * for (const auto &e : events) { - * if (auto quote = e->template sharedAs(); quote) { - * std::cout << "Q : " + quote->toString() << std::endl; - * } else if (auto tns = e->template sharedAs(); tns) { - * std::cout << "TnS : " + tns->toString() << std::endl; - * } - * } - * }; - * - * sub->addSymbols({"$TOP10L/Q", "$SP500#45", "$TICK", "SPX"}); - * sub->onEvent() -= id; + * sub->setSymbols({"AAPL", "IBM"sv, "TSLA"s, "GOOG"_s}); * ``` * - * @return The incoming events' handler (delegate) + * @param collection The symbols collection */ - OnEventHandler &onEvent(); + void setSymbols(std::initializer_list collection) const; /** * Adds the specified symbol to the set of subscribed symbols. @@ -415,22 +371,6 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeSharedremoveSymbols("TSLA"); - * sub->removeSymbols("XBT/USD:GDAX"s); - * sub->removeSymbols("BTC/EUR:CXBITF"sv); - * ``` - * - * @param symbolWrapper The symbol. - */ - void removeSymbols(const SymbolWrapper &symbolWrapper) const; - /** * Adds the specified collection (using iterators) of symbols to the set of subscribed symbols. * @@ -488,6 +428,22 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const; + /** + * Removes the specified symbol from the set of subscribed symbols. + * To conveniently remove one or few symbols you can use @ref DXFeedSubscription::removeSymbols(const + * SymbolsCollection &collection) "removeSymbols(symbols)" method. + * + * Example: + * ```cpp + * sub->removeSymbols("TSLA"); + * sub->removeSymbols("XBT/USD:GDAX"s); + * sub->removeSymbols("BTC/EUR:CXBITF"sv); + * ``` + * + * @param symbolWrapper The symbol. + */ + void removeSymbols(const SymbolWrapper &symbolWrapper) const; + /** * Removes the specified collection (using iterators) of symbols from the set of subscribed symbols. * @@ -546,114 +502,202 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const; /** - * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection (using - * iterators). + * Returns the aggregation period for data for this subscription instance. * - * Example: - * ```cpp - * auto v = std::vector{"XBT/USD:GDAX"s, "BTC/EUR:CXBITF"sv, "TSLA", "GOOG"_s}; - * - * sub->setSymbols(v.begin(), v.end()); - * ``` + * @return The aggregation period for data, represented as a TimePeriod object. + */ + TimePeriod getAggregationPeriod() const; + + /** + * Sets the aggregation period for data. + * This method sets a new aggregation period for data, which will only take effect on the next iteration of + * data notification. For example, if the current aggregation period is 5 seconds and it is changed + * to 1 second, the next call to the next call to the retrieve method may take up to 5 seconds, after which + * the new aggregation period will take effect. * - * @tparam SymbolIt The collection's iterator type - * @param begin The beginning of the collection of symbols. - * @param end The end of symbol collection. + * @param aggregationPeriod the new aggregation period for data */ - template void setSymbols(SymbolIt begin, SymbolIt end) const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::setSymbols(symbols = " + elementsToString(begin, end) + ")"); - } + void setAggregationPeriod(const TimePeriod &aggregationPeriod) const; - auto *list = SymbolWrapper::SymbolListUtils::toGraalList(begin, end); + /** + * Sets the aggregation period for data. + * This method sets a new aggregation period for data, which will only take effect on the next iteration of + * data notification. For example, if the current aggregation period is 5 seconds and it is changed + * to 1 second, the next call to the next call to the retrieve method may take up to 5 seconds, after which + * the new aggregation period will take effect. + * + * @param aggregationPeriod the new aggregation period (in millis) for data + */ + void setAggregationPeriod(std::chrono::milliseconds aggregationPeriod) const { + return setAggregationPeriod(TimePeriod::valueOf(aggregationPeriod)); + } - setSymbolsImpl(list); - SymbolWrapper::SymbolListUtils::freeGraalList(list); + /** + * Sets the aggregation period for data. + * This method sets a new aggregation period for data, which will only take effect on the next iteration of + * data notification. For example, if the current aggregation period is 5 seconds and it is changed + * to 1 second, the next call to the next call to the retrieve method may take up to 5 seconds, after which + * the new aggregation period will take effect. + * + * @param aggregationPeriod the new aggregation period (in millis) for data + */ + void setAggregationPeriod(std::int64_t aggregationPeriod) const { + return setAggregationPeriod(TimePeriod::valueOf(aggregationPeriod)); } /** - * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection. + * Adds listener for events. + * Event lister can be added only when subscription is not producing any events. + * The subscription must be either empty + * (its set of @ref DXFeedSubscription::getSymbols() "symbols" is empty or not @ref DXFeedSubscription::attach() + * "attached" to any feed (its set of change listeners is empty). + * + * This method does nothing if this subscription is closed. * * Example: * ```cpp - * auto v = std::vector{"XBT/USD:GDAX"s, "BTC/EUR:CXBITF"sv, "TSLA", "GOOG"_s}; + * auto sub = endpoint->getFeed()->createSubscription({dxfcpp::Quote::TYPE, dxfcpp::TimeAndSale::TYPE}); * - * sub->setSymbols(std::vector{"AAPL", "IBM"}); - * sub->setSymbols(v); + * sub->addEventListener([](auto &&events) { + * for (const auto &e : events) { + * if (auto quote = e->template sharedAs(); quote) { + * std::cout << "Q : " + quote->toString() << std::endl; + * } else if (auto tns = e->template sharedAs(); tns) { + * std::cout << "TnS : " + tns->toString() << std::endl; + * } + * } + * }); + * + * sub->addSymbols({"$TOP10L/Q", "$SP500#45", "$TICK", "SPX"}); * ``` * - * @tparam SymbolsCollection The symbols collection's type - * @param collection The symbols collection + * @tparam EventListener The listener type. Listener can be callable with signature: `void(const + * std::vector&)` + * @param listener The event listener + * @return The listener id */ - template - void setSymbols(SymbolsCollection &&collection) const { - setSymbols(std::begin(collection), std::end(collection)); + template + std::size_t addEventListener(EventListener &&listener) +#if __cpp_concepts + requires requires { + { listener(std::vector>{}) } -> std::same_as; + } +#endif + { + if (!tryToSetEventListenerHandle()) { + return OnEventHandler::FAKE_ID; + } + + return onEvent_ += listener; } /** - * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection - * (initializer list). + * Adds typed listener for events. + * Event lister can be added only when subscription is not producing any events. + * The subscription must be either empty + * (its set of @ref DXFeedSubscription::getSymbols() "symbols" is empty or not @ref DXFeedSubscription::attach() + * "attached" to any feed (its set of change listeners is empty). + * + * This method does nothing if this subscription is closed. * * Example: * ```cpp - * sub->setSymbols({"AAPL", "IBM"sv, "TSLA"s, "GOOG"_s}); + * auto sub = endpoint->getFeed()->createSubscription({dxfcpp::Quote::TYPE, dxfcpp::TimeAndSale::TYPE}); + * + * sub->addEventListener(std::function([](const std::vector> "es) -> void { + * for (const auto &q : quotes) { + * std::cout << "Q : " + q->toString() << std::endl; + * } + * })); + * + * sub->addEventListener([](const auto &timeAndSales) -> void { + * for (const auto &tns : timeAndSales) { + * std::cout << "TnS : " + tns->toString() << std::endl; + * } + * }); + * + * sub->addEventListener([](const auto &marketEvents) -> void { + * for (const auto &me : marketEvents) { + * std::cout << "Market Event's symbol: " + me->getEventSymbol() << std::endl; + * } + * }); + * + * sub->addSymbols({"$TOP10L/Q", "AAPL", "$TICK", "SPX"}); * ``` * - * @param collection The symbols collection + * @tparam EventT The event type (EventType's child with field TYPE, convertible to EventTypeEnum or MarketEvent + * or LastingEvent or TimeSeriesEvent or IndexedEvent) + * @param listener The listener. Listener can be callable with signature: `void(const + * std::vector&)` + * @return The listener id */ - void setSymbols(std::initializer_list collection) const; + template + std::size_t addEventListener(std::function> &)> &&listener) +#if __cpp_concepts + requires std::is_base_of_v && + (requires { + { EventT::TYPE } -> dxfcpp::ConvertibleTo; + } || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v) +#endif + { + if (!tryToSetEventListenerHandle()) { + return SimpleHandler> &)>::FAKE_ID; + } - /** - * Clears the set of subscribed symbols. - */ - void clear() const; + return onEvent_ += [l = listener](auto &&events) { + std::vector> filteredEvents{}; - /** - * Returns `true` if this subscription is closed. - * - * @return `true` if this subscription is closed. - * - * @see DXFeedSubscription::close() - */ - bool isClosed() override; + filteredEvents.reserve(events.size()); - /** - * Returns a set of subscribed event types. - * - * @return A set of subscribed event types. - */ - std::unordered_set getEventTypes() override; + for (const auto &e : events) { + if (auto expected = e->template sharedAs(); expected) { + filteredEvents.emplace_back(expected); + } + } - /** - * Returns `true` if this subscription contains the corresponding event type. - * - * @param eventType The type of event that is checked. - * @return `true` if this subscription contains the corresponding event type. - * - * @see DXFeedSubscription::getEventTypes() - */ - bool containsEventType(const EventTypeEnum &eventType) override; + l(filteredEvents); + }; + } /** - * Returns a set of subscribed symbols (depending on the actual implementation of subscription). + * Removes listener for events. * - * The resulting set maybe either a snapshot of the set of the subscribed symbols at the time of invocation or a - * weakly consistent view of the set. + * Example: + * ```cpp + * auto id = sub->addEventListener([](auto){}); * - * @return A set of subscribed symbols. + * sub->removeEventListener(id); + * ``` + * + * @param listenerId The listener id */ - std::vector getSymbols() const; + void removeEventListener(std::size_t listenerId); /** - * Returns a set of decorated symbols (depending on the actual implementation of subscription). + * Returns a reference to an incoming events' handler (delegate), to which listeners can be added and removed. + * Listener can be callable with signature: `void(const std::vector&)` * - * The resulting set maybe either a snapshot of the set of the subscribed symbols at the time of invocation or a - * weakly consistent view of the set. + * Example: + * ```cpp + * auto sub = endpoint->getFeed()->createSubscription({dxfcpp::Quote::TYPE, dxfcpp::TimeAndSale::TYPE}); + * auto id = sub->onEvent() += [](auto &&events) { + * for (const auto &e : events) { + * if (auto quote = e->template sharedAs(); quote) { + * std::cout << "Q : " + quote->toString() << std::endl; + * } else if (auto tns = e->template sharedAs(); tns) { + * std::cout << "TnS : " + tns->toString() << std::endl; + * } + * } + * }; * - * @return A set of decorated subscribed symbols. + * sub->addSymbols({"$TOP10L/Q", "$SP500#45", "$TICK", "SPX"}); + * sub->onEvent() -= id; + * ``` + * + * @return The incoming events' handler (delegate) */ - std::vector getDecoratedSymbols() const; + OnEventHandler &onEvent(); std::size_t addChangeListener(std::shared_ptr listener) override; diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 1bd18a5e0..73e080cbc 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -7,12 +7,12 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) -#include - #include "../../api/DXFeedSubscription.hpp" DXFCPP_BEGIN_NAMESPACE +struct TimePeriod; + namespace isolated::api::IsolatedDXFeedSubscription { /** @@ -37,6 +37,21 @@ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &eventClassList); +// int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +// int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_isClosed` in isolation. + * + * @param sub The subscription's handle. + * @return `true` if subscription is closed. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_close` in isolation. * @@ -47,36 +62,48 @@ create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &ev */ void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +// dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t +// *sub); + +// int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_event_clazz_t eventClazz); + /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_addEventListener` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_clear` in isolation. * * @param sub The subscription's handle. - * @param listener The listener's handle. - * @throws std::invalid_argument if DXFeedSubscription's or DXFeedEventListener's handle is invalid. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ -addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, - /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); +void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); -// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -// dxfg_feed_event_listener_t *listener); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getSymbols` in isolation. + * + * @param sub The subscription's handle. + * @return The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getDecoratedSymbols` in isolation. * * @param sub The subscription's handle. - * @param symbol The subscription's symbol. - * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbol is nullptr. + * @return The subscription's decorated symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, - /* dxfg_symbol_t * */ void *symbol); +std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbols` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_setSymbols` in isolation. * * @param sub The subscription's handle. * @param symbols The subscription's symbols. @@ -84,11 +111,10 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, - /* dxfg_symbol_list * */ void *symbols); +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbol` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. * * @param sub The subscription's handle. * @param symbol The subscription's symbol. @@ -96,11 +122,11 @@ void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, - /* dxfg_symbol_t * */ void *symbol); +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbols` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbols` in isolation. * * @param sub The subscription's handle. * @param symbols The subscription's symbols. @@ -108,78 +134,73 @@ void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHand * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, - /* dxfg_symbol_list * */ void *symbols); +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_clear` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbol` in isolation. * * @param sub The subscription's handle. - * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @param symbol The subscription's symbol. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbol is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); - -// int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); - -// int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); +void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_isClosed` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbols` in isolation. * * @param sub The subscription's handle. - * @return `true` if subscription is closed. - * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); -// dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t -// *sub); +// dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -// int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -// dxfg_event_clazz_t eventClazz); +// int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_getSymbols` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getAggregationPeriod` in isolation. * * @param sub The subscription's handle. - * @return The subscription's symbols. * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); - -// int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); +/* dxfg_time_period_t* */ JavaObjectHandle getAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_setSymbols` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_setAggregationPeriod` in isolation. * * @param sub The subscription's handle. - * @param symbols The subscription's symbols. - * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @param period The period's handle. + * @throws std::invalid_argument if DXFeedSubscription's handle or period's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); +/* int32_t */ void setAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_time_period_t * */ const JavaObjectHandle& period); /** - * Calls the Graal SDK function `dxfg_DXFeedSubscription_getDecoratedSymbols` in isolation. + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addEventListener` in isolation. * * @param sub The subscription's handle. - * @return The subscription's decorated symbols. - * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or DXFeedEventListener's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); - -// dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +void /* int32_t */ +addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); -// int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); +// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_feed_event_listener_t *listener); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. diff --git a/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp b/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp index 70380a927..d181aadc7 100644 --- a/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp +++ b/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp @@ -11,10 +11,14 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE +class DXFeedSubscription; + /** * Value class for period of time with support for ISO8601 duration format. */ struct DXFCPP_EXPORT TimePeriod { + friend DXFeedSubscription; + /// Time-period of zero. static const TimePeriod ZERO; diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 3ce0dc80d..933dec714 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -57,6 +57,10 @@ bool DXFeedSubscription::tryToSetEventListenerHandle() { return true; } +void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); +} + void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); } @@ -65,10 +69,6 @@ void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); } -void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); -} - DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) : impl_(std::make_unique()) { } @@ -135,6 +135,15 @@ void DXFeedSubscription::detach(std::shared_ptr feed) { feed->detachSubscription(sharedAs()); } +bool DXFeedSubscription::isClosed() { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::isClosed()"); + } + + return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); +} + void DXFeedSubscription::close() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode @@ -144,92 +153,91 @@ void DXFeedSubscription::close() const { isolated::api::IsolatedDXFeedSubscription::close(handle_); } -void DXFeedSubscription::removeEventListener(std::size_t listenerId) { - onEvent_ -= listenerId; +std::unordered_set DXFeedSubscription::getEventTypes() { + return eventTypes_; } -DXFeedSubscription::OnEventHandler &DXFeedSubscription::onEvent() { - tryToSetEventListenerHandle(); - - return onEvent_; +bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) { + return eventTypes_.contains(eventType); } -void DXFeedSubscription::addSymbols(const SymbolWrapper &symbolWrapper) const { +void DXFeedSubscription::clear() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::addSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); + Debugger::debug(toString() + "::clear()"); } - auto graal = symbolWrapper.toGraalUnique(); - - isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graal.get()); + isolated::api::IsolatedDXFeedSubscription::clear(handle_); } -void DXFeedSubscription::removeSymbols(const SymbolWrapper &symbolWrapper) const { +std::vector DXFeedSubscription::getSymbols() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::removeSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); + Debugger::debug(toString() + "::getSymbols()"); } - auto graal = symbolWrapper.toGraalUnique(); - - isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graal.get()); + return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); } -void DXFeedSubscription::addSymbols(std::initializer_list collection) const { - addSymbols(collection.begin(), collection.end()); -} +std::vector DXFeedSubscription::getDecoratedSymbols() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::getDecoratedSymbols()"); + } -void DXFeedSubscription::removeSymbols(std::initializer_list collection) const { - removeSymbols(collection.begin(), collection.end()); + return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); } void DXFeedSubscription::setSymbols(std::initializer_list collection) const { setSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::clear() const { +void DXFeedSubscription::addSymbols(const SymbolWrapper &symbolWrapper) const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::clear()"); + Debugger::debug(toString() + "::addSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); } - isolated::api::IsolatedDXFeedSubscription::clear(handle_); + auto graal = symbolWrapper.toGraalUnique(); + + isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graal.get()); } -bool DXFeedSubscription::isClosed() { +void DXFeedSubscription::addSymbols(std::initializer_list collection) const { + addSymbols(collection.begin(), collection.end()); +} + +void DXFeedSubscription::removeSymbols(const SymbolWrapper &symbolWrapper) const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::isClosed()"); + Debugger::debug(toString() + "::removeSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); } - return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); + auto graal = symbolWrapper.toGraalUnique(); + + isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graal.get()); } -std::unordered_set DXFeedSubscription::getEventTypes() { - return eventTypes_; +void DXFeedSubscription::removeSymbols(std::initializer_list collection) const { + removeSymbols(collection.begin(), collection.end()); } -bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) { - return eventTypes_.contains(eventType); +TimePeriod DXFeedSubscription::getAggregationPeriod() const { + return TimePeriod(isolated::api::IsolatedDXFeedSubscription::getAggregationPeriod(handle_)); } -std::vector DXFeedSubscription::getSymbols() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::getSymbols()"); - } +void DXFeedSubscription::setAggregationPeriod(const TimePeriod &aggregationPeriod) const { + isolated::api::IsolatedDXFeedSubscription::setAggregationPeriod(handle_, aggregationPeriod.handle_); +} - return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); +void DXFeedSubscription::removeEventListener(std::size_t listenerId) { + onEvent_ -= listenerId; } -std::vector DXFeedSubscription::getDecoratedSymbols() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::getDecoratedSymbols()"); - } +DXFeedSubscription::OnEventHandler &DXFeedSubscription::onEvent() { + tryToSetEventListenerHandle(); - return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); + return onEvent_; } std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index a76c818d4..0d64b3959 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -9,7 +9,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { - JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( @@ -26,6 +25,16 @@ create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &ev dxfg_DXFeedSubscription_new2, static_cast(eventClassList->getHandle()))); } +bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_isClosed`. The `sub` handle is invalid"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_isClosed, + static_cast(sub.get())) == 1; +} + void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { throw std::invalid_argument( @@ -36,22 +45,65 @@ void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle(sub.get())); } -void /* int32_t */ -addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, - /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener) { +void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { throw std::invalid_argument( - "Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The `sub` handle is invalid"); + "Unable to execute function `dxfg_DXFeedSubscription_clear`. The `sub` handle is invalid"); } - if (!listener) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The " - "`listener` handle is invalid"); + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_clear, + static_cast(sub.get())); +} + +std::vector /* dxfg_symbol_list* */ +getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_getSymbols`. The `sub` handle is invalid"); } - runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addEventListener, + dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr(dxfg_DXFeedSubscription_getSymbols, + static_cast(sub.get())); + + auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); + + return result; +} + +std::vector /* dxfg_symbol_list* */ +getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_getDecoratedSymbols`. The `sub` handle is invalid"); + } + + dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr(dxfg_DXFeedSubscription_getDecoratedSymbols, + static_cast(sub.get())); + + auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); + + return result; +} + +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_setSymbols, static_cast(sub.get()), - static_cast(listener.get())); + static_cast(symbols)); } void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, @@ -122,72 +174,50 @@ void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHan static_cast(symbols)); } -void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { +/* dxfg_time_period_t* */ JavaObjectHandle +getAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { throw std::invalid_argument( - "Unable to execute function `dxfg_DXFeedSubscription_clear`. The `sub` handle is invalid"); + "Unable to execute function `dxfg_DXFeedSubscription_getAggregationPeriod`. The `sub` handle is invalid"); } - runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_clear, - static_cast(sub.get())); + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_getAggregationPeriod, static_cast(sub.get()))); } -bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { +/* int32_t */ void setAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_time_period_t * */ const JavaObjectHandle &period) { if (!sub) { throw std::invalid_argument( - "Unable to execute function `dxfg_DXFeedSubscription_isClosed`. The `sub` handle is invalid"); + "Unable to execute function `dxfg_DXFeedSubscription_setAggregationPeriod`. The `sub` handle is invalid"); } - return runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_isClosed, - static_cast(sub.get())) == 1; -} - -std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { - if (!sub) { - throw std::invalid_argument( - "Unable to execute function `dxfg_DXFeedSubscription_getSymbols`. The `sub` handle is invalid"); + if (!period) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setAggregationPeriod`. The " + "`period` handle is invalid"); } - dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr( - dxfg_DXFeedSubscription_getSymbols, static_cast(sub.get())); - - auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); - - runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); - - return result; + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_setAggregationPeriod, + static_cast(sub.get()), + static_cast(period.get())); } -void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { +void /* int32_t */ +addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener) { if (!sub) { throw std::invalid_argument( - "Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The `sub` handle is invalid"); + "Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The `sub` handle is invalid"); } - if (!symbols) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The " - "`symbols` is nullptr"); + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The " + "`listener` handle is invalid"); } - runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_setSymbols, + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addEventListener, static_cast(sub.get()), - static_cast(symbols)); -} - -std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { - if (!sub) { - throw std::invalid_argument( - "Unable to execute function `dxfg_DXFeedSubscription_getDecoratedSymbols`. The `sub` handle is invalid"); - } - - dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr( - dxfg_DXFeedSubscription_getDecoratedSymbols, static_cast(sub.get())); - - auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); - - runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); - - return result; + static_cast(listener.get())); } void /* int32_t */ addChangeListener( From 13cb425cf21744baa2ed7c096be32261807cb11f Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Wed, 10 Jul 2024 19:24:33 +0300 Subject: [PATCH 038/178] [MDAPI-26] Update Graal SDK to v1.1.21 DXFeedSubscription::getEventsBatchLimit DXFeedSubscription::setEventsBatchLimit --- .../api/DXFeedSubscription.hpp | 26 +++++++++++++++++++ .../api/IsolatedDXFeedSubscription.hpp | 25 +++++++++++++----- src/api/DXFeedSubscription.cpp | 8 ++++++ .../api/IsolatedDXFeedSubscription.cpp | 21 +++++++++++++++ 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 3b939a724..012a272fd 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -44,6 +44,17 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared> &)>; + // These constants are linked with same ones in RecordBuffer - POOLED_CAPACITY and UNLIMITED_CAPACITY. + /** + * The optimal events' batch limit for single notification in OnEventHandler. + */ + static const std::int32_t OPTIMAL_BATCH_LIMIT = 0; + + /** + * The maximum events' batch limit for single notification in OnEventHandler. + */ + static const std::int32_t MAX_BATCH_LIMIT = std::numeric_limits::max(); + private: friend struct DXFeed; @@ -702,6 +713,21 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared listener) override; void removeChangeListener(std::size_t changeListenerId) override; + + /** + * Returns maximum number of events in the single notification of OnEventHandler. + * Special cases are supported for constants ::OPTIMAL_BATCH_LIMIT and ::MAX_BATCH_LIMIT. + */ + std::int32_t getEventsBatchLimit() const; + + /** + * Sets maximum number of events in the single notification of OnEventHandler. + * Special cases are supported for constants ::OPTIMAL_BATCH_LIMIT and ::MAX_BATCH_LIMIT. + * + * @param eventsBatchLimit the notification events limit + * @throws JavaException if eventsBatchLimit < 0 (see ::OPTIMAL_BATCH_LIMIT or ::MAX_BATCH_LIMIT) + */ + void setEventsBatchLimit(std::int32_t eventsBatchLimit) const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 73e080cbc..34dd7a4b0 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -87,7 +87,8 @@ void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +std::vector /* dxfg_symbol_list* */ +getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_getDecoratedSymbols` in isolation. @@ -98,9 +99,11 @@ std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscripti * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +std::vector /* dxfg_symbol_list* */ +getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); -// int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); +// int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t +// *symbol); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_setSymbols` in isolation. @@ -111,7 +114,8 @@ std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_s * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. @@ -173,7 +177,8 @@ void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHan * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -/* dxfg_time_period_t* */ JavaObjectHandle getAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +/* dxfg_time_period_t* */ JavaObjectHandle +getAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_setAggregationPeriod` in isolation. @@ -184,7 +189,8 @@ void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHan * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -/* int32_t */ void setAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_time_period_t * */ const JavaObjectHandle& period); +/* int32_t */ void setAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_time_period_t * */ const JavaObjectHandle &period); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addEventListener` in isolation. @@ -232,6 +238,13 @@ void /* int32_t */ removeChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener); +/// dxfg_DXFeedSubscription_getEventsBatchLimit +std::int32_t getEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +/// dxfg_DXFeedSubscription_setEventsBatchLimit +/* int32_t */ void setEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + std::int32_t eventsBatchLimit); + namespace DXFeedEventListener { /** diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 933dec714..9df7955aa 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -272,4 +272,12 @@ void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { } } +std::int32_t DXFeedSubscription::getEventsBatchLimit() const { + return isolated::api::IsolatedDXFeedSubscription::getEventsBatchLimit(handle_); +} + +void DXFeedSubscription::setEventsBatchLimit(std::int32_t eventsBatchLimit) const { + isolated::api::IsolatedDXFeedSubscription::setEventsBatchLimit(handle_, eventsBatchLimit); +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 0d64b3959..7424a7483 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -258,6 +258,27 @@ void /* int32_t */ removeChangeListener( static_cast(listener.get())); } +std::int32_t getEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_getEventsBatchLimit`. " + "The `sub` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_DXFeedSubscription_getEventsBatchLimit, + static_cast(sub.get())); +} + +/* int32_t */ void setEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + std::int32_t eventsBatchLimit) { + if (!sub) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setEventsBatchLimit`. " + "The `sub` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_setEventsBatchLimit, + static_cast(sub.get()), eventsBatchLimit); +} + namespace DXFeedEventListener { JavaObjectHandle /* dxfg_feed_event_listener_t* */ From ff95415f3cee034e6c37ff041bede8b82e10aa6c Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 11 Jul 2024 21:10:16 +0300 Subject: [PATCH 039/178] [MDAPI-26] Update Graal SDK to v1.1.21 Fix `getEventsBatchLimit` docs --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 012a272fd..d3489b1b0 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -715,7 +715,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared Date: Fri, 12 Jul 2024 13:10:20 +0300 Subject: [PATCH 040/178] [MDAPI-26] Update Graal SDK to v1.1.21 AuthToken --- CMakeLists.txt | 7 + include/dxfeed_graal_cpp_api/api.hpp | 3 + .../dxfeed_graal_cpp_api/auth/AuthToken.hpp | 173 ++++++++++++++++++ .../exceptions/JavaException.hpp | 8 + .../isolated/IsolatedCommon.hpp | 8 + .../isolated/auth/IsolatedAuthToken.hpp | 77 ++++++++ .../isolated/internal/IsolatedObject.hpp | 31 ++++ src/auth/AuthToken.cpp | 131 +++++++++++++ src/internal/JavaObjectHandle.cpp | 3 + src/isolated/auth/IsolatedAuthToken.cpp | 135 ++++++++++++++ src/isolated/internal/IsolatedObject.cpp | 57 ++++++ 11 files changed, 633 insertions(+) create mode 100644 include/dxfeed_graal_cpp_api/auth/AuthToken.hpp create mode 100644 include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp create mode 100644 include/dxfeed_graal_cpp_api/isolated/internal/IsolatedObject.hpp create mode 100644 src/auth/AuthToken.cpp create mode 100644 src/isolated/auth/IsolatedAuthToken.cpp create mode 100644 src/isolated/internal/IsolatedObject.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d317e56c..1433c5fd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,8 +210,10 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/IsolatedDXPublisher.cpp src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp + src/isolated/auth/IsolatedAuthToken.cpp src/isolated/promise/IsolatedPromise.cpp src/isolated/internal/IsolatedString.cpp + src/isolated/internal/IsolatedObject.cpp src/isolated/internal/IsolatedTimeFormat.cpp src/isolated/internal/IsolatedTools.cpp src/isolated/util/IsolatedTimePeriod.cpp @@ -232,6 +234,10 @@ set(dxFeedGraalCxxApi_ApiOsub_Sources src/api/osub/ObservableSubscriptionChangeListener.cpp ) +set(dxFeedGraalCxxApi_Auth_Sources + src/auth/AuthToken.cpp +) + set(dxFeedGraalCxxApi_Ipf_Sources src/ipf/InstrumentProfile.cpp src/ipf/InstrumentProfileType.cpp @@ -339,6 +345,7 @@ set(dxFeedGraalCxxApi_Sources ${dxFeedGraalCxxApi_Exceptions_Sources} ${dxFeedGraalCxxApi_Api_Sources} ${dxFeedGraalCxxApi_ApiOsub_Sources} + ${dxFeedGraalCxxApi_Auth_Sources} ${dxFeedGraalCxxApi_Ipf_Sources} ${dxFeedGraalCxxApi_OnDemand_Sources} ${dxFeedGraalCxxApi_Promise_Sources} diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 4bda7b535..bf80e9fba 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -41,6 +41,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "util/TimePeriod.hpp" #include "api/ApiModule.hpp" +#include "auth/AuthToken.hpp" #include "ipf/IpfModule.hpp" #include "entity/EntityModule.hpp" #include "event/EventModule.hpp" @@ -60,8 +61,10 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/api/IsolatedDXPublisher.hpp" #include "isolated/api/IsolatedDXPublisherObservableSubscription.hpp" #include "isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp" +#include "isolated/auth/IsolatedAuthToken.hpp" #include "isolated/promise/IsolatedPromise.hpp" #include "isolated/internal/IsolatedString.hpp" +#include "isolated/internal/IsolatedObject.hpp" #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" diff --git a/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp b/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp new file mode 100644 index 000000000..c7de8b827 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp @@ -0,0 +1,173 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../internal/Conf.hpp" + +#include "../internal/Common.hpp" +#include "../internal/JavaObjectHandle.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +/** + * The AuthToken class represents an authorization token and encapsulates information about the authorization scheme + * and its associated value. + * + *

An AuthToken consists of the following components: + *

    + *
  • Scheme - The authorization scheme (e.g., "Basic" or "Bearer").
  • + *
  • Value - The encoded value, which is scheme-dependent (e.g., an access token per RFC6750 or Base64-encoded + * "user:password" per RFC2617).
  • String representation - A string that combines the scheme and value in the + * format: [scheme + " " + value].
  • + *
+ */ +struct DXFCPP_EXPORT AuthToken { + static const std::string BASIC_SCHEME; + static const std::string BEARER_SCHEME; + + static const AuthToken NULL_TOKEN; + + /** + * Constructs an AuthToken from the specified string. + * + * @param string The string (or c-string or string view) with space-separated scheme and value. + * @return The constructed AuthToken. + * @throws JavaException("InvalidFormatException") if the string is malformed, or if the scheme is "Basic" but the + * format does not comply with RFC2617 + * @see ::toString() + */ + static AuthToken valueOf(const StringLikeWrapper &string); + + /** + * Constructs an AuthToken with the specified username and password per RFC2617. + * Username and password can be empty. + * + * @param userPassword the string (or c-string or string view) containing the username and password in the format + * "username:password" + * @return The constructed AuthToken. + * @throws JavaException("InvalidFormatException") if the userPassword is malformed + */ + static AuthToken createBasicToken(const StringLikeWrapper &userPassword); + + /** + * Constructs an AuthToken with the specified username and password per RFC2617. + * Username and password can be empty. + * + * @param user The username. + * @param password The password. + * @return The constructed AuthToken. + */ + static AuthToken createBasicToken(const StringLikeWrapper &user, const StringLikeWrapper &password); + + /** + * Constructs an AuthToken with the specified username and password per RFC2617. + * If both the username and password are empty returns AuthToken::NULL_TOKEN. + * + * @param user the username + * @param password the password + * @return the constructed AuthToken or AuthToken::NULL_TOKEN + */ + static AuthToken createBasicTokenOrNull(const StringLikeWrapper &user, const StringLikeWrapper &password); + + /** + * Constructs an AuthToken with the specified bearer token per RFC6750. + * + * @param token the access token + * @return the constructed AuthToken + * @throws JavaException("InvalidFormatException") if the token is empty + */ + static AuthToken createBearerToken(const StringLikeWrapper &token); + + /** + * Constructs an AuthToken with the specified bearer token per RFC6750. + * + * @param token the access token + * @return the constructed AuthToken or AuthToken::NULL_TOKEN. + */ + static AuthToken createBearerTokenOrNull(const StringLikeWrapper &token); + + /** + * Constructs an AuthToken with a custom scheme and value. + * + * @param scheme the custom scheme + * @param value the custom value + * @return the constructed AuthToken + * @throws JavaException("InvalidFormatException") if the scheme or value is empty + */ + static AuthToken createCustomToken(const StringLikeWrapper &scheme, const StringLikeWrapper &value); + + /** + * Returns the HTTP authorization header value. + * + * @return the HTTP authorization header value + */ + std::string getHttpAuthorization() const; + + /** + * Returns the username or dxfcpp::String::NUL (`std::string{""}`) if it is not known or applicable. + * + * @return the username, or dxfcpp::String::NUL (`std::string{""}`) if not known or applicable + */ + std::string getUser() const; + + /** + * Returns the password or dxfcpp::String::NUL (`std::string{""}`) if it is not known or applicable. + * + * @return the password, or dxfcpp::String::NUL (`std::string{""}`) if not known or applicable + */ + std::string getPassword() const; + + /** + * Returns the authentication scheme. + * + * @return the authentication scheme + */ + std::string getScheme() const; + + /** + * Returns the access token for RFC6750 or the Base64-encoded "username:password" for RFC2617. + * + * @return the access token or Base64-encoded "username:password" + */ + std::string getValue() const; + + std::string toString() const; + + friend std::ostream &operator<<(std::ostream &os, const AuthToken &t) { + return os << t.toString(); + } + + std::size_t hashCode() const; + + bool operator==(const AuthToken &other) const noexcept; + + virtual ~AuthToken() noexcept = default; + + AuthToken(const AuthToken &) = delete; + AuthToken(AuthToken &&) noexcept = delete; + AuthToken &operator=(const AuthToken &) = delete; + AuthToken &operator=(const AuthToken &&) noexcept = delete; + +private: + + JavaObjectHandle handle_; + std::atomic isNull_; + + explicit AuthToken(JavaObjectHandle &&handle, bool isNull = false); +}; + +DXFCPP_END_NAMESPACE + +template <> struct std::hash { + std::size_t operator()(const dxfcpp::AuthToken &t) const noexcept { + return t.hashCode(); + } +}; + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index 2e0543dec..ee38853e9 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -72,6 +72,14 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { return v; } + template static constexpr T throwIfMinusMin(T v) { + if (v == -std::numeric_limits::min()) { + throwIfJavaThreadExceptionExists(); + } + + return v; + } + /** * @return dxFeed Graal CXX API stack trace + Java (GraalVM) exception's stack trace. */ diff --git a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp index e5c8a501b..ceef8e40b 100644 --- a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp @@ -46,6 +46,10 @@ constexpr auto throwIfMinusOne = [](auto v) { return JavaException::throwIfMinusOne(v); }; +constexpr auto throwIfMinusMin = [](auto v) { + return JavaException::throwIfMinusMin(v); +}; + constexpr auto runGraalFunction(auto graalFunction, auto &&...params) { return runIsolatedThrow( [](auto threadHandle, auto &&graalFunction, auto &&...params) { @@ -74,6 +78,10 @@ constexpr auto runGraalFunctionAndThrowIfMinusOne(auto graalFunction, auto &&... return runGraalFunctionAndThrow(throwIfMinusOne, graalFunction, params...); } +constexpr auto runGraalFunctionAndThrowIfMinusMin(auto graalFunction, auto &&...params) { + return runGraalFunctionAndThrow(throwIfMinusMin, graalFunction, params...); +} + } // namespace isolated DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp b/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp new file mode 100644 index 000000000..6cd1b3085 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp @@ -0,0 +1,77 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include +#include +#include + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include "../../auth/AuthToken.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::auth::IsolatedAuthToken { + +/* + +dxfg_auth_token_t* dxfg_AuthToken_valueOf(graal_isolatethread_t *thread, const char* string); +dxfg_auth_token_t* dxfg_AuthToken_createBasicToken(graal_isolatethread_t *thread, const char* userPassword); +dxfg_auth_token_t* dxfg_AuthToken_createBasicToken2(graal_isolatethread_t *thread, const char* user, const char* password); +dxfg_auth_token_t* dxfg_AuthToken_createBasicTokenOrNull(graal_isolatethread_t *thread, const char* user, const char* password); +dxfg_auth_token_t* dxfg_AuthToken_createBearerToken(graal_isolatethread_t *thread, const char* token); +dxfg_auth_token_t* dxfg_AuthToken_createBearerTokenOrNull(graal_isolatethread_t *thread, const char* token); +dxfg_auth_token_t* dxfg_AuthToken_createCustomToken(graal_isolatethread_t *thread, const char* scheme, const char* value); +const char* dxfg_AuthToken_getHttpAuthorization(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); +const char* dxfg_AuthToken_getUser(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); +const char* dxfg_AuthToken_getPassword(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); +const char* dxfg_AuthToken_getScheme(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); +const char* dxfg_AuthToken_getValue(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); + +*/ + +/// dxfg_AuthToken_valueOf +/* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ std::string_view string); + +/// dxfg_AuthToken_createBasicToken +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view userPassword); + +/// dxfg_AuthToken_createBasicToken2 +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view user, /* const char* */ std::string_view password); + +/// dxfg_AuthToken_createBasicTokenOrNull +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicTokenOrNull(/* const char* */ std::string_view user, /* const char* */ std::string_view password); + +/// dxfg_AuthToken_createBearerToken +/* dxfg_auth_token_t* */ JavaObjectHandle createBearerToken(/* const char* */ std::string_view token); + +/// dxfg_AuthToken_createBearerTokenOrNull +/* dxfg_auth_token_t* */ JavaObjectHandle createBearerTokenOrNull(/* const char* */ std::string_view token); + +/// dxfg_AuthToken_createCustomToken +/* dxfg_auth_token_t* */ JavaObjectHandle createCustomToken(/* const char* */ std::string_view scheme, /* const char* */ std::string_view value); + +/// dxfg_AuthToken_getHttpAuthorization +/* const char* */ std::string getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle& authToken); + +/// dxfg_AuthToken_getUser +/* const char* */ std::string getUser(/* dxfg_auth_token_t* */ const JavaObjectHandle& authToken); + +/// dxfg_AuthToken_getPassword +/* const char* */ std::string getPassword(/* dxfg_auth_token_t* */ const JavaObjectHandle& authToken); + +/// dxfg_AuthToken_getScheme +/* const char* */ std::string getScheme(/* dxfg_auth_token_t* */ const JavaObjectHandle& authToken); + +/// dxfg_AuthToken_getValue +/* const char* */ std::string getValue(/* dxfg_auth_token_t* */ const JavaObjectHandle& authToken); + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedObject.hpp b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedObject.hpp new file mode 100644 index 000000000..97baff111 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedObject.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::internal { +namespace IsolatedObject { + +/// dxfg_Object_toString +/* const char* */ std::string toString(/* dxfg_java_object_handler* */ void *object); + +/// dxfg_Object_equals +std::int32_t equals(/* dxfg_java_object_handler* */ void *object, /* dxfg_java_object_handler* */ void *other); + +/// dxfg_Object_hashCode +/* int32_t */ std::size_t hashCode(/* dxfg_java_object_handler* */ void *object); + +} // namespace IsolatedObject +} // namespace isolated::internal + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/auth/AuthToken.cpp b/src/auth/AuthToken.cpp new file mode 100644 index 000000000..995bcaf57 --- /dev/null +++ b/src/auth/AuthToken.cpp @@ -0,0 +1,131 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +const AuthToken AuthToken::NULL_TOKEN(JavaObjectHandle(), true); + +AuthToken AuthToken::valueOf(const StringLikeWrapper &string) { + return AuthToken(isolated::auth::IsolatedAuthToken::valueOf(string)); +} + +AuthToken AuthToken::createBasicToken(const StringLikeWrapper &userPassword) { + return AuthToken(isolated::auth::IsolatedAuthToken::createBasicToken(userPassword)); +} + +AuthToken AuthToken::createBasicToken(const StringLikeWrapper &user, const StringLikeWrapper &password) { + return AuthToken(isolated::auth::IsolatedAuthToken::createBasicToken(user, password)); +} + +AuthToken AuthToken::createBasicTokenOrNull(const StringLikeWrapper &user, const StringLikeWrapper &password) { + auto handle = isolated::auth::IsolatedAuthToken::createBasicTokenOrNull(user, password); + + if (!handle) { + return AuthToken(JavaObjectHandle(), true); + } + + return AuthToken(std::move(handle)); +} + +AuthToken AuthToken::createBearerToken(const StringLikeWrapper &token) { + return AuthToken(isolated::auth::IsolatedAuthToken::createBearerToken(token)); +} + +AuthToken AuthToken::createBearerTokenOrNull(const StringLikeWrapper &token) { + auto handle = isolated::auth::IsolatedAuthToken::createBearerTokenOrNull(token); + + if (!handle) { + return AuthToken(JavaObjectHandle(), true); + } + + return AuthToken(std::move(handle)); +} + +AuthToken AuthToken::createCustomToken(const StringLikeWrapper &scheme, const StringLikeWrapper &value) { + return AuthToken(isolated::auth::IsolatedAuthToken::createCustomToken(scheme, value)); +} + +std::string AuthToken::getHttpAuthorization() const { + if (isNull_) { + return String::NUL; + } + + return isolated::auth::IsolatedAuthToken::getHttpAuthorization(handle_); +} + +std::string AuthToken::getUser() const { + if (isNull_) { + return String::NUL; + } + + return isolated::auth::IsolatedAuthToken::getUser(handle_); +} + +std::string AuthToken::getPassword() const { + if (isNull_) { + return String::NUL; + } + + return isolated::auth::IsolatedAuthToken::getPassword(handle_); +} + +std::string AuthToken::getScheme() const { + if (isNull_) { + return String::NUL; + } + + return isolated::auth::IsolatedAuthToken::getScheme(handle_); +} + +std::string AuthToken::getValue() const { + if (isNull_) { + return String::NUL; + } + + return isolated::auth::IsolatedAuthToken::getValue(handle_); +} + +std::string AuthToken::toString() const { + if (isNull_) { + return "AuthToken{}"; + } + + return isolated::internal::IsolatedObject::toString(handle_.get()); +} + +std::size_t AuthToken::hashCode() const { + if (isNull_) { + return 0; + } + + return isolated::internal::IsolatedObject::hashCode(handle_.get()); +} + +bool AuthToken::operator==(const AuthToken &other) const noexcept { + if (isNull_) { + return other.isNull_; + } + + if (other.isNull_) { + return false; + } + + return isolated::internal::IsolatedObject::equals(handle_.get(), other.handle_.get()) == 0; +} + +AuthToken::AuthToken(JavaObjectHandle &&handle, bool isNull) : handle_(std::move(handle)), isNull_(isNull) {} + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index daa059153..55faffbc0 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -89,4 +89,7 @@ template struct JavaObjectHandle; template struct JavaObjectHandle; +template struct JavaObjectHandle; + + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/auth/IsolatedAuthToken.cpp b/src/isolated/auth/IsolatedAuthToken.cpp new file mode 100644 index 000000000..aa9bed5d9 --- /dev/null +++ b/src/isolated/auth/IsolatedAuthToken.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::auth::IsolatedAuthToken { + +/// dxfg_AuthToken_valueOf +/* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ std::string_view string) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_valueOf, string.data())); +} + +/// dxfg_AuthToken_createBasicToken +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view userPassword) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicToken, userPassword.data())); +} + +/// dxfg_AuthToken_createBasicToken2 +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view user, + /* const char* */ std::string_view password) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicToken2, user.data(), password.data())); +} + +/// dxfg_AuthToken_createBasicTokenOrNull +/* dxfg_auth_token_t* */ JavaObjectHandle +createBasicTokenOrNull(/* const char* */ std::string_view user, /* const char* */ std::string_view password) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicTokenOrNull, user.data(), password.data())); +} + +/// dxfg_AuthToken_createBearerToken +/* dxfg_auth_token_t* */ JavaObjectHandle createBearerToken(/* const char* */ std::string_view token) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBearerToken, token.data())); +} + +/// dxfg_AuthToken_createBearerTokenOrNull +/* dxfg_auth_token_t* */ JavaObjectHandle createBearerTokenOrNull(/* const char* */ std::string_view token) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBearerTokenOrNull, token.data())); +} + +/// dxfg_AuthToken_createCustomToken +/* dxfg_auth_token_t* */ JavaObjectHandle createCustomToken(/* const char* */ std::string_view scheme, + /* const char* */ std::string_view value) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createCustomToken, scheme.data(), value.data())); +} + +/// dxfg_AuthToken_getHttpAuthorization +/* const char* */ std::string +getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { + if (!authToken) { + throw std::invalid_argument( + "Unable to execute function `dxfg_AuthToken_getHttpAuthorization`. The `authToken` handle is invalid"); + } + + auto httpAuthorization = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getHttpAuthorization, + static_cast(authToken.get())); + auto result = dxfcpp::toString(httpAuthorization); + + internal::IsolatedString::release(httpAuthorization); + + return result; +} + +/// dxfg_AuthToken_getUser +/* const char* */ std::string getUser(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { + if (!authToken) { + throw std::invalid_argument( + "Unable to execute function `dxfg_AuthToken_getUser`. The `authToken` handle is invalid"); + } + + auto user = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getUser, + static_cast(authToken.get())); + auto result = dxfcpp::toString(user); + + internal::IsolatedString::release(user); + + return result; +} + +/// dxfg_AuthToken_getPassword +/* const char* */ std::string getPassword(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { + if (!authToken) { + throw std::invalid_argument( + "Unable to execute function `dxfg_AuthToken_getPassword`. The `authToken` handle is invalid"); + } + + auto password = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getPassword, + static_cast(authToken.get())); + auto result = dxfcpp::toString(password); + + internal::IsolatedString::release(password); + + return result; +} + +/// dxfg_AuthToken_getScheme +/* const char* */ std::string getScheme(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { + if (!authToken) { + throw std::invalid_argument( + "Unable to execute function `dxfg_AuthToken_getScheme`. The `authToken` handle is invalid"); + } + + auto scheme = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getScheme, + static_cast(authToken.get())); + auto result = dxfcpp::toString(scheme); + + internal::IsolatedString::release(scheme); + + return result; +} + +/// dxfg_AuthToken_getValue +/* const char* */ std::string getValue(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { + if (!authToken) { + throw std::invalid_argument( + "Unable to execute function `dxfg_AuthToken_getValue`. The `authToken` handle is invalid"); + } + + auto value = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getValue, + static_cast(authToken.get())); + auto result = dxfcpp::toString(value); + + internal::IsolatedString::release(value); + + return result; +} + +} // namespace isolated::auth::IsolatedAuthToken + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/internal/IsolatedObject.cpp b/src/isolated/internal/IsolatedObject.cpp new file mode 100644 index 000000000..516cf81a6 --- /dev/null +++ b/src/isolated/internal/IsolatedObject.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::internal { +namespace IsolatedObject { + +/// dxfg_Object_toString +/* const char* */ std::string toString(/* dxfg_java_object_handler* */ void *object) { + if (!object) { + throw std::invalid_argument("Unable to execute function `dxfg_Object_toString`. The `object` is null"); + } + + auto value = + runGraalFunctionAndThrowIfNullptr(dxfg_Object_toString, static_cast(object)); + auto result = dxfcpp::toString(value); + + IsolatedString::release(value); + + return result; +} + +/// dxfg_Object_equals +std::int32_t equals(/* dxfg_java_object_handler* */ void *object, /* dxfg_java_object_handler* */ void *other) { + if (!object) { + throw std::invalid_argument("Unable to execute function `dxfg_Object_equals`. The `object` is null"); + } + + if (!other) { + throw std::invalid_argument("Unable to execute function `dxfg_Object_equals`. The `other` is null"); + } + + return runGraalFunctionAndThrowIfMinusMin(dxfg_Object_equals, static_cast(object), + static_cast(other)); +} + +/// dxfg_Object_hashCode +/* int32_t */ std::size_t hashCode(/* dxfg_java_object_handler* */ void *object) { + if (!object) { + throw std::invalid_argument("Unable to execute function `dxfg_Object_hashCode`. The `object` is null"); + } + + return static_cast( + runGraalFunctionAndThrowIfMinusMin(dxfg_Object_hashCode, static_cast(object))); +} + +} // namespace IsolatedObject +} // namespace isolated::internal + +DXFCPP_END_NAMESPACE \ No newline at end of file From 074d75e8644afc2249c21a7a1d11df3962b97fbe Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 12 Jul 2024 13:48:42 +0300 Subject: [PATCH 041/178] [MDAPI-26] Update Graal SDK to v1.1.21 IsolatedInstrumentProfileReader --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../dxfeed_graal_cpp_api/internal/Common.hpp | 52 +++++++++--- .../ipf/InstrumentProfileReader.hpp | 17 ++-- .../isolated/Isolated.hpp | 19 ----- .../isolated/auth/IsolatedAuthToken.hpp | 17 ---- .../ipf/IsolatedInstrumentProfileReader.hpp | 40 +++++++++ src/internal/Isolate.cpp | 81 ------------------- src/ipf/InstrumentProfileReader.cpp | 34 +++----- .../ipf/IsolatedInstrumentProfileReader.cpp | 80 ++++++++++++++++++ 10 files changed, 183 insertions(+), 159 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp create mode 100644 src/isolated/ipf/IsolatedInstrumentProfileReader.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1433c5fd3..7cb82d984 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,6 +217,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/internal/IsolatedTimeFormat.cpp src/isolated/internal/IsolatedTools.cpp src/isolated/util/IsolatedTimePeriod.cpp + src/isolated/ipf/IsolatedInstrumentProfileReader.cpp ) set(dxFeedGraalCxxApi_Api_Sources diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index bf80e9fba..3e79dc74a 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -67,6 +67,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/internal/IsolatedObject.hpp" #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" +#include "isolated/ipf/IsolatedInstrumentProfileReader.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" #include "ondemand/OnDemandService.hpp" diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index 65fa9a8a4..b97531ac8 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -679,18 +679,20 @@ template T fitToType(const U &size) { struct StringLikeWrapper { using DataType = std::variant; - DataType data{}; + private: + DataType data_{}; - StringLikeWrapper(std::string_view sv) : data{sv} { + public: + StringLikeWrapper(std::string_view sv) : data_{sv} { } - StringLikeWrapper(const char *chars) : data{chars == nullptr ? std::string_view{} : std::string_view{chars}} { + StringLikeWrapper(const char *chars) : data_{chars == nullptr ? std::string_view{} : std::string_view{chars}} { } - StringLikeWrapper(const std::string &s) : data{s} { + StringLikeWrapper(const std::string &s) : data_{s} { } - StringLikeWrapper(std::string &&s) : data{std::move(s)} { + StringLikeWrapper(std::string &&s) : data_{std::move(s)} { } template @@ -698,21 +700,53 @@ struct StringLikeWrapper { } operator std::string() const { - if (auto sv = std::get_if(&data); sv) { + if (auto sv = std::get_if(&data_); sv) { return {sv->data(), sv->size()}; } else { - return std::get(data); + return std::get(data_); } } operator std::string_view() const & { - if (auto sv = std::get_if(&data); sv) { + if (auto sv = std::get_if(&data_); sv) { return *sv; } else { - return std::get(data); + return std::get(data_); } } + const char *data() const { + if (auto sv = std::get_if(&data_); sv) { + return sv->data(); + } else { + return std::get(data_).c_str(); + } + } + + const char *c_str() const { + return data(); + } + + bool empty() const { + if (auto sv = std::get_if(&data_); sv) { + return sv->empty(); + } else { + return std::get(data_).empty(); + } + } + + std::size_t size() const { + if (auto sv = std::get_if(&data_); sv) { + return sv->size(); + } else { + return std::get(data_).size(); + } + } + + std::size_t length() const { + return size(); + } + bool operator==(const StringLikeWrapper &sw) const { return sw.operator std::string_view() == this->operator std::string_view(); } diff --git a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp index d55fd1c2e..648989f6c 100644 --- a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp @@ -70,13 +70,13 @@ class DXFCPP_EXPORT InstrumentProfileReader final : public SharedEntity { /** * Returns `true` if IPF was fully read on last InstrumentProfileReader::readFromFile() operation. */ - bool wasComplete() const noexcept; + bool wasComplete() const; /** * Converts a specified string address specification into an URL that will be read by * InstrumentProfileReader::readFromFile() method. */ - static std::string resolveSourceURL(const std::string &address) noexcept; + static std::string resolveSourceURL(const StringLikeWrapper &address); /** * Reads and returns instrument profiles from specified file. @@ -88,15 +88,12 @@ class DXFCPP_EXPORT InstrumentProfileReader final : public SharedEntity { *

Authentication information can be supplied to this method as part of URL user info * like {@code "http://user:password@host:port/path/file.ipf"}. * - *

This is a shortcut for - * {@link #readFromFile(String, String, String) readFromFile}(address, null, null). - * *

This operation updates {@link #getLastModified() lastModified} and {@link #wasComplete() wasComplete}. * * @param address URL of file to read from * @return list of instrument profiles */ - std::vector> readFromFile(const std::string &address) const; + std::vector> readFromFile(const StringLikeWrapper &address) const; /** * Reads and returns instrument profiles from specified address with a specified basic user and password @@ -112,12 +109,12 @@ class DXFCPP_EXPORT InstrumentProfileReader final : public SharedEntity { *

This operation updates {@link #getLastModified() lastModified} and {@link #wasComplete() wasComplete}. * * @param address URL of file to read from - * @param user the user name (may be null) - * @param password the password (may be null) + * @param user the user name + * @param password the password * @return list of instrument profiles */ - std::vector> readFromFile(const std::string &address, const std::string &user, - const std::string &password) const; + std::vector> readFromFile(const StringLikeWrapper &address, const StringLikeWrapper &user, + const StringLikeWrapper &password) const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 0e5d016d4..696ffaad2 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -24,25 +24,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { namespace ipf { -struct InstrumentProfileReader { - static /* dxfg_instrument_profile_reader_t* */ JavaObjectHandle create(); - - static std::int64_t - getLastModified(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle& handle); - - static bool wasComplete(/* dxfg_instrument_profile_reader_t * */ void *graalInstrumentProfileReaderHandle) noexcept; - - static /* dxfg_instrument_profile_list* */ void * - readFromFile(/* dxfg_instrument_profile_reader_t * */ void *graalInstrumentProfileReaderHandle, - const std::string &address) noexcept; - - static /* dxfg_instrument_profile_list* */ void * - readFromFile(/* dxfg_instrument_profile_reader_t * */ void *graalInstrumentProfileReaderHandle, - const std::string &address, const std::string &user, const std::string &password) noexcept; - - static std::string resolveSourceURL(const std::string &address) noexcept; -}; - struct InstrumentProfileCollector { static /* dxfg_ipf_collector_t* */ void *create() noexcept; static std::int64_t getLastUpdateTime(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept; diff --git a/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp b/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp index 6cd1b3085..4ee6a6a1d 100644 --- a/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp @@ -17,23 +17,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::auth::IsolatedAuthToken { -/* - -dxfg_auth_token_t* dxfg_AuthToken_valueOf(graal_isolatethread_t *thread, const char* string); -dxfg_auth_token_t* dxfg_AuthToken_createBasicToken(graal_isolatethread_t *thread, const char* userPassword); -dxfg_auth_token_t* dxfg_AuthToken_createBasicToken2(graal_isolatethread_t *thread, const char* user, const char* password); -dxfg_auth_token_t* dxfg_AuthToken_createBasicTokenOrNull(graal_isolatethread_t *thread, const char* user, const char* password); -dxfg_auth_token_t* dxfg_AuthToken_createBearerToken(graal_isolatethread_t *thread, const char* token); -dxfg_auth_token_t* dxfg_AuthToken_createBearerTokenOrNull(graal_isolatethread_t *thread, const char* token); -dxfg_auth_token_t* dxfg_AuthToken_createCustomToken(graal_isolatethread_t *thread, const char* scheme, const char* value); -const char* dxfg_AuthToken_getHttpAuthorization(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); -const char* dxfg_AuthToken_getUser(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); -const char* dxfg_AuthToken_getPassword(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); -const char* dxfg_AuthToken_getScheme(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); -const char* dxfg_AuthToken_getValue(graal_isolatethread_t *thread, dxfg_auth_token_t* authToken); - -*/ - /// dxfg_AuthToken_valueOf /* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ std::string_view string); diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp new file mode 100644 index 000000000..ad98c579a --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include +#include +#include + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include "../../auth/AuthToken.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ipf::IsolatedInstrumentProfileReader { +/* dxfg_instrument_profile_reader_t* */ JavaObjectHandle create(); + +std::int64_t getLastModified( + /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle); + +bool wasComplete( + /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle); + +/* dxfg_instrument_profile_list* */ void * +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, + const StringLikeWrapper &address); + +/* dxfg_instrument_profile_list* */ void * +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, + const StringLikeWrapper &address, const StringLikeWrapper &user, const StringLikeWrapper &password); + +std::string resolveSourceURL(const StringLikeWrapper &address); +} // namespace isolated::ipf::IsolatedInstrumentProfileReader + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index d3971cf97..1a92f9851 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -158,87 +158,6 @@ using NativeStringList = typename isolated::internal::NativeStringListWrapper -InstrumentProfileReader::create() { - return dxfcpp::JavaObjectHandle{ - runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileReader_new)}; -} - -std::int64_t InstrumentProfileReader::getLastModified( - /* dxfg_instrument_profile_reader_t * */ const dxfcpp::JavaObjectHandle &handle) { - if (!handle) { - throw std::invalid_argument( - "Unable to execute function `dxfg_InstrumentProfileReader_getLastModified`. The handle is invalid"); - } - - return runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfileReader_getLastModified, - static_cast(handle.get())); -} - -bool InstrumentProfileReader::wasComplete( - /* dxfg_instrument_profile_reader_t * */ void *graalInstrumentProfileReaderHandle) noexcept { - if (!graalInstrumentProfileReaderHandle) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileReader_wasComplete(static_cast(threadHandle), - params...) == 1; - }, - false, static_cast(graalInstrumentProfileReaderHandle)); -} - -/* dxfg_instrument_profile_list* */ void * -InstrumentProfileReader::readFromFile(/* dxfg_instrument_profile_reader_t * */ void *graalInstrumentProfileReaderHandle, - const std::string &address) noexcept { - if (!graalInstrumentProfileReaderHandle) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileReader_readFromFile(static_cast(threadHandle), - params...); - }, - nullptr, static_cast(graalInstrumentProfileReaderHandle), address.c_str())); -} - -/* dxfg_instrument_profile_list* */ void * -InstrumentProfileReader::readFromFile(/* dxfg_instrument_profile_reader_t * */ void *graalInstrumentProfileReaderHandle, - const std::string &address, const std::string &user, - const std::string &password) noexcept { - if (!graalInstrumentProfileReaderHandle) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileReader_readFromFile2(static_cast(threadHandle), - params...); - }, - nullptr, static_cast(graalInstrumentProfileReaderHandle), address.c_str(), - user.c_str(), password.c_str())); -} - -std::string InstrumentProfileReader::resolveSourceURL(const std::string &address) noexcept { - auto resolvedURL = runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileReader_resolveSourceURL(static_cast(threadHandle), - params...); - }, - nullptr, address.c_str()); - - auto result = dxfcpp::toString(resolvedURL); - - isolated::internal::IsolatedString::release(resolvedURL); - - return result; -} - /* dxfg_ipf_collector_t* */ void *InstrumentProfileCollector::create() noexcept { return static_cast(runIsolatedOrElse( [](auto threadHandle) { diff --git a/src/ipf/InstrumentProfileReader.cpp b/src/ipf/InstrumentProfileReader.cpp index 0e4028076..2afdd6f93 100644 --- a/src/ipf/InstrumentProfileReader.cpp +++ b/src/ipf/InstrumentProfileReader.cpp @@ -19,7 +19,7 @@ DXFCPP_BEGIN_NAMESPACE InstrumentProfileReader::InstrumentProfileReader() : id_{Id::UNKNOWN}, handle_{} { - handle_ = dxfcpp::isolated::ipf::InstrumentProfileReader::create(); + handle_ = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::create(); } InstrumentProfileReader::Ptr InstrumentProfileReader::create() { @@ -31,28 +31,20 @@ InstrumentProfileReader::Ptr InstrumentProfileReader::create() { } std::int64_t InstrumentProfileReader::getLastModified() const { - return isolated::ipf::InstrumentProfileReader::getLastModified(handle_); + return isolated::ipf::IsolatedInstrumentProfileReader::getLastModified(handle_); } -bool InstrumentProfileReader::wasComplete() const noexcept { - if (!handle_) { - return false; - } - - return isolated::ipf::InstrumentProfileReader::wasComplete(handle_.get()); +bool InstrumentProfileReader::wasComplete() const { + return isolated::ipf::IsolatedInstrumentProfileReader::wasComplete(handle_); } -std::string InstrumentProfileReader::resolveSourceURL(const std::string &address) noexcept { - return isolated::ipf::InstrumentProfileReader::resolveSourceURL(address); +std::string InstrumentProfileReader::resolveSourceURL(const StringLikeWrapper &address) { + return isolated::ipf::IsolatedInstrumentProfileReader::resolveSourceURL(address); } std::vector> -InstrumentProfileReader::readFromFile(const std::string &address) const { - if (!handle_) { - return {}; - } - - auto *list = dxfcpp::isolated::ipf::InstrumentProfileReader::readFromFile(handle_.get(), address); +InstrumentProfileReader::readFromFile(const StringLikeWrapper &address) const { + auto *list = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address); auto result = InstrumentProfile::fromGraalList(list); dxfcpp::isolated::ipf::InstrumentProfileList::release(list); @@ -61,13 +53,9 @@ InstrumentProfileReader::readFromFile(const std::string &address) const { } std::vector> -InstrumentProfileReader::readFromFile(const std::string &address, const std::string &user, - const std::string &password) const { - if (!handle_) { - return {}; - } - - auto *list = dxfcpp::isolated::ipf::InstrumentProfileReader::readFromFile(handle_.get(), address, user, password); +InstrumentProfileReader::readFromFile(const StringLikeWrapper &address, const StringLikeWrapper &user, + const StringLikeWrapper &password) const { + auto *list = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address, user, password); auto result = InstrumentProfile::fromGraalList(list); dxfcpp::isolated::ipf::InstrumentProfileList::release(list); diff --git a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp new file mode 100644 index 000000000..94d234eca --- /dev/null +++ b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ipf::IsolatedInstrumentProfileReader { + +/* dxfg_instrument_profile_reader_t* */ JavaObjectHandle create() { + return dxfcpp::JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileReader_new)}; +} + +std::int64_t getLastModified( + /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle) { + if (!handle) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfileReader_getLastModified`. The handle is invalid"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfileReader_getLastModified, + static_cast(handle.get())); +} + +bool wasComplete( + /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle) { + if (!handle) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfileReader_wasComplete`. The handle is invalid"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfileReader_wasComplete, + static_cast(handle.get())) == 1; +} + +/* dxfg_instrument_profile_list* */ void * +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, + const StringLikeWrapper &address) { + if (!handle) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile`. The handle is invalid"); + } + + return dxfcpp::bit_cast(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfileReader_readFromFile, static_cast(handle.get()), + address.c_str())); +} + +/* dxfg_instrument_profile_list* */ void * +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, + const StringLikeWrapper &address, const StringLikeWrapper &user, const StringLikeWrapper &password) { + if (!handle) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile`. The handle is invalid"); + } + + return dxfcpp::bit_cast(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfileReader_readFromFile2, static_cast(handle.get()), + address.c_str(), user.c_str(), password.c_str())); +} + +std::string resolveSourceURL(const StringLikeWrapper &address) { + auto resolvedURL = + runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileReader_resolveSourceURL, address.c_str()); + + auto result = dxfcpp::toString(resolvedURL); + + isolated::internal::IsolatedString::release(resolvedURL); + + return result; +} + +} // namespace isolated::ipf::IsolatedInstrumentProfileReader + +DXFCPP_END_NAMESPACE \ No newline at end of file From 024f72325370827eb46749aef72944425a060e39 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 12 Jul 2024 13:56:11 +0300 Subject: [PATCH 042/178] [MDAPI-26] Update Graal SDK to v1.1.21 IsolatedInstrumentProfileReader IsolatedAuthToken --- .../isolated/auth/IsolatedAuthToken.hpp | 15 +++-- src/isolated/auth/IsolatedAuthToken.cpp | 60 +++++++++++-------- .../ipf/IsolatedInstrumentProfileReader.cpp | 2 +- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp b/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp index 4ee6a6a1d..440c652fe 100644 --- a/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/auth/IsolatedAuthToken.hpp @@ -7,7 +7,6 @@ #include #include -#include DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) @@ -18,25 +17,25 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::auth::IsolatedAuthToken { /// dxfg_AuthToken_valueOf -/* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ std::string_view string); +/* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ const StringLikeWrapper & string); /// dxfg_AuthToken_createBasicToken -/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view userPassword); +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ const StringLikeWrapper & userPassword); /// dxfg_AuthToken_createBasicToken2 -/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view user, /* const char* */ std::string_view password); +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ const StringLikeWrapper & user, /* const char* */ const StringLikeWrapper & password); /// dxfg_AuthToken_createBasicTokenOrNull -/* dxfg_auth_token_t* */ JavaObjectHandle createBasicTokenOrNull(/* const char* */ std::string_view user, /* const char* */ std::string_view password); +/* dxfg_auth_token_t* */ JavaObjectHandle createBasicTokenOrNull(/* const char* */ const StringLikeWrapper & user, /* const char* */ const StringLikeWrapper & password); /// dxfg_AuthToken_createBearerToken -/* dxfg_auth_token_t* */ JavaObjectHandle createBearerToken(/* const char* */ std::string_view token); +/* dxfg_auth_token_t* */ JavaObjectHandle createBearerToken(/* const char* */ const StringLikeWrapper & token); /// dxfg_AuthToken_createBearerTokenOrNull -/* dxfg_auth_token_t* */ JavaObjectHandle createBearerTokenOrNull(/* const char* */ std::string_view token); +/* dxfg_auth_token_t* */ JavaObjectHandle createBearerTokenOrNull(/* const char* */ const StringLikeWrapper & token); /// dxfg_AuthToken_createCustomToken -/* dxfg_auth_token_t* */ JavaObjectHandle createCustomToken(/* const char* */ std::string_view scheme, /* const char* */ std::string_view value); +/* dxfg_auth_token_t* */ JavaObjectHandle createCustomToken(/* const char* */ const StringLikeWrapper & scheme, /* const char* */ const StringLikeWrapper & value); /// dxfg_AuthToken_getHttpAuthorization /* const char* */ std::string getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle& authToken); diff --git a/src/isolated/auth/IsolatedAuthToken.cpp b/src/isolated/auth/IsolatedAuthToken.cpp index aa9bed5d9..c678e1971 100644 --- a/src/isolated/auth/IsolatedAuthToken.cpp +++ b/src/isolated/auth/IsolatedAuthToken.cpp @@ -4,49 +4,61 @@ #include #include -#include #include +#include DXFCPP_BEGIN_NAMESPACE namespace isolated::auth::IsolatedAuthToken { /// dxfg_AuthToken_valueOf -/* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ std::string_view string) { +/* dxfg_auth_token_t* */ JavaObjectHandle valueOf(/* const char* */ const StringLikeWrapper &string) { return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_valueOf, string.data())); } /// dxfg_AuthToken_createBasicToken -/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view userPassword) { - return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicToken, userPassword.data())); +/* dxfg_auth_token_t* */ JavaObjectHandle +createBasicToken(/* const char* */ const StringLikeWrapper &userPassword) { + return JavaObjectHandle( + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicToken, userPassword.data())); } /// dxfg_AuthToken_createBasicToken2 -/* dxfg_auth_token_t* */ JavaObjectHandle createBasicToken(/* const char* */ std::string_view user, - /* const char* */ std::string_view password) { - return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicToken2, user.data(), password.data())); +/* dxfg_auth_token_t* */ JavaObjectHandle +createBasicToken(/* const char* */ const StringLikeWrapper &user, + /* const char* */ const StringLikeWrapper &password) { + return JavaObjectHandle( + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicToken2, user.data(), password.data())); } /// dxfg_AuthToken_createBasicTokenOrNull /* dxfg_auth_token_t* */ JavaObjectHandle -createBasicTokenOrNull(/* const char* */ std::string_view user, /* const char* */ std::string_view password) { - return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicTokenOrNull, user.data(), password.data())); +createBasicTokenOrNull(/* const char* */ const StringLikeWrapper &user, + /* const char* */ const StringLikeWrapper &password) { + return JavaObjectHandle( + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBasicTokenOrNull, user.data(), password.data())); } /// dxfg_AuthToken_createBearerToken -/* dxfg_auth_token_t* */ JavaObjectHandle createBearerToken(/* const char* */ std::string_view token) { - return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBearerToken, token.data())); +/* dxfg_auth_token_t* */ JavaObjectHandle +createBearerToken(/* const char* */ const StringLikeWrapper &token) { + return JavaObjectHandle( + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBearerToken, token.data())); } /// dxfg_AuthToken_createBearerTokenOrNull -/* dxfg_auth_token_t* */ JavaObjectHandle createBearerTokenOrNull(/* const char* */ std::string_view token) { - return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBearerTokenOrNull, token.data())); +/* dxfg_auth_token_t* */ JavaObjectHandle +createBearerTokenOrNull(/* const char* */ const StringLikeWrapper &token) { + return JavaObjectHandle( + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createBearerTokenOrNull, token.data())); } /// dxfg_AuthToken_createCustomToken -/* dxfg_auth_token_t* */ JavaObjectHandle createCustomToken(/* const char* */ std::string_view scheme, - /* const char* */ std::string_view value) { - return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createCustomToken, scheme.data(), value.data())); +/* dxfg_auth_token_t* */ JavaObjectHandle +createCustomToken(/* const char* */ const StringLikeWrapper &scheme, + /* const char* */ const StringLikeWrapper &value) { + return JavaObjectHandle( + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_createCustomToken, scheme.data(), value.data())); } /// dxfg_AuthToken_getHttpAuthorization @@ -58,7 +70,7 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle } auto httpAuthorization = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getHttpAuthorization, - static_cast(authToken.get())); + static_cast(authToken.get())); auto result = dxfcpp::toString(httpAuthorization); internal::IsolatedString::release(httpAuthorization); @@ -73,8 +85,8 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle "Unable to execute function `dxfg_AuthToken_getUser`. The `authToken` handle is invalid"); } - auto user = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getUser, - static_cast(authToken.get())); + auto user = + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getUser, static_cast(authToken.get())); auto result = dxfcpp::toString(user); internal::IsolatedString::release(user); @@ -90,7 +102,7 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle } auto password = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getPassword, - static_cast(authToken.get())); + static_cast(authToken.get())); auto result = dxfcpp::toString(password); internal::IsolatedString::release(password); @@ -105,8 +117,8 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle "Unable to execute function `dxfg_AuthToken_getScheme`. The `authToken` handle is invalid"); } - auto scheme = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getScheme, - static_cast(authToken.get())); + auto scheme = + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getScheme, static_cast(authToken.get())); auto result = dxfcpp::toString(scheme); internal::IsolatedString::release(scheme); @@ -121,8 +133,8 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle "Unable to execute function `dxfg_AuthToken_getValue`. The `authToken` handle is invalid"); } - auto value = runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getValue, - static_cast(authToken.get())); + auto value = + runGraalFunctionAndThrowIfNullptr(dxfg_AuthToken_getValue, static_cast(authToken.get())); auto result = dxfcpp::toString(value); internal::IsolatedString::release(value); diff --git a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp index 94d234eca..457769ea0 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp @@ -52,7 +52,7 @@ readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, const StringLikeWrapper &address, const StringLikeWrapper &user, const StringLikeWrapper &password) { if (!handle) { throw std::invalid_argument( From c96486964988cd679dfc08047e9f0278aa77bdb4 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 12 Jul 2024 16:40:14 +0300 Subject: [PATCH 043/178] [MDAPI-26] Update Graal SDK to v1.1.21 std::vector> InstrumentProfileReader::readFromFile(const StringLikeWrapper &address, const AuthToken &token) --- .../dxfeed_graal_cpp_api/auth/AuthToken.hpp | 4 ++ .../ipf/InstrumentProfileReader.hpp | 37 +++++++++++++++---- .../ipf/IsolatedInstrumentProfileReader.hpp | 15 +++++--- src/ipf/InstrumentProfileReader.cpp | 10 +++++ .../ipf/IsolatedInstrumentProfileReader.cpp | 19 ++++++++++ 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp b/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp index c7de8b827..f83be83a0 100644 --- a/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp +++ b/include/dxfeed_graal_cpp_api/auth/AuthToken.hpp @@ -15,6 +15,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE +class InstrumentProfileReader; + /** * The AuthToken class represents an authorization token and encapsulates information about the authorization scheme * and its associated value. @@ -28,6 +30,8 @@ DXFCPP_BEGIN_NAMESPACE * */ struct DXFCPP_EXPORT AuthToken { + friend class InstrumentProfileReader; + static const std::string BASIC_SCHEME; static const std::string BEARER_SCHEME; diff --git a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp index 648989f6c..b45217a28 100644 --- a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfileReader.hpp @@ -31,14 +31,14 @@ DXFCPP_BEGIN_NAMESPACE * This reader automatically uses data formats as specified in the stream. * *

This reader is intended for "one time only" usage: create new instances for new IPF reads. - *

Use {@link InstrumentProfileConnection} if support for streaming updates of instrument profiles is needed. + *

Use InstrumentProfileConnection if support for streaming updates of instrument profiles is needed. * *

For backward compatibility reader can be configured with system property "-Dcom.dxfeed.ipf.complete" to control * the strategy for missing "##COMPLETE" tag when reading IPF, possible values are: *

    - *
  • {@code warn} - show warning in the log (default)
  • - *
  • {@code error} - throw exception (future default)
  • - *
  • {@code ignore} - do nothing (for backward compatibility)
  • + *
  • `warn` - show warning in the log (default)
  • + *
  • `error - throw exception (future default)
  • + *
  • `ignore` - do nothing (for backward compatibility)
  • *
*/ class DXFCPP_EXPORT InstrumentProfileReader final : public SharedEntity { @@ -88,7 +88,7 @@ class DXFCPP_EXPORT InstrumentProfileReader final : public SharedEntity { *

Authentication information can be supplied to this method as part of URL user info * like {@code "http://user:password@host:port/path/file.ipf"}. * - *

This operation updates {@link #getLastModified() lastModified} and {@link #wasComplete() wasComplete}. + *

This operation updates @ref ::getLastModified() "lastModified" and @ref ::wasComplete() "wasComplete". * * @param address URL of file to read from * @return list of instrument profiles @@ -106,15 +106,38 @@ class DXFCPP_EXPORT InstrumentProfileReader final : public SharedEntity { *

Specified user and password take precedence over authentication information that is supplied to this method * as part of URL user info like {@code "http://user:password@host:port/path/file.ipf"}. * - *

This operation updates {@link #getLastModified() lastModified} and {@link #wasComplete() wasComplete}. + *

This operation updates @ref ::getLastModified() "lastModified" and @ref ::wasComplete() "wasComplete". * * @param address URL of file to read from * @param user the user name * @param password the password * @return list of instrument profiles */ - std::vector> readFromFile(const StringLikeWrapper &address, const StringLikeWrapper &user, + std::vector> readFromFile(const StringLikeWrapper &address, + const StringLikeWrapper &user, const StringLikeWrapper &password) const; + + /** + * Reads and returns instrument profiles from specified address with a specified token credentials. + * This method recognizes data compression formats "zip" and "gzip" automatically. + * In case of zip the first file entry will be read and parsed as a plain data stream. + * In case of gzip compressed content will be read and processed. + * In other cases data considered uncompressed and will be parsed as is. + * + *

Specified token take precedence over authentication information that is supplied to this method + * as part of URL user info like {@code "http://user:password@host:port/path/file.ipf"}. + * + *

This operation updates @ref ::getLastModified() "lastModified" and @ref ::wasComplete() "wasComplete". + * + * @param address URL of file to read from + * @param token the token + * @return list of instrument profiles + * @throws JavaException("InstrumentProfileFormatException") if input stream does not conform to the Instrument + * Profile Format + * @throws JavaException("IOException") If an I/O error occurs + */ + std::vector> readFromFile(const StringLikeWrapper &address, + const AuthToken &token) const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp index ad98c579a..792bfd21b 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfileReader.hpp @@ -16,22 +16,27 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE namespace isolated::ipf::IsolatedInstrumentProfileReader { -/* dxfg_instrument_profile_reader_t* */ JavaObjectHandle create(); +/* dxfg_instrument_profile_reader_t* */ JavaObjectHandle create(); std::int64_t getLastModified( - /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle); + /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle); bool wasComplete( - /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle); + /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle); /* dxfg_instrument_profile_list* */ void * -readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, const StringLikeWrapper &address); /* dxfg_instrument_profile_list* */ void * -readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, const StringLikeWrapper &address, const StringLikeWrapper &user, const StringLikeWrapper &password); +/// dxfg_InstrumentProfileReader_readFromFile3 +/* dxfg_instrument_profile_list* */ void * +readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, + const StringLikeWrapper &address, const JavaObjectHandle &token); + std::string resolveSourceURL(const StringLikeWrapper &address); } // namespace isolated::ipf::IsolatedInstrumentProfileReader diff --git a/src/ipf/InstrumentProfileReader.cpp b/src/ipf/InstrumentProfileReader.cpp index 2afdd6f93..39c6a04db 100644 --- a/src/ipf/InstrumentProfileReader.cpp +++ b/src/ipf/InstrumentProfileReader.cpp @@ -63,4 +63,14 @@ InstrumentProfileReader::readFromFile(const StringLikeWrapper &address, const St return result; } +std::vector> InstrumentProfileReader::readFromFile(const StringLikeWrapper &address, + const AuthToken &token) const { + auto *list = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address, token.handle_); + auto result = InstrumentProfile::fromGraalList(list); + + dxfcpp::isolated::ipf::InstrumentProfileList::release(list); + + return result; +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp index 457769ea0..807c57405 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp @@ -64,6 +64,25 @@ readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, + const StringLikeWrapper &address, const JavaObjectHandle &token) { + if (!handle) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile`. The handle is invalid"); + } + + if (!token) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile3`. The token is invalid"); + } + + return dxfcpp::bit_cast(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfileReader_readFromFile3, static_cast(handle.get()), + address.c_str(), static_cast(token.get()))); +} + std::string resolveSourceURL(const StringLikeWrapper &address) { auto resolvedURL = runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileReader_resolveSourceURL, address.c_str()); From 05750541f75b91a0ff3f3ac5521ac2a4757f441b Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 12 Jul 2024 16:57:21 +0300 Subject: [PATCH 044/178] [MDAPI-26] Update Graal SDK to v1.1.21 ReleaseNotes.md --- ReleaseNotes.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ReleaseNotes.md diff --git a/ReleaseNotes.md b/ReleaseNotes.md new file mode 100644 index 000000000..145b045f3 --- /dev/null +++ b/ReleaseNotes.md @@ -0,0 +1,12 @@ + +* **\[MDAPI-26]\[C++]** Migrate to Graal SDK v1.1.21. + * Added `Day::getSessions` method. + * New order sources added: `CEDX` and `cedx`. + * Added the ability to use dxFeed Graal SDK stub. In other words, now API can be built for any 32 and 64 platforms. + * Added `TimePeriod` class. + * Added `DXFeedSubscription::getAggregationPeriod` and `DXFeedSubscription::setAggregationPeriod` methods. + * Added `DXFeedSubscription::getEventsBatchLimit` and `DXFeedSubscription::setEventsBatchLimit` methods. + * Added `AuthToken` class. + * Added `InstrumentProfileReader::readFromFile(address, token)` method. + +## v2.0.0 \ No newline at end of file From 3707495141c289b012c538a16be8d108e78e5fe3 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 15 Jul 2024 16:50:13 +0300 Subject: [PATCH 045/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile IsolatedInstrumentProfile --- CMakeLists.txt | 3 +- DEPENDENCIES.md | 2 +- include/dxfeed_graal_cpp_api/api.hpp | 1 + .../ipf/IsolatedInstrumentProfile.hpp | 99 ++++++ src/internal/JavaObjectHandle.cpp | 1 + src/ipf/InstrumentProfile.cpp | 306 +++++++++--------- .../ipf/IsolatedInstrumentProfile.cpp | 15 + 7 files changed, 272 insertions(+), 155 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp create mode 100644 src/isolated/ipf/IsolatedInstrumentProfile.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cb82d984..449377175 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ project(dxFeedGraalCxxApi) set(DXFCXX_VERSION "v2.0.0" CACHE STRING "The dxFeed Graal CXX API package version") -set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.21" CACHE STRING "") +set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.22" CACHE STRING "") set(FMTLIB_VERSION "10.2.1") set(BOOST_VERSION "1.84.0") set(UTFCPP_VERSION "3.2.3") @@ -217,6 +217,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/internal/IsolatedTimeFormat.cpp src/isolated/internal/IsolatedTools.cpp src/isolated/util/IsolatedTimePeriod.cpp + src/isolated/ipf/IsolatedInstrumentProfile.cpp src/isolated/ipf/IsolatedInstrumentProfileReader.cpp ) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 875162037..bb8205fd9 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -2,7 +2,7 @@ ## Compile-time -- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.21 +- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.22 - [Boost](https://github.com/boostorg/boost) v1.84.0 - Boost.Stacktrace 1.0 - [utfcpp](https://github.com/nemtrif/utfcpp) v3.2.3 diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 3e79dc74a..3e63c1164 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -67,6 +67,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/internal/IsolatedObject.hpp" #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" +#include "isolated/ipf/IsolatedInstrumentProfile.hpp" #include "isolated/ipf/IsolatedInstrumentProfileReader.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp new file mode 100644 index 000000000..769ae8c0b --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp @@ -0,0 +1,99 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include +#include +#include + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ipf::IsolatedInstrumentProfile { + +/* +dxfg_instrument_profile_t* dxfg_InstrumentProfile_new(graal_isolatethread_t *thread); +dxfg_instrument_profile_t* dxfg_InstrumentProfile_new2(graal_isolatethread_t *thread, dxfg_instrument_profile_t* ip); +const char* dxfg_InstrumentProfile_getType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getLocalSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setLocalSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getLocalDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setLocalDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getCountry(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setCountry(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getOPOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setOPOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getExchangeData(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setExchangeData(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getExchanges(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setExchanges(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getBaseCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setBaseCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getCFI(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setCFI(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getISIN(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setISIN(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getSEDOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setSEDOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getCUSIP(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setCUSIP(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +int32_t dxfg_InstrumentProfile_getICB(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setICB(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); +int32_t dxfg_InstrumentProfile_getSIC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setSIC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); +double dxfg_InstrumentProfile_getMultiplier(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setMultiplier(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, double value); +const char* dxfg_InstrumentProfile_getProduct(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setProduct(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getUnderlying(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setUnderlying(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +double dxfg_InstrumentProfile_getSPC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setSPC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, double value); +const char* dxfg_InstrumentProfile_getAdditionalUnderlyings(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setAdditionalUnderlyings(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getMMY(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setMMY(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +int32_t dxfg_InstrumentProfile_getExpiration(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setExpiration(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); +int32_t dxfg_InstrumentProfile_getLastTrade(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setLastTrade(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); +double dxfg_InstrumentProfile_getStrike(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setStrike(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, double value); +const char* dxfg_InstrumentProfile_getOptionType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setOptionType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getExpirationStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setExpirationStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getSettlementStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setSettlementStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getPriceIncrements(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setPriceIncrements(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getTradingHours(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_setTradingHours(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); +const char* dxfg_InstrumentProfile_getField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name); +int32_t dxfg_InstrumentProfile_setField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name, const char *value); +double dxfg_InstrumentProfile_getNumericField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name); +int32_t dxfg_InstrumentProfile_setNumericField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name, double value); +int32_t dxfg_InstrumentProfile_getDateField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name); +int32_t dxfg_InstrumentProfile_setDateField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name, int32_t value); +dxfg_string_list* dxfg_InstrumentProfile_getNonEmptyCustomFieldNames(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +int32_t dxfg_InstrumentProfile_release(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); +*/ + + + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index 55faffbc0..413c51c0a 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -63,6 +63,7 @@ template struct JavaObjectHandle; template struct JavaObjectHandle; template struct JavaObjectHandle; +template struct JavaObjectHandle; template struct JavaObjectHandle; template struct JavaObjectHandle; template struct JavaObjectHandle; diff --git a/src/ipf/InstrumentProfile.cpp b/src/ipf/InstrumentProfile.cpp index 6e72bc50f..5a77a13ef 100644 --- a/src/ipf/InstrumentProfile.cpp +++ b/src/ipf/InstrumentProfile.cpp @@ -25,75 +25,75 @@ void InstrumentProfile::fillData(void *graalNative) noexcept { auto graalInstrumentProfile = static_cast(graalNative); - data_ = { - .type = dxfcpp::toString(graalInstrumentProfile->type), - .symbol = dxfcpp::toString(graalInstrumentProfile->symbol), - .description = dxfcpp::toString(graalInstrumentProfile->description), - .localSymbol = dxfcpp::toString(graalInstrumentProfile->local_symbol), - .localDescription = dxfcpp::toString(graalInstrumentProfile->local_description), - .country = dxfcpp::toString(graalInstrumentProfile->country), - .opol = dxfcpp::toString(graalInstrumentProfile->opol), - .exchangeData = dxfcpp::toString(graalInstrumentProfile->exchange_data), - .exchanges = dxfcpp::toString(graalInstrumentProfile->exchanges), - .currency = dxfcpp::toString(graalInstrumentProfile->currency), - .baseCurrency = dxfcpp::toString(graalInstrumentProfile->base_currency), - .cfi = dxfcpp::toString(graalInstrumentProfile->cfi), - .isin = dxfcpp::toString(graalInstrumentProfile->isin), - .sedol = dxfcpp::toString(graalInstrumentProfile->sedol), - .cusip = dxfcpp::toString(graalInstrumentProfile->cusip), - .icb = graalInstrumentProfile->icb, - .sic = graalInstrumentProfile->sic, - .multiplier = graalInstrumentProfile->multiplier, - .product = dxfcpp::toString(graalInstrumentProfile->product), - .underlying = dxfcpp::toString(graalInstrumentProfile->underlying), - .spc = graalInstrumentProfile->spc, - .additionalUnderlyings = dxfcpp::toString(graalInstrumentProfile->additional_underlyings), - .mmy = dxfcpp::toString(graalInstrumentProfile->mmy), - .expiration = graalInstrumentProfile->expiration, - .lastTrade = graalInstrumentProfile->last_trade, - .strike = graalInstrumentProfile->strike, - .optionType = dxfcpp::toString(graalInstrumentProfile->option_type), - .expirationStyle = dxfcpp::toString(graalInstrumentProfile->expiration_style), - .settlementStyle = dxfcpp::toString(graalInstrumentProfile->settlement_style), - .priceIncrements = dxfcpp::toString(graalInstrumentProfile->price_increments), - .tradingHours = dxfcpp::toString(graalInstrumentProfile->trading_hours), - .rawCustomFields = - [](dxfg_string_list *strings) { - std::vector result{}; - - if (!strings || strings->size == 0) { - return result; - } - - result.resize(strings->size); - - for (std::int32_t i = 0; i < strings->size; i++) { - result[i] = dxfcpp::toString(strings->elements[i]); - } - - return result; - }(graalInstrumentProfile->custom_fields), - .customFields = - [](dxfg_string_list *strings) { - std::unordered_map result{}; - - if (!strings || strings->size < 2) { - return result; - } - - for (std::int32_t i = 0; i < strings->size - 1; i += 2) { - auto key = dxfcpp::toString(strings->elements[i]); - - if (key.empty()) { - continue; - } - - result[key] = dxfcpp::toString(strings->elements[i + 1]); - } - - return result; - }(graalInstrumentProfile->custom_fields), - }; + // data_ = { + // .type = dxfcpp::toString(graalInstrumentProfile->type), + // .symbol = dxfcpp::toString(graalInstrumentProfile->symbol), + // .description = dxfcpp::toString(graalInstrumentProfile->description), + // .localSymbol = dxfcpp::toString(graalInstrumentProfile->local_symbol), + // .localDescription = dxfcpp::toString(graalInstrumentProfile->local_description), + // .country = dxfcpp::toString(graalInstrumentProfile->country), + // .opol = dxfcpp::toString(graalInstrumentProfile->opol), + // .exchangeData = dxfcpp::toString(graalInstrumentProfile->exchange_data), + // .exchanges = dxfcpp::toString(graalInstrumentProfile->exchanges), + // .currency = dxfcpp::toString(graalInstrumentProfile->currency), + // .baseCurrency = dxfcpp::toString(graalInstrumentProfile->base_currency), + // .cfi = dxfcpp::toString(graalInstrumentProfile->cfi), + // .isin = dxfcpp::toString(graalInstrumentProfile->isin), + // .sedol = dxfcpp::toString(graalInstrumentProfile->sedol), + // .cusip = dxfcpp::toString(graalInstrumentProfile->cusip), + // .icb = graalInstrumentProfile->icb, + // .sic = graalInstrumentProfile->sic, + // .multiplier = graalInstrumentProfile->multiplier, + // .product = dxfcpp::toString(graalInstrumentProfile->product), + // .underlying = dxfcpp::toString(graalInstrumentProfile->underlying), + // .spc = graalInstrumentProfile->spc, + // .additionalUnderlyings = dxfcpp::toString(graalInstrumentProfile->additional_underlyings), + // .mmy = dxfcpp::toString(graalInstrumentProfile->mmy), + // .expiration = graalInstrumentProfile->expiration, + // .lastTrade = graalInstrumentProfile->last_trade, + // .strike = graalInstrumentProfile->strike, + // .optionType = dxfcpp::toString(graalInstrumentProfile->option_type), + // .expirationStyle = dxfcpp::toString(graalInstrumentProfile->expiration_style), + // .settlementStyle = dxfcpp::toString(graalInstrumentProfile->settlement_style), + // .priceIncrements = dxfcpp::toString(graalInstrumentProfile->price_increments), + // .tradingHours = dxfcpp::toString(graalInstrumentProfile->trading_hours), + // .rawCustomFields = + // [](dxfg_string_list *strings) { + // std::vector result{}; + // + // if (!strings || strings->size == 0) { + // return result; + // } + // + // result.resize(strings->size); + // + // for (std::int32_t i = 0; i < strings->size; i++) { + // result[i] = dxfcpp::toString(strings->elements[i]); + // } + // + // return result; + // }(graalInstrumentProfile->custom_fields), + // .customFields = + // [](dxfg_string_list *strings) { + // std::unordered_map result{}; + // + // if (!strings || strings->size < 2) { + // return result; + // } + // + // for (std::int32_t i = 0; i < strings->size - 1; i += 2) { + // auto key = dxfcpp::toString(strings->elements[i]); + // + // if (key.empty()) { + // continue; + // } + // + // result[key] = dxfcpp::toString(strings->elements[i + 1]); + // } + // + // return result; + // }(graalInstrumentProfile->custom_fields), + // }; } void InstrumentProfile::fillGraalData(void *graalNative) const { @@ -103,54 +103,54 @@ void InstrumentProfile::fillGraalData(void *graalNative) const { auto graalInstrumentProfile = static_cast(graalNative); - graalInstrumentProfile->type = createCString(data_.type); - graalInstrumentProfile->symbol = createCString(data_.symbol); - graalInstrumentProfile->description = createCString(data_.description); - graalInstrumentProfile->local_symbol = createCString(data_.localSymbol); - graalInstrumentProfile->local_description = createCString(data_.localDescription); - graalInstrumentProfile->country = createCString(data_.country); - graalInstrumentProfile->opol = createCString(data_.opol); - graalInstrumentProfile->exchange_data = createCString(data_.exchangeData); - graalInstrumentProfile->exchanges = createCString(data_.exchanges); - graalInstrumentProfile->currency = createCString(data_.currency); - graalInstrumentProfile->base_currency = createCString(data_.baseCurrency); - graalInstrumentProfile->cfi = createCString(data_.cfi); - graalInstrumentProfile->isin = createCString(data_.isin); - graalInstrumentProfile->sedol = createCString(data_.sedol); - graalInstrumentProfile->cusip = createCString(data_.cusip); - graalInstrumentProfile->icb = data_.icb; - graalInstrumentProfile->sic = data_.sic; - graalInstrumentProfile->multiplier = data_.multiplier; - graalInstrumentProfile->product = createCString(data_.product); - graalInstrumentProfile->underlying = createCString(data_.underlying); - graalInstrumentProfile->spc = data_.spc; - graalInstrumentProfile->additional_underlyings = createCString(data_.additionalUnderlyings); - graalInstrumentProfile->mmy = createCString(data_.mmy); - graalInstrumentProfile->expiration = data_.expiration; - graalInstrumentProfile->last_trade = data_.lastTrade; - graalInstrumentProfile->strike = data_.strike; - graalInstrumentProfile->option_type = createCString(data_.optionType); - graalInstrumentProfile->expiration_style = createCString(data_.expirationStyle); - graalInstrumentProfile->settlement_style = createCString(data_.settlementStyle); - graalInstrumentProfile->price_increments = createCString(data_.priceIncrements); - graalInstrumentProfile->trading_hours = createCString(data_.tradingHours); - - if (data_.rawCustomFields.empty()) { - graalInstrumentProfile->custom_fields = nullptr; - } else { - graalInstrumentProfile->custom_fields = new dxfg_string_list{}; - graalInstrumentProfile->custom_fields->size = static_cast(data_.rawCustomFields.size()); - graalInstrumentProfile->custom_fields->elements = new const char *[data_.rawCustomFields.size()] { - nullptr - }; - - for (std::int32_t i = 0; i < graalInstrumentProfile->custom_fields->size; i++) { - // TODO: process null-strings. ? - if (!data_.rawCustomFields[i].empty()) { - graalInstrumentProfile->custom_fields->elements[i] = createCString(data_.rawCustomFields[i]); - } - } - } + // graalInstrumentProfile->type = createCString(data_.type); + // graalInstrumentProfile->symbol = createCString(data_.symbol); + // graalInstrumentProfile->description = createCString(data_.description); + // graalInstrumentProfile->local_symbol = createCString(data_.localSymbol); + // graalInstrumentProfile->local_description = createCString(data_.localDescription); + // graalInstrumentProfile->country = createCString(data_.country); + // graalInstrumentProfile->opol = createCString(data_.opol); + // graalInstrumentProfile->exchange_data = createCString(data_.exchangeData); + // graalInstrumentProfile->exchanges = createCString(data_.exchanges); + // graalInstrumentProfile->currency = createCString(data_.currency); + // graalInstrumentProfile->base_currency = createCString(data_.baseCurrency); + // graalInstrumentProfile->cfi = createCString(data_.cfi); + // graalInstrumentProfile->isin = createCString(data_.isin); + // graalInstrumentProfile->sedol = createCString(data_.sedol); + // graalInstrumentProfile->cusip = createCString(data_.cusip); + // graalInstrumentProfile->icb = data_.icb; + // graalInstrumentProfile->sic = data_.sic; + // graalInstrumentProfile->multiplier = data_.multiplier; + // graalInstrumentProfile->product = createCString(data_.product); + // graalInstrumentProfile->underlying = createCString(data_.underlying); + // graalInstrumentProfile->spc = data_.spc; + // graalInstrumentProfile->additional_underlyings = createCString(data_.additionalUnderlyings); + // graalInstrumentProfile->mmy = createCString(data_.mmy); + // graalInstrumentProfile->expiration = data_.expiration; + // graalInstrumentProfile->last_trade = data_.lastTrade; + // graalInstrumentProfile->strike = data_.strike; + // graalInstrumentProfile->option_type = createCString(data_.optionType); + // graalInstrumentProfile->expiration_style = createCString(data_.expirationStyle); + // graalInstrumentProfile->settlement_style = createCString(data_.settlementStyle); + // graalInstrumentProfile->price_increments = createCString(data_.priceIncrements); + // graalInstrumentProfile->trading_hours = createCString(data_.tradingHours); + // + // if (data_.rawCustomFields.empty()) { + // graalInstrumentProfile->custom_fields = nullptr; + // } else { + // graalInstrumentProfile->custom_fields = new dxfg_string_list{}; + // graalInstrumentProfile->custom_fields->size = static_cast(data_.rawCustomFields.size()); + // graalInstrumentProfile->custom_fields->elements = new const char *[data_.rawCustomFields.size()] { + // nullptr + // }; + // + // for (std::int32_t i = 0; i < graalInstrumentProfile->custom_fields->size; i++) { + // // TODO: process null-strings. ? + // if (!data_.rawCustomFields[i].empty()) { + // graalInstrumentProfile->custom_fields->elements[i] = createCString(data_.rawCustomFields[i]); + // } + // } + // } } void InstrumentProfile::freeGraalData(void *graalNative) noexcept { @@ -160,42 +160,42 @@ void InstrumentProfile::freeGraalData(void *graalNative) noexcept { auto graalInstrumentProfile = static_cast(graalNative); - delete[] graalInstrumentProfile->type; - delete[] graalInstrumentProfile->symbol; - delete[] graalInstrumentProfile->description; - delete[] graalInstrumentProfile->local_symbol; - delete[] graalInstrumentProfile->local_description; - delete[] graalInstrumentProfile->country; - delete[] graalInstrumentProfile->opol; - delete[] graalInstrumentProfile->exchange_data; - delete[] graalInstrumentProfile->exchanges; - delete[] graalInstrumentProfile->currency; - delete[] graalInstrumentProfile->base_currency; - delete[] graalInstrumentProfile->cfi; - delete[] graalInstrumentProfile->isin; - delete[] graalInstrumentProfile->sedol; - delete[] graalInstrumentProfile->cusip; - delete[] graalInstrumentProfile->product; - delete[] graalInstrumentProfile->underlying; - delete[] graalInstrumentProfile->additional_underlyings; - delete[] graalInstrumentProfile->mmy; - delete[] graalInstrumentProfile->option_type; - delete[] graalInstrumentProfile->expiration_style; - delete[] graalInstrumentProfile->settlement_style; - delete[] graalInstrumentProfile->price_increments; - delete[] graalInstrumentProfile->trading_hours; - - if (graalInstrumentProfile->custom_fields) { - if (graalInstrumentProfile->custom_fields->elements && graalInstrumentProfile->custom_fields->size > 0) { - for (std::int32_t i = 0; i < graalInstrumentProfile->custom_fields->size; i++) { - delete[] graalInstrumentProfile->custom_fields->elements[i]; - } - - delete[] graalInstrumentProfile->custom_fields->elements; - } - - delete graalInstrumentProfile->custom_fields; - } + // delete[] graalInstrumentProfile->type; + // delete[] graalInstrumentProfile->symbol; + // delete[] graalInstrumentProfile->description; + // delete[] graalInstrumentProfile->local_symbol; + // delete[] graalInstrumentProfile->local_description; + // delete[] graalInstrumentProfile->country; + // delete[] graalInstrumentProfile->opol; + // delete[] graalInstrumentProfile->exchange_data; + // delete[] graalInstrumentProfile->exchanges; + // delete[] graalInstrumentProfile->currency; + // delete[] graalInstrumentProfile->base_currency; + // delete[] graalInstrumentProfile->cfi; + // delete[] graalInstrumentProfile->isin; + // delete[] graalInstrumentProfile->sedol; + // delete[] graalInstrumentProfile->cusip; + // delete[] graalInstrumentProfile->product; + // delete[] graalInstrumentProfile->underlying; + // delete[] graalInstrumentProfile->additional_underlyings; + // delete[] graalInstrumentProfile->mmy; + // delete[] graalInstrumentProfile->option_type; + // delete[] graalInstrumentProfile->expiration_style; + // delete[] graalInstrumentProfile->settlement_style; + // delete[] graalInstrumentProfile->price_increments; + // delete[] graalInstrumentProfile->trading_hours; + // + // if (graalInstrumentProfile->custom_fields) { + // if (graalInstrumentProfile->custom_fields->elements && graalInstrumentProfile->custom_fields->size > 0) { + // for (std::int32_t i = 0; i < graalInstrumentProfile->custom_fields->size; i++) { + // delete[] graalInstrumentProfile->custom_fields->elements[i]; + // } + // + // delete[] graalInstrumentProfile->custom_fields->elements; + // } + // + // delete graalInstrumentProfile->custom_fields; + // } } std::shared_ptr InstrumentProfile::fromGraal(void *graalNative) { diff --git a/src/isolated/ipf/IsolatedInstrumentProfile.cpp b/src/isolated/ipf/IsolatedInstrumentProfile.cpp new file mode 100644 index 000000000..7d2cf1d73 --- /dev/null +++ b/src/isolated/ipf/IsolatedInstrumentProfile.cpp @@ -0,0 +1,15 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ipf::IsolatedInstrumentProfile { +} + +DXFCPP_END_NAMESPACE \ No newline at end of file From c929425a1ab06ba464c669a7182c7dc9d2eaefcc Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 15 Jul 2024 17:49:22 +0300 Subject: [PATCH 046/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile StringUtils: remove a commented code --- src/internal/utils/StringUtils.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/internal/utils/StringUtils.cpp b/src/internal/utils/StringUtils.cpp index 88067962a..6e9fdf186 100644 --- a/src/internal/utils/StringUtils.cpp +++ b/src/internal/utils/StringUtils.cpp @@ -153,13 +153,6 @@ std::int16_t utf8to16(char in) noexcept { std::string formatTimeStamp(std::int64_t timestamp) { return TimeFormat::DEFAULT.format(timestamp); -// if (timestamp == 0) { -// return "0"; -// } -// -// auto tm = fmt::localtime(static_cast(timestamp / 1000)); -// -// return fmt::format("{:%Y%m%d-%H%M%S}", tm); } std::string formatTimeStampWithTimeZone(std::int64_t timestamp) { @@ -174,28 +167,10 @@ std::string formatTimeStampWithTimeZone(std::int64_t timestamp) { std::string formatTimeStampWithMillis(std::int64_t timestamp) { return TimeFormat::DEFAULT_WITH_MILLIS.format(timestamp); -// -// if (timestamp == 0) { -// return "0"; -// } -// -// auto ms = timestamp % 1000; -// auto tm = fmt::localtime(static_cast(timestamp / 1000)); -// -// return fmt::format("{:%Y%m%d-%H%M%S}.{:0>3}", tm, ms); } std::string formatTimeStampWithMillisWithTimeZone(std::int64_t timestamp) { return TimeFormat::DEFAULT_WITH_MILLIS_WITH_TIMEZONE.format(timestamp); - -// if (timestamp == 0) { -// return "0"; -// } -// -// auto ms = timestamp % 1000; -// auto tm = fmt::localtime(static_cast(timestamp / 1000)); -// -// return fmt::format("{:%Y%m%d-%H%M%S}.{:0>3}{:%z}", tm, ms, tm); } char *createCString(const std::string &s) { From b080662b1df3fa9d6563040166aa1e309d91a33e Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 15 Jul 2024 18:58:11 +0300 Subject: [PATCH 047/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile toStringAny C++11 edition --- .../internal/utils/StringUtils.hpp | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp b/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp index 44559eab5..a3ad6b9c4 100644 --- a/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp +++ b/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp @@ -14,6 +14,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include #include #include +#include DXFCPP_BEGIN_NAMESPACE @@ -34,12 +35,13 @@ DXFCPP_EXPORT std::string toString(void *ptr); DXFCPP_EXPORT std::string toString(double d); -template std::string toStringAny(T &&t); +// template std::string toStringAny(T &&t); template std::string toString(const std::pair &p) { return "{" + toStringAny(p.first) + ", " + toStringAny(p.second) + "}"; } +#if __cpp_concepts template std::string toStringAny(T &&t) { if constexpr (requires { t.toString(); }) { return t.toString(); @@ -55,6 +57,89 @@ template std::string toStringAny(T &&t) { return "unknown"; } } +#else +namespace to_string_any { +namespace detail { +template struct HasToStringMember : std::false_type {}; + +template struct HasToStringMember().toString(), void())> : std::true_type {}; + +template struct HasToStringMemberByPointer : std::false_type {}; + +template +struct HasToStringMemberByPointer()->toString(), void())> : std::true_type {}; + +template struct HasFreeToString : std::false_type {}; + +template struct HasFreeToString()), void())> : std::true_type {}; + +template struct HasStdToString : std::false_type {}; + +template struct HasStdToString()), void())> : std::true_type {}; + +template struct IsConvertibleToString : std::false_type {}; + +template +struct IsConvertibleToString::value>::type> + : std::true_type {}; + +} // namespace detail +} // namespace to_string_any + +template +typename std::enable_if::value, std::string>::type toStringAny(T &&t) { + return t.toString(); +} + +template +typename std::enable_if::value && + !to_string_any::detail::HasToStringMember::value, + std::string>::type +toStringAny(T &&t) { + return t->toString(); +} + +template +typename std::enable_if::value && + !to_string_any::detail::HasToStringMember::value && + !to_string_any::detail::HasToStringMemberByPointer::value, + std::string>::type +toStringAny(T &&t) { + return toString(t); +} + +template +typename std::enable_if::value && + !to_string_any::detail::HasToStringMember::value && + !to_string_any::detail::HasToStringMemberByPointer::value && + !to_string_any::detail::HasFreeToString::value, + std::string>::type +toStringAny(T &&t) { + return std::to_string(t); +} + +template +typename std::enable_if< + to_string_any::detail::IsConvertibleToString::value && !to_string_any::detail::HasToStringMember::value && + !to_string_any::detail::HasToStringMemberByPointer::value && + !to_string_any::detail::HasFreeToString::value && !to_string_any::detail::HasStdToString::value, + std::string>::type +toStringAny(T &&t) { + return std::string(t); +} + +// Fallback case +template +typename std::enable_if::value && + !to_string_any::detail::HasToStringMemberByPointer::value && + !to_string_any::detail::HasFreeToString::value && + !to_string_any::detail::HasStdToString::value && + !to_string_any::detail::IsConvertibleToString::value, + std::string>::type +toStringAny(T &&) { + return "unknown"; +} +#endif /** * Tries to convert UTF16 char to ASCII (part of UTF8) char. From d2142c460cc8ac454934ef2efd8d19061a1e87e9 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Wed, 17 Jul 2024 19:14:31 +0300 Subject: [PATCH 048/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile IsolatedInstrumentProfile --- .../isolated/internal/IsolatedString.hpp | 3 + .../ipf/IsolatedInstrumentProfile.hpp | 359 +++++++++++---- src/isolated/internal/IsolatedString.cpp | 9 + .../ipf/IsolatedInstrumentProfile.cpp | 418 ++++++++++++++++++ 4 files changed, 710 insertions(+), 79 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp index 63330153f..28a0c5326 100644 --- a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp @@ -24,6 +24,9 @@ namespace IsolatedString { * @throws GraalException if something happened with the GraalVM. */ bool release(const char *string); + +std::unique_ptr toUnique(const char *string); + } // namespace IsolatedString namespace IsolatedStringList { diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp index 769ae8c0b..944fa0218 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp @@ -5,9 +5,11 @@ #include "../../internal/Conf.hpp" +#include "../../ipf/InstrumentProfile.hpp" + #include #include -#include +#include DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) @@ -15,84 +17,283 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::ipf::IsolatedInstrumentProfile { -/* -dxfg_instrument_profile_t* dxfg_InstrumentProfile_new(graal_isolatethread_t *thread); -dxfg_instrument_profile_t* dxfg_InstrumentProfile_new2(graal_isolatethread_t *thread, dxfg_instrument_profile_t* ip); -const char* dxfg_InstrumentProfile_getType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getLocalSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setLocalSymbol(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getLocalDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setLocalDescription(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getCountry(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setCountry(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getOPOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setOPOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getExchangeData(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setExchangeData(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getExchanges(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setExchanges(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getBaseCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setBaseCurrency(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getCFI(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setCFI(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getISIN(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setISIN(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getSEDOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setSEDOL(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getCUSIP(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setCUSIP(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -int32_t dxfg_InstrumentProfile_getICB(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setICB(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); -int32_t dxfg_InstrumentProfile_getSIC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setSIC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); -double dxfg_InstrumentProfile_getMultiplier(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setMultiplier(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, double value); -const char* dxfg_InstrumentProfile_getProduct(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setProduct(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getUnderlying(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setUnderlying(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -double dxfg_InstrumentProfile_getSPC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setSPC(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, double value); -const char* dxfg_InstrumentProfile_getAdditionalUnderlyings(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setAdditionalUnderlyings(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getMMY(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setMMY(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -int32_t dxfg_InstrumentProfile_getExpiration(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setExpiration(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); -int32_t dxfg_InstrumentProfile_getLastTrade(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setLastTrade(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, int32_t value); -double dxfg_InstrumentProfile_getStrike(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setStrike(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, double value); -const char* dxfg_InstrumentProfile_getOptionType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setOptionType(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getExpirationStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setExpirationStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getSettlementStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setSettlementStyle(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getPriceIncrements(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setPriceIncrements(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getTradingHours(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_setTradingHours(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *value); -const char* dxfg_InstrumentProfile_getField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name); -int32_t dxfg_InstrumentProfile_setField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name, const char *value); -double dxfg_InstrumentProfile_getNumericField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name); -int32_t dxfg_InstrumentProfile_setNumericField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name, double value); -int32_t dxfg_InstrumentProfile_getDateField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name); -int32_t dxfg_InstrumentProfile_setDateField(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip, const char *name, int32_t value); -dxfg_string_list* dxfg_InstrumentProfile_getNonEmptyCustomFieldNames(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -int32_t dxfg_InstrumentProfile_release(graal_isolatethread_t *thread, dxfg_instrument_profile_t *ip); -*/ - - - -} +// dxfg_InstrumentProfile_new +/* dxfg_instrument_profile_t* */ JavaObjectHandle create(); + +// dxfg_InstrumentProfile_new2 +/* dxfg_instrument_profile_t* */ JavaObjectHandle +create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_getType +/* const char* */ std::string getType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setType +/* std::int32_t */ void setType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getSymbol +/* const char* */ std::string getSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setSymbol +/* std::int32_t */ void setSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getDescription +/* const char* */ std::string +getDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setDescription +/* std::int32_t */ void setDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getLocalSymbol +/* const char* */ std::string +getLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setLocalSymbol +/* std::int32_t */ void setLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getLocalDescription +/* const char* */ std::string +getLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setLocalDescription +/* std::int32_t */ void +setLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getCountry +/* const char* */ std::string +getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setCountry +/* std::int32_t */ void setCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getOPOL +/* const char* */ std::string getOPOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setOPOL +/* std::int32_t */ void setOPOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getExchangeData +/* const char* */ std::string +getExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setExchangeData +/* std::int32_t */ void setExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getExchanges +/* const char* */ std::string +getExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setExchanges +/* std::int32_t */ void setExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getCurrency +/* const char* */ std::string +getCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setCurrency +/* std::int32_t */ void setCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getBaseCurrency +/* const char* */ std::string +getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setBaseCurrency +/* std::int32_t */ void setBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getCFI +/* const char* */ std::string getCFI(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setCFI +/* std::int32_t */ void setCFI(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getISIN +/* const char* */ std::string getISIN(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setISIN +/* std::int32_t */ void setISIN(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getSEDOL +/* const char* */ std::string getSEDOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setSEDOL +/* std::int32_t */ void setSEDOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getCUSIP +/* const char* */ std::string getCUSIP(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setCUSIP +/* std::int32_t */ void setCUSIP(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getICB +std::int32_t getICB(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setICB +/* std::int32_t */ void setICB(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value); + +// dxfg_InstrumentProfile_getSIC +std::int32_t getSIC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setSIC +/* std::int32_t */ void setSIC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value); + +// dxfg_InstrumentProfile_getMultiplier +double getMultiplier(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setMultiplier +/* std::int32_t */ void setMultiplier(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + double value); + +// dxfg_InstrumentProfile_getProduct +/* const char* */ std::string +getProduct(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setProduct +/* std::int32_t */ void setProduct(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getUnderlying +/* const char* */ std::string +getUnderlying(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setUnderlying +/* std::int32_t */ void setUnderlying(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getSPC +double getSPC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setSPC +/* std::int32_t */ void setSPC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + double value); + +// dxfg_InstrumentProfile_getAdditionalUnderlyings +/* const char* */ std::string +getAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setAdditionalUnderlyings +/* std::int32_t */ void +setAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getMMY +/* const char* */ std::string getMMY(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setMMY +/* std::int32_t */ void setMMY(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getExpiration +std::int32_t getExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setExpiration +/* std::int32_t */ void setExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value); + +// dxfg_InstrumentProfile_getLastTrade +std::int32_t getLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setLastTrade +/* std::int32_t */ void setLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value); + +// dxfg_InstrumentProfile_getStrike +double getStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setStrike +/* std::int32_t */ void setStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + double value); + +// dxfg_InstrumentProfile_getOptionType +/* const char* */ std::string +getOptionType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setOptionType +/* std::int32_t */ void setOptionType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getExpirationStyle +/* const char* */ std::string +getExpirationStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setExpirationStyle +/* std::int32_t */ void +setExpirationStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getSettlementStyle +/* const char* */ std::string +getSettlementStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setSettlementStyle +/* std::int32_t */ void +setSettlementStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getPriceIncrements +/* const char* */ std::string +getPriceIncrements(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setPriceIncrements +/* std::int32_t */ void +setPriceIncrements(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getTradingHours +/* const char* */ std::string +getTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_setTradingHours +/* std::int32_t */ void setTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getField +/* const char* */ std::string getField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name); + +// dxfg_InstrumentProfile_setField +/* std::int32_t */ void setField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name, const StringLikeWrapper &value); + +// dxfg_InstrumentProfile_getNumericField +double getNumericField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name); + +// dxfg_InstrumentProfile_setNumericField +/* std::int32_t */ void setNumericField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name, double value); + +// dxfg_InstrumentProfile_getDateField +std::int32_t getDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name); + +// dxfg_InstrumentProfile_setDateField +/* std::int32_t */ void setDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name, std::int32_t value); + +// dxfg_InstrumentProfile_getNonEmptyCustomFieldNames +/* dxfg_string_list* */ std::vector +getNonEmptyCustomFieldNames(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip); + +// dxfg_InstrumentProfile_release +// /* std::int32_t */ void release(/* dxfg_instrument_profile_t* */ const JavaObjectHandle& ip); + +} // namespace isolated::ipf::IsolatedInstrumentProfile DXFCPP_END_NAMESPACE diff --git a/src/isolated/internal/IsolatedString.cpp b/src/isolated/internal/IsolatedString.cpp index ac294b257..a9c1c7d73 100644 --- a/src/isolated/internal/IsolatedString.cpp +++ b/src/isolated/internal/IsolatedString.cpp @@ -13,6 +13,9 @@ namespace isolated::internal { namespace IsolatedString { bool release(const char *string) { + std::cerr << 222 << std::endl; + std::cerr << toString(string) << std::endl; + if (!string) { throw std::invalid_argument("Unable to execute function `dxfg_String_release`. The `string` is nullptr"); } @@ -20,6 +23,12 @@ bool release(const char *string) { return runGraalFunctionAndThrowIfLessThanZero(dxfg_String_release, string) == 0; } +std::unique_ptr toUnique(const char *string) { +std::cerr << 111 << std::endl; + + return {string, release}; +} + } // namespace IsolatedString namespace IsolatedStringList { diff --git a/src/isolated/ipf/IsolatedInstrumentProfile.cpp b/src/isolated/ipf/IsolatedInstrumentProfile.cpp index 7d2cf1d73..40289ee44 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfile.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfile.cpp @@ -10,6 +10,424 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::ipf::IsolatedInstrumentProfile { + +// dxfg_InstrumentProfile_new +/* dxfg_instrument_profile_t* */ JavaObjectHandle create() { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfile_new)); +} + +// dxfg_InstrumentProfile_new2 +/* dxfg_instrument_profile_t* */ JavaObjectHandle +create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_new2`. The ip handle is invalid"); + } + + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_new2, static_cast(ip.get()))); +} + +// dxfg_InstrumentProfile_getType +/* const char* */ std::string getType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getType`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getType, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setType +/* int32_t */ void setType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setType`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setType, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getSymbol +/* const char* */ std::string +getSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getSymbol`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getSymbol, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setSymbol +/* std::int32_t */ void setSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setSymbol`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setSymbol, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getDescription +/* const char* */ std::string +getDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getDescription`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getDescription, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setDescription +/* std::int32_t */ void setDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setDescription`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setDescription, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getLocalSymbol +/* const char* */ std::string +getLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getLocalSymbol`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getLocalSymbol, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setLocalSymbol +/* std::int32_t */ void setLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setLocalSymbol`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setLocalSymbol, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getLocalDescription +/* const char* */ std::string +getLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getLocalDescription`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getLocalDescription, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setLocalDescription +/* std::int32_t */ void +setLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setLocalDescription`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setLocalDescription, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getCountry +/* const char* */ std::string +getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getCountry`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getCountry, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setCountry +/* std::int32_t */ void setCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setCountry`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setCountry, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getOPOL +/* const char* */ std::string getOPOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getOPOL`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getOPOL, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setOPOL +/* std::int32_t */ void setOPOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setOPOL`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setOPOL, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getExchangeData +/* const char* */ std::string +getExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getExchangeData`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getExchangeData, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setExchangeData +/* std::int32_t */ void setExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setExchangeData`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setExchangeData, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getExchanges +/* const char* */ std::string +getExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getExchanges`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getExchanges, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setExchanges +/* std::int32_t */ void setExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setExchanges`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setExchanges, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getCurrency +/* const char* */ std::string +getCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getCurrency`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getCurrency, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setCurrency +/* std::int32_t */ void setCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setCurrency`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setCurrency, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getBaseCurrency +/* const char* */ std::string +getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getBaseCurrency`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getBaseCurrency, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; } +// dxfg_InstrumentProfile_setBaseCurrency +/* std::int32_t */ void setBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setBaseCurrency`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setBaseCurrency, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getCFI +/* const char* */ std::string getCFI(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getCFI`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getCFI, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setCFI +/* std::int32_t */ void setCFI(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setCFI`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setCFI, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getISIN +/* const char* */ std::string getISIN(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getISIN`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getISIN, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setISIN +/* std::int32_t */ void setISIN(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setISIN`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setISIN, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getSEDOL +/* const char* */ std::string getSEDOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getSEDOL`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getSEDOL, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setSEDOL +/* std::int32_t */ void setSEDOL(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setSEDOL`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setSEDOL, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getCUSIP +/* const char* */ std::string getCUSIP(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getCUSIP`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getCUSIP, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setCUSIP +/* std::int32_t */ void setCUSIP(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setCUSIP`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_InstrumentProfile_setCUSIP, + static_cast(ip.get()), value.c_str()); +} + +} // namespace isolated::ipf::IsolatedInstrumentProfile + DXFCPP_END_NAMESPACE \ No newline at end of file From 5a3455d15d8888464c27586aa254bfc013ed78b0 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 18 Jul 2024 15:19:46 +0300 Subject: [PATCH 049/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile IsolatedInstrumentProfile --- .../exceptions/JavaException.hpp | 8 + .../isolated/IsolatedCommon.hpp | 8 + .../isolated/internal/IsolatedString.hpp | 3 + src/isolated/internal/IsolatedString.cpp | 9 +- .../ipf/IsolatedInstrumentProfile.cpp | 568 +++++++++++++++++- 5 files changed, 561 insertions(+), 35 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index ee38853e9..b27c9f926 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -80,6 +80,14 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { return v; } + template static constexpr T throwIfMinusInf(T v) { + if (v == -std::numeric_limits::infinity()) { + throwIfJavaThreadExceptionExists(); + } + + return v; + } + /** * @return dxFeed Graal CXX API stack trace + Java (GraalVM) exception's stack trace. */ diff --git a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp index ceef8e40b..83a61fa8c 100644 --- a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp @@ -50,6 +50,10 @@ constexpr auto throwIfMinusMin = [](auto v) { return JavaException::throwIfMinusMin(v); }; +constexpr auto throwIfMinusInf = [](auto v) { + return JavaException::throwIfMinusInf(v); +}; + constexpr auto runGraalFunction(auto graalFunction, auto &&...params) { return runIsolatedThrow( [](auto threadHandle, auto &&graalFunction, auto &&...params) { @@ -82,6 +86,10 @@ constexpr auto runGraalFunctionAndThrowIfMinusMin(auto graalFunction, auto &&... return runGraalFunctionAndThrow(throwIfMinusMin, graalFunction, params...); } +constexpr auto runGraalFunctionAndThrowIfMinusInf(auto graalFunction, auto &&...params) { + return runGraalFunctionAndThrow(throwIfMinusInf, graalFunction, params...); +} + } // namespace isolated DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp index 28a0c5326..4f26195ac 100644 --- a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp @@ -40,6 +40,9 @@ namespace IsolatedStringList { * @throws GraalException if something happened with the GraalVM. */ bool release(/* dxfg_string_list* */ void *stringList); + +std::unique_ptr toUnique(void *stringList); + } // namespace IsolatedStringList template struct NativeStringListWrapper final { diff --git a/src/isolated/internal/IsolatedString.cpp b/src/isolated/internal/IsolatedString.cpp index a9c1c7d73..418af0e42 100644 --- a/src/isolated/internal/IsolatedString.cpp +++ b/src/isolated/internal/IsolatedString.cpp @@ -13,9 +13,6 @@ namespace isolated::internal { namespace IsolatedString { bool release(const char *string) { - std::cerr << 222 << std::endl; - std::cerr << toString(string) << std::endl; - if (!string) { throw std::invalid_argument("Unable to execute function `dxfg_String_release`. The `string` is nullptr"); } @@ -24,8 +21,6 @@ bool release(const char *string) { } std::unique_ptr toUnique(const char *string) { -std::cerr << 111 << std::endl; - return {string, release}; } @@ -43,6 +38,10 @@ bool release(/* dxfg_string_list* */ void *stringList) { static_cast(stringList)); } +std::unique_ptr toUnique(void *stringList) { + return {stringList, release}; +} + } // namespace IsolatedStringList } // namespace isolated::internal diff --git a/src/isolated/ipf/IsolatedInstrumentProfile.cpp b/src/isolated/ipf/IsolatedInstrumentProfile.cpp index 40289ee44..af8c83e05 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfile.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfile.cpp @@ -50,8 +50,8 @@ create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setType, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getSymbol @@ -77,8 +77,8 @@ getSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setSymbol, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getDescription @@ -104,8 +104,8 @@ getDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setDescription, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getLocalSymbol @@ -131,8 +131,8 @@ getLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setLocalSymbol, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getLocalDescription @@ -159,8 +159,8 @@ setLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setLocalDescription, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getCountry @@ -186,8 +186,8 @@ getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setCountry, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getOPOL @@ -212,8 +212,8 @@ getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setOPOL, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getExchangeData @@ -239,8 +239,8 @@ getExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setExchangeData, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getExchanges @@ -266,8 +266,8 @@ getExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setExchanges, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getCurrency @@ -293,8 +293,8 @@ getCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setCurrency, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getBaseCurrency @@ -320,8 +320,8 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setBaseCurrency, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getCFI @@ -346,8 +346,8 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setCFI, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getISIN @@ -372,8 +372,8 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setISIN, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getSEDOL @@ -398,8 +398,8 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setSEDOL, + static_cast(ip.get()), value.c_str()); } // dxfg_InstrumentProfile_getCUSIP @@ -424,8 +424,516 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle(ip.get()), value.c_str()); + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setCUSIP, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getICB +std::int32_t getICB(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getICB`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_getICB, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setICB +/* std::int32_t */ void setICB(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setICB`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setICB, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getSIC +std::int32_t getSIC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getSIC`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_getSIC, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setSIC +/* std::int32_t */ void setSIC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setSIC`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setSIC, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getMultiplier +double getMultiplier(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getMultiplier`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusInf(dxfg_InstrumentProfile_getMultiplier, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setMultiplier +/* std::int32_t */ void setMultiplier(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + double value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setMultiplier`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setMultiplier, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getProduct +/* const char* */ std::string +getProduct(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getProduct`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getProduct, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setProduct +/* std::int32_t */ void setProduct(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setProduct`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setProduct, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getUnderlying +/* const char* */ std::string +getUnderlying(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getUnderlying`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getUnderlying, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setUnderlying +/* std::int32_t */ void setUnderlying(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setUnderlying`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setUnderlying, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getSPC +double getSPC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getSPC`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusInf(dxfg_InstrumentProfile_getSPC, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setSPC +/* std::int32_t */ void setSPC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + double value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setSPC`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setSPC, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getAdditionalUnderlyings +/* const char* */ std::string +getAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getAdditionalUnderlyings`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getAdditionalUnderlyings, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setAdditionalUnderlyings +/* std::int32_t */ void +setAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setAdditionalUnderlyings`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setAdditionalUnderlyings, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getMMY +/* const char* */ std::string getMMY(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getMMY`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getMMY, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setMMY +/* std::int32_t */ void setMMY(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setMMY`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setMMY, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getExpiration +std::int32_t getExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getExpiration`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_getExpiration, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setExpiration +/* std::int32_t */ void setExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setExpiration`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setExpiration, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getLastTrade +std::int32_t getLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getLastTrade`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_getLastTrade, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setLastTrade +/* std::int32_t */ void setLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + std::int32_t value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setLastTrade`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setLastTrade, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getStrike +double getStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getStrike`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusInf(dxfg_InstrumentProfile_getStrike, + static_cast(ip.get())); +} + +// dxfg_InstrumentProfile_setStrike +/* std::int32_t */ void setStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + double value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setStrike`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setStrike, + static_cast(ip.get()), value); +} + +// dxfg_InstrumentProfile_getOptionType +/* const char* */ std::string +getOptionType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getOptionType`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getOptionType, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setOptionType +/* std::int32_t */ void setOptionType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setOptionType`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setOptionType, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getExpirationStyle +/* const char* */ std::string +getExpirationStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getExpirationStyle`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getExpirationStyle, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setExpirationStyle +/* std::int32_t */ void +setExpirationStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setExpirationStyle`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setExpirationStyle, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getSettlementStyle +/* const char* */ std::string +getSettlementStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getSettlementStyle`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getSettlementStyle, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setSettlementStyle +/* std::int32_t */ void +setSettlementStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setSettlementStyle`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setSettlementStyle, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getPriceIncrements +/* const char* */ std::string +getPriceIncrements(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getPriceIncrements`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getPriceIncrements, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setPriceIncrements +/* std::int32_t */ void +setPriceIncrements(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setPriceIncrements`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setPriceIncrements, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getTradingHours +/* const char* */ std::string +getTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getTradingHours`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getTradingHours, static_cast(ip.get()))); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setTradingHours +/* std::int32_t */ void setTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setTradingHours`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setTradingHours, + static_cast(ip.get()), value.c_str()); +} + +// dxfg_InstrumentProfile_getField +/* const char* */ std::string getField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getField`. The ip handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getField, static_cast(ip.get()), name.c_str())); + auto result = dxfcpp::toString(string.get()); + + return result; +} + +// dxfg_InstrumentProfile_setField +/* std::int32_t */ void setField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name, const StringLikeWrapper &value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setField`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setField, + static_cast(ip.get()), name.c_str(), value.c_str()); +} + +// dxfg_InstrumentProfile_getNumericField +double getNumericField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getNumericField`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusInf(dxfg_InstrumentProfile_getNumericField, + static_cast(ip.get()), name.c_str()); +} + +// dxfg_InstrumentProfile_setNumericField +/* std::int32_t */ void setNumericField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name, double value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setNumericField`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setNumericField, + static_cast(ip.get()), name.c_str(), value); +} + +// dxfg_InstrumentProfile_getDateField +std::int32_t getDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_getDateField`. The ip handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_getDateField, + static_cast(ip.get()), name.c_str()); +} + +// dxfg_InstrumentProfile_setDateField +/* std::int32_t */ void setDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, + const StringLikeWrapper &name, std::int32_t value) { + if (!ip) { + throw std::invalid_argument( + "Unable to execute function `dxfg_InstrumentProfile_setNumericField`. The ip handle is invalid"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfile_setNumericField, + static_cast(ip.get()), name.c_str(), value); +} + +// dxfg_InstrumentProfile_getNonEmptyCustomFieldNames +/* dxfg_string_list* */ std::vector +getNonEmptyCustomFieldNames(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { + if (!ip) { + throw std::invalid_argument("Unable to execute function `dxfg_InstrumentProfile_getNonEmptyCustomFieldNames`. " + "The ip handle is invalid"); + } + + std::vector result; + auto graalStringList = internal::IsolatedStringList::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfile_getNonEmptyCustomFieldNames, static_cast(ip.get()))); + + const auto size = static_cast(graalStringList.get())->size; + const auto elements = static_cast(graalStringList.get())->elements; + + result.reserve(size); + + for (auto i = 0; i < size; i++) { + result.emplace_back(dxfcpp::toString(elements[i])); + } + + result.shrink_to_fit(); + + return result; } } // namespace isolated::ipf::IsolatedInstrumentProfile From 4a095c7c96957af547ca9b908348f2a9d1222949 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 18 Jul 2024 19:39:30 +0300 Subject: [PATCH 050/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile InstrumentProfile --- .../ipf/InstrumentProfile.hpp | 899 +++--------------- .../ipf/live/InstrumentProfileCollector.hpp | 10 - .../isolated/Isolated.hpp | 8 - .../ipf/IsolatedInstrumentProfile.hpp | 7 + src/internal/Isolate.cpp | 26 - src/ipf/InstrumentProfile.cpp | 234 +---- src/ipf/InstrumentProfileReader.cpp | 21 +- src/ipf/live/InstrumentProfileCollector.cpp | 25 +- src/ipf/live/IterableInstrumentProfile.cpp | 5 +- .../ipf/IsolatedInstrumentProfile.cpp | 27 + 10 files changed, 236 insertions(+), 1026 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp index 1392a80c9..24a1f7e82 100644 --- a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp @@ -19,79 +19,22 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE +class IterableInstrumentProfile; +struct NonOwningInstrumentProfileIterator; +class InstrumentProfileReader; +class InstrumentProfileCollector; + /** * Represents basic profile information about market instrument. * Please see Instrument * Profile Format documentation for complete description. */ -class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { - struct Data { - std::string type{}; - std::string symbol{}; - std::string description{}; - std::string localSymbol{}; - std::string localDescription{}; - std::string country{}; - std::string opol{}; - std::string exchangeData{}; - std::string exchanges{}; - std::string currency{}; - std::string baseCurrency{}; - std::string cfi{}; - std::string isin{}; - std::string sedol{}; - std::string cusip{}; - std::int32_t icb{}; - std::int32_t sic{}; - double multiplier = math::NaN; - std::string product{}; - std::string underlying{}; - double spc = math::NaN; - std::string additionalUnderlyings{}; - std::string mmy{}; - int32_t expiration{}; - int32_t lastTrade{}; - double strike = math::NaN; - std::string optionType{}; - std::string expirationStyle{}; - std::string settlementStyle{}; - std::string priceIncrements{}; - std::string tradingHours{}; - std::vector rawCustomFields{}; - std::unordered_map customFields{}; - }; - - Data data_{}; - - void fillData(void *graalNative) noexcept; - void fillGraalData(void *graalNative) const; - static void freeGraalData(void *graalNative) noexcept; - - /** - * Returns custom field value with a specified name. - * - * @param name The name of custom field. - * @return The reference to custom field value with a specified name or std::nullopt - */ - std::optional> getCustomField(const std::string &name) const noexcept { - if (!data_.customFields.contains(name)) { - return std::nullopt; - } - - return std::cref(data_.customFields.at(name)); - } +struct DXFCPP_EXPORT InstrumentProfile final : public RequireMakeShared { + friend IterableInstrumentProfile; + friend NonOwningInstrumentProfileIterator; + friend InstrumentProfileReader; + friend InstrumentProfileCollector; - /** - * Changes custom field value with a specified name. - * - * @param name The name of custom field. - * @param value The custom field value. - */ - void setCustomField(const std::string &name, const std::string &value) { - data_.customFields[name] = value; - } - - public: /// The alias to a type of shared pointer to the InstrumentProfile object using Ptr = std::shared_ptr; @@ -99,44 +42,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { using Unique = std::unique_ptr; /** - * Creates an object of the current type and fills it with data from the the dxFeed Graal SDK structure. - * - * @param graalNative The pointer to the dxFeed Graal SDK structure. - * @return The object of current type. - * @throws std::invalid_argument - */ - static Ptr fromGraal(void *graalNative); - - /** - * Creates a vector of objects of the current type and fills it with data from the the dxFeed Graal SDK list of - * structures. - * - * @param graalList The pointer to the dxFeed Graal SDK list of structures. - * @return The vector of objects of current type - * @throws std::invalid_argument + * Creates an instrument profile with default values. */ - static std::vector fromGraalList(void *graalList); + static Ptr create(); /** - * Allocates memory for the dxFeed Graal SDK structure. - * Fills the dxFeed Graal SDK structure's fields by the data of the current entity. - * Returns the pointer to the filled structure. - * - * @return The pointer to the filled dxFeed Graal SDK structure - */ - void *toGraal() const; - - /** - * Releases the memory occupied by the dxFeed Graal SDK structure. - * - * @param graalNative The pointer to the dxFeed Graal SDK structure. + * Creates an instrument profile as a copy of the specified instrument profile. + * @param ip an instrument profile to copy. */ - static void freeGraal(void *graalNative); - - /** - * Creates new instrument profile with default values. - */ - InstrumentProfile() noexcept = default; + static Ptr create(Ptr ip); /** * Returns type of instrument. @@ -146,9 +60,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return type of instrument. */ - const std::string &getType() const & noexcept { - return data_.type; - } + std::string getType() const; /** * Changes type of instrument. @@ -158,21 +70,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param type The type of instrument. */ - void setType(const std::string &type) noexcept { - data_.type = type; - } - - /** - * Changes type of instrument and returns the current instrument profile. - * - * @param type The type of instrument. - * @return The current instrument profile. - */ - InstrumentProfile &withType(const std::string &type) noexcept { - InstrumentProfile::setType(type); - - return *this; - } + void setType(const StringLikeWrapper &type) const; /** * Returns identifier of instrument, preferable an international one in Latin alphabet. @@ -181,20 +79,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The identifier of instrument. */ - const std::string &getSymbol() const & noexcept { - return data_.symbol; - } - - /** - * Changes identifier of instrument, preferable an international one in Latin alphabet. - * It is a mandatory field. It may not be empty. - * Example: "GOOG", "/YGM9", ".ZYEAD". - * - * @param symbol The identifier of instrument. - */ - void setSymbol(const std::string &symbol) noexcept { - data_.symbol = symbol; - } + std::string getSymbol() const; /** * Changes identifier of instrument, preferable an international one in Latin alphabet. @@ -202,13 +87,8 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * Example: "GOOG", "/YGM9", ".ZYEAD". * * @param symbol The identifier of instrument. - * @return The current instrument profile. */ - InstrumentProfile &withSymbol(const std::string &symbol) noexcept { - InstrumentProfile::setSymbol(symbol); - - return *this; - } + void setSymbol(const StringLikeWrapper &symbol) const; /** * Returns the description of instrument, preferable an international one in Latin alphabet. @@ -216,32 +96,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The description of instrument. */ - const std::string &getDescription() const & noexcept { - return data_.description; - } - - /** - * Changes description of instrument, preferable an international one in Latin alphabet. - * Example: "Google Inc.", "Mini Gold Futures,Jun-2009,ETH". - * - * @param description The description of instrument. - */ - void setDescription(const std::string &description) noexcept { - data_.description = description; - } + std::string getDescription() const; /** * Changes description of instrument, preferable an international one in Latin alphabet. * Example: "Google Inc.", "Mini Gold Futures,Jun-2009,ETH". * * @param description The description of instrument. - * @return The current instrument profile. */ - InstrumentProfile &withDescription(const std::string &description) noexcept { - InstrumentProfile::setDescription(description); - - return *this; - } + void setDescription(const StringLikeWrapper &description) const; /** * Returns identifier of instrument in national language. @@ -249,32 +112,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The identifier of instrument in national language. */ - const std::string &getLocalSymbol() const & noexcept { - return data_.localSymbol; - } - - /** - * Changes identifier of instrument in national language. - * It shall be empty if same as @ref InstrumentProfile::getSymbol() "symbol". - * - * @param localSymbol The identifier of instrument in national language. - */ - void setLocalSymbol(const std::string &localSymbol) noexcept { - data_.localSymbol = localSymbol; - } + std::string getLocalSymbol() const; /** * Changes identifier of instrument in national language. * It shall be empty if same as @ref InstrumentProfile::getSymbol() "symbol". * * @param localSymbol The identifier of instrument in national language. - * @return The current instrument profile. */ - InstrumentProfile &withLocalSymbol(const std::string &localSymbol) noexcept { - InstrumentProfile::setLocalSymbol(localSymbol); - - return *this; - } + void setLocalSymbol(const StringLikeWrapper &localSymbol) const; /** * Returns description of instrument in national language. @@ -282,9 +128,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The description of instrument in national language. */ - const std::string &getLocalDescription() const & noexcept { - return data_.localDescription; - } + std::string getLocalDescription() const; /** * Changes description of instrument in national language. @@ -292,22 +136,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param localDescription The description of instrument in national language. */ - void setLocalDescription(const std::string &localDescription) noexcept { - data_.localDescription = localDescription; - } - - /** - * Changes description of instrument in national language. - * It shall be empty if same as @ref InstrumentProfile::getDescription() "description". - * - * @param localDescription The description of instrument in national language. - * @return The current instrument profile. - */ - InstrumentProfile &withLocalDescription(const std::string &localDescription) noexcept { - InstrumentProfile::setLocalDescription(localDescription); - - return *this; - } + void setLocalDescription(const StringLikeWrapper &localDescription) const; /** * Returns country of origin (incorporation) of corresponding company or parent entity. @@ -317,9 +146,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The country of origin (incorporation) of corresponding company or parent entity. */ - const std::string &getCountry() const & noexcept { - return data_.country; - } + std::string getCountry() const; /** * Changes country of origin (incorporation) of corresponding company or parent entity. @@ -329,24 +156,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param country The country of origin (incorporation) of corresponding company or parent entity. */ - void setCountry(const std::string &country) noexcept { - data_.country = country; - } - - /** - * Changes country of origin (incorporation) of corresponding company or parent entity. - * It shall use two-letter country code from ISO 3166-1 standard. - * See ISO 3166-1 on Wikipedia. - * Example: "US", "RU". - * - * @param country The country of origin (incorporation) of corresponding company or parent entity. - * @return The current instrument profile. - */ - InstrumentProfile &withCountry(const std::string &country) noexcept { - InstrumentProfile::setCountry(country); - - return *this; - } + void setCountry(const StringLikeWrapper &country) const; /** * Returns official Place Of Listing, the organization that have listed this instrument. @@ -358,23 +168,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The official Place Of Listing, the organization that have listed this instrument. */ - const std::string &getOPOL() const & noexcept { - return data_.opol; - } - - /** - * Changes official Place Of Listing, the organization that have listed this instrument. - * Instruments with multiple listings shall use separate profiles for each listing. - * It shall use Market Identifier Code (MIC) from ISO 10383 standard. - * See ISO 10383 on Wikipedia - * or MIC homepage. - * Example: "XNAS", "RTSX" - * - * @param opol The official Place Of Listing, the organization that have listed this instrument. - */ - void setOPOL(const std::string &opol) noexcept { - data_.opol = opol; - } + std::string getOPOL() const; /** * Changes official Place Of Listing, the organization that have listed this instrument. @@ -385,13 +179,8 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * Example: "XNAS", "RTSX" * * @param opol The official Place Of Listing, the organization that have listed this instrument. - * @return The current instrument profile. */ - InstrumentProfile &withOPOL(const std::string &opol) noexcept { - InstrumentProfile::setOPOL(opol); - - return *this; - } + void setOPOL(const StringLikeWrapper &opol) const; /** * Returns exchange-specific data required to properly identify instrument when communicating with exchange. @@ -399,9 +188,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The exchange-specific data required to properly identify instrument when communicating with exchange. */ - const std::string &getExchangeData() const & noexcept { - return data_.exchangeData; - } + std::string getExchangeData() const; /** * Changes exchange-specific data required to properly identify instrument when communicating with exchange. @@ -410,23 +197,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * @param exchangeData The exchange-specific data required to properly identify instrument when communicating with * exchange. */ - void setExchangeData(const std::string &exchangeData) noexcept { - data_.exchangeData = exchangeData; - } - - /** - * Changes exchange-specific data required to properly identify instrument when communicating with exchange. - * It uses exchange-specific format. - * - * @param exchangeData The exchange-specific data required to properly identify instrument when communicating with - * exchange. - * @return The current instrument profile. - */ - InstrumentProfile &withExchangeData(const std::string &exchangeData) noexcept { - InstrumentProfile::setExchangeData(exchangeData); - - return *this; - } + void setExchangeData(const StringLikeWrapper &exchangeData) const; /** * Returns list of exchanges where instrument is quoted or traded. @@ -441,9 +212,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The list of exchanges where instrument is quoted or traded. */ - const std::string &getExchanges() const & noexcept { - return data_.exchanges; - } + std::string getExchanges() const; /** * Changes list of exchanges where instrument is quoted or traded. @@ -458,29 +227,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param exchanges The list of exchanges where instrument is quoted or traded. */ - void setExchanges(const std::string &exchanges) noexcept { - data_.exchanges = exchanges; - } - - /** - * Changes list of exchanges where instrument is quoted or traded. - * It shall use the following format: - * ``` - * ::= | - * ::= | - * - * the list shall be sorted by MIC. - * ``` - * Example: "ARCX;CBSX ;XNAS;XNYS". - * - * @param exchanges The list of exchanges where instrument is quoted or traded. - * @return The current instrument profile. - */ - InstrumentProfile &withExchanges(const std::string &exchanges) noexcept { - InstrumentProfile::setExchanges(exchanges); - - return *this; - } + void setExchanges(const StringLikeWrapper &exchanges) const; /** * Returns currency of quotation, pricing and trading. @@ -490,9 +237,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return Currency of quotation, pricing and trading. */ - const std::string &getCurrency() const & noexcept { - return data_.currency; - } + std::string getCurrency() const; /** * Changes currency of quotation, pricing and trading. @@ -502,24 +247,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param currency Currency of quotation, pricing and trading. */ - void setCurrency(const std::string ¤cy) noexcept { - data_.currency = currency; - } - - /** - * Changes currency of quotation, pricing and trading. - * It shall use three-letter currency code from ISO 4217 standard. - * See ISO 4217 on Wikipedia. - * Example: "USD", "RUB". - * - * @param currency Currency of quotation, pricing and trading. - * @return The current instrument profile. - */ - InstrumentProfile &withCurrency(const std::string ¤cy) noexcept { - InstrumentProfile::setCurrency(currency); - - return *this; - } + void setCurrency(const StringLikeWrapper ¤cy) const; /** * Returns base currency of currency pair (FOREX instruments). @@ -527,32 +255,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The base currency of currency pair (FOREX instruments). */ - const std::string &getBaseCurrency() const & noexcept { - return data_.baseCurrency; - } - - /** - * Changes base currency of currency pair (FOREX instruments). - * It shall use three-letter currency code similarly to @ref InstrumentProfile::getCurrency() "currency". - * - * @param baseCurrency The base currency of currency pair (FOREX instruments). - */ - void setBaseCurrency(const std::string &baseCurrency) noexcept { - data_.baseCurrency = baseCurrency; - } + std::string getBaseCurrency() const; /** * Changes base currency of currency pair (FOREX instruments). * It shall use three-letter currency code similarly to @ref InstrumentProfile::getCurrency() "currency". * * @param baseCurrency The base currency of currency pair (FOREX instruments). - * @return The current instrument profile. */ - InstrumentProfile &withBaseCurrency(const std::string &baseCurrency) noexcept { - InstrumentProfile::setBaseCurrency(baseCurrency); - - return *this; - } + void setBaseCurrency(const StringLikeWrapper &baseCurrency) const; /** * Returns Classification of Financial Instruments code. @@ -565,9 +276,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return CFI code. */ - const std::string &getCFI() const & noexcept { - return data_.cfi; - } + std::string getCFI() const; /** * Changes Classification of Financial Instruments code. @@ -580,27 +289,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param cfi CFI code. */ - void setCFI(const std::string &cfi) noexcept { - data_.cfi = cfi; - } - - /** - * Changes Classification of Financial Instruments code. - * It is a mandatory field for OPTION instruments as it is the only way to distinguish Call/Put type, - * American/European exercise, Cash/Physical delivery. - * It shall use six-letter CFI code from ISO 10962 standard. - * It is allowed to use 'X' extensively and to omit trailing letters (assumed to be 'X'). - * See ISO 10962 on Wikipedia. - * Example: "ESNTPB", "ESXXXX", "ES" , "OPASPS". - * - * @param cfi CFI code. - * @return The current instrument profile. - */ - InstrumentProfile &withCFI(const std::string &cfi) noexcept { - InstrumentProfile::setCFI(cfi); - - return *this; - } + void setCFI(const StringLikeWrapper &cfi) const; /** * Returns International Securities Identifying Number. @@ -611,22 +300,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return International Securities Identifying Number. */ - const std::string &getISIN() const & noexcept { - return data_.isin; - } - - /** - * Changes International Securities Identifying Number. - * It shall use twelve-letter code from ISO 6166 standard. - * See ISO 6166 on Wikipedia - * or ISIN on Wikipedia. - * Example: "DE0007100000", "US38259P5089". - * - * @param isin International Securities Identifying Number. - */ - void setISIN(const std::string &isin) noexcept { - data_.isin = isin; - } + std::string getISIN() const; /** * Changes International Securities Identifying Number. @@ -636,13 +310,8 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * Example: "DE0007100000", "US38259P5089". * * @param isin International Securities Identifying Number. - * @return The current instrument profile. */ - InstrumentProfile &withISIN(const std::string &isin) noexcept { - InstrumentProfile::setISIN(isin); - - return *this; - } + void setISIN(const StringLikeWrapper &isin) const; /** * Returns Stock Exchange Daily Official List. @@ -653,22 +322,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return Stock Exchange Daily Official List. */ - const std::string &getSEDOL() const & noexcept { - return data_.sedol; - } - - /** - * Changes Stock Exchange Daily Official List. - * It shall use seven-letter code assigned by London Stock Exchange. - * See SEDOL on Wikipedia or - * SEDOL on LSE. - * Example: "2310967", "5766857". - * - * @param sedol Stock Exchange Daily Official List. - */ - void setSEDOL(const std::string &sedol) noexcept { - data_.sedol = sedol; - } + std::string getSEDOL() const; /** * Changes Stock Exchange Daily Official List. @@ -678,13 +332,8 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * Example: "2310967", "5766857". * * @param sedol Stock Exchange Daily Official List. - * @return The current instrument profile. */ - InstrumentProfile &withSEDOL(const std::string &sedol) noexcept { - InstrumentProfile::setSEDOL(sedol); - - return *this; - } + void setSEDOL(const StringLikeWrapper &sedol) const; /** * Returns Committee on Uniform Security Identification Procedures code. @@ -694,9 +343,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return CUSIP code. */ - const std::string &getCUSIP() const & noexcept { - return data_.cusip; - } + std::string getCUSIP() const; /** * Changes Committee on Uniform Security Identification Procedures code. @@ -706,24 +353,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param cusip CUSIP code. */ - void setCUSIP(const std::string &cusip) noexcept { - data_.cusip = cusip; - } - - /** - * Changes Committee on Uniform Security Identification Procedures code. - * It shall use nine-letter code assigned by CUSIP Services Bureau. - * See CUSIP on Wikipedia. - * Example: "38259P508". - * - * @param cusip CUSIP code - * @return The current instrument profile. - */ - InstrumentProfile &withCUSIP(const std::string &cusip) noexcept { - InstrumentProfile::setCUSIP(cusip); - - return *this; - } + void setCUSIP(const StringLikeWrapper &cusip) const; /** * Returns Industry Classification Benchmark. @@ -734,9 +364,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return Industry Classification Benchmark. */ - std::int32_t getICB() const noexcept { - return data_.icb; - } + std::int32_t getICB() const; /** * Changes Industry Classification Benchmark. @@ -747,25 +375,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param icb Industry Classification Benchmark. */ - void setICB(std::int32_t icb) noexcept { - data_.icb = icb; - } - - /** - * Changes Industry Classification Benchmark. - * It shall use four-digit number from ICB catalog. - * See ICB on Wikipedia - * or ICB homepage. - * Example: "9535". - * - * @param icb Industry Classification Benchmark. - * @return The current instrument profile. - */ - InstrumentProfile &withICB(std::int32_t icb) noexcept { - InstrumentProfile::setICB(icb); - - return *this; - } + void setICB(std::int32_t icb) const; /** * Returns Standard Industrial Classification. @@ -776,9 +386,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return Standard Industrial Classification. */ - std::int32_t getSIC() const noexcept { - return data_.sic; - } + std::int32_t getSIC() const; /** * Changes Standard Industrial Classification. @@ -789,25 +397,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param sic Standard Industrial Classification. */ - void setSIC(std::int32_t sic) noexcept { - data_.sic = sic; - } - - /** - * Changes Standard Industrial Classification. - * It shall use four-digit number from SIC catalog. - * See SIC on Wikipedia - * or SIC structure. - * Example: "7371". - * - * @param sic Standard Industrial Classification. - * @return The current instrument profile. - */ - InstrumentProfile &withSIC(std::int32_t sic) noexcept { - InstrumentProfile::setSIC(sic); - - return *this; - } + void setSIC(std::int32_t sic) const; /** * Returns market value multiplier. @@ -815,9 +405,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The market value multiplier. */ - double getMultiplier() const noexcept { - return data_.multiplier; - } + double getMultiplier() const; /** * Changes market value multiplier. @@ -825,22 +413,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param multiplier The market value multiplier. */ - void setMultiplier(double multiplier) noexcept { - data_.multiplier = multiplier; - } - - /** - * Changes market value multiplier. - * Example: 100, 33.2. - * - * @param multiplier The market value multiplier. - * @return The current instrument profile. - */ - InstrumentProfile &withMultiplier(double multiplier) noexcept { - InstrumentProfile::setMultiplier(multiplier); - - return *this; - } + void setMultiplier(double multiplier) const; /** * Returns product for futures and options on futures (underlying asset name). @@ -848,9 +421,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The product for futures and options on futures (underlying asset name). */ - const std::string &getProduct() const & noexcept { - return data_.product; - } + std::string getProduct() const; /** * Changes product for futures and options on futures (underlying asset name). @@ -858,22 +429,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param product The product for futures and options on futures (underlying asset name). */ - void setProduct(const std::string &product) noexcept { - data_.product = product; - } - - /** - * Changes product for futures and options on futures (underlying asset name). - * Example: "/YG". - * - * @param product The product for futures and options on futures (underlying asset name). - * @return The current instrument profile. - */ - InstrumentProfile &withProduct(const std::string &product) noexcept { - InstrumentProfile::setProduct(product); - - return *this; - } + void setProduct(const StringLikeWrapper &product) const; /** * Returns primary underlying symbol for options. @@ -881,32 +437,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The primary underlying symbol for options. */ - const std::string &getUnderlying() const & noexcept { - return data_.underlying; - } - - /** - * Changes primary underlying symbol for options. - * Example: "C", "/YGM9" - * - * @param underlying The primary underlying symbol for options. - */ - void setUnderlying(const std::string &underlying) noexcept { - data_.underlying = underlying; - } + std::string getUnderlying() const; /** * Changes primary underlying symbol for options. * Example: "C", "/YGM9" * * @param underlying The primary underlying symbol for options. - * @return The current instrument profile. */ - InstrumentProfile &withUnderlying(const std::string &underlying) noexcept { - InstrumentProfile::setUnderlying(underlying); - - return *this; - } + void setUnderlying(const StringLikeWrapper &underlying) const; /** * Returns shares per contract for options. @@ -914,9 +453,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return shares per contract for options. */ - double getSPC() const noexcept { - return data_.spc; - } + double getSPC() const; /** * Changes shares per contract for options. @@ -924,22 +461,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param spc The shares per contract for options. */ - void setSPC(double spc) noexcept { - data_.spc = spc; - } - - /** - * Changes shares per contract for options. - * Example: 1, 100. - * - * @param spc The shares per contract for options. - * @return The current instrument profile. - */ - InstrumentProfile &withSPC(double spc) noexcept { - InstrumentProfile::setSPC(spc); - - return *this; - } + void setSPC(double spc) const; /** * Returns additional underlyings for options, including additional cash. @@ -954,26 +476,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The additional underlyings for options, including additional cash. */ - const std::string &getAdditionalUnderlyings() const & noexcept { - return data_.additionalUnderlyings; - } - - /** - * Changes additional underlyings for options, including additional cash. - * It shall use following format: - * ``` - * ::= | - * ::= | - * ::= - * the list shall be sorted by . - * ``` - * Example: "SE 50", "FIS 53; US$ 45.46". - * - * @param additionalUnderlyings The additional underlyings for options, including additional cash. - */ - void setAdditionalUnderlyings(const std::string &additionalUnderlyings) noexcept { - data_.additionalUnderlyings = additionalUnderlyings; - } + std::string getAdditionalUnderlyings() const; /** * Changes additional underlyings for options, including additional cash. @@ -987,13 +490,8 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * Example: "SE 50", "FIS 53; US$ 45.46". * * @param additionalUnderlyings The additional underlyings for options, including additional cash. - * @return The current instrument profile. */ - InstrumentProfile &withAdditionalUnderlyings(const std::string &additionalUnderlyings) noexcept { - InstrumentProfile::setAdditionalUnderlyings(additionalUnderlyings); - - return *this; - } + void setAdditionalUnderlyings(const StringLikeWrapper &additionalUnderlyings) const; /** * Returns maturity month-year as provided for corresponding FIX tag (200). @@ -1006,24 +504,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The maturity month-year as provided for corresponding FIX tag (200). */ - const std::string &getMMY() const & noexcept { - return data_.mmy; - } - - /** - * Changes maturity month-year as provided for corresponding FIX tag (200). - * It can use several different formats depending on data source: - *

    - *
  • YYYYMM – if only year and month are specified - *
  • YYYYMMDD – if full date is specified - *
  • YYYYMMwN – if week number (within a month) is specified - *
- * - * @param mmy The maturity month-year as provided for corresponding FIX tag (200). - */ - void setMMY(const std::string &mmy) noexcept { - data_.mmy = mmy; - } + std::string getMMY() const; /** * Changes maturity month-year as provided for corresponding FIX tag (200). @@ -1035,13 +516,8 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * * @param mmy The maturity month-year as provided for corresponding FIX tag (200). - * @return The current instrument profile. */ - InstrumentProfile &withMMY(const std::string &mmy) noexcept { - InstrumentProfile::setMMY(mmy); - - return *this; - } + void setMMY(const StringLikeWrapper &mmy) const; /** * Returns day id of expiration. @@ -1049,32 +525,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The day id of expiration. */ - std::int32_t getExpiration() const noexcept { - return data_.expiration; - } - - /** - * Changes day id of expiration. - * Example: @ref day_util::#getDayIdByYearMonthDay() "dxfcpp::day_util::getDayIdByYearMonthDay"(20090117). - * - * @param expiration The day id of expiration. - */ - void setExpiration(std::int32_t expiration) noexcept { - data_.expiration = expiration; - } + std::int32_t getExpiration() const; /** * Changes day id of expiration. * Example: @ref day_util::#getDayIdByYearMonthDay() "dxfcpp::day_util::getDayIdByYearMonthDay"(20090117). * * @param expiration The day id of expiration. - * @return The current instrument profile. */ - InstrumentProfile &withExpiration(std::int32_t expiration) noexcept { - InstrumentProfile::setExpiration(expiration); - - return *this; - } + void setExpiration(std::int32_t expiration) const; /** * Returns day id of last trading day. @@ -1082,32 +541,15 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The day id of last trading day. */ - std::int32_t getLastTrade() const noexcept { - return data_.lastTrade; - } - - /** - * Changes day id of last trading day. - * Example: @ref day_util::#getDayIdByYearMonthDay() "dxfcpp::day_util::getDayIdByYearMonthDay"(20090116). - * - * @param lastTrade The day id of last trading day. - */ - void setLastTrade(std::int32_t lastTrade) noexcept { - data_.lastTrade = lastTrade; - } + std::int32_t getLastTrade() const; /** * Changes day id of last trading day. * Example: @ref day_util::#getDayIdByYearMonthDay() "dxfcpp::day_util::getDayIdByYearMonthDay"(20090116). * * @param lastTrade The day id of last trading day. - * @return The current instrument profile. */ - InstrumentProfile &withLastTrade(std::int32_t lastTrade) noexcept { - InstrumentProfile::setLastTrade(lastTrade); - - return *this; - } + void setLastTrade(std::int32_t lastTrade) const; /** * Returns strike price for options. @@ -1115,9 +557,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The strike price for options. */ - double getStrike() const noexcept { - return data_.strike; - } + double getStrike() const; /** * Changes strike price for options. @@ -1125,22 +565,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param strike The strike price for options. */ - void setStrike(double strike) noexcept { - data_.strike = strike; - } - - /** - * Changes strike price for options. - * Example: 80, 22.5. - * - * @param strike The strike price for options - * @return The current instrument profile. - */ - InstrumentProfile &withStrike(double strike) noexcept { - InstrumentProfile::setStrike(strike); - - return *this; - } + void setStrike(double strike) const; /** * Returns type of option. @@ -1157,9 +582,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The type of option. */ - const std::string &getOptionType() const & noexcept { - return data_.optionType; - } + std::string getOptionType() const; /** * Changes type of option. @@ -1176,91 +599,35 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param optionType The type of option. */ - void setOptionType(const std::string &optionType) noexcept { - data_.optionType = optionType; - } - - /** - * Changes type of option. - * It shall use one of following values: - *
    - *
  • STAN = Standard Options - *
  • LEAP = Long-term Equity AnticiPation Securities - *
  • SDO = Special Dated Options - *
  • BINY = Binary Options - *
  • FLEX = FLexible EXchange Options - *
  • VSO = Variable Start Options - *
  • RNGE = Range - *
- * - * @param optionType The type of option. - * @return The current instrument profile. - */ - InstrumentProfile &withOptionType(const std::string &optionType) noexcept { - InstrumentProfile::setOptionType(optionType); - - return *this; - } + void setOptionType(const StringLikeWrapper &optionType) const; /** * Returns expiration cycle style, such as "Weeklys", "Quarterlys". * * @return The expiration cycle style. */ - const std::string &getExpirationStyle() const & noexcept { - return data_.expirationStyle; - } + std::string getExpirationStyle() const; /** * Changes the expiration cycle style, such as "Weeklys", "Quarterlys". * * @param expirationStyle The expiration cycle style. */ - void setExpirationStyle(const std::string &expirationStyle) noexcept { - data_.expirationStyle = expirationStyle; - } - - /** - * Changes the expiration cycle style, such as "Weeklys", "Quarterlys". - * - * @param expirationStyle The expiration cycle style. - * @return The current instrument profile. - */ - InstrumentProfile &withExpirationStyle(const std::string &expirationStyle) noexcept { - InstrumentProfile::setExpirationStyle(expirationStyle); - - return *this; - } + void setExpirationStyle(const StringLikeWrapper &expirationStyle) const; /** * Returns settlement price determination style, such as "Open", "Close". * * @return The settlement price determination style. */ - const std::string &getSettlementStyle() const & noexcept { - return data_.settlementStyle; - } + std::string getSettlementStyle() const; /** * Changes settlement price determination style, such as "Open", "Close". * * @param settlementStyle The settlement price determination style. */ - void setSettlementStyle(const std::string &settlementStyle) noexcept { - data_.settlementStyle = settlementStyle; - } - - /** - * Changes settlement price determination style, such as "Open", "Close". - * - * @param settlementStyle The settlement price determination style. - * @return The current instrument profile. - */ - InstrumentProfile &withSettlementStyle(const std::string &settlementStyle) noexcept { - InstrumentProfile::setSettlementStyle(settlementStyle); - - return *this; - } + void setSettlementStyle(const StringLikeWrapper &settlementStyle) const; /** * Returns minimum allowed price increments with corresponding price ranges. @@ -1275,9 +642,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The minimum allowed price increments with corresponding price ranges. */ - const std::string &getPriceIncrements() const & noexcept { - return data_.priceIncrements; - } + std::string getPriceIncrements() const; /** * Changes minimum allowed price increments with corresponding price ranges. @@ -1292,29 +657,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param priceIncrements The minimum allowed price increments with corresponding price ranges. */ - void setPriceIncrements(const std::string &priceIncrements) noexcept { - data_.priceIncrements = priceIncrements; - } - - /** - * Changes minimum allowed price increments with corresponding price ranges. - * It shall use following format: - * ``` - * ::= | - * ::= | - * ::= - * the list shall be sorted by . - * ``` - * Example: "0.25", "0.01 3; 0.05". - * - * @param priceIncrements The minimum allowed price increments with corresponding price ranges. - * @return The current instrument profile. - */ - InstrumentProfile &withPriceIncrements(const std::string &priceIncrements) noexcept { - InstrumentProfile::setPriceIncrements(priceIncrements); - - return *this; - } + void setPriceIncrements(const StringLikeWrapper &priceIncrements) const; /** * Returns trading hours specification. @@ -1322,9 +665,7 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @return The trading hours specification. */ - const std::string &getTradingHours() const & noexcept { - return data_.tradingHours; - } + std::string getTradingHours() const; /** * Changes trading hours specification. @@ -1332,22 +673,88 @@ class DXFCPP_EXPORT InstrumentProfile final : public SharedEntity { * * @param tradingHours The trading hours specification. */ - void setTradingHours(const std::string &tradingHours) noexcept { - data_.tradingHours = tradingHours; - } + void setTradingHours(const StringLikeWrapper &tradingHours) const; /** - * Changes trading hours specification. - * See Schedule::getInstance(). + * Returns field value with a specified name. * - * @param tradingHours The trading hours specification. - * @return The current instrument profile. + * @param name name of field. + * @return field value. + */ + std::string getField(const StringLikeWrapper &name) const; + + /** + * Changes field value with a specified name. + * + * @param name name of field. + * @param value field value. + */ + void setField(const StringLikeWrapper &name, const StringLikeWrapper &value) const; + + /** + * Returns numeric field value with a specified name. + * + * @param name name of field. + * @return field value. */ - InstrumentProfile &withTradingHours(const std::string &tradingHours) noexcept { - InstrumentProfile::setTradingHours(tradingHours); + double getNumericField(const StringLikeWrapper &name); - return *this; - } + /** + * Changes numeric field value with a specified name. + * + * @param name name of field. + * @param value field value. + */ + void setNumericField(const StringLikeWrapper &name, double value); + + /** + * Returns day id value for a date field with a specified name. + * + * @param name name of field. + * @return day id value. + */ + std::int32_t getDateField(const StringLikeWrapper &name); + + /** + * Changes day id value for a date field with a specified name. + * + * @param name name of field. + * @param value day id value. + */ + void setDateField(const StringLikeWrapper &name, std::int32_t value); + + /** + * Returns names of non-empty custom fields + * + * @return names of non-empty custom fields + */ + std::vector getNonEmptyCustomFieldNames() const; + + ~InstrumentProfile() noexcept override; + + InstrumentProfile(const InstrumentProfile &) = delete; + InstrumentProfile(InstrumentProfile &&) noexcept = delete; + InstrumentProfile &operator=(const InstrumentProfile &) = delete; + InstrumentProfile &operator=(const InstrumentProfile &&) noexcept = delete; + + private: + JavaObjectHandle handle_; + + explicit InstrumentProfile(LockExternalConstructionTag, JavaObjectHandle &&handle); + + static Ptr create(JavaObjectHandle &&handle); + + struct List { + /** + * Creates a vector of objects of the current type and fills it with data from the the dxFeed Graal SDK list of + * structures. + * + * @param list The pointer to the dxFeed Graal SDK list of structures. + * @return The vector of objects of current type + * @throws std::invalid_argument + */ + static std::vector fromGraal(void *list); + }; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp b/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp index e9a1219c0..7ee6b07b5 100644 --- a/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp @@ -107,16 +107,6 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { */ void updateInstrumentProfile(std::shared_ptr ip) const; - /** - * Convenience method to update one instrument profile in this collector. This is a shortcut for: - *

-     *    @ref InstrumentProfileCollector::updateInstrumentProfiles() "updateInstrumentProfiles"({ip}, nullptr);
-     * 
- * - * @param ip The instrument profile. - */ - void updateInstrumentProfile(const InstrumentProfile &ip) const; - /** * Returns a concurrent view of the set of instrument profiles. * Note, that removal of instrument profile is represented by an InstrumentProfile instance with a diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 696ffaad2..34f65f834 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -62,14 +62,6 @@ struct IpfPropertyChangeListener { create(/* dxfg_ipf_connection_state_change_listener_func */ void *userFunc, void *userData) noexcept; }; -struct InstrumentProfile { - static bool release(/* dxfg_instrument_profile_t* */ void *ip) noexcept; -}; - -struct InstrumentProfileList { - static bool release(/* dxfg_instrument_profile_list * */ void *graalInstrumentProfileList) noexcept; -}; - struct InstrumentProfileIterator { static bool hasNext(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; static /* dxfg_instrument_profile_t* */ void *next(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp index 944fa0218..722edeb5b 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/IsolatedInstrumentProfile.hpp @@ -295,6 +295,13 @@ getNonEmptyCustomFieldNames(/* dxfg_instrument_profile_t* */ const JavaObjectHan } // namespace isolated::ipf::IsolatedInstrumentProfile +namespace isolated::ipf::IsolatedInstrumentProfileList { +void release(/* dxfg_instrument_profile_list * */ void *list); +void releaseWrapper(/* dxfg_instrument_profile_list * */ void *list); + +std::unique_ptr toUniqueWrapper(/* dxfg_instrument_profile_list * */ void *list); +} // namespace isolated::ipf::IsolatedInstrumentProfileList + DXFCPP_END_NAMESPACE DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 1a92f9851..944cad783 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -436,32 +436,6 @@ IpfPropertyChangeListener::create(/* dxfg_ipf_connection_state_change_listener_f nullptr, dxfcpp::bit_cast(userFunc), userData)); } -bool InstrumentProfile::release(/* dxfg_instrument_profile_t* */ void *ip) noexcept { - if (!ip) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&ip) { - return dxfg_InstrumentProfile_release(static_cast(threadHandle), ip) == 0; - }, - false, static_cast(ip)); -} - -bool InstrumentProfileList::release(/* dxfg_instrument_profile_list * */ void *graalInstrumentProfileList) noexcept { - if (!graalInstrumentProfileList) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&list) { - return dxfg_CList_InstrumentProfile_release(static_cast(threadHandle), list) == 0; - }, - false, static_cast(graalInstrumentProfileList)); -} - bool InstrumentProfileIterator::hasNext(/* dxfg_iterable_ip_t * */ void *iterable) noexcept { if (!iterable) { // TODO: Improve error handling diff --git a/src/ipf/InstrumentProfile.cpp b/src/ipf/InstrumentProfile.cpp index 5a77a13ef..4bbb404c2 100644 --- a/src/ipf/InstrumentProfile.cpp +++ b/src/ipf/InstrumentProfile.cpp @@ -18,199 +18,57 @@ DXFCPP_BEGIN_NAMESPACE -void InstrumentProfile::fillData(void *graalNative) noexcept { - if (graalNative == nullptr) { - return; - } +InstrumentProfile::Ptr InstrumentProfile::create() { + return createShared(isolated::ipf::IsolatedInstrumentProfile::create()); +} + +InstrumentProfile::Ptr InstrumentProfile::create(Ptr ip) { + return createShared(isolated::ipf::IsolatedInstrumentProfile::create(ip->handle_)); +} - auto graalInstrumentProfile = static_cast(graalNative); +std::string InstrumentProfile::getType() const { + return isolated::ipf::IsolatedInstrumentProfile::getType(handle_); +} - // data_ = { - // .type = dxfcpp::toString(graalInstrumentProfile->type), - // .symbol = dxfcpp::toString(graalInstrumentProfile->symbol), - // .description = dxfcpp::toString(graalInstrumentProfile->description), - // .localSymbol = dxfcpp::toString(graalInstrumentProfile->local_symbol), - // .localDescription = dxfcpp::toString(graalInstrumentProfile->local_description), - // .country = dxfcpp::toString(graalInstrumentProfile->country), - // .opol = dxfcpp::toString(graalInstrumentProfile->opol), - // .exchangeData = dxfcpp::toString(graalInstrumentProfile->exchange_data), - // .exchanges = dxfcpp::toString(graalInstrumentProfile->exchanges), - // .currency = dxfcpp::toString(graalInstrumentProfile->currency), - // .baseCurrency = dxfcpp::toString(graalInstrumentProfile->base_currency), - // .cfi = dxfcpp::toString(graalInstrumentProfile->cfi), - // .isin = dxfcpp::toString(graalInstrumentProfile->isin), - // .sedol = dxfcpp::toString(graalInstrumentProfile->sedol), - // .cusip = dxfcpp::toString(graalInstrumentProfile->cusip), - // .icb = graalInstrumentProfile->icb, - // .sic = graalInstrumentProfile->sic, - // .multiplier = graalInstrumentProfile->multiplier, - // .product = dxfcpp::toString(graalInstrumentProfile->product), - // .underlying = dxfcpp::toString(graalInstrumentProfile->underlying), - // .spc = graalInstrumentProfile->spc, - // .additionalUnderlyings = dxfcpp::toString(graalInstrumentProfile->additional_underlyings), - // .mmy = dxfcpp::toString(graalInstrumentProfile->mmy), - // .expiration = graalInstrumentProfile->expiration, - // .lastTrade = graalInstrumentProfile->last_trade, - // .strike = graalInstrumentProfile->strike, - // .optionType = dxfcpp::toString(graalInstrumentProfile->option_type), - // .expirationStyle = dxfcpp::toString(graalInstrumentProfile->expiration_style), - // .settlementStyle = dxfcpp::toString(graalInstrumentProfile->settlement_style), - // .priceIncrements = dxfcpp::toString(graalInstrumentProfile->price_increments), - // .tradingHours = dxfcpp::toString(graalInstrumentProfile->trading_hours), - // .rawCustomFields = - // [](dxfg_string_list *strings) { - // std::vector result{}; - // - // if (!strings || strings->size == 0) { - // return result; - // } - // - // result.resize(strings->size); - // - // for (std::int32_t i = 0; i < strings->size; i++) { - // result[i] = dxfcpp::toString(strings->elements[i]); - // } - // - // return result; - // }(graalInstrumentProfile->custom_fields), - // .customFields = - // [](dxfg_string_list *strings) { - // std::unordered_map result{}; - // - // if (!strings || strings->size < 2) { - // return result; - // } - // - // for (std::int32_t i = 0; i < strings->size - 1; i += 2) { - // auto key = dxfcpp::toString(strings->elements[i]); - // - // if (key.empty()) { - // continue; - // } - // - // result[key] = dxfcpp::toString(strings->elements[i + 1]); - // } - // - // return result; - // }(graalInstrumentProfile->custom_fields), - // }; +void InstrumentProfile::setType(const StringLikeWrapper &type) const { + isolated::ipf::IsolatedInstrumentProfile::setType(handle_, type); } -void InstrumentProfile::fillGraalData(void *graalNative) const { - if (graalNative == nullptr) { - return; - } +std::string InstrumentProfile::getSymbol() const { + return isolated::ipf::IsolatedInstrumentProfile::getSymbol(handle_); +} - auto graalInstrumentProfile = static_cast(graalNative); +void InstrumentProfile::setSymbol(const StringLikeWrapper &symbol) const { + isolated::ipf::IsolatedInstrumentProfile::setSymbol(handle_, symbol); +} - // graalInstrumentProfile->type = createCString(data_.type); - // graalInstrumentProfile->symbol = createCString(data_.symbol); - // graalInstrumentProfile->description = createCString(data_.description); - // graalInstrumentProfile->local_symbol = createCString(data_.localSymbol); - // graalInstrumentProfile->local_description = createCString(data_.localDescription); - // graalInstrumentProfile->country = createCString(data_.country); - // graalInstrumentProfile->opol = createCString(data_.opol); - // graalInstrumentProfile->exchange_data = createCString(data_.exchangeData); - // graalInstrumentProfile->exchanges = createCString(data_.exchanges); - // graalInstrumentProfile->currency = createCString(data_.currency); - // graalInstrumentProfile->base_currency = createCString(data_.baseCurrency); - // graalInstrumentProfile->cfi = createCString(data_.cfi); - // graalInstrumentProfile->isin = createCString(data_.isin); - // graalInstrumentProfile->sedol = createCString(data_.sedol); - // graalInstrumentProfile->cusip = createCString(data_.cusip); - // graalInstrumentProfile->icb = data_.icb; - // graalInstrumentProfile->sic = data_.sic; - // graalInstrumentProfile->multiplier = data_.multiplier; - // graalInstrumentProfile->product = createCString(data_.product); - // graalInstrumentProfile->underlying = createCString(data_.underlying); - // graalInstrumentProfile->spc = data_.spc; - // graalInstrumentProfile->additional_underlyings = createCString(data_.additionalUnderlyings); - // graalInstrumentProfile->mmy = createCString(data_.mmy); - // graalInstrumentProfile->expiration = data_.expiration; - // graalInstrumentProfile->last_trade = data_.lastTrade; - // graalInstrumentProfile->strike = data_.strike; - // graalInstrumentProfile->option_type = createCString(data_.optionType); - // graalInstrumentProfile->expiration_style = createCString(data_.expirationStyle); - // graalInstrumentProfile->settlement_style = createCString(data_.settlementStyle); - // graalInstrumentProfile->price_increments = createCString(data_.priceIncrements); - // graalInstrumentProfile->trading_hours = createCString(data_.tradingHours); - // - // if (data_.rawCustomFields.empty()) { - // graalInstrumentProfile->custom_fields = nullptr; - // } else { - // graalInstrumentProfile->custom_fields = new dxfg_string_list{}; - // graalInstrumentProfile->custom_fields->size = static_cast(data_.rawCustomFields.size()); - // graalInstrumentProfile->custom_fields->elements = new const char *[data_.rawCustomFields.size()] { - // nullptr - // }; - // - // for (std::int32_t i = 0; i < graalInstrumentProfile->custom_fields->size; i++) { - // // TODO: process null-strings. ? - // if (!data_.rawCustomFields[i].empty()) { - // graalInstrumentProfile->custom_fields->elements[i] = createCString(data_.rawCustomFields[i]); - // } - // } - // } +std::string InstrumentProfile::getDescription() const { + return isolated::ipf::IsolatedInstrumentProfile::getDescription(handle_); } -void InstrumentProfile::freeGraalData(void *graalNative) noexcept { - if (graalNative == nullptr) { - return; - } +void InstrumentProfile::setDescription(const StringLikeWrapper &description) const { + isolated::ipf::IsolatedInstrumentProfile::setDescription(handle_, description); +} - auto graalInstrumentProfile = static_cast(graalNative); - // delete[] graalInstrumentProfile->type; - // delete[] graalInstrumentProfile->symbol; - // delete[] graalInstrumentProfile->description; - // delete[] graalInstrumentProfile->local_symbol; - // delete[] graalInstrumentProfile->local_description; - // delete[] graalInstrumentProfile->country; - // delete[] graalInstrumentProfile->opol; - // delete[] graalInstrumentProfile->exchange_data; - // delete[] graalInstrumentProfile->exchanges; - // delete[] graalInstrumentProfile->currency; - // delete[] graalInstrumentProfile->base_currency; - // delete[] graalInstrumentProfile->cfi; - // delete[] graalInstrumentProfile->isin; - // delete[] graalInstrumentProfile->sedol; - // delete[] graalInstrumentProfile->cusip; - // delete[] graalInstrumentProfile->product; - // delete[] graalInstrumentProfile->underlying; - // delete[] graalInstrumentProfile->additional_underlyings; - // delete[] graalInstrumentProfile->mmy; - // delete[] graalInstrumentProfile->option_type; - // delete[] graalInstrumentProfile->expiration_style; - // delete[] graalInstrumentProfile->settlement_style; - // delete[] graalInstrumentProfile->price_increments; - // delete[] graalInstrumentProfile->trading_hours; - // - // if (graalInstrumentProfile->custom_fields) { - // if (graalInstrumentProfile->custom_fields->elements && graalInstrumentProfile->custom_fields->size > 0) { - // for (std::int32_t i = 0; i < graalInstrumentProfile->custom_fields->size; i++) { - // delete[] graalInstrumentProfile->custom_fields->elements[i]; - // } - // - // delete[] graalInstrumentProfile->custom_fields->elements; - // } - // - // delete graalInstrumentProfile->custom_fields; - // } +std::string InstrumentProfile::getLocalSymbol() const { + return isolated::ipf::IsolatedInstrumentProfile::getLocalSymbol(handle_); } -std::shared_ptr InstrumentProfile::fromGraal(void *graalNative) { - if (!graalNative) { - throw std::invalid_argument("Unable to create InstrumentProfile. The `graalNative` parameter is nullptr"); - } +void InstrumentProfile::setLocalSymbol(const StringLikeWrapper &localSymbol) const { + isolated::ipf::IsolatedInstrumentProfile::setLocalSymbol(handle_, localSymbol); +} - auto instrumentProfile = std::make_shared(); +InstrumentProfile::~InstrumentProfile() noexcept {} - instrumentProfile->fillData(graalNative); +InstrumentProfile::InstrumentProfile(LockExternalConstructionTag, JavaObjectHandle &&handle) : handle_(std::move(handle)) { +} - return instrumentProfile; +InstrumentProfile::Ptr InstrumentProfile::create(JavaObjectHandle &&handle) { + return createShared(std::move(handle)); } -std::vector> InstrumentProfile::fromGraalList(void *graalList) { +std::vector> InstrumentProfile::List::fromGraal(void *graalList) { using ListType = dxfg_instrument_profile_list; using SizeType = decltype(ListType::size); @@ -220,7 +78,7 @@ std::vector> InstrumentProfile::fromGraalList std::vector> result{}; - auto list = static_cast(graalList); + const auto list = static_cast(graalList); if (list->size <= 0 || list->elements == nullptr) { return result; @@ -228,31 +86,11 @@ std::vector> InstrumentProfile::fromGraalList for (SizeType elementIndex = 0; elementIndex < list->size; elementIndex++) { if (list->elements[elementIndex]) { - result.emplace_back(InstrumentProfile::fromGraal(static_cast(list->elements[elementIndex]))); + result.emplace_back(create(JavaObjectHandle(list->elements[elementIndex]))); } } return result; } -void *InstrumentProfile::toGraal() const { - auto *graalInstrumentProfile = new dxfg_instrument_profile_t{}; - - fillGraalData(static_cast(graalInstrumentProfile)); - - return static_cast(graalInstrumentProfile); -} - -void InstrumentProfile::freeGraal(void *graalNative) { - if (!graalNative) { - return; - } - - auto graalInstrumentProfile = static_cast(graalNative); - - freeGraalData(graalNative); - - delete graalInstrumentProfile; -} - DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/ipf/InstrumentProfileReader.cpp b/src/ipf/InstrumentProfileReader.cpp index 39c6a04db..12074c8d6 100644 --- a/src/ipf/InstrumentProfileReader.cpp +++ b/src/ipf/InstrumentProfileReader.cpp @@ -44,10 +44,9 @@ std::string InstrumentProfileReader::resolveSourceURL(const StringLikeWrapper &a std::vector> InstrumentProfileReader::readFromFile(const StringLikeWrapper &address) const { - auto *list = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address); - auto result = InstrumentProfile::fromGraalList(list); - - dxfcpp::isolated::ipf::InstrumentProfileList::release(list); + const auto list = isolated::ipf::IsolatedInstrumentProfileList::toUniqueWrapper( + isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address)); + auto result = InstrumentProfile::List::fromGraal(list.get()); return result; } @@ -55,20 +54,18 @@ InstrumentProfileReader::readFromFile(const StringLikeWrapper &address) const { std::vector> InstrumentProfileReader::readFromFile(const StringLikeWrapper &address, const StringLikeWrapper &user, const StringLikeWrapper &password) const { - auto *list = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address, user, password); - auto result = InstrumentProfile::fromGraalList(list); - - dxfcpp::isolated::ipf::InstrumentProfileList::release(list); + const auto list = isolated::ipf::IsolatedInstrumentProfileList::toUniqueWrapper( + isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address, user, password)); + auto result = InstrumentProfile::List::fromGraal(list.get()); return result; } std::vector> InstrumentProfileReader::readFromFile(const StringLikeWrapper &address, const AuthToken &token) const { - auto *list = dxfcpp::isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address, token.handle_); - auto result = InstrumentProfile::fromGraalList(list); - - dxfcpp::isolated::ipf::InstrumentProfileList::release(list); + const auto list = isolated::ipf::IsolatedInstrumentProfileList::toUniqueWrapper( + isolated::ipf::IsolatedInstrumentProfileReader::readFromFile(handle_, address, token.handle_)); + auto result = InstrumentProfile::List::fromGraal(list.get()); return result; } diff --git a/src/ipf/live/InstrumentProfileCollector.cpp b/src/ipf/live/InstrumentProfileCollector.cpp index 28601953c..55ba440e5 100644 --- a/src/ipf/live/InstrumentProfileCollector.cpp +++ b/src/ipf/live/InstrumentProfileCollector.cpp @@ -36,8 +36,7 @@ struct NonOwningInstrumentProfileIterator { } auto graalProfile = isolated::ipf::InstrumentProfileIterator::next(iterable); - auto result = InstrumentProfile::fromGraal(graalProfile); - isolated::ipf::InstrumentProfile::release(graalProfile); + auto result = InstrumentProfile::create(JavaObjectHandle(graalProfile)); return result; }; @@ -154,27 +153,7 @@ void InstrumentProfileCollector::updateInstrumentProfile(std::shared_ptrtoGraal(); - - if (graal) { - dxfcpp::isolated::ipf::InstrumentProfileCollector::updateInstrumentProfile(handle_.get(), graal); - - InstrumentProfile::freeGraal(graal); - } -} - -void InstrumentProfileCollector::updateInstrumentProfile(const InstrumentProfile &ip) const { - if (!handle_) { - return; - } - - auto graal = ip.toGraal(); - - if (graal) { - dxfcpp::isolated::ipf::InstrumentProfileCollector::updateInstrumentProfile(handle_.get(), graal); - - InstrumentProfile::freeGraal(graal); - } + isolated::ipf::InstrumentProfileCollector::updateInstrumentProfile(handle_.get(), ip->handle_.get()); } std::shared_ptr InstrumentProfileCollector::view() const noexcept { diff --git a/src/ipf/live/IterableInstrumentProfile.cpp b/src/ipf/live/IterableInstrumentProfile.cpp index f6f3a74ef..b24c2e91c 100644 --- a/src/ipf/live/IterableInstrumentProfile.cpp +++ b/src/ipf/live/IterableInstrumentProfile.cpp @@ -21,7 +21,7 @@ DXFCPP_BEGIN_NAMESPACE IterableInstrumentProfile::IterableInstrumentProfile(void *handle) noexcept : handle_(handle) { } -std::shared_ptr IterableInstrumentProfile::create(void* handle) noexcept { +std::shared_ptr IterableInstrumentProfile::create(void *handle) noexcept { return std::shared_ptr(new IterableInstrumentProfile(handle)); } @@ -39,8 +39,7 @@ std::shared_ptr IterableInstrumentProfile::create(voi } auto graalProfile = isolated::ipf::InstrumentProfileIterator::next(handle_.get()); - auto result = InstrumentProfile::fromGraal(graalProfile); - isolated::ipf::InstrumentProfile::release(graalProfile); + auto result = InstrumentProfile::create(JavaObjectHandle(graalProfile)); return result; }; diff --git a/src/isolated/ipf/IsolatedInstrumentProfile.cpp b/src/isolated/ipf/IsolatedInstrumentProfile.cpp index af8c83e05..c59859c09 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfile.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfile.cpp @@ -938,4 +938,31 @@ getNonEmptyCustomFieldNames(/* dxfg_instrument_profile_t* */ const JavaObjectHan } // namespace isolated::ipf::IsolatedInstrumentProfile +namespace isolated::ipf::IsolatedInstrumentProfileList { +void release(/* dxfg_instrument_profile_list * */ void *list) { + if (!list) { + throw std::invalid_argument( + "Unable to execute function `dxfg_CList_InstrumentProfile_wrapper_release`. The list is nullptr"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_CList_InstrumentProfile_release, + static_cast(list)); +} + +void releaseWrapper(/* dxfg_instrument_profile_list * */ void *list) { + if (!list) { + throw std::invalid_argument( + "Unable to execute function `dxfg_CList_InstrumentProfile_wrapper_release`. The list is nullptr"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_CList_InstrumentProfile_wrapper_release, + static_cast(list)); +} + +std::unique_ptr toUniqueWrapper(/* dxfg_instrument_profile_list * */ void *list) { + return {list, releaseWrapper}; +} + +} // namespace isolated::ipf::IsolatedInstrumentProfileList + DXFCPP_END_NAMESPACE \ No newline at end of file From 1e015f05afde6bb8266ee2482543f0926cc001a3 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sat, 20 Jul 2024 00:19:20 +0300 Subject: [PATCH 051/178] [MDAPI-80] [C++][IPF] Implement custom fields in InstrumentProfile Final --- ReleaseNotes.md | 12 +- .../dxfeed_graal_cpp_api/api/DXEndpoint.hpp | 2 +- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 2 +- .../api/DXFeedSubscription.hpp | 2 +- .../dxfeed_graal_cpp_api/api/DXPublisher.hpp | 2 +- .../osub/IndexedEventSubscriptionSymbol.hpp | 2 +- .../api/osub/TimeSeriesSubscriptionSymbol.hpp | 2 +- .../api/osub/WildcardSymbol.hpp | 2 +- .../entity/SharedEntity.hpp | 2 +- .../dxfeed_graal_cpp_api/event/EventFlag.hpp | 2 +- .../dxfeed_graal_cpp_api/event/EventType.hpp | 2 +- .../event/IndexedEventSource.hpp | 2 +- .../event/candle/Candle.hpp | 2 +- .../event/candle/CandleAlignment.hpp | 2 +- .../event/candle/CandleExchange.hpp | 2 +- .../event/candle/CandlePriceLevel.hpp | 2 +- .../event/market/AnalyticOrder.hpp | 2 +- .../event/market/OptionSale.hpp | 2 +- .../event/market/Order.hpp | 2 +- .../event/market/OrderBase.hpp | 2 +- .../event/market/OtcMarketsOrder.hpp | 2 +- .../event/market/Profile.hpp | 2 +- .../event/market/Quote.hpp | 2 +- .../event/market/SpreadOrder.hpp | 2 +- .../event/market/Summary.hpp | 2 +- .../event/market/TimeAndSale.hpp | 2 +- .../event/market/Trade.hpp | 2 +- .../event/market/TradeBase.hpp | 2 +- .../event/market/TradeETH.hpp | 2 +- .../event/misc/Message.hpp | 2 +- .../event/option/Greeks.hpp | 2 +- .../event/option/Series.hpp | 2 +- .../event/option/TheoPrice.hpp | 2 +- .../event/option/Underlying.hpp | 2 +- .../dxfeed_graal_cpp_api/internal/Isolate.hpp | 2 +- .../internal/JavaObjectHandle.hpp | 4 +- .../ipf/InstrumentProfile.hpp | 48 ++- include/dxfeed_graal_cpp_api/schedule/Day.hpp | 2 +- .../dxfeed_graal_cpp_api/schedule/Session.hpp | 2 +- .../schedule/SessionFilter.hpp | 2 +- .../symbols/StringSymbol.hpp | 2 +- .../symbols/SymbolWrapper.hpp | 2 +- src/api/DXEndpoint.cpp | 2 +- src/api/DXFeed.cpp | 2 +- src/api/DXFeedSubscription.cpp | 2 +- src/api/DXPublisher.cpp | 2 +- .../osub/IndexedEventSubscriptionSymbol.cpp | 2 +- src/api/osub/TimeSeriesSubscriptionSymbol.cpp | 2 +- src/event/candle/Candle.cpp | 2 +- src/event/market/AnalyticOrder.cpp | 2 +- src/event/market/OptionSale.cpp | 2 +- src/event/market/Order.cpp | 2 +- src/event/market/OrderBase.cpp | 2 +- src/event/market/OtcMarketsOrder.cpp | 2 +- src/event/market/Profile.cpp | 2 +- src/event/market/Quote.cpp | 2 +- src/event/market/SpreadOrder.cpp | 2 +- src/event/market/Summary.cpp | 2 +- src/event/market/TimeAndSale.cpp | 2 +- src/event/market/Trade.cpp | 2 +- src/event/market/TradeBase.cpp | 2 +- src/event/market/TradeETH.cpp | 2 +- src/event/misc/Message.cpp | 2 +- src/event/option/Greeks.cpp | 2 +- src/event/option/Series.cpp | 2 +- src/event/option/TheoPrice.cpp | 2 +- src/event/option/Underlying.cpp | 2 +- src/ipf/InstrumentProfile.cpp | 279 +++++++++++++++++- src/schedule/Day.cpp | 2 +- src/schedule/Schedule.cpp | 17 +- src/schedule/Session.cpp | 2 +- 71 files changed, 402 insertions(+), 90 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 145b045f3..e4f1e1536 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,4 +1,14 @@ - +* **\[MDAPI-80]\[C++]\[IPF]** Implement custom fields in InstrumentProfile + * The API was migrated to Graal SDK v1.1.22 + * Added methods: + * `InstrumentProfile::getField` + * `InstrumentProfile::setField` + * `InstrumentProfile::getNumericField` + * `InstrumentProfile::setNumericField` + * `InstrumentProfile::getDateField` + * `InstrumentProfile::setDateField` + * `InstrumentProfile::getNonEmptyCustomFieldNames` + * **\[BREAKING]**: All `toString` methods can now throw exceptions. * **\[MDAPI-26]\[C++]** Migrate to Graal SDK v1.1.21. * Added `Day::getSessions` method. * New order sources added: `CEDX` and `cedx`. diff --git a/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp b/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp index 00a430875..d294e4e75 100644 --- a/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp @@ -982,7 +982,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { std::shared_ptr build(); }; - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index 6e77b835d..27d069907 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -315,7 +315,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return Promise>>(getTimeSeriesPromiseImpl(E::TYPE, symbol, fromTime, toTime)); } - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index d3489b1b0..7440b7617 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -133,7 +133,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSubscription(const EventTypeEnum &eventType); - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp b/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp index 6a7ca294a..80c0fdab9 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp @@ -108,7 +108,7 @@ class DXFCPP_EXPORT IndexedEventSubscriptionSymbol { * * @return string representation of this indexed event subscription symbol. */ - virtual std::string toString() const noexcept; + virtual std::string toString() const; bool operator==(const IndexedEventSubscriptionSymbol &indexedEventSubscriptionSymbol) const noexcept; diff --git a/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp b/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp index dd99cb423..71286b21b 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp @@ -102,7 +102,7 @@ class DXFCPP_EXPORT TimeSeriesSubscriptionSymbol final : public IndexedEventSubs * * @return string representation of this time-series subscription symbol. */ - std::string toString() const noexcept override; + std::string toString() const override; bool operator==(const TimeSeriesSubscriptionSymbol &timeSeriesSubscriptionSymbol) const noexcept; diff --git a/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp b/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp index 2dc46089d..66da25235 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp @@ -90,7 +90,7 @@ struct DXFCPP_EXPORT WildcardSymbol final { * * @return string representation of this wildcard subscription symbol. */ - std::string toString() const noexcept { + std::string toString() const { if constexpr (Debugger::isDebug) { return "WildcardSymbol{" + symbol_ + "}"; } else { diff --git a/include/dxfeed_graal_cpp_api/entity/SharedEntity.hpp b/include/dxfeed_graal_cpp_api/entity/SharedEntity.hpp index 16ba6bcd2..7bd8da04e 100644 --- a/include/dxfeed_graal_cpp_api/entity/SharedEntity.hpp +++ b/include/dxfeed_graal_cpp_api/entity/SharedEntity.hpp @@ -66,7 +66,7 @@ struct DXFCPP_EXPORT SharedEntity : public Entity, std::enable_shared_from_this< * * @return a string representation */ - virtual std::string toString() const noexcept { + virtual std::string toString() const { return "SharedEntity{}"; } }; diff --git a/include/dxfeed_graal_cpp_api/event/EventFlag.hpp b/include/dxfeed_graal_cpp_api/event/EventFlag.hpp index fb05d0c8d..50032a604 100644 --- a/include/dxfeed_graal_cpp_api/event/EventFlag.hpp +++ b/include/dxfeed_graal_cpp_api/event/EventFlag.hpp @@ -415,7 +415,7 @@ class EventFlagsMask final { } /// - std::string toString() const noexcept { + std::string toString() const { bool addOrSign = false; std::ostringstream result{}; diff --git a/include/dxfeed_graal_cpp_api/event/EventType.hpp b/include/dxfeed_graal_cpp_api/event/EventType.hpp index fad4f32d2..e6e2a02ff 100644 --- a/include/dxfeed_graal_cpp_api/event/EventType.hpp +++ b/include/dxfeed_graal_cpp_api/event/EventType.hpp @@ -73,7 +73,7 @@ struct DXFCPP_EXPORT EventType : public SharedEntity { virtual void *toGraal() const = 0; /// - std::string toString() const noexcept override { + std::string toString() const override { return "EventType{}"; } diff --git a/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp b/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp index 875a40e8e..60a4a38c1 100644 --- a/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp +++ b/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp @@ -88,7 +88,7 @@ class DXFCPP_EXPORT IndexedEventSource { * * @return The string representation of the object. */ - std::string toString() const noexcept { + std::string toString() const { return name_; } diff --git a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp index 7fc0b642b..787022f9d 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp @@ -690,7 +690,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, return *this; } - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp index 6e30218ec..4640e8d82 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp @@ -87,7 +87,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * * @return string representation of this candle alignment. */ - std::string toString() const noexcept { + std::string toString() const { return string_; } diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleExchange.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleExchange.hpp index d59ed7560..c473f520b 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleExchange.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleExchange.hpp @@ -73,7 +73,7 @@ struct DXFCPP_EXPORT CandleExchange : public CandleSymbolAttribute { * * @return string representation of this exchange. */ - std::string toString() const noexcept { + std::string toString() const { return exchangeCode_ == '\0' ? "COMPOSITE" : std::string(1, exchangeCode_); } diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp index a41bdfdb9..5db0211e8 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp @@ -77,7 +77,7 @@ struct DXFCPP_EXPORT CandlePriceLevel : public CandleSymbolAttribute { * * @return string representation of this price level. */ - std::string toString() const noexcept { + std::string toString() const { if (math::equals(value_, static_cast(value_))) { return std::to_string(static_cast(value_)); } diff --git a/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp index e7b1ac59a..abdb534a1 100644 --- a/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp @@ -540,7 +540,7 @@ class DXFCPP_EXPORT AnalyticOrder final : public Order { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp b/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp index 61875ceb9..acb69bf3b 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp @@ -851,7 +851,7 @@ class DXFCPP_EXPORT OptionSale final : public MarketEvent, public IndexedEvent { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/Order.hpp b/include/dxfeed_graal_cpp_api/event/market/Order.hpp index 53450ee6b..d0ac6bb4f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Order.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Order.hpp @@ -534,7 +534,7 @@ class DXFCPP_EXPORT Order : public OrderBase { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp index ea605d379..42f217f39 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp @@ -669,7 +669,7 @@ class DXFCPP_EXPORT OrderBase : public MarketEvent, public IndexedEvent { * * @return string representation of this order event's fields. */ - std::string baseFieldsToString() const noexcept; + std::string baseFieldsToString() const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp index 4c13f2de9..506ede3de 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp @@ -721,7 +721,7 @@ class DXFCPP_EXPORT OtcMarketsOrder final : public Order { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/Profile.hpp b/include/dxfeed_graal_cpp_api/event/market/Profile.hpp index 6a3c5cc4f..91064111f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Profile.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Profile.hpp @@ -478,7 +478,7 @@ class DXFCPP_EXPORT Profile final : public MarketEvent, public LastingEvent { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/Quote.hpp b/include/dxfeed_graal_cpp_api/event/market/Quote.hpp index 9badcaa5d..68df6ad92 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Quote.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Quote.hpp @@ -547,7 +547,7 @@ class DXFCPP_EXPORT Quote final : public MarketEvent, public LastingEvent { * * @return A string representation. */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp index 31929dfbd..c41c13f84 100644 --- a/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp @@ -524,7 +524,7 @@ class DXFCPP_EXPORT SpreadOrder : public OrderBase { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/Summary.hpp b/include/dxfeed_graal_cpp_api/event/market/Summary.hpp index 52246c22b..6e0607da4 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Summary.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Summary.hpp @@ -318,7 +318,7 @@ class DXFCPP_EXPORT Summary final : public MarketEvent, public LastingEvent { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp b/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp index fda727bce..6e8553e1f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp @@ -653,7 +653,7 @@ class DXFCPP_EXPORT TimeAndSale final : public MarketEvent, public TimeSeriesEve * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/Trade.hpp b/include/dxfeed_graal_cpp_api/event/market/Trade.hpp index 74f04b153..57e70d85f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Trade.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Trade.hpp @@ -128,7 +128,7 @@ class DXFCPP_EXPORT Trade final : public TradeBase { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp b/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp index b1a84884f..14494ca23 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp @@ -394,7 +394,7 @@ class DXFCPP_EXPORT TradeBase : public MarketEvent, public LastingEvent { * * @return string representation of this trade event's fields. */ - std::string baseFieldsToString() const noexcept; + std::string baseFieldsToString() const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp b/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp index 9ffb7fd96..2fa8122e4 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp @@ -153,7 +153,7 @@ class DXFCPP_EXPORT TradeETH final : public TradeBase { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/misc/Message.hpp b/include/dxfeed_graal_cpp_api/event/misc/Message.hpp index 51c87dd74..a1534bb17 100644 --- a/include/dxfeed_graal_cpp_api/event/misc/Message.hpp +++ b/include/dxfeed_graal_cpp_api/event/misc/Message.hpp @@ -208,7 +208,7 @@ class DXFCPP_EXPORT Message : public EventTypeWithSymbol { return *this; } - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp b/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp index 52dab6b95..1214828fd 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp @@ -361,7 +361,7 @@ class DXFCPP_EXPORT Greeks final : public MarketEvent, public TimeSeriesEvent, p * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/option/Series.hpp b/include/dxfeed_graal_cpp_api/event/option/Series.hpp index 6c88e11fa..0f168e9e5 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Series.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Series.hpp @@ -517,7 +517,7 @@ class DXFCPP_EXPORT Series final : public MarketEvent, public IndexedEvent { * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp b/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp index 1f36fb78e..e9ef569dd 100644 --- a/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp @@ -352,7 +352,7 @@ class DXFCPP_EXPORT TheoPrice final : public MarketEvent, public TimeSeriesEvent * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp b/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp index 162b18902..dc483e3cb 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp @@ -363,7 +363,7 @@ class DXFCPP_EXPORT Underlying final : public MarketEvent, public TimeSeriesEven * * @return a string representation */ - std::string toString() const noexcept override; + std::string toString() const override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp index dce68b0f9..575e686a5 100644 --- a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp @@ -262,7 +262,7 @@ class Isolate final { } } - std::string toString() const noexcept { + std::string toString() const { return std::string("Isolate{") + dxfcpp::toString(handle_) + ", main = " + mainIsolateThread_.toString() + ", current = " + currentIsolateThread_.toString() + "}"; } diff --git a/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp b/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp index 7dd5b613f..b38c20934 100644 --- a/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp +++ b/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp @@ -36,7 +36,7 @@ template struct JavaObjectHandle { JavaObjectHandle &operator=(JavaObjectHandle &&) noexcept = default; virtual ~JavaObjectHandle() noexcept = default; - [[nodiscard]] std::string toString() const noexcept { + [[nodiscard]] std::string toString() const { if (impl_) return dxfcpp::toString(impl_.get()); else @@ -77,7 +77,7 @@ template struct JavaObjectHandleList { JavaObjectHandleList &operator=(JavaObjectHandleList &&) noexcept = default; virtual ~JavaObjectHandleList() noexcept = default; - [[nodiscard]] std::string toString() const noexcept { + [[nodiscard]] std::string toString() const { if (impl_) return dxfcpp::toString(impl_.get()); else diff --git a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp index 24a1f7e82..b929e38fb 100644 --- a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp @@ -23,6 +23,7 @@ class IterableInstrumentProfile; struct NonOwningInstrumentProfileIterator; class InstrumentProfileReader; class InstrumentProfileCollector; +struct Schedule; /** * Represents basic profile information about market instrument. @@ -34,6 +35,7 @@ struct DXFCPP_EXPORT InstrumentProfile final : public RequireMakeShared; @@ -697,7 +699,7 @@ struct DXFCPP_EXPORT InstrumentProfile final : public RequireMakeShared getNonEmptyCustomFieldNames() const; + std::string toString() const override; + + friend std::ostream &operator<<(std::ostream &os, const InstrumentProfile &ip) { + return os << ip.toString(); + } + + friend std::ostream &operator<<(std::ostream &os, const InstrumentProfile::Ptr &ip) { + return os << ip->toString(); + } + + std::size_t hashCode() const; + + bool operator==(const InstrumentProfile &other) const; + + friend bool operator==(const InstrumentProfile::Ptr &ip1, const InstrumentProfile::Ptr &ip2) { + if (ip1.get() == ip2.get()) { + return true; + } + + return *ip1.get() == *ip2.get(); + } + ~InstrumentProfile() noexcept override; InstrumentProfile(const InstrumentProfile &) = delete; @@ -737,11 +761,11 @@ struct DXFCPP_EXPORT InstrumentProfile final : public RequireMakeShared &&handle); + private: JavaObjectHandle handle_; - explicit InstrumentProfile(LockExternalConstructionTag, JavaObjectHandle &&handle); - static Ptr create(JavaObjectHandle &&handle); struct List { @@ -759,4 +783,16 @@ struct DXFCPP_EXPORT InstrumentProfile final : public RequireMakeShared struct std::hash { + std::size_t operator()(const dxfcpp::InstrumentProfile &t) const noexcept { + return t.hashCode(); + } +}; + +template <> struct std::hash { + std::size_t operator()(const dxfcpp::InstrumentProfile::Ptr &t) const noexcept { + return t->hashCode(); + } +}; + DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/schedule/Day.hpp b/include/dxfeed_graal_cpp_api/schedule/Day.hpp index 8db375629..01c57a21b 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Day.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Day.hpp @@ -286,7 +286,7 @@ struct DXFCPP_EXPORT Day { * * @return A string representation */ - std::string toString() const noexcept; + std::string toString() const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/schedule/Session.hpp b/include/dxfeed_graal_cpp_api/schedule/Session.hpp index 6497def5a..978961398 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Session.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Session.hpp @@ -186,7 +186,7 @@ struct DXFCPP_EXPORT Session { * * @return a string representation */ - std::string toString() const noexcept; + std::string toString() const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp index 41a329127..51d899be6 100644 --- a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp @@ -108,7 +108,7 @@ struct DXFCPP_EXPORT SessionFilter { return type_ == sessionFilter.type_ && trading_ == sessionFilter.trading_; } - std::string toString() const noexcept { + std::string toString() const { return std::string("SessionFilter(") + ((!type_) ? "null" : type_.value().toString()) + ", " + ((!trading_) ? "null" : dxfcpp::toString(trading_.value())) + ")"; } diff --git a/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp b/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp index 39f2256fe..5d3a54d88 100644 --- a/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp @@ -96,7 +96,7 @@ struct DXFCPP_EXPORT StringSymbol final { * * @return a string representation */ - std::string toString() const noexcept { + std::string toString() const { if constexpr (Debugger::isDebug) { return "StringSymbol{" + data_ + "}"; } else { diff --git a/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp b/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp index b6bc4feb7..25e2c38c9 100644 --- a/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp +++ b/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp @@ -259,7 +259,7 @@ struct DXFCPP_EXPORT SymbolWrapper final { * * @return a string representation */ - std::string toString() const noexcept { + std::string toString() const { return "SymbolWrapper{" + std::visit( [](const auto &symbol) { diff --git a/src/api/DXEndpoint.cpp b/src/api/DXEndpoint.cpp index b494b7cf3..7e64b5e89 100644 --- a/src/api/DXEndpoint.cpp +++ b/src/api/DXEndpoint.cpp @@ -359,7 +359,7 @@ std::shared_ptr DXEndpoint::Builder::withName(const std::st return withProperty(NAME_PROPERTY, name); } -std::string DXEndpoint::toString() const noexcept { +std::string DXEndpoint::toString() const { return fmt::format("DXEndpoint{{{}}}", handle_.toString()); } diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 1925bd97e..d918ea822 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -126,7 +126,7 @@ void *DXFeed::getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const Sym return isolated::api::IsolatedDXFeed::getTimeSeriesPromise(handle_, eventType, symbol, fromTime, toTime); } -std::string DXFeed::toString() const noexcept { +std::string DXFeed::toString() const { return fmt::format("DXFeed{{{}}}", handle_.toString()); } diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 9df7955aa..25770bc85 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -83,7 +83,7 @@ DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const Ev handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); } -std::string DXFeedSubscription::toString() const noexcept { +std::string DXFeedSubscription::toString() const { return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); } diff --git a/src/api/DXPublisher.cpp b/src/api/DXPublisher.cpp index 77fbe4665..89354e502 100644 --- a/src/api/DXPublisher.cpp +++ b/src/api/DXPublisher.cpp @@ -51,7 +51,7 @@ std::shared_ptr DXPublisher::getSubscription(const Event return subscription_; } -std::string DXPublisher::toString() const noexcept { +std::string DXPublisher::toString() const { return fmt::format("DXPublisher{{{}}}", handle_.toString()); } diff --git a/src/api/osub/IndexedEventSubscriptionSymbol.cpp b/src/api/osub/IndexedEventSubscriptionSymbol.cpp index daa6b17b2..3ed16136a 100644 --- a/src/api/osub/IndexedEventSubscriptionSymbol.cpp +++ b/src/api/osub/IndexedEventSubscriptionSymbol.cpp @@ -57,7 +57,7 @@ IndexedEventSubscriptionSymbol IndexedEventSubscriptionSymbol::fromGraal(void *g return {SymbolWrapper::fromGraal(graalSymbol->symbol), IndexedEventSource::fromGraal(graalSymbol->source)}; } -std::string IndexedEventSubscriptionSymbol::toString() const noexcept { +std::string IndexedEventSubscriptionSymbol::toString() const { if constexpr (Debugger::isDebug) { return "IndexedEventSubscriptionSymbol{" + eventSymbol_->toString() + ", source = " + source_.toString() + "}"; } else { diff --git a/src/api/osub/TimeSeriesSubscriptionSymbol.cpp b/src/api/osub/TimeSeriesSubscriptionSymbol.cpp index 203c5847c..061c44041 100644 --- a/src/api/osub/TimeSeriesSubscriptionSymbol.cpp +++ b/src/api/osub/TimeSeriesSubscriptionSymbol.cpp @@ -60,7 +60,7 @@ TimeSeriesSubscriptionSymbol TimeSeriesSubscriptionSymbol::fromGraal(void *graal return {SymbolWrapper::fromGraal(graalSymbol->symbol), graalSymbol->from_time}; } -std::string TimeSeriesSubscriptionSymbol::toString() const noexcept { +std::string TimeSeriesSubscriptionSymbol::toString() const { if constexpr (Debugger::isDebug) { return "TimeSeriesSubscriptionSymbol{" + getEventSymbol()->toString() + ", fromTime = " + TimeFormat::DEFAULT_WITH_MILLIS.format(fromTime_) + "}"; diff --git a/src/event/candle/Candle.cpp b/src/event/candle/Candle.cpp index f7e7c82fd..96bb3862e 100644 --- a/src/event/candle/Candle.cpp +++ b/src/event/candle/Candle.cpp @@ -134,7 +134,7 @@ void Candle::freeGraal(void *graalNative) { delete graalCandle; } -std::string Candle::toString() const noexcept { +std::string Candle::toString() const { return fmt::format( "Candle{{{}, eventTime={}, eventFlags={:#x}, time={}, sequence={}, count={}, open={}, high={}, low={}, " "close={}, volume={}, vwap={}, bidVolume={}, askVolume={}, impVolatility={}, openInterest={}}}", diff --git a/src/event/market/AnalyticOrder.cpp b/src/event/market/AnalyticOrder.cpp index 9ef106699..fa70aa55a 100644 --- a/src/event/market/AnalyticOrder.cpp +++ b/src/event/market/AnalyticOrder.cpp @@ -66,7 +66,7 @@ std::shared_ptr AnalyticOrder::fromGraal(void *graalNative) { return analyticOrder; } -std::string AnalyticOrder::toString() const noexcept { +std::string AnalyticOrder::toString() const { return fmt::format("AnalyticOrder{{{}, marketMaker={}, icebergPeakSize={}, icebergHiddenSize={}, " "icebergExecutedSize={}, icebergType={}}}", baseFieldsToString(), getMarketMaker(), dxfcpp::toString(getIcebergPeakSize()), diff --git a/src/event/market/OptionSale.cpp b/src/event/market/OptionSale.cpp index e8a84f69c..0363d90e1 100644 --- a/src/event/market/OptionSale.cpp +++ b/src/event/market/OptionSale.cpp @@ -111,7 +111,7 @@ void OptionSale::setExchangeCode(char exchangeCode) noexcept { data_.exchangeCode = utf8to16(exchangeCode); } -std::string OptionSale::toString() const noexcept { +std::string OptionSale::toString() const { return fmt::format( "OptionSale{{{}, eventTime={}, eventFlags={:#x}, index={:#x}, time={}, timeNanoPart={}, sequence={}, " "exchange={}, price={}, size={}, bid={}, ask={}, ESC='{}', TTE={}, side={}, spread={}, ETH={}, " diff --git a/src/event/market/Order.cpp b/src/event/market/Order.cpp index a31dc96b7..0cd045a49 100644 --- a/src/event/market/Order.cpp +++ b/src/event/market/Order.cpp @@ -72,7 +72,7 @@ std::shared_ptr Order::fromGraal(void *graalNative) { return order; } -std::string Order::toString() const noexcept { +std::string Order::toString() const { return fmt::format("Order{{{}, marketMaker={}}}", baseFieldsToString(), getMarketMaker()); } diff --git a/src/event/market/OrderBase.cpp b/src/event/market/OrderBase.cpp index 1c695fd1a..bd836b8b1 100644 --- a/src/event/market/OrderBase.cpp +++ b/src/event/market/OrderBase.cpp @@ -67,7 +67,7 @@ void OrderBase::fillGraalData(void *graalNative) const noexcept { graalOrderBase->trade_size = orderBaseData_.tradeSize; } -std::string OrderBase::baseFieldsToString() const noexcept { +std::string OrderBase::baseFieldsToString() const { return fmt::format( "{}, eventTime={}, source={}, eventFlags={:#x}, index={:#x}, time={}, sequence={}, " "timeNanoPart={}, action={}, actionTime={}, orderId={}, auxOrderId={}, price={}, " diff --git a/src/event/market/OtcMarketsOrder.cpp b/src/event/market/OtcMarketsOrder.cpp index 854620264..14e4b916b 100644 --- a/src/event/market/OtcMarketsOrder.cpp +++ b/src/event/market/OtcMarketsOrder.cpp @@ -64,7 +64,7 @@ OtcMarketsOrder::Ptr OtcMarketsOrder::fromGraal(void *graalNative) { return otcMarketsOrder; } -std::string OtcMarketsOrder::toString() const noexcept { +std::string OtcMarketsOrder::toString() const { return fmt::format("OtcMarketsOrder{{{}, marketMaker={}, QAP={}, open={}, unsolicited={}, priceType={}, " "saturated={}, autoEx={}, NMS={}}}", baseFieldsToString(), getMarketMaker(), getQuoteAccessPayment(), isOpen(), isUnsolicited(), diff --git a/src/event/market/Profile.cpp b/src/event/market/Profile.cpp index 7645f4124..764958f48 100644 --- a/src/event/market/Profile.cpp +++ b/src/event/market/Profile.cpp @@ -109,7 +109,7 @@ std::shared_ptr Profile::fromGraal(void *graalNative) { return profile; } -std::string Profile::toString() const noexcept { +std::string Profile::toString() const { return fmt::format( "Profile{{{}, eventTime={}, description='{}', SSR={}, status={}, statusReason='{}', " "haltStartTime={}, haltEndTime={}, highLimitPrice={}, lowLimitPrice={}, high52WeekPrice={}, " diff --git a/src/event/market/Quote.cpp b/src/event/market/Quote.cpp index aadf9985a..94c87c47e 100644 --- a/src/event/market/Quote.cpp +++ b/src/event/market/Quote.cpp @@ -100,7 +100,7 @@ void Quote::fillGraalData(void *graalNative) const noexcept { graalQuote->ask_size = data_.askSize; } -std::string Quote::toString() const noexcept { +std::string Quote::toString() const { return fmt::format( "Quote{{{}, eventTime={}, time={}, timeNanoPart={}, sequence={}, bidTime={}, bidExchange={}, bidPrice={}, " "bidSize={}, askTime={}, askExchange={}, askPrice={}, askSize={}}}", diff --git a/src/event/market/SpreadOrder.cpp b/src/event/market/SpreadOrder.cpp index a255907a9..4e517276e 100644 --- a/src/event/market/SpreadOrder.cpp +++ b/src/event/market/SpreadOrder.cpp @@ -72,7 +72,7 @@ std::shared_ptr SpreadOrder::fromGraal(void *graalNative) { return spreadOrder; } -std::string SpreadOrder::toString() const noexcept { +std::string SpreadOrder::toString() const { return fmt::format("SpreadOrder{{{}, spreadSymbol={}}}", baseFieldsToString(), getSpreadSymbol()); } diff --git a/src/event/market/Summary.cpp b/src/event/market/Summary.cpp index 43d3c45a8..5ad82f3de 100644 --- a/src/event/market/Summary.cpp +++ b/src/event/market/Summary.cpp @@ -84,7 +84,7 @@ std::shared_ptr Summary::fromGraal(void *graalNative) { return summary; } -std::string Summary::toString() const noexcept { +std::string Summary::toString() const { return fmt::format( "Summary{{{}, eventTime={}, day={}, dayOpen={}, dayHigh={}, dayLow='{}', " "dayClose={}, dayCloseType={}, prevDay={}, prevDayClose={}, prevDayCloseType={}, " diff --git a/src/event/market/TimeAndSale.cpp b/src/event/market/TimeAndSale.cpp index 979d98d61..748befb55 100644 --- a/src/event/market/TimeAndSale.cpp +++ b/src/event/market/TimeAndSale.cpp @@ -106,7 +106,7 @@ std::shared_ptr TimeAndSale::fromGraal(void *graalNative) { return timeAndSale; } -std::string TimeAndSale::toString() const noexcept { +std::string TimeAndSale::toString() const { return fmt::format("TimeAndSale{{{}, eventTime={}, eventFlags={:#x}, time={}, timeNanoPart={}, sequence={}, " "exchange={}, price={}, size={}, bid={}, " "ask={}, ESC='{}', TTE={}, side={}, spread={}, ETH={}, validTick={}, type={}{}{}}}", diff --git a/src/event/market/Trade.cpp b/src/event/market/Trade.cpp index 4d6d6058a..7f1b297e9 100644 --- a/src/event/market/Trade.cpp +++ b/src/event/market/Trade.cpp @@ -59,7 +59,7 @@ std::shared_ptr Trade::fromGraal(void *graalNative) { return trade; } -std::string Trade::toString() const noexcept { +std::string Trade::toString() const { return fmt::format("Trade{{{}}}", baseFieldsToString()); } diff --git a/src/event/market/TradeBase.cpp b/src/event/market/TradeBase.cpp index 61a5813d4..53c717045 100644 --- a/src/event/market/TradeBase.cpp +++ b/src/event/market/TradeBase.cpp @@ -57,7 +57,7 @@ void TradeBase::fillGraalData(void *graalNative) const noexcept { graalTradeBase->flags = tradeBaseData_.flags; } -std::string TradeBase::baseFieldsToString() const noexcept { +std::string TradeBase::baseFieldsToString() const { return fmt::format("{}, eventTime={}, time={}, timeNanoPart={}, sequence={}, exchange={}, price={}, " "change={}, size={}, day={}, dayVolume={}, dayTurnover={}, " "direction={}, ETH={}", diff --git a/src/event/market/TradeETH.cpp b/src/event/market/TradeETH.cpp index 36c28a29b..f9104e2dc 100644 --- a/src/event/market/TradeETH.cpp +++ b/src/event/market/TradeETH.cpp @@ -59,7 +59,7 @@ std::shared_ptr TradeETH::fromGraal(void *graalNative) { return tradeEth; } -std::string TradeETH::toString() const noexcept { +std::string TradeETH::toString() const { return fmt::format("TradeETH{{{}}}", baseFieldsToString()); } diff --git a/src/event/misc/Message.cpp b/src/event/misc/Message.cpp index 397f61e10..5c0965ac1 100644 --- a/src/event/misc/Message.cpp +++ b/src/event/misc/Message.cpp @@ -113,7 +113,7 @@ void Message::freeGraal(void *graalNative) { delete graalMessage; } -std::string Message::toString() const noexcept { +std::string Message::toString() const { return fmt::format("Message{{{}, eventTime={}, attachment={}}}", getEventSymbol(), TimeFormat::DEFAULT_WITH_MILLIS.format(getEventTime()), attachment_.value_or(String::NUL)); } diff --git a/src/event/option/Greeks.cpp b/src/event/option/Greeks.cpp index d878b7f9d..220dafa4f 100644 --- a/src/event/option/Greeks.cpp +++ b/src/event/option/Greeks.cpp @@ -82,7 +82,7 @@ std::shared_ptr Greeks::fromGraal(void *graalNative) { return greeks; } -std::string Greeks::toString() const noexcept { +std::string Greeks::toString() const { return fmt::format( "Greeks{{{}, eventTime={}, eventFlags={:#x}, time={}, sequence={}, price={}, volatility={}, delta={}, " "gamma={}, theta={}, rho={}, vega={}}}", diff --git a/src/event/option/Series.cpp b/src/event/option/Series.cpp index 2b28ed4ef..729039f18 100644 --- a/src/event/option/Series.cpp +++ b/src/event/option/Series.cpp @@ -86,7 +86,7 @@ std::shared_ptr Series::fromGraal(void *graalNative) { return series; } -std::string Series::toString() const noexcept { +std::string Series::toString() const { return fmt::format( "Series{{{}, eventTime={}, eventFlags={:#x}, index={:#x}, time={}, sequence={}, expiration={}, " "volatility={}, callVolume={}, putVolume={}, putCallRatio={}, forwardPrice={}, dividend={}, interest={}}}", diff --git a/src/event/option/TheoPrice.cpp b/src/event/option/TheoPrice.cpp index 91a2cdbe2..408d63e8e 100644 --- a/src/event/option/TheoPrice.cpp +++ b/src/event/option/TheoPrice.cpp @@ -80,7 +80,7 @@ std::shared_ptr TheoPrice::fromGraal(void *graalNative) { return theoPrice; } -std::string TheoPrice::toString() const noexcept { +std::string TheoPrice::toString() const { return fmt::format( "TheoPrice{{{}, eventTime={}, eventFlags={:#x}, time={}, sequence={}, price={}, underlyingPrice={}, " "delta={}, gamma={}, dividend={}, interest={}}}", diff --git a/src/event/option/Underlying.cpp b/src/event/option/Underlying.cpp index 95e922b96..d509aaa02 100644 --- a/src/event/option/Underlying.cpp +++ b/src/event/option/Underlying.cpp @@ -80,7 +80,7 @@ std::shared_ptr Underlying::fromGraal(void *graalNative) { return underlying; } -std::string Underlying::toString() const noexcept { +std::string Underlying::toString() const { return fmt::format( "Underlying{{{}, eventTime={}, eventFlags={:#x}, time={}, sequence={}, volatility={}, frontVolatility={}, " "backVolatility={}, callVolume={}, putVolume={}, putCallRatio={}}}", diff --git a/src/ipf/InstrumentProfile.cpp b/src/ipf/InstrumentProfile.cpp index 4bbb404c2..6888b2819 100644 --- a/src/ipf/InstrumentProfile.cpp +++ b/src/ipf/InstrumentProfile.cpp @@ -50,7 +50,6 @@ void InstrumentProfile::setDescription(const StringLikeWrapper &description) con isolated::ipf::IsolatedInstrumentProfile::setDescription(handle_, description); } - std::string InstrumentProfile::getLocalSymbol() const { return isolated::ipf::IsolatedInstrumentProfile::getLocalSymbol(handle_); } @@ -59,9 +58,283 @@ void InstrumentProfile::setLocalSymbol(const StringLikeWrapper &localSymbol) con isolated::ipf::IsolatedInstrumentProfile::setLocalSymbol(handle_, localSymbol); } -InstrumentProfile::~InstrumentProfile() noexcept {} +std::string InstrumentProfile::getLocalDescription() const { + return isolated::ipf::IsolatedInstrumentProfile::getLocalDescription(handle_); +} + +void InstrumentProfile::setLocalDescription(const StringLikeWrapper &localDescription) const { + isolated::ipf::IsolatedInstrumentProfile::setLocalDescription(handle_, localDescription); +} + +std::string InstrumentProfile::getCountry() const { + return isolated::ipf::IsolatedInstrumentProfile::getCountry(handle_); +} + +void InstrumentProfile::setCountry(const StringLikeWrapper &country) const { + isolated::ipf::IsolatedInstrumentProfile::setCountry(handle_, country); +} + +std::string InstrumentProfile::getOPOL() const { + return isolated::ipf::IsolatedInstrumentProfile::getOPOL(handle_); +} + +void InstrumentProfile::setOPOL(const StringLikeWrapper &opol) const { + isolated::ipf::IsolatedInstrumentProfile::setOPOL(handle_, opol); +} + +std::string InstrumentProfile::getExchangeData() const { + return isolated::ipf::IsolatedInstrumentProfile::getExchangeData(handle_); +} + +void InstrumentProfile::setExchangeData(const StringLikeWrapper &exchangeData) const { + isolated::ipf::IsolatedInstrumentProfile::setExchangeData(handle_, exchangeData); +} + +std::string InstrumentProfile::getExchanges() const { + return isolated::ipf::IsolatedInstrumentProfile::getExchanges(handle_); +} + +void InstrumentProfile::setExchanges(const StringLikeWrapper &exchanges) const { + isolated::ipf::IsolatedInstrumentProfile::setExchanges(handle_, exchanges); +} + +std::string InstrumentProfile::getCurrency() const { + return isolated::ipf::IsolatedInstrumentProfile::getCurrency(handle_); +} + +void InstrumentProfile::setCurrency(const StringLikeWrapper ¤cy) const { + isolated::ipf::IsolatedInstrumentProfile::setCurrency(handle_, currency); +} + +std::string InstrumentProfile::getBaseCurrency() const { + return isolated::ipf::IsolatedInstrumentProfile::getBaseCurrency(handle_); +} + +void InstrumentProfile::setBaseCurrency(const StringLikeWrapper &baseCurrency) const { + isolated::ipf::IsolatedInstrumentProfile::setBaseCurrency(handle_, baseCurrency); +} + +std::string InstrumentProfile::getCFI() const { + return isolated::ipf::IsolatedInstrumentProfile::getCFI(handle_); +} + +void InstrumentProfile::setCFI(const StringLikeWrapper &cfi) const { + isolated::ipf::IsolatedInstrumentProfile::setCFI(handle_, cfi); +} + +std::string InstrumentProfile::getISIN() const { + return isolated::ipf::IsolatedInstrumentProfile::getISIN(handle_); +} + +void InstrumentProfile::setISIN(const StringLikeWrapper &isin) const { + isolated::ipf::IsolatedInstrumentProfile::setISIN(handle_, isin); +} + +std::string InstrumentProfile::getSEDOL() const { + return isolated::ipf::IsolatedInstrumentProfile::getSEDOL(handle_); +} + +void InstrumentProfile::setSEDOL(const StringLikeWrapper &sedol) const { + isolated::ipf::IsolatedInstrumentProfile::setSEDOL(handle_, sedol); +} + +std::string InstrumentProfile::getCUSIP() const { + return isolated::ipf::IsolatedInstrumentProfile::getCUSIP(handle_); +} + +void InstrumentProfile::setCUSIP(const StringLikeWrapper &cusip) const { + isolated::ipf::IsolatedInstrumentProfile::setCUSIP(handle_, cusip); +} + +std::int32_t InstrumentProfile::getICB() const { + return isolated::ipf::IsolatedInstrumentProfile::getICB(handle_); +} + +void InstrumentProfile::setICB(std::int32_t icb) const { + isolated::ipf::IsolatedInstrumentProfile::setICB(handle_, icb); +} + +std::int32_t InstrumentProfile::getSIC() const { + return isolated::ipf::IsolatedInstrumentProfile::getSIC(handle_); +} + +void InstrumentProfile::setSIC(std::int32_t sic) const { + isolated::ipf::IsolatedInstrumentProfile::setSIC(handle_, sic); +} + +double InstrumentProfile::getMultiplier() const { + return isolated::ipf::IsolatedInstrumentProfile::getMultiplier(handle_); +} + +void InstrumentProfile::setMultiplier(double multiplier) const { + isolated::ipf::IsolatedInstrumentProfile::setMultiplier(handle_, multiplier); +} + +std::string InstrumentProfile::getProduct() const { + return isolated::ipf::IsolatedInstrumentProfile::getProduct(handle_); +} + +void InstrumentProfile::setProduct(const StringLikeWrapper &product) const { + isolated::ipf::IsolatedInstrumentProfile::setProduct(handle_, product); +} + +std::string InstrumentProfile::getUnderlying() const { + return isolated::ipf::IsolatedInstrumentProfile::getUnderlying(handle_); +} + +void InstrumentProfile::setUnderlying(const StringLikeWrapper &underlying) const { + isolated::ipf::IsolatedInstrumentProfile::setUnderlying(handle_, underlying); +} + +double InstrumentProfile::getSPC() const { + return isolated::ipf::IsolatedInstrumentProfile::getSPC(handle_); +} + +void InstrumentProfile::setSPC(double spc) const { + isolated::ipf::IsolatedInstrumentProfile::setSPC(handle_, spc); +} + +std::string InstrumentProfile::getAdditionalUnderlyings() const { + return isolated::ipf::IsolatedInstrumentProfile::getAdditionalUnderlyings(handle_); +} + +void InstrumentProfile::setAdditionalUnderlyings(const StringLikeWrapper &additionalUnderlyings) const { + isolated::ipf::IsolatedInstrumentProfile::setAdditionalUnderlyings(handle_, additionalUnderlyings); +} + +std::string InstrumentProfile::getMMY() const { + return isolated::ipf::IsolatedInstrumentProfile::getMMY(handle_); +} + +void InstrumentProfile::setMMY(const StringLikeWrapper &mmy) const { + isolated::ipf::IsolatedInstrumentProfile::setMMY(handle_, mmy); +} + +std::int32_t InstrumentProfile::getExpiration() const { + return isolated::ipf::IsolatedInstrumentProfile::getExpiration(handle_); +} + +void InstrumentProfile::setExpiration(std::int32_t expiration) const { + isolated::ipf::IsolatedInstrumentProfile::setExpiration(handle_, expiration); +} + +std::int32_t InstrumentProfile::getLastTrade() const { + return isolated::ipf::IsolatedInstrumentProfile::getLastTrade(handle_); +} + +void InstrumentProfile::setLastTrade(std::int32_t lastTrade) const { + isolated::ipf::IsolatedInstrumentProfile::setLastTrade(handle_, lastTrade); +} + +double InstrumentProfile::getStrike() const { + return isolated::ipf::IsolatedInstrumentProfile::getStrike(handle_); +} + +void InstrumentProfile::setStrike(double strike) const { + isolated::ipf::IsolatedInstrumentProfile::setStrike(handle_, strike); +} + +std::string InstrumentProfile::getOptionType() const { + return isolated::ipf::IsolatedInstrumentProfile::getOptionType(handle_); +} + +void InstrumentProfile::setOptionType(const StringLikeWrapper &optionType) const { + isolated::ipf::IsolatedInstrumentProfile::setOptionType(handle_, optionType); +} + +std::string InstrumentProfile::getExpirationStyle() const { + return isolated::ipf::IsolatedInstrumentProfile::getExpirationStyle(handle_); +} + +void InstrumentProfile::setExpirationStyle(const StringLikeWrapper &expirationStyle) const { + isolated::ipf::IsolatedInstrumentProfile::setExpirationStyle(handle_, expirationStyle); +} + +std::string InstrumentProfile::getSettlementStyle() const { + return isolated::ipf::IsolatedInstrumentProfile::getSettlementStyle(handle_); +} + +void InstrumentProfile::setSettlementStyle(const StringLikeWrapper &settlementStyle) const { + isolated::ipf::IsolatedInstrumentProfile::setSettlementStyle(handle_, settlementStyle); +} + +std::string InstrumentProfile::getPriceIncrements() const { + return isolated::ipf::IsolatedInstrumentProfile::getPriceIncrements(handle_); +} + +void InstrumentProfile::setPriceIncrements(const StringLikeWrapper &priceIncrements) const { + isolated::ipf::IsolatedInstrumentProfile::setPriceIncrements(handle_, priceIncrements); +} + +std::string InstrumentProfile::getTradingHours() const { + return isolated::ipf::IsolatedInstrumentProfile::getTradingHours(handle_); +} + +void InstrumentProfile::setTradingHours(const StringLikeWrapper &tradingHours) const { + isolated::ipf::IsolatedInstrumentProfile::setTradingHours(handle_, tradingHours); +} + +std::string InstrumentProfile::getField(const StringLikeWrapper &name) const { + return isolated::ipf::IsolatedInstrumentProfile::getField(handle_, name); +} + +void InstrumentProfile::setField(const StringLikeWrapper &name, const StringLikeWrapper &value) const { + isolated::ipf::IsolatedInstrumentProfile::setField(handle_, name, value); +} + +double InstrumentProfile::getNumericField(const StringLikeWrapper &name) const { + return isolated::ipf::IsolatedInstrumentProfile::getNumericField(handle_, name); +} + +void InstrumentProfile::setNumericField(const StringLikeWrapper &name, double value) const { + isolated::ipf::IsolatedInstrumentProfile::setNumericField(handle_, name, value); +} + +std::int32_t InstrumentProfile::getDateField(const StringLikeWrapper &name) const { + return isolated::ipf::IsolatedInstrumentProfile::getDateField(handle_, name); +} + +void InstrumentProfile::setDateField(const StringLikeWrapper &name, std::int32_t value) const { + isolated::ipf::IsolatedInstrumentProfile::setDateField(handle_, name, value); +} + +std::vector InstrumentProfile::getNonEmptyCustomFieldNames() const { + return isolated::ipf::IsolatedInstrumentProfile::getNonEmptyCustomFieldNames(handle_); +} + +std::string InstrumentProfile::toString() const { + if (!handle_) { + return "InstrumentProfile{}"; + } + + return isolated::internal::IsolatedObject::toString(handle_.get()); +} + +std::size_t InstrumentProfile::hashCode() const { + if (!handle_) { + return 0; + } + + return isolated::internal::IsolatedObject::hashCode(handle_.get()); +} + +bool InstrumentProfile::operator==(const InstrumentProfile &other) const { + if (!handle_) { + return !other.handle_; + } + + if (!other.handle_) { + return false; + } + + return isolated::internal::IsolatedObject::equals(handle_.get(), other.handle_.get()) == 0; +} + +InstrumentProfile::~InstrumentProfile() noexcept { +} -InstrumentProfile::InstrumentProfile(LockExternalConstructionTag, JavaObjectHandle &&handle) : handle_(std::move(handle)) { +InstrumentProfile::InstrumentProfile(LockExternalConstructionTag, JavaObjectHandle &&handle) + : handle_(std::move(handle)) { } InstrumentProfile::Ptr InstrumentProfile::create(JavaObjectHandle &&handle) { diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index 5dda74cee..2ef773775 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -253,7 +253,7 @@ std::size_t Day::getHashCode() const noexcept { return isolated::schedule::Day::getHashCode(handle_.get()); } -std::string Day::toString() const noexcept { +std::string Day::toString() const { if (!handle_) { return dxfcpp::String::EMPTY; } diff --git a/src/schedule/Schedule.cpp b/src/schedule/Schedule.cpp index f8b495b2d..4459ce80b 100644 --- a/src/schedule/Schedule.cpp +++ b/src/schedule/Schedule.cpp @@ -13,8 +13,7 @@ Schedule::Schedule(void *handle) noexcept : handle_(handle) { Schedule::Ptr Schedule::create(void *handle) { if (!handle) { - throw std::invalid_argument( - "Unable to create a Schedule object. The handle is nullptr"); + throw std::invalid_argument("Unable to create a Schedule object. The handle is nullptr"); } return std::shared_ptr(new Schedule(handle)); @@ -25,9 +24,7 @@ Schedule::Ptr Schedule::getInstance(std::shared_ptr profile) throw std::invalid_argument("The profile is nullptr"); } - auto graalProfile = profile->toGraal(); - auto schedule = create(isolated::schedule::Schedule::getInstance(graalProfile)); - InstrumentProfile::freeGraal(graalProfile); + auto schedule = create(isolated::schedule::Schedule::getInstance(profile->handle_.get())); return schedule; } @@ -41,9 +38,7 @@ Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, throw std::invalid_argument("The profile is nullptr"); } - auto graalProfile = profile->toGraal(); - auto schedule = create(isolated::schedule::Schedule::getInstance(graalProfile, venue)); - InstrumentProfile::freeGraal(graalProfile); + auto schedule = create(isolated::schedule::Schedule::getInstance(profile->handle_.get(), venue)); return schedule; } @@ -53,9 +48,7 @@ std::vector Schedule::getTradingVenues(std::shared_ptrtoGraal(); - auto result = isolated::schedule::Schedule::getTradingVenues(graalProfile); - InstrumentProfile::freeGraal(graalProfile); + auto result = isolated::schedule::Schedule::getTradingVenues(profile->handle_.get()); return result; } @@ -109,7 +102,7 @@ Session::Ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionF isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.handle_.get())); } -Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter& filter) const noexcept { +Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { if (!handle_ || !filter.handle_) { return {}; } diff --git a/src/schedule/Session.cpp b/src/schedule/Session.cpp index 6dca007ef..58b296446 100644 --- a/src/schedule/Session.cpp +++ b/src/schedule/Session.cpp @@ -139,7 +139,7 @@ std::size_t Session::getHashCode() const noexcept { return isolated::schedule::Session::getHashCode(handle_.get()); } -std::string Session::toString() const noexcept { +std::string Session::toString() const { if (!handle_) { return dxfcpp::String::EMPTY; } From f6328c560e065ea54e66b36dec145392a5409bed Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 22 Jul 2024 13:38:08 +0300 Subject: [PATCH 052/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type LatencyTest: refactor --- tools/Tools/src/LatencyTest/LatencyTestTool.hpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp index e9438d37b..4d6551e8c 100644 --- a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp +++ b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp @@ -44,8 +44,8 @@ struct LatencyTest { [[nodiscard]] static std::string prepareHelp(std::size_t namePadding, std::size_t nameFieldSize /* padding + name + padding */, std::size_t) noexcept { - return fmt::format("{:{}}{:<{}}{:{}}{}\n", "", namePadding, getFullName(), - nameFieldSize - 2 * namePadding, "", namePadding, SHORT_DESCRIPTION); + return fmt::format("{:{}}{:<{}}{:{}}{}\n", "", namePadding, getFullName(), nameFieldSize - 2 * namePadding, "", + namePadding, SHORT_DESCRIPTION); } struct Diagnostic final { @@ -320,16 +320,21 @@ struct LatencyTest { intervalIsParsed = true; index = parseResult.nextIndex; } else { - if (!forceStream && (forceStream = ForceStreamArg::parse(args, index).result)) { - index++; - continue; + if (!forceStream) { + forceStream = ForceStreamArg::parse(args, index).result; + + if (forceStream) { + index++; + continue; + } } index++; } } - return ParseResult::ok({parsedAddress.result, parsedTypes.result, parsedSymbols.result, properties, forceStream, interval.value_or(2)}); + return ParseResult::ok({parsedAddress.result, parsedTypes.result, parsedSymbols.result, properties, + forceStream, interval.value_or(2)}); } }; From a5ef177b941bd9ce51d07d5e2241f38fd0eb5240 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 24 Jul 2024 14:08:49 +0300 Subject: [PATCH 053/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type dxfcpp::RuntimeException --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../exceptions/GraalException.hpp | 11 +-- .../exceptions/JavaException.hpp | 19 ++--- .../exceptions/RuntimeException.hpp | 41 ++++++++++ samples/cpp/ConvertTapeFile/src/main.cpp | 8 +- samples/cpp/DxFeedConnect/src/main.cpp | 8 +- samples/cpp/DxFeedFileParser/src/main.cpp | 8 +- samples/cpp/DxFeedIpfConnect/src/main.cpp | 8 +- samples/cpp/DxFeedLiveIpfSample/src/main.cpp | 8 +- samples/cpp/DxFeedSample/src/main.cpp | 8 +- samples/cpp/FetchDailyCandles/src/main.cpp | 8 +- samples/cpp/OnDemandSample/src/main.cpp | 8 +- samples/cpp/PrintQuoteEvents/src/main.cpp | 8 +- samples/cpp/PublishProfiles/src/main.cpp | 8 +- samples/cpp/ScheduleSample/src/main.cpp | 8 +- samples/cpp/WriteTapeFile/src/main.cpp | 8 +- src/exceptions/GraalException.cpp | 7 +- src/exceptions/JavaException.cpp | 68 ++-------------- src/exceptions/RuntimeException.cpp | 81 +++++++++++++++++++ tools/Tools/src/Connect/ConnectTool.hpp | 8 +- tools/Tools/src/Dump/DumpTool.hpp | 8 +- .../Tools/src/LatencyTest/LatencyTestTool.hpp | 9 +-- tools/Tools/src/PerfTest/PerfTestTool.hpp | 8 +- tools/Tools/src/main.cpp | 16 +--- 25 files changed, 178 insertions(+), 196 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp create mode 100644 src/exceptions/RuntimeException.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 449377175..a4f9563e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,6 +199,7 @@ set(dxFeedGraalCxxApi_InternalUtilsDebug_Sources ) set(dxFeedGraalCxxApi_Exceptions_Sources + src/exceptions/RuntimeException.cpp src/exceptions/GraalException.cpp src/exceptions/JavaException.cpp ) diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 3e63c1164..eaf5aafb5 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -52,6 +52,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/Isolated.hpp" +#include "exceptions/RuntimeException.hpp" #include "exceptions/JavaException.hpp" #include "exceptions/GraalException.hpp" diff --git a/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp b/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp index 67269bbe6..44424544f 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp @@ -9,6 +9,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4275) #include "../internal/CEntryPointErrors.hpp" +#include "RuntimeException.hpp" + #include #include @@ -17,7 +19,7 @@ DXFCPP_BEGIN_NAMESPACE /** * The wrapper over CEntryPointErrorsEnum, the error code returned by GraalVM. */ -struct DXFCPP_EXPORT GraalException : public std::runtime_error { +struct DXFCPP_EXPORT GraalException : RuntimeException { /** * Constructs an exception. * @@ -25,11 +27,6 @@ struct DXFCPP_EXPORT GraalException : public std::runtime_error { */ GraalException(CEntryPointErrorsEnum entryPointErrorsEnum); - /** - * @return dxFeed Graal CXX API stack trace - */ - const std::string& getStackTrace() const&; - private: static inline std::string createMessage(CEntryPointErrorsEnum entryPointErrorsEnum) { auto result = CEntryPointErrorsEnumToStr(entryPointErrorsEnum); @@ -41,8 +38,6 @@ struct DXFCPP_EXPORT GraalException : public std::runtime_error { return result; } - - std::string stackTrace_; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index b27c9f926..b7648f676 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -5,8 +5,12 @@ #include "../internal/Conf.hpp" +#include "../internal/Common.hpp" + DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4275) +#include "RuntimeException.hpp" + #include #include #include @@ -17,7 +21,7 @@ DXFCPP_BEGIN_NAMESPACE /** * A wrapper over the interceptable Java exceptions thrown by the dxFeed Native Graal SDK */ -struct DXFCPP_EXPORT JavaException : public std::runtime_error { +struct DXFCPP_EXPORT JavaException : RuntimeException { /** * Creates an exception using Java message, className and stack trace. Also uses current stack trace. * @@ -25,7 +29,8 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { * @param className Java class name. * @param stackTrace Java stack trace. */ - JavaException(const std::string &message, const std::string &className, std::string stackTrace); + JavaException(const StringLikeWrapper &message, const StringLikeWrapper &className, + const StringLikeWrapper &stackTrace); /** * Creates an exception using native (GraalVM) Java exception handle @@ -33,7 +38,7 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { * @param exceptionHandle The native Java exception handle. * @return An exception. */ - static JavaException create(void* exceptionHandle); + static JavaException create(void *exceptionHandle); /// Throws a JavaException if it exists (i.e. intercepted by Graal SDK) static void throwIfJavaThreadExceptionExists(); @@ -87,14 +92,6 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { return v; } - - /** - * @return dxFeed Graal CXX API stack trace + Java (GraalVM) exception's stack trace. - */ - const std::string &getStackTrace() const &; - - private: - std::string stackTrace_; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp b/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp new file mode 100644 index 000000000..4c7bdb454 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../internal/Conf.hpp" + +#include "../internal/Common.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4275) + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +/** + * A runtime axception with stacktrace + */ +struct DXFCPP_EXPORT RuntimeException : std::runtime_error { + /** + * Constructs a runtime exception. + * + * @param message The exception's message. + * @param additionalStackTrace The additional stacktrace that will be concatenated with current stacktrace. + */ + explicit RuntimeException(const StringLikeWrapper& message, const StringLikeWrapper& additionalStackTrace = ""); + + /** + * @return The current stacktrace + the additional stacktrace if present. + */ + const std::string& getStackTrace() const &; +private: + std::string stackTrace_; +}; + +DXFCPP_END_NAMESPACE + +DXFCPP_EXPORT std::ostream &operator<<(std::ostream &os, const dxfcpp::RuntimeException &e); + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/samples/cpp/ConvertTapeFile/src/main.cpp b/samples/cpp/ConvertTapeFile/src/main.cpp index 61108307a..d8afbf358 100644 --- a/samples/cpp/ConvertTapeFile/src/main.cpp +++ b/samples/cpp/ConvertTapeFile/src/main.cpp @@ -70,12 +70,8 @@ int main(int argc, char *argv[]) { // Wait until all data is processed and written, and then gracefully close output endpoint. outputEndpoint->awaitProcessed(); outputEndpoint->closeAndAwaitTermination(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } return 0; diff --git a/samples/cpp/DxFeedConnect/src/main.cpp b/samples/cpp/DxFeedConnect/src/main.cpp index 1a6f93573..e42a6ab79 100644 --- a/samples/cpp/DxFeedConnect/src/main.cpp +++ b/samples/cpp/DxFeedConnect/src/main.cpp @@ -91,12 +91,8 @@ int main(int argc, char *argv[]) { } std::cin.get(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } return 0; diff --git a/samples/cpp/DxFeedFileParser/src/main.cpp b/samples/cpp/DxFeedFileParser/src/main.cpp index da767f198..682bb7ab7 100644 --- a/samples/cpp/DxFeedFileParser/src/main.cpp +++ b/samples/cpp/DxFeedFileParser/src/main.cpp @@ -68,12 +68,8 @@ int main(int argc, char *argv[]) { // Close endpoint when we're done. // This method will gracefully close endpoint, waiting while data processing completes. endpoint->closeAndAwaitTermination(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } return 0; diff --git a/samples/cpp/DxFeedIpfConnect/src/main.cpp b/samples/cpp/DxFeedIpfConnect/src/main.cpp index d516252ff..f54671d37 100644 --- a/samples/cpp/DxFeedIpfConnect/src/main.cpp +++ b/samples/cpp/DxFeedIpfConnect/src/main.cpp @@ -79,11 +79,7 @@ int main(int argc, char *argv[]) { sub->addSymbols(getSymbols(ipfFile)); std::this_thread::sleep_for(std::chrono::days(365)); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } diff --git a/samples/cpp/DxFeedLiveIpfSample/src/main.cpp b/samples/cpp/DxFeedLiveIpfSample/src/main.cpp index 29fdaa49a..907111638 100644 --- a/samples/cpp/DxFeedLiveIpfSample/src/main.cpp +++ b/samples/cpp/DxFeedLiveIpfSample/src/main.cpp @@ -102,11 +102,7 @@ int main(int argc, char *argv[]) { std::this_thread::sleep_for(std::chrono::days(365)); connection->close(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } \ No newline at end of file diff --git a/samples/cpp/DxFeedSample/src/main.cpp b/samples/cpp/DxFeedSample/src/main.cpp index 0e82bcdbe..c50ec59b4 100644 --- a/samples/cpp/DxFeedSample/src/main.cpp +++ b/samples/cpp/DxFeedSample/src/main.cpp @@ -75,11 +75,7 @@ DxFeedSample testQuoteAndTradeListener(symbol); std::cin.get(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } diff --git a/samples/cpp/FetchDailyCandles/src/main.cpp b/samples/cpp/FetchDailyCandles/src/main.cpp index a2d653922..8fb934ee1 100644 --- a/samples/cpp/FetchDailyCandles/src/main.cpp +++ b/samples/cpp/FetchDailyCandles/src/main.cpp @@ -46,11 +46,7 @@ FetchDailyCandles std::cout << "Fetching last " << DAYS << " days of candles for " << baseSymbol << "\n"; fetchAndPrint(candleSymbol, toTime, fromTime); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } diff --git a/samples/cpp/OnDemandSample/src/main.cpp b/samples/cpp/OnDemandSample/src/main.cpp index 1071fd8ee..23104eb72 100644 --- a/samples/cpp/OnDemandSample/src/main.cpp +++ b/samples/cpp/OnDemandSample/src/main.cpp @@ -53,11 +53,7 @@ int main(int /* argc */, char ** /* argv */) { // close endpoint completely to release resources and shutdown GraalVM onDemand->getEndpoint()->closeAndAwaitTermination(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } diff --git a/samples/cpp/PrintQuoteEvents/src/main.cpp b/samples/cpp/PrintQuoteEvents/src/main.cpp index 5995508fc..18091fb7b 100644 --- a/samples/cpp/PrintQuoteEvents/src/main.cpp +++ b/samples/cpp/PrintQuoteEvents/src/main.cpp @@ -34,11 +34,7 @@ int main(int argc, char *argv[]) { subscription->addSymbols(symbol); std::cin.get(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } diff --git a/samples/cpp/PublishProfiles/src/main.cpp b/samples/cpp/PublishProfiles/src/main.cpp index c3e36c165..39d9613e2 100644 --- a/samples/cpp/PublishProfiles/src/main.cpp +++ b/samples/cpp/PublishProfiles/src/main.cpp @@ -53,12 +53,8 @@ int main(int argc, char *argv[]) { })); std::cin.get(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } return 0; diff --git a/samples/cpp/ScheduleSample/src/main.cpp b/samples/cpp/ScheduleSample/src/main.cpp index b49e51e67..f60b6b268 100644 --- a/samples/cpp/ScheduleSample/src/main.cpp +++ b/samples/cpp/ScheduleSample/src/main.cpp @@ -225,11 +225,7 @@ int main(int argc, char *argv[]) { printCurrentSession(profile, time); printNextTradingSession(profile, time); printNearestTradingSession(profile, time); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } \ No newline at end of file diff --git a/samples/cpp/WriteTapeFile/src/main.cpp b/samples/cpp/WriteTapeFile/src/main.cpp index 567bf34d1..da277b92a 100644 --- a/samples/cpp/WriteTapeFile/src/main.cpp +++ b/samples/cpp/WriteTapeFile/src/main.cpp @@ -33,12 +33,8 @@ int main() { // Wait until all data is written, close, and wait until it closes. endpoint->awaitProcessed(); endpoint->closeAndAwaitTermination(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } return 0; diff --git a/src/exceptions/GraalException.cpp b/src/exceptions/GraalException.cpp index c3576ae42..9a1ee17cf 100644 --- a/src/exceptions/GraalException.cpp +++ b/src/exceptions/GraalException.cpp @@ -13,12 +13,7 @@ DXFCPP_BEGIN_NAMESPACE std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace); GraalException::GraalException(CEntryPointErrorsEnum entryPointErrorsEnum) - : std::runtime_error(createMessage(entryPointErrorsEnum)), - stackTrace_{stackTraceToString(boost::stacktrace::stacktrace())} { -} - -const std::string &GraalException::getStackTrace() const & { - return stackTrace_; + : RuntimeException(createMessage(entryPointErrorsEnum)) { } DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index b3ee9a5a8..9f489c679 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -10,6 +10,8 @@ DXFCPP_BEGIN_NAMESPACE +std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace); + void JavaException::throwIfJavaThreadExceptionExists() { dxfg_exception_t *exception = runIsolatedThrow([](auto threadHandle) { return dxfg_get_and_clear_thread_exception_t(static_cast(threadHandle)); @@ -36,64 +38,10 @@ void JavaException::throwException() { }); } -std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace) { - std::string result; - - for (auto &&frame : stacktrace) { - result += "\tat "; - auto frameString = boost::stacktrace::to_string(frame); - - if (frameString.empty()) { - result += "\n"; - - continue; - } - - std::string what; - std::size_t whereStart = 0; - - auto foundIn = frameString.find(" in "); - - if (foundIn != std::string::npos) { - what = frameString.substr(0, foundIn); - whereStart = foundIn + 4; - } else { - auto foundAt = frameString.find(" at "); - - if (foundAt != std::string::npos) { - what = frameString.substr(0, foundAt); - whereStart = foundIn + 4; - } else { - whereStart = frameString.size(); - } - } - - if (whereStart == frameString.size()) { - what = frameString; - - result += what + "\n"; - - continue; - } - - auto foundLastSep = frameString.find_last_of("\\/"); - std::string where; - - if (foundLastSep != std::string::npos && foundLastSep < frameString.size() - 1) { - where = frameString.substr(foundLastSep + 1); - } else { - where = frameString.substr(whereStart); - } - - result += fmt::format("{}({})\n", what, where); - } - - return result; -} - -JavaException::JavaException(const std::string &message, const std::string &className, std::string stackTrace) - : std::runtime_error(fmt::format("Java exception of type '{}' was thrown. {}", className, message)), - stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { +JavaException::JavaException(const StringLikeWrapper &message, const StringLikeWrapper &className, + const StringLikeWrapper &stackTrace) + : RuntimeException(fmt::format("Java exception of type '{}' was thrown. {}", className.c_str(), message.c_str()), + stackTrace) { } JavaException JavaException::create(void *exceptionHandle) { @@ -106,8 +54,4 @@ JavaException JavaException::create(void *exceptionHandle) { return {toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)}; } -const std::string &JavaException::getStackTrace() const & { - return stackTrace_; -} - DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/exceptions/RuntimeException.cpp b/src/exceptions/RuntimeException.cpp new file mode 100644 index 000000000..0e6ae776a --- /dev/null +++ b/src/exceptions/RuntimeException.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace) { + std::string result; + + for (auto &&frame : stacktrace) { + result += "\tat "; + auto frameString = boost::stacktrace::to_string(frame); + + if (frameString.empty()) { + result += "\n"; + + continue; + } + + std::string what; + std::size_t whereStart = 0; + + auto foundIn = frameString.find(" in "); + + if (foundIn != std::string::npos) { + what = frameString.substr(0, foundIn); + whereStart = foundIn + 4; + } else { + auto foundAt = frameString.find(" at "); + + if (foundAt != std::string::npos) { + what = frameString.substr(0, foundAt); + whereStart = foundIn + 4; + } else { + whereStart = frameString.size(); + } + } + + if (whereStart == frameString.size()) { + what = frameString; + + result += what + "\n"; + + continue; + } + + auto foundLastSep = frameString.find_last_of("\\/"); + std::string where; + + if (foundLastSep != std::string::npos && foundLastSep < frameString.size() - 1) { + where = frameString.substr(foundLastSep + 1); + } else { + where = frameString.substr(whereStart); + } + + result += fmt::format("{}({})\n", what, where); + } + + return result; +} + +RuntimeException::RuntimeException(const StringLikeWrapper &message, const StringLikeWrapper &additionalStackTrace) + : runtime_error(message.c_str()), + stackTrace_(additionalStackTrace.empty() ? stackTraceToString(boost::stacktrace::stacktrace()) + : fmt::format("{}\n{}", additionalStackTrace.c_str(), + stackTraceToString(boost::stacktrace::stacktrace()))) { +} + +const std::string &RuntimeException::getStackTrace() const & { + return stackTrace_; +} + +DXFCPP_END_NAMESPACE + +std::ostream &operator<<(std::ostream &os, const dxfcpp::RuntimeException &e) { + return os << fmt::format("{}\n{}", e.what(), e.getStackTrace()); +} diff --git a/tools/Tools/src/Connect/ConnectTool.hpp b/tools/Tools/src/Connect/ConnectTool.hpp index 9b6905a14..00dbc0af6 100644 --- a/tools/Tools/src/Connect/ConnectTool.hpp +++ b/tools/Tools/src/Connect/ConnectTool.hpp @@ -209,12 +209,8 @@ struct ConnectTool { sub->addSymbols(symbols); endpoint->connect(args.address); std::this_thread::sleep_for(std::chrono::days(365)); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } }; diff --git a/tools/Tools/src/Dump/DumpTool.hpp b/tools/Tools/src/Dump/DumpTool.hpp index 600dd428b..088da526f 100644 --- a/tools/Tools/src/Dump/DumpTool.hpp +++ b/tools/Tools/src/Dump/DumpTool.hpp @@ -184,12 +184,8 @@ struct DumpTool { outputEndpoint.value()->awaitProcessed(); outputEndpoint.value()->closeAndAwaitTermination(); } - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } }; diff --git a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp index 4d6551e8c..a45097f12 100644 --- a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp +++ b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp @@ -340,7 +340,6 @@ struct LatencyTest { static void run(const Args &args) noexcept { try { - using namespace std::literals; auto parsedProperties = CmdArgsUtils::parseProperties(args.properties); @@ -368,12 +367,8 @@ struct LatencyTest { endpoint->connect(args.address); endpoint->awaitNotConnected(); endpoint->closeAndAwaitTermination(); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } }; diff --git a/tools/Tools/src/PerfTest/PerfTestTool.hpp b/tools/Tools/src/PerfTest/PerfTestTool.hpp index e3af5bd8a..dcbe28a5b 100644 --- a/tools/Tools/src/PerfTest/PerfTestTool.hpp +++ b/tools/Tools/src/PerfTest/PerfTestTool.hpp @@ -271,12 +271,8 @@ struct PerfTestTool { endpoint->closeAndAwaitTermination(); std::cout << hash << std::endl; - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } } }; diff --git a/tools/Tools/src/main.cpp b/tools/Tools/src/main.cpp index 70661a07c..75f9920e0 100644 --- a/tools/Tools/src/main.cpp +++ b/tools/Tools/src/main.cpp @@ -83,12 +83,8 @@ int main(int argc, char *argv[]) { std::cout << tools::Tools::getName() << "\n"; T::run(parseResult.result); - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } }, tool); @@ -97,12 +93,8 @@ int main(int argc, char *argv[]) { } std::cout << usage << "\n"; - } catch (const JavaException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; - } catch (const GraalException &e) { - std::cerr << e.what() << '\n'; - std::cerr << e.getStackTrace() << '\n'; + } catch (const RuntimeException &e) { + std::cerr << e << '\n'; } catch (const std::runtime_error &e) { std::cerr << e.what() << '\n'; } catch (...) { From 360475b41683c6fd3410b6bc1c40d52fd3b751e5 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 24 Jul 2024 16:52:02 +0300 Subject: [PATCH 054/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type dxfcpp::InvalidArgumentException --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../dxfeed_graal_cpp_api/api/DXEndpoint.hpp | 58 +++---- .../osub/IndexedEventSubscriptionSymbol.hpp | 3 +- .../api/osub/TimeSeriesSubscriptionSymbol.hpp | 3 +- .../api/osub/WildcardSymbol.hpp | 3 +- .../event/IndexedEventSource.hpp | 3 +- .../event/candle/Candle.hpp | 10 +- .../event/candle/CandleAlignment.hpp | 9 +- .../event/candle/CandlePeriod.hpp | 2 + .../event/candle/CandlePrice.hpp | 20 +-- .../event/candle/CandlePriceLevel.hpp | 5 +- .../event/candle/CandleSession.hpp | 17 +-- .../event/candle/CandleSymbol.hpp | 3 +- .../event/candle/CandleType.hpp | 18 +-- .../event/market/AnalyticOrder.hpp | 3 +- .../event/market/OptionSale.hpp | 6 +- .../event/market/Order.hpp | 3 +- .../event/market/OrderBase.hpp | 6 +- .../event/market/OrderSource.hpp | 8 +- .../event/market/OtcMarketsOrder.hpp | 3 +- .../event/market/Profile.hpp | 3 +- .../event/market/Quote.hpp | 6 +- .../event/market/SpreadOrder.hpp | 3 +- .../event/market/Summary.hpp | 3 +- .../event/market/TimeAndSale.hpp | 6 +- .../event/market/Trade.hpp | 3 +- .../event/market/TradeBase.hpp | 3 +- .../event/market/TradeETH.hpp | 3 +- .../event/misc/Message.hpp | 3 +- .../event/option/Greeks.hpp | 6 +- .../event/option/Series.hpp | 6 +- .../event/option/TheoPrice.hpp | 6 +- .../event/option/Underlying.hpp | 6 +- .../exceptions/InvalidArgumentException.hpp | 28 ++++ .../dxfeed_graal_cpp_api/internal/Common.hpp | 42 ++--- .../internal/TimeFormat.hpp | 2 +- .../ipf/InstrumentProfile.hpp | 2 +- .../isolated/api/IsolatedDXEndpoint.hpp | 44 +++--- .../api/IsolatedDXFeedSubscription.hpp | 34 ++--- .../isolated/api/IsolatedDXPublisher.hpp | 4 +- ...latedDXPublisherObservableSubscription.hpp | 10 +- ...edObservableSubscriptionChangeListener.hpp | 2 +- .../isolated/internal/IsolatedString.hpp | 4 +- .../isolated/promise/IsolatedPromise.hpp | 22 +-- .../symbols/StringSymbol.hpp | 3 +- .../symbols/SymbolWrapper.hpp | 4 +- src/api/DXEndpoint.cpp | 2 +- .../osub/IndexedEventSubscriptionSymbol.cpp | 2 +- src/api/osub/TimeSeriesSubscriptionSymbol.cpp | 2 +- src/event/EventMapper.cpp | 18 +-- src/event/candle/Candle.cpp | 6 +- src/event/market/AnalyticOrder.cpp | 6 +- src/event/market/OptionSale.cpp | 4 +- src/event/market/Order.cpp | 6 +- src/event/market/OtcMarketsOrder.cpp | 6 +- src/event/market/Profile.cpp | 6 +- src/event/market/Quote.cpp | 6 +- src/event/market/SpreadOrder.cpp | 6 +- src/event/market/Summary.cpp | 6 +- src/event/market/TimeAndSale.cpp | 6 +- src/event/market/Trade.cpp | 6 +- src/event/market/TradeETH.cpp | 6 +- src/event/misc/Message.cpp | 6 +- src/event/option/Greeks.cpp | 6 +- src/event/option/Series.cpp | 6 +- src/event/option/TheoPrice.cpp | 6 +- src/event/option/Underlying.cpp | 6 +- src/exceptions/InvalidArgumentException.cpp | 16 ++ src/internal/Common.cpp | 29 ++++ src/ipf/live/InstrumentProfileConnection.cpp | 2 +- src/isolated/api/IsolatedDXEndpoint.cpp | 48 +++--- src/isolated/api/IsolatedDXFeed.cpp | 2 +- .../api/IsolatedDXFeedSubscription.cpp | 56 +++---- src/isolated/api/IsolatedDXPublisher.cpp | 6 +- ...latedDXPublisherObservableSubscription.cpp | 14 +- ...edObservableSubscriptionChangeListener.cpp | 6 +- src/isolated/auth/IsolatedAuthToken.cpp | 10 +- src/isolated/internal/IsolatedObject.cpp | 8 +- src/isolated/internal/IsolatedString.cpp | 4 +- src/isolated/internal/IsolatedTimeFormat.cpp | 8 +- .../ipf/IsolatedInstrumentProfile.cpp | 144 +++++++++--------- .../ipf/IsolatedInstrumentProfileReader.cpp | 12 +- src/isolated/promise/IsolatedPromise.cpp | 22 +-- src/isolated/util/IsolatedTimePeriod.cpp | 6 +- src/ondemand/OnDemandService.cpp | 2 +- src/schedule/Day.cpp | 2 +- src/schedule/Schedule.cpp | 8 +- src/schedule/Session.cpp | 2 +- src/symbols/StringSymbol.cpp | 2 +- src/symbols/SymbolWrapper.cpp | 4 +- 91 files changed, 549 insertions(+), 431 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp create mode 100644 src/exceptions/InvalidArgumentException.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a4f9563e8..526b63efc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,6 +200,7 @@ set(dxFeedGraalCxxApi_InternalUtilsDebug_Sources set(dxFeedGraalCxxApi_Exceptions_Sources src/exceptions/RuntimeException.cpp + src/exceptions/InvalidArgumentException.cpp src/exceptions/GraalException.cpp src/exceptions/JavaException.cpp ) diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index eaf5aafb5..c11a19e3b 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -53,6 +53,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/Isolated.hpp" #include "exceptions/RuntimeException.hpp" +#include "exceptions/InvalidArgumentException.hpp" #include "exceptions/JavaException.hpp" #include "exceptions/GraalException.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp b/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp index d294e4e75..f82308904 100644 --- a/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXEndpoint.hpp @@ -178,7 +178,7 @@ struct OnDemandService; * * Some methods that are not marked `noexcept` may throw exceptions: * - * @throws std::invalid_argument if handle is invalid. + * @throws InvalidArgumentException if handle is invalid. * @throws JavaException if something happened with the dxFeed API backend * @throws GraalException if something happened with the GraalVM */ @@ -481,7 +481,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { // Throws: // - std::bad_alloc if it was not possible to allocate the required amount of memory - // - std::invalid_argument if endpointHandle is nullptr + // - InvalidArgumentException if endpointHandle is nullptr // - JavaException if something happened with the dxFeed API backend // - GraalException if something happened with the GraalVM static std::shared_ptr create(void *endpointHandle, Role role, @@ -509,7 +509,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @ref DXEndpoint::getInstance(Role) "getInstance"(@ref DXEndpoint "DXEndpoint"::@ref DXEndpoint::Role "Role"::@ref * DXEndpoint.Role::FEED "FEED"). * @see DXEndpoint::getInstance(Role) - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -533,7 +533,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * @param role The role of DXEndpoint instance * @return The DXEndpoint instance - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -546,7 +546,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * Use Builder::build() to build an instance of DXEndpoint when all configuration properties were set. * * @return the created endpoint builder. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -559,7 +559,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @ref DXEndpoint::newBuilder() "newBuilder()"->@ref Builder::build() "build()" * * @return the created endpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -573,7 +573,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * @param role the role. * @return the created endpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -594,7 +594,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @return the state. * * @see DXEndpoint - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -602,7 +602,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { /** * @return `true` if the endpoint is closed - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -658,7 +658,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @param user The user name. * * @return this DXEndpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -672,7 +672,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @param password The password. * * @return this DXEndpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -706,7 +706,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @param address The data source address. * @return this DXEndpoint. * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException if something happened with the dxFeed API backend or if address string is malformed. * @throws GraalException */ @@ -728,7 +728,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#reconnect--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -744,7 +744,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#disconnect--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -760,7 +760,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#disconnectAndClear--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -775,7 +775,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#close--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -792,7 +792,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#awaitNotConnected--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -805,7 +805,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#awaitProcessed--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -822,7 +822,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * [Javadoc.](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/api/DXEndpoint.html#closeAndAwaitTermination--) * - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -833,7 +833,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { /** * @return The feed that is associated with this endpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -841,7 +841,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { /** * @return The publisher that is associated with this endpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -852,7 +852,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * * Some methods that are not marked `noexcept` may throw exceptions: * - * @throws std::invalid_argument if handle is invalid. + * @throws InvalidArgumentException if handle is invalid. * @throws JavaException if something happened with the dxFeed API backend * @throws GraalException if something happened with the GraalVM */ @@ -880,7 +880,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * or "dxpublisher.properties" for the Role::PUBLISHER role. * * Non thread-safe. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -900,7 +900,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @param name The endpoint's name * * @return `this` endpoint builder. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -913,7 +913,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @param role The endpoint's role * * @return `this` endpoint builder. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -927,7 +927,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @return `this` endpoint builder. * * @see ::supportsProperty(const std::string&) - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -941,7 +941,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @return `this` endpoint builder. * * @see ::withProperty(const std::string&, const std::string&) - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -965,7 +965,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * @return `true` if the corresponding property key is supported. * * @see ::withProperty(const std::string&, const std::string&) - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ @@ -975,7 +975,7 @@ struct DXFCPP_EXPORT DXEndpoint : public RequireMakeShared { * Builds DXEndpoint instance. * * @return the created endpoint. - * @throws std::invalid_argument + * @throws InvalidArgumentException * @throws JavaException * @throws GraalException */ diff --git a/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp b/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp index 80c0fdab9..04a088c66 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/IndexedEventSubscriptionSymbol.hpp @@ -56,6 +56,7 @@ class DXFCPP_EXPORT IndexedEventSubscriptionSymbol { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -65,7 +66,7 @@ class DXFCPP_EXPORT IndexedEventSubscriptionSymbol { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static IndexedEventSubscriptionSymbol fromGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp b/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp index 71286b21b..01acf3ca3 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/TimeSeriesSubscriptionSymbol.hpp @@ -84,6 +84,7 @@ class DXFCPP_EXPORT TimeSeriesSubscriptionSymbol final : public IndexedEventSubs * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -93,7 +94,7 @@ class DXFCPP_EXPORT TimeSeriesSubscriptionSymbol final : public IndexedEventSubs * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static TimeSeriesSubscriptionSymbol fromGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp b/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp index 66da25235..01c725cb2 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp @@ -73,6 +73,7 @@ struct DXFCPP_EXPORT WildcardSymbol final { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -81,7 +82,7 @@ struct DXFCPP_EXPORT WildcardSymbol final { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static const WildcardSymbol &fromGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp b/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp index 60a4a38c1..1070fcde6 100644 --- a/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp +++ b/include/dxfeed_graal_cpp_api/event/IndexedEventSource.hpp @@ -41,6 +41,7 @@ class DXFCPP_EXPORT IndexedEventSource { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -49,7 +50,7 @@ class DXFCPP_EXPORT IndexedEventSource { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static IndexedEventSource fromGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp index 787022f9d..37caec072 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp @@ -14,6 +14,9 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include #include "../../internal/Common.hpp" + +#include "../../exceptions/InvalidArgumentException.hpp" + #include "../EventType.hpp" #include "../EventTypeEnum.hpp" #include "../IndexedEventSource.hpp" @@ -126,7 +129,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -143,6 +146,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -343,13 +347,13 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * * @param sequence the sequence. * @see Candle::getSequence() - * @throws std::invalid_argument if sequence is below zero or above ::MAX_SEQUENCE. + * @throws InvalidArgumentException if sequence is below zero or above ::MAX_SEQUENCE. */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid value for argument `sequence`: " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); } data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp index 4640e8d82..9489686e9 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp @@ -8,6 +8,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../internal/utils/StringUtils.hpp" +#include "../../exceptions/InvalidArgumentException.hpp" #include "../market/MarketEventSymbols.hpp" #include "CandleSymbolAttribute.hpp" @@ -101,7 +102,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * * @param s The string representation of candle alignment. * @return The candle alignment (reference) - * @throws std::invalid_argument if the string representation is invalid. + * @throws InvalidArgumentException if the string representation is invalid. */ static std::reference_wrapper parse(const dxfcpp::StringLikeWrapper &s) { auto found = BY_STRING.find(s); @@ -118,7 +119,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { } } - throw std::invalid_argument("Unknown candle alignment: " + s); + throw InvalidArgumentException("Unknown candle alignment: " + s); } /** @@ -152,7 +153,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { try { auto other = parse(a.value()); - if (other == DEFAULT) { + if (other.get() == DEFAULT) { return MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY); } @@ -160,6 +161,8 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.get().toString()); } + return symbol; + } catch (const InvalidArgumentException &) { return symbol; } catch (const std::invalid_argument &) { return symbol; diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp index c0835a3c3..50b98ba06 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp @@ -234,6 +234,8 @@ struct DXFCPP_EXPORT CandlePeriod : public CandleSymbolAttribute { return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.toString()); } + return symbol; + } catch (const InvalidArgumentException &) { return symbol; } catch (const std::invalid_argument &) { return symbol; diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandlePrice.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandlePrice.hpp index b547e1141..d6142542e 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandlePrice.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandlePrice.hpp @@ -7,6 +7,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include "../../exceptions/InvalidArgumentException.hpp" #include "../../internal/utils/StringUtils.hpp" #include "../market/MarketEventSymbols.hpp" #include "CandleSymbolAttribute.hpp" @@ -117,13 +118,11 @@ struct DXFCPP_EXPORT CandlePrice : public CandleSymbolAttribute { * * @param s The string representation of candle price type. * @return The candle price type (reference). + * @throws InvalidArgumentException if argument is empty or invalid */ static std::reference_wrapper parse(const dxfcpp::StringLikeWrapper &s) { - auto sw = s.operator std::string_view(); - auto n = sw.length(); - - if (n == 0) { - throw std::invalid_argument("Missing candle price"); + if (s.empty()) { + throw InvalidArgumentException("Missing candle price"); } auto found = BY_STRING.find(s); @@ -135,12 +134,12 @@ struct DXFCPP_EXPORT CandlePrice : public CandleSymbolAttribute { for (const auto &priceRef : VALUES) { const auto &priceStr = priceRef.get().toString(); - if (priceStr.length() >= n && iEquals(priceStr.substr(0, n), s)) { + if (priceStr.length() >= s.length() && iEquals(priceStr.substr(0, s.length()), s)) { return priceRef; } } - throw std::invalid_argument("Unknown candle price: " + s); + throw InvalidArgumentException("Unknown candle price: " + s); } /** @@ -163,8 +162,7 @@ struct DXFCPP_EXPORT CandlePrice : public CandleSymbolAttribute { * @param symbol candle symbol string. * @return candle symbol string with the normalized representation of the the candle price type attribute. */ - static std::string - normalizeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) { + static std::string normalizeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) { auto a = MarketEventSymbols::getAttributeStringByKey(symbol, ATTRIBUTE_KEY); if (!a) { @@ -174,7 +172,7 @@ struct DXFCPP_EXPORT CandlePrice : public CandleSymbolAttribute { try { auto other = parse(a.value()); - if (other == DEFAULT) { + if (other.get() == DEFAULT) { return MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY); } @@ -182,6 +180,8 @@ struct DXFCPP_EXPORT CandlePrice : public CandleSymbolAttribute { return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.get().toString()); } + return symbol; + } catch (const InvalidArgumentException &) { return symbol; } catch (const std::invalid_argument &) { return symbol; diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp index 5db0211e8..121618edf 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandlePriceLevel.hpp @@ -117,10 +117,11 @@ struct DXFCPP_EXPORT CandlePriceLevel : public CandleSymbolAttribute { * * @param value candle price level value. * @return candle price level with the given value and type. + * @throws InvalidArgumentException if value is incorrect */ static CandlePriceLevel valueOf(double value) { if (std::isinf(value) || (value == 0.0 && std::signbit(value))) { - throw std::invalid_argument("Incorrect candle price level: " + dxfcpp::toString(value)); + throw InvalidArgumentException("Incorrect candle price level: " + dxfcpp::toString(value)); } return std::isnan(value) ? DEFAULT : CandlePriceLevel(value); @@ -164,6 +165,8 @@ struct DXFCPP_EXPORT CandlePriceLevel : public CandleSymbolAttribute { return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.toString()); } + return symbol; + } catch (const InvalidArgumentException &) { return symbol; } catch (const std::invalid_argument &) { return symbol; diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp index 8e0d6b117..f22b722d1 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp @@ -113,14 +113,11 @@ struct DXFCPP_EXPORT CandleSession : public CandleSymbolAttribute { * * @param s The string representation of candle session attribute. * @return The candle session attribute (reference). - * @throws std::invalid_argument + * @throws InvalidArgumentException if argument is empty or invalid */ static std::reference_wrapper parse(const dxfcpp::StringLikeWrapper &s) { - auto sw = s.operator std::string_view(); - auto n = sw.length(); - - if (n == 0) { - throw std::invalid_argument("Missing candle session"); + if (s.empty()) { + throw InvalidArgumentException("Missing candle session"); } auto found = BY_STRING.find(s); @@ -132,12 +129,12 @@ struct DXFCPP_EXPORT CandleSession : public CandleSymbolAttribute { for (const auto &sessionRef : VALUES) { const auto &sessionStr = sessionRef.get().toString(); - if (sessionStr.length() >= n && iEquals(sessionStr.substr(0, n), s)) { + if (sessionStr.length() >= s.length() && iEquals(sessionStr.substr(0, s.length()), s)) { return sessionRef; } } - throw std::invalid_argument("Unknown candle session: " + s); + throw InvalidArgumentException("Unknown candle session: " + s); } /** @@ -169,7 +166,7 @@ struct DXFCPP_EXPORT CandleSession : public CandleSymbolAttribute { try { auto other = parse(a.value()); - if (other == DEFAULT) { + if (other.get() == DEFAULT) { return MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY); } @@ -177,6 +174,8 @@ struct DXFCPP_EXPORT CandleSession : public CandleSymbolAttribute { return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.get().toString()); } + return symbol; + } catch (const InvalidArgumentException &) { return symbol; } catch (const std::invalid_argument &) { return symbol; diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp index ba0b26a54..313d87dd2 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp @@ -273,6 +273,7 @@ struct DXFCPP_EXPORT CandleSymbol { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -281,7 +282,7 @@ struct DXFCPP_EXPORT CandleSymbol { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static CandleSymbol fromGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp index def9246f6..60c0536f2 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp @@ -158,7 +158,7 @@ struct DXFCPP_EXPORT CandleType { * distinguish it from CandleType::MINUTE that is represented as `"m"`. * * @return string representation of this candle price type. - * @throws std::invalid_argument if the string representation is invalid. + * @throws InvalidArgumentException if the string representation is invalid. */ const std::string &toString() const & noexcept { return string_; @@ -171,16 +171,14 @@ struct DXFCPP_EXPORT CandleType { * * @param s The string representation of candle type. * @return A candle type. + * @throws InvalidArgumentException if argument is empty or invalid */ static std::reference_wrapper parse(const dxfcpp::StringLikeWrapper &s) { - auto sw = s.operator std::string_view(); - auto n = sw.length(); - - if (n == 0) { - throw std::invalid_argument("Missing candle type"); + if (s.empty()) { + throw InvalidArgumentException("Missing candle type"); } - auto result = BY_STRING.find(sw); + auto result = BY_STRING.find(s); if (result != BY_STRING.end()) { return result->second; @@ -190,17 +188,17 @@ struct DXFCPP_EXPORT CandleType { const auto &name = typeRef.get().getName(); // Tick|TICK|tick, Minute|MINUTE|minute, Second|SECOND|second, etc - if (name.length() >= n && iEquals(name.substr(0, n), sw)) { + if (name.length() >= s.length() && iEquals(name.substr(0, s.length()), s)) { return typeRef; } // Ticks, Minutes, Seconds, etc - if (sw.ends_with("s") && iEquals(name, sw.substr(0, n - 1))) { + if (s.ends_with("s") && iEquals(name, s.substr(0, s.length() - 1))) { return typeRef; } } - throw std::invalid_argument("Unknown candle type: " + s); + throw InvalidArgumentException("Unknown candle type: " + s); } bool operator==(const CandleType &candleType) const noexcept { diff --git a/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp index abdb534a1..d40d7cf2c 100644 --- a/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp @@ -89,7 +89,7 @@ class DXFCPP_EXPORT AnalyticOrder final : public Order { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -106,6 +106,7 @@ class DXFCPP_EXPORT AnalyticOrder final : public Order { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp b/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp index acb69bf3b..042a007bd 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp @@ -107,7 +107,7 @@ class DXFCPP_EXPORT OptionSale final : public MarketEvent, public IndexedEvent { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -124,6 +124,7 @@ class DXFCPP_EXPORT OptionSale final : public MarketEvent, public IndexedEvent { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -409,12 +410,13 @@ class DXFCPP_EXPORT OptionSale final : public MarketEvent, public IndexedEvent { * * @param sequence the sequence. * @see ::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid sequence value = " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid sequence value = " + std::to_string(sequence)); } data_.timeSequence = orOp(andOp(data_.timeSequence, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/market/Order.hpp b/include/dxfeed_graal_cpp_api/event/market/Order.hpp index d0ac6bb4f..208ae0b16 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Order.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Order.hpp @@ -121,7 +121,7 @@ class DXFCPP_EXPORT Order : public OrderBase { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -138,6 +138,7 @@ class DXFCPP_EXPORT Order : public OrderBase { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp index 42f217f39..0b77c52f5 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp @@ -234,10 +234,11 @@ class DXFCPP_EXPORT OrderBase : public MarketEvent, public IndexedEvent { * Use OrderBase::setSource() after invocation of this method to set the desired value of source. * * @param index unique per-symbol index of this order. + * @throws InvalidArgumentException */ void setIndex(std::int64_t index) override { if (index < 0) { - throw std::invalid_argument("Negative index: " + std::to_string(index)); + throw InvalidArgumentException("Negative index: " + std::to_string(index)); } orderBaseData_.index = index; @@ -333,10 +334,11 @@ class DXFCPP_EXPORT OrderBase : public MarketEvent, public IndexedEvent { * @param sequence the sequence. * * @see OrderBase::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid sequence value = " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid sequence value = " + std::to_string(sequence)); } orderBaseData_.timeSequence = orOp(andOp(orderBaseData_.timeSequence, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp index 41a34497f..9efed430e 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp @@ -71,7 +71,7 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { auto n = name.length(); if (n == 0 || n > 4) { - throw std::invalid_argument("Source name must contain from 1 to 4 characters"); + throw InvalidArgumentException("Source name must contain from 1 to 4 characters"); } for (auto c : name) { @@ -87,12 +87,12 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { return; } - throw std::invalid_argument("Source name must contain only alphanumeric characters"); + throw InvalidArgumentException("Source name must contain only alphanumeric characters"); } static std::string decodeName(std::int32_t id) { if (id == 0) { - throw std::invalid_argument("Source name must contain from 1 to 4 characters"); + throw InvalidArgumentException("Source name must contain from 1 to 4 characters"); } std::string name(4, '\0'); @@ -130,7 +130,7 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { return PUB_SPREAD_ORDER; } - throw std::invalid_argument("Invalid order event type: " + eventType.getName()); + throw InvalidArgumentException("Invalid order event type: " + eventType.getName()); } /** diff --git a/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp index 506ede3de..068a02c82 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp @@ -156,7 +156,7 @@ class DXFCPP_EXPORT OtcMarketsOrder final : public Order { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -173,6 +173,7 @@ class DXFCPP_EXPORT OtcMarketsOrder final : public Order { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/Profile.hpp b/include/dxfeed_graal_cpp_api/event/market/Profile.hpp index 91064111f..16c00f7d8 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Profile.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Profile.hpp @@ -87,7 +87,7 @@ class DXFCPP_EXPORT Profile final : public MarketEvent, public LastingEvent { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -104,6 +104,7 @@ class DXFCPP_EXPORT Profile final : public MarketEvent, public LastingEvent { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/Quote.hpp b/include/dxfeed_graal_cpp_api/event/market/Quote.hpp index 68df6ad92..8d8ff6889 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Quote.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Quote.hpp @@ -80,7 +80,7 @@ class DXFCPP_EXPORT Quote final : public MarketEvent, public LastingEvent { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -97,6 +97,7 @@ class DXFCPP_EXPORT Quote final : public MarketEvent, public LastingEvent { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -153,12 +154,13 @@ class DXFCPP_EXPORT Quote final : public MarketEvent, public LastingEvent { * @param sequence The sequence. * * @see Quote::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid sequence value = " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid sequence value = " + std::to_string(sequence)); } data_.timeMillisSequence = orOp(andOp(data_.timeMillisSequence, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp index c41c13f84..ab943f027 100644 --- a/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp @@ -120,7 +120,7 @@ class DXFCPP_EXPORT SpreadOrder : public OrderBase { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -137,6 +137,7 @@ class DXFCPP_EXPORT SpreadOrder : public OrderBase { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/Summary.hpp b/include/dxfeed_graal_cpp_api/event/market/Summary.hpp index 6e0607da4..3db8194b6 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Summary.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Summary.hpp @@ -78,7 +78,7 @@ class DXFCPP_EXPORT Summary final : public MarketEvent, public LastingEvent { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -95,6 +95,7 @@ class DXFCPP_EXPORT Summary final : public MarketEvent, public LastingEvent { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp b/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp index 6e8553e1f..495d454ed 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp @@ -135,7 +135,7 @@ class DXFCPP_EXPORT TimeAndSale final : public MarketEvent, public TimeSeriesEve * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -152,6 +152,7 @@ class DXFCPP_EXPORT TimeAndSale final : public MarketEvent, public TimeSeriesEve * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -292,12 +293,13 @@ class DXFCPP_EXPORT TimeAndSale final : public MarketEvent, public TimeSeriesEve * * @param sequence the sequence. * @see ::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid sequence value = " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid sequence value = " + std::to_string(sequence)); } data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/market/Trade.hpp b/include/dxfeed_graal_cpp_api/event/market/Trade.hpp index 57e70d85f..0dd1f83ad 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Trade.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Trade.hpp @@ -92,7 +92,7 @@ class DXFCPP_EXPORT Trade final : public TradeBase { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -109,6 +109,7 @@ class DXFCPP_EXPORT Trade final : public TradeBase { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp b/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp index 14494ca23..d8e54ce2f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp @@ -192,12 +192,13 @@ class DXFCPP_EXPORT TradeBase : public MarketEvent, public LastingEvent { * * @param sequence the sequence. * @see TradeBase::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid sequence value = " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid sequence value = " + std::to_string(sequence)); } tradeBaseData_.timeSequence = orOp(andOp(tradeBaseData_.timeSequence, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp b/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp index 2fa8122e4..9ef8f435d 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp @@ -117,7 +117,7 @@ class DXFCPP_EXPORT TradeETH final : public TradeBase { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -134,6 +134,7 @@ class DXFCPP_EXPORT TradeETH final : public TradeBase { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/misc/Message.hpp b/include/dxfeed_graal_cpp_api/event/misc/Message.hpp index a1534bb17..38c8b3be8 100644 --- a/include/dxfeed_graal_cpp_api/event/misc/Message.hpp +++ b/include/dxfeed_graal_cpp_api/event/misc/Message.hpp @@ -56,7 +56,7 @@ class DXFCPP_EXPORT Message : public EventTypeWithSymbol { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -73,6 +73,7 @@ class DXFCPP_EXPORT Message : public EventTypeWithSymbol { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp b/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp index 1214828fd..ea5c1f420 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp @@ -95,7 +95,7 @@ class DXFCPP_EXPORT Greeks final : public MarketEvent, public TimeSeriesEvent, p * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -119,6 +119,7 @@ class DXFCPP_EXPORT Greeks final : public MarketEvent, public TimeSeriesEvent, p * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -219,12 +220,13 @@ class DXFCPP_EXPORT Greeks final : public MarketEvent, public TimeSeriesEvent, p * Changes @ref ::getSequence() "sequence number" of this event. * @param sequence the sequence. * @see ::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid value for argument `sequence`: " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); } data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/option/Series.hpp b/include/dxfeed_graal_cpp_api/event/option/Series.hpp index 0f168e9e5..46c26d65b 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Series.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Series.hpp @@ -110,7 +110,7 @@ class DXFCPP_EXPORT Series final : public MarketEvent, public IndexedEvent { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -127,6 +127,7 @@ class DXFCPP_EXPORT Series final : public MarketEvent, public IndexedEvent { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -324,12 +325,13 @@ class DXFCPP_EXPORT Series final : public MarketEvent, public IndexedEvent { * * @param sequence the sequence. * @see Series::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid value for argument `sequence`: " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); } data_.timeSequence = orOp(andOp(data_.timeSequence, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp b/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp index e9ef569dd..6643302c2 100644 --- a/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp @@ -109,7 +109,7 @@ class DXFCPP_EXPORT TheoPrice final : public MarketEvent, public TimeSeriesEvent * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -126,6 +126,7 @@ class DXFCPP_EXPORT TheoPrice final : public MarketEvent, public TimeSeriesEvent * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -226,12 +227,13 @@ class DXFCPP_EXPORT TheoPrice final : public MarketEvent, public TimeSeriesEvent * Changes @ref ::getSequence() "sequence number" of this event. * @param sequence the sequence. * @see ::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid value for argument `sequence`: " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); } data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp b/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp index dc483e3cb..80aad0b94 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp @@ -105,7 +105,7 @@ class DXFCPP_EXPORT Underlying final : public MarketEvent, public TimeSeriesEven * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static Ptr fromGraal(void *graalNative); @@ -122,6 +122,7 @@ class DXFCPP_EXPORT Underlying final : public MarketEvent, public TimeSeriesEven * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -222,12 +223,13 @@ class DXFCPP_EXPORT Underlying final : public MarketEvent, public TimeSeriesEven * Changes @ref ::getSequence() "sequence number" of this event. * @param sequence the sequence. * @see ::getSequence() + * @throws InvalidArgumentException */ void setSequence(std::int32_t sequence) { assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw std::invalid_argument("Invalid value for argument `sequence`: " + std::to_string(sequence)); + throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); } data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); diff --git a/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp b/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp new file mode 100644 index 000000000..2ced4912b --- /dev/null +++ b/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../internal/Conf.hpp" + +#include "../internal/Common.hpp" +#include "RuntimeException.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4275) + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +/** + * Thrown to indicate that a method has been passed an illegal or inappropriate argument. + */ +struct DXFCPP_EXPORT InvalidArgumentException : RuntimeException { + explicit InvalidArgumentException(const StringLikeWrapper &message, + const StringLikeWrapper &additionalStackTrace = ""); +}; + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index b97531ac8..c9e306711 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -18,11 +18,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include #include #include -#include -#include -#include #include -#include #include #include #include @@ -289,20 +285,7 @@ constexpr static std::int32_t getYearMonthDayByDayId(std::int32_t dayId) { return yyyy >= 0 ? yyyymmdd : -yyyymmdd; } -static std::int32_t getDayIdByYearMonthDay(std::int32_t year, std::int32_t month, std::int32_t day) { - if (month < 1 || month > 12) { - throw std::invalid_argument("invalid month " + std::to_string(month)); - } - - std::int32_t dayOfYear = DAY_OF_YEAR[month] + day - 1; - - if (month > 2 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) { - dayOfYear++; - } - - return year * 365 + math_util::div(year - 1, 4) - math_util::div(year - 1, 100) + math_util::div(year - 1, 400) + - dayOfYear - 719527; -} +static std::int32_t getDayIdByYearMonthDay(std::int32_t year, std::int32_t month, std::int32_t day); } // namespace day_util @@ -747,6 +730,24 @@ struct StringLikeWrapper { return size(); } + bool ends_with(const StringLikeWrapper &sw) const { + if (auto sv = std::get_if(&data_); sv) { + return sv->ends_with(sw); + } else { + return std::get(data_).ends_with(sw); + } + } + + std::string substr(std::string::size_type pos = 0, std::string::size_type count = std::string::npos) const { + if (auto sv = std::get_if(&data_); sv) { + auto sv2 = sv->substr(pos, count); + + return {sv2.data(), sv->size()}; + } else { + return std::get(data_).substr(pos, count); + } + } + bool operator==(const StringLikeWrapper &sw) const { return sw.operator std::string_view() == this->operator std::string_view(); } @@ -796,9 +797,8 @@ struct StringHash { }; namespace util { -inline void throwInvalidChar(char c, const std::string &name) { - throw std::invalid_argument("Invalid " + name + ": " + encodeChar(c)); -} + +inline void throwInvalidChar(char c, const std::string &name); inline void checkChar(char c, std::uint32_t mask, const std::string &name) { if ((andOp(c, ~mask)) != 0) { diff --git a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp index 74c5d5b00..eda13b86b 100644 --- a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp +++ b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp @@ -19,7 +19,7 @@ DXFCPP_BEGIN_NAMESPACE * * Some methods that are not marked `noexcept` may throw exceptions: * - * @throws std::invalid_argument if handle is invalid. + * @throws InvalidArgumentException if handle is invalid. * @throws JavaException if something happened with the dxFeed API backend * @throws GraalException if something happened with the GraalVM */ diff --git a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp index b929e38fb..77d88caab 100644 --- a/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/InstrumentProfile.hpp @@ -775,7 +775,7 @@ struct DXFCPP_EXPORT InstrumentProfile final : public RequireMakeShared fromGraal(void *list); }; diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXEndpoint.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXEndpoint.hpp index b294b9bc6..8fcf8f2d9 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXEndpoint.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXEndpoint.hpp @@ -28,7 +28,7 @@ namespace isolated::api::IsolatedDXEndpoint { * Calls the Graal SDK function `dxfg_DXEndpoint_close` in isolation. * * @param endpoint The endpoint's handle. - * @throws std::invalid_argument if endpoint handle is invalid. + * @throws InvalidArgumentException if endpoint handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -38,7 +38,7 @@ void /* int32_t */ close(/* dxfg_endpoint_t* */ const JavaObjectHandle & * Calls the Graal SDK function `dxfg_DXEndpoint_reconnect` in isolation. * * @param endpoint The endpoint's handle. - * @throws std::invalid_argument if endpoint handle is invalid. + * @throws InvalidArgumentException if endpoint handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -95,7 +95,7 @@ void reconnect(/* dxfg_endpoint_t* */ const JavaObjectHandle * Calls the Graal SDK function `dxfg_DXEndpoint_disconnect` in isolation. * * @param endpoint The endpoint's handle. - * @throws std::invalid_argument if endpoint handle is invalid. + * @throws InvalidArgumentException if endpoint handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -105,7 +105,7 @@ void disconnect(/* dxfg_endpoint_t* */ const JavaObjectHandle * * @param endpoint The endpoint's handle. * @return A set of event types. - * @throws std::invalid_argument if endpoint handle is invalid. + * @throws InvalidArgumentException if endpoint handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -223,7 +223,7 @@ void * /* dxfg_endpoint_builder_t* */ create(); * Calls the Graal SDK function `dxfg_DXEndpoint_Builder_withRole` in isolation. * @param builder The DXEndpoint::Builder's handle. * @param role The endpoint's role. - * @throws std::invalid_argument if DXEndpoint::Builder's handle is invalid. + * @throws InvalidArgumentException if DXEndpoint::Builder's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -239,7 +239,7 @@ withRole(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle &ev * * @param sub The subscription's handle. * @return `true` if subscription is closed. - * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws InvalidArgumentException if DXFeedSubscription's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -56,7 +56,7 @@ bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle /* dxfg_event_clazz_list_t* */ getEventTypes( * @param sub The subscription's handle. * @param eventType The type of event that is checked. * @return `true` if this subscription contains the corresponding event type. - * @throws std::invalid_argument if DXPublisherObservableSubscription's handle is invalid. + * @throws InvalidArgumentException if DXPublisherObservableSubscription's handle is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -57,7 +57,7 @@ bool /* int32_t */ containsEventType( * * @param sub The subscription's handle. * @param listener The listener's handle. - * @throws std::invalid_argument if DXPublisherObservableSubscription's or ObservableSubscriptionChangeListener's handle + * @throws InvalidArgumentException if DXPublisherObservableSubscription's or ObservableSubscriptionChangeListener's handle * is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. @@ -72,7 +72,7 @@ void /* int32_t */ addChangeListener( * * @param sub The subscription's handle. * @param listener The listener's handle. - * @throws std::invalid_argument if DXPublisherObservableSubscription's or ObservableSubscriptionChangeListener's handle + * @throws InvalidArgumentException if DXPublisherObservableSubscription's or ObservableSubscriptionChangeListener's handle * is invalid. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. diff --git a/include/dxfeed_graal_cpp_api/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp b/include/dxfeed_graal_cpp_api/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp index ca3a2c15b..c3535bfef 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp @@ -23,7 +23,7 @@ namespace isolated::api::IsolatedObservableSubscriptionChangeListener { * @param userData User data, which is placed each time as a callback parameter when called from listener. * @return The ObservableSubscriptionChangeListener's handle. * - * @throws std::invalid_argument if functionSymbolsAdded or functionSymbolsRemoved or functionSubscriptionClosed is + * @throws InvalidArgumentException if functionSymbolsAdded or functionSymbolsRemoved or functionSubscriptionClosed is * nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. diff --git a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp index 4f26195ac..401c8f884 100644 --- a/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/internal/IsolatedString.hpp @@ -19,7 +19,7 @@ namespace IsolatedString { * @param string The pointer to C-string * @return `true` if OK. * - * @throws std::invalid_argument if string is nullptr. + * @throws InvalidArgumentException if string is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -35,7 +35,7 @@ namespace IsolatedStringList { * @param stringList The pointer to dxFeed Graal SDK' string list. * @return `true` if OK. * - * @throws std::invalid_argument if stringList is nullptr. + * @throws InvalidArgumentException if stringList is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp index 6ad680278..23e8e635d 100644 --- a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -22,7 +22,7 @@ namespace isolated::promise::IsolatedPromise { * * @param promise The promise's handle. * @return `true` when computation has completed normally or exceptionally or was cancelled. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -33,7 +33,7 @@ bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise); * * @param promise The promise's handle. * @return `true` when computation has completed normally - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -44,7 +44,7 @@ bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise); * * @param promise The promise's handle. * @return `true` when computation has completed exceptionally or was cancelled. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -55,7 +55,7 @@ bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise); * * @param promise The promise's handle. * @return `true` when computation was cancelled. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -66,7 +66,7 @@ bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise); * * @param promise The promise's handle. * @return event by promise - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -77,7 +77,7 @@ std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_ev * * @param promise The promise's handle. * @return events by promise - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -88,7 +88,7 @@ std::vector> /* dxfg_event_type_list* */ getResults(/ * * @param promise The promise's handle. * @return exception by promise - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -98,7 +98,7 @@ JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* * Calls the Graal SDK function `dxfg_Promise_await` in isolation. * * @param promise The promise's handle. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -109,7 +109,7 @@ void /* int32_t */ await(/* dxfg_promise_t * */ void* promise); * * @param promise The promise's handle. * @param timeoutInMilliseconds The promise's timeout. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -121,7 +121,7 @@ void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t time * @param promise The promise's handle. * @param timeoutInMilliseconds The promise's timeout. * @return `true` if the computation has completed normally; `false` when wait timed out. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ @@ -131,7 +131,7 @@ bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, s * Calls the Graal SDK function `dxfg_Promise_cancel` in isolation. * * @param promise The promise's handle. - * @throws std::invalid_argument if promise handle is nullptr. + * @throws InvalidArgumentException if promise handle is nullptr. * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ diff --git a/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp b/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp index 5d3a54d88..3572f3a5b 100644 --- a/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp @@ -79,6 +79,7 @@ struct DXFCPP_EXPORT StringSymbol final { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -87,7 +88,7 @@ struct DXFCPP_EXPORT StringSymbol final { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException */ static StringSymbol fromGraal(void *graalNative); diff --git a/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp b/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp index 25e2c38c9..37bd05671 100644 --- a/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp +++ b/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp @@ -219,6 +219,7 @@ struct DXFCPP_EXPORT SymbolWrapper final { * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * * @param graalNative The pointer to the dxFeed Graal SDK structure. + * @throws InvalidArgumentException */ static void freeGraal(void *graalNative); @@ -227,7 +228,8 @@ struct DXFCPP_EXPORT SymbolWrapper final { * * @param graalNative The pointer to the dxFeed Graal SDK structure. * @return The object of current type. - * @throws std::invalid_argument + * @throws InvalidArgumentException + * @throws RuntimeException if symbol type is unknown */ static SymbolWrapper fromGraal(void *graalNative); diff --git a/src/api/DXEndpoint.cpp b/src/api/DXEndpoint.cpp index 7e64b5e89..2be43b6a0 100644 --- a/src/api/DXEndpoint.cpp +++ b/src/api/DXEndpoint.cpp @@ -120,7 +120,7 @@ std::unordered_map> DXEndpoint::Im std::shared_ptr DXEndpoint::create(void *endpointHandle, DXEndpoint::Role role, const std::unordered_map &properties) { if (endpointHandle == nullptr) { - throw std::invalid_argument("Unable to create DXEndpoint. The `endpointHandle` is nullptr"); + throw InvalidArgumentException("Unable to create DXEndpoint. The `endpointHandle` is nullptr"); } if constexpr (Debugger::isDebug) { diff --git a/src/api/osub/IndexedEventSubscriptionSymbol.cpp b/src/api/osub/IndexedEventSubscriptionSymbol.cpp index 3ed16136a..ffb973645 100644 --- a/src/api/osub/IndexedEventSubscriptionSymbol.cpp +++ b/src/api/osub/IndexedEventSubscriptionSymbol.cpp @@ -48,7 +48,7 @@ IndexedEventSubscriptionSymbol IndexedEventSubscriptionSymbol::fromGraal(void *g } if (graalNative == nullptr) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create IndexedEventSubscriptionSymbol. The `graalNative` parameter is nullptr"); } diff --git a/src/api/osub/TimeSeriesSubscriptionSymbol.cpp b/src/api/osub/TimeSeriesSubscriptionSymbol.cpp index 061c44041..6019c28ce 100644 --- a/src/api/osub/TimeSeriesSubscriptionSymbol.cpp +++ b/src/api/osub/TimeSeriesSubscriptionSymbol.cpp @@ -51,7 +51,7 @@ TimeSeriesSubscriptionSymbol TimeSeriesSubscriptionSymbol::fromGraal(void *graal } if (graalNative == nullptr) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create TimeSeriesSubscriptionSymbol. The `graalNative` parameter is nullptr"); } diff --git a/src/event/EventMapper.cpp b/src/event/EventMapper.cpp index 32add654a..e9a73983d 100644 --- a/src/event/EventMapper.cpp +++ b/src/event/EventMapper.cpp @@ -18,7 +18,7 @@ DXFCPP_BEGIN_NAMESPACE std::shared_ptr EventMapper::fromGraal(void *graalNativeEvent) { if (!graalNativeEvent) { - throw std::invalid_argument("The `graalNativeEvent` is nullptr"); + throw InvalidArgumentException("The `graalNativeEvent` is nullptr"); } // TODO: implement other types [EN-8235] @@ -34,7 +34,7 @@ std::shared_ptr EventMapper::fromGraal(void *graalNativeEvent) { case DXFG_EVENT_CANDLE: return Candle::fromGraal(e); case DXFG_EVENT_DAILY_CANDLE: - throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); case DXFG_EVENT_UNDERLYING: return Underlying::fromGraal(e); case DXFG_EVENT_THEO_PRICE: @@ -44,13 +44,13 @@ std::shared_ptr EventMapper::fromGraal(void *graalNativeEvent) { case DXFG_EVENT_TRADE_ETH: return TradeETH::fromGraal(e); case DXFG_EVENT_CONFIGURATION: - throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); case DXFG_EVENT_MESSAGE: return Message::fromGraal(e); case DXFG_EVENT_TIME_AND_SALE: return TimeAndSale::fromGraal(e); case DXFG_EVENT_ORDER_BASE: - throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); case DXFG_EVENT_ORDER: return Order::fromGraal(e); case DXFG_EVENT_ANALYTIC_ORDER: @@ -64,7 +64,7 @@ std::shared_ptr EventMapper::fromGraal(void *graalNativeEvent) { case DXFG_EVENT_OPTION_SALE: return OptionSale::fromGraal(e); default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Unknown event type: " + std::to_string(static_cast(e->clazz))); } } @@ -115,7 +115,7 @@ void EventMapper::freeGraal(void *graalNativeEvent) { break; case DXFG_EVENT_DAILY_CANDLE: - throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); case DXFG_EVENT_UNDERLYING: Underlying::freeGraal(e); @@ -134,7 +134,7 @@ void EventMapper::freeGraal(void *graalNativeEvent) { break; case DXFG_EVENT_CONFIGURATION: - throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); case DXFG_EVENT_MESSAGE: Message::freeGraal(e); @@ -145,7 +145,7 @@ void EventMapper::freeGraal(void *graalNativeEvent) { break; case DXFG_EVENT_ORDER_BASE: - throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); case DXFG_EVENT_ORDER: Order::freeGraal(e); @@ -172,7 +172,7 @@ void EventMapper::freeGraal(void *graalNativeEvent) { break; default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); + throw InvalidArgumentException("Unknown event type: " + std::to_string(static_cast(e->clazz))); } } diff --git a/src/event/candle/Candle.cpp b/src/event/candle/Candle.cpp index 96bb3862e..d25af22e5 100644 --- a/src/event/candle/Candle.cpp +++ b/src/event/candle/Candle.cpp @@ -84,11 +84,11 @@ void Candle::freeGraalData(void *graalNative) noexcept { std::shared_ptr Candle::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Candle. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Candle. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_CANDLE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Candle. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_CANDLE)))); @@ -120,7 +120,7 @@ void Candle::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_CANDLE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Candle's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_CANDLE)))); diff --git a/src/event/market/AnalyticOrder.cpp b/src/event/market/AnalyticOrder.cpp index fa70aa55a..4df5b1bc5 100644 --- a/src/event/market/AnalyticOrder.cpp +++ b/src/event/market/AnalyticOrder.cpp @@ -49,11 +49,11 @@ void AnalyticOrder::fillGraalData(void *graalNative) const noexcept { std::shared_ptr AnalyticOrder::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create AnalyticOrder. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create AnalyticOrder. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_ANALYTIC_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create AnalyticOrder. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_ANALYTIC_ORDER)))); @@ -92,7 +92,7 @@ void AnalyticOrder::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_ANALYTIC_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free AnalyticOrder's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_ANALYTIC_ORDER)))); diff --git a/src/event/market/OptionSale.cpp b/src/event/market/OptionSale.cpp index 0363d90e1..9c17558c0 100644 --- a/src/event/market/OptionSale.cpp +++ b/src/event/market/OptionSale.cpp @@ -90,11 +90,11 @@ void OptionSale::freeGraalData(void *graalNative) noexcept { std::shared_ptr OptionSale::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create OptionSale. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create OptionSale. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_OPTION_SALE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Order. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_OPTION_SALE)))); diff --git a/src/event/market/Order.cpp b/src/event/market/Order.cpp index 0cd045a49..8fa1ea2a2 100644 --- a/src/event/market/Order.cpp +++ b/src/event/market/Order.cpp @@ -55,11 +55,11 @@ void Order::freeGraalData(void *graalNative) noexcept { std::shared_ptr Order::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Order. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Order. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Order. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_ORDER)))); @@ -94,7 +94,7 @@ void Order::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Order's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_ORDER)))); diff --git a/src/event/market/OtcMarketsOrder.cpp b/src/event/market/OtcMarketsOrder.cpp index 14e4b916b..11b9d5196 100644 --- a/src/event/market/OtcMarketsOrder.cpp +++ b/src/event/market/OtcMarketsOrder.cpp @@ -47,11 +47,11 @@ void OtcMarketsOrder::fillGraalData(void *graalNative) const noexcept { OtcMarketsOrder::Ptr OtcMarketsOrder::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create OtcMarketsOrder. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create OtcMarketsOrder. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_OTC_MARKETS_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create OtcMarketsOrder. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_OTC_MARKETS_ORDER)))); @@ -89,7 +89,7 @@ void OtcMarketsOrder::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_OTC_MARKETS_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free OtcMarketsOrder's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_OTC_MARKETS_ORDER)))); diff --git a/src/event/market/Profile.cpp b/src/event/market/Profile.cpp index 764958f48..785dfb39c 100644 --- a/src/event/market/Profile.cpp +++ b/src/event/market/Profile.cpp @@ -92,11 +92,11 @@ void Profile::freeGraalData(void *graalNative) noexcept { std::shared_ptr Profile::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Profile. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Profile. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_PROFILE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Profile. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_PROFILE)))); @@ -143,7 +143,7 @@ void Profile::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_PROFILE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Profile's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_PROFILE)))); diff --git a/src/event/market/Quote.cpp b/src/event/market/Quote.cpp index 94c87c47e..797d015f3 100644 --- a/src/event/market/Quote.cpp +++ b/src/event/market/Quote.cpp @@ -113,11 +113,11 @@ std::string Quote::toString() const { std::shared_ptr Quote::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Quote. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Quote. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != DXFG_EVENT_QUOTE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Quote. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_QUOTE)))); @@ -148,7 +148,7 @@ void Quote::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_QUOTE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Quote's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_QUOTE)))); diff --git a/src/event/market/SpreadOrder.cpp b/src/event/market/SpreadOrder.cpp index 4e517276e..bd7cd3a14 100644 --- a/src/event/market/SpreadOrder.cpp +++ b/src/event/market/SpreadOrder.cpp @@ -55,11 +55,11 @@ void SpreadOrder::freeGraalData(void *graalNative) noexcept { std::shared_ptr SpreadOrder::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create SpreadOrder. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create SpreadOrder. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != DXFG_EVENT_SPREAD_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create SpreadOrder. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_SPREAD_ORDER)))); @@ -94,7 +94,7 @@ void SpreadOrder::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != DXFG_EVENT_SPREAD_ORDER) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free SpreadOrder's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_SPREAD_ORDER)))); diff --git a/src/event/market/Summary.cpp b/src/event/market/Summary.cpp index 5ad82f3de..febfacc5b 100644 --- a/src/event/market/Summary.cpp +++ b/src/event/market/Summary.cpp @@ -67,11 +67,11 @@ void Summary::fillGraalData(void *graalNative) const noexcept { std::shared_ptr Summary::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Summary. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Summary. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_SUMMARY) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Summary. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_SUMMARY)))); @@ -115,7 +115,7 @@ void Summary::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_SUMMARY) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Summary's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_SUMMARY)))); diff --git a/src/event/market/TimeAndSale.cpp b/src/event/market/TimeAndSale.cpp index 748befb55..6f7bd7521 100644 --- a/src/event/market/TimeAndSale.cpp +++ b/src/event/market/TimeAndSale.cpp @@ -89,11 +89,11 @@ void TimeAndSale::freeGraalData(void *graalNative) noexcept { std::shared_ptr TimeAndSale::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create TimeAndSale. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create TimeAndSale. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_TIME_AND_SALE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create TimeAndSale. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_TIME_AND_SALE)))); @@ -139,7 +139,7 @@ void TimeAndSale::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_TIME_AND_SALE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free TimeAndSale's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_TIME_AND_SALE)))); diff --git a/src/event/market/Trade.cpp b/src/event/market/Trade.cpp index 7f1b297e9..67986ce72 100644 --- a/src/event/market/Trade.cpp +++ b/src/event/market/Trade.cpp @@ -42,11 +42,11 @@ void Trade::fillGraalData(void *graalNative) const noexcept { std::shared_ptr Trade::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Trade. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Trade. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_TRADE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Trade. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_TRADE)))); @@ -81,7 +81,7 @@ void Trade::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_TRADE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Trade's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_TRADE)))); diff --git a/src/event/market/TradeETH.cpp b/src/event/market/TradeETH.cpp index f9104e2dc..f8fbb8dca 100644 --- a/src/event/market/TradeETH.cpp +++ b/src/event/market/TradeETH.cpp @@ -42,11 +42,11 @@ void TradeETH::fillGraalData(void *graalNative) const noexcept { std::shared_ptr TradeETH::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create TradeETH. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create TradeETH. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_TRADE_ETH) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create TradeETH. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_TRADE_ETH)))); @@ -81,7 +81,7 @@ void TradeETH::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_TRADE_ETH) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free TradeETH's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_TRADE_ETH)))); diff --git a/src/event/misc/Message.cpp b/src/event/misc/Message.cpp index 5c0965ac1..9d2650a00 100644 --- a/src/event/misc/Message.cpp +++ b/src/event/misc/Message.cpp @@ -65,11 +65,11 @@ void Message::freeGraalData(void *graalNative) noexcept { std::shared_ptr Message::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Message. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Message. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_MESSAGE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Message. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_MESSAGE)))); @@ -100,7 +100,7 @@ void Message::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_MESSAGE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Message's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_MESSAGE)))); diff --git a/src/event/option/Greeks.cpp b/src/event/option/Greeks.cpp index 220dafa4f..a51a7c05e 100644 --- a/src/event/option/Greeks.cpp +++ b/src/event/option/Greeks.cpp @@ -65,11 +65,11 @@ void Greeks::fillGraalData(void *graalNative) const noexcept { std::shared_ptr Greeks::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Greeks. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Greeks. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_GREEKS) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Greeks. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_GREEKS)))); @@ -111,7 +111,7 @@ void Greeks::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_GREEKS) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Greeks's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_GREEKS)))); diff --git a/src/event/option/Series.cpp b/src/event/option/Series.cpp index 729039f18..e0be71656 100644 --- a/src/event/option/Series.cpp +++ b/src/event/option/Series.cpp @@ -69,11 +69,11 @@ void Series::fillGraalData(void *graalNative) const noexcept { std::shared_ptr Series::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Series. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Series. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_SERIES) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Series. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_SERIES)))); @@ -115,7 +115,7 @@ void Series::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_SERIES) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Series's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_SERIES)))); diff --git a/src/event/option/TheoPrice.cpp b/src/event/option/TheoPrice.cpp index 408d63e8e..1e69b1810 100644 --- a/src/event/option/TheoPrice.cpp +++ b/src/event/option/TheoPrice.cpp @@ -63,11 +63,11 @@ void TheoPrice::fillGraalData(void *graalNative) const noexcept { std::shared_ptr TheoPrice::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create TheoPrice. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create TheoPrice. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_THEO_PRICE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create TheoPrice. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_THEO_PRICE)))); @@ -108,7 +108,7 @@ void TheoPrice::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_THEO_PRICE) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free TheoPrice's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_THEO_PRICE)))); diff --git a/src/event/option/Underlying.cpp b/src/event/option/Underlying.cpp index d509aaa02..00c2245b0 100644 --- a/src/event/option/Underlying.cpp +++ b/src/event/option/Underlying.cpp @@ -63,11 +63,11 @@ void Underlying::fillGraalData(void *graalNative) const noexcept { std::shared_ptr Underlying::fromGraal(void *graalNative) { if (!graalNative) { - throw std::invalid_argument("Unable to create Underlying. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create Underlying. The `graalNative` parameter is nullptr"); } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_UNDERLYING) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to create Underlying. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_UNDERLYING)))); @@ -109,7 +109,7 @@ void Underlying::freeGraal(void *graalNative) { } if (static_cast(graalNative)->clazz != dxfg_event_clazz_t::DXFG_EVENT_UNDERLYING) { - throw std::invalid_argument( + throw InvalidArgumentException( fmt::format("Unable to free Underlying's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_UNDERLYING)))); diff --git a/src/exceptions/InvalidArgumentException.cpp b/src/exceptions/InvalidArgumentException.cpp new file mode 100644 index 000000000..96575ef46 --- /dev/null +++ b/src/exceptions/InvalidArgumentException.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +InvalidArgumentException::InvalidArgumentException(const StringLikeWrapper &message, + const StringLikeWrapper &additionalStackTrace) + : RuntimeException(message, additionalStackTrace) { +} + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/internal/Common.cpp b/src/internal/Common.cpp index 3fd6b42ae..4852f0f76 100644 --- a/src/internal/Common.cpp +++ b/src/internal/Common.cpp @@ -5,3 +5,32 @@ #include #include + +DXFCPP_BEGIN_NAMESPACE + +namespace day_util { +std::int32_t getDayIdByYearMonthDay(std::int32_t year, std::int32_t month, std::int32_t day) { + if (month < 1 || month > 12) { + throw InvalidArgumentException("invalid month " + std::to_string(month)); + } + + std::int32_t dayOfYear = DAY_OF_YEAR[month] + day - 1; + + if (month > 2 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) { + dayOfYear++; + } + + return year * 365 + math_util::div(year - 1, 4) - math_util::div(year - 1, 100) + math_util::div(year - 1, 400) + + dayOfYear - 719527; +} +} // namespace day_util + +namespace util { + +inline void throwInvalidChar(char c, const std::string &name) { + throw InvalidArgumentException("Invalid " + name + ": " + encodeChar(c)); +} + +} + +DXFCPP_END_NAMESPACE diff --git a/src/ipf/live/InstrumentProfileConnection.cpp b/src/ipf/live/InstrumentProfileConnection.cpp index be34bc180..dd2e420e3 100644 --- a/src/ipf/live/InstrumentProfileConnection.cpp +++ b/src/ipf/live/InstrumentProfileConnection.cpp @@ -66,7 +66,7 @@ InstrumentProfileConnection::createConnection(const std::string &address, std::shared_ptr connection(new InstrumentProfileConnection{}); if (!collector->handle_) { - throw std::invalid_argument("The collector's handle is invalid"); + throw InvalidArgumentException("The collector's handle is invalid"); } connection->id_ = diff --git a/src/isolated/api/IsolatedDXEndpoint.cpp b/src/isolated/api/IsolatedDXEndpoint.cpp index c2dd3aadf..c12140b88 100644 --- a/src/isolated/api/IsolatedDXEndpoint.cpp +++ b/src/isolated/api/IsolatedDXEndpoint.cpp @@ -13,7 +13,7 @@ namespace isolated::api::IsolatedDXEndpoint { void /* int32_t */ close(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_close`. The `endpoint` handle is invalid"); } @@ -23,7 +23,7 @@ close(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoin void /* int32_t */ closeAndAwaitTermination(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_closeAndAwaitTermination`. The `endpoint` handle is invalid"); } @@ -34,7 +34,7 @@ closeAndAwaitTermination(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint, std::string_view user) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_user`. The `endpoint` handle is invalid"); } @@ -45,7 +45,7 @@ void /* int32_t */ user(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint, std::string_view password) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_password`. The `endpoint` handle is invalid"); } @@ -55,7 +55,7 @@ void /* int32_t */ password(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint, std::string_view address) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_connect`. The `endpoint` handle is invalid"); } @@ -65,7 +65,7 @@ void connect(/* dxfg_endpoint_t* */ const JavaObjectHandle & void reconnect(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_reconnect`. The `endpoint` handle is invalid"); } @@ -74,7 +74,7 @@ void reconnect(/* dxfg_endpoint_t* */ const JavaObjectHandle void disconnect(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_disconnect`. The `endpoint` handle is invalid"); } @@ -83,7 +83,7 @@ void disconnect(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_disconnectAndClear`. The `endpoint` handle is invalid"); } @@ -93,7 +93,7 @@ void disconnectAndClear(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_awaitProcessed`. The `endpoint` handle is invalid"); } @@ -103,7 +103,7 @@ void awaitProcessed(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_awaitNotConnected`. The `endpoint` handle is invalid"); } @@ -113,7 +113,7 @@ void awaitNotConnected(/* dxfg_endpoint_t* */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument("Unable to get state. The `endpoint` handle is invalid"); + throw InvalidArgumentException("Unable to get state. The `endpoint` handle is invalid"); } return graalStateToState(runGraalFunctionAndThrowIfLessThanZero(dxfg_DXEndpoint_getState, @@ -126,11 +126,11 @@ void addStateChangeListener( &listener) { if (!endpoint) { - throw std::invalid_argument("Unable to add DXEndpointStateChangeListener. The `endpoint` handle is invalid"); + throw InvalidArgumentException("Unable to add DXEndpointStateChangeListener. The `endpoint` handle is invalid"); } if (!listener) { - throw std::invalid_argument("Unable to add DXEndpointStateChangeListener. The `listener` handle is invalid"); + throw InvalidArgumentException("Unable to add DXEndpointStateChangeListener. The `listener` handle is invalid"); } runGraalFunctionAndThrowIfLessThanZero(dxfg_DXEndpoint_addStateChangeListener, @@ -144,11 +144,11 @@ void removeStateChangeListener( &listener) { if (!endpoint) { - throw std::invalid_argument("Unable to remove DXEndpointStateChangeListener. The `endpoint` handle is invalid"); + throw InvalidArgumentException("Unable to remove DXEndpointStateChangeListener. The `endpoint` handle is invalid"); } if (!listener) { - throw std::invalid_argument("Unable to remove DXEndpointStateChangeListener. The `listener` handle is invalid"); + throw InvalidArgumentException("Unable to remove DXEndpointStateChangeListener. The `listener` handle is invalid"); } runGraalFunctionAndThrowIfLessThanZero(dxfg_DXEndpoint_removeStateChangeListener, @@ -158,7 +158,7 @@ void removeStateChangeListener( void * /* dxfg_feed_t* */ getFeed(/* dxfg_endpoint_t * */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_getFeed`. The `endpoint` handle is invalid"); } @@ -169,7 +169,7 @@ void * /* dxfg_feed_t* */ getFeed(/* dxfg_endpoint_t * */ const JavaObjectHandle void * /* dxfg_publisher_t* */ getPublisher(/* dxfg_endpoint_t * */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_getPublisher`. The `endpoint` handle is invalid"); } @@ -180,7 +180,7 @@ getPublisher(/* dxfg_endpoint_t * */ const JavaObjectHandle /* dxfg_event_clazz_list_t* */ std::unordered_set getEventTypes(/* dxfg_endpoint_t * */ const JavaObjectHandle &endpoint) { if (!endpoint) { - throw std::invalid_argument("Unable to retrieve event types. The `endpoint` handle is invalid"); + throw InvalidArgumentException("Unable to retrieve event types. The `endpoint` handle is invalid"); } std::unordered_set result{}; @@ -233,7 +233,7 @@ void /* int32_t */ withRole(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle &builder, /* dxfg_endpoint_role_t */ dxfcpp::DXEndpoint::Role role) { if (!builder) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_Builder_withRole`. The `builder` handle is invalid"); } @@ -246,7 +246,7 @@ void /* int32_t */ withProperty(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle &builder, std::string_view key, std::string_view value) { if (!builder) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_Builder_withProperty`. The `builder` handle is invalid"); } @@ -260,7 +260,7 @@ void /* int32_t */ withProperties(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle &builder, std::string_view filePath) { if (!builder) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_Builder_withProperties`. The `builder` handle is invalid"); } @@ -273,7 +273,7 @@ bool /* int32_t */ supportsProperty(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle &builder, std::string_view key) { if (!builder) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_Builder_supportsProperty`. The `builder` handle is invalid"); } @@ -286,7 +286,7 @@ supportsProperty(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle &builder) { if (!builder) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXEndpoint_Builder_build`. The `builder` handle is invalid"); } @@ -299,7 +299,7 @@ build(/* dxfg_endpoint_builder_t * */ const JavaObjectHandle create(void *userFunc, void *userData) { if (!userFunc) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create DXEndpointStateChangeListener. The `userFunc` parameter is nullptr"); } diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp index 1358bd752..34bb5ff5e 100644 --- a/src/isolated/api/IsolatedDXFeed.cpp +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -15,7 +15,7 @@ namespace isolated::api::IsolatedDXFeed { /* dxfg_symbol_t * */ const SymbolWrapper &symbol, std::int64_t fromTime, std::int64_t toTime) { if (!feed) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeed_getTimeSeriesPromise`. The `feed` handle is invalid"); } diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 7424a7483..0a784cef3 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -18,7 +18,7 @@ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &eventClassList) { if (!eventClassList) { - throw std::invalid_argument("The eventClassList is nullptr"); + throw InvalidArgumentException("The eventClassList is nullptr"); } return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( @@ -27,7 +27,7 @@ create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &ev bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_isClosed`. The `sub` handle is invalid"); } @@ -37,7 +37,7 @@ bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_close`. The `sub` handle is invalid"); } @@ -47,7 +47,7 @@ void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_clear`. The `sub` handle is invalid"); } @@ -58,7 +58,7 @@ void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_getSymbols`. The `sub` handle is invalid"); } @@ -75,7 +75,7 @@ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_getDecoratedSymbols`. The `sub` handle is invalid"); } @@ -92,12 +92,12 @@ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void *symbols) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The `sub` handle is invalid"); } if (!symbols) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The " "`symbols` is nullptr"); } @@ -109,12 +109,12 @@ void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void *symbol) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The `sub` handle is invalid"); } if (!symbol) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The " "`symbol` is nullptr"); } @@ -126,12 +126,12 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void *symbols) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The `sub` handle is invalid"); } if (!symbols) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The " "`symbols` is nullptr"); } @@ -143,12 +143,12 @@ void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void *symbol) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The `sub` handle is invalid"); } if (!symbol) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The " "`symbol` is nullptr"); } @@ -160,12 +160,12 @@ void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHand void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void *symbols) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The `sub` handle is invalid"); } if (!symbols) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The " "`symbols` is nullptr"); } @@ -177,7 +177,7 @@ void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHan /* dxfg_time_period_t* */ JavaObjectHandle getAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_getAggregationPeriod`. The `sub` handle is invalid"); } @@ -188,12 +188,12 @@ getAggregationPeriod(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_time_period_t * */ const JavaObjectHandle &period) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_setAggregationPeriod`. The `sub` handle is invalid"); } if (!period) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setAggregationPeriod`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_setAggregationPeriod`. The " "`period` handle is invalid"); } @@ -206,12 +206,12 @@ void /* int32_t */ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The `sub` handle is invalid"); } if (!listener) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The " "`listener` handle is invalid"); } @@ -225,12 +225,12 @@ void /* int32_t */ addChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The `sub` handle is invalid"); } if (!listener) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The " "`listener` handle is invalid"); } @@ -244,12 +244,12 @@ void /* int32_t */ removeChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener) { if (!sub) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. " "The `sub` handle is invalid"); } if (!listener) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. The " "`listener` handle is invalid"); } @@ -260,7 +260,7 @@ void /* int32_t */ removeChangeListener( std::int32_t getEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_getEventsBatchLimit`. " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_getEventsBatchLimit`. " "The `sub` handle is invalid"); } @@ -271,7 +271,7 @@ std::int32_t getEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHan /* int32_t */ void setEventsBatchLimit(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, std::int32_t eventsBatchLimit) { if (!sub) { - throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setEventsBatchLimit`. " + throw InvalidArgumentException("Unable to execute function `dxfg_DXFeedSubscription_setEventsBatchLimit`. " "The `sub` handle is invalid"); } @@ -284,7 +284,7 @@ namespace DXFeedEventListener { JavaObjectHandle /* dxfg_feed_event_listener_t* */ create(/* dxfg_feed_event_listener_function */ void *userFunc, void *userData) { if (!userFunc) { - throw std::invalid_argument("Unable to create DXFeedEventListener. The `userFunc` parameter is nullptr"); + throw InvalidArgumentException("Unable to create DXFeedEventListener. The `userFunc` parameter is nullptr"); } return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( diff --git a/src/isolated/api/IsolatedDXPublisher.cpp b/src/isolated/api/IsolatedDXPublisher.cpp index 76139e832..bb01e17be 100644 --- a/src/isolated/api/IsolatedDXPublisher.cpp +++ b/src/isolated/api/IsolatedDXPublisher.cpp @@ -14,12 +14,12 @@ namespace isolated::api::IsolatedDXPublisher { void /* int32_t */ publishEvents(/* dxfg_publisher_t * */ const JavaObjectHandle &publisher, /* dxfg_event_type_list * */ void *events) { if (!publisher) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXPublisher_publishEvents`. The `publisher` handle is invalid"); } if (!events) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXPublisher_publishEvents`. The `events` is nullptr"); } @@ -32,7 +32,7 @@ JavaObjectHandle /* dxfg_observable_subscript getSubscription(/* dxfg_publisher_t * */ const JavaObjectHandle &publisher, /* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { if (!publisher) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_DXPublisher_getSubscription`. The `publisher` handle is invalid"); } diff --git a/src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp b/src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp index 6a3cc3b49..116b9c7bb 100644 --- a/src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp +++ b/src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp @@ -13,7 +13,7 @@ namespace isolated::api::IsolatedDXPublisherObservableSubscription { bool /* int32_t */ isClosed(/* dxfg_observable_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_ObservableSubscription_isClosed`. The `sub` handle is invalid"); } @@ -24,7 +24,7 @@ isClosed(/* dxfg_observable_subscription_t * */ const JavaObjectHandle /* dxfg_event_clazz_list_t* */ getEventTypes( /* dxfg_observable_subscription_t * */ const JavaObjectHandle &sub) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_ObservableSubscription_getEventTypes`. The `sub` handle is invalid"); } @@ -53,7 +53,7 @@ bool /* int32_t */ containsEventType( /* dxfg_observable_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_ObservableSubscription_containsEventType`. The `sub` handle is invalid"); } @@ -67,12 +67,12 @@ void /* int32_t */ addChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener) { if (!sub) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_ObservableSubscription_addChangeListener`. The `sub` handle is invalid"); } if (!listener) { - throw std::invalid_argument("Unable to execute function `dxfg_ObservableSubscription_addChangeListener`. The " + throw InvalidArgumentException("Unable to execute function `dxfg_ObservableSubscription_addChangeListener`. The " "`listener` handle is invalid"); } @@ -86,12 +86,12 @@ void /* int32_t */ removeChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener) { if (!sub) { - throw std::invalid_argument("Unable to execute function `dxfg_ObservableSubscription_removeChangeListener`. " + throw InvalidArgumentException("Unable to execute function `dxfg_ObservableSubscription_removeChangeListener`. " "The `sub` handle is invalid"); } if (!listener) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_ObservableSubscription_removeChangeListener`. The " "`listener` handle is invalid"); } diff --git a/src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp b/src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp index 45b2f7352..2853efcc4 100644 --- a/src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp +++ b/src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp @@ -16,17 +16,17 @@ create(/* dxfg_ObservableSubscriptionChangeListener_function_symbolsAdded */ voi /* dxfg_ObservableSubscriptionChangeListener_function_subscriptionClosed */ void *functionSubscriptionClosed, void *userData) { if (!functionSymbolsAdded) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create ObservableSubscriptionChangeListener. The `functionSymbolsAdded` parameter is nullptr"); } if (!functionSymbolsRemoved) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create ObservableSubscriptionChangeListener. The `functionSymbolsRemoved` parameter is nullptr"); } if (!functionSubscriptionClosed) { - throw std::invalid_argument("Unable to create ObservableSubscriptionChangeListener. The " + throw InvalidArgumentException("Unable to create ObservableSubscriptionChangeListener. The " "`functionSubscriptionClosed` parameter is nullptr"); } diff --git a/src/isolated/auth/IsolatedAuthToken.cpp b/src/isolated/auth/IsolatedAuthToken.cpp index c678e1971..b07b49ea9 100644 --- a/src/isolated/auth/IsolatedAuthToken.cpp +++ b/src/isolated/auth/IsolatedAuthToken.cpp @@ -65,7 +65,7 @@ createCustomToken(/* const char* */ const StringLikeWrapper &scheme, /* const char* */ std::string getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { if (!authToken) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_AuthToken_getHttpAuthorization`. The `authToken` handle is invalid"); } @@ -81,7 +81,7 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle /// dxfg_AuthToken_getUser /* const char* */ std::string getUser(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { if (!authToken) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_AuthToken_getUser`. The `authToken` handle is invalid"); } @@ -97,7 +97,7 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle /// dxfg_AuthToken_getPassword /* const char* */ std::string getPassword(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { if (!authToken) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_AuthToken_getPassword`. The `authToken` handle is invalid"); } @@ -113,7 +113,7 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle /// dxfg_AuthToken_getScheme /* const char* */ std::string getScheme(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { if (!authToken) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_AuthToken_getScheme`. The `authToken` handle is invalid"); } @@ -129,7 +129,7 @@ getHttpAuthorization(/* dxfg_auth_token_t* */ const JavaObjectHandle /// dxfg_AuthToken_getValue /* const char* */ std::string getValue(/* dxfg_auth_token_t* */ const JavaObjectHandle &authToken) { if (!authToken) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_AuthToken_getValue`. The `authToken` handle is invalid"); } diff --git a/src/isolated/internal/IsolatedObject.cpp b/src/isolated/internal/IsolatedObject.cpp index 516cf81a6..543451820 100644 --- a/src/isolated/internal/IsolatedObject.cpp +++ b/src/isolated/internal/IsolatedObject.cpp @@ -15,7 +15,7 @@ namespace IsolatedObject { /// dxfg_Object_toString /* const char* */ std::string toString(/* dxfg_java_object_handler* */ void *object) { if (!object) { - throw std::invalid_argument("Unable to execute function `dxfg_Object_toString`. The `object` is null"); + throw InvalidArgumentException("Unable to execute function `dxfg_Object_toString`. The `object` is null"); } auto value = @@ -30,11 +30,11 @@ namespace IsolatedObject { /// dxfg_Object_equals std::int32_t equals(/* dxfg_java_object_handler* */ void *object, /* dxfg_java_object_handler* */ void *other) { if (!object) { - throw std::invalid_argument("Unable to execute function `dxfg_Object_equals`. The `object` is null"); + throw InvalidArgumentException("Unable to execute function `dxfg_Object_equals`. The `object` is null"); } if (!other) { - throw std::invalid_argument("Unable to execute function `dxfg_Object_equals`. The `other` is null"); + throw InvalidArgumentException("Unable to execute function `dxfg_Object_equals`. The `other` is null"); } return runGraalFunctionAndThrowIfMinusMin(dxfg_Object_equals, static_cast(object), @@ -44,7 +44,7 @@ std::int32_t equals(/* dxfg_java_object_handler* */ void *object, /* dxfg_java_o /// dxfg_Object_hashCode /* int32_t */ std::size_t hashCode(/* dxfg_java_object_handler* */ void *object) { if (!object) { - throw std::invalid_argument("Unable to execute function `dxfg_Object_hashCode`. The `object` is null"); + throw InvalidArgumentException("Unable to execute function `dxfg_Object_hashCode`. The `object` is null"); } return static_cast( diff --git a/src/isolated/internal/IsolatedString.cpp b/src/isolated/internal/IsolatedString.cpp index 418af0e42..9f6bcf4c0 100644 --- a/src/isolated/internal/IsolatedString.cpp +++ b/src/isolated/internal/IsolatedString.cpp @@ -14,7 +14,7 @@ namespace IsolatedString { bool release(const char *string) { if (!string) { - throw std::invalid_argument("Unable to execute function `dxfg_String_release`. The `string` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_String_release`. The `string` is nullptr"); } return runGraalFunctionAndThrowIfLessThanZero(dxfg_String_release, string) == 0; @@ -30,7 +30,7 @@ namespace IsolatedStringList { bool release(/* dxfg_string_list* */ void *stringList) { if (!stringList) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_CList_String_release`. The `stringList` is nullptr"); } diff --git a/src/isolated/internal/IsolatedTimeFormat.cpp b/src/isolated/internal/IsolatedTimeFormat.cpp index e09ccdb7e..8a087b07c 100644 --- a/src/isolated/internal/IsolatedTimeFormat.cpp +++ b/src/isolated/internal/IsolatedTimeFormat.cpp @@ -24,7 +24,7 @@ namespace IsolatedTimeFormat { /* dxfg_time_format_t* */ JavaObjectHandle withTimeZone(/* dxfg_time_format_t* */ const JavaObjectHandle &timeFormat) { if (!timeFormat) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimeFormat_withTimeZone`. The `timeFormat` handle is invalid"); } @@ -35,7 +35,7 @@ withTimeZone(/* dxfg_time_format_t* */ const JavaObjectHandle withMillis(/* dxfg_time_format_t* */ const JavaObjectHandle &timeFormat) { if (!timeFormat) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimeFormat_withMillis`. The `timeFormat` handle is invalid"); } @@ -46,7 +46,7 @@ withMillis(/* dxfg_time_format_t* */ const JavaObjectHandle std::int64_t parse(/* dxfg_time_format_t* */ const JavaObjectHandle &timeFormat, std::string_view value) { if (!timeFormat) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimeFormat_parse`. The `timeFormat` handle is invalid"); } @@ -57,7 +57,7 @@ std::int64_t parse(/* dxfg_time_format_t* */ const JavaObjectHandle &timeFormat, std::int64_t value) { if (!timeFormat) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimeFormat_format`. The `timeFormat` handle is invalid"); } diff --git a/src/isolated/ipf/IsolatedInstrumentProfile.cpp b/src/isolated/ipf/IsolatedInstrumentProfile.cpp index c59859c09..46e6de71c 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfile.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfile.cpp @@ -20,7 +20,7 @@ namespace isolated::ipf::IsolatedInstrumentProfile { /* dxfg_instrument_profile_t* */ JavaObjectHandle create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_new2`. The ip handle is invalid"); } @@ -31,7 +31,7 @@ create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getType`. The ip handle is invalid"); } @@ -46,7 +46,7 @@ create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setType`. The ip handle is invalid"); } @@ -58,7 +58,7 @@ create(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getSymbol`. The ip handle is invalid"); } @@ -73,7 +73,7 @@ getSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setSymbol`. The ip handle is invalid"); } @@ -85,7 +85,7 @@ getSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getDescription`. The ip handle is invalid"); } @@ -100,7 +100,7 @@ getDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setDescription`. The ip handle is invalid"); } @@ -112,7 +112,7 @@ getDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getLocalSymbol`. The ip handle is invalid"); } @@ -127,7 +127,7 @@ getLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setLocalSymbol`. The ip handle is invalid"); } @@ -139,7 +139,7 @@ getLocalSymbol(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getLocalDescription`. The ip handle is invalid"); } @@ -155,7 +155,7 @@ getLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setLocalDescription`. The ip handle is invalid"); } @@ -167,7 +167,7 @@ setLocalDescription(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getCountry`. The ip handle is invalid"); } @@ -182,7 +182,7 @@ getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setCountry`. The ip handle is invalid"); } @@ -193,7 +193,7 @@ getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getOPOL`. The ip handle is invalid"); } @@ -208,7 +208,7 @@ getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setOPOL`. The ip handle is invalid"); } @@ -220,7 +220,7 @@ getCountry(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getExchangeData`. The ip handle is invalid"); } @@ -235,7 +235,7 @@ getExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setExchangeData`. The ip handle is invalid"); } @@ -247,7 +247,7 @@ getExchangeData(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getExchanges`. The ip handle is invalid"); } @@ -262,7 +262,7 @@ getExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setExchanges`. The ip handle is invalid"); } @@ -274,7 +274,7 @@ getExchanges(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getCurrency`. The ip handle is invalid"); } @@ -289,7 +289,7 @@ getCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setCurrency`. The ip handle is invalid"); } @@ -301,7 +301,7 @@ getCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getBaseCurrency`. The ip handle is invalid"); } @@ -316,7 +316,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setBaseCurrency`. The ip handle is invalid"); } @@ -327,7 +327,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getCFI`. The ip handle is invalid"); } @@ -342,7 +342,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setCFI`. The ip handle is invalid"); } @@ -353,7 +353,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getISIN`. The ip handle is invalid"); } @@ -368,7 +368,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setISIN`. The ip handle is invalid"); } @@ -379,7 +379,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getSEDOL`. The ip handle is invalid"); } @@ -394,7 +394,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setSEDOL`. The ip handle is invalid"); } @@ -405,7 +405,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getCUSIP`. The ip handle is invalid"); } @@ -420,7 +420,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setCUSIP`. The ip handle is invalid"); } @@ -431,7 +431,7 @@ getBaseCurrency(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getICB`. The ip handle is invalid"); } @@ -443,7 +443,7 @@ std::int32_t getICB(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, std::int32_t value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setICB`. The ip handle is invalid"); } @@ -454,7 +454,7 @@ std::int32_t getICB(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getSIC`. The ip handle is invalid"); } @@ -466,7 +466,7 @@ std::int32_t getSIC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, std::int32_t value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setSIC`. The ip handle is invalid"); } @@ -477,7 +477,7 @@ std::int32_t getSIC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getMultiplier`. The ip handle is invalid"); } @@ -489,7 +489,7 @@ double getMultiplier(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, double value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setMultiplier`. The ip handle is invalid"); } @@ -501,7 +501,7 @@ double getMultiplier(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getProduct`. The ip handle is invalid"); } @@ -516,7 +516,7 @@ getProduct(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setProduct`. The ip handle is invalid"); } @@ -528,7 +528,7 @@ getProduct(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getUnderlying`. The ip handle is invalid"); } @@ -543,7 +543,7 @@ getUnderlying(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setUnderlying`. The ip handle is invalid"); } @@ -554,7 +554,7 @@ getUnderlying(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getSPC`. The ip handle is invalid"); } @@ -566,7 +566,7 @@ double getSPC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, double value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setSPC`. The ip handle is invalid"); } @@ -578,7 +578,7 @@ double getSPC(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getAdditionalUnderlyings`. The ip handle is invalid"); } @@ -594,7 +594,7 @@ getAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle setAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setAdditionalUnderlyings`. The ip handle is invalid"); } @@ -605,7 +605,7 @@ setAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle // dxfg_InstrumentProfile_getMMY /* const char* */ std::string getMMY(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getMMY`. The ip handle is invalid"); } @@ -620,7 +620,7 @@ setAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle /* std::int32_t */ void setMMY(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setMMY`. The ip handle is invalid"); } @@ -631,7 +631,7 @@ setAdditionalUnderlyings(/* dxfg_instrument_profile_t* */ const JavaObjectHandle // dxfg_InstrumentProfile_getExpiration std::int32_t getExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getExpiration`. The ip handle is invalid"); } @@ -643,7 +643,7 @@ std::int32_t getExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHand /* std::int32_t */ void setExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, std::int32_t value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setExpiration`. The ip handle is invalid"); } @@ -654,7 +654,7 @@ std::int32_t getExpiration(/* dxfg_instrument_profile_t* */ const JavaObjectHand // dxfg_InstrumentProfile_getLastTrade std::int32_t getLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getLastTrade`. The ip handle is invalid"); } @@ -666,7 +666,7 @@ std::int32_t getLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandl /* std::int32_t */ void setLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, std::int32_t value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setLastTrade`. The ip handle is invalid"); } @@ -677,7 +677,7 @@ std::int32_t getLastTrade(/* dxfg_instrument_profile_t* */ const JavaObjectHandl // dxfg_InstrumentProfile_getStrike double getStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getStrike`. The ip handle is invalid"); } @@ -689,7 +689,7 @@ double getStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, double value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setStrike`. The ip handle is invalid"); } @@ -701,7 +701,7 @@ double getStrike(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getOptionType`. The ip handle is invalid"); } @@ -716,7 +716,7 @@ getOptionType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setOptionType`. The ip handle is invalid"); } @@ -728,7 +728,7 @@ getOptionType(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getExpirationStyle`. The ip handle is invalid"); } @@ -744,7 +744,7 @@ getExpirationStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setExpirationStyle`. The ip handle is invalid"); } @@ -756,7 +756,7 @@ setExpirationStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getSettlementStyle`. The ip handle is invalid"); } @@ -772,7 +772,7 @@ getSettlementStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setSettlementStyle`. The ip handle is invalid"); } @@ -784,7 +784,7 @@ setSettlementStyle(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getPriceIncrements`. The ip handle is invalid"); } @@ -800,7 +800,7 @@ getPriceIncrements(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setPriceIncrements`. The ip handle is invalid"); } @@ -812,7 +812,7 @@ setPriceIncrements(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getTradingHours`. The ip handle is invalid"); } @@ -827,7 +827,7 @@ getTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setTradingHours`. The ip handle is invalid"); } @@ -839,7 +839,7 @@ getTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &name) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getField`. The ip handle is invalid"); } @@ -854,7 +854,7 @@ getTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &name, const StringLikeWrapper &value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setField`. The ip handle is invalid"); } @@ -866,7 +866,7 @@ getTradingHours(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &name) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getNumericField`. The ip handle is invalid"); } @@ -878,7 +878,7 @@ double getNumericField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &name, double value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setNumericField`. The ip handle is invalid"); } @@ -890,7 +890,7 @@ double getNumericField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &name) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_getDateField`. The ip handle is invalid"); } @@ -902,7 +902,7 @@ std::int32_t getDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandl /* std::int32_t */ void setDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip, const StringLikeWrapper &name, std::int32_t value) { if (!ip) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfile_setNumericField`. The ip handle is invalid"); } @@ -914,7 +914,7 @@ std::int32_t getDateField(/* dxfg_instrument_profile_t* */ const JavaObjectHandl /* dxfg_string_list* */ std::vector getNonEmptyCustomFieldNames(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &ip) { if (!ip) { - throw std::invalid_argument("Unable to execute function `dxfg_InstrumentProfile_getNonEmptyCustomFieldNames`. " + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfile_getNonEmptyCustomFieldNames`. " "The ip handle is invalid"); } @@ -941,7 +941,7 @@ getNonEmptyCustomFieldNames(/* dxfg_instrument_profile_t* */ const JavaObjectHan namespace isolated::ipf::IsolatedInstrumentProfileList { void release(/* dxfg_instrument_profile_list * */ void *list) { if (!list) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_CList_InstrumentProfile_wrapper_release`. The list is nullptr"); } @@ -951,7 +951,7 @@ void release(/* dxfg_instrument_profile_list * */ void *list) { void releaseWrapper(/* dxfg_instrument_profile_list * */ void *list) { if (!list) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_CList_InstrumentProfile_wrapper_release`. The list is nullptr"); } diff --git a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp index 807c57405..60aebb72f 100644 --- a/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp +++ b/src/isolated/ipf/IsolatedInstrumentProfileReader.cpp @@ -19,7 +19,7 @@ namespace isolated::ipf::IsolatedInstrumentProfileReader { std::int64_t getLastModified( /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileReader_getLastModified`. The handle is invalid"); } @@ -30,7 +30,7 @@ std::int64_t getLastModified( bool wasComplete( /* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileReader_wasComplete`. The handle is invalid"); } @@ -42,7 +42,7 @@ bool wasComplete( readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, const StringLikeWrapper &address) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile`. The handle is invalid"); } @@ -55,7 +55,7 @@ readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, const StringLikeWrapper &address, const StringLikeWrapper &user, const StringLikeWrapper &password) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile`. The handle is invalid"); } @@ -69,12 +69,12 @@ readFromFile(/* dxfg_instrument_profile_reader_t * */ const JavaObjectHandle &handle, const StringLikeWrapper &address, const JavaObjectHandle &token) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile`. The handle is invalid"); } if (!token) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileReader_readFromFile3`. The token is invalid"); } diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index b88776ab2..92836e758 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -13,7 +13,7 @@ namespace isolated::promise::IsolatedPromise { bool /* int32_t */ isDone(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); } return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_isDone, static_cast(promise)) == 1; @@ -21,7 +21,7 @@ bool /* int32_t */ isDone(/* dxfg_promise_t * */ void *promise) { bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); } return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_hasResult, static_cast(promise)) == 1; @@ -29,7 +29,7 @@ bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void *promise) { bool /* int32_t */ hasException(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); } return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_hasException, static_cast(promise)) == @@ -38,7 +38,7 @@ bool /* int32_t */ hasException(/* dxfg_promise_t * */ void *promise) { bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); } return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_isCancelled, static_cast(promise)) == @@ -47,7 +47,7 @@ bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void *promise) { std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); } @@ -64,7 +64,7 @@ std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_ev std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); } @@ -80,7 +80,7 @@ getResults(/* dxfg_promise_events_t * */ void *promise) { JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); } auto *graalException = @@ -95,7 +95,7 @@ JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void * void /* int32_t */ await(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); } runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_await, static_cast(promise)); @@ -103,7 +103,7 @@ void /* int32_t */ await(/* dxfg_promise_t * */ void *promise) { void /* int32_t */ await(/* dxfg_promise_t * */ void *promise, std::int32_t timeoutInMilliseconds) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); } runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_await2, static_cast(promise), @@ -112,7 +112,7 @@ void /* int32_t */ await(/* dxfg_promise_t * */ void *promise, std::int32_t time bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void *promise, std::int32_t timeoutInMilliseconds) { if (!promise) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); } @@ -122,7 +122,7 @@ bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void *promise, s void /* int32_t */ cancel(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument("Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); + throw InvalidArgumentException("Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); } runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_cancel, static_cast(promise)); diff --git a/src/isolated/util/IsolatedTimePeriod.cpp b/src/isolated/util/IsolatedTimePeriod.cpp index 4aa3d3f0d..5e7e374d5 100644 --- a/src/isolated/util/IsolatedTimePeriod.cpp +++ b/src/isolated/util/IsolatedTimePeriod.cpp @@ -27,7 +27,7 @@ namespace isolated::util::IsolatedTimePeriod { std::int64_t getTime(/* dxfg_time_period_t* */ const JavaObjectHandle &timePeriod) { if (!timePeriod) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimePeriod_getTime`. The `timePeriod` handle is invalid"); } @@ -37,7 +37,7 @@ std::int64_t getTime(/* dxfg_time_period_t* */ const JavaObjectHandle &timePeriod) { if (!timePeriod) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimePeriod_getSeconds`. The `timePeriod` handle is invalid"); } @@ -47,7 +47,7 @@ std::int32_t getSeconds(/* dxfg_time_period_t* */ const JavaObjectHandle &timePeriod) { if (!timePeriod) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to execute function `dxfg_TimePeriod_getNanos`. The `timePeriod` handle is invalid"); } diff --git a/src/ondemand/OnDemandService.cpp b/src/ondemand/OnDemandService.cpp index 94a02f9c9..e25c2fb8c 100644 --- a/src/ondemand/OnDemandService.cpp +++ b/src/ondemand/OnDemandService.cpp @@ -40,7 +40,7 @@ std::shared_ptr OnDemandService::getInstance(std::shared_ptr onDemandService{new OnDemandService{}}; if (!endpoint->handle_) { - throw std::invalid_argument("The endpoint's handle is invalid"); + throw InvalidArgumentException("The endpoint's handle is invalid"); } auto id = ApiContext::getInstance()->getManager()->registerEntity(onDemandService); diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index 2ef773775..1dd363869 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -14,7 +14,7 @@ Day::Day(void *handle) noexcept : handle_(handle) { Day::Ptr Day::create(void *handle) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create a Day object. The handle is nullptr"); } diff --git a/src/schedule/Schedule.cpp b/src/schedule/Schedule.cpp index 4459ce80b..58fa561e3 100644 --- a/src/schedule/Schedule.cpp +++ b/src/schedule/Schedule.cpp @@ -13,7 +13,7 @@ Schedule::Schedule(void *handle) noexcept : handle_(handle) { Schedule::Ptr Schedule::create(void *handle) { if (!handle) { - throw std::invalid_argument("Unable to create a Schedule object. The handle is nullptr"); + throw InvalidArgumentException("Unable to create a Schedule object. The handle is nullptr"); } return std::shared_ptr(new Schedule(handle)); @@ -21,7 +21,7 @@ Schedule::Ptr Schedule::create(void *handle) { Schedule::Ptr Schedule::getInstance(std::shared_ptr profile) { if (!profile) { - throw std::invalid_argument("The profile is nullptr"); + throw InvalidArgumentException("The profile is nullptr"); } auto schedule = create(isolated::schedule::Schedule::getInstance(profile->handle_.get())); @@ -35,7 +35,7 @@ Schedule::Ptr Schedule::getInstance(const std::string &scheduleDefinition) { Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, const std::string &venue) { if (!profile) { - throw std::invalid_argument("The profile is nullptr"); + throw InvalidArgumentException("The profile is nullptr"); } auto schedule = create(isolated::schedule::Schedule::getInstance(profile->handle_.get(), venue)); @@ -45,7 +45,7 @@ Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, std::vector Schedule::getTradingVenues(std::shared_ptr profile) { if (!profile) { - throw std::invalid_argument("The profile is nullptr"); + throw InvalidArgumentException("The profile is nullptr"); } auto result = isolated::schedule::Schedule::getTradingVenues(profile->handle_.get()); diff --git a/src/schedule/Session.cpp b/src/schedule/Session.cpp index 58b296446..e4455130e 100644 --- a/src/schedule/Session.cpp +++ b/src/schedule/Session.cpp @@ -13,7 +13,7 @@ Session::Session(void *handle) noexcept : handle_(handle) { Session::Ptr Session::create(void *handle) { if (!handle) { - throw std::invalid_argument( + throw InvalidArgumentException( "Unable to create a Session object. The handle is nullptr"); } diff --git a/src/symbols/StringSymbol.cpp b/src/symbols/StringSymbol.cpp index dc8e2a224..0fb86ee37 100644 --- a/src/symbols/StringSymbol.cpp +++ b/src/symbols/StringSymbol.cpp @@ -72,7 +72,7 @@ StringSymbol StringSymbol::fromGraal(void *graalNative) { } if (graalNative == nullptr) { - throw std::invalid_argument("Unable to create StringSymbol. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create StringSymbol. The `graalNative` parameter is nullptr"); } auto *graalSymbol = static_cast(graalNative); diff --git a/src/symbols/SymbolWrapper.cpp b/src/symbols/SymbolWrapper.cpp index 192b72e1e..0c7df0fa5 100644 --- a/src/symbols/SymbolWrapper.cpp +++ b/src/symbols/SymbolWrapper.cpp @@ -178,7 +178,7 @@ SymbolWrapper SymbolWrapper::fromGraal(void *graalNative) { } if (graalNative == nullptr) { - throw std::invalid_argument("Unable to create SymbolWrapper. The `graalNative` parameter is nullptr"); + throw InvalidArgumentException("Unable to create SymbolWrapper. The `graalNative` parameter is nullptr"); } switch (static_cast(graalNative)->type) { @@ -198,7 +198,7 @@ SymbolWrapper SymbolWrapper::fromGraal(void *graalNative) { return TimeSeriesSubscriptionSymbol::fromGraal(graalNative); default: - throw std::runtime_error(fmt::format("Unable to create SymbolWrapper. Unknown symbol type: {}", + throw RuntimeException(fmt::format("Unable to create SymbolWrapper. Unknown symbol type: {}", static_cast(static_cast(graalNative)->type))); } From 87ebbf8f92580af1257625869ddf959f56c6eb79 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 24 Jul 2024 17:16:39 +0300 Subject: [PATCH 055/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type fix CandleSymbolTest --- include/dxfeed_graal_cpp_api/internal/Common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index c9e306711..e0db3213b 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -742,7 +742,7 @@ struct StringLikeWrapper { if (auto sv = std::get_if(&data_); sv) { auto sv2 = sv->substr(pos, count); - return {sv2.data(), sv->size()}; + return {sv2.data(), sv2.size()}; } else { return std::get(data_).substr(pos, count); } From c64a959f3dc80ad8206ef406976bd4526fe52876 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 24 Jul 2024 18:36:54 +0300 Subject: [PATCH 056/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type Check the types parsing. --- .../internal/utils/CmdArgsUtils.hpp | 22 ++++---- .../internal/utils/StringUtils.hpp | 10 ++-- src/internal/utils/CmdArgsUtils.cpp | 52 ++++++++++-------- tools/Tools/src/Connect/ConnectTool.hpp | 55 ++++++++++++------- tools/Tools/src/Dump/DumpTool.hpp | 22 ++++++-- .../Tools/src/LatencyTest/LatencyTestTool.hpp | 21 ++++++- tools/Tools/src/PerfTest/PerfTestTool.hpp | 23 ++++++-- 7 files changed, 136 insertions(+), 69 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/internal/utils/CmdArgsUtils.hpp b/include/dxfeed_graal_cpp_api/internal/utils/CmdArgsUtils.hpp index fc9c89ad1..b693505ad 100644 --- a/include/dxfeed_graal_cpp_api/internal/utils/CmdArgsUtils.hpp +++ b/include/dxfeed_graal_cpp_api/internal/utils/CmdArgsUtils.hpp @@ -107,10 +107,10 @@ struct DXFCPP_EXPORT CmdArgsUtils final { * "all" or "*" will be converted to all types. * * @param types The comma-separated list of event types. - * @return The created set of parsed types. + * @return The created pair of set of parsed types and vector unknown types. */ - static std::unordered_set> - parseTypes(const std::string &types) noexcept; + static std::pair>, std::vector> + parseTypes(const std::string &types); /** * Parses an input string and returns a set of event types. @@ -118,9 +118,10 @@ struct DXFCPP_EXPORT CmdArgsUtils final { * "all" or "*" will be converted to all types. * * @param types The comma-separated list of event types. - * @return The created set of parsed types. + * @return The created pair of set of parsed types and vector unknown types. */ - static std::unordered_set> parseTypes(const char *types) noexcept { + static std::pair>, std::vector> + parseTypes(const char *types) { return parseTypes(std::string(types)); } @@ -130,9 +131,10 @@ struct DXFCPP_EXPORT CmdArgsUtils final { * "all" or "*" will be converted to all types. * * @param types The comma-separated list of event types. - * @return The created set of parsed types. + * @return The created pair of set of parsed types and vector unknown types. */ - static std::unordered_set> parseTypes(std::string_view types) noexcept { + static std::pair>, std::vector> + parseTypes(std::string_view types) { return parseTypes(types.data()); } @@ -142,10 +144,10 @@ struct DXFCPP_EXPORT CmdArgsUtils final { * "all" or "*" will be converted to all types. * * @param types The comma-separated list of event types. - * @return The created set of parsed types. + * @return The created pair of set of parsed types and vector unknown types. */ - static std::unordered_set> - parseTypes(std::optional types) noexcept; + static std::pair>, std::vector> + parseTypes(std::optional types); /** * Parses the input collection of strings and returns a collection of key-value properties. diff --git a/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp b/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp index a3ad6b9c4..8a8c3867d 100644 --- a/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp +++ b/include/dxfeed_graal_cpp_api/internal/utils/StringUtils.hpp @@ -217,14 +217,16 @@ std::string namesToString(It begin, It end) { return result + "]"; } -template std::string elementsToString(It begin, It end) { - std::string result{"["}; +template +std::string elementsToString(It begin, It end, const std::string &prefix = "[", const std::string &postfix = "[", + const std::string &separator = ", ") { + std::string result{prefix}; for (auto it = begin; it != end; it++) { - result += String::EMPTY + toStringAny(*it) + (std::next(it) == end ? "" : ", "); + result += String::EMPTY + toStringAny(*it) + (std::next(it) == end ? "" : separator); } - return result + "]"; + return result + postfix; } DXFCPP_EXPORT std::string encodeChar(std::int16_t c); diff --git a/src/internal/utils/CmdArgsUtils.cpp b/src/internal/utils/CmdArgsUtils.cpp index bed73cb00..d13803c87 100644 --- a/src/internal/utils/CmdArgsUtils.cpp +++ b/src/internal/utils/CmdArgsUtils.cpp @@ -55,13 +55,17 @@ auto splitAndTrim = [](auto &&symbols, char sep = ',') noexcept { return symbols | ranges::views::split(sep) | filterNonEmpty | transformToString | trim; }; -decltype(ranges::views::transform([](auto &&s) { +auto toUpper = [](auto&& s) { auto locale = std::locale{}; return s | ranges::views::transform([&locale](auto c) { return std::toupper(c, locale); }) | ranges::to(); +}; + +decltype(ranges::views::transform([](auto &&s) { + return toUpper(s); })) transformToUpper{}; std::unordered_set parseStringSymbols(const std::string &symbols) noexcept { @@ -171,8 +175,8 @@ std::unordered_set CmdArgsUtils::parseCandleSymbols(std::optional< return {}; } -std::unordered_set> -CmdArgsUtils::parseTypes(const std::string &types) noexcept { +std::pair>, std::vector> +CmdArgsUtils::parseTypes(const std::string &types) { auto trimmedTypes = trimStr(types); if (trimmedTypes.empty()) { @@ -180,34 +184,36 @@ CmdArgsUtils::parseTypes(const std::string &types) noexcept { } if (trimmedTypes == "*" || trimmedTypes == "all" || trimmedTypes == "All" || trimmedTypes == "ALL") { - return EventTypeEnum::ALL | ranges::to>>(); + return {EventTypeEnum::ALL | ranges::to>>(), {}}; } - auto split = splitAndTrim(trimmedTypes) | filterNonEmpty; - auto allByName = split | transformToUpper | ranges::views::filter([](const auto &s) { - return EventTypeEnum::ALL_BY_NAME.contains(s); - }) | - ranges::views::transform([](const auto &s) { - return EventTypeEnum::ALL_BY_NAME.at(s); - }); - auto allByClassName = split | ranges::views::filter([](const auto &s) { - return EventTypeEnum::ALL_BY_CLASS_NAME.contains(s); - }) | - ranges::views::transform([](const auto &s) { - return EventTypeEnum::ALL_BY_CLASS_NAME.at(s); - }); - - return ranges::views::concat(allByName, allByClassName) | - ranges::to>>(); + auto split = splitAndTrim(trimmedTypes) | filterNonEmpty | ranges::to>; + + std::unordered_set> result; + std::vector unknown; + + for (auto t : split) { + auto u = toUpper(t); + + if (EventTypeEnum::ALL_BY_NAME.contains(u)) { + result.emplace(EventTypeEnum::ALL_BY_NAME.at(u)); + } else if (EventTypeEnum::ALL_BY_CLASS_NAME.contains(t)) { + result.emplace(EventTypeEnum::ALL_BY_CLASS_NAME.at(t)); + } else { + unknown.push_back(t); + } + } + + return {result, unknown}; } -std::unordered_set> -CmdArgsUtils::parseTypes(std::optional types) noexcept { +std::pair>, std::vector> +CmdArgsUtils::parseTypes(std::optional types) { if (types.has_value()) { return parseTypes(types.value()); } - return std::unordered_set>{}; + return {}; } std::unordered_map CmdArgsUtils::parseProperties(const std::string &properties) noexcept { diff --git a/tools/Tools/src/Connect/ConnectTool.hpp b/tools/Tools/src/Connect/ConnectTool.hpp index 00dbc0af6..a63788ab3 100644 --- a/tools/Tools/src/Connect/ConnectTool.hpp +++ b/tools/Tools/src/Connect/ConnectTool.hpp @@ -152,14 +152,45 @@ struct ConnectTool { System::setProperties(parsedProperties); + auto [parsedTypes, unknownTypes] = CmdArgsUtils::parseTypes(args.types); + + if (!unknownTypes.empty()) { + auto unknown = elementsToString(unknownTypes.begin(), unknownTypes.end(), "", ""); + + throw InvalidArgumentException( + fmt::format("There are unknown event types: {}!\n List of available event types: {}", unknown, + enum_utils::getEventTypeEnumClassNamesList(", "))); + } + + if (parsedTypes.empty()) { + throw InvalidArgumentException("The resulting list of types is empty!"); + } + + auto parsedSymbols = CmdArgsUtils::parseSymbols(args.symbols); + + if (args.fromTime.has_value()) { + auto fromTime = TimeFormat::DEFAULT.parse(args.fromTime.value()); + + parsedSymbols = parsedSymbols | ranges::views::transform([fromTime](const auto &sw) { + return TimeSeriesSubscriptionSymbol{sw, fromTime}; + }) | + ranges::to>; + } else if (args.source.has_value()) { + auto source = OrderSource::valueOf(args.source.value()); + + parsedSymbols = parsedSymbols | ranges::views::transform([source](const auto &sw) { + return IndexedEventSubscriptionSymbol{sw, source}; + }) | + ranges::to>; + } + auto endpoint = DXEndpoint::newBuilder() ->withRole(args.forceStream ? DXEndpoint::Role::STREAM_FEED : DXEndpoint::Role::FEED) ->withProperties(parsedProperties) ->withName(NAME + "Tool-Feed") ->build(); - std::shared_ptr sub = - endpoint->getFeed()->createSubscription(CmdArgsUtils::parseTypes(args.types)); + std::shared_ptr sub = endpoint->getFeed()->createSubscription(parsedTypes); if (!args.isQuite) { sub->addEventListener([](auto &&events) { @@ -171,24 +202,6 @@ struct ConnectTool { }); } - auto symbols = CmdArgsUtils::parseSymbols(args.symbols); - - if (args.fromTime.has_value()) { - auto fromTime = TimeFormat::DEFAULT.parse(args.fromTime.value()); - - symbols = symbols | ranges::views::transform([fromTime](const auto &sw) { - return TimeSeriesSubscriptionSymbol{sw, fromTime}; - }) | - ranges::to>; - } else if (args.source.has_value()) { - auto source = OrderSource::valueOf(args.source.value()); - - symbols = symbols | ranges::views::transform([source](const auto &sw) { - return IndexedEventSubscriptionSymbol{sw, source}; - }) | - ranges::to>; - } - if (args.tape.has_value()) { std::string tape = args.tape.value(); @@ -206,7 +219,7 @@ struct ConnectTool { }); } - sub->addSymbols(symbols); + sub->addSymbols(parsedSymbols); endpoint->connect(args.address); std::this_thread::sleep_for(std::chrono::days(365)); } catch (const RuntimeException &e) { diff --git a/tools/Tools/src/Dump/DumpTool.hpp b/tools/Tools/src/Dump/DumpTool.hpp index 088da526f..7501e3d62 100644 --- a/tools/Tools/src/Dump/DumpTool.hpp +++ b/tools/Tools/src/Dump/DumpTool.hpp @@ -133,6 +133,22 @@ struct DumpTool { System::setProperties(parsedProperties); + auto [parsedTypes, unknownTypes] = CmdArgsUtils::parseTypes(args.types.has_value() ? *args.types : "all"); + + if (!unknownTypes.empty()) { + auto unknown = elementsToString(unknownTypes.begin(), unknownTypes.end(), "", ""); + + throw InvalidArgumentException( + fmt::format("There are unknown event types: {}!\n List of available event types: {}", unknown, + enum_utils::getEventTypeEnumClassNamesList(", "))); + } + + if (parsedTypes.empty()) { + throw InvalidArgumentException("The resulting list of types is empty!"); + } + + auto parsedSymbols = CmdArgsUtils::parseSymbols(args.symbols.has_value() ? *args.symbols : "all"); + auto inputEndpoint = DXEndpoint::newBuilder() ->withRole(DXEndpoint::Role::STREAM_FEED) @@ -141,8 +157,7 @@ struct DumpTool { ->withName(NAME + "Tool-Feed") ->build(); - auto sub = inputEndpoint->getFeed()->createSubscription( - !args.types.has_value() ? CmdArgsUtils::parseTypes("all") : CmdArgsUtils::parseTypes(*args.types)); + auto sub = inputEndpoint->getFeed()->createSubscription(parsedTypes); if (!args.isQuite) { sub->addEventListener([](auto &&events) { @@ -173,8 +188,7 @@ struct DumpTool { }); } - sub->addSymbols(!args.symbols.has_value() ? CmdArgsUtils::parseSymbols("all") - : CmdArgsUtils::parseSymbols(args.symbols.value())); + sub->addSymbols(parsedSymbols); inputEndpoint->connect(args.address); inputEndpoint->awaitNotConnected(); diff --git a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp index a45097f12..d360f0392 100644 --- a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp +++ b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp @@ -346,6 +346,22 @@ struct LatencyTest { System::setProperties(parsedProperties); + auto [parsedTypes, unknownTypes] = CmdArgsUtils::parseTypes(args.types.has_value() ? *args.types : "all"); + + if (!unknownTypes.empty()) { + auto unknown = elementsToString(unknownTypes.begin(), unknownTypes.end(), "", ""); + + throw InvalidArgumentException( + fmt::format("There are unknown event types: {}!\n List of available event types: {}", unknown, + enum_utils::getEventTypeEnumClassNamesList(", "))); + } + + if (parsedTypes.empty()) { + throw InvalidArgumentException("The resulting list of types is empty!"); + } + + auto parsedSymbols = CmdArgsUtils::parseSymbols(args.symbols.has_value() ? *args.symbols : "all"); + auto endpoint = DXEndpoint::newBuilder() ->withRole(args.forceStream ? DXEndpoint::Role::STREAM_FEED : DXEndpoint::Role::FEED) @@ -354,8 +370,7 @@ struct LatencyTest { ->withName(NAME + "Tool-Feed") ->build(); - auto sub = endpoint->getFeed()->createSubscription( - CmdArgsUtils::parseTypes(args.types.has_value() ? *args.types : "all")); + auto sub = endpoint->getFeed()->createSubscription(parsedTypes); auto diagnostic = Diagnostic::create(std::chrono::seconds(args.interval)); sub->addEventListener([d = diagnostic](auto &&events) { @@ -363,7 +378,7 @@ struct LatencyTest { d->handleEvents(events); }); - sub->addSymbols(CmdArgsUtils::parseSymbols(args.symbols.has_value() ? *args.symbols : "all")); + sub->addSymbols(parsedSymbols); endpoint->connect(args.address); endpoint->awaitNotConnected(); endpoint->closeAndAwaitTermination(); diff --git a/tools/Tools/src/PerfTest/PerfTestTool.hpp b/tools/Tools/src/PerfTest/PerfTestTool.hpp index dcbe28a5b..cd5485913 100644 --- a/tools/Tools/src/PerfTest/PerfTestTool.hpp +++ b/tools/Tools/src/PerfTest/PerfTestTool.hpp @@ -133,8 +133,7 @@ struct PerfTestTool { } public: - static std::shared_ptr create(std::chrono::seconds measurementPeriod, - bool showCpuUsageByCore) { + static std::shared_ptr create(std::chrono::seconds measurementPeriod, bool showCpuUsageByCore) { auto d = std::shared_ptr(new Diagnostic(showCpuUsageByCore)); d->timer_ = Timer::schedule( @@ -241,6 +240,22 @@ struct PerfTestTool { System::setProperties(parsedProperties); + auto [parsedTypes, unknownTypes] = CmdArgsUtils::parseTypes(args.types); + + if (!unknownTypes.empty()) { + auto unknown = elementsToString(unknownTypes.begin(), unknownTypes.end(), "", ""); + + throw InvalidArgumentException( + fmt::format("There are unknown event types: {}!\n List of available event types: {}", unknown, + enum_utils::getEventTypeEnumClassNamesList(", "))); + } + + if (parsedTypes.empty()) { + throw InvalidArgumentException("The resulting list of types is empty!"); + } + + auto parsedSymbols = CmdArgsUtils::parseSymbols(args.symbols); + auto endpoint = DXEndpoint::newBuilder() ->withRole(args.forceStream ? DXEndpoint::Role::STREAM_FEED : DXEndpoint::Role::FEED) @@ -249,7 +264,7 @@ struct PerfTestTool { ->withName(NAME + "Tool-Feed") ->build(); - auto sub = endpoint->getFeed()->createSubscription(CmdArgsUtils::parseTypes(args.types)); + auto sub = endpoint->getFeed()->createSubscription(parsedTypes); auto diagnostic = Diagnostic::create(2s, args.showCpuUsageByCore); std::atomic hash{}; @@ -265,7 +280,7 @@ struct PerfTestTool { }); } - sub->addSymbols(CmdArgsUtils::parseSymbols(args.symbols)); + sub->addSymbols(parsedSymbols); endpoint->connect(args.address); endpoint->awaitNotConnected(); endpoint->closeAndAwaitTermination(); From aa23c5c54de0c0f6b25f31c3dbe6e83657ff7eb0 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 24 Jul 2024 18:45:50 +0300 Subject: [PATCH 057/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type ReleaseNotes --- ReleaseNotes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index e4f1e1536..ac329d786 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,8 @@ +* **\[MDAPI-113]\[C++]\[Tools]** Tools should report invalid event type + * Added classes: `RuntimeException`, `InvalidArgumentException` + * `InvalidArgumentException`, `GraalException`, `JavaException` are now descendants of the `RuntimeException` class, which can collect stacktrace. + * Now an `InvalidArgumentException` exception is thrown instead of the `std::invalid_argument` exception. + * `Tools` now reports incorrect event types specified by the user. * **\[MDAPI-80]\[C++]\[IPF]** Implement custom fields in InstrumentProfile * The API was migrated to Graal SDK v1.1.22 * Added methods: From 0911cef4b0f5479e7e53eb253ae39a9980f60ae0 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 24 Jul 2024 18:59:09 +0300 Subject: [PATCH 058/178] [MDAPI-113] [C++][Tools] Tools should report invalid event type Fix samples build --- samples/cpp/DxFeedConnect/src/main.cpp | 2 +- samples/cpp/DxFeedFileParser/src/main.cpp | 2 +- samples/cpp/DxFeedIpfConnect/src/main.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/cpp/DxFeedConnect/src/main.cpp b/samples/cpp/DxFeedConnect/src/main.cpp index e42a6ab79..00df8ce5a 100644 --- a/samples/cpp/DxFeedConnect/src/main.cpp +++ b/samples/cpp/DxFeedConnect/src/main.cpp @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) { auto endpoint = DXEndpoint::create()->connect(address); // Create a subscription with specified types attached to feed. - auto sub = endpoint->getFeed()->createSubscription(types); + auto sub = endpoint->getFeed()->createSubscription(types.first); // Add an event listener. sub->addEventListener([&ioMtx](const auto &events) { diff --git a/samples/cpp/DxFeedFileParser/src/main.cpp b/samples/cpp/DxFeedFileParser/src/main.cpp index 682bb7ab7..2525a46b1 100644 --- a/samples/cpp/DxFeedFileParser/src/main.cpp +++ b/samples/cpp/DxFeedFileParser/src/main.cpp @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) { auto feed = endpoint->getFeed(); // Subscribe to a specified event and symbol. - auto sub = feed->createSubscription(types); + auto sub = feed->createSubscription(types.first); sub->addEventListener([&eventCounter, &ioMtx](const auto &events) { std::lock_guard lock{ioMtx}; diff --git a/samples/cpp/DxFeedIpfConnect/src/main.cpp b/samples/cpp/DxFeedIpfConnect/src/main.cpp index f54671d37..975118688 100644 --- a/samples/cpp/DxFeedIpfConnect/src/main.cpp +++ b/samples/cpp/DxFeedIpfConnect/src/main.cpp @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) { auto types = CmdArgsUtils::parseTypes(argv[1]); auto ipfFile = argv[2]; - auto sub = DXFeed::getInstance()->createSubscription(types); + auto sub = DXFeed::getInstance()->createSubscription(types.first); sub->addEventListener([](auto &&events) { for (auto &&event : events) { From 6fc175d0df722ea135b4d7e5dc5071e7c48fa9b6 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 25 Jul 2024 13:19:22 +0300 Subject: [PATCH 059/178] [MDAPI-37][C++] Retrieve latest events from feed DXFeed::getLastEvent stub --- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 32 +++++++++++++++++++++ src/api/DXFeed.cpp | 5 ++++ 2 files changed, 37 insertions(+) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index 27d069907..25878adbf 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -194,6 +194,38 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { */ void detachSubscriptionAndClear(std::shared_ptr subscription); + /** + * Returns the last event for the specified event instance. + * This method works only for event types that implement LastingEvent marker interface. + * This method does not make any remote calls to the uplink data provider. + * It just retrieves last received event from the local cache of this feed. + * The events are stored in the cache only if there is some attached DXFeedSubscription that is subscribed to the + * corresponding symbol and event type. + * WildcardSymbol::ALL subscription does not count for that purpose. + * + *

Use @ref ::getLastEventPromise() "getLastEventPromise" method if an event needs to be requested in the absence + * of subscription. + * + *

This method fills in the values for the last event into the `event argument. + * If the last event is not available for any reason (no subscription, no connection to uplink, etc). + * then the event object is not changed. + * This method always returns the same `event` instance that is passed to it as an argument. + * + *

This method provides no way to distinguish a case when there is no subscription from the case when + * there is a subscription, but the event data have not arrived yet. It is recommened to use + * @ref ::getLastEventIfSubscribed() "getLastEventIfSubscribed" method instead of this `getLastEvent` method to + * fail-fast in case when the subscription was supposed to be set by the logic of the code, since + * @ref ::getLastEventIfSubscribed() "getLastEventIfSubscribed" method returns null when there is no subscription. + * + *

Note, that this method does not work when DXEndpoint was created with + * @ref DXEndpoint::Role::STREAM_FEED "STREAM_FEED" role (never fills in the event). + * + * @tparam E The type of event. + * @param event the event. + * @return The same event. + */ + template E> std::shared_ptr getLastEvent(std::shared_ptr event); + /** * Creates new subscription for a single event type that is attached to this feed. * This method creates new DXFeedSubscription and invokes @link DXFeed::attachSubscription. diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index d918ea822..1879502ee 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -81,6 +81,11 @@ void DXFeed::detachSubscriptionAndClear(std::shared_ptr subs } } +template E> std::shared_ptr DXFeed::getLastEvent(std::shared_ptr event) { + //TODO: implement + return event; +} + std::shared_ptr DXFeed::createSubscription(const EventTypeEnum &eventType) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventType = " + eventType.getName() + ")"); From 2ff98d3b9b71f0cfea994b0e6f433324f18df86c Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 25 Jul 2024 16:19:44 +0300 Subject: [PATCH 060/178] [MDAPI-37][C++] Retrieve latest events from feed IsolatetEventType --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../isolated/event/IsolatedEventType.hpp | 40 ++++++++++++++ src/isolated/event/IsolatedEventType.cpp | 54 +++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp create mode 100644 src/isolated/event/IsolatedEventType.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 526b63efc..fb6de0ea8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,6 +213,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp src/isolated/auth/IsolatedAuthToken.cpp + src/isolated/event/IsolatedEventType.cpp src/isolated/promise/IsolatedPromise.cpp src/isolated/internal/IsolatedString.cpp src/isolated/internal/IsolatedObject.cpp diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index c11a19e3b..13712e45e 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -64,6 +64,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/api/IsolatedDXPublisherObservableSubscription.hpp" #include "isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp" #include "isolated/auth/IsolatedAuthToken.hpp" +#include "isolated/event/IsolatedEventType.hpp" #include "isolated/promise/IsolatedPromise.hpp" #include "isolated/internal/IsolatedString.hpp" #include "isolated/internal/IsolatedObject.hpp" diff --git a/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp b/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp new file mode 100644 index 000000000..460fc91f8 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include "../../internal/Common.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::events { +namespace IsolatetEventType { + +// dxfg_EventType_new +/* dxfg_event_type_t* */ void* create(const StringLikeWrapper& symbolName, /* dxfg_event_clazz_t */ const EventTypeEnum& eventType); + +// dxfg_EventType_release +/* int32_t */ void release(/* dxfg_event_type_t* */ void* eventType); + +std::unique_ptr toUnique(void *eventType); + +} // namespace IsolatetEventType + + +namespace IsolatetEventTypeList { + +// dxfg_CList_EventType_release +/* int32_t */ void release(/* dxfg_event_type_list* */ void* eventTypes); + +std::unique_ptr toUnique(void *eventTypes); + +} +} // namespace isolated::events + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/isolated/event/IsolatedEventType.cpp b/src/isolated/event/IsolatedEventType.cpp new file mode 100644 index 000000000..e09bc9ec2 --- /dev/null +++ b/src/isolated/event/IsolatedEventType.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::internal { +namespace IsolatedEventType { + +// dxfg_EventType_new +/* dxfg_event_type_t* */ void *create(const StringLikeWrapper &symbolName, + /* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { + return dxfcpp::bit_cast(runGraalFunctionAndThrowIfNullptr( + dxfg_EventType_new, symbolName.c_str(), static_cast(eventType.getId()))); +} + +// dxfg_EventType_release +/* int32_t */ void release(/* dxfg_event_type_t* */ void *eventType) { + if (!eventType) { + throw InvalidArgumentException("Unable to execute function `dxfg_EventType_release`. The `eventType` is null"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_EventType_release, dxfcpp::bit_cast(eventType)); +} + +std::unique_ptr toUnique(void *eventType) { + return {eventType, release}; +} + +} // namespace IsolatedEventType + +namespace IsolatedEventTypeList { +// dxfg_CList_EventType_release +/* int32_t */ void release(/* dxfg_event_type_list* */ void *eventTypes) { + if (!eventTypes) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_CList_EventType_release`. The `eventTypes` is null"); + } + + runGraalFunctionAndThrowIfMinusOne(dxfg_CList_EventType_release, + dxfcpp::bit_cast(eventTypes)); +} + +std::unique_ptr toUnique(void *eventTypes) { + return {eventTypes, release}; +} +} // namespace IsolatedEventTypeList +} // namespace isolated::internal + +DXFCPP_END_NAMESPACE \ No newline at end of file From 7850e169475b6b873358ac7de7a46d4bd784b4fb Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 25 Jul 2024 16:27:44 +0300 Subject: [PATCH 061/178] [MDAPI-37][C++] Retrieve latest events from feed SymbolWrapper::toStringUnderlying --- .../symbols/SymbolWrapper.hpp | 13 +++++++++ tests/CMakeLists.txt | 1 + tests/api/DXEndpointTest.cpp | 22 --------------- tests/symbols/SymbolWrapperTest.cpp | 28 +++++++++++++++++++ 4 files changed, 42 insertions(+), 22 deletions(-) create mode 100644 tests/symbols/SymbolWrapperTest.cpp diff --git a/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp b/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp index 37bd05671..f90403557 100644 --- a/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp +++ b/include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp @@ -271,6 +271,19 @@ struct DXFCPP_EXPORT SymbolWrapper final { "}"; } + /** + * Returns a string representation of the underlying object. + * + * @return a string representation of the underlying object. + */ + std::string toStringUnderlying() const { + return std::visit( + [](const auto &symbol) { + return toStringAny(symbol); + }, + data_); + } + /** * @return `true` if current SymbolWrapper holds a StringSymbol */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 15e910142..b23bf2fdd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,7 @@ set(DXFC_TEST_SOURCES api/MarketEventSymbolsTest.cpp api/OrderSourceTest.cpp schedule/ScheduleTest.cpp + symbols/SymbolWrapperTest.cpp system/SystemTest.cpp) #add_definitions(-DDXFCPP_DEBUG -DDXFCPP_DEBUG_ISOLATES) diff --git a/tests/api/DXEndpointTest.cpp b/tests/api/DXEndpointTest.cpp index 6d2092021..0d880c6e8 100644 --- a/tests/api/DXEndpointTest.cpp +++ b/tests/api/DXEndpointTest.cpp @@ -141,28 +141,6 @@ TEST_CASE("dxfcpp::DXFeed::getInstance()") { dxfcpp::DXFeed::getInstance(); } -TEST_CASE("dxfcpp::SymbolWrapper::SymbolListUtils::toGraalList") { - using namespace std::literals; - - auto *list = dxfcpp::SymbolWrapper::SymbolListUtils::toGraalList({"AAPL", "IBM"s, "TSLA"sv}); - auto *list2 = dxfcpp::SymbolWrapper::SymbolListUtils::toGraalList(std::vector{"XXX", "YYY", "ZZZ"}); - - auto set = std::set{"111", "222"sv, "333"s}; - - auto *list3 = dxfcpp::SymbolWrapper::SymbolListUtils::toGraalList(set.begin(), set.end()); - - auto sl = dxfcpp::SymbolWrapper::SymbolListUtils::fromGraalList(list); - - std::cout << "Symbols:\n"; - for (const auto &s : sl) { - std::cout << s.toString() << "\n"; - } - - dxfcpp::SymbolWrapper::SymbolListUtils::freeGraalList(list); - dxfcpp::SymbolWrapper::SymbolListUtils::freeGraalList(list2); - dxfcpp::SymbolWrapper::SymbolListUtils::freeGraalList(list3); -} - TEST_CASE("DXEndpoint::user") { using namespace std::literals; diff --git a/tests/symbols/SymbolWrapperTest.cpp b/tests/symbols/SymbolWrapperTest.cpp new file mode 100644 index 000000000..a597065f4 --- /dev/null +++ b/tests/symbols/SymbolWrapperTest.cpp @@ -0,0 +1,28 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#include +#include +#include +#include + +#include +#include + +#include + +using namespace dxfcpp; +using namespace dxfcpp::literals; +using namespace std::literals; + +TEST_CASE("SymbolWrapper::toStringUnderlying") { + auto c = CandleSymbol::valueOf("AAPL&Q{=1m}"); + + REQUIRE(SymbolWrapper(c).toStringUnderlying() == c.toString()); + REQUIRE(SymbolWrapper(WildcardSymbol::ALL).toStringUnderlying() == WildcardSymbol::ALL.toString()); + REQUIRE(SymbolWrapper(c).toString() != c.toString()); + REQUIRE(SymbolWrapper(WildcardSymbol::ALL).toString() != WildcardSymbol::ALL.toString()); +} + From 1786d5eca81b5a958481bd301082c96aaac99d5c Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 25 Jul 2024 16:28:42 +0300 Subject: [PATCH 062/178] [MDAPI-37][C++] Retrieve latest events from feed IsolatedDXFeed::getLastEvent --- .../isolated/api/IsolatedDXFeed.hpp | 11 +++++++--- src/isolated/api/IsolatedDXFeed.cpp | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp index 8fe95894e..72668c35f 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp @@ -27,16 +27,21 @@ dxfg_event_type_t* dxfg_DXFeed_getLastEventIfSubscribed(graal_iso dxfg_event_type_list* dxfg_DXFeed_getIndexedEventsIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, const char *source); dxfg_event_type_list* dxfg_DXFeed_getTimeSeriesIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, int64_t from_time, int64_t to_time); // use dxfg_EventType_new to create an empty structure so that java tries to free up memory when replacing subjects -int32_t dxfg_DXFeed_getLastEvent(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_t *event); + +*/ + +// dxfg_DXFeed_getLastEvent +/* int32_t */ std::shared_ptr getLastEvent(/* dxfg_feed_t * */ const JavaObjectHandle& feed, /* dxfg_event_type_t * */ const StringLikeWrapper& symbolName, const EventTypeEnum& eventType); + +/* int32_t dxfg_DXFeed_getLastEvents(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_list *events); dxfg_promise_event_t* dxfg_DXFeed_getLastEventPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); dxfg_promise_list* dxfg_DXFeed_getLastEventsPromises(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_list *symbols); dxfg_promise_events_t* dxfg_DXFeed_getIndexedEventsPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, dxfg_indexed_event_source_t* source); -dxfg_promise_events_t* dxfg_DXFeed_getTimeSeriesPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t clazz, dxfg_symbol_t *symbol, int64_t fromTime, int64_t toTime); */ - +// dxfg_DXFeed_getTimeSeriesPromise /* dxfg_promise_events_t* */ void* getTimeSeriesPromise(/* dxfg_feed_t * */ const JavaObjectHandle& feed, /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, /* dxfg_symbol_t * */ const SymbolWrapper &symbol, std::int64_t fromTime, std::int64_t toTime); diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp index 34bb5ff5e..40453aba0 100644 --- a/src/isolated/api/IsolatedDXFeed.cpp +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -5,11 +5,33 @@ #include #include +#include DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeed { + +// dxfg_DXFeed_getLastEvent +/* int32_t */ std::shared_ptr getLastEvent(/* dxfg_feed_t * */ const JavaObjectHandle& feed, /* dxfg_event_type_t * */ const StringLikeWrapper& symbolName, const EventTypeEnum& eventType) { + if (!feed) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_DXFeed_getLastEvent`. The `feed` handle is invalid"); + } + + auto e = events::IsolatetEventType::toUnique(events::IsolatetEventType::create(symbolName, eventType)); + + return EventMapper::fromGraal(e.get()); +} + +/* +int32_t dxfg_DXFeed_getLastEvents(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_list *events); +dxfg_promise_event_t* dxfg_DXFeed_getLastEventPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); +dxfg_promise_list* dxfg_DXFeed_getLastEventsPromises(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_list *symbols); +dxfg_promise_events_t* dxfg_DXFeed_getIndexedEventsPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, dxfg_indexed_event_source_t* source); + +*/ + /* dxfg_promise_events_t* */ void *getTimeSeriesPromise(/* dxfg_feed_t * */ const JavaObjectHandle &feed, /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, /* dxfg_symbol_t * */ const SymbolWrapper &symbol, From 0d9db2bd49a44c098c8ed6fadd94e51b04ac599d Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Thu, 25 Jul 2024 19:15:51 +0300 Subject: [PATCH 063/178] [MDAPI-37][C++] Retrieve latest events from feed EventType::assign DXFeed::getLastEvent DXFeedSample::testTradeSnapshots --- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 12 +++-- .../dxfeed_graal_cpp_api/event/EventType.hpp | 13 ++++- .../event/candle/Candle.hpp | 3 ++ .../event/market/AnalyticOrder.hpp | 3 ++ .../event/market/MarketEvent.hpp | 10 +++- .../event/market/OptionSale.hpp | 3 ++ .../event/market/Order.hpp | 3 ++ .../event/market/OrderBase.hpp | 3 ++ .../event/market/OtcMarketsOrder.hpp | 3 ++ .../event/market/Profile.hpp | 3 ++ .../event/market/Quote.hpp | 3 ++ .../event/market/SpreadOrder.hpp | 3 ++ .../event/market/Summary.hpp | 3 ++ .../event/market/TimeAndSale.hpp | 3 ++ .../event/market/Trade.hpp | 3 ++ .../event/market/TradeBase.hpp | 3 ++ .../event/market/TradeETH.hpp | 3 ++ .../event/misc/Message.hpp | 3 ++ .../event/option/Greeks.hpp | 3 ++ .../event/option/Series.hpp | 3 ++ .../event/option/TheoPrice.hpp | 3 ++ .../event/option/Underlying.hpp | 3 ++ .../isolated/event/IsolatedEventType.hpp | 18 +++---- samples/cpp/DxFeedSample/src/main.cpp | 31 +++++++++-- src/api/DXFeed.cpp | 9 ++-- src/event/candle/Candle.cpp | 11 ++-- src/event/market/AnalyticOrder.cpp | 8 +++ src/event/market/OptionSale.cpp | 14 +++-- src/event/market/Order.cpp | 8 +++ src/event/market/OrderBase.cpp | 8 +++ src/event/market/OtcMarketsOrder.cpp | 8 +++ src/event/market/Profile.cpp | 8 +++ src/event/market/Quote.cpp | 8 +++ src/event/market/SpreadOrder.cpp | 8 +++ src/event/market/Summary.cpp | 8 +++ src/event/market/TimeAndSale.cpp | 8 +++ src/event/market/Trade.cpp | 7 +++ src/event/market/TradeBase.cpp | 8 +++ src/event/market/TradeETH.cpp | 7 +++ src/event/misc/Message.cpp | 8 +++ src/event/option/Greeks.cpp | 8 +++ src/event/option/Series.cpp | 8 +++ src/event/option/TheoPrice.cpp | 8 +++ src/event/option/Underlying.cpp | 8 +++ src/isolated/api/IsolatedDXFeed.cpp | 2 +- src/isolated/event/IsolatedEventType.cpp | 4 +- tests/CMakeLists.txt | 1 + tests/event/EventsTest.cpp | 53 +++++++++++++++++++ tests/symbols/SymbolWrapperTest.cpp | 2 +- 49 files changed, 336 insertions(+), 35 deletions(-) create mode 100644 tests/event/EventsTest.cpp diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index 25878adbf..febf77de8 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -128,6 +128,8 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { void *getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol, std::int64_t fromTime, std::int64_t toTime) const; + std::shared_ptr getLastEventImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol) const; + protected: DXFeed() noexcept : handle_{} { if constexpr (Debugger::isDebug) { @@ -207,12 +209,12 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * of subscription. * *

This method fills in the values for the last event into the `event argument. - * If the last event is not available for any reason (no subscription, no connection to uplink, etc). + * If the last event is not available for any reason (no subscription, no connection to uplink, etc.) * then the event object is not changed. * This method always returns the same `event` instance that is passed to it as an argument. * *

This method provides no way to distinguish a case when there is no subscription from the case when - * there is a subscription, but the event data have not arrived yet. It is recommened to use + * there is a subscription, but the event data have not arrived yet. It is recommended to use * @ref ::getLastEventIfSubscribed() "getLastEventIfSubscribed" method instead of this `getLastEvent` method to * fail-fast in case when the subscription was supposed to be set by the logic of the code, since * @ref ::getLastEventIfSubscribed() "getLastEventIfSubscribed" method returns null when there is no subscription. @@ -224,7 +226,11 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param event the event. * @return The same event. */ - template E> std::shared_ptr getLastEvent(std::shared_ptr event); + template E> std::shared_ptr getLastEvent(std::shared_ptr event) { + event->assign(getLastEventImpl(E::TYPE, event->getEventSymbol())); + + return event; + } /** * Creates new subscription for a single event type that is attached to this feed. diff --git a/include/dxfeed_graal_cpp_api/event/EventType.hpp b/include/dxfeed_graal_cpp_api/event/EventType.hpp index e6e2a02ff..af6b93252 100644 --- a/include/dxfeed_graal_cpp_api/event/EventType.hpp +++ b/include/dxfeed_graal_cpp_api/event/EventType.hpp @@ -72,6 +72,15 @@ struct DXFCPP_EXPORT EventType : public SharedEntity { */ virtual void *toGraal() const = 0; + /** + * Replaces the contents of the event. + * + * @param event the event to use as source. + */ + virtual void assign(std::shared_ptr event) { + ignore_unused(event); + } + /// std::string toString() const override { return "EventType{}"; @@ -111,14 +120,14 @@ template struct DXFCPP_EXPORT EventTypeWithSymbol : public Eve * * @return The event symbol. */ - virtual const Symbol &getEventSymbol() const& noexcept = 0; + virtual const Symbol &getEventSymbol() const & noexcept = 0; /** * Returns event symbol that identifies this event type in @ref DXFeedSubscription "subscription". * * @return The event symbol or std::nullopt. */ - virtual const std::optional &getEventSymbolOpt() const& noexcept = 0; + virtual const std::optional &getEventSymbolOpt() const & noexcept = 0; /** * Changes event symbol that identifies this event type in @ref DXFeedSubscription "subscription". diff --git a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp index 37caec072..dffba65fd 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp @@ -142,6 +142,9 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, */ void *toGraal() const override; + /// + void assign(std::shared_ptr event) override; + /** * Releases the memory occupied by the dxFeed Graal SDK structure (recursively if necessary). * diff --git a/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp index d40d7cf2c..a17a5b8f7 100644 --- a/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/AnalyticOrder.hpp @@ -110,6 +110,9 @@ class DXFCPP_EXPORT AnalyticOrder final : public Order { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new analytic order event with default values. AnalyticOrder() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/MarketEvent.hpp b/include/dxfeed_graal_cpp_api/event/market/MarketEvent.hpp index 7fab6bee8..479d54b5b 100644 --- a/include/dxfeed_graal_cpp_api/event/market/MarketEvent.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/MarketEvent.hpp @@ -9,8 +9,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include #include -#include #include +#include #include "../EventType.hpp" @@ -46,6 +46,14 @@ struct DXFCPP_EXPORT MarketEvent : public EventTypeWithSymbol { static void freeGraalData(void *graalNative) noexcept; public: + /// + void assign(std::shared_ptr event) override { + if (const auto other = event->sharedAs(); other) { + eventSymbol_ = other->eventSymbol_; + eventTime_ = other->eventTime_; + } + } + /** * Returns symbol of this event. * diff --git a/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp b/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp index 042a007bd..9da1bb27a 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OptionSale.hpp @@ -128,6 +128,9 @@ class DXFCPP_EXPORT OptionSale final : public MarketEvent, public IndexedEvent { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new option sale event with default values. OptionSale() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/Order.hpp b/include/dxfeed_graal_cpp_api/event/market/Order.hpp index 208ae0b16..b84bb2477 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Order.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Order.hpp @@ -142,6 +142,9 @@ class DXFCPP_EXPORT Order : public OrderBase { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new order event with default values. Order() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp index 0b77c52f5..6907dc998 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp @@ -165,6 +165,9 @@ class DXFCPP_EXPORT OrderBase : public MarketEvent, public IndexedEvent { */ static constexpr std::uint32_t MAX_SEQUENCE = (1U << 22U) - 1U; + /// + void assign(std::shared_ptr event) override; + /// Creates new order event with default values. OrderBase() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp index 068a02c82..9436ee5f1 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OtcMarketsOrder.hpp @@ -177,6 +177,9 @@ class DXFCPP_EXPORT OtcMarketsOrder final : public Order { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new OTC Markets order event with default values. OtcMarketsOrder() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/Profile.hpp b/include/dxfeed_graal_cpp_api/event/market/Profile.hpp index 16c00f7d8..7c0ad5aaa 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Profile.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Profile.hpp @@ -108,6 +108,9 @@ class DXFCPP_EXPORT Profile final : public MarketEvent, public LastingEvent { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new profile event with default values. Profile() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/Quote.hpp b/include/dxfeed_graal_cpp_api/event/market/Quote.hpp index 8d8ff6889..76aa55bd5 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Quote.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Quote.hpp @@ -101,6 +101,9 @@ class DXFCPP_EXPORT Quote final : public MarketEvent, public LastingEvent { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new quote event with default values. Quote() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp b/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp index ab943f027..28ed0acf6 100644 --- a/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/SpreadOrder.hpp @@ -141,6 +141,9 @@ class DXFCPP_EXPORT SpreadOrder : public OrderBase { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new spread order event with default values. SpreadOrder() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/Summary.hpp b/include/dxfeed_graal_cpp_api/event/market/Summary.hpp index 3db8194b6..1f1d6c72f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Summary.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Summary.hpp @@ -99,6 +99,9 @@ class DXFCPP_EXPORT Summary final : public MarketEvent, public LastingEvent { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new summary event with default values. Summary() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp b/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp index 495d454ed..68d5830af 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TimeAndSale.hpp @@ -156,6 +156,9 @@ class DXFCPP_EXPORT TimeAndSale final : public MarketEvent, public TimeSeriesEve */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new time and sale event with default values. TimeAndSale() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/Trade.hpp b/include/dxfeed_graal_cpp_api/event/market/Trade.hpp index 0dd1f83ad..b86abe54e 100644 --- a/include/dxfeed_graal_cpp_api/event/market/Trade.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/Trade.hpp @@ -113,6 +113,9 @@ class DXFCPP_EXPORT Trade final : public TradeBase { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new trade event with default values. Trade() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp b/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp index d8e54ce2f..cbff924f4 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TradeBase.hpp @@ -81,6 +81,9 @@ class DXFCPP_EXPORT TradeBase : public MarketEvent, public LastingEvent { */ static constexpr std::uint32_t MAX_SEQUENCE = (1U << 22U) - 1U; + /// + void assign(std::shared_ptr event) override; + /// Creates new trade event with default values. TradeBase() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp b/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp index 9ef8f435d..7502b77eb 100644 --- a/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/TradeETH.hpp @@ -138,6 +138,9 @@ class DXFCPP_EXPORT TradeETH final : public TradeBase { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new trade event with default values. TradeETH() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/misc/Message.hpp b/include/dxfeed_graal_cpp_api/event/misc/Message.hpp index 38c8b3be8..d816136ce 100644 --- a/include/dxfeed_graal_cpp_api/event/misc/Message.hpp +++ b/include/dxfeed_graal_cpp_api/event/misc/Message.hpp @@ -77,6 +77,9 @@ class DXFCPP_EXPORT Message : public EventTypeWithSymbol { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /** * Creates new message with default values. */ diff --git a/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp b/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp index ea5c1f420..042ac6981 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Greeks.hpp @@ -123,6 +123,9 @@ class DXFCPP_EXPORT Greeks final : public MarketEvent, public TimeSeriesEvent, p */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new greeks event with default values. Greeks() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/option/Series.hpp b/include/dxfeed_graal_cpp_api/event/option/Series.hpp index 46c26d65b..cfc17f172 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Series.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Series.hpp @@ -131,6 +131,9 @@ class DXFCPP_EXPORT Series final : public MarketEvent, public IndexedEvent { */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new series event with default values. Series() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp b/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp index 6643302c2..e65c0ce34 100644 --- a/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/TheoPrice.hpp @@ -130,6 +130,9 @@ class DXFCPP_EXPORT TheoPrice final : public MarketEvent, public TimeSeriesEvent */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new theoprice event with default values. TheoPrice() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp b/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp index 80aad0b94..78a08cb3d 100644 --- a/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp +++ b/include/dxfeed_graal_cpp_api/event/option/Underlying.hpp @@ -126,6 +126,9 @@ class DXFCPP_EXPORT Underlying final : public MarketEvent, public TimeSeriesEven */ static void freeGraal(void *graalNative); + /// + void assign(std::shared_ptr event) override; + /// Creates new underlying event with default values. Underlying() noexcept = default; diff --git a/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp b/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp index 460fc91f8..9c37d9630 100644 --- a/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/event/IsolatedEventType.hpp @@ -11,29 +11,29 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE -namespace isolated::events { -namespace IsolatetEventType { +namespace isolated::event { +namespace IsolatedEventType { // dxfg_EventType_new -/* dxfg_event_type_t* */ void* create(const StringLikeWrapper& symbolName, /* dxfg_event_clazz_t */ const EventTypeEnum& eventType); +/* dxfg_event_type_t* */ void *create(const StringLikeWrapper &symbolName, + /* dxfg_event_clazz_t */ const EventTypeEnum &eventType); // dxfg_EventType_release -/* int32_t */ void release(/* dxfg_event_type_t* */ void* eventType); +/* int32_t */ void release(/* dxfg_event_type_t* */ void *eventType); std::unique_ptr toUnique(void *eventType); } // namespace IsolatetEventType - -namespace IsolatetEventTypeList { +namespace IsolatedEventTypeList { // dxfg_CList_EventType_release -/* int32_t */ void release(/* dxfg_event_type_list* */ void* eventTypes); +/* int32_t */ void release(/* dxfg_event_type_list* */ void *eventTypes); std::unique_ptr toUnique(void *eventTypes); -} -} // namespace isolated::events +} // namespace IsolatetEventTypeList +} // namespace isolated::event DXFCPP_END_NAMESPACE diff --git a/samples/cpp/DxFeedSample/src/main.cpp b/samples/cpp/DxFeedSample/src/main.cpp index c50ec59b4..e2e59bfb3 100644 --- a/samples/cpp/DxFeedSample/src/main.cpp +++ b/samples/cpp/DxFeedSample/src/main.cpp @@ -4,10 +4,13 @@ #include #include +#include +#include -void testQuoteListener(const std::string &symbol) { - using namespace dxfcpp; +using namespace dxfcpp; +using namespace std::literals; +void testQuoteListener(const std::string &symbol) { // Creates a subscription attached to a default DXFeed with a Quote event type. // The endpoint address to use is stored in the "dxfeed.properties" file. auto subscription = DXFeed::getInstance()->createSubscription(Quote::TYPE); @@ -25,8 +28,6 @@ void testQuoteListener(const std::string &symbol) { } void testQuoteAndTradeListener(const std::string &symbol) { - using namespace dxfcpp; - // Creates a subscription attached to a default DXFeed with a Quote and Trade event types. // The endpoint address to use is stored in the "dxfeed.properties" file. auto subscription = DXFeed::getInstance()->createSubscription({Quote::TYPE, Trade::TYPE}); @@ -43,10 +44,29 @@ void testQuoteAndTradeListener(const std::string &symbol) { } }); + // Another way to subscribe: + // subscription->addEventListener([](const auto &events) { + // for (const auto &e : events) { + // std::cout << e->toString() + "\n"; + // } + // }); + // Adds specified symbol. subscription->addSymbols(symbol); } +void testTradeSnapshots(const std::string &symbol) { + auto feed = DXFeed::getInstance(); + auto sub = feed->createSubscription(Trade::TYPE); + + sub->addSymbols(symbol); + + while (true) { + std::cout << feed->getLastEvent(std::make_shared(symbol))->toString() + "\n"; + std::this_thread::sleep_for(1000ms); + } +} + /* * Creates multiple event listener and subscribe to Quote and Trade events. * Use default DXFeed instance for that data feed address is defined by "dxfeed.properties" file. @@ -73,8 +93,9 @@ DxFeedSample testQuoteListener(symbol); testQuoteAndTradeListener(symbol); + testTradeSnapshots(symbol); - std::cin.get(); + //std::cin.get(); } catch (const RuntimeException &e) { std::cerr << e << '\n'; } diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 1879502ee..43d530cc1 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -81,11 +81,6 @@ void DXFeed::detachSubscriptionAndClear(std::shared_ptr subs } } -template E> std::shared_ptr DXFeed::getLastEvent(std::shared_ptr event) { - //TODO: implement - return event; -} - std::shared_ptr DXFeed::createSubscription(const EventTypeEnum &eventType) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventType = " + eventType.getName() + ")"); @@ -131,6 +126,10 @@ void *DXFeed::getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const Sym return isolated::api::IsolatedDXFeed::getTimeSeriesPromise(handle_, eventType, symbol, fromTime, toTime); } +std::shared_ptr DXFeed::getLastEventImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol) const { + return isolated::api::IsolatedDXFeed::getLastEvent(handle_, symbol.toStringUnderlying(), eventType); +} + std::string DXFeed::toString() const { return fmt::format("DXFeed{{{}}}", handle_.toString()); } diff --git a/src/event/candle/Candle.cpp b/src/event/candle/Candle.cpp index d25af22e5..11a977018 100644 --- a/src/event/candle/Candle.cpp +++ b/src/event/candle/Candle.cpp @@ -106,14 +106,20 @@ void *Candle::toGraal() const { Debugger::debug(toString() + "::toGraal()"); } - auto *graalCandle = - new dxfg_candle_t{}; + auto *graalCandle = new dxfg_candle_t{}; fillGraalData(static_cast(graalCandle)); return static_cast(graalCandle); } +void Candle::assign(std::shared_ptr event) { + if (const auto other = event->sharedAs(); other) { + eventSymbol_ = other->eventSymbol_; + data_ = other->data_; + } +} + void Candle::freeGraal(void *graalNative) { if (!graalNative) { return; @@ -124,7 +130,6 @@ void Candle::freeGraal(void *graalNative) { fmt::format("Unable to free Candle's Graal data. Wrong event class {}! Expected: {}.", std::to_string(static_cast(static_cast(graalNative)->clazz)), std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_CANDLE)))); - } auto graalCandle = static_cast(graalNative); diff --git a/src/event/market/AnalyticOrder.cpp b/src/event/market/AnalyticOrder.cpp index 4df5b1bc5..a1257fac6 100644 --- a/src/event/market/AnalyticOrder.cpp +++ b/src/event/market/AnalyticOrder.cpp @@ -105,4 +105,12 @@ void AnalyticOrder::freeGraal(void *graalNative) { delete graalAnalyticOrder; } +void AnalyticOrder::assign(std::shared_ptr event) { + Order::assign(event); + + if (const auto other = event->sharedAs(); other) { + analyticOrderData_ = other->analyticOrderData_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/OptionSale.cpp b/src/event/market/OptionSale.cpp index 9c17558c0..53ee9307e 100644 --- a/src/event/market/OptionSale.cpp +++ b/src/event/market/OptionSale.cpp @@ -100,11 +100,11 @@ std::shared_ptr OptionSale::fromGraal(void *graalNative) { std::to_string(static_cast(dxfg_event_clazz_t::DXFG_EVENT_OPTION_SALE)))); } - auto optionSale = std::make_shared(); + auto optionSale = std::make_shared(); - optionSale->fillData(graalNative); + optionSale->fillData(graalNative); - return optionSale; + return optionSale; } void OptionSale::setExchangeCode(char exchangeCode) noexcept { @@ -153,4 +153,12 @@ void OptionSale::freeGraal(void *graalNative) { delete graalOptionSale; } +void OptionSale::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/Order.cpp b/src/event/market/Order.cpp index 8fa1ea2a2..a77f84786 100644 --- a/src/event/market/Order.cpp +++ b/src/event/market/Order.cpp @@ -107,4 +107,12 @@ void Order::freeGraal(void *graalNative) { delete graalOrder; } +void Order::assign(std::shared_ptr event) { + OrderBase::assign(event); + + if (const auto other = event->sharedAs(); other) { + orderData_ = other->orderData_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/OrderBase.cpp b/src/event/market/OrderBase.cpp index bd836b8b1..de46fed4a 100644 --- a/src/event/market/OrderBase.cpp +++ b/src/event/market/OrderBase.cpp @@ -67,6 +67,14 @@ void OrderBase::fillGraalData(void *graalNative) const noexcept { graalOrderBase->trade_size = orderBaseData_.tradeSize; } +void OrderBase::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + orderBaseData_ = other->orderBaseData_; + } +} + std::string OrderBase::baseFieldsToString() const { return fmt::format( "{}, eventTime={}, source={}, eventFlags={:#x}, index={:#x}, time={}, sequence={}, " diff --git a/src/event/market/OtcMarketsOrder.cpp b/src/event/market/OtcMarketsOrder.cpp index 11b9d5196..08b94b283 100644 --- a/src/event/market/OtcMarketsOrder.cpp +++ b/src/event/market/OtcMarketsOrder.cpp @@ -102,4 +102,12 @@ void OtcMarketsOrder::freeGraal(void *graalNative) { delete graalOtcMarketsOrder; } +void OtcMarketsOrder::assign(std::shared_ptr event) { + Order::assign(event); + + if (const auto other = event->sharedAs(); other) { + otcMarketsOrderData_ = other->otcMarketsOrderData_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/Profile.cpp b/src/event/market/Profile.cpp index 785dfb39c..710dd565d 100644 --- a/src/event/market/Profile.cpp +++ b/src/event/market/Profile.cpp @@ -156,4 +156,12 @@ void Profile::freeGraal(void *graalNative) { delete graalProfile; } +void Profile::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/Quote.cpp b/src/event/market/Quote.cpp index 797d015f3..34251eddd 100644 --- a/src/event/market/Quote.cpp +++ b/src/event/market/Quote.cpp @@ -161,4 +161,12 @@ void Quote::freeGraal(void *graalNative) { delete graalQuote; } +void Quote::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/SpreadOrder.cpp b/src/event/market/SpreadOrder.cpp index bd7cd3a14..c0b16fe54 100644 --- a/src/event/market/SpreadOrder.cpp +++ b/src/event/market/SpreadOrder.cpp @@ -107,4 +107,12 @@ void SpreadOrder::freeGraal(void *graalNative) { delete graalSpreadOrder; } +void SpreadOrder::assign(std::shared_ptr event) { + OrderBase::assign(event); + + if (const auto other = event->sharedAs(); other) { + spreadOrderData_ = other->spreadOrderData_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/Summary.cpp b/src/event/market/Summary.cpp index febfacc5b..2db9ecbc2 100644 --- a/src/event/market/Summary.cpp +++ b/src/event/market/Summary.cpp @@ -128,4 +128,12 @@ void Summary::freeGraal(void *graalNative) { delete graalSummary; } +void Summary::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs

(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/TimeAndSale.cpp b/src/event/market/TimeAndSale.cpp index 6f7bd7521..34073b310 100644 --- a/src/event/market/TimeAndSale.cpp +++ b/src/event/market/TimeAndSale.cpp @@ -152,4 +152,12 @@ void TimeAndSale::freeGraal(void *graalNative) { delete graalTimeAndSale; } +void TimeAndSale::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/Trade.cpp b/src/event/market/Trade.cpp index 67986ce72..5fcad493f 100644 --- a/src/event/market/Trade.cpp +++ b/src/event/market/Trade.cpp @@ -94,4 +94,11 @@ void Trade::freeGraal(void *graalNative) { delete graalTrade; } +void Trade::assign(std::shared_ptr event) { + TradeBase::assign(event); + + // if (const auto other = event->sharedAs(); other) { + // } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/market/TradeBase.cpp b/src/event/market/TradeBase.cpp index 53c717045..9e828fbc9 100644 --- a/src/event/market/TradeBase.cpp +++ b/src/event/market/TradeBase.cpp @@ -57,6 +57,14 @@ void TradeBase::fillGraalData(void *graalNative) const noexcept { graalTradeBase->flags = tradeBaseData_.flags; } +void TradeBase::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + tradeBaseData_ = other->tradeBaseData_; + } +} + std::string TradeBase::baseFieldsToString() const { return fmt::format("{}, eventTime={}, time={}, timeNanoPart={}, sequence={}, exchange={}, price={}, " "change={}, size={}, day={}, dayVolume={}, dayTurnover={}, " diff --git a/src/event/market/TradeETH.cpp b/src/event/market/TradeETH.cpp index f8fbb8dca..1b65d2605 100644 --- a/src/event/market/TradeETH.cpp +++ b/src/event/market/TradeETH.cpp @@ -94,4 +94,11 @@ void TradeETH::freeGraal(void *graalNative) { delete graalTradeEth; } +void TradeETH::assign(std::shared_ptr event) { + TradeBase::assign(event); + + // if (const auto other = event->sharedAs(); other) { + // } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/misc/Message.cpp b/src/event/misc/Message.cpp index 9d2650a00..f7b6a5b11 100644 --- a/src/event/misc/Message.cpp +++ b/src/event/misc/Message.cpp @@ -113,6 +113,14 @@ void Message::freeGraal(void *graalNative) { delete graalMessage; } +void Message::assign(std::shared_ptr event) { + if (const auto other = event->sharedAs(); other) { + eventSymbol_ = other->eventSymbol_; + eventTime_ = other->eventTime_; + attachment_ = other->attachment_; + } +} + std::string Message::toString() const { return fmt::format("Message{{{}, eventTime={}, attachment={}}}", getEventSymbol(), TimeFormat::DEFAULT_WITH_MILLIS.format(getEventTime()), attachment_.value_or(String::NUL)); diff --git a/src/event/option/Greeks.cpp b/src/event/option/Greeks.cpp index a51a7c05e..980285143 100644 --- a/src/event/option/Greeks.cpp +++ b/src/event/option/Greeks.cpp @@ -124,4 +124,12 @@ void Greeks::freeGraal(void *graalNative) { delete graalGreeks; } +void Greeks::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/option/Series.cpp b/src/event/option/Series.cpp index e0be71656..24de3e45f 100644 --- a/src/event/option/Series.cpp +++ b/src/event/option/Series.cpp @@ -128,4 +128,12 @@ void Series::freeGraal(void *graalNative) { delete graalSeries; } +void Series::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/option/TheoPrice.cpp b/src/event/option/TheoPrice.cpp index 1e69b1810..1ac54cc3f 100644 --- a/src/event/option/TheoPrice.cpp +++ b/src/event/option/TheoPrice.cpp @@ -121,4 +121,12 @@ void TheoPrice::freeGraal(void *graalNative) { delete graalTheoPrice; } +void TheoPrice::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/event/option/Underlying.cpp b/src/event/option/Underlying.cpp index 00c2245b0..712b4c799 100644 --- a/src/event/option/Underlying.cpp +++ b/src/event/option/Underlying.cpp @@ -122,4 +122,12 @@ void Underlying::freeGraal(void *graalNative) { delete graalUnderlying; } +void Underlying::assign(std::shared_ptr event) { + MarketEvent::assign(event); + + if (const auto other = event->sharedAs(); other) { + data_ = other->data_; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp index 40453aba0..1498a8732 100644 --- a/src/isolated/api/IsolatedDXFeed.cpp +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -19,7 +19,7 @@ namespace isolated::api::IsolatedDXFeed { "Unable to execute function `dxfg_DXFeed_getLastEvent`. The `feed` handle is invalid"); } - auto e = events::IsolatetEventType::toUnique(events::IsolatetEventType::create(symbolName, eventType)); + auto e = event::IsolatedEventType::toUnique(event::IsolatedEventType::create(symbolName, eventType)); return EventMapper::fromGraal(e.get()); } diff --git a/src/isolated/event/IsolatedEventType.cpp b/src/isolated/event/IsolatedEventType.cpp index e09bc9ec2..0d389d01c 100644 --- a/src/isolated/event/IsolatedEventType.cpp +++ b/src/isolated/event/IsolatedEventType.cpp @@ -8,7 +8,7 @@ DXFCPP_BEGIN_NAMESPACE -namespace isolated::internal { +namespace isolated::event { namespace IsolatedEventType { // dxfg_EventType_new @@ -49,6 +49,6 @@ std::unique_ptr toUnique(void *eventTypes) { return {eventTypes, release}; } } // namespace IsolatedEventTypeList -} // namespace isolated::internal +} // namespace isolated::event DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b23bf2fdd..10b9c4027 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,6 +28,7 @@ set(DXFC_TEST_SOURCES api/EventsTest.cpp api/MarketEventSymbolsTest.cpp api/OrderSourceTest.cpp + event/EventsTest.cpp schedule/ScheduleTest.cpp symbols/SymbolWrapperTest.cpp system/SystemTest.cpp) diff --git a/tests/event/EventsTest.cpp b/tests/event/EventsTest.cpp new file mode 100644 index 000000000..80e1d8f88 --- /dev/null +++ b/tests/event/EventsTest.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#include +#include +#include +#include + +#include +#include + +#include + +using namespace dxfcpp; +using namespace dxfcpp::literals; +using namespace std::literals; + +TEST_CASE("The Candle::assign method must set all fields") { + auto c1 = std::make_shared(CandleSymbol::valueOf("AAPL&Q")); + c1->setEventTime(100); + + auto c2 = std::make_shared(CandleSymbol::valueOf("IBM")); + + c2->setEventTime(1200); + + // index + c2->setTime(222); + c2->setSequence(23); + + c2->setCount(5); + + c2->setOpen(50.1); + c2->setHigh(100.2); + c2->setLow(40.3); + c2->setClose(34.4); + + c2->setVolume(1000.34); + c2->setVWAP(34.22); + c2->setBidVolume(1234.33); + c2->setAskVolume(14.44); + c2->setImpVolatility(200); + c2->setOpenInterest(200); + + auto c3 = std::make_shared(); + + c3->assign(c1); + c1->assign(c2); + + REQUIRE(c1->toString() == c2->toString()); + REQUIRE(c1->toString() != c3->toString()); +} \ No newline at end of file diff --git a/tests/symbols/SymbolWrapperTest.cpp b/tests/symbols/SymbolWrapperTest.cpp index a597065f4..d73addba9 100644 --- a/tests/symbols/SymbolWrapperTest.cpp +++ b/tests/symbols/SymbolWrapperTest.cpp @@ -17,7 +17,7 @@ using namespace dxfcpp; using namespace dxfcpp::literals; using namespace std::literals; -TEST_CASE("SymbolWrapper::toStringUnderlying") { +TEST_CASE("SymbolWrapper::toStringUnderlying should return the result of toString called on the underlying symbol") { auto c = CandleSymbol::valueOf("AAPL&Q{=1m}"); REQUIRE(SymbolWrapper(c).toStringUnderlying() == c.toString()); From 218a7a289559bf0f902cf38803a01a6801635d60 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 26 Jul 2024 12:47:47 +0300 Subject: [PATCH 064/178] [MDAPI-37][C++] Retrieve latest events from feed Fix IsolatedDXFeed::getLastEvent --- samples/cpp/DxFeedSample/src/main.cpp | 4 +--- src/isolated/api/IsolatedDXFeed.cpp | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/samples/cpp/DxFeedSample/src/main.cpp b/samples/cpp/DxFeedSample/src/main.cpp index e2e59bfb3..129784c20 100644 --- a/samples/cpp/DxFeedSample/src/main.cpp +++ b/samples/cpp/DxFeedSample/src/main.cpp @@ -62,7 +62,7 @@ void testTradeSnapshots(const std::string &symbol) { sub->addSymbols(symbol); while (true) { - std::cout << feed->getLastEvent(std::make_shared(symbol))->toString() + "\n"; + std::cout << "LAST: " + feed->getLastEvent(std::make_shared(symbol))->toString() + "\n"; std::this_thread::sleep_for(1000ms); } } @@ -94,8 +94,6 @@ DxFeedSample testQuoteListener(symbol); testQuoteAndTradeListener(symbol); testTradeSnapshots(symbol); - - //std::cin.get(); } catch (const RuntimeException &e) { std::cerr << e << '\n'; } diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp index 1498a8732..3e6e0df69 100644 --- a/src/isolated/api/IsolatedDXFeed.cpp +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -11,24 +11,30 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeed { - // dxfg_DXFeed_getLastEvent -/* int32_t */ std::shared_ptr getLastEvent(/* dxfg_feed_t * */ const JavaObjectHandle& feed, /* dxfg_event_type_t * */ const StringLikeWrapper& symbolName, const EventTypeEnum& eventType) { +/* int32_t */ std::shared_ptr getLastEvent(/* dxfg_feed_t * */ const JavaObjectHandle &feed, + /* dxfg_event_type_t * */ const StringLikeWrapper &symbolName, + const EventTypeEnum &eventType) { if (!feed) { throw InvalidArgumentException( "Unable to execute function `dxfg_DXFeed_getLastEvent`. The `feed` handle is invalid"); } - auto e = event::IsolatedEventType::toUnique(event::IsolatedEventType::create(symbolName, eventType)); + const auto e = event::IsolatedEventType::toUnique(event::IsolatedEventType::create(symbolName, eventType)); + + runGraalFunctionAndThrowIfMinusOne(dxfg_DXFeed_getLastEvent, static_cast(feed.get()), + static_cast(e.get())); return EventMapper::fromGraal(e.get()); } /* -int32_t dxfg_DXFeed_getLastEvents(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_list *events); -dxfg_promise_event_t* dxfg_DXFeed_getLastEventPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); -dxfg_promise_list* dxfg_DXFeed_getLastEventsPromises(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_list *symbols); -dxfg_promise_events_t* dxfg_DXFeed_getIndexedEventsPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, dxfg_indexed_event_source_t* source); +int32_t dxfg_DXFeed_getLastEvents(graal_isolatethread_t *thread, dxfg_feed_t *feed, +dxfg_event_type_list *events); dxfg_promise_event_t* dxfg_DXFeed_getLastEventPromise(graal_isolatethread_t +*thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); dxfg_promise_list* +dxfg_DXFeed_getLastEventsPromises(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, +dxfg_symbol_list *symbols); dxfg_promise_events_t* dxfg_DXFeed_getIndexedEventsPromise(graal_isolatethread_t +*thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, dxfg_indexed_event_source_t* source); */ From 718b9901ac2d4f43862f69acc39be8c760587f77 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 26 Jul 2024 14:14:02 +0300 Subject: [PATCH 065/178] [MDAPI-37][C++] Retrieve latest events from feed DXFeed::getLastEvents --- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 21 ++++++++++++++++++++- samples/cpp/DxFeedSample/src/main.cpp | 10 +++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index febf77de8..804299831 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -223,7 +223,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @ref DXEndpoint::Role::STREAM_FEED "STREAM_FEED" role (never fills in the event). * * @tparam E The type of event. - * @param event the event. + * @param event The event. * @return The same event. */ template E> std::shared_ptr getLastEvent(std::shared_ptr event) { @@ -232,6 +232,25 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return event; } + /** + * Returns the last events for the specified list of event instances. + * This is a bulk version of @ref ::getLastEvent() "getLastEvent" method. + * + *

Note, that this method does not work when DXEndpoint was created with + * @ref DXEndpoint::Role::STREAM_FEED "STREAM_FEED" role. + * + * @tparam Collection The collection type. + * @param events The collection of shared ptrs of events. + * @return The same collection of shared ptrs of events. + */ + template const Collection &getLastEvents(const Collection &events) { + for (auto e : events) { + getLastEvent(e); + } + + return events; + } + /** * Creates new subscription for a single event type that is attached to this feed. * This method creates new DXFeedSubscription and invokes @link DXFeed::attachSubscription. diff --git a/samples/cpp/DxFeedSample/src/main.cpp b/samples/cpp/DxFeedSample/src/main.cpp index 129784c20..b90a6f1d3 100644 --- a/samples/cpp/DxFeedSample/src/main.cpp +++ b/samples/cpp/DxFeedSample/src/main.cpp @@ -3,8 +3,8 @@ #include -#include #include +#include #include using namespace dxfcpp; @@ -59,6 +59,14 @@ void testTradeSnapshots(const std::string &symbol) { auto feed = DXFeed::getInstance(); auto sub = feed->createSubscription(Trade::TYPE); + std::vector e = {std::make_shared("AAPL"), std::make_shared("IBM")}; + auto x = std::remove_reference_t>::iterator>::value_type>>(); + + decltype(x) y; + + auto z = feed->getLastEvents(e); + sub->addSymbols(symbol); while (true) { From 9b601853043e436031dd997d3ff2bb2a13a33e44 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 26 Jul 2024 14:30:28 +0300 Subject: [PATCH 066/178] [MDAPI-37][C++] Retrieve latest events from feed DXFeed::getLastEvents --- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 9 ++++++++- samples/cpp/DxFeedSample/src/main.cpp | 8 -------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index 804299831..5241e9749 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -243,7 +243,14 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param events The collection of shared ptrs of events. * @return The same collection of shared ptrs of events. */ - template const Collection &getLastEvents(const Collection &events) { + template , + typename Event = std::decay_t> + const Collection &getLastEvents(const Collection &events) { + static_assert( + std::is_same_v> && std::is_base_of_v, + "The collection element must be of type `std::shared_ptr`, where `Event` is a descendant of " + "`LastingEvent`"); + for (auto e : events) { getLastEvent(e); } diff --git a/samples/cpp/DxFeedSample/src/main.cpp b/samples/cpp/DxFeedSample/src/main.cpp index b90a6f1d3..f7d317872 100644 --- a/samples/cpp/DxFeedSample/src/main.cpp +++ b/samples/cpp/DxFeedSample/src/main.cpp @@ -59,14 +59,6 @@ void testTradeSnapshots(const std::string &symbol) { auto feed = DXFeed::getInstance(); auto sub = feed->createSubscription(Trade::TYPE); - std::vector e = {std::make_shared("AAPL"), std::make_shared("IBM")}; - auto x = std::remove_reference_t>::iterator>::value_type>>(); - - decltype(x) y; - - auto z = feed->getLastEvents(e); - sub->addSymbols(symbol); while (true) { From cf62ece1e509a9bd4aca648d974d6ee6bedd3992 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 26 Jul 2024 15:24:25 +0300 Subject: [PATCH 067/178] [MDAPI-37][C++] Retrieve latest events from feed DXFeed::getLastEventIfSubscribed --- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 37 ++++++++++++++++++- .../isolated/api/IsolatedDXFeed.hpp | 27 ++++++++++---- src/api/DXFeed.cpp | 5 ++- src/isolated/api/IsolatedDXFeed.cpp | 31 ++++++++++++++-- 4 files changed, 84 insertions(+), 16 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index 5241e9749..7739e80ae 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -128,7 +128,8 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { void *getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol, std::int64_t fromTime, std::int64_t toTime) const; - std::shared_ptr getLastEventImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol) const; + std::shared_ptr getLastEventIfSubscribedImpl(const EventTypeEnum &eventType, + const SymbolWrapper &symbol) const; protected: DXFeed() noexcept : handle_{} { @@ -227,7 +228,9 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @return The same event. */ template E> std::shared_ptr getLastEvent(std::shared_ptr event) { - event->assign(getLastEventImpl(E::TYPE, event->getEventSymbol())); + if (auto last = getLastEventIfSubscribed(event->getEventSymbol())) { + event->assign(last); + } return event; } @@ -258,6 +261,36 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return events; } + /** + * Returns the last event for the specified event type and symbol if there is a subscription for it. + * This method works only for event types that implement LastingEvent marker interface. + * This method does not make any remote calls to the uplink data provider. + * It just retrieves last received event from the local cache of this feed. + * The events are stored in the cache only if there is some attached DXFeedSubscription that is subscribed to the + * corresponding event type and symbol. + * The subscription can also be permanently defined using DXEndpoint properties. + * WildcardSymbol::ALL subscription does not count for that purpose. + * If there is no subscription, then this method returns `std::shared_ptr(nullptr)`. + * + *

If there is a subscription, but the event has not arrived from the uplink data provider, + * this method returns an non-initialized event object: its @ref EventType#getEventSymbol() "eventSymbol" + * property is set to the requested symbol, but all the other properties have their default values. + * + *

Use @ref ::getLastEventPromise() "getLastEventPromise" method if an event needs to be requested in the + * absence of subscription. + * + *

Note, that this method does not work when DXEndpoint} was created with @ref DXEndpoint::Role::STREAM_FEED + * "STREAM_FEED" role (always returns `std::shared_ptr(nullptr)`). + * + * @tparam E The type of event. + * @param symbol The symbol. + * @return the event or `std::shared_ptr(nullptr)` if there is no subscription for the specified event type and + * symbol. + */ + template E> std::shared_ptr getLastEventIfSubscribed(const SymbolWrapper &symbol) { + return getLastEventIfSubscribedImpl(E::TYPE, symbol)->sharedAs(); + } + /** * Creates new subscription for a single event type that is attached to this feed. * This method creates new DXFeedSubscription and invokes @link DXFeed::attachSubscription. diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp index 72668c35f..fdc576f19 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp @@ -16,14 +16,25 @@ namespace isolated::api::IsolatedDXFeed { /* dxfg_feed_t* dxfg_DXFeed_getInstance(graal_isolatethread_t *thread); -dxfg_subscription_t* dxfg_DXFeed_createSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz); -dxfg_subscription_t* dxfg_DXFeed_createSubscription2(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); -dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz); -dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription2(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); -int32_t dxfg_DXFeed_attachSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); -int32_t dxfg_DXFeed_detachSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); -int32_t dxfg_DXFeed_detachSubscriptionAndClear(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); -dxfg_event_type_t* dxfg_DXFeed_getLastEventIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); +dxfg_subscription_t* dxfg_DXFeed_createSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, +dxfg_event_clazz_t eventClazz); dxfg_subscription_t* dxfg_DXFeed_createSubscription2(graal_isolatethread_t +*thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); dxfg_time_series_subscription_t* +dxfg_DXFeed_createTimeSeriesSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t +eventClazz); dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription2(graal_isolatethread_t *thread, +dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); int32_t dxfg_DXFeed_attachSubscription(graal_isolatethread_t +*thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); int32_t dxfg_DXFeed_detachSubscription(graal_isolatethread_t +*thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); int32_t +dxfg_DXFeed_detachSubscriptionAndClear(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +*/ + +// dxfg_DXFeed_getLastEventIfSubscribed +/* dxfg_event_type_t* */ std::shared_ptr +getLastEventIfSubscribed(/* dxfg_feed_t * */ const JavaObjectHandle &feed, + /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, + /* dxfg_symbol_t * */ const SymbolWrapper &symbol); + +/* + dxfg_event_type_list* dxfg_DXFeed_getIndexedEventsIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, const char *source); dxfg_event_type_list* dxfg_DXFeed_getTimeSeriesIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, int64_t from_time, int64_t to_time); // use dxfg_EventType_new to create an empty structure so that java tries to free up memory when replacing subjects diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 43d530cc1..a8a71d2bb 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -126,8 +126,9 @@ void *DXFeed::getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const Sym return isolated::api::IsolatedDXFeed::getTimeSeriesPromise(handle_, eventType, symbol, fromTime, toTime); } -std::shared_ptr DXFeed::getLastEventImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol) const { - return isolated::api::IsolatedDXFeed::getLastEvent(handle_, symbol.toStringUnderlying(), eventType); +std::shared_ptr DXFeed::getLastEventIfSubscribedImpl(const EventTypeEnum &eventType, + const SymbolWrapper &symbol) const { + return isolated::api::IsolatedDXFeed::getLastEventIfSubscribed(handle_, eventType, symbol); } std::string DXFeed::toString() const { diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp index 3e6e0df69..0fcec9982 100644 --- a/src/isolated/api/IsolatedDXFeed.cpp +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -11,6 +11,31 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeed { +// dxfg_DXFeed_getLastEventIfSubscribed +/* dxfg_event_type_t* */ std::shared_ptr +getLastEventIfSubscribed(/* dxfg_feed_t * */ const JavaObjectHandle &feed, + /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, + /* dxfg_symbol_t * */ const SymbolWrapper &symbol) { + if (!feed) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_DXFeed_getLastEventIfSubscribed`. The `feed` handle is invalid"); + } + + auto graalSymbol = symbol.toGraalUnique(); + + const auto e = static_cast(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeed_getLastEventIfSubscribed, static_cast(feed.get()), + static_cast(eventType.getId()), static_cast(graalSymbol.get()))); + + if (!e) { + return {}; + } + + auto u = event::IsolatedEventType::toUnique(e); + + return EventMapper::fromGraal(u.get()); +} + // dxfg_DXFeed_getLastEvent /* int32_t */ std::shared_ptr getLastEvent(/* dxfg_feed_t * */ const JavaObjectHandle &feed, /* dxfg_event_type_t * */ const StringLikeWrapper &symbolName, @@ -47,14 +72,12 @@ dxfg_symbol_list *symbols); dxfg_promise_events_t* dxfg_DXFeed_getInd "Unable to execute function `dxfg_DXFeed_getTimeSeriesPromise`. The `feed` handle is invalid"); } - auto graalSymbol = symbol.toGraal(); + auto graalSymbol = symbol.toGraalUnique(); auto result = dxfcpp::bit_cast( runGraalFunctionAndThrowIfNullptr(dxfg_DXFeed_getTimeSeriesPromise, static_cast(feed.get()), static_cast(eventType.getId()), - static_cast(graalSymbol), fromTime, toTime)); - - SymbolWrapper::freeGraal(graalSymbol); + static_cast(graalSymbol.get()), fromTime, toTime)); return result; } From b39f3d1ca0e353d35bcdbc9e53842412a255b1b1 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 26 Jul 2024 15:25:51 +0300 Subject: [PATCH 068/178] [MDAPI-37][C++] Retrieve latest events from feed Fix build --- include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index 7739e80ae..60ebc51cb 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -288,7 +288,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * symbol. */ template E> std::shared_ptr getLastEventIfSubscribed(const SymbolWrapper &symbol) { - return getLastEventIfSubscribedImpl(E::TYPE, symbol)->sharedAs(); + return getLastEventIfSubscribedImpl(E::TYPE, symbol)->template sharedAs(); } /** From e0bf48069f28e0d86a06e01db3021787f0f0b0e2 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 26 Jul 2024 15:50:15 +0300 Subject: [PATCH 069/178] [MDAPI-37][C++] Retrieve latest events from feed ReleaseNotes --- ReleaseNotes.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index ac329d786..681beb222 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,10 +1,15 @@ -* **\[MDAPI-113]\[C++]\[Tools]** Tools should report invalid event type - * Added classes: `RuntimeException`, `InvalidArgumentException` +* **\[MDAPI-37]\[C++]** Retrieve latest events from feed. + * Added `SymbolWrapper::toStringUnderlying` method that returns a string representation of the underlying symbol object. + * Added `EventType::assign`. All `EventType` successors can populate their fields using `EventType` successors of the same type. + * Added `DXFeed::getLastEventIfSubscribed` method. + * Added `DXFeed::getLastEvent` and `DXFeed::getLastEvents` methods that use the `DXFeed::getLastEventIfSubscribed` method. +* **\[MDAPI-113]\[C++]\[Tools]** Tools should report invalid event type. + * Added classes: `RuntimeException`, `InvalidArgumentException`. * `InvalidArgumentException`, `GraalException`, `JavaException` are now descendants of the `RuntimeException` class, which can collect stacktrace. * Now an `InvalidArgumentException` exception is thrown instead of the `std::invalid_argument` exception. * `Tools` now reports incorrect event types specified by the user. -* **\[MDAPI-80]\[C++]\[IPF]** Implement custom fields in InstrumentProfile - * The API was migrated to Graal SDK v1.1.22 +* **\[MDAPI-80]\[C++]\[IPF]** Implement custom fields in InstrumentProfile. + * The API was migrated to Graal SDK v1.1.22. * Added methods: * `InstrumentProfile::getField` * `InstrumentProfile::setField` From 4ef3e1c3220dba69cfe7e67fb1ac51f347e51549 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 12 Aug 2024 00:20:26 +0300 Subject: [PATCH 070/178] Replace multiple set_property(TARGET ...) commands with a single set_target_properties() command. --- tests/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 10b9c4027..71be8f280 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -39,7 +39,7 @@ foreach (DXFC_TEST_SOURCE ${DXFC_TEST_SOURCES}) string(REPLACE "/" "_" DXFC_TEST_BASENAME "${DXFC_TEST_BASENAME}") string(REPLACE "\\" "_" DXFC_TEST_BASENAME "${DXFC_TEST_BASENAME}") set(DXFC_TEST_BASENAME dxFeedGraalCxxApi_${DXFC_TEST_BASENAME}) - message("${DXFC_TEST_BASENAME}: ${DXFC_TEST_SOURCE}") + # message("${DXFC_TEST_BASENAME}: ${DXFC_TEST_SOURCE}") add_executable(${DXFC_TEST_BASENAME} ${DXFC_TEST_SOURCE}) target_include_directories(${DXFC_TEST_BASENAME} PRIVATE ${DXFC_TEST_INCLUDE_DIRS}) @@ -49,9 +49,12 @@ foreach (DXFC_TEST_SOURCE ${DXFC_TEST_SOURCES}) LinkStacktrace(${DXFC_TEST_BASENAME}) endif () - set_property(TARGET ${DXFC_TEST_BASENAME} PROPERTY CXX_STANDARD 20) - set_property(TARGET ${DXFC_TEST_BASENAME} PROPERTY CMAKE_C_STANDARD 11) - set_property(TARGET ${DXFC_TEST_BASENAME} PROPERTY CXX_EXTENSIONS OFF) + set_target_properties(${DXFC_TEST_BASENAME} PROPERTIES + CXX_STANDARD 20 + CMAKE_C_STANDARD 11 + CXX_EXTENSIONS OFF + ) + add_test(NAME ${DXFC_TEST_BASENAME} COMMAND ${DXFC_TEST_BASENAME}) add_custom_command(TARGET ${DXFC_TEST_BASENAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different From 29e8df304e8e80b7f9921adc5f9625f1458da3aa Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 12 Aug 2024 16:29:58 +0300 Subject: [PATCH 071/178] Update Graal SDK to v1.1.23 --- CMakeLists.txt | 2 +- DEPENDENCIES.md | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb6de0ea8..f60e0d404 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ project(dxFeedGraalCxxApi) set(DXFCXX_VERSION "v2.0.0" CACHE STRING "The dxFeed Graal CXX API package version") -set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.22" CACHE STRING "") +set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.23" CACHE STRING "") set(FMTLIB_VERSION "10.2.1") set(BOOST_VERSION "1.84.0") set(UTFCPP_VERSION "3.2.3") diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index bb8205fd9..5bf0439f0 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -2,7 +2,8 @@ ## Compile-time -- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.22 +- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.23 + - [Bundles](https://dxfeed.jfrog.io/artifactory/maven-open/com/dxfeed/graal-native-sdk/) - [Boost](https://github.com/boostorg/boost) v1.84.0 - Boost.Stacktrace 1.0 - [utfcpp](https://github.com/nemtrif/utfcpp) v3.2.3 @@ -24,7 +25,8 @@ - addr2line \[opt] (Diagnostic backtraces) ## Run-time -- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.16 +- [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.23 + - [Bundles](https://dxfeed.jfrog.io/artifactory/maven-open/com/dxfeed/graal-native-sdk/) - [doctest](https://github.com/doctest/doctest) v2.4.11 (Tests) From 4625e5ebc1d6cb7ef2931eb41d9e60f862c7b71c Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 12 Aug 2024 17:55:28 +0300 Subject: [PATCH 072/178] Use CPM.cmake --- CMakeLists.txt | 48 +- DEPENDENCIES.md | 3 +- THIRD_PARTY_LICENSES.md | 2 + cmake/third_party/CPM.cmake-v0.40.2/CPM.cmake | 1269 +++++++++++++++++ .../CPM.cmake-v0.40.2/get_cpm.cmake | 24 + 5 files changed, 1320 insertions(+), 26 deletions(-) create mode 100644 cmake/third_party/CPM.cmake-v0.40.2/CPM.cmake create mode 100644 cmake/third_party/CPM.cmake-v0.40.2/get_cpm.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f60e0d404..eb35049ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,13 @@ set(FMTLIB_VERSION "10.2.1") set(BOOST_VERSION "1.84.0") set(UTFCPP_VERSION "3.2.3") set(DATE_VERSION "3.0.1") +set(PROCESS_VERSION "v3.0.1") +set(CONSOLE_VERSION "v1.0.1") set(RANGE_VERSION "0.12") set(DOCTEST_VERSION "2.4.11") +set(CPM_CMAKE_VERSION "v0.40.2") + +include(cmake/third_party/CPM.cmake-${CPM_CMAKE_VERSION}/CPM.cmake) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -116,25 +121,8 @@ endif () FetchContent_MakeAvailable(DxFeedGraalNativeSdk) # DxFeedGraalNativeSdk_SOURCE_DIR -FetchContent_Declare( - Process - GIT_REPOSITORY "https://github.com/ttldtor/Process.git" GIT_TAG default - USES_TERMINAL_DOWNLOAD TRUE - GIT_PROGRESS TRUE - DOWNLOAD_NO_EXTRACT FALSE -) - -FetchContent_MakeAvailable(Process) - -FetchContent_Declare( - Console - GIT_REPOSITORY "https://github.com/ttldtor/Console.git" GIT_TAG default - USES_TERMINAL_DOWNLOAD TRUE - GIT_PROGRESS TRUE - DOWNLOAD_NO_EXTRACT FALSE -) - -FetchContent_MakeAvailable(Console) +CPMAddPackage("gh:ttldtor/Process#${PROCESS_VERSION}") +CPMAddPackage("gh:ttldtor/Console#${CONSOLE_VERSION}") add_subdirectory(third_party/utfcpp-${UTFCPP_VERSION}) @@ -155,17 +143,27 @@ FetchContent_MakeAvailable(fmt) add_subdirectory(third_party/date-${DATE_VERSION}) set(BOOST_INCLUDE_LIBRARIES stacktrace) -set(BOOST_ENABLE_CMAKE ON) -FetchContent_Declare( - Boost - URL https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.7z # downloading a zip release speeds up the download +CPMAddPackage( + NAME Boost + VERSION ${BOOST_VERSION} + URL https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.tar.xz + OPTIONS "BOOST_ENABLE_CMAKE ON" USES_TERMINAL_DOWNLOAD TRUE GIT_PROGRESS TRUE - DOWNLOAD_NO_EXTRACT FALSE OVERRIDE_FIND_PACKAGE ) -FetchContent_MakeAvailable(Boost) + +# +#FetchContent_Declare( +# Boost +# URL https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.7z # downloading a zip release speeds up the download +# USES_TERMINAL_DOWNLOAD TRUE +# GIT_PROGRESS TRUE +# DOWNLOAD_NO_EXTRACT FALSE +# OVERRIDE_FIND_PACKAGE +#) +#FetchContent_MakeAvailable(Boost) #find_package( diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 5bf0439f0..9821fed7c 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -11,8 +11,9 @@ - [doctest](https://github.com/doctest/doctest) v2.4.11 (Tests) - [range-v3](https://github.com/ericniebler/range-v3) v0.12 - [date](https://github.com/HowardHinnant/date) v3.0.1 -- [Process](https://github.com/ttldtor/Process) v3.0.0 (Tools) +- [Process](https://github.com/ttldtor/Process) v3.0.1 (Tools) - [Console](https://github.com/ttldtor/Console) v1.0.1 (Tools) +- [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake) v0.40.2 - On Windows: diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 13f45ecab..d726a9805 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -16,4 +16,6 @@ SPDX-License-Identifier: BSL-1.0 8. Console - https://github.com/ttldtor/Console/blob/default/LICENSE SPDX-License-Identifier: BSL-1.0 +9. CPM.cmake - https://github.com/cpm-cmake/CPM.cmake/blob/master/LICENSE + SPDX-License-Identifier: MIT \ No newline at end of file diff --git a/cmake/third_party/CPM.cmake-v0.40.2/CPM.cmake b/cmake/third_party/CPM.cmake-v0.40.2/CPM.cmake new file mode 100644 index 000000000..8269a8bf6 --- /dev/null +++ b/cmake/third_party/CPM.cmake-v0.40.2/CPM.cmake @@ -0,0 +1,1269 @@ +# CPM.cmake - CMake's missing package manager +# =========================================== +# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions. +# +# MIT License +# ----------- +#[[ + Copyright (c) 2019-2023 Lars Melchior and contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +]] + +cmake_minimum_required(VERSION 3.14 FATAL_ERROR) + +# Initialize logging prefix +if(NOT CPM_INDENT) + set(CPM_INDENT + "CPM:" + CACHE INTERNAL "" + ) +endif() + +if(NOT COMMAND cpm_message) + function(cpm_message) + message(${ARGV}) + endfunction() +endif() + +set(CURRENT_CPM_VERSION 0.40.2) + +get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH) +if(CPM_DIRECTORY) + if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY) + if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION) + message( + AUTHOR_WARNING + "${CPM_INDENT} \ +A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \ +It is recommended to upgrade CPM to the most recent version. \ +See https://github.com/cpm-cmake/CPM.cmake for more information." + ) + endif() + if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + include(FetchContent) + endif() + return() + endif() + + get_property( + CPM_INITIALIZED GLOBAL "" + PROPERTY CPM_INITIALIZED + SET + ) + if(CPM_INITIALIZED) + return() + endif() +endif() + +if(CURRENT_CPM_VERSION MATCHES "development-version") + message( + WARNING "${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \ +Please update to a recent release if possible. \ +See https://github.com/cpm-cmake/CPM.cmake for details." + ) +endif() + +set_property(GLOBAL PROPERTY CPM_INITIALIZED true) + +macro(cpm_set_policies) + # the policy allows us to change options without caching + cmake_policy(SET CMP0077 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + + # the policy allows us to change set(CACHE) without caching + if(POLICY CMP0126) + cmake_policy(SET CMP0126 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0126 NEW) + endif() + + # The policy uses the download time for timestamp, instead of the timestamp in the archive. This + # allows for proper rebuilds when a projects url changes + if(POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0135 NEW) + endif() + + # treat relative git repository paths as being relative to the parent project's remote + if(POLICY CMP0150) + cmake_policy(SET CMP0150 NEW) + set(CMAKE_POLICY_DEFAULT_CMP0150 NEW) + endif() +endmacro() +cpm_set_policies() + +option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" + $ENV{CPM_USE_LOCAL_PACKAGES} +) +option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" + $ENV{CPM_LOCAL_PACKAGES_ONLY} +) +option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL}) +option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" + $ENV{CPM_DONT_UPDATE_MODULE_PATH} +) +option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path" + $ENV{CPM_DONT_CREATE_PACKAGE_LOCK} +) +option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK + "Add all packages added through CPM.cmake to the package lock" + $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK} +) +option(CPM_USE_NAMED_CACHE_DIRECTORIES + "Use additional directory of package name in cache on the most nested level." + $ENV{CPM_USE_NAMED_CACHE_DIRECTORIES} +) + +set(CPM_VERSION + ${CURRENT_CPM_VERSION} + CACHE INTERNAL "" +) +set(CPM_DIRECTORY + ${CPM_CURRENT_DIRECTORY} + CACHE INTERNAL "" +) +set(CPM_FILE + ${CMAKE_CURRENT_LIST_FILE} + CACHE INTERNAL "" +) +set(CPM_PACKAGES + "" + CACHE INTERNAL "" +) +set(CPM_DRY_RUN + OFF + CACHE INTERNAL "Don't download or configure dependencies (for testing)" +) + +if(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) +else() + set(CPM_SOURCE_CACHE_DEFAULT OFF) +endif() + +set(CPM_SOURCE_CACHE + ${CPM_SOURCE_CACHE_DEFAULT} + CACHE PATH "Directory to download CPM dependencies" +) + +if(NOT CPM_DONT_UPDATE_MODULE_PATH) + set(CPM_MODULE_PATH + "${CMAKE_BINARY_DIR}/CPM_modules" + CACHE INTERNAL "" + ) + # remove old modules + file(REMOVE_RECURSE ${CPM_MODULE_PATH}) + file(MAKE_DIRECTORY ${CPM_MODULE_PATH}) + # locally added CPM modules should override global packages + set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}") +endif() + +if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + set(CPM_PACKAGE_LOCK_FILE + "${CMAKE_BINARY_DIR}/cpm-package-lock.cmake" + CACHE INTERNAL "" + ) + file(WRITE ${CPM_PACKAGE_LOCK_FILE} + "# CPM Package Lock\n# This file should be committed to version control\n\n" + ) +endif() + +include(FetchContent) + +# Try to infer package name from git repository uri (path or url) +function(cpm_package_name_from_git_uri URI RESULT) + if("${URI}" MATCHES "([^/:]+)/?.git/?$") + set(${RESULT} + ${CMAKE_MATCH_1} + PARENT_SCOPE + ) + else() + unset(${RESULT} PARENT_SCOPE) + endif() +endfunction() + +# Try to infer package name and version from a url +function(cpm_package_name_and_ver_from_url url outName outVer) + if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)") + # We matched an archive + set(filename "${CMAKE_MATCH_1}") + + if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)") + # We matched - (ie foo-1.2.3) + set(${outName} + "${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + set(${outVer} + "${CMAKE_MATCH_2}" + PARENT_SCOPE + ) + elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)") + # We couldn't find a name, but we found a version + # + # In many cases (which we don't handle here) the url would look something like + # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly + # distinguish the package name from the irrelevant bits. Moreover if we try to match the + # package name from the filename, we'd get bogus at best. + unset(${outName} PARENT_SCOPE) + set(${outVer} + "${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + else() + # Boldly assume that the file name is the package name. + # + # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but + # such cases should be quite rare. No popular service does this... we think. + set(${outName} + "${filename}" + PARENT_SCOPE + ) + unset(${outVer} PARENT_SCOPE) + endif() + else() + # No ideas yet what to do with non-archives + unset(${outName} PARENT_SCOPE) + unset(${outVer} PARENT_SCOPE) + endif() +endfunction() + +function(cpm_find_package NAME VERSION) + string(REPLACE " " ";" EXTRA_ARGS "${ARGN}") + find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET) + if(${CPM_ARGS_NAME}_FOUND) + if(DEFINED ${CPM_ARGS_NAME}_VERSION) + set(VERSION ${${CPM_ARGS_NAME}_VERSION}) + endif() + cpm_message(STATUS "${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}") + CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}") + set(CPM_PACKAGE_FOUND + YES + PARENT_SCOPE + ) + else() + set(CPM_PACKAGE_FOUND + NO + PARENT_SCOPE + ) + endif() +endfunction() + +# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from +# finding the system library +function(cpm_create_module_file Name) + if(NOT CPM_DONT_UPDATE_MODULE_PATH) + # erase any previous modules + file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake + "include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)" + ) + endif() +endfunction() + +# Find a package locally or fallback to CPMAddPackage +function(CPMFindPackage) + set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS) + + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN}) + + if(NOT DEFINED CPM_ARGS_VERSION) + if(DEFINED CPM_ARGS_GIT_TAG) + cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) + endif() + endif() + + set(downloadPackage ${CPM_DOWNLOAD_ALL}) + if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME}) + set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}}) + elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}}) + set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}}) + endif() + if(downloadPackage) + CPMAddPackage(${ARGN}) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) + + if(NOT CPM_PACKAGE_FOUND) + CPMAddPackage(${ARGN}) + cpm_export_variables(${CPM_ARGS_NAME}) + endif() + +endfunction() + +# checks if a package has been added before +function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION) + if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) + CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) + if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}") + message( + WARNING + "${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})." + ) + endif() + cpm_get_fetch_properties(${CPM_ARGS_NAME}) + set(${CPM_ARGS_NAME}_ADDED NO) + set(CPM_PACKAGE_ALREADY_ADDED + YES + PARENT_SCOPE + ) + cpm_export_variables(${CPM_ARGS_NAME}) + else() + set(CPM_PACKAGE_ALREADY_ADDED + NO + PARENT_SCOPE + ) + endif() +endfunction() + +# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of +# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted +# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3 +function(cpm_parse_add_package_single_arg arg outArgs) + # Look for a scheme + if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$") + string(TOLOWER "${CMAKE_MATCH_1}" scheme) + set(uri "${CMAKE_MATCH_2}") + + # Check for CPM-specific schemes + if(scheme STREQUAL "gh") + set(out "GITHUB_REPOSITORY;${uri}") + set(packageType "git") + elseif(scheme STREQUAL "gl") + set(out "GITLAB_REPOSITORY;${uri}") + set(packageType "git") + elseif(scheme STREQUAL "bb") + set(out "BITBUCKET_REPOSITORY;${uri}") + set(packageType "git") + # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine + # type + elseif(arg MATCHES ".git/?(@|#|$)") + set(out "GIT_REPOSITORY;${arg}") + set(packageType "git") + else() + # Fall back to a URL + set(out "URL;${arg}") + set(packageType "archive") + + # We could also check for SVN since FetchContent supports it, but SVN is so rare these days. + # We just won't bother with the additional complexity it will induce in this function. SVN is + # done by multi-arg + endif() + else() + if(arg MATCHES ".git/?(@|#|$)") + set(out "GIT_REPOSITORY;${arg}") + set(packageType "git") + else() + # Give up + message(FATAL_ERROR "${CPM_INDENT} Can't determine package type of '${arg}'") + endif() + endif() + + # For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs + # containing '@' can be used + string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}") + + # Parse the rest according to package type + if(packageType STREQUAL "git") + # For git repos we interpret #... as a tag or branch or commit hash + string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}") + elseif(packageType STREQUAL "archive") + # For archives we interpret #... as a URL hash. + string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}") + # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url + # should do this at a later point + else() + # We should never get here. This is an assertion and hitting it means there's a problem with the + # code above. A packageType was set, but not handled by this if-else. + message(FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'") + endif() + + set(${outArgs} + ${out} + PARENT_SCOPE + ) +endfunction() + +# Check that the working directory for a git repo is clean +function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean) + + find_package(Git REQUIRED) + + if(NOT GIT_EXECUTABLE) + # No git executable, assume directory is clean + set(${isClean} + TRUE + PARENT_SCOPE + ) + return() + endif() + + # check for uncommitted changes + execute_process( + COMMAND ${GIT_EXECUTABLE} status --porcelain + RESULT_VARIABLE resultGitStatus + OUTPUT_VARIABLE repoStatus + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET + WORKING_DIRECTORY ${repoPath} + ) + if(resultGitStatus) + # not supposed to happen, assume clean anyway + message(WARNING "${CPM_INDENT} Calling git status on folder ${repoPath} failed") + set(${isClean} + TRUE + PARENT_SCOPE + ) + return() + endif() + + if(NOT "${repoStatus}" STREQUAL "") + set(${isClean} + FALSE + PARENT_SCOPE + ) + return() + endif() + + # check for committed changes + execute_process( + COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag} + RESULT_VARIABLE resultGitDiff + OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET + WORKING_DIRECTORY ${repoPath} + ) + + if(${resultGitDiff} EQUAL 0) + set(${isClean} + TRUE + PARENT_SCOPE + ) + else() + set(${isClean} + FALSE + PARENT_SCOPE + ) + endif() + +endfunction() + +# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN +# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended +# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`. +function(cpm_add_patches) + # Return if no patch files are supplied. + if(NOT ARGN) + return() + endif() + + # Find the patch program. + find_program(PATCH_EXECUTABLE patch) + if(WIN32 AND NOT PATCH_EXECUTABLE) + # The Windows git executable is distributed with patch.exe. Find the path to the executable, if + # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe. + find_package(Git QUIET) + if(GIT_EXECUTABLE) + get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY) + get_filename_component(extra_search_path_1up ${extra_search_path} DIRECTORY) + get_filename_component(extra_search_path_2up ${extra_search_path_1up} DIRECTORY) + find_program( + PATCH_EXECUTABLE patch HINTS "${extra_search_path_1up}/usr/bin" + "${extra_search_path_2up}/usr/bin" + ) + endif() + endif() + if(NOT PATCH_EXECUTABLE) + message(FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword.") + endif() + + # Create a temporary + set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS}) + + # Ensure each file exists (or error out) and add it to the list. + set(first_item True) + foreach(PATCH_FILE ${ARGN}) + # Make sure the patch file exists, if we can't find it, try again in the current directory. + if(NOT EXISTS "${PATCH_FILE}") + if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}") + message(FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE}'") + endif() + set(PATCH_FILE "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}") + endif() + + # Convert to absolute path for use with patch file command. + get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE) + + # The first patch entry must be preceded by "PATCH_COMMAND" while the following items are + # preceded by "&&". + if(first_item) + set(first_item False) + list(APPEND temp_list "PATCH_COMMAND") + else() + list(APPEND temp_list "&&") + endif() + # Add the patch command to the list + list(APPEND temp_list "${PATCH_EXECUTABLE}" "-p1" "<" "${PATCH_FILE}") + endforeach() + + # Move temp out into parent scope. + set(CPM_ARGS_UNPARSED_ARGUMENTS + ${temp_list} + PARENT_SCOPE + ) + +endfunction() + +# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload +# FetchContent calls. As these are internal cmake properties, this method should be used carefully +# and may need modification in future CMake versions. Source: +# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152 +function(cpm_override_fetchcontent contentName) + cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "") + if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "") + message(FATAL_ERROR "${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + + string(TOLOWER ${contentName} contentNameLower) + set(prefix "_FetchContent_${contentNameLower}") + + set(propertyName "${prefix}_sourceDir") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}") + + set(propertyName "${prefix}_binaryDir") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}") + + set(propertyName "${prefix}_populated") + define_property( + GLOBAL + PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} TRUE) +endfunction() + +# Download and add a package from source +function(CPMAddPackage) + cpm_set_policies() + + list(LENGTH ARGN argnLength) + if(argnLength EQUAL 1) + cpm_parse_add_package_single_arg("${ARGN}" ARGN) + + # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM + set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;") + endif() + + set(oneValueArgs + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + BITBUCKET_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + FIND_PACKAGE_ARGUMENTS + NO_CACHE + SYSTEM + GIT_SHALLOW + EXCLUDE_FROM_ALL + SOURCE_SUBDIR + CUSTOM_CACHE_KEY + ) + + set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES) + + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") + + # Set default values for arguments + + if(NOT DEFINED CPM_ARGS_VERSION) + if(DEFINED CPM_ARGS_GIT_TAG) + cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) + endif() + endif() + + if(CPM_ARGS_DOWNLOAD_ONLY) + set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY}) + else() + set(DOWNLOAD_ONLY NO) + endif() + + if(DEFINED CPM_ARGS_GITHUB_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git") + elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git") + elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY) + set(CPM_ARGS_GIT_REPOSITORY "https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git") + endif() + + if(DEFINED CPM_ARGS_GIT_REPOSITORY) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY}) + if(NOT DEFINED CPM_ARGS_GIT_TAG) + set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) + endif() + + # If a name wasn't provided, try to infer it from the git repo + if(NOT DEFINED CPM_ARGS_NAME) + cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME) + endif() + endif() + + set(CPM_SKIP_FETCH FALSE) + + if(DEFINED CPM_ARGS_GIT_TAG) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG}) + # If GIT_SHALLOW is explicitly specified, honor the value. + if(DEFINED CPM_ARGS_GIT_SHALLOW) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW}) + endif() + endif() + + if(DEFINED CPM_ARGS_URL) + # If a name or version aren't provided, try to infer them from the URL + list(GET CPM_ARGS_URL 0 firstUrl) + cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl) + # If we fail to obtain name and version from the first URL, we could try other URLs if any. + # However multiple URLs are expected to be quite rare, so for now we won't bother. + + # If the caller provided their own name and version, they trump the inferred ones. + if(NOT DEFINED CPM_ARGS_NAME) + set(CPM_ARGS_NAME ${nameFromUrl}) + endif() + if(NOT DEFINED CPM_ARGS_VERSION) + set(CPM_ARGS_VERSION ${verFromUrl}) + endif() + + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}") + endif() + + # Check for required arguments + + if(NOT DEFINED CPM_ARGS_NAME) + message( + FATAL_ERROR + "${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'" + ) + endif() + + # Check if package has been added before + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + if(CPM_PACKAGE_ALREADY_ADDED) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + # Check for manual overrides + if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "") + set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE}) + set(CPM_${CPM_ARGS_NAME}_SOURCE "") + CPMAddPackage( + NAME "${CPM_ARGS_NAME}" + SOURCE_DIR "${PACKAGE_SOURCE}" + EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}" + SYSTEM "${CPM_ARGS_SYSTEM}" + PATCHES "${CPM_ARGS_PATCHES}" + OPTIONS "${CPM_ARGS_OPTIONS}" + SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}" + DOWNLOAD_ONLY "${DOWNLOAD_ONLY}" + FORCE True + ) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + # Check for available declaration + if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "") + set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}}) + set(CPM_DECLARATION_${CPM_ARGS_NAME} "") + CPMAddPackage(${declaration}) + cpm_export_variables(${CPM_ARGS_NAME}) + # checking again to ensure version and option compatibility + cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}") + return() + endif() + + if(NOT CPM_ARGS_FORCE) + if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY) + cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) + + if(CPM_PACKAGE_FOUND) + cpm_export_variables(${CPM_ARGS_NAME}) + return() + endif() + + if(CPM_LOCAL_PACKAGES_ONLY) + message( + SEND_ERROR + "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})" + ) + endif() + endif() + endif() + + CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}") + + if(DEFINED CPM_ARGS_GIT_TAG) + set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") + elseif(DEFINED CPM_ARGS_SOURCE_DIR) + set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}") + else() + set(PACKAGE_INFO "${CPM_ARGS_VERSION}") + endif() + + if(DEFINED FETCHCONTENT_BASE_DIR) + # respect user's FETCHCONTENT_BASE_DIR if set + set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR}) + else() + set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps) + endif() + + cpm_add_patches(${CPM_ARGS_PATCHES}) + + if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) + elseif(DEFINED CPM_ARGS_SOURCE_DIR) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR}) + if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR}) + # Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work + # for relative paths. + get_filename_component( + source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR} + ) + else() + set(source_directory ${CPM_ARGS_SOURCE_DIR}) + endif() + if(NOT EXISTS ${source_directory}) + string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) + # remove timestamps so CMake will re-download the dependency + file(REMOVE_RECURSE "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild") + endif() + elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE) + string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) + set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS}) + list(SORT origin_parameters) + if(CPM_ARGS_CUSTOM_CACHE_KEY) + # Application set a custom unique directory name + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY}) + elseif(CPM_USE_NAMED_CACHE_DIRECTORIES) + string(SHA1 origin_hash "${origin_parameters};NEW_CACHE_STRUCTURE_TAG") + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME}) + else() + string(SHA1 origin_hash "${origin_parameters}") + set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}) + endif() + # Expand `download_directory` relative path. This is important because EXISTS doesn't work for + # relative paths. + get_filename_component(download_directory ${download_directory} ABSOLUTE) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory}) + + if(CPM_SOURCE_CACHE) + file(LOCK ${download_directory}/../cmake.lock) + endif() + + if(EXISTS ${download_directory}) + if(CPM_SOURCE_CACHE) + file(LOCK ${download_directory}/../cmake.lock RELEASE) + endif() + + cpm_store_fetch_properties( + ${CPM_ARGS_NAME} "${download_directory}" + "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build" + ) + cpm_get_fetch_properties("${CPM_ARGS_NAME}") + + if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS)) + # warn if cache has been changed since checkout + cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN) + if(NOT ${IS_CLEAN}) + message( + WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty" + ) + endif() + endif() + + cpm_add_subdirectory( + "${CPM_ARGS_NAME}" + "${DOWNLOAD_ONLY}" + "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + "${${CPM_ARGS_NAME}_BINARY_DIR}" + "${CPM_ARGS_EXCLUDE_FROM_ALL}" + "${CPM_ARGS_SYSTEM}" + "${CPM_ARGS_OPTIONS}" + ) + set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}") + + # As the source dir is already cached/populated, we override the call to FetchContent. + set(CPM_SKIP_FETCH TRUE) + cpm_override_fetchcontent( + "${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}" + ) + + else() + # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but + # it should guarantee no commit hash get mis-detected. + if(NOT DEFINED CPM_ARGS_GIT_SHALLOW) + cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH) + if(NOT ${IS_HASH}) + list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE) + endif() + endif() + + # remove timestamps so CMake will re-download the dependency + file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild) + set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}") + endif() + endif() + + cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\"${ARGN}\")") + + if(CPM_PACKAGE_LOCK_ENABLED) + if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK) + cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") + elseif(CPM_ARGS_SOURCE_DIR) + cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory") + else() + cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}") + endif() + endif() + + cpm_message( + STATUS "${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})" + ) + + if(NOT CPM_SKIP_FETCH) + # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare. + # Calling FetchContent_MakeAvailable will then internally forward these options to + # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and + # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30. + set(fetchContentDeclareExtraArgs "") + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0") + if(${CPM_ARGS_EXCLUDE_FROM_ALL}) + list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL) + endif() + if(${CPM_ARGS_SYSTEM}) + list(APPEND fetchContentDeclareExtraArgs SYSTEM) + endif() + if(DEFINED CPM_ARGS_SOURCE_SUBDIR) + list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR}) + endif() + # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory + if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY) + foreach(OPTION ${CPM_ARGS_OPTIONS}) + cpm_parse_option("${OPTION}") + set(${OPTION_KEY} "${OPTION_VALUE}") + endforeach() + endif() + endif() + cpm_declare_fetch( + "${CPM_ARGS_NAME}" ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS}" + ) + + cpm_fetch_package("${CPM_ARGS_NAME}" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS}) + if(CPM_SOURCE_CACHE AND download_directory) + file(LOCK ${download_directory}/../cmake.lock RELEASE) + endif() + if(${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0") + cpm_add_subdirectory( + "${CPM_ARGS_NAME}" + "${DOWNLOAD_ONLY}" + "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" + "${${CPM_ARGS_NAME}_BINARY_DIR}" + "${CPM_ARGS_EXCLUDE_FROM_ALL}" + "${CPM_ARGS_SYSTEM}" + "${CPM_ARGS_OPTIONS}" + ) + endif() + cpm_get_fetch_properties("${CPM_ARGS_NAME}") + endif() + + set(${CPM_ARGS_NAME}_ADDED YES) + cpm_export_variables("${CPM_ARGS_NAME}") +endfunction() + +# Fetch a previously declared package +macro(CPMGetPackage Name) + if(DEFINED "CPM_DECLARATION_${Name}") + CPMAddPackage(NAME ${Name}) + else() + message(SEND_ERROR "${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available") + endif() +endmacro() + +# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set +macro(cpm_export_variables name) + set(${name}_SOURCE_DIR + "${${name}_SOURCE_DIR}" + PARENT_SCOPE + ) + set(${name}_BINARY_DIR + "${${name}_BINARY_DIR}" + PARENT_SCOPE + ) + set(${name}_ADDED + "${${name}_ADDED}" + PARENT_SCOPE + ) + set(CPM_LAST_PACKAGE_NAME + "${name}" + PARENT_SCOPE + ) +endmacro() + +# declares a package, so that any call to CPMAddPackage for the package name will use these +# arguments instead. Previous declarations will not be overridden. +macro(CPMDeclarePackage Name) + if(NOT DEFINED "CPM_DECLARATION_${Name}") + set("CPM_DECLARATION_${Name}" "${ARGN}") + endif() +endmacro() + +function(cpm_add_to_package_lock Name) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN}) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n") + endif() +endfunction() + +function(cpm_add_comment_to_package_lock Name) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN}) + file(APPEND ${CPM_PACKAGE_LOCK_FILE} + "# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n" + ) + endif() +endfunction() + +# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to +# update it +macro(CPMUsePackageLock file) + if(NOT CPM_DONT_CREATE_PACKAGE_LOCK) + get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE) + if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}) + endif() + if(NOT TARGET cpm-update-package-lock) + add_custom_target( + cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE} + ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH} + ) + endif() + set(CPM_PACKAGE_LOCK_ENABLED true) + endif() +endmacro() + +# registers a package that has been added to CPM +function(CPMRegisterPackage PACKAGE VERSION) + list(APPEND CPM_PACKAGES ${PACKAGE}) + set(CPM_PACKAGES + ${CPM_PACKAGES} + CACHE INTERNAL "" + ) + set("CPM_PACKAGE_${PACKAGE}_VERSION" + ${VERSION} + CACHE INTERNAL "" + ) +endfunction() + +# retrieve the current version of the package to ${OUTPUT} +function(CPMGetPackageVersion PACKAGE OUTPUT) + set(${OUTPUT} + "${CPM_PACKAGE_${PACKAGE}_VERSION}" + PARENT_SCOPE + ) +endfunction() + +# declares a package in FetchContent_Declare +function(cpm_declare_fetch PACKAGE) + if(${CPM_DRY_RUN}) + cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)") + return() + endif() + + FetchContent_Declare(${PACKAGE} ${ARGN}) +endfunction() + +# returns properties for a package previously defined by cpm_declare_fetch +function(cpm_get_fetch_properties PACKAGE) + if(${CPM_DRY_RUN}) + return() + endif() + + set(${PACKAGE}_SOURCE_DIR + "${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}" + PARENT_SCOPE + ) + set(${PACKAGE}_BINARY_DIR + "${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}" + PARENT_SCOPE + ) +endfunction() + +function(cpm_store_fetch_properties PACKAGE source_dir binary_dir) + if(${CPM_DRY_RUN}) + return() + endif() + + set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR + "${source_dir}" + CACHE INTERNAL "" + ) + set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR + "${binary_dir}" + CACHE INTERNAL "" + ) +endfunction() + +# adds a package as a subdirectory if viable, according to provided options +function( + cpm_add_subdirectory + PACKAGE + DOWNLOAD_ONLY + SOURCE_DIR + BINARY_DIR + EXCLUDE + SYSTEM + OPTIONS +) + + if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt) + set(addSubdirectoryExtraArgs "") + if(EXCLUDE) + list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL) + endif() + if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25") + # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM + list(APPEND addSubdirectoryExtraArgs SYSTEM) + endif() + if(OPTIONS) + foreach(OPTION ${OPTIONS}) + cpm_parse_option("${OPTION}") + set(${OPTION_KEY} "${OPTION_VALUE}") + endforeach() + endif() + set(CPM_OLD_INDENT "${CPM_INDENT}") + set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:") + add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs}) + set(CPM_INDENT "${CPM_OLD_INDENT}") + endif() +endfunction() + +# downloads a previously declared package via FetchContent and exports the variables +# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope +function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated) + set(${populated} + FALSE + PARENT_SCOPE + ) + if(${CPM_DRY_RUN}) + cpm_message(STATUS "${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)") + return() + endif() + + FetchContent_GetProperties(${PACKAGE}) + + string(TOLOWER "${PACKAGE}" lower_case_name) + + if(NOT ${lower_case_name}_POPULATED) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0") + if(DOWNLOAD_ONLY) + # MakeAvailable will call add_subdirectory internally which is not what we want when + # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the + # build + FetchContent_Populate( + ${PACKAGE} + SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src" + BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build" + SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild" + ${ARGN} + ) + else() + FetchContent_MakeAvailable(${PACKAGE}) + endif() + else() + FetchContent_Populate(${PACKAGE}) + endif() + set(${populated} + TRUE + PARENT_SCOPE + ) + endif() + + cpm_store_fetch_properties( + ${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR} + ) + + set(${PACKAGE}_SOURCE_DIR + ${${lower_case_name}_SOURCE_DIR} + PARENT_SCOPE + ) + set(${PACKAGE}_BINARY_DIR + ${${lower_case_name}_BINARY_DIR} + PARENT_SCOPE + ) +endfunction() + +# splits a package option +function(cpm_parse_option OPTION) + string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}") + string(LENGTH "${OPTION}" OPTION_LENGTH) + string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH) + if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) + # no value for key provided, assume user wants to set option to "ON" + set(OPTION_VALUE "ON") + else() + math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1") + string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE) + endif() + set(OPTION_KEY + "${OPTION_KEY}" + PARENT_SCOPE + ) + set(OPTION_VALUE + "${OPTION_VALUE}" + PARENT_SCOPE + ) +endfunction() + +# guesses the package version from a git tag +function(cpm_get_version_from_git_tag GIT_TAG RESULT) + string(LENGTH ${GIT_TAG} length) + if(length EQUAL 40) + # GIT_TAG is probably a git hash + set(${RESULT} + 0 + PARENT_SCOPE + ) + else() + string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG}) + set(${RESULT} + ${CMAKE_MATCH_1} + PARENT_SCOPE + ) + endif() +endfunction() + +# guesses if the git tag is a commit hash or an actual tag or a branch name. +function(cpm_is_git_tag_commit_hash GIT_TAG RESULT) + string(LENGTH "${GIT_TAG}" length) + # full hash has 40 characters, and short hash has at least 7 characters. + if(length LESS 7 OR length GREATER 40) + set(${RESULT} + 0 + PARENT_SCOPE + ) + else() + if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$") + set(${RESULT} + 1 + PARENT_SCOPE + ) + else() + set(${RESULT} + 0 + PARENT_SCOPE + ) + endif() + endif() +endfunction() + +function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT) + set(oneValueArgs + NAME + FORCE + VERSION + GIT_TAG + DOWNLOAD_ONLY + GITHUB_REPOSITORY + GITLAB_REPOSITORY + BITBUCKET_REPOSITORY + GIT_REPOSITORY + SOURCE_DIR + FIND_PACKAGE_ARGUMENTS + NO_CACHE + SYSTEM + GIT_SHALLOW + EXCLUDE_FROM_ALL + SOURCE_SUBDIR + ) + set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND) + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(oneArgName ${oneValueArgs}) + if(DEFINED CPM_ARGS_${oneArgName}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + if(${oneArgName} STREQUAL "SOURCE_DIR") + string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName} + ${CPM_ARGS_${oneArgName}} + ) + endif() + string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n") + endif() + endforeach() + foreach(multiArgName ${multiValueArgs}) + if(DEFINED CPM_ARGS_${multiArgName}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n") + foreach(singleOption ${CPM_ARGS_${multiArgName}}) + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n") + endforeach() + endif() + endforeach() + + if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "") + if(${IS_IN_COMMENT}) + string(APPEND PRETTY_OUT_VAR "#") + endif() + string(APPEND PRETTY_OUT_VAR " ") + foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS}) + string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}") + endforeach() + string(APPEND PRETTY_OUT_VAR "\n") + endif() + + set(${OUT_VAR} + ${PRETTY_OUT_VAR} + PARENT_SCOPE + ) + +endfunction() diff --git a/cmake/third_party/CPM.cmake-v0.40.2/get_cpm.cmake b/cmake/third_party/CPM.cmake-v0.40.2/get_cpm.cmake new file mode 100644 index 000000000..baf2d8c34 --- /dev/null +++ b/cmake/third_party/CPM.cmake-v0.40.2/get_cpm.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.40.2) +set(CPM_HASH_SUM "c8cdc32c03816538ce22781ed72964dc864b2a34a310d3b7104812a5ca2d835d") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) From 59bb990d2115f9d64505bcf3762d3d50767ab145 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 14 Aug 2024 12:15:55 +0300 Subject: [PATCH 073/178] Add DEPENDENCIES.md and ReleaseNotes.md to bundle. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb35049ee..6cbea5705 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -549,5 +549,5 @@ if (DXFCXX_INSTALL) install(DIRECTORY "include" DESTINATION "." PATTERN "build" EXCLUDE) endif () - install(FILES "LICENSE" "README.md" "THIRD_PARTY_LICENSES.md" DESTINATION ".") + install(FILES "DEPENDENCIES.md" "LICENSE" "README.md" "ReleaseNotes.md" "THIRD_PARTY_LICENSES.md" DESTINATION ".") endif () \ No newline at end of file From 0a4435aa9a82a8f9cc67a59df8ca24c435f4a0a2 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 14 Aug 2024 12:21:20 +0300 Subject: [PATCH 074/178] Change the API major version to v3. --- CMakeLists.txt | 2 +- include/dxfeed_graal_cpp_api/internal/Conf.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cbea5705..52c3c0858 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) project(dxFeedGraalCxxApi) -set(DXFCXX_VERSION "v2.0.0" CACHE STRING "The dxFeed Graal CXX API package version") +set(DXFCXX_VERSION "v3.0.0-rc1" CACHE STRING "The dxFeed Graal CXX API package version") set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.23" CACHE STRING "") set(FMTLIB_VERSION "10.2.1") diff --git a/include/dxfeed_graal_cpp_api/internal/Conf.hpp b/include/dxfeed_graal_cpp_api/internal/Conf.hpp index 577e71f91..e1a21f052 100644 --- a/include/dxfeed_graal_cpp_api/internal/Conf.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Conf.hpp @@ -50,7 +50,7 @@ #ifndef DXFCPP_BEGIN_NAMESPACE # define DXFCPP_BEGIN_NAMESPACE \ namespace dxfcpp { \ - inline namespace v2 { + inline namespace v3 { # define DXFCPP_END_NAMESPACE \ } \ } From d14cbc5383026076e54e485c25c2acdd2d95183c Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 28 Aug 2024 20:59:42 +0300 Subject: [PATCH 075/178] [MDAPI-127] [C++] Make statics initialization more lazy. Add TimeFormat and TimePeriod lazy c-tors. --- .../internal/TimeFormat.hpp | 12 ++++- .../dxfeed_graal_cpp_api/util/TimePeriod.hpp | 9 +++- src/internal/TimeFormat.cpp | 51 +++++++++++++++---- src/util/TimePeriod.cpp | 30 +++++++++-- 4 files changed, 85 insertions(+), 17 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp index eda13b86b..4802a1051 100644 --- a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp +++ b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp @@ -38,9 +38,15 @@ struct DXFCPP_EXPORT TimeFormat { const static TimeFormat GMT; private: - JavaObjectHandle handle_; + mutable JavaObjectHandle handle_; + mutable std::mutex mtx_{}; + mutable bool initialized_{}; + std::function()> initializer_; - explicit TimeFormat(JavaObjectHandle &&handle); + //lazy c-tor + explicit TimeFormat(std::function()> &&initializer); + + void init() const; public: virtual ~TimeFormat() noexcept = default; @@ -50,6 +56,8 @@ struct DXFCPP_EXPORT TimeFormat { TimeFormat &operator=(const TimeFormat &) = delete; TimeFormat &operator=(const TimeFormat &&) noexcept = delete; + const JavaObjectHandle &getHandle() const; + /** * Reads Date from String and returns timestamp. * This method is designed to understand diff --git a/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp b/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp index d181aadc7..1c3797d08 100644 --- a/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp +++ b/include/dxfeed_graal_cpp_api/util/TimePeriod.hpp @@ -90,9 +90,16 @@ struct DXFCPP_EXPORT TimePeriod { TimePeriod &operator=(const TimePeriod &&) noexcept = delete; private: - JavaObjectHandle handle_; + mutable JavaObjectHandle handle_; + mutable std::mutex mtx_{}; + mutable bool initialized_{}; + std::function()> initializer_; + //lazy c-tor + explicit TimePeriod(std::function()> &&initializer); explicit TimePeriod(JavaObjectHandle &&handle); + + void init() const; }; DXFCPP_END_NAMESPACE diff --git a/src/internal/TimeFormat.cpp b/src/internal/TimeFormat.cpp index c2057b7ad..f03520c3e 100644 --- a/src/internal/TimeFormat.cpp +++ b/src/internal/TimeFormat.cpp @@ -9,23 +9,52 @@ DXFCPP_BEGIN_NAMESPACE -const TimeFormat TimeFormat::DEFAULT(isolated::internal::IsolatedTimeFormat::getDefault()); -const TimeFormat - TimeFormat::DEFAULT_WITH_MILLIS(DEFAULT.handle_ - ? isolated::internal::IsolatedTimeFormat::withMillis(DEFAULT.handle_) - : JavaObjectHandle{nullptr}); -const TimeFormat TimeFormat::DEFAULT_WITH_MILLIS_WITH_TIMEZONE( - DEFAULT_WITH_MILLIS.handle_ ? isolated::internal::IsolatedTimeFormat::withTimeZone(DEFAULT_WITH_MILLIS.handle_) - : JavaObjectHandle{nullptr}); -const TimeFormat TimeFormat::GMT(isolated::internal::IsolatedTimeFormat::getGmt()); - -TimeFormat::TimeFormat(JavaObjectHandle &&handle) : handle_(std::move(handle)){}; +const TimeFormat TimeFormat::DEFAULT([] { + return isolated::internal::IsolatedTimeFormat::getDefault(); +}); + +const TimeFormat TimeFormat::DEFAULT_WITH_MILLIS([] { + return DEFAULT.getHandle() ? isolated::internal::IsolatedTimeFormat::withMillis(DEFAULT.getHandle()) + : JavaObjectHandle{nullptr}; +}); + +const TimeFormat TimeFormat::DEFAULT_WITH_MILLIS_WITH_TIMEZONE([] { + return DEFAULT_WITH_MILLIS.getHandle() + ? isolated::internal::IsolatedTimeFormat::withTimeZone(DEFAULT_WITH_MILLIS.getHandle()) + : JavaObjectHandle{nullptr}; +}); + +const TimeFormat TimeFormat::GMT([] { + return isolated::internal::IsolatedTimeFormat::getGmt(); +}); + +TimeFormat::TimeFormat(std::function()> &&initializer) + : initializer_(std::move(initializer)){}; + +void TimeFormat::init() const { + std::lock_guard lock(mtx_); + + if (!initialized_) { + handle_ = initializer_(); + initialized_ = true; + } +} + +const JavaObjectHandle &TimeFormat::getHandle() const { + init(); + + return handle_; +} std::int64_t TimeFormat::parse(const StringLikeWrapper &value) const { + init(); + return isolated::internal::IsolatedTimeFormat::parse(handle_, value); } std::string TimeFormat::format(std::int64_t timestamp) const { + init(); + return isolated::internal::IsolatedTimeFormat::format(handle_, timestamp); } diff --git a/src/util/TimePeriod.cpp b/src/util/TimePeriod.cpp index 1a9cfeed5..9104e8a13 100644 --- a/src/util/TimePeriod.cpp +++ b/src/util/TimePeriod.cpp @@ -16,9 +16,13 @@ DXFCPP_BEGIN_NAMESPACE -const TimePeriod TimePeriod::ZERO(isolated::util::IsolatedTimePeriod::ZERO()); +const TimePeriod TimePeriod::ZERO([] { + return isolated::util::IsolatedTimePeriod::ZERO(); +}); -const TimePeriod TimePeriod::UNLIMITED(isolated::util::IsolatedTimePeriod::UNLIMITED()); +const TimePeriod TimePeriod::UNLIMITED([] { + return isolated::util::IsolatedTimePeriod::UNLIMITED(); +}); TimePeriod TimePeriod::valueOf(std::int64_t value) { return TimePeriod(isolated::util::IsolatedTimePeriod::valueOf(value)); @@ -29,18 +33,38 @@ TimePeriod TimePeriod::valueOf(const StringLikeWrapper &value) { } std::int64_t TimePeriod::getTime() const { + init(); + return isolated::util::IsolatedTimePeriod::getTime(handle_); } std::int32_t TimePeriod::getSeconds() const { + init(); + return isolated::util::IsolatedTimePeriod::getSeconds(handle_); } std::int64_t TimePeriod::getNanos() const { + init(); + return isolated::util::IsolatedTimePeriod::getNanos(handle_); } -TimePeriod::TimePeriod(JavaObjectHandle &&handle) : handle_(std::move(handle)) { +TimePeriod::TimePeriod(std::function()> &&initializer) + : initializer_(std::move(initializer)) { +} + +TimePeriod::TimePeriod(JavaObjectHandle &&handle): handle_(std::move(handle)) { + initialized_ = true; +} + +void TimePeriod::init() const { + std::lock_guard lock(mtx_); + + if (!initialized_) { + handle_ = initializer_(); + initialized_ = true; + } } DXFCPP_END_NAMESPACE From 83bf2eb01f6f2bd92a6e597521b1761ec631ee5f Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 1 Sep 2024 21:31:04 +0300 Subject: [PATCH 076/178] [MDAPI-127] [C++] Make statics initialization more lazy. Make IsolateThread moveable-only. --- include/dxfeed_graal_cpp_api/internal/Isolate.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp index 575e686a5..76c4abb5d 100644 --- a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp @@ -47,6 +47,12 @@ class Isolate final { } } + IsolateThread(const IsolateThread &) = delete; + IsolateThread(IsolateThread &&) = default; + + IsolateThread &operator=(const IsolateThread &) = delete; + IsolateThread &operator=(IsolateThread &&) = default; + CEntryPointErrorsEnum detach() noexcept; CEntryPointErrorsEnum detachAllThreadsAndTearDownIsolate() noexcept; From d9e61cb1bef400b8deff4fa78d5ba3d7a123f97c Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 2 Sep 2024 17:55:43 +0300 Subject: [PATCH 077/178] [MDAPI-127] [C++] Make statics initialization more lazy. Get rid of warnings about NamedUnsignedIntArg on a 32-bit architecture. --- .gitignore | 2 ++ tools/Tools/src/Args/Args.hpp | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3bbe16101..0576ab831 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ dist-*/ CMakeSettings.json *.patch .vs/** +.cache/** +/Folder.DotSettings.user diff --git a/tools/Tools/src/Args/Args.hpp b/tools/Tools/src/Args/Args.hpp index a4ebb32f4..06f54aa42 100644 --- a/tools/Tools/src/Args/Args.hpp +++ b/tools/Tools/src/Args/Args.hpp @@ -173,7 +173,13 @@ struct NamedUnsignedIntArg : NamedArg { if ((!A::SHORT_NAME.empty() && args[index] == "-" + A::SHORT_NAME) || (!A::LONG_NAME.empty() && args[index] == "--" + A::LONG_NAME)) { try { - return ParseResult>::ok(std::stoull(args[index + 1]), index + 2); + auto res = std::stoull(args[index + 1]); + + if (res >= std::numeric_limits::max()) { + return ParseResult>::ok(std::nullopt, index); + } + + return ParseResult>::ok(static_cast(res), index + 2); } catch (...) { return ParseResult>::ok(std::nullopt, index); } From 4020a5ad2de1bd52ed7d9c55d5fb4569a7db51d1 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 5 Sep 2024 17:37:11 +0300 Subject: [PATCH 078/178] [MDAPI-127] [C++] Make statics initialization more lazy. Remove checks that IsolateThread is bound to the main thread. Remove explicit Isolate initialization for the main thread. Make initialization of SessionFilter handle more lazy. --- .../dxfeed_graal_cpp_api/internal/Isolate.hpp | 42 ++++--------------- .../schedule/SessionFilter.hpp | 13 ++++-- src/api.cpp | 2 - src/event/candle/CandleSession.cpp | 12 +++++- src/internal/Isolate.cpp | 8 +--- src/schedule/Day.cpp | 26 ++++++------ src/schedule/Schedule.cpp | 8 ++-- src/schedule/Session.cpp | 19 ++++----- 8 files changed, 55 insertions(+), 75 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp index 76c4abb5d..f4f1e541c 100644 --- a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp @@ -12,10 +12,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "Common.hpp" #include "utils/StringUtils.hpp" -#include #include #include -#include #include #include #include @@ -33,17 +31,16 @@ using ConstGraalIsolateThreadHandle = const void *; class Isolate final { struct IsolateThread final { GraalIsolateThreadHandle handle{}; - bool isMain{}; std::thread::id tid{}; std::size_t idx{}; - explicit IsolateThread(GraalIsolateThreadHandle handle = nullptr, bool isMain = false) noexcept - : handle{handle}, isMain{isMain}, tid{std::this_thread::get_id()} { + explicit IsolateThread(GraalIsolateThreadHandle handle = nullptr) noexcept + : handle{handle}, tid{std::this_thread::get_id()} { this->idx = Id::getNext().getValue(); if constexpr (Debugger::traceIsolates) { - Debugger::trace("IsolateThread{" + dxfcpp::toString(handle) + ", isMain = " + dxfcpp::toString(isMain) + - ", tid = " + dxfcpp::toString(tid) + ", idx = " + std::to_string(idx) + "}()"); + Debugger::trace("IsolateThread{" + dxfcpp::toString(handle) + ", tid = " + dxfcpp::toString(tid) + + ", idx = " + std::to_string(idx) + "}()"); } } @@ -62,42 +59,21 @@ class Isolate final { Debugger::trace(toString() + "::~()"); } - if (isMain) { - if constexpr (Debugger::traceIsolates) { - Debugger::trace(toString() + "::~(): isMain => This is the main thread"); - } - - return; - } - - detach(); + // detach(); } std::string toString() const { - return std::string("IsolateThread{") + dxfcpp::toString(handle) + ", isMain = " + dxfcpp::toString(isMain) + - ", tid = " + dxfcpp::toString(tid) + ", idx = " + std::to_string(idx) + "}"; + return std::string("IsolateThread{") + dxfcpp::toString(handle) + ", tid = " + dxfcpp::toString(tid) + + ", idx = " + std::to_string(idx) + "}"; } }; mutable std::recursive_mutex mtx_{}; ConstGraalIsolateThreadHandle handle_; - IsolateThread mainIsolateThread_; static thread_local IsolateThread currentIsolateThread_; Isolate() noexcept; - Isolate(GraalIsolateHandle handle, GraalIsolateThreadHandle mainIsolateThreadHandle) noexcept - : mtx_{}, handle_{handle}, mainIsolateThread_{mainIsolateThreadHandle, true} { - - currentIsolateThread_.handle = mainIsolateThreadHandle; - currentIsolateThread_.isMain = true; - - if constexpr (Debugger::traceIsolates) { - Debugger::trace("Isolate{" + dxfcpp::toString(handle) + ", main = " + mainIsolateThread_.toString() + - ", current = " + currentIsolateThread_.toString() + "}()"); - } - } - CEntryPointErrorsEnum attach() noexcept; GraalIsolateThreadHandle get() noexcept; @@ -269,8 +245,8 @@ class Isolate final { } std::string toString() const { - return std::string("Isolate{") + dxfcpp::toString(handle_) + ", main = " + mainIsolateThread_.toString() + - ", current = " + currentIsolateThread_.toString() + "}"; + return std::string("Isolate{") + dxfcpp::toString(handle_) + ", current = " + currentIsolateThread_.toString() + + "}"; } }; diff --git a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp index 51d899be6..9f0949067 100644 --- a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp @@ -9,6 +9,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "SessionType.hpp" +#include + DXFCPP_BEGIN_NAMESPACE enum class SessionFilterEnum : std::uint32_t { @@ -40,9 +42,9 @@ enum class SessionFilterEnum : std::uint32_t { * some only non-trading, and some ignore type of session altogether. */ struct DXFCPP_EXPORT SessionFilter { - friend struct Session; - friend struct Schedule; - friend struct Day; + // friend struct Session; + // friend struct Schedule; + // friend struct Day; /** Accepts any session - useful for pure schedule navigation. */ static const SessionFilter ANY; @@ -70,7 +72,8 @@ struct DXFCPP_EXPORT SessionFilter { /// Required trading flag, std::nullopt if not relevant. std::optional trading_; - JavaObjectHandle handle_; + mutable std::mutex mtx_{}; + mutable JavaObjectHandle handle_{}; public: SessionFilter() noexcept = default; @@ -119,6 +122,8 @@ struct DXFCPP_EXPORT SessionFilter { const std::optional &getTrading() const & noexcept { return trading_; } + + const JavaObjectHandle& getHandle() const&; }; DXFCPP_END_NAMESPACE diff --git a/src/api.cpp b/src/api.cpp index 2c5425524..00d1716cb 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -16,6 +16,4 @@ DXFCPP_BEGIN_NAMESPACE thread_local Isolate::IsolateThread Isolate::currentIsolateThread_{}; -auto IS = Isolate::getInstance().toString(); - DXFCPP_END_NAMESPACE diff --git a/src/event/candle/CandleSession.cpp b/src/event/candle/CandleSession.cpp index 73de17b1d..ff1c25dd4 100644 --- a/src/event/candle/CandleSession.cpp +++ b/src/event/candle/CandleSession.cpp @@ -17,9 +17,17 @@ const SessionType SessionType::AFTER_MARKET{SessionTypeEnum::AFTER_MARKET, "AFTE SessionFilter::SessionFilter(SessionFilterEnum code, std::string name, std::optional type, std::optional trading) noexcept : code_{code}, name_{std::move(name)}, type_{type}, trading_{trading} { +} + +const JavaObjectHandle &SessionFilter::getHandle() const & { + std::lock_guard lock(mtx_); + + if (!handle_) { + handle_ = JavaObjectHandle( + isolated::schedule::SessionFilter::getInstance(static_cast(code_))); + } - handle_ = JavaObjectHandle( - isolated::schedule::SessionFilter::getInstance(static_cast(code))); + return handle_; } const SessionFilter SessionFilter::ANY{SessionFilterEnum::ANY, "ANY", std::nullopt, std::nullopt}; diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 944cad783..6ab5651ec 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -77,15 +77,12 @@ Isolate::Isolate() noexcept : mtx_{} { nullptr, &graalIsolateHandle, &graalIsolateThreadHandle)) == CEntryPointErrorsEnum::NO_ERROR) { handle_ = graalIsolateHandle; - mainIsolateThread_ = std::move(IsolateThread{graalIsolateThreadHandle, true}); - currentIsolateThread_.handle = graalIsolateThreadHandle; - currentIsolateThread_.isMain = true; } if constexpr (Debugger::traceIsolates) { - Debugger::trace("Isolate::Isolate() -> " + std::string("Isolate{") + dxfcpp::toString(handle_) + ", main = " + - mainIsolateThread_.toString() + ", current = " + currentIsolateThread_.toString() + "}"); + Debugger::trace("Isolate::Isolate() -> " + std::string("Isolate{") + dxfcpp::toString(handle_) + + ", current = " + currentIsolateThread_.toString() + "}"); } } @@ -116,7 +113,6 @@ CEntryPointErrorsEnum Isolate::attach() noexcept { } currentIsolateThread_.handle = newIsolateThreadHandle; - currentIsolateThread_.isMain = mainIsolateThread_.handle == newIsolateThreadHandle; if constexpr (Debugger::traceIsolates) { Debugger::trace(toString() + "::attach(): Attached: " + currentIsolateThread_.toString()); diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index 1dd363869..97e6f402e 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -14,8 +14,7 @@ Day::Day(void *handle) noexcept : handle_(handle) { Day::Ptr Day::create(void *handle) { if (!handle) { - throw InvalidArgumentException( - "Unable to create a Day object. The handle is nullptr"); + throw InvalidArgumentException("Unable to create a Day object. The handle is nullptr"); } return std::shared_ptr(new Day(handle)); @@ -138,13 +137,13 @@ std::vector> Day::getSessions() const { return {}; } - auto* graalSessionList = isolated::schedule::Day::getSessions(handle_.get()); + auto *graalSessionList = isolated::schedule::Day::getSessions(handle_.get()); if (!graalSessionList) { return {}; } - auto* sessionList = dxfcpp::bit_cast(graalSessionList); + auto *sessionList = dxfcpp::bit_cast(graalSessionList); std::vector> result; if (sessionList->size > 0 && sessionList->elements) { @@ -155,8 +154,7 @@ std::vector> Day::getSessions() const { } } - isolated::runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, - sessionList); + isolated::runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, sessionList); return result; } @@ -170,35 +168,35 @@ std::shared_ptr Day::getSessionByTime(std::int64_t time) const noexcept } std::shared_ptr Day::getFirstSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Day::getFirstSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Day::getFirstSession(handle_.get(), filter.getHandle().get())); } std::shared_ptr Day::getLastSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Day::getLastSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Day::getLastSession(handle_.get(), filter.getHandle().get())); } std::shared_ptr Day::findFirstSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Day::findFirstSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Day::findFirstSession(handle_.get(), filter.getHandle().get())); } std::shared_ptr Day::findLastSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Day::findLastSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Day::findLastSession(handle_.get(), filter.getHandle().get())); } Day::Ptr Day::getPrevDay(const DayFilter &filter) const noexcept { diff --git a/src/schedule/Schedule.cpp b/src/schedule/Schedule.cpp index 58fa561e3..426dd3252 100644 --- a/src/schedule/Schedule.cpp +++ b/src/schedule/Schedule.cpp @@ -94,21 +94,21 @@ Day::Ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const noexcep } Session::Ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } return Session::create( - isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.handle_.get())); + isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.getHandle().get())); } Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } return Session::create( - isolated::schedule::Schedule::findNearestSessionByTime(handle_.get(), time, filter.handle_.get())); + isolated::schedule::Schedule::findNearestSessionByTime(handle_.get(), time, filter.getHandle().get())); } std::string Schedule::getName() const noexcept { diff --git a/src/schedule/Session.cpp b/src/schedule/Session.cpp index e4455130e..3e05a6104 100644 --- a/src/schedule/Session.cpp +++ b/src/schedule/Session.cpp @@ -13,8 +13,7 @@ Session::Session(void *handle) noexcept : handle_(handle) { Session::Ptr Session::create(void *handle) { if (!handle) { - throw InvalidArgumentException( - "Unable to create a Session object. The handle is nullptr"); + throw InvalidArgumentException("Unable to create a Session object. The handle is nullptr"); } return std::shared_ptr(new Session(handle)); @@ -88,35 +87,35 @@ bool Session::containsTime(std::int64_t time) const noexcept { } Session::Ptr Session::getPrevSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Session::getPrevSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Session::getPrevSession(handle_.get(), filter.getHandle().get())); } Session::Ptr Session::getNextSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Session::getNextSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Session::getNextSession(handle_.get(), filter.getHandle().get())); } Session::Ptr Session::findPrevSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Session::findPrevSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Session::findPrevSession(handle_.get(), filter.getHandle().get())); } Session::Ptr Session::findNextSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { + if (!handle_ || !filter.getHandle()) { return {}; } - return Session::create(isolated::schedule::Session::findNextSession(handle_.get(), filter.handle_.get())); + return Session::create(isolated::schedule::Session::findNextSession(handle_.get(), filter.getHandle().get())); } bool Session::operator==(const Session &other) const noexcept { From c16a0dc742c6c9ee489ead8fdcc70c9c1d705043 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 6 Sep 2024 12:58:37 +0300 Subject: [PATCH 079/178] [MDAPI-127] [C++] Make statics initialization more lazy. Clean up, get rid build warnings. --- .../event/candle/CandleSession.hpp | 2 +- include/dxfeed_graal_cpp_api/internal/Common.hpp | 4 ++-- include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp | 3 +++ .../dxfeed_graal_cpp_api/schedule/SessionFilter.hpp | 12 ++++-------- samples/cpp/OnDemandSample/src/main.cpp | 1 - src/internal/Common.cpp | 2 +- src/internal/utils/CmdArgsUtils.cpp | 4 ---- 7 files changed, 11 insertions(+), 17 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp index f22b722d1..4d6211d17 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp @@ -34,7 +34,7 @@ DXFCPP_BEGIN_NAMESPACE * The key to use with these methods is available via CandleSession::ATTRIBUTE_KEY constant. * The value that this key shall be set to is equal to the corresponding CandleSession::toString() */ -struct DXFCPP_EXPORT CandleSession : public CandleSymbolAttribute { +struct DXFCPP_EXPORT CandleSession final : CandleSymbolAttribute { /** * All trading sessions are used to build candles. */ diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index e0db3213b..342db5bf9 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -285,7 +285,7 @@ constexpr static std::int32_t getYearMonthDayByDayId(std::int32_t dayId) { return yyyy >= 0 ? yyyymmdd : -yyyymmdd; } -static std::int32_t getDayIdByYearMonthDay(std::int32_t year, std::int32_t month, std::int32_t day); +std::int32_t getDayIdByYearMonthDay(std::int32_t year, std::int32_t month, std::int32_t day); } // namespace day_util @@ -798,7 +798,7 @@ struct StringHash { namespace util { -inline void throwInvalidChar(char c, const std::string &name); +void throwInvalidChar(char c, const std::string &name); inline void checkChar(char c, std::uint32_t mask, const std::string &name) { if ((andOp(c, ~mask)) != 0) { diff --git a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp index 4802a1051..0cd10ce27 100644 --- a/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp +++ b/include/dxfeed_graal_cpp_api/internal/TimeFormat.hpp @@ -11,9 +11,12 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include #include +#include DXFCPP_BEGIN_NAMESPACE +struct StringLikeWrapper; + /** * Utility class for parsing and formatting dates and times in ISO-compatible format. * diff --git a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp index 9f0949067..3dec6bf88 100644 --- a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp @@ -41,11 +41,7 @@ enum class SessionFilterEnum : std::uint32_t { * Different filters treat this distinction differently - some accept only trading sessions, * some only non-trading, and some ignore type of session altogether. */ -struct DXFCPP_EXPORT SessionFilter { - // friend struct Session; - // friend struct Schedule; - // friend struct Day; - +struct DXFCPP_EXPORT SessionFilter final { /** Accepts any session - useful for pure schedule navigation. */ static const SessionFilter ANY; /** Accepts trading sessions only - those with (Session::isTrading() == true). */ @@ -65,12 +61,12 @@ struct DXFCPP_EXPORT SessionFilter { protected: SessionFilterEnum code_{}; - std::string name_; + std::string name_{}; /// Required type, std::nullopt if not relevant. - std::optional type_; + std::optional type_{}; /// Required trading flag, std::nullopt if not relevant. - std::optional trading_; + std::optional trading_{}; mutable std::mutex mtx_{}; mutable JavaObjectHandle handle_{}; diff --git a/samples/cpp/OnDemandSample/src/main.cpp b/samples/cpp/OnDemandSample/src/main.cpp index 23104eb72..f3b3c6a55 100644 --- a/samples/cpp/OnDemandSample/src/main.cpp +++ b/samples/cpp/OnDemandSample/src/main.cpp @@ -16,7 +16,6 @@ int main(int /* argc */, char ** /* argv */) { using namespace std::literals; try { - // get on-demand-only data feed auto onDemand = OnDemandService::getInstance(); auto feed = onDemand->getEndpoint()->getFeed(); diff --git a/src/internal/Common.cpp b/src/internal/Common.cpp index 4852f0f76..b2ff2bae0 100644 --- a/src/internal/Common.cpp +++ b/src/internal/Common.cpp @@ -27,7 +27,7 @@ std::int32_t getDayIdByYearMonthDay(std::int32_t year, std::int32_t month, std:: namespace util { -inline void throwInvalidChar(char c, const std::string &name) { +void throwInvalidChar(char c, const std::string &name) { throw InvalidArgumentException("Invalid " + name + ": " + encodeChar(c)); } diff --git a/src/internal/utils/CmdArgsUtils.cpp b/src/internal/utils/CmdArgsUtils.cpp index d13803c87..677d35df2 100644 --- a/src/internal/utils/CmdArgsUtils.cpp +++ b/src/internal/utils/CmdArgsUtils.cpp @@ -64,10 +64,6 @@ auto toUpper = [](auto&& s) { ranges::to(); }; -decltype(ranges::views::transform([](auto &&s) { - return toUpper(s); -})) transformToUpper{}; - std::unordered_set parseStringSymbols(const std::string &symbols) noexcept { auto trimmedSymbols = trimStr(symbols); From b1b27d8cc1609c054c42f31481ba8bf859184ecc Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 6 Sep 2024 13:13:28 +0300 Subject: [PATCH 080/178] [MDAPI-127] [C++] Make statics initialization more lazy. Tune up the endpoint's test. --- tests/api/DXEndpointTest.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/api/DXEndpointTest.cpp b/tests/api/DXEndpointTest.cpp index 0d880c6e8..78b6d79bc 100644 --- a/tests/api/DXEndpointTest.cpp +++ b/tests/api/DXEndpointTest.cpp @@ -141,19 +141,6 @@ TEST_CASE("dxfcpp::DXFeed::getInstance()") { dxfcpp::DXFeed::getInstance(); } -TEST_CASE("DXEndpoint::user") { - using namespace std::literals; - - // dxfcpp::System::setProperty("log.file", "log.txt"); - - auto endpoint = dxfcpp::DXEndpoint::create(dxfcpp::DXEndpoint::Role::FEED); - - endpoint->user("\xe2\x28\xa1"); - endpoint->connect("123123123"); - - std::this_thread::sleep_for(std::chrono::seconds(5)); -} - TEST_CASE("DXEndpoint::getFeed and getPublisher") { auto feed = DXEndpoint::getInstance()->getFeed(); auto publisher = DXEndpoint::getInstance()->getPublisher(); @@ -180,8 +167,6 @@ TEST_CASE("Test DXEndpoint + multi-thread setProperty") { } endpoint->close(); - - std::cout << "!!!!!\n" << std::endl; } TEST_CASE("Test DXEndpoint + multi-thread setProperty v2") { @@ -197,6 +182,4 @@ TEST_CASE("Test DXEndpoint + multi-thread setProperty v2") { std::this_thread::sleep_for(1s); endpoint->close(); - - std::cout << "!!!!!\n" << std::endl; } \ No newline at end of file From 535ea46698b6782bcc35ab4a5ca83357815050eb Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 9 Sep 2024 16:13:47 +0300 Subject: [PATCH 081/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. Add IsolatedInstrumentProfileCollector skeleton --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../IsolatedInstrumentProfileCollector.hpp | 37 ++++++++++++++ .../IsolatedInstrumentProfileCollector.cpp | 49 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp create mode 100644 src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 52c3c0858..a7ad891ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/internal/IsolatedTools.cpp src/isolated/util/IsolatedTimePeriod.cpp src/isolated/ipf/IsolatedInstrumentProfile.cpp + src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp src/isolated/ipf/IsolatedInstrumentProfileReader.cpp ) diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 13712e45e..e13dee68a 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -71,6 +71,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" #include "isolated/ipf/IsolatedInstrumentProfile.hpp" +#include "isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp" #include "isolated/ipf/IsolatedInstrumentProfileReader.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp new file mode 100644 index 000000000..0cd2dfd2b --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../../internal/Conf.hpp" + +#include "../../../ipf/live/InstrumentProfileCollector.hpp" + +#include +#include +#include + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ipf::live::IsolatedInstrumentProfileCollector { +/* dxfg_ipf_collector_t* */ JavaObjectHandle create(); +std::int64_t getLastUpdateTime( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector); +bool updateInstrumentProfile( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, + /* dxfg_instrument_profile_t * */ void *ip); +/* dxfg_iterable_ip_t* */ void * +view(/* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector); +bool addUpdateListener( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); +bool removeUpdateListener( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); +} // namespace isolated::ipf::live::IsolatedInstrumentProfileCollector + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp new file mode 100644 index 000000000..473c37f16 --- /dev/null +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +//TODO: implement + +namespace isolated::ipf::live::IsolatedInstrumentProfileCollector { +/* dxfg_ipf_collector_t* */ JavaObjectHandle create() { + return JavaObjectHandle{nullptr}; +} + +std::int64_t getLastUpdateTime( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector) { + return {}; +} + +bool updateInstrumentProfile( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, + /* dxfg_instrument_profile_t * */ void *ip) { + return {}; +} + +/* dxfg_iterable_ip_t* */ void * +view(/* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector) { + return nullptr; +} + +bool addUpdateListener( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { + return {}; +} + +bool removeUpdateListener( + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { + return {}; +} + +} // namespace isolated::ipf::live::IsolatedInstrumentProfileCollector + +DXFCPP_END_NAMESPACE \ No newline at end of file From 3d65f74d8e357409e2a4060e505356f15ec85da0 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 12 Sep 2024 17:42:32 +0300 Subject: [PATCH 082/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedInstrumentProfileCollector --- .../event/market/OrderBase.hpp | 4 +- .../ipf/live/InstrumentProfileCollector.hpp | 18 ++-- .../isolated/Isolated.hpp | 14 --- .../IsolatedInstrumentProfileCollector.hpp | 6 +- src/internal/Isolate.cpp | 87 ------------------- src/ipf/live/InstrumentProfileCollector.cpp | 25 +++--- .../IsolatedInstrumentProfileCollector.cpp | 59 ++++++++++--- 7 files changed, 73 insertions(+), 140 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp index 6907dc998..4757966c5 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderBase.hpp @@ -607,8 +607,8 @@ class DXFCPP_EXPORT OrderBase : public MarketEvent, public IndexedEvent { std::string getExchangeCodeString() const noexcept { // TODO: cache [EN-8231] - return std::string( - 1ULL, static_cast( // NOLINT(*-return-braced-init-list) + return std::string( // NOLINT(*-return-braced-init-list) + 1ULL, static_cast( static_cast(getBits(orderBaseData_.flags, EXCHANGE_MASK, EXCHANGE_SHIFT)))); } diff --git a/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp b/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp index 7ee6b07b5..d8989d4d6 100644 --- a/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileCollector.hpp @@ -48,14 +48,14 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { std::unordered_map> &)>> onInstrumentProfilesUpdateHandlers_{}; - InstrumentProfileCollector() noexcept; + InstrumentProfileCollector(); struct Impl; - void addListenerHandle(std::size_t id) noexcept; - void removeListenerHandle(std::size_t id) noexcept; + void addListenerHandle(std::size_t id); + void removeListenerHandle(std::size_t id); - void removeUpdateListenerImpl(std::size_t listenerId) noexcept { + void removeUpdateListenerImpl(std::size_t listenerId) { removeListenerHandle(listenerId); onInstrumentProfilesUpdateHandlers_[listenerId].remove(listenerId); @@ -84,7 +84,7 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { * * @return The last modification time (in milliseconds) of instrument profiles or zero if it is unknown. */ - std::int64_t getLastUpdateTime() const noexcept; + std::int64_t getLastUpdateTime() const; /** * Returns last modification time (as std::chrono::milliseconds) of instrument profiles or zero if it is unknown. @@ -93,7 +93,7 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { * @return The last modification time (as std::chrono::milliseconds) of instrument profiles or zero if it is * unknown. */ - std::chrono::milliseconds getLastUpdateTimeAsDuration() const noexcept { + std::chrono::milliseconds getLastUpdateTimeAsDuration() const { return std::chrono::milliseconds(getLastUpdateTime()); } @@ -118,7 +118,7 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { * * @return A concurrent view of the set of instrument profiles. */ - std::shared_ptr view() const noexcept; + std::shared_ptr view() const; /** * Adds listener that is notified about any updates in the set of instrument profiles. @@ -157,7 +157,7 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { * @return The listener id */ template - std::size_t addUpdateListener(InstrumentProfileUpdateListener listener) noexcept + std::size_t addUpdateListener(InstrumentProfileUpdateListener listener) #if __cpp_concepts requires requires { { listener(std::vector>{}) } -> std::same_as; @@ -187,7 +187,7 @@ class DXFCPP_EXPORT InstrumentProfileCollector final : public SharedEntity { * * @param listenerId The listener id */ - void removeUpdateListener(std::size_t listenerId) noexcept { + void removeUpdateListener(std::size_t listenerId) { std::lock_guard guard{listenersMutex_}; if (onInstrumentProfilesUpdateHandlers_.contains(listenerId)) { diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 34f65f834..dcf833fcf 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -24,20 +24,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { namespace ipf { -struct InstrumentProfileCollector { - static /* dxfg_ipf_collector_t* */ void *create() noexcept; - static std::int64_t getLastUpdateTime(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept; - static bool updateInstrumentProfile( - /* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle, - /* dxfg_instrument_profile_t * */ void *ip) noexcept; - static /* dxfg_iterable_ip_t* */ void * - view(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept; - static bool addUpdateListener(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle, - /* dxfg_ipf_update_listener_t* */ void *listener) noexcept; - static bool removeUpdateListener(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle, - /* dxfg_ipf_update_listener_t* */ void *listener) noexcept; -}; - struct InstrumentProfileConnection { static /* dxfg_ipf_connection_t* */ void * createConnection(const std::string &address, diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp index 0cd2dfd2b..90348da0e 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp @@ -21,15 +21,15 @@ std::int64_t getLastUpdateTime( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector); bool updateInstrumentProfile( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, - /* dxfg_instrument_profile_t * */ void *ip); + /* dxfg_instrument_profile_t * */ const JavaObjectHandle &ip); /* dxfg_iterable_ip_t* */ void * view(/* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector); bool addUpdateListener( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, - /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); bool removeUpdateListener( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, - /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); } // namespace isolated::ipf::live::IsolatedInstrumentProfileCollector DXFCPP_END_NAMESPACE diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 6ab5651ec..03a2adf71 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -154,93 +154,6 @@ using NativeStringList = typename isolated::internal::NativeStringListWrapper(runIsolatedOrElse( - [](auto threadHandle) { - return dxfg_InstrumentProfileCollector_new(static_cast(threadHandle)); - }, - nullptr)); -} - -std::int64_t InstrumentProfileCollector::getLastUpdateTime( - /* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept { - if (!instrumentProfileCollectorHandle) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileCollector_getLastUpdateTime(static_cast(threadHandle), - params...); - }, - 0, static_cast(instrumentProfileCollectorHandle)); -} - -bool InstrumentProfileCollector::updateInstrumentProfile( - /* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle, - /* dxfg_instrument_profile_t * */ void *ip) noexcept { - if (!instrumentProfileCollectorHandle || !ip) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileCollector_updateInstrumentProfile( - static_cast(threadHandle), params...) == 0; - }, - false, static_cast(instrumentProfileCollectorHandle), - static_cast(ip)); -} - -/* dxfg_iterable_ip_t* */ void * -InstrumentProfileCollector::view(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept { - if (!instrumentProfileCollectorHandle) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileCollector_view(static_cast(threadHandle), params...); - }, - nullptr, static_cast(instrumentProfileCollectorHandle))); -} - -bool InstrumentProfileCollector::addUpdateListener(/* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle, - /* dxfg_ipf_update_listener_t* */ void *listener) noexcept { - if (!instrumentProfileCollectorHandle || !listener) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileCollector_addUpdateListener(static_cast(threadHandle), - params...) == 0; - }, - false, static_cast(instrumentProfileCollectorHandle), - static_cast(listener)); -} - -bool InstrumentProfileCollector::removeUpdateListener( - /* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle, - /* dxfg_ipf_update_listener_t* */ void *listener) noexcept { - if (!instrumentProfileCollectorHandle || !listener) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileCollector_removeUpdateListener( - static_cast(threadHandle), params...) == 0; - }, - false, static_cast(instrumentProfileCollectorHandle), - static_cast(listener)); -} - /* dxfg_ipf_connection_t* */ void *InstrumentProfileConnection::createConnection( const std::string &address, /* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept { diff --git a/src/ipf/live/InstrumentProfileCollector.cpp b/src/ipf/live/InstrumentProfileCollector.cpp index 55ba440e5..c4e64ed64 100644 --- a/src/ipf/live/InstrumentProfileCollector.cpp +++ b/src/ipf/live/InstrumentProfileCollector.cpp @@ -81,12 +81,11 @@ struct InstrumentProfileCollector::Impl { } }; -InstrumentProfileCollector::InstrumentProfileCollector() noexcept - : id_{Id::UNKNOWN}, handle_{} { - handle_ = JavaObjectHandle(dxfcpp::isolated::ipf::InstrumentProfileCollector::create()); +InstrumentProfileCollector::InstrumentProfileCollector() : id_{Id::UNKNOWN} { + handle_ = dxfcpp::isolated::ipf::live::IsolatedInstrumentProfileCollector::create(); } -void InstrumentProfileCollector::addListenerHandle(std::size_t id) noexcept { +void InstrumentProfileCollector::addListenerHandle(std::size_t id) { if (!handle_) { return; } @@ -100,10 +99,10 @@ void InstrumentProfileCollector::addListenerHandle(std::size_t id) noexcept { return; } - isolated::ipf::InstrumentProfileCollector::addUpdateListener(handle_.get(), listenerHandles_[id].get()); + isolated::ipf::live::IsolatedInstrumentProfileCollector::addUpdateListener(handle_, listenerHandles_[id]); } -void InstrumentProfileCollector::removeListenerHandle(std::size_t id) noexcept { +void InstrumentProfileCollector::removeListenerHandle(std::size_t id) { if (!handle_) { return; } @@ -112,10 +111,10 @@ void InstrumentProfileCollector::removeListenerHandle(std::size_t id) noexcept { return; } - isolated::ipf::InstrumentProfileCollector::removeUpdateListener(handle_.get(), listenerHandles_[id].get()); + isolated::ipf::live::IsolatedInstrumentProfileCollector::removeUpdateListener(handle_, listenerHandles_[id]); } -InstrumentProfileCollector::~InstrumentProfileCollector() noexcept { +InstrumentProfileCollector::~InstrumentProfileCollector() { std::lock_guard guard{listenersMutex_}; std::vector listenerIds{}; @@ -140,12 +139,12 @@ InstrumentProfileCollector::Ptr InstrumentProfileCollector::create() { return collector; } -std::int64_t InstrumentProfileCollector::getLastUpdateTime() const noexcept { +std::int64_t InstrumentProfileCollector::getLastUpdateTime() const { if (!handle_) { return 0; } - return dxfcpp::isolated::ipf::InstrumentProfileCollector::getLastUpdateTime(handle_.get()); + return dxfcpp::isolated::ipf::live::IsolatedInstrumentProfileCollector::getLastUpdateTime(handle_); } void InstrumentProfileCollector::updateInstrumentProfile(std::shared_ptr ip) const { @@ -153,15 +152,15 @@ void InstrumentProfileCollector::updateInstrumentProfile(std::shared_ptrhandle_.get()); + isolated::ipf::live::IsolatedInstrumentProfileCollector::updateInstrumentProfile(handle_, ip->handle_); } -std::shared_ptr InstrumentProfileCollector::view() const noexcept { +std::shared_ptr InstrumentProfileCollector::view() const { if (!handle_) { return {}; } - auto iterable = dxfcpp::isolated::ipf::InstrumentProfileCollector::view(handle_.get()); + auto iterable = dxfcpp::isolated::ipf::live::IsolatedInstrumentProfileCollector::view(handle_); return IterableInstrumentProfile::create(iterable); } diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp index 473c37f16..755f584e3 100644 --- a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp @@ -4,44 +4,79 @@ #include #include -#include #include DXFCPP_BEGIN_NAMESPACE -//TODO: implement - namespace isolated::ipf::live::IsolatedInstrumentProfileCollector { /* dxfg_ipf_collector_t* */ JavaObjectHandle create() { - return JavaObjectHandle{nullptr}; + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileCollector_new)}; } std::int64_t getLastUpdateTime( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector) { - return {}; + if (!instrumentProfileCollector) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_getLastUpdateTime`. The " + "`instrumentProfileCollector` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_getLastUpdateTime, + static_cast(instrumentProfileCollector.get())); } bool updateInstrumentProfile( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, - /* dxfg_instrument_profile_t * */ void *ip) { - return {}; + /* dxfg_instrument_profile_t * */ const JavaObjectHandle &ip) { + if (!instrumentProfileCollector || !ip) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_updateInstrumentProfile`. The " + "`instrumentProfileCollector` handle or `ip` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_updateInstrumentProfile, + static_cast(instrumentProfileCollector.get()), + static_cast(ip.get())) == 0; } /* dxfg_iterable_ip_t* */ void * view(/* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector) { - return nullptr; + if (!instrumentProfileCollector) { + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfileCollector_view`. The " + "`instrumentProfileCollector` handle is invalid"); + } + + return dxfcpp::bit_cast(runGraalFunctionAndThrowIfNullptr( + dxfg_InstrumentProfileCollector_view, static_cast(instrumentProfileCollector.get()))); } bool addUpdateListener( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, - /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { - return {}; + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { + if (!instrumentProfileCollector || !listener) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_addUpdateListener`. The " + "`instrumentProfileCollector` handle or `listener` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_addUpdateListener, + static_cast(instrumentProfileCollector.get()), + static_cast(listener.get())) == 0; } bool removeUpdateListener( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, - /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { - return {}; + /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { + if (!instrumentProfileCollector || !listener) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_removeUpdateListener`. The " + "`instrumentProfileCollector` handle or `listener` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_removeUpdateListener, + static_cast(instrumentProfileCollector.get()), + static_cast(listener.get())) == 0; } } // namespace isolated::ipf::live::IsolatedInstrumentProfileCollector From dd5a7cca8db69fc8bd5075722312b8e7db9cb985 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 13 Sep 2024 21:04:33 +0300 Subject: [PATCH 083/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedInstrumentProfileUpdateListener Fix warnings on Win (/W4) --- CMakeLists.txt | 4 ++-- .../internal/PrecompiledHeaders.hpp | 2 ++ .../isolated/Isolated.hpp | 5 ---- .../IsolatedInstrumentProfileCollector.hpp | 16 +++++++++++-- .../dxfeed_graal_cpp_api/promise/Promise.hpp | 2 +- samples/cpp/DxFeedConnect/src/main.cpp | 2 ++ samples/cpp/PublishProfiles/src/main.cpp | 2 ++ src/internal/Isolate.cpp | 16 ------------- src/internal/utils/CmdArgsUtils.cpp | 18 ++++++++++---- src/internal/utils/EnumUtils.cpp | 2 ++ src/internal/utils/StringUtils.cpp | 2 ++ src/ipf/live/InstrumentProfileCollector.cpp | 4 ++-- .../IsolatedInstrumentProfileCollector.cpp | 24 +++++++++++++++++-- tests/api/DXEndpointTest.cpp | 5 ++-- tests/schedule/ScheduleTest.cpp | 2 ++ tools/Tools/src/Args/Args.hpp | 2 ++ tools/Tools/src/Connect/ConnectTool.hpp | 2 ++ tools/Tools/src/Dump/DumpTool.hpp | 2 ++ tools/Tools/src/Help/HelpTool.hpp | 2 ++ .../Tools/src/LatencyTest/LatencyTestTool.hpp | 2 ++ tools/Tools/src/PerfTest/PerfTestTool.hpp | 2 ++ tools/Tools/src/Qds/QdsTool.hpp | 2 ++ tools/Tools/src/Tools.hpp | 2 ++ tools/Tools/src/main.cpp | 2 ++ 24 files changed, 87 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7ad891ae..99baf7f12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -404,13 +404,13 @@ target_include_directories(${PROJECT_NAME}_static PRIVATE third_party/range-v3-$ target_compile_definitions(${PROJECT_NAME}_static PRIVATE FMT_HEADER_ONLY=1 _SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS=1) -set(DXFCXX_MSVC_COMPILE_OPTIONS "/W2") +set(DXFCXX_MSVC_COMPILE_OPTIONS "/W4") set(DXFCXX_MSVC_DEBUG_LINK_OPTIONS "/PDBALTPATH:$") set(DXFCXX_GCC_LIKE_COMPILE_OPTIONS -fPIC -Wall -Wextra -pedantic) set(DXFCXX_GCC_LIKE_LINK_OPTIONS "-fPIC") #A workaround to fix 'relocation truncated to fit: IMAGE_REL_AMD64_SECREL' error (MinGW + Debug) -set(DXFCXX_MINGW_DEBUG_LINK_OPTIONS "-Wl,--disable-dynamicbase,--disable-high-entropy-va,--default-image-base-low") +set(MINGW_DEBUG_LINK_OPTIONS "-Wl,--disable-dynamicbase,--disable-high-entropy-va,--default-image-base-low") # https://developercommunity.visualstudio.com/t/Invalid-code-generation-in-release-1940/10678572?sort=newest&viewtype=all # https://github.com/microsoft/STL/wiki/Changelog#vs-2022-1710 diff --git a/include/dxfeed_graal_cpp_api/internal/PrecompiledHeaders.hpp b/include/dxfeed_graal_cpp_api/internal/PrecompiledHeaders.hpp index 4d0fdf887..322bbb75f 100644 --- a/include/dxfeed_graal_cpp_api/internal/PrecompiledHeaders.hpp +++ b/include/dxfeed_graal_cpp_api/internal/PrecompiledHeaders.hpp @@ -43,7 +43,9 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() #include "Common.hpp" #include "Handler.hpp" diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index dcf833fcf..8770023b8 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -53,11 +53,6 @@ struct InstrumentProfileIterator { static /* dxfg_instrument_profile_t* */ void *next(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; }; -struct InstrumentProfileUpdateListener { - static /* dxfg_ipf_update_listener_t* */ void *create(/* dxfg_ipf_update_listener_function */ void *userFunc, - void *userData) noexcept; -}; - } // namespace ipf namespace ondemand { diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp index 90348da0e..286cd37f0 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp @@ -15,7 +15,10 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE -namespace isolated::ipf::live::IsolatedInstrumentProfileCollector { +namespace isolated::ipf::live { + +namespace IsolatedInstrumentProfileCollector { + /* dxfg_ipf_collector_t* */ JavaObjectHandle create(); std::int64_t getLastUpdateTime( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector); @@ -30,7 +33,16 @@ bool addUpdateListener( bool removeUpdateListener( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener); -} // namespace isolated::ipf::live::IsolatedInstrumentProfileCollector + +} // namespace IsolatedInstrumentProfileCollector + +namespace IsolatedInstrumentProfileUpdateListener { + +/* dxfg_ipf_update_listener_t* */ JavaObjectHandle +create(/* dxfg_ipf_update_listener_function */ void *userFunc, void *userData); + +} +} // namespace isolated::ipf::live DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp index 5bfc5c809..cb96f4166 100644 --- a/include/dxfeed_graal_cpp_api/promise/Promise.hpp +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -303,7 +303,7 @@ template struct EventsPromiseMixin { timeout = std::numeric_limits::max(); } - static_cast(this)->impl.await(timeout); + static_cast(this)->impl.await(static_cast(timeout)); return getResult(); } diff --git a/samples/cpp/DxFeedConnect/src/main.cpp b/samples/cpp/DxFeedConnect/src/main.cpp index 00df8ce5a..0f2b32cba 100644 --- a/samples/cpp/DxFeedConnect/src/main.cpp +++ b/samples/cpp/DxFeedConnect/src/main.cpp @@ -8,7 +8,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() using namespace dxfcpp; using namespace dxfcpp::literals; diff --git a/samples/cpp/PublishProfiles/src/main.cpp b/samples/cpp/PublishProfiles/src/main.cpp index 39d9613e2..d4cc75970 100644 --- a/samples/cpp/PublishProfiles/src/main.cpp +++ b/samples/cpp/PublishProfiles/src/main.cpp @@ -5,7 +5,9 @@ #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() using namespace dxfcpp; using namespace dxfcpp::literals; diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 03a2adf71..401ede74f 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -373,22 +373,6 @@ InstrumentProfileIterator::next(/* dxfg_iterable_ip_t * */ void *iterable) noexc nullptr, static_cast(iterable))); } -/* dxfg_ipf_update_listener_t* */ void * -InstrumentProfileUpdateListener::create(/* dxfg_ipf_update_listener_function */ void *userFunc, - void *userData) noexcept { - if (!userFunc) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&userFunc, auto &&userData) { - return dxfg_InstrumentProfileUpdateListener_new(static_cast(threadHandle), - userFunc, userData); - }, - nullptr, dxfcpp::bit_cast(userFunc), userData)); -} - } // namespace ipf namespace ondemand { diff --git a/src/internal/utils/CmdArgsUtils.cpp b/src/internal/utils/CmdArgsUtils.cpp index 677d35df2..6b9dc9bf3 100644 --- a/src/internal/utils/CmdArgsUtils.cpp +++ b/src/internal/utils/CmdArgsUtils.cpp @@ -1,11 +1,15 @@ // Copyright (c) 2024 Devexperts LLC. // SPDX-License-Identifier: MPL-2.0 +#define _CRT_SECURE_NO_WARNINGS + #include #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4996) + #include #include #include @@ -22,7 +26,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() #if !defined(__cpp_lib_chrono) || (__cpp_lib_chrono < 201907L) # include @@ -47,15 +53,15 @@ decltype(ranges::views::transform([](auto &&s) { return s | ranges::to(); })) transformToString{}; -decltype(ranges::views::transform([](const std::string &s) { - return trimStr(s); -})) trim{}; - auto splitAndTrim = [](auto &&symbols, char sep = ',') noexcept { + decltype(ranges::views::transform([](const std::string &s) { + return trimStr(s); + })) trim{}; + return symbols | ranges::views::split(sep) | filterNonEmpty | transformToString | trim; }; -auto toUpper = [](auto&& s) { +auto toUpper = [](auto &&s) { auto locale = std::locale{}; return s | ranges::views::transform([&locale](auto c) { @@ -232,3 +238,5 @@ std::unordered_map CmdArgsUtils::parseProperties(const } DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/utils/EnumUtils.cpp b/src/internal/utils/EnumUtils.cpp index 5ced84deb..1291c57a6 100644 --- a/src/internal/utils/EnumUtils.cpp +++ b/src/internal/utils/EnumUtils.cpp @@ -18,7 +18,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() using namespace std::literals; diff --git a/src/internal/utils/StringUtils.cpp b/src/internal/utils/StringUtils.cpp index 6e9fdf186..2145baa39 100644 --- a/src/internal/utils/StringUtils.cpp +++ b/src/internal/utils/StringUtils.cpp @@ -16,7 +16,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() DXFCPP_BEGIN_NAMESPACE diff --git a/src/ipf/live/InstrumentProfileCollector.cpp b/src/ipf/live/InstrumentProfileCollector.cpp index c4e64ed64..9686a24bb 100644 --- a/src/ipf/live/InstrumentProfileCollector.cpp +++ b/src/ipf/live/InstrumentProfileCollector.cpp @@ -91,9 +91,9 @@ void InstrumentProfileCollector::addListenerHandle(std::size_t id) { } listenerHandles_.emplace( - id, JavaObjectHandle(isolated::ipf::InstrumentProfileUpdateListener::create( + id, isolated::ipf::live::IsolatedInstrumentProfileUpdateListener::create( dxfcpp::bit_cast(&InstrumentProfileCollector::Impl::onInstrumentProfilesUpdate), - dxfcpp::bit_cast(dxfcpp::pack(id_.getValue(), id))))); + dxfcpp::bit_cast(dxfcpp::pack(id_.getValue(), id)))); if (!listenerHandles_[id]) { return; diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp index 755f584e3..aea342067 100644 --- a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp @@ -8,7 +8,9 @@ DXFCPP_BEGIN_NAMESPACE -namespace isolated::ipf::live::IsolatedInstrumentProfileCollector { +namespace isolated::ipf::live { + +namespace IsolatedInstrumentProfileCollector { /* dxfg_ipf_collector_t* */ JavaObjectHandle create() { return JavaObjectHandle{ runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileCollector_new)}; @@ -79,6 +81,24 @@ bool removeUpdateListener( static_cast(listener.get())) == 0; } -} // namespace isolated::ipf::live::IsolatedInstrumentProfileCollector +} // namespace IsolatedInstrumentProfileCollector + +namespace IsolatedInstrumentProfileUpdateListener { + +/* dxfg_ipf_update_listener_t* */ JavaObjectHandle +create(/* dxfg_ipf_update_listener_function */ void *userFunc, void *userData) { + if (!userFunc) { + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfileUpdateListener_new`. The " + "`userFunc` is nullptr"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileUpdateListener_new, + dxfcpp::bit_cast(userFunc), userData)}; +} + +} // namespace IsolatedInstrumentProfileUpdateListener + +} // namespace isolated::ipf::live DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/tests/api/DXEndpointTest.cpp b/tests/api/DXEndpointTest.cpp index 78b6d79bc..0bf4d9c05 100644 --- a/tests/api/DXEndpointTest.cpp +++ b/tests/api/DXEndpointTest.cpp @@ -160,10 +160,11 @@ TEST_CASE("Test DXEndpoint + multi-thread setProperty") { auto endpoint = DXEndpoint::create(); for (int i = 0; i < 1000; ++i) { - std::thread t{[] { + std::thread t2{[] { System::setProperty("test", "test"); }}; - t.join(); + + t2.join(); } endpoint->close(); diff --git a/tests/schedule/ScheduleTest.cpp b/tests/schedule/ScheduleTest.cpp index 39973c6b4..047d3b831 100644 --- a/tests/schedule/ScheduleTest.cpp +++ b/tests/schedule/ScheduleTest.cpp @@ -11,7 +11,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() #include diff --git a/tools/Tools/src/Args/Args.hpp b/tools/Tools/src/Args/Args.hpp index 06f54aa42..2211d0603 100644 --- a/tools/Tools/src/Args/Args.hpp +++ b/tools/Tools/src/Args/Args.hpp @@ -17,7 +17,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/Connect/ConnectTool.hpp b/tools/Tools/src/Connect/ConnectTool.hpp index a63788ab3..e703e809a 100644 --- a/tools/Tools/src/Connect/ConnectTool.hpp +++ b/tools/Tools/src/Connect/ConnectTool.hpp @@ -19,7 +19,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/Dump/DumpTool.hpp b/tools/Tools/src/Dump/DumpTool.hpp index 7501e3d62..67f6fe101 100644 --- a/tools/Tools/src/Dump/DumpTool.hpp +++ b/tools/Tools/src/Dump/DumpTool.hpp @@ -19,7 +19,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/Help/HelpTool.hpp b/tools/Tools/src/Help/HelpTool.hpp index 6649e9d66..3f8546257 100644 --- a/tools/Tools/src/Help/HelpTool.hpp +++ b/tools/Tools/src/Help/HelpTool.hpp @@ -28,7 +28,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() #include diff --git a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp index d360f0392..52fecd4cc 100644 --- a/tools/Tools/src/LatencyTest/LatencyTestTool.hpp +++ b/tools/Tools/src/LatencyTest/LatencyTestTool.hpp @@ -21,7 +21,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/PerfTest/PerfTestTool.hpp b/tools/Tools/src/PerfTest/PerfTestTool.hpp index cd5485913..eecb2ae58 100644 --- a/tools/Tools/src/PerfTest/PerfTestTool.hpp +++ b/tools/Tools/src/PerfTest/PerfTestTool.hpp @@ -20,7 +20,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/Qds/QdsTool.hpp b/tools/Tools/src/Qds/QdsTool.hpp index 2ce3fc789..e47090957 100644 --- a/tools/Tools/src/Qds/QdsTool.hpp +++ b/tools/Tools/src/Qds/QdsTool.hpp @@ -7,7 +7,9 @@ #include "../Args/Args.hpp" +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/Tools.hpp b/tools/Tools/src/Tools.hpp index 91e5abcaf..ad0e60231 100644 --- a/tools/Tools/src/Tools.hpp +++ b/tools/Tools/src/Tools.hpp @@ -25,7 +25,9 @@ #include #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() namespace dxfcpp::tools { diff --git a/tools/Tools/src/main.cpp b/tools/Tools/src/main.cpp index 75f9920e0..568ac93e9 100644 --- a/tools/Tools/src/main.cpp +++ b/tools/Tools/src/main.cpp @@ -14,7 +14,9 @@ #include +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4702) #include +DXFCXX_DISABLE_MSC_WARNINGS_POP() template struct overloaded : Ts... { using Ts::operator()...; From c02cf8d2d02e6b11a5e3927ba683975dde52fe83 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sat, 14 Sep 2024 20:11:24 +0300 Subject: [PATCH 084/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. Enable MinGW link options --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99baf7f12..fe10fb8a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,7 +410,7 @@ set(DXFCXX_GCC_LIKE_COMPILE_OPTIONS -fPIC -Wall -Wextra -pedantic) set(DXFCXX_GCC_LIKE_LINK_OPTIONS "-fPIC") #A workaround to fix 'relocation truncated to fit: IMAGE_REL_AMD64_SECREL' error (MinGW + Debug) -set(MINGW_DEBUG_LINK_OPTIONS "-Wl,--disable-dynamicbase,--disable-high-entropy-va,--default-image-base-low") +set(DXFCXX_MINGW_DEBUG_LINK_OPTIONS "-Wl,--disable-dynamicbase,--disable-high-entropy-va,--default-image-base-low") # https://developercommunity.visualstudio.com/t/Invalid-code-generation-in-release-1940/10678572?sort=newest&viewtype=all # https://github.com/microsoft/STL/wiki/Changelog#vs-2022-1710 From 674080d3c7416521db6eaf88144868bce3d039f6 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 16 Sep 2024 00:30:53 +0300 Subject: [PATCH 085/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedInstrumentProfileConnection --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../ipf/live/InstrumentProfileConnection.hpp | 30 +-- .../isolated/Isolated.hpp | 18 -- .../IsolatedInstrumentProfileConnection.hpp | 53 ++++++ src/internal/Isolate.cpp | 175 ------------------ src/ipf/live/InstrumentProfileConnection.cpp | 87 +++------ .../IsolatedInstrumentProfileCollector.cpp | 30 ++- .../IsolatedInstrumentProfileConnection.cpp | 165 +++++++++++++++++ 9 files changed, 283 insertions(+), 277 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp create mode 100644 src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fe10fb8a3..b19e7e731 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,6 +220,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/util/IsolatedTimePeriod.cpp src/isolated/ipf/IsolatedInstrumentProfile.cpp src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp + src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp src/isolated/ipf/IsolatedInstrumentProfileReader.cpp ) diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index e13dee68a..3bb3fa08e 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -72,6 +72,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/internal/IsolatedTools.hpp" #include "isolated/ipf/IsolatedInstrumentProfile.hpp" #include "isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp" +#include "isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp" #include "isolated/ipf/IsolatedInstrumentProfileReader.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" diff --git a/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileConnection.hpp b/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileConnection.hpp index 2cbd14d7f..607d49700 100644 --- a/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileConnection.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/live/InstrumentProfileConnection.hpp @@ -102,7 +102,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return new instrument profile connection. */ - static Ptr createConnection(const std::string &address, InstrumentProfileCollector::Ptr collector); + static Ptr createConnection(const StringLikeWrapper &address, InstrumentProfileCollector::Ptr collector); /** * Returns the address of this instrument profile connection. @@ -110,7 +110,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return The address of this instrument profile connection. */ - std::string getAddress() const noexcept; + std::string getAddress() const; /** * Returns update period in milliseconds. @@ -121,7 +121,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return The update period in milliseconds. */ - std::int64_t getUpdatePeriod() const noexcept; + std::int64_t getUpdatePeriod() const; /** * Returns update period in milliseconds as chrono::duration @@ -132,7 +132,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return The update period in milliseconds as chrono::duration. */ - std::chrono::milliseconds getUpdatePeriodAsDuration() const noexcept { + std::chrono::milliseconds getUpdatePeriodAsDuration() const { return std::chrono::milliseconds(getUpdatePeriod()); } @@ -142,7 +142,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * @param updatePeriod The update period in milliseconds. * @see InstrumentProfileConnection::getUpdatePeriod() */ - void setUpdatePeriod(std::int64_t updatePeriod) const noexcept; + void setUpdatePeriod(std::int64_t updatePeriod) const; /** * Changes the update period in milliseconds as chrono::duration. @@ -150,7 +150,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * @param updatePeriod The update period in milliseconds as chrono::duration. * @see InstrumentProfileConnection::getUpdatePeriod() */ - void setUpdatePeriod(std::chrono::milliseconds updatePeriod) const noexcept { + void setUpdatePeriod(std::chrono::milliseconds updatePeriod) const { setUpdatePeriod(updatePeriod.count()); } @@ -159,7 +159,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return The state of this instrument profile connections. */ - State getState() const noexcept; + State getState() const; /** * Returns last modification time (in milliseconds) of instrument profiles or zero if it is unknown. @@ -167,20 +167,20 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return The last modification time (in milliseconds) of instrument profiles or zero if it is unknown. */ - std::int64_t getLastModified() const noexcept; + std::int64_t getLastModified() const; /** * Starts this instrument profile connection. This connection's state immediately changes to * @ref InstrumentProfileConnection::State::CONNECTING "CONNECTING" and the actual connection establishment proceeds * in the background. */ - void start() const noexcept; + void start() const; /** * Closes this instrument profile connection. This connection's state immediately changes to * @ref InstrumentProfileConnection::State::CLOSED "CLOSED" and the background update procedures are terminated. */ - void close() const noexcept; + void close() const; /** * Adds listener that is notified about changes in @ref InstrumentProfileConnection::getState() "state" property. @@ -193,7 +193,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * @return the listener id */ template - std::size_t addStateChangeListener(StateChangeListener &&listener) noexcept + std::size_t addStateChangeListener(StateChangeListener &&listener) #if __cpp_concepts requires requires { { listener(State{}, State{}) } -> std::same_as; @@ -210,7 +210,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @param listenerId The listener id to remove */ - void removeStateChangeListener(std::size_t listenerId) noexcept { + void removeStateChangeListener(std::size_t listenerId) { onStateChange_ -= listenerId; } @@ -220,7 +220,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * * @return onStateChange handler with `void(State, State)` signature */ - auto &onStateChange() noexcept { + auto &onStateChange() { return onStateChange_; } @@ -231,7 +231,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * @return `true` if @ref InstrumentProfileConnection::State::COMPLETED "COMPLETED" state was reached and `false` * if the waiting time elapsed before snapshot was fully read. */ - bool waitUntilCompleted(std::int64_t timeout) const noexcept; + bool waitUntilCompleted(std::int64_t timeout) const; /** * Synchronously waits for full first snapshot read with the specified timeout. @@ -240,7 +240,7 @@ class DXFCPP_EXPORT InstrumentProfileConnection final : public SharedEntity { * @return `true` if @ref InstrumentProfileConnection::State::COMPLETED "COMPLETED" state was reached and `false` * if the waiting time elapsed before snapshot was fully read. */ - bool waitUntilCompleted(std::chrono::milliseconds timeout) const noexcept { + bool waitUntilCompleted(std::chrono::milliseconds timeout) const { return waitUntilCompleted(timeout.count()); } }; diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 8770023b8..86e88cc3a 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -24,24 +24,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { namespace ipf { -struct InstrumentProfileConnection { - static /* dxfg_ipf_connection_t* */ void * - createConnection(const std::string &address, - /* dxfg_ipf_collector_t* */ void *instrumentProfileCollectorHandle) noexcept; - static std::string getAddress(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept; - static std::int64_t getUpdatePeriod(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept; - static bool setUpdatePeriod(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle, - std::int64_t updatePeriod) noexcept; - static dxfcpp::InstrumentProfileConnection::State - getState(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept; - static std::int64_t getLastModified(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept; - static bool start(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept; - static bool close(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept; - static bool addStateChangeListener(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle, - /* dxfg_ipf_connection_state_change_listener_t * */ void *listener) noexcept; - static bool waitUntilCompleted(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle, - std::int64_t timeoutInMs) noexcept; -}; struct IpfPropertyChangeListener { static /* dxfg_ipf_connection_state_change_listener_t* */ void * diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp new file mode 100644 index 000000000..b3c282e86 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../../internal/Conf.hpp" + +#include "../../../ipf/live/InstrumentProfileConnection.hpp" +#include "../../../ipf/live/InstrumentProfileCollector.hpp" + +#include +#include +#include + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ipf::live { +namespace IsolatedInstrumentProfileConnection { + +/* dxfg_ipf_connection_t* */ JavaObjectHandle +createConnection(const StringLikeWrapper &address, + /* dxfg_ipf_collector_t* */ const JavaObjectHandle + &instrumentProfileCollector); + +std::string getAddress(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); + +std::int64_t getUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); + +bool setUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection, std::int64_t updatePeriod); + +dxfcpp::InstrumentProfileConnection::State +getState(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); + +std::int64_t getLastModified(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); + +bool start(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); + +bool close(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); + +bool addStateChangeListener(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection, + /* dxfg_ipf_connection_state_change_listener_t * */ const JavaObjectHandle& listener); + +bool waitUntilCompleted(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection, + std::int64_t timeoutInMs); + +} // namespace IsolatedInstrumentProfileConnection +} // namespace isolated::ipf::live + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 401ede74f..f0081c4cf 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -154,181 +154,6 @@ using NativeStringList = typename isolated::internal::NativeStringListWrapper(runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_createConnection(static_cast(threadHandle), - params...); - }, - nullptr, address.c_str(), static_cast(instrumentProfileCollectorHandle))); -} - -std::string InstrumentProfileConnection::getAddress( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return dxfcpp::String::EMPTY; - } - - auto address = runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_getAddress(static_cast(threadHandle), - params...); - }, - nullptr, static_cast(instrumentProfileConnectionHandle)); - - auto result = dxfcpp::toString(address); - - isolated::internal::IsolatedString::release(address); - - return result; -} - -std::int64_t InstrumentProfileConnection::getUpdatePeriod( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_getUpdatePeriod(static_cast(threadHandle), - params...); - }, - 0, static_cast(instrumentProfileConnectionHandle)); -} - -bool InstrumentProfileConnection::setUpdatePeriod(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle, - std::int64_t updatePeriod) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_setUpdatePeriod(static_cast(threadHandle), - params...) == 0; - }, - false, static_cast(instrumentProfileConnectionHandle), updatePeriod); -} - -static dxfcpp::InstrumentProfileConnection::State graalStateToState(dxfg_ipf_connection_state_t state) { - switch (state) { - case DXFG_IPF_CONNECTION_STATE_NOT_CONNECTED: - return dxfcpp::InstrumentProfileConnection::State::NOT_CONNECTED; - case DXFG_IPF_CONNECTION_STATE_CONNECTING: - return dxfcpp::InstrumentProfileConnection::State::CONNECTING; - case DXFG_IPF_CONNECTION_STATE_CONNECTED: - return dxfcpp::InstrumentProfileConnection::State::CONNECTED; - case DXFG_IPF_CONNECTION_STATE_COMPLETED: - return dxfcpp::InstrumentProfileConnection::State::COMPLETED; - case DXFG_IPF_CONNECTION_STATE_CLOSED: - return dxfcpp::InstrumentProfileConnection::State::CLOSED; - } - - // TODO: Improve error handling - return dxfcpp::InstrumentProfileConnection::State::NOT_CONNECTED; -} - -dxfcpp::InstrumentProfileConnection::State -InstrumentProfileConnection::getState(/* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return dxfcpp::InstrumentProfileConnection::State::CLOSED; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return graalStateToState(dxfg_InstrumentProfileConnection_getState( - static_cast(threadHandle), params...)); - }, - dxfcpp::InstrumentProfileConnection::State::CLOSED, - static_cast(instrumentProfileConnectionHandle)); -} - -std::int64_t InstrumentProfileConnection::getLastModified( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_getLastModified(static_cast(threadHandle), - params...); - }, - 0, static_cast(instrumentProfileConnectionHandle)); -} - -bool InstrumentProfileConnection::start( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_start(static_cast(threadHandle), - params...) == 0; - }, - false, static_cast(instrumentProfileConnectionHandle)); -} - -bool InstrumentProfileConnection::close( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&...params) { - return dxfg_InstrumentProfileConnection_close(static_cast(threadHandle), - params...) == 0; - }, - false, static_cast(instrumentProfileConnectionHandle)); -} - -bool InstrumentProfileConnection::addStateChangeListener( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle, - /* dxfg_ipf_connection_state_change_listener_t * */ void *listener) noexcept { - if (!instrumentProfileConnectionHandle || !listener) { - // TODO: Improve error handling - return false; - } - - return runGraalFunction(equalsToZero, dxfg_InstrumentProfileConnection_addStateChangeListener, false, - static_cast(instrumentProfileConnectionHandle), - static_cast(listener)); -} - -bool InstrumentProfileConnection::waitUntilCompleted( - /* dxfg_ipf_connection_t * */ void *instrumentProfileConnectionHandle, std::int64_t timeoutInMs) noexcept { - if (!instrumentProfileConnectionHandle) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&instrumentProfileConnectionHandle, auto &&listener) { - return dxfg_InstrumentProfileConnection_waitUntilCompleted( - static_cast(threadHandle), instrumentProfileConnectionHandle, - listener) == 1; - }, - false, static_cast(instrumentProfileConnectionHandle), timeoutInMs); -} - /* dxfg_ipf_connection_state_change_listener_t* */ void * IpfPropertyChangeListener::create(/* dxfg_ipf_connection_state_change_listener_func */ void *userFunc, void *userData) noexcept { diff --git a/src/ipf/live/InstrumentProfileConnection.cpp b/src/ipf/live/InstrumentProfileConnection.cpp index dd2e420e3..1a005be32 100644 --- a/src/ipf/live/InstrumentProfileConnection.cpp +++ b/src/ipf/live/InstrumentProfileConnection.cpp @@ -18,7 +18,7 @@ DXFCPP_BEGIN_NAMESPACE -static dxfcpp::InstrumentProfileConnection::State graalStateToState(dxfg_ipf_connection_state_t state) { +dxfcpp::InstrumentProfileConnection::State graalIpfConnectionStateToState(dxfg_ipf_connection_state_t state) { switch (state) { case DXFG_IPF_CONNECTION_STATE_NOT_CONNECTED: return dxfcpp::InstrumentProfileConnection::State::NOT_CONNECTED; @@ -47,7 +47,8 @@ struct InstrumentProfileConnection::Impl { } if (connection) { - connection->onStateChange_(graalStateToState(oldState), graalStateToState(newState)); + connection->onStateChange_(graalIpfConnectionStateToState(oldState), + graalIpfConnectionStateToState(newState)); if (newState == DXFG_IPF_CONNECTION_STATE_CLOSED) { ApiContext::getInstance()->getManager()->unregisterEntity(id); @@ -61,96 +62,56 @@ InstrumentProfileConnection::InstrumentProfileConnection() noexcept } InstrumentProfileConnection::Ptr -InstrumentProfileConnection::createConnection(const std::string &address, +InstrumentProfileConnection::createConnection(const StringLikeWrapper &address, InstrumentProfileCollector::Ptr collector) { std::shared_ptr connection(new InstrumentProfileConnection{}); - if (!collector->handle_) { - throw InvalidArgumentException("The collector's handle is invalid"); - } - connection->id_ = ApiContext::getInstance()->getManager()->registerEntity(connection); - connection->handle_ = JavaObjectHandle( - isolated::ipf::InstrumentProfileConnection::createConnection(address, collector->handle_.get())); + connection->handle_ = + isolated::ipf::live::IsolatedInstrumentProfileConnection::createConnection(address, collector->handle_); connection->stateChangeListenerHandle_ = JavaObjectHandle(isolated::ipf::IpfPropertyChangeListener::create( dxfcpp::bit_cast(&InstrumentProfileConnection::Impl::onStateChange), dxfcpp::bit_cast(connection->id_.getValue()))); - if (!connection->handle_ || !connection->stateChangeListenerHandle_) { - return connection; - } - - isolated::ipf::InstrumentProfileConnection::addStateChangeListener(connection->handle_.get(), - connection->stateChangeListenerHandle_.get()); + isolated::ipf::live::IsolatedInstrumentProfileConnection::addStateChangeListener( + connection->handle_, connection->stateChangeListenerHandle_); return connection; } -std::string InstrumentProfileConnection::getAddress() const noexcept { - if (!handle_) { - return String::EMPTY; - } - - return isolated::ipf::InstrumentProfileConnection::getAddress(handle_.get()); +std::string InstrumentProfileConnection::getAddress() const { + return isolated::ipf::live::IsolatedInstrumentProfileConnection::getAddress(handle_); } -std::int64_t InstrumentProfileConnection::getUpdatePeriod() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::ipf::InstrumentProfileConnection::getUpdatePeriod(handle_.get()); +std::int64_t InstrumentProfileConnection::getUpdatePeriod() const { + return isolated::ipf::live::IsolatedInstrumentProfileConnection::getUpdatePeriod(handle_); } -void InstrumentProfileConnection::setUpdatePeriod(std::int64_t updatePeriod) const noexcept { - if (!handle_) { - return; - } - - isolated::ipf::InstrumentProfileConnection::setUpdatePeriod(handle_.get(), updatePeriod); +void InstrumentProfileConnection::setUpdatePeriod(std::int64_t updatePeriod) const { + isolated::ipf::live::IsolatedInstrumentProfileConnection::setUpdatePeriod(handle_, updatePeriod); } -InstrumentProfileConnection::State InstrumentProfileConnection::getState() const noexcept { - if (!handle_) { - return InstrumentProfileConnection::State::CLOSED; - } - - return isolated::ipf::InstrumentProfileConnection::getState(handle_.get()); +InstrumentProfileConnection::State InstrumentProfileConnection::getState() const { + return isolated::ipf::live::IsolatedInstrumentProfileConnection::getState(handle_); } -std::int64_t InstrumentProfileConnection::getLastModified() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::ipf::InstrumentProfileConnection::getLastModified(handle_.get()); +std::int64_t InstrumentProfileConnection::getLastModified() const { + return isolated::ipf::live::IsolatedInstrumentProfileConnection::getLastModified(handle_); } -void InstrumentProfileConnection::start() const noexcept { - if (!handle_) { - return; - } - - isolated::ipf::InstrumentProfileConnection::start(handle_.get()); +void InstrumentProfileConnection::start() const { + isolated::ipf::live::IsolatedInstrumentProfileConnection::start(handle_); } -void InstrumentProfileConnection::close() const noexcept { - if (!handle_) { - return; - } - - isolated::ipf::InstrumentProfileConnection::close(handle_.get()); +void InstrumentProfileConnection::close() const { + isolated::ipf::live::IsolatedInstrumentProfileConnection::close(handle_); } -bool InstrumentProfileConnection::waitUntilCompleted(std::int64_t timeout) const noexcept { - if (!handle_) { - return false; - } - - return isolated::ipf::InstrumentProfileConnection::waitUntilCompleted(handle_.get(), timeout); +bool InstrumentProfileConnection::waitUntilCompleted(std::int64_t timeout) const { + return isolated::ipf::live::IsolatedInstrumentProfileConnection::waitUntilCompleted(handle_, timeout); } DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp index aea342067..887a73cf6 100644 --- a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp @@ -31,10 +31,16 @@ std::int64_t getLastUpdateTime( bool updateInstrumentProfile( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, /* dxfg_instrument_profile_t * */ const JavaObjectHandle &ip) { - if (!instrumentProfileCollector || !ip) { + if (!instrumentProfileCollector) { throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileCollector_updateInstrumentProfile`. The " - "`instrumentProfileCollector` handle or `ip` handle is invalid"); + "`instrumentProfileCollector` handle is invalid"); + } + + if (!ip) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_updateInstrumentProfile`. The " + "`ip` handle is invalid"); } return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_updateInstrumentProfile, @@ -56,10 +62,16 @@ view(/* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { - if (!instrumentProfileCollector || !listener) { + if (!instrumentProfileCollector) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_addUpdateListener`. The " + "`instrumentProfileCollector` handle is invalid"); + } + + if (!listener) { throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileCollector_addUpdateListener`. The " - "`instrumentProfileCollector` handle or `listener` handle is invalid"); + "`listener` handle is invalid"); } return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_addUpdateListener, @@ -70,10 +82,16 @@ bool addUpdateListener( bool removeUpdateListener( /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector, /* dxfg_ipf_update_listener_t* */ const JavaObjectHandle &listener) { - if (!instrumentProfileCollector || !listener) { + if (!instrumentProfileCollector) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileCollector_removeUpdateListener`. The " + "`instrumentProfileCollector` handle is invalid"); + } + + if (!listener) { throw InvalidArgumentException( "Unable to execute function `dxfg_InstrumentProfileCollector_removeUpdateListener`. The " - "`instrumentProfileCollector` handle or `listener` handle is invalid"); + "`listener` handle is invalid"); } return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileCollector_removeUpdateListener, diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp new file mode 100644 index 000000000..db2a7646b --- /dev/null +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp @@ -0,0 +1,165 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +dxfcpp::InstrumentProfileConnection::State graalIpfConnectionStateToState(dxfg_ipf_connection_state_t state); + +namespace isolated::ipf::live { +namespace IsolatedInstrumentProfileConnection { + +/* dxfg_ipf_connection_t* */ JavaObjectHandle +createConnection(const StringLikeWrapper &address, + /* dxfg_ipf_collector_t* */ const JavaObjectHandle + &instrumentProfileCollector) { + if (!instrumentProfileCollector) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_createConnection`. The " + "`instrumentProfileCollector` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileConnection_createConnection, address.c_str(), + static_cast(instrumentProfileCollector.get()))}; +} + +std::string getAddress(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfileConnection_getAddress`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + auto address = + runGraalFunctionAndThrowIfNullptr(dxfg_InstrumentProfileConnection_getAddress, + static_cast(instrumentProfileConnection.get())); + + auto result = dxfcpp::toString(address); + + isolated::internal::IsolatedString::release(address); + + return result; +} + +std::int64_t getUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_getUpdatePeriod`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileConnection_getUpdatePeriod, + static_cast(instrumentProfileConnection.get())); +} + +bool setUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection, + std::int64_t updatePeriod) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_setUpdatePeriod`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileConnection_setUpdatePeriod, + static_cast(instrumentProfileConnection.get()), + updatePeriod) == 0; +} + +dxfcpp::InstrumentProfileConnection::State +getState(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfileConnection_getState`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return graalIpfConnectionStateToState( + runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileConnection_getState, + static_cast(instrumentProfileConnection.get()))); +} + +std::int64_t getLastModified(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_getLastModified`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileConnection_getLastModified, + static_cast(instrumentProfileConnection.get())); +} + +bool start(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfileConnection_start`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne( + dxfg_InstrumentProfileConnection_start, + static_cast(instrumentProfileConnection.get())) == 0; +} + +bool close(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException("Unable to execute function `dxfg_InstrumentProfileConnection_close`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne( + dxfg_InstrumentProfileConnection_close, + static_cast(instrumentProfileConnection.get())) == 0; +} + +bool addStateChangeListener( + /* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection, + /* dxfg_ipf_connection_state_change_listener_t * */ const JavaObjectHandle + &listener) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_addStateChangeListener`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + if (!listener) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_addStateChangeListener`. The " + "`listener` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne( + dxfg_InstrumentProfileConnection_addStateChangeListener, + static_cast(instrumentProfileConnection.get()), + static_cast(listener.get())) == 0; +} + +bool waitUntilCompleted(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection, + std::int64_t timeoutInMs) { + if (!instrumentProfileConnection) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_InstrumentProfileConnection_waitUntilCompleted`. The " + "`instrumentProfileConnection` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_InstrumentProfileConnection_waitUntilCompleted, + static_cast(instrumentProfileConnection.get()), + timeoutInMs) == 1; +} + +} // namespace IsolatedInstrumentProfileConnection +} // namespace isolated::ipf::live + +DXFCPP_END_NAMESPACE \ No newline at end of file From d13a0576bdb5b508fd302b52113d02d3930751a5 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 16 Sep 2024 00:40:46 +0300 Subject: [PATCH 086/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedIpfPropertyChangeListener --- .../isolated/Isolated.hpp | 5 -- .../IsolatedInstrumentProfileConnection.hpp | 49 +++++++++++++------ src/internal/Isolate.cpp | 16 ------ src/ipf/live/InstrumentProfileConnection.cpp | 8 ++- .../IsolatedInstrumentProfileConnection.cpp | 18 +++++++ 5 files changed, 55 insertions(+), 41 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 86e88cc3a..20233b2d3 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -25,11 +25,6 @@ namespace isolated { namespace ipf { -struct IpfPropertyChangeListener { - static /* dxfg_ipf_connection_state_change_listener_t* */ void * - create(/* dxfg_ipf_connection_state_change_listener_func */ void *userFunc, void *userData) noexcept; -}; - struct InstrumentProfileIterator { static bool hasNext(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; static /* dxfg_instrument_profile_t* */ void *next(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp index b3c282e86..60d687206 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp @@ -5,8 +5,8 @@ #include "../../../internal/Conf.hpp" -#include "../../../ipf/live/InstrumentProfileConnection.hpp" #include "../../../ipf/live/InstrumentProfileCollector.hpp" +#include "../../../ipf/live/InstrumentProfileConnection.hpp" #include #include @@ -19,33 +19,52 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::ipf::live { namespace IsolatedInstrumentProfileConnection { -/* dxfg_ipf_connection_t* */ JavaObjectHandle -createConnection(const StringLikeWrapper &address, - /* dxfg_ipf_collector_t* */ const JavaObjectHandle - &instrumentProfileCollector); +/* dxfg_ipf_connection_t* */ JavaObjectHandle createConnection( + const StringLikeWrapper &address, + /* dxfg_ipf_collector_t* */ const JavaObjectHandle &instrumentProfileCollector); -std::string getAddress(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); +std::string getAddress(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection); -std::int64_t getUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); +std::int64_t getUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection); -bool setUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection, std::int64_t updatePeriod); +bool setUpdatePeriod(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection, + std::int64_t updatePeriod); dxfcpp::InstrumentProfileConnection::State -getState(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); +getState(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection); -std::int64_t getLastModified(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); +std::int64_t getLastModified(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection); -bool start(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); +bool start(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection); -bool close(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection); +bool close(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection); -bool addStateChangeListener(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection, - /* dxfg_ipf_connection_state_change_listener_t * */ const JavaObjectHandle& listener); +bool addStateChangeListener( + /* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection, + /* dxfg_ipf_connection_state_change_listener_t * */ const JavaObjectHandle + &listener); -bool waitUntilCompleted(/* dxfg_ipf_connection_t * */ const JavaObjectHandle& instrumentProfileConnection, +bool waitUntilCompleted(/* dxfg_ipf_connection_t * */ const JavaObjectHandle + &instrumentProfileConnection, std::int64_t timeoutInMs); } // namespace IsolatedInstrumentProfileConnection + +namespace IsolatedIpfPropertyChangeListener { + +/* dxfg_ipf_connection_state_change_listener_t* */ JavaObjectHandle +create(/* dxfg_ipf_connection_state_change_listener_func */ void *userFunc, void *userData); + +} + } // namespace isolated::ipf::live DXFCPP_END_NAMESPACE diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index f0081c4cf..033e796b7 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -154,22 +154,6 @@ using NativeStringList = typename isolated::internal::NativeStringListWrapper(runIsolatedOrElse( - [](auto threadHandle, auto &&userFunc, auto &&userData) { - return dxfg_IpfPropertyChangeListener_new(static_cast(threadHandle), userFunc, - userData); - }, - nullptr, dxfcpp::bit_cast(userFunc), userData)); -} - bool InstrumentProfileIterator::hasNext(/* dxfg_iterable_ip_t * */ void *iterable) noexcept { if (!iterable) { // TODO: Improve error handling diff --git a/src/ipf/live/InstrumentProfileConnection.cpp b/src/ipf/live/InstrumentProfileConnection.cpp index 1a005be32..fd40a9f39 100644 --- a/src/ipf/live/InstrumentProfileConnection.cpp +++ b/src/ipf/live/InstrumentProfileConnection.cpp @@ -70,11 +70,9 @@ InstrumentProfileConnection::createConnection(const StringLikeWrapper &address, ApiContext::getInstance()->getManager()->registerEntity(connection); connection->handle_ = isolated::ipf::live::IsolatedInstrumentProfileConnection::createConnection(address, collector->handle_); - - connection->stateChangeListenerHandle_ = - JavaObjectHandle(isolated::ipf::IpfPropertyChangeListener::create( - dxfcpp::bit_cast(&InstrumentProfileConnection::Impl::onStateChange), - dxfcpp::bit_cast(connection->id_.getValue()))); + connection->stateChangeListenerHandle_ = isolated::ipf::live::IsolatedIpfPropertyChangeListener::create( + dxfcpp::bit_cast(&InstrumentProfileConnection::Impl::onStateChange), + dxfcpp::bit_cast(connection->id_.getValue())); isolated::ipf::live::IsolatedInstrumentProfileConnection::addStateChangeListener( connection->handle_, connection->stateChangeListenerHandle_); diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp index db2a7646b..b9ef3cc60 100644 --- a/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp @@ -12,6 +12,7 @@ DXFCPP_BEGIN_NAMESPACE dxfcpp::InstrumentProfileConnection::State graalIpfConnectionStateToState(dxfg_ipf_connection_state_t state); namespace isolated::ipf::live { + namespace IsolatedInstrumentProfileConnection { /* dxfg_ipf_connection_t* */ JavaObjectHandle @@ -160,6 +161,23 @@ bool waitUntilCompleted(/* dxfg_ipf_connection_t * */ const JavaObjectHandle +create(/* dxfg_ipf_connection_state_change_listener_func */ void *userFunc, void *userData) { + if (!userFunc) { + throw InvalidArgumentException("Unable to execute function `dxfg_IpfPropertyChangeListener_new`. The " + "`userFunc` is nullptr"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_IpfPropertyChangeListener_new, dxfcpp::bit_cast(userFunc), + userData)}; +} + +} // namespace IsolatedIpfPropertyChangeListener + } // namespace isolated::ipf::live DXFCPP_END_NAMESPACE \ No newline at end of file From 6b714669a101e46db2f4b31057311f10fd2eff12 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 16 Sep 2024 00:54:21 +0300 Subject: [PATCH 087/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedInstrumentProfileIterator --- .../isolated/Isolated.hpp | 9 ------ .../IsolatedInstrumentProfileCollector.hpp | 9 ++++++ src/internal/Isolate.cpp | 32 ------------------- src/ipf/live/InstrumentProfileCollector.cpp | 4 +-- src/ipf/live/IterableInstrumentProfile.cpp | 4 +-- .../IsolatedInstrumentProfileCollector.cpp | 24 ++++++++++++++ 6 files changed, 37 insertions(+), 45 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 20233b2d3..1ee68a838 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -23,15 +23,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { -namespace ipf { - -struct InstrumentProfileIterator { - static bool hasNext(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; - static /* dxfg_instrument_profile_t* */ void *next(/* dxfg_iterable_ip_t * */ void *iterable) noexcept; -}; - -} // namespace ipf - namespace ondemand { struct OnDemandService { diff --git a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp index 286cd37f0..259bbd4f6 100644 --- a/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp @@ -42,6 +42,15 @@ namespace IsolatedInstrumentProfileUpdateListener { create(/* dxfg_ipf_update_listener_function */ void *userFunc, void *userData); } + +namespace IsolatedInstrumentProfileIterator { + +bool hasNext(/* dxfg_iterable_ip_t * */ void *iterable); + +/* dxfg_instrument_profile_t* */ void *next(/* dxfg_iterable_ip_t * */ void *iterable); + +} // namespace IsolatedInstrumentProfileIterator + } // namespace isolated::ipf::live DXFCPP_END_NAMESPACE diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 033e796b7..9e1b277c6 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -152,38 +152,6 @@ constexpr auto runGraalFunction(auto resultCheckerConverter, auto graalFunction, using NativeStringList = typename isolated::internal::NativeStringListWrapper; -namespace ipf { - -bool InstrumentProfileIterator::hasNext(/* dxfg_iterable_ip_t * */ void *iterable) noexcept { - if (!iterable) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&iterable) { - return dxfg_Iterable_InstrumentProfile_hasNext(static_cast(threadHandle), - iterable) == 1; - }, - false, static_cast(iterable)); -} - -/* dxfg_instrument_profile_t* */ void * -InstrumentProfileIterator::next(/* dxfg_iterable_ip_t * */ void *iterable) noexcept { - if (!iterable) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&iterable) { - return dxfg_Iterable_InstrumentProfile_next(static_cast(threadHandle), iterable); - }, - nullptr, static_cast(iterable))); -} - -} // namespace ipf - namespace ondemand { /* dxfg_on_demand_service_t* */ void *OnDemandService::getInstance(/* dxfg_endpoint_t * */ void *endpoint) noexcept { diff --git a/src/ipf/live/InstrumentProfileCollector.cpp b/src/ipf/live/InstrumentProfileCollector.cpp index 9686a24bb..823345209 100644 --- a/src/ipf/live/InstrumentProfileCollector.cpp +++ b/src/ipf/live/InstrumentProfileCollector.cpp @@ -27,7 +27,7 @@ struct NonOwningInstrumentProfileIterator { return false; } - return isolated::ipf::InstrumentProfileIterator::hasNext(iterable); + return isolated::ipf::live::IsolatedInstrumentProfileIterator::hasNext(iterable); } [[nodiscard]] std::shared_ptr next() const { @@ -35,7 +35,7 @@ struct NonOwningInstrumentProfileIterator { return {}; } - auto graalProfile = isolated::ipf::InstrumentProfileIterator::next(iterable); + auto graalProfile = isolated::ipf::live::IsolatedInstrumentProfileIterator::next(iterable); auto result = InstrumentProfile::create(JavaObjectHandle(graalProfile)); return result; diff --git a/src/ipf/live/IterableInstrumentProfile.cpp b/src/ipf/live/IterableInstrumentProfile.cpp index b24c2e91c..5f766910e 100644 --- a/src/ipf/live/IterableInstrumentProfile.cpp +++ b/src/ipf/live/IterableInstrumentProfile.cpp @@ -30,7 +30,7 @@ std::shared_ptr IterableInstrumentProfile::create(voi return false; } - return isolated::ipf::InstrumentProfileIterator::hasNext(handle_.get()); + return isolated::ipf::live::IsolatedInstrumentProfileIterator::hasNext(handle_.get()); } [[nodiscard]] std::shared_ptr IterableInstrumentProfile::next() const { @@ -38,7 +38,7 @@ std::shared_ptr IterableInstrumentProfile::create(voi return {}; } - auto graalProfile = isolated::ipf::InstrumentProfileIterator::next(handle_.get()); + auto graalProfile = isolated::ipf::live::IsolatedInstrumentProfileIterator::next(handle_.get()); auto result = InstrumentProfile::create(JavaObjectHandle(graalProfile)); return result; diff --git a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp index 887a73cf6..e5ba355e5 100644 --- a/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp +++ b/src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp @@ -117,6 +117,30 @@ create(/* dxfg_ipf_update_listener_function */ void *userFunc, void *userData) { } // namespace IsolatedInstrumentProfileUpdateListener +namespace IsolatedInstrumentProfileIterator { + +bool hasNext(/* dxfg_iterable_ip_t * */ void *iterable) { + if (!iterable) { + throw InvalidArgumentException("Unable to execute function `dxfg_Iterable_InstrumentProfile_hasNext`. The " + "`iterable` is nullptr"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Iterable_InstrumentProfile_hasNext, + static_cast(iterable)) == 1; +} + +/* dxfg_instrument_profile_t* */ void *next(/* dxfg_iterable_ip_t * */ void *iterable) { + if (!iterable) { + throw InvalidArgumentException("Unable to execute function `dxfg_Iterable_InstrumentProfile_next`. The " + "`iterable` is nullptr"); + } + + return runGraalFunctionAndThrowIfNullptr(dxfg_Iterable_InstrumentProfile_next, + static_cast(iterable)); +} + +} // namespace IsolatedInstrumentProfileIterator + } // namespace isolated::ipf::live DXFCPP_END_NAMESPACE \ No newline at end of file From 7cc2e7173314b4722a2e265128fb9808daf4e47a Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 16 Sep 2024 02:10:00 +0300 Subject: [PATCH 088/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedOnDemandService --- CMakeLists.txt | 7 +- include/dxfeed_graal_cpp_api/api.hpp | 1 + .../isolated/Isolated.hpp | 19 -- .../ondemand/IsolatedOnDemandService.hpp | 49 ++++++ .../ondemand/OnDemandService.hpp | 24 +-- src/internal/Isolate.cpp | 163 ------------------ .../ondemand/IsolatedOnDemandService.cpp | 143 +++++++++++++++ src/ondemand/OnDemandService.cpp | 97 +++-------- 8 files changed, 233 insertions(+), 270 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/ondemand/IsolatedOnDemandService.hpp create mode 100644 src/isolated/ondemand/IsolatedOnDemandService.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b19e7e731..35098cb04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,16 +212,17 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp src/isolated/auth/IsolatedAuthToken.cpp src/isolated/event/IsolatedEventType.cpp - src/isolated/promise/IsolatedPromise.cpp src/isolated/internal/IsolatedString.cpp src/isolated/internal/IsolatedObject.cpp src/isolated/internal/IsolatedTimeFormat.cpp src/isolated/internal/IsolatedTools.cpp - src/isolated/util/IsolatedTimePeriod.cpp + src/isolated/promise/IsolatedPromise.cpp src/isolated/ipf/IsolatedInstrumentProfile.cpp + src/isolated/ipf/IsolatedInstrumentProfileReader.cpp src/isolated/ipf/live/IsolatedInstrumentProfileCollector.cpp src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp - src/isolated/ipf/IsolatedInstrumentProfileReader.cpp + src/isolated/ondemand/IsolatedOnDemandService.cpp + src/isolated/util/IsolatedTimePeriod.cpp ) set(dxFeedGraalCxxApi_Api_Sources diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 3bb3fa08e..f53bc584c 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -74,6 +74,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/ipf/live/IsolatedInstrumentProfileCollector.hpp" #include "isolated/ipf/live/IsolatedInstrumentProfileConnection.hpp" #include "isolated/ipf/IsolatedInstrumentProfileReader.hpp" +#include "isolated/ondemand/IsolatedOnDemandService.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" #include "ondemand/OnDemandService.hpp" diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 1ee68a838..63b2fd139 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -23,25 +23,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { -namespace ondemand { - -struct OnDemandService { - static /* dxfg_on_demand_service_t* */ void *getInstance(/* dxfg_endpoint_t * */ void *endpoint) noexcept; - static bool isReplaySupported(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static bool isReplay(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static bool isClear(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static std::int64_t getTime(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static double getSpeed(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static bool replay(/* dxfg_on_demand_service_t * */ void *service, std::int64_t time) noexcept; - static bool replay(/* dxfg_on_demand_service_t * */ void *service, std::int64_t time, double speed) noexcept; - static bool pause(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static bool stopAndResume(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static bool stopAndClear(/* dxfg_on_demand_service_t * */ void *service) noexcept; - static bool setSpeed(/* dxfg_on_demand_service_t * */ void *service, double speed) noexcept; -}; - -} // namespace ondemand - namespace schedule { struct DayFilter { static /* dxfg_day_filter_t* */ void *getInstance(std::uint32_t code) noexcept; diff --git a/include/dxfeed_graal_cpp_api/isolated/ondemand/IsolatedOnDemandService.hpp b/include/dxfeed_graal_cpp_api/isolated/ondemand/IsolatedOnDemandService.hpp new file mode 100644 index 000000000..a177b45bd --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/ondemand/IsolatedOnDemandService.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include "../../ondemand/OnDemandService.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ondemand { + +namespace IsolatedOnDemandService { + +/* dxfg_on_demand_service_t* */ JavaObjectHandle +getInstance(/* dxfg_endpoint_t * */ const JavaObjectHandle& endpoint); + +bool isReplaySupported(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +bool isReplay(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +bool isClear(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +std::int64_t getTime(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +double getSpeed(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +bool replay(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service, std::int64_t time); + +bool replay(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service, std::int64_t time, double speed); + +bool pause(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +bool stopAndResume(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +bool stopAndClear(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service); + +bool setSpeed(/* dxfg_on_demand_service_t * */ const JavaObjectHandle& service, double speed); + +} // namespace IsolatedOnDemandService + +} // namespace isolated::ondemand + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/ondemand/OnDemandService.hpp b/include/dxfeed_graal_cpp_api/ondemand/OnDemandService.hpp index a466d0a90..ab824620d 100644 --- a/include/dxfeed_graal_cpp_api/ondemand/OnDemandService.hpp +++ b/include/dxfeed_graal_cpp_api/ondemand/OnDemandService.hpp @@ -101,7 +101,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @return on-demand endpoint for the default DXEndpoint instance. */ - static std::shared_ptr getInstance() noexcept; + static std::shared_ptr getInstance(); /** * Returns on-demand service for the specified DXEndpoint. @@ -131,7 +131,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @return `true` when on-demand historical data replay mode is supported. */ - bool isReplaySupported() const noexcept; + bool isReplaySupported() const; /** * Returns `true` when this on-demand historical data replay service is in replay mode. @@ -140,7 +140,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @return `true` when this on-demand historical data replay service is in replay mode. */ - bool isReplay() const noexcept; + bool isReplay() const; /** * Returns `true` when this on-demand historical data replay service is in clear mode. @@ -149,7 +149,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @return `true` when this on-demand historical data replay service is in clear mode. */ - bool isClear() const noexcept; + bool isClear() const; /** * Returns current or last on-demand historical data replay time. @@ -159,7 +159,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @return current or last on-demand historical data replay time in millis. */ - std::int64_t getTime() const noexcept; + std::int64_t getTime() const; /** * Returns on-demand historical data replay speed. @@ -170,7 +170,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @return on-demand historical data replay speed. */ - double getSpeed() const noexcept; + double getSpeed() const; /** * Turns on-demand historical data replay mode from a specified time with real-time speed. @@ -184,7 +184,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @param time time (timestamp in millis) to start replay from. */ - void replay(std::int64_t time) const noexcept; + void replay(std::int64_t time) const; /** * Turns on-demand historical data replay mode from a specified time and with a specified speed. @@ -205,7 +205,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * @param speed speed to start replay with. Use 1 for real-time speed, >1 for faster than real-time speed, * <1 for slower than real-time speed, and 0 for pause. */ - void replay(std::int64_t time, double speed) const noexcept; + void replay(std::int64_t time, double speed) const; /** * Pauses on-demand historical data replay and keeps data snapshot. @@ -222,7 +222,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { *

  • OnDemandService::getSpeed() returns `0`. * */ - void pause() const noexcept; + void pause() const; /** * Stops on-demand historical data replay and resumes ordinary data feed. @@ -242,7 +242,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * @ref DXEndpoint::Role::ON_DEMAND_FEED "ON_DEMAND_FEED" do not have an ordinary feed (they are essentially on-demand only) * and thus `stopAndResume` method works like @ref OnDemandService::stopAndClear() "stopAndClear" for them. */ - void stopAndResume() const noexcept; + void stopAndResume() const; /** * Stops incoming data and clears it without resuming data updates. @@ -259,7 +259,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { *

    Ordinary data feed can be resumed with OnDemandService::stopAndResume() method and on-demand historical data * replay can be continued with @ref OnDemandService::replay() "replay(...)" method. */ - void stopAndClear() const noexcept; + void stopAndClear() const; /** * Changes on-demand historical data replay speed while continuing replay at current @ref OnDemandService::getTime() "time". @@ -268,7 +268,7 @@ struct DXFCPP_EXPORT OnDemandService : SharedEntity { * * @param speed on-demand historical data replay speed. */ - void setSpeed(double speed) const noexcept; + void setSpeed(double speed) const; }; DXFCPP_END_NAMESPACE diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 9e1b277c6..2657d205a 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -152,169 +152,6 @@ constexpr auto runGraalFunction(auto resultCheckerConverter, auto graalFunction, using NativeStringList = typename isolated::internal::NativeStringListWrapper; -namespace ondemand { - -/* dxfg_on_demand_service_t* */ void *OnDemandService::getInstance(/* dxfg_endpoint_t * */ void *endpoint) noexcept { - if (!endpoint) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&endpoint) { - return dxfg_OnDemandService_getInstance2(static_cast(threadHandle), endpoint); - }, - nullptr, static_cast(endpoint))); -} - -bool OnDemandService::isReplaySupported(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_isReplaySupported(static_cast(threadHandle), - service) == 1; - }, - false, static_cast(service)); -} - -bool OnDemandService::isReplay(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_isReplay(static_cast(threadHandle), service) == 1; - }, - false, static_cast(service)); -} - -bool OnDemandService::isClear(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_isClear(static_cast(threadHandle), service) == 1; - }, - false, static_cast(service)); -} - -std::int64_t OnDemandService::getTime(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_getTime(static_cast(threadHandle), service); - }, - 0, static_cast(service)); -} - -double OnDemandService::getSpeed(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return 0.0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_getSpeed(static_cast(threadHandle), service); - }, - 0.0, static_cast(service)); -} - -bool OnDemandService::replay(/* dxfg_on_demand_service_t * */ void *service, std::int64_t time) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service, auto &&time) { - return dxfg_OnDemandService_replay(static_cast(threadHandle), service, time) == 0; - }, - false, static_cast(service), time); -} - -bool OnDemandService::replay(/* dxfg_on_demand_service_t * */ void *service, std::int64_t time, double speed) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service, auto &&time, auto &&speed) { - return dxfg_OnDemandService_replay2(static_cast(threadHandle), service, time, - speed) == 0; - }, - false, static_cast(service), time, speed); -} - -bool OnDemandService::pause(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_pause(static_cast(threadHandle), service) == 0; - }, - false, static_cast(service)); -} - -bool OnDemandService::stopAndResume(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_stopAndResume(static_cast(threadHandle), service) == 0; - }, - false, static_cast(service)); -} - -bool OnDemandService::stopAndClear(/* dxfg_on_demand_service_t * */ void *service) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service) { - return dxfg_OnDemandService_stopAndClear(static_cast(threadHandle), service) == 0; - }, - false, static_cast(service)); -} - -bool OnDemandService::setSpeed(/* dxfg_on_demand_service_t * */ void *service, double speed) noexcept { - if (!service) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&service, auto &&speed) { - return dxfg_OnDemandService_setSpeed(static_cast(threadHandle), service, speed) == - 0; - }, - false, static_cast(service), speed); -} - -} // namespace ondemand - namespace schedule { /* dxfg_schedule_t* */ void *Day::getSchedule(/* dxfg_day_t* */ void *day) noexcept { diff --git a/src/isolated/ondemand/IsolatedOnDemandService.cpp b/src/isolated/ondemand/IsolatedOnDemandService.cpp new file mode 100644 index 000000000..8db0d3534 --- /dev/null +++ b/src/isolated/ondemand/IsolatedOnDemandService.cpp @@ -0,0 +1,143 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::ondemand { + +namespace IsolatedOnDemandService { + +/* dxfg_on_demand_service_t* */ JavaObjectHandle +getInstance(/* dxfg_endpoint_t * */ const JavaObjectHandle &endpoint) { + if (!endpoint) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_getInstance2`. The `endpoint` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_OnDemandService_getInstance2, static_cast(endpoint.get()))}; +} + +bool isReplaySupported(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_isReplaySupported`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_isReplaySupported, + static_cast(service.get())) == 1; +} + +bool isReplay(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_isReplay`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_isReplay, + static_cast(service.get())) == 1; +} + +bool isClear(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_isClear`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_isClear, + static_cast(service.get())) == 1; +} + +std::int64_t getTime(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_getTime`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_getTime, + static_cast(service.get())); +} + +double getSpeed(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_getSpeed`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusInf(dxfg_OnDemandService_getSpeed, + static_cast(service.get())); +} + +bool replay(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service, + std::int64_t time) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_replay`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_replay, + static_cast(service.get()), time) == 0; +} + +bool replay(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service, + std::int64_t time, double speed) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_replay2`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_replay2, + static_cast(service.get()), time, speed) == 0; +} + +bool pause(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_pause`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_pause, + static_cast(service.get())) == 0; +} + +bool stopAndResume(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_stopAndResume`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_stopAndResume, + static_cast(service.get())) == 0; +} + +bool stopAndClear(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_stopAndClear`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_stopAndClear, + static_cast(service.get())) == 0; +} + +bool setSpeed(/* dxfg_on_demand_service_t * */ const JavaObjectHandle &service, double speed) { + if (!service) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_OnDemandService_setSpeed`. The `service` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_OnDemandService_setSpeed, + static_cast(service.get()), speed) == 0; +} + +} // namespace IsolatedOnDemandService + +} // namespace isolated::ondemand + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/ondemand/OnDemandService.cpp b/src/ondemand/OnDemandService.cpp index e25c2fb8c..b8b9938a1 100644 --- a/src/ondemand/OnDemandService.cpp +++ b/src/ondemand/OnDemandService.cpp @@ -28,7 +28,7 @@ OnDemandService::~OnDemandService() noexcept { } } -std::shared_ptr OnDemandService::getInstance() noexcept { +std::shared_ptr OnDemandService::getInstance() { return getInstance(DXEndpoint::getInstance(DXEndpoint::Role::ON_DEMAND_FEED)); } @@ -39,16 +39,11 @@ std::shared_ptr OnDemandService::getInstance(std::shared_ptr onDemandService{new OnDemandService{}}; - if (!endpoint->handle_) { - throw InvalidArgumentException("The endpoint's handle is invalid"); - } - auto id = ApiContext::getInstance()->getManager()->registerEntity(onDemandService); ignore_unused(id); onDemandService->endpoint_ = endpoint; - onDemandService->handle_ = - JavaObjectHandle(isolated::ondemand::OnDemandService::getInstance(endpoint->handle_.get())); + onDemandService->handle_ = isolated::ondemand::IsolatedOnDemandService::getInstance(endpoint->handle_); return onDemandService; } @@ -57,92 +52,48 @@ std::shared_ptr OnDemandService::getEndpoint() const noexcept { return endpoint_; } -bool OnDemandService::isReplaySupported() const noexcept { - if (!handle_) { - return false; - } - - return isolated::ondemand::OnDemandService::isReplaySupported(handle_.get()); +bool OnDemandService::isReplaySupported() const { + return isolated::ondemand::IsolatedOnDemandService::isReplaySupported(handle_); } -bool OnDemandService::isReplay() const noexcept { - if (!handle_) { - return false; - } - - return isolated::ondemand::OnDemandService::isReplay(handle_.get()); +bool OnDemandService::isReplay() const { + return isolated::ondemand::IsolatedOnDemandService::isReplay(handle_); } -bool OnDemandService::isClear() const noexcept { - if (!handle_) { - return false; - } - - return isolated::ondemand::OnDemandService::isClear(handle_.get()); +bool OnDemandService::isClear() const { + return isolated::ondemand::IsolatedOnDemandService::isClear(handle_); } -std::int64_t OnDemandService::getTime() const noexcept { - if (!handle_) { - return {}; - } - - return isolated::ondemand::OnDemandService::getTime(handle_.get()); +std::int64_t OnDemandService::getTime() const { + return isolated::ondemand::IsolatedOnDemandService::getTime(handle_); } -double OnDemandService::getSpeed() const noexcept { - if (!handle_) { - return {}; - } - - return isolated::ondemand::OnDemandService::getSpeed(handle_.get()); +double OnDemandService::getSpeed() const { + return isolated::ondemand::IsolatedOnDemandService::getSpeed(handle_); } -void OnDemandService::replay(std::int64_t time) const noexcept { - if (!handle_) { - return; - } - - isolated::ondemand::OnDemandService::replay(handle_.get(), time); +void OnDemandService::replay(std::int64_t time) const { + isolated::ondemand::IsolatedOnDemandService::replay(handle_, time); } -void OnDemandService::replay(std::int64_t time, double speed) const noexcept { - if (!handle_) { - return; - } - - isolated::ondemand::OnDemandService::replay(handle_.get(), time, speed); +void OnDemandService::replay(std::int64_t time, double speed) const { + isolated::ondemand::IsolatedOnDemandService::replay(handle_, time, speed); } -void OnDemandService::pause() const noexcept { - if (!handle_) { - return; - } - - isolated::ondemand::OnDemandService::pause(handle_.get()); +void OnDemandService::pause() const { + isolated::ondemand::IsolatedOnDemandService::pause(handle_); } -void OnDemandService::stopAndResume() const noexcept { - if (!handle_) { - return; - } - - isolated::ondemand::OnDemandService::stopAndResume(handle_.get()); +void OnDemandService::stopAndResume() const { + isolated::ondemand::IsolatedOnDemandService::stopAndResume(handle_); } -void OnDemandService::stopAndClear() const noexcept { - if (!handle_) { - return; - } - - isolated::ondemand::OnDemandService::stopAndClear(handle_.get()); +void OnDemandService::stopAndClear() const { + isolated::ondemand::IsolatedOnDemandService::stopAndClear(handle_); } -void OnDemandService::setSpeed(double speed) const noexcept { - if (!handle_) { - return; - } - - isolated::ondemand::OnDemandService::setSpeed(handle_.get(), speed); +void OnDemandService::setSpeed(double speed) const { + isolated::ondemand::IsolatedOnDemandService::setSpeed(handle_, speed); } DXFCPP_END_NAMESPACE \ No newline at end of file From 706092a1f57aa7671e07e9da6f37b73805e20286 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 16 Sep 2024 13:09:02 +0300 Subject: [PATCH 089/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedDayFilter --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../isolated/Isolated.hpp | 3 -- .../isolated/schedule/IsolatedDay.hpp | 32 +++++++++++++++++++ src/internal/Isolate.cpp | 8 ----- src/isolated/schedule/IsolatedDay.cpp | 26 +++++++++++++++ src/schedule/DayFilter.cpp | 2 +- 7 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp create mode 100644 src/isolated/schedule/IsolatedDay.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 35098cb04..eba579132 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,6 +223,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/ipf/live/IsolatedInstrumentProfileConnection.cpp src/isolated/ondemand/IsolatedOnDemandService.cpp src/isolated/util/IsolatedTimePeriod.cpp + src/isolated/schedule/IsolatedDay.cpp ) set(dxFeedGraalCxxApi_Api_Sources diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index f53bc584c..5e0e48cd0 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -76,6 +76,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/ipf/IsolatedInstrumentProfileReader.hpp" #include "isolated/ondemand/IsolatedOnDemandService.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" +#include "isolated/schedule/IsolatedDay.hpp" #include "ondemand/OnDemandService.hpp" diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 63b2fd139..7f20b023f 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -24,9 +24,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated { namespace schedule { -struct DayFilter { - static /* dxfg_day_filter_t* */ void *getInstance(std::uint32_t code) noexcept; -}; struct Day { static /* dxfg_schedule_t* */ void *getSchedule(/* dxfg_day_t* */ void *day) noexcept; diff --git a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp new file mode 100644 index 000000000..3a5aece50 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include "../../schedule/DayFilter.hpp" +#include "../../schedule/Day.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::schedule { + +namespace IsolatedDayFilter { + +/* dxfg_day_filter_t* */ JavaObjectHandle getInstance(std::uint32_t code); + +} + +namespace IsolatedDay { + + +} + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 2657d205a..2c91bde85 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -726,14 +726,6 @@ std::string Session::toString(/* dxfg_session_t* */ void *session) noexcept { return result; } -/* dxfg_day_filter_t* */ void *DayFilter::getInstance(std::uint32_t code) noexcept { - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&filter) { - return dxfg_DayFilter_getInstance(static_cast(threadHandle), filter); - }, - nullptr, static_cast(code))); -} - /* dxfg_schedule_t* */ void *Schedule::getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept { if (!instrumentProfile) { // TODO: Improve error handling diff --git a/src/isolated/schedule/IsolatedDay.cpp b/src/isolated/schedule/IsolatedDay.cpp new file mode 100644 index 000000000..582ba26cf --- /dev/null +++ b/src/isolated/schedule/IsolatedDay.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::schedule { + +namespace IsolatedDayFilter { + +/* dxfg_day_filter_t* */ JavaObjectHandle getInstance(std::uint32_t code) { + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_DayFilter_getInstance, static_cast(code))}; +} + +} // namespace IsolatedDayFilter + +namespace IsolatedDay {} + +} // namespace isolated::schedule + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/schedule/DayFilter.cpp b/src/schedule/DayFilter.cpp index 5041b6600..b4fc2f3bc 100644 --- a/src/schedule/DayFilter.cpp +++ b/src/schedule/DayFilter.cpp @@ -14,7 +14,7 @@ DayFilter::DayFilter(DayFilterEnum code, std::string name, std::uint32_t dayOfWe : code_{code}, name_{std::move(name)}, dayOfWeekMask_{dayOfWeekMask}, holiday_{holiday}, shortDay_{shortDay}, trading_{trading} { - handle_ = JavaObjectHandle(isolated::schedule::DayFilter::getInstance(static_cast(code))); + handle_ = isolated::schedule::IsolatedDayFilter::getInstance(static_cast(code)); } /// Accepts any day - useful for pure calendar navigation. From 38890e3d635b5f23ec222d3a6db68c095a36dea5 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 16 Sep 2024 19:18:40 +0300 Subject: [PATCH 090/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedSessionList IsolatedDay --- .../event/candle/CandleSession.hpp | 2 +- .../isolated/Isolated.hpp | 38 -- .../isolated/schedule/IsolatedDay.hpp | 81 +++- include/dxfeed_graal_cpp_api/schedule/Day.hpp | 59 +-- .../schedule/Schedule.hpp | 4 +- .../dxfeed_graal_cpp_api/schedule/Session.hpp | 4 +- src/internal/Isolate.cpp | 368 ------------------ src/isolated/schedule/IsolatedDay.cpp | 347 ++++++++++++++++- src/schedule/Day.cpp | 227 +++-------- src/schedule/Schedule.cpp | 32 +- src/schedule/Session.cpp | 22 +- 11 files changed, 549 insertions(+), 635 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp index 4d6211d17..a8c3612b2 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleSession.hpp @@ -78,7 +78,7 @@ struct DXFCPP_EXPORT CandleSession final : CandleSymbolAttribute { * Returns session filter that corresponds to this session attribute. * @return session filter that corresponds to this session attribute. */ - const SessionFilter &getSessionFilter() const noexcept { + const SessionFilter &getSessionFilter() const& noexcept { return *sessionFilter_; } diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 7f20b023f..05a34a10e 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -25,44 +25,6 @@ namespace isolated { namespace schedule { -struct Day { - static /* dxfg_schedule_t* */ void *getSchedule(/* dxfg_day_t* */ void *day) noexcept; - static std::int32_t getDayId(/* dxfg_day_t* */ void *day) noexcept; - static std::int32_t getYearMonthDay(/* dxfg_day_t* */ void *day) noexcept; - static std::int32_t getYear(/* dxfg_day_t* */ void *day) noexcept; - static std::int32_t getMonthOfYear(/* dxfg_day_t* */ void *day) noexcept; - static std::int32_t getDayOfMonth(/* dxfg_day_t* */ void *day) noexcept; - static std::int32_t getDayOfWeek(/* dxfg_day_t* */ void *day) noexcept; - static bool isHoliday(/* dxfg_day_t* */ void *day) noexcept; - static bool isShortDay(/* dxfg_day_t* */ void *day) noexcept; - static bool isTrading(/* dxfg_day_t* */ void *day) noexcept; - static std::int64_t getStartTime(/* dxfg_day_t* */ void *day) noexcept; - static std::int64_t getEndTime(/* dxfg_day_t* */ void *day) noexcept; - static bool containsTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept; - static std::int64_t getResetTime(/* dxfg_day_t* */ void *day) noexcept; - static /* dxfg_session_list* */ void* getSessions(/* dxfg_day_t* */ void *day); - static /* dxfg_session_t* */ void *getSessionByTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept; - static /* dxfg_session_t* */ void *getFirstSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *getLastSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *findFirstSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *findLastSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_day_t* */ void *getPrevDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept; - static /* dxfg_day_t* */ void *getNextDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept; - static /* dxfg_day_t* */ void *findPrevDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept; - static /* dxfg_day_t* */ void *findNextDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept; - static std::size_t getHashCode(/* dxfg_day_t* */ void *day) noexcept; - static bool equals(/* dxfg_day_t* */ void *day, /* dxfg_day_t* */ void *otherDay) noexcept; - static std::string toString(/* dxfg_day_t* */ void *day) noexcept; -}; - struct SessionFilter { static /* dxfg_session_filter_t* */ void *getInstance(std::uint32_t code) noexcept; }; diff --git a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp index 3a5aece50..790e1dab7 100644 --- a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp @@ -5,8 +5,8 @@ #include "../../internal/Conf.hpp" -#include "../../schedule/DayFilter.hpp" #include "../../schedule/Day.hpp" +#include "../../schedule/DayFilter.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) @@ -20,13 +20,88 @@ namespace IsolatedDayFilter { } -namespace IsolatedDay { +namespace IsolatedSessionList { +bool release(/* dxfg_session_list* */ void *sessionList); -} +std::unique_ptr toUnique(/* dxfg_session_list* */ void *sessionList); } +namespace IsolatedDay { + +/* dxfg_schedule_t* */ JavaObjectHandle getSchedule(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int32_t getDayId(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int32_t getYearMonthDay(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int32_t getYear(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int32_t getMonthOfYear(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int32_t getDayOfMonth(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int32_t getDayOfWeek(/* dxfg_day_t* */ const JavaObjectHandle &day); + +bool isHoliday(/* dxfg_day_t* */ const JavaObjectHandle &day); + +bool isShortDay(/* dxfg_day_t* */ const JavaObjectHandle &day); + +bool isTrading(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int64_t getStartTime(/* dxfg_day_t* */ const JavaObjectHandle &day); + +std::int64_t getEndTime(/* dxfg_day_t* */ const JavaObjectHandle &day); + +bool containsTime(/* dxfg_day_t* */ const JavaObjectHandle &day, std::int64_t time); + +std::int64_t getResetTime(/* dxfg_day_t* */ const JavaObjectHandle &day); + +/* dxfg_session_list* */ void *getSessions(/* dxfg_day_t* */ const JavaObjectHandle &day); + +/* dxfg_session_t* */ JavaObjectHandle getSessionByTime(/* dxfg_day_t* */ const JavaObjectHandle &day, + std::int64_t time); + +/* dxfg_session_t* */ JavaObjectHandle +getFirstSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +getLastSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +findFirstSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +findLastSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_day_t* */ JavaObjectHandle getPrevDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_day_t* */ JavaObjectHandle getNextDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_day_t* */ JavaObjectHandle findPrevDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_day_t* */ JavaObjectHandle findNextDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter); + +std::size_t getHashCode(/* dxfg_day_t* */ const JavaObjectHandle &day); + +bool equals(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_t* */ const JavaObjectHandle &otherDay); + +std::string toString(/* dxfg_day_t* */ const JavaObjectHandle &day); + +} // namespace IsolatedDay + +} // namespace isolated::schedule + DXFCPP_END_NAMESPACE DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/schedule/Day.hpp b/include/dxfeed_graal_cpp_api/schedule/Day.hpp index 01c57a21b..7fb24b84c 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Day.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Day.hpp @@ -12,6 +12,7 @@ DXFCPP_BEGIN_NAMESPACE struct Schedule; struct Session; struct SessionFilter; +struct DayFilter; /** * Day represents a continuous period of time approximately 24 hours long. The day is aligned @@ -47,7 +48,7 @@ struct DXFCPP_EXPORT Day { private: JavaObjectHandle handle_; - explicit Day(void *handle = nullptr) noexcept; + explicit Day(JavaObjectHandle&& handle) noexcept; /** * Checks the handle, attempts to allocate memory for the pointer and return Day::Ptr @@ -55,19 +56,19 @@ struct DXFCPP_EXPORT Day { * @param handle The graal Day's handle * @return The smart pointer for the Day object. */ - static Day::Ptr create(void *handle); + static Day::Ptr create(JavaObjectHandle&& handle); public: /** * @return The schedule to which this day belongs. */ - std::shared_ptr getSchedule() const noexcept; + std::shared_ptr getSchedule() const; /** * @return The number of this day since January 1, 1970 (that day has identifier of 0 and previous days have * negative identifiers). */ - std::int32_t getDayId() const noexcept; + std::int32_t getDayId() const; /** * Returns year, month and day numbers packed in the following way: @@ -76,66 +77,66 @@ struct DXFCPP_EXPORT Day { * * @return Packed year, month and day numbers */ - std::int32_t getYearMonthDay() const noexcept; + std::int32_t getYearMonthDay() const; /** * @return The calendar year - i.e. it returns 1977 for the year 1977. */ - std::int32_t getYear() const noexcept; + std::int32_t getYear() const; /** * @return The calendar month number in the year starting with 1=January and ending with 12=December. */ - std::int32_t getMonthOfYear() const noexcept; + std::int32_t getMonthOfYear() const; /** * @return The ordinal day number in the month starting with 1 for the first day of month. */ - std::int32_t getDayOfMonth() const noexcept; + std::int32_t getDayOfMonth() const; /** * @return The ordinal day number in the week starting with 1=Monday and ending with 7=Sunday. */ - std::int32_t getDayOfWeek() const noexcept; + std::int32_t getDayOfWeek() const; /** * @return true if this day is an exchange holiday. * Usually there are no trading takes place on an exchange holiday. */ - bool isHoliday() const noexcept; + bool isHoliday() const; /** * @return true if this day is a short day. * Usually trading stops earlier on a short day. */ - bool isShortDay() const noexcept; + bool isShortDay() const; /** * @return true if trading activity is allowed within this day. * Positive result assumes that day has at least one trading session. */ - bool isTrading() const noexcept; + bool isTrading() const; /** * @return The start time of this day (inclusive). */ - std::int64_t getStartTime() const noexcept; + std::int64_t getStartTime() const; /** * @return The end time of this day (exclusive). */ - std::int64_t getEndTime() const noexcept; + std::int64_t getEndTime() const; /** * @return true if specified time belongs to this day. */ - bool containsTime(std::int64_t time) const noexcept; + bool containsTime(std::int64_t time) const; /** * @return The reset time for this day. * Reset of daily data is performed on trading days only, the result has no meaning for non-trading days. */ - std::int64_t getResetTime() const noexcept; + std::int64_t getResetTime() const; /** * @return collection of sessions that constitute this day. @@ -152,7 +153,7 @@ struct DXFCPP_EXPORT Day { * @return The session that contains specified time or Session::Ptr{nullptr} (std::shared_ptr{nullptr}) * if no such session was found within this day */ - std::shared_ptr getSessionByTime(std::int64_t time) const noexcept; + std::shared_ptr getSessionByTime(std::int64_t time) const; /** * Returns first session belonging to this day accepted by specified filter. @@ -168,7 +169,7 @@ struct DXFCPP_EXPORT Day { * @return The first session that is accepted by the filter or Session::Ptr{nullptr} * (std::shared_ptr{nullptr}) if no such session was found within this day */ - std::shared_ptr getFirstSession(const SessionFilter &filter) const noexcept; + std::shared_ptr getFirstSession(const SessionFilter &filter) const; /** * Returns last session belonging to this day accepted by specified filter. @@ -184,7 +185,7 @@ struct DXFCPP_EXPORT Day { * @return The last session that is accepted by the filter or Session::Ptr{nullptr} * (std::shared_ptr{nullptr}) if no such session was found within this day */ - std::shared_ptr getLastSession(const SessionFilter &filter) const noexcept; + std::shared_ptr getLastSession(const SessionFilter &filter) const; /** * Returns first session belonging to this day accepted by specified filter. @@ -199,7 +200,7 @@ struct DXFCPP_EXPORT Day { * @param filter The filter to test sessions * @return The first session that is accepted by the filter */ - std::shared_ptr findFirstSession(const SessionFilter &filter) const noexcept; + std::shared_ptr findFirstSession(const SessionFilter &filter) const; /** * Returns last session belonging to this day accepted by specified filter. @@ -214,7 +215,7 @@ struct DXFCPP_EXPORT Day { * @param filter The filter to test sessions * @return The last session that is accepted by the filter */ - std::shared_ptr findLastSession(const SessionFilter &filter) const noexcept; + std::shared_ptr findLastSession(const SessionFilter &filter) const; /** * Returns previous day accepted by specified filter. @@ -225,7 +226,7 @@ struct DXFCPP_EXPORT Day { * @return The nearest previous day that is accepted by the filter or Day::Ptr{nullptr} * (std::shared_ptr{nullptr}) if no such day was found within one year */ - Day::Ptr getPrevDay(const DayFilter &filter) const noexcept; + Day::Ptr getPrevDay(const DayFilter &filter) const; /** * Returns following day accepted by specified filter. @@ -236,7 +237,7 @@ struct DXFCPP_EXPORT Day { * @return The nearest following day that is accepted by the filter or Day::Ptr{nullptr} * (std::shared_ptr{nullptr}) if no such day was found within one year */ - Day::Ptr getNextDay(const DayFilter &filter) const noexcept; + Day::Ptr getNextDay(const DayFilter &filter) const; /** * Returns previous day accepted by specified filter. @@ -246,7 +247,7 @@ struct DXFCPP_EXPORT Day { * @param filter The filter to test days * @return The nearest previous day that is accepted by the filter */ - Day::Ptr findPrevDay(const DayFilter &filter) const noexcept; + Day::Ptr findPrevDay(const DayFilter &filter) const; /** * Returns following day accepted by specified filter. @@ -256,7 +257,7 @@ struct DXFCPP_EXPORT Day { * @param filter The filter to test days * @return The nearest following day that is accepted by the filter */ - Day::Ptr findNextDay(const DayFilter &filter) const noexcept; + Day::Ptr findNextDay(const DayFilter &filter) const; /** * Returns `true` if this object is equal to `other` object @@ -264,7 +265,7 @@ struct DXFCPP_EXPORT Day { * @param other Another object * @return `true` if this object is equal to `other` object */ - bool operator==(const Day &other) const noexcept; + bool operator==(const Day &other) const; /** * Returns `true` if this object is equal to `other` object @@ -272,14 +273,14 @@ struct DXFCPP_EXPORT Day { * @param other Another object * @return `true` if this object is equal to `other` object */ - bool operator==(const Day::Ptr &other) const noexcept { + bool operator==(const Day::Ptr &other) const { return *this == *other; } /** * @return A hash code value for this object. */ - std::size_t getHashCode() const noexcept; + std::size_t getHashCode() const; /** * Returns a string representation of the current object. @@ -292,7 +293,7 @@ struct DXFCPP_EXPORT Day { DXFCPP_END_NAMESPACE template <> struct DXFCPP_EXPORT std::hash { - std::size_t operator()(const dxfcpp::Day &day) const noexcept { + std::size_t operator()(const dxfcpp::Day &day) const { return day.getHashCode(); } }; diff --git a/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp b/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp index 01b56f94b..4f9a188a7 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp @@ -28,7 +28,7 @@ struct DXFCPP_EXPORT Schedule { private: JavaObjectHandle handle_; - explicit Schedule(void *handle = nullptr) noexcept; + explicit Schedule(JavaObjectHandle&& handle) noexcept; /** * Checks the handle, attempts to allocate memory for the pointer and return Schedule::Ptr @@ -36,7 +36,7 @@ struct DXFCPP_EXPORT Schedule { * @param handle The graal Schedule's handle * @return The smart pointer for the Schedule object. */ - static Schedule::Ptr create(void *handle); + static Schedule::Ptr create(JavaObjectHandle&& handle); public: /** diff --git a/include/dxfeed_graal_cpp_api/schedule/Session.hpp b/include/dxfeed_graal_cpp_api/schedule/Session.hpp index 978961398..7cfb22fc4 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Session.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Session.hpp @@ -33,7 +33,7 @@ struct DXFCPP_EXPORT Session { private: JavaObjectHandle handle_; - explicit Session(void *handle) noexcept; + explicit Session(JavaObjectHandle&& handle) noexcept; /** * Checks the handle, attempts to allocate memory for the pointer and return Session::Ptr @@ -41,7 +41,7 @@ struct DXFCPP_EXPORT Session { * @param handle The graal Session's handle * @return The smart pointer for the Session object. */ - static Session::Ptr create(void *handle); + static Session::Ptr create(JavaObjectHandle&& handle); public: /** diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 2c91bde85..afcdb4fe0 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -154,374 +154,6 @@ using NativeStringList = typename isolated::internal::NativeStringListWrapper(runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getSchedule(static_cast(threadHandle), day); - }, - nullptr, static_cast(day))); -} - -std::int32_t Day::getDayId(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getDayId(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -std::int32_t Day::getYearMonthDay(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getYearMonthDay(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -std::int32_t Day::getYear(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getYear(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -std::int32_t Day::getMonthOfYear(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getMonthOfYear(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -std::int32_t Day::getDayOfMonth(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getDayOfMonth(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -std::int32_t Day::getDayOfWeek(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getDayOfWeek(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -bool Day::isHoliday(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_isHoliday(static_cast(threadHandle), day) == 1; - }, - false, static_cast(day)); -} - -bool Day::isShortDay(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_isShortDay(static_cast(threadHandle), day) == 1; - }, - false, static_cast(day)); -} - -bool Day::isTrading(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_isTrading(static_cast(threadHandle), day) == 1; - }, - false, static_cast(day)); -} - -std::int64_t Day::getStartTime(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getStartTime(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -std::int64_t Day::getEndTime(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getEndTime(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -bool Day::containsTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept { - if (!day) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&time) { - return dxfg_Day_containsTime(static_cast(threadHandle), day, time) == 1; - }, - false, static_cast(day), time); -} - -std::int64_t Day::getResetTime(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getResetTime(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -/* dxfg_session_list* */ void *Day::getSessions(/* dxfg_day_t* */ void *day) { - if (!day) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_getSessions(static_cast(threadHandle), day); - }, - nullptr, static_cast(day))); -} - -/* dxfg_session_t* */ void *Day::getSessionByTime(/* dxfg_day_t* */ void *day, std::int64_t time) noexcept { - if (!day) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&time) { - return dxfg_Day_getSessionByTime(static_cast(threadHandle), day, time); - }, - nullptr, static_cast(day), time)); -} - -/* dxfg_session_t* */ void *Day::getFirstSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_getFirstSession(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_session_t* */ void *Day::getLastSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_getLastSession(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_session_t* */ void *Day::findFirstSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_findFirstSession(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_session_t* */ void *Day::findLastSession(/* dxfg_day_t* */ void *day, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_findLastSession(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_day_t* */ void *Day::getPrevDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_getPrevDay(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_day_t* */ void *Day::getNextDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_getNextDay(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_day_t* */ void *Day::findPrevDay(/* dxfg_day_t* */ void *day, - /* dxfg_day_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_findPrevDay(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -/* dxfg_day_t* */ void *Day::findNextDay(/* dxfg_day_t* */ void *day, /* dxfg_day_filter_t* */ void *filter) noexcept { - if (!day || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&filter) { - return dxfg_Day_findNextDay(static_cast(threadHandle), day, filter); - }, - nullptr, static_cast(day), static_cast(filter))); -} - -std::size_t Day::getHashCode(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return dxfcpp::bit_cast(day); - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_hashCode(static_cast(threadHandle), day); - }, - 0, static_cast(day)); -} - -bool Day::equals(/* dxfg_day_t* */ void *day, /* dxfg_day_t* */ void *otherDay) noexcept { - if (!day || !otherDay) { - // TODO: Improve error handling - return false; - } - - if (day == otherDay) { - return true; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&day, auto &&otherDay) { - return dxfg_Day_equals(static_cast(threadHandle), day, otherDay) == 1; - }, - false, static_cast(day), static_cast(otherDay)); -} - -std::string Day::toString(/* dxfg_day_t* */ void *day) noexcept { - if (!day) { - // TODO: Improve error handling - return dxfcpp::String::EMPTY; - } - - auto string = runIsolatedOrElse( - [](auto threadHandle, auto &&day) { - return dxfg_Day_toString(static_cast(threadHandle), day); - }, - nullptr, static_cast(day)); - - auto result = dxfcpp::toString(string); - - isolated::internal::IsolatedString::release(string); - - return result; -} - /* dxfg_session_filter_t* */ void *SessionFilter::getInstance(std::uint32_t code) noexcept { return static_cast(runIsolatedOrElse( [](auto threadHandle, auto &&filter) { diff --git a/src/isolated/schedule/IsolatedDay.cpp b/src/isolated/schedule/IsolatedDay.cpp index 582ba26cf..efdcddc6f 100644 --- a/src/isolated/schedule/IsolatedDay.cpp +++ b/src/isolated/schedule/IsolatedDay.cpp @@ -4,6 +4,7 @@ #include #include +#include #include DXFCPP_BEGIN_NAMESPACE @@ -19,7 +20,351 @@ namespace IsolatedDayFilter { } // namespace IsolatedDayFilter -namespace IsolatedDay {} +// TODO: move to IsolatedSession +namespace IsolatedSessionList { + +bool release(/* dxfg_session_list* */ void *sessionList) { + if (!sessionList) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_SessionList_wrapper_release`. The `sessionList` is nullptr"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, + static_cast(sessionList)); +} + +std::unique_ptr toUnique(/* dxfg_session_list* */ void *sessionList) { + return {sessionList, release}; +} + +} // namespace IsolatedSessionList + +namespace IsolatedDay { + +/* dxfg_schedule_t* */ JavaObjectHandle +getSchedule(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getSchedule`. The `day` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Day_getSchedule, static_cast(day.get()))}; +} + +std::int32_t getDayId(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_getDayId`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getDayId, static_cast(day.get())); +} + +std::int32_t getYearMonthDay(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getYearMonthDay`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getYearMonthDay, static_cast(day.get())); +} + +std::int32_t getYear(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_getYear`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getYear, static_cast(day.get())); +} + +std::int32_t getMonthOfYear(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getMonthOfYear`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getMonthOfYear, static_cast(day.get())); +} + +std::int32_t getDayOfMonth(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getDayOfMonth`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getDayOfMonth, static_cast(day.get())); +} + +std::int32_t getDayOfWeek(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getDayOfWeek`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getDayOfWeek, static_cast(day.get())); +} + +bool isHoliday(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_isHoliday`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_isHoliday, static_cast(day.get())) == 1; +} + +bool isShortDay(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_isShortDay`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_isShortDay, static_cast(day.get())) == 1; +} + +bool isTrading(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_isTrading`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_isTrading, static_cast(day.get())) == 1; +} + +std::int64_t getStartTime(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getStartTime`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getStartTime, static_cast(day.get())); +} + +std::int64_t getEndTime(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_getEndTime`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getEndTime, static_cast(day.get())); +} + +bool containsTime(/* dxfg_day_t* */ const JavaObjectHandle &day, std::int64_t time) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_containsTime`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_containsTime, static_cast(day.get()), time) == 1; +} + +std::int64_t getResetTime(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getResetTime`. The `day` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_getResetTime, static_cast(day.get())); +} + +/* dxfg_session_list* */ void *getSessions(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getSessions`. The `day` handle is invalid"); + } + + return static_cast( + runGraalFunctionAndThrowIfNullptr(dxfg_Day_getSessions, static_cast(day.get()))); +} + +/* dxfg_session_t* */ JavaObjectHandle +getSessionByTime(/* dxfg_day_t* */ const JavaObjectHandle &day, std::int64_t time) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getSessionByTime`. The `day` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Day_getSessionByTime, static_cast(day.get()), time)}; +} + +/* dxfg_session_t* */ JavaObjectHandle +getFirstSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getFirstSession`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getFirstSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Day_getFirstSession, static_cast(day.get()), + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +getLastSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getLastSession`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getLastSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Day_getLastSession, static_cast(day.get()), + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +findFirstSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findFirstSession`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findFirstSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Day_findFirstSession, static_cast(day.get()), + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +findLastSession(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findLastSession`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findLastSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Day_findLastSession, static_cast(day.get()), + static_cast(filter.get()))}; +} + +/* dxfg_day_t* */ JavaObjectHandle +getPrevDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_getPrevDay`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getPrevDay`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Day_getPrevDay, static_cast(day.get()), static_cast(filter.get()))}; +} + +/* dxfg_day_t* */ JavaObjectHandle +getNextDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_getNextDay`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getNextDay`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Day_getNextDay, static_cast(day.get()), static_cast(filter.get()))}; +} + +/* dxfg_day_t* */ JavaObjectHandle +findPrevDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findPrevDay`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findPrevDay`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Day_findPrevDay, static_cast(day.get()), static_cast(filter.get()))}; +} + +/* dxfg_day_t* */ JavaObjectHandle +findNextDay(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_filter_t* */ const JavaObjectHandle &filter) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findNextDay`. The `day` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_findNextDay`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Day_findNextDay, static_cast(day.get()), static_cast(filter.get()))}; +} + +std::size_t getHashCode(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_getHashCode`. The `day` handle is invalid"); + } + + return static_cast( + runGraalFunctionAndThrowIfMinusOne(dxfg_Day_hashCode, static_cast(day.get()))); +} + +bool equals(/* dxfg_day_t* */ const JavaObjectHandle &day, + /* dxfg_day_t* */ const JavaObjectHandle &otherDay) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_equals`. The `day` handle is invalid"); + } + + if (!otherDay) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Day_equals`. The `otherDay` handle is invalid"); + } + + if (day.get() == otherDay.get()) { + return true; + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Day_equals, static_cast(day.get()), + static_cast(otherDay.get())) == 1; +} + +std::string toString(/* dxfg_day_t* */ const JavaObjectHandle &day) { + if (!day) { + throw InvalidArgumentException("Unable to execute function `dxfg_Day_toString`. The `day` handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique( + runGraalFunctionAndThrowIfNullptr(dxfg_Day_toString, static_cast(day.get()))); + + auto result = dxfcpp::toString(string.get()); + + return result; +} + +} // namespace IsolatedDay } // namespace isolated::schedule diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index 97e6f402e..94406055f 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -9,254 +9,145 @@ DXFCPP_BEGIN_NAMESPACE -Day::Day(void *handle) noexcept : handle_(handle) { +Day::Day(JavaObjectHandle &&handle) noexcept : handle_(std::move(handle)) { } -Day::Ptr Day::create(void *handle) { +Day::Ptr Day::create(JavaObjectHandle &&handle) { if (!handle) { - throw InvalidArgumentException("Unable to create a Day object. The handle is nullptr"); + throw InvalidArgumentException("Unable to create a Day object. The handle is invalid"); } - return std::shared_ptr(new Day(handle)); + return std::shared_ptr(new Day(std::move(handle))); } -std::shared_ptr Day::getSchedule() const noexcept { - if (!handle_) { - return {}; - } - - return Schedule::create(isolated::schedule::Day::getSchedule(handle_.get())); +std::shared_ptr Day::getSchedule() const { + return Schedule::create(isolated::schedule::IsolatedDay::getSchedule(handle_)); } -std::int32_t Day::getDayId() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getDayId(handle_.get()); +std::int32_t Day::getDayId() const { + return isolated::schedule::IsolatedDay::getDayId(handle_); } -std::int32_t Day::getYearMonthDay() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getYearMonthDay(handle_.get()); +std::int32_t Day::getYearMonthDay() const { + return isolated::schedule::IsolatedDay::getYearMonthDay(handle_); } -std::int32_t Day::getYear() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getYear(handle_.get()); +std::int32_t Day::getYear() const { + return isolated::schedule::IsolatedDay::getYear(handle_); } -std::int32_t Day::getMonthOfYear() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getMonthOfYear(handle_.get()); +std::int32_t Day::getMonthOfYear() const { + return isolated::schedule::IsolatedDay::getMonthOfYear(handle_); } -std::int32_t Day::getDayOfMonth() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getDayOfMonth(handle_.get()); +std::int32_t Day::getDayOfMonth() const { + return isolated::schedule::IsolatedDay::getDayOfMonth(handle_); } -std::int32_t Day::getDayOfWeek() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getDayOfWeek(handle_.get()); +std::int32_t Day::getDayOfWeek() const { + return isolated::schedule::IsolatedDay::getDayOfWeek(handle_); } -bool Day::isHoliday() const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Day::isHoliday(handle_.get()); +bool Day::isHoliday() const { + return isolated::schedule::IsolatedDay::isHoliday(handle_); } -bool Day::isShortDay() const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Day::isShortDay(handle_.get()); +bool Day::isShortDay() const { + return isolated::schedule::IsolatedDay::isShortDay(handle_); } -bool Day::isTrading() const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Day::isTrading(handle_.get()); +bool Day::isTrading() const { + return isolated::schedule::IsolatedDay::isTrading(handle_); } -std::int64_t Day::getStartTime() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getStartTime(handle_.get()); +std::int64_t Day::getStartTime() const { + return isolated::schedule::IsolatedDay::getStartTime(handle_); } -std::int64_t Day::getEndTime() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getEndTime(handle_.get()); +std::int64_t Day::getEndTime() const { + return isolated::schedule::IsolatedDay::getEndTime(handle_); } -bool Day::containsTime(std::int64_t time) const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Day::containsTime(handle_.get(), time); +bool Day::containsTime(std::int64_t time) const { + return isolated::schedule::IsolatedDay::containsTime(handle_, time); } -std::int64_t Day::getResetTime() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Day::getResetTime(handle_.get()); +std::int64_t Day::getResetTime() const { + return isolated::schedule::IsolatedDay::getResetTime(handle_); } std::vector> Day::getSessions() const { - if (!handle_) { - return {}; - } - - auto *graalSessionList = isolated::schedule::Day::getSessions(handle_.get()); + auto graalSessionList = + isolated::schedule::IsolatedSessionList::toUnique(isolated::schedule::IsolatedDay::getSessions(handle_)); if (!graalSessionList) { return {}; } - auto *sessionList = dxfcpp::bit_cast(graalSessionList); + auto *sessionList = dxfcpp::bit_cast(graalSessionList.get()); std::vector> result; if (sessionList->size > 0 && sessionList->elements) { result.reserve(static_cast(sessionList->size)); for (std::int32_t i = 0; i < sessionList->size; i++) { - result.emplace_back(Session::create(sessionList->elements[i])); + result.emplace_back(Session::create(JavaObjectHandle(sessionList->elements[i]))); } } - isolated::runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, sessionList); - return result; } -std::shared_ptr Day::getSessionByTime(std::int64_t time) const noexcept { - if (!handle_) { - return {}; - } - - return Session::create(isolated::schedule::Day::getSessionByTime(handle_.get(), time)); +std::shared_ptr Day::getSessionByTime(std::int64_t time) const { + return Session::create(isolated::schedule::IsolatedDay::getSessionByTime(handle_, time)); } -std::shared_ptr Day::getFirstSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(isolated::schedule::Day::getFirstSession(handle_.get(), filter.getHandle().get())); +std::shared_ptr Day::getFirstSession(const SessionFilter &filter) const { + return Session::create(isolated::schedule::IsolatedDay::getFirstSession(handle_, filter.getHandle())); } -std::shared_ptr Day::getLastSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(isolated::schedule::Day::getLastSession(handle_.get(), filter.getHandle().get())); +std::shared_ptr Day::getLastSession(const SessionFilter &filter) const { + return Session::create(isolated::schedule::IsolatedDay::getLastSession(handle_, filter.getHandle())); } -std::shared_ptr Day::findFirstSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(isolated::schedule::Day::findFirstSession(handle_.get(), filter.getHandle().get())); +std::shared_ptr Day::findFirstSession(const SessionFilter &filter) const { + return Session::create(isolated::schedule::IsolatedDay::findFirstSession(handle_, filter.getHandle())); } -std::shared_ptr Day::findLastSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(isolated::schedule::Day::findLastSession(handle_.get(), filter.getHandle().get())); +std::shared_ptr Day::findLastSession(const SessionFilter &filter) const { + return Session::create(isolated::schedule::IsolatedDay::findLastSession(handle_, filter.getHandle())); } -Day::Ptr Day::getPrevDay(const DayFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { - return {}; - } - - return create(isolated::schedule::Day::getPrevDay(handle_.get(), filter.handle_.get())); +Day::Ptr Day::getPrevDay(const DayFilter &filter) const { + return create(isolated::schedule::IsolatedDay::getPrevDay(handle_, filter.handle_)); } -Day::Ptr Day::getNextDay(const DayFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { - return {}; - } - - return create(isolated::schedule::Day::getNextDay(handle_.get(), filter.handle_.get())); +Day::Ptr Day::getNextDay(const DayFilter &filter) const { + return create(isolated::schedule::IsolatedDay::getNextDay(handle_, filter.handle_)); } -Day::Ptr Day::findPrevDay(const DayFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { - return {}; - } - - return create(isolated::schedule::Day::findPrevDay(handle_.get(), filter.handle_.get())); +Day::Ptr Day::findPrevDay(const DayFilter &filter) const { + return create(isolated::schedule::IsolatedDay::findPrevDay(handle_, filter.handle_)); } -Day::Ptr Day::findNextDay(const DayFilter &filter) const noexcept { - if (!handle_ || !filter.handle_) { - return {}; - } - - return create(isolated::schedule::Day::findNextDay(handle_.get(), filter.handle_.get())); +Day::Ptr Day::findNextDay(const DayFilter &filter) const { + return create(isolated::schedule::IsolatedDay::findNextDay(handle_, filter.handle_)); } -bool Day::operator==(const Day &other) const noexcept { - if (!handle_ || !other.handle_) { - return false; - } - +bool Day::operator==(const Day &other) const { if (this == &other) { return true; } - return isolated::schedule::Day::equals(handle_.get(), other.handle_.get()); + return isolated::schedule::IsolatedDay::equals(handle_, other.handle_); } -std::size_t Day::getHashCode() const noexcept { - if (!handle_) { - return dxfcpp::bit_cast(this); - } - - return isolated::schedule::Day::getHashCode(handle_.get()); +std::size_t Day::getHashCode() const { + return isolated::schedule::IsolatedDay::getHashCode(handle_); } std::string Day::toString() const { - if (!handle_) { - return dxfcpp::String::EMPTY; - } - - return isolated::schedule::Day::toString(handle_.get()); + return isolated::schedule::IsolatedDay::toString(handle_); } DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/schedule/Schedule.cpp b/src/schedule/Schedule.cpp index 426dd3252..aae18221a 100644 --- a/src/schedule/Schedule.cpp +++ b/src/schedule/Schedule.cpp @@ -8,15 +8,15 @@ DXFCPP_BEGIN_NAMESPACE -Schedule::Schedule(void *handle) noexcept : handle_(handle) { +Schedule::Schedule(JavaObjectHandle &&handle) noexcept : handle_(std::move(handle)) { } -Schedule::Ptr Schedule::create(void *handle) { +Schedule::Ptr Schedule::create(JavaObjectHandle &&handle) { if (!handle) { throw InvalidArgumentException("Unable to create a Schedule object. The handle is nullptr"); } - return std::shared_ptr(new Schedule(handle)); + return std::shared_ptr(new Schedule(std::move(handle))); } Schedule::Ptr Schedule::getInstance(std::shared_ptr profile) { @@ -24,13 +24,14 @@ Schedule::Ptr Schedule::getInstance(std::shared_ptr profile) throw InvalidArgumentException("The profile is nullptr"); } - auto schedule = create(isolated::schedule::Schedule::getInstance(profile->handle_.get())); + auto schedule = + create(JavaObjectHandle{isolated::schedule::Schedule::getInstance(profile->handle_.get())}); return schedule; } Schedule::Ptr Schedule::getInstance(const std::string &scheduleDefinition) { - return create(isolated::schedule::Schedule::getInstance(scheduleDefinition)); + return create(JavaObjectHandle{isolated::schedule::Schedule::getInstance(scheduleDefinition)}); } Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, const std::string &venue) { @@ -38,7 +39,8 @@ Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, throw InvalidArgumentException("The profile is nullptr"); } - auto schedule = create(isolated::schedule::Schedule::getInstance(profile->handle_.get(), venue)); + auto schedule = + create(JavaObjectHandle{isolated::schedule::Schedule::getInstance(profile->handle_.get(), venue)}); return schedule; } @@ -66,7 +68,8 @@ Session::Ptr Schedule::getSessionByTime(std::int64_t time) const noexcept { return {}; } - return Session::create(isolated::schedule::Schedule::getSessionByTime(handle_.get(), time)); + return Session::create( + JavaObjectHandle{isolated::schedule::Schedule::getSessionByTime(handle_.get(), time)}); } Day::Ptr Schedule::getDayByTime(std::int64_t time) const noexcept { @@ -74,7 +77,7 @@ Day::Ptr Schedule::getDayByTime(std::int64_t time) const noexcept { return {}; } - return Day::create(isolated::schedule::Schedule::getDayByTime(handle_.get(), time)); + return Day::create(JavaObjectHandle{isolated::schedule::Schedule::getDayByTime(handle_.get(), time)}); } Day::Ptr Schedule::getDayById(std::int32_t dayId) const noexcept { @@ -82,7 +85,7 @@ Day::Ptr Schedule::getDayById(std::int32_t dayId) const noexcept { return {}; } - return Day::create(isolated::schedule::Schedule::getDayById(handle_.get(), dayId)); + return Day::create(JavaObjectHandle{isolated::schedule::Schedule::getDayById(handle_.get(), dayId)}); } Day::Ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const noexcept { @@ -90,7 +93,8 @@ Day::Ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const noexcep return {}; } - return Day::create(isolated::schedule::Schedule::getDayByYearMonthDay(handle_.get(), yearMonthDay)); + return Day::create( + JavaObjectHandle{isolated::schedule::Schedule::getDayByYearMonthDay(handle_.get(), yearMonthDay)}); } Session::Ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { @@ -98,8 +102,8 @@ Session::Ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionF return {}; } - return Session::create( - isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.getHandle().get())); + return Session::create(JavaObjectHandle{ + isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.getHandle().get())}); } Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { @@ -107,8 +111,8 @@ Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const Session return {}; } - return Session::create( - isolated::schedule::Schedule::findNearestSessionByTime(handle_.get(), time, filter.getHandle().get())); + return Session::create(JavaObjectHandle{ + isolated::schedule::Schedule::findNearestSessionByTime(handle_.get(), time, filter.getHandle().get())}); } std::string Schedule::getName() const noexcept { diff --git a/src/schedule/Session.cpp b/src/schedule/Session.cpp index 3e05a6104..e89c9e081 100644 --- a/src/schedule/Session.cpp +++ b/src/schedule/Session.cpp @@ -8,15 +8,15 @@ DXFCPP_BEGIN_NAMESPACE -Session::Session(void *handle) noexcept : handle_(handle) { +Session::Session(JavaObjectHandle &&handle) noexcept : handle_(std::move(handle)) { } -Session::Ptr Session::create(void *handle) { +Session::Ptr Session::create(JavaObjectHandle &&handle) { if (!handle) { - throw InvalidArgumentException("Unable to create a Session object. The handle is nullptr"); + throw InvalidArgumentException("Unable to create a Session object. The handle is invalid"); } - return std::shared_ptr(new Session(handle)); + return std::shared_ptr(new Session(std::move(handle))); } Day::Ptr Session::getDay() const noexcept { @@ -24,7 +24,7 @@ Day::Ptr Session::getDay() const noexcept { return {}; } - return Day::create(isolated::schedule::Session::getDay(handle_.get())); + return Day::create(JavaObjectHandle{isolated::schedule::Session::getDay(handle_.get())}); } const SessionType &Session::getType() const & noexcept { @@ -91,7 +91,8 @@ Session::Ptr Session::getPrevSession(const SessionFilter &filter) const noexcept return {}; } - return Session::create(isolated::schedule::Session::getPrevSession(handle_.get(), filter.getHandle().get())); + return Session::create(JavaObjectHandle{ + isolated::schedule::Session::getPrevSession(handle_.get(), filter.getHandle().get())}); } Session::Ptr Session::getNextSession(const SessionFilter &filter) const noexcept { @@ -99,7 +100,8 @@ Session::Ptr Session::getNextSession(const SessionFilter &filter) const noexcept return {}; } - return Session::create(isolated::schedule::Session::getNextSession(handle_.get(), filter.getHandle().get())); + return Session::create(JavaObjectHandle{ + isolated::schedule::Session::getNextSession(handle_.get(), filter.getHandle().get())}); } Session::Ptr Session::findPrevSession(const SessionFilter &filter) const noexcept { @@ -107,7 +109,8 @@ Session::Ptr Session::findPrevSession(const SessionFilter &filter) const noexcep return {}; } - return Session::create(isolated::schedule::Session::findPrevSession(handle_.get(), filter.getHandle().get())); + return Session::create(JavaObjectHandle{ + isolated::schedule::Session::findPrevSession(handle_.get(), filter.getHandle().get())}); } Session::Ptr Session::findNextSession(const SessionFilter &filter) const noexcept { @@ -115,7 +118,8 @@ Session::Ptr Session::findNextSession(const SessionFilter &filter) const noexcep return {}; } - return Session::create(isolated::schedule::Session::findNextSession(handle_.get(), filter.getHandle().get())); + return Session::create(JavaObjectHandle{ + isolated::schedule::Session::findNextSession(handle_.get(), filter.getHandle().get())}); } bool Session::operator==(const Session &other) const noexcept { From 8f9196a7e04af2ec7ddbc034e6ec8d4939c24fcd Mon Sep 17 00:00:00 2001 From: ttldtor Date: Tue, 17 Sep 2024 21:12:11 +0300 Subject: [PATCH 091/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedSessionFilter IsolatedSession --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + .../ipf/live/IterableInstrumentProfile.hpp | 8 +- .../isolated/Isolated.hpp | 25 -- .../isolated/schedule/IsolatedDay.hpp | 8 - .../isolated/schedule/IsolatedSession.hpp | 76 ++++++ include/dxfeed_graal_cpp_api/schedule/Day.hpp | 45 ++-- .../schedule/Schedule.hpp | 26 +- .../dxfeed_graal_cpp_api/schedule/Session.hpp | 55 +++-- src/event/candle/CandleSession.cpp | 3 +- src/internal/Isolate.cpp | 204 ---------------- src/ipf/live/IterableInstrumentProfile.cpp | 8 +- src/isolated/schedule/IsolatedDay.cpp | 19 -- src/isolated/schedule/IsolatedSession.cpp | 230 ++++++++++++++++++ src/schedule/Day.cpp | 44 +++- src/schedule/Schedule.cpp | 22 +- src/schedule/Session.cpp | 126 ++++------ 17 files changed, 474 insertions(+), 427 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSession.hpp create mode 100644 src/isolated/schedule/IsolatedSession.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index eba579132..0d49c9afe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/ondemand/IsolatedOnDemandService.cpp src/isolated/util/IsolatedTimePeriod.cpp src/isolated/schedule/IsolatedDay.cpp + src/isolated/schedule/IsolatedSession.cpp ) set(dxFeedGraalCxxApi_Api_Sources diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 5e0e48cd0..e824c7306 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -77,6 +77,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/ondemand/IsolatedOnDemandService.hpp" #include "isolated/util/IsolatedTimePeriod.hpp" #include "isolated/schedule/IsolatedDay.hpp" +#include "isolated/schedule/IsolatedSession.hpp" #include "ondemand/OnDemandService.hpp" diff --git a/include/dxfeed_graal_cpp_api/ipf/live/IterableInstrumentProfile.hpp b/include/dxfeed_graal_cpp_api/ipf/live/IterableInstrumentProfile.hpp index 6c57a6f22..1e5a5a888 100644 --- a/include/dxfeed_graal_cpp_api/ipf/live/IterableInstrumentProfile.hpp +++ b/include/dxfeed_graal_cpp_api/ipf/live/IterableInstrumentProfile.hpp @@ -37,14 +37,16 @@ class DXFCPP_EXPORT IterableInstrumentProfile final { * * @return `true` if the iteration has more elements */ - [[nodiscard]] bool hasNext() const noexcept; + bool hasNext() const noexcept; /** * Returns the next element in the iteration. * - * @return the next element in the iteration or std::shared_ptr{nullptr} + * @return the next element in the iteration + * @throw InvalidArgumentException + * @throw JavaException "NoSuchElementException" */ - [[nodiscard]] std::shared_ptr next() const; + std::shared_ptr next() const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp index 05a34a10e..7c53063b9 100644 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp @@ -25,31 +25,6 @@ namespace isolated { namespace schedule { -struct SessionFilter { - static /* dxfg_session_filter_t* */ void *getInstance(std::uint32_t code) noexcept; -}; - -struct Session { - static /* dxfg_day_t* */ void *getDay(/* dxfg_session_t* */ void *session) noexcept; - static std::int32_t getType(/* dxfg_session_t* */ void *session) noexcept; - static bool isTrading(/* dxfg_session_t* */ void *session) noexcept; - static bool isEmpty(/* dxfg_session_t* */ void *session) noexcept; - static std::int64_t getStartTime(/* dxfg_session_t* */ void *session) noexcept; - static std::int64_t getEndTime(/* dxfg_session_t* */ void *session) noexcept; - static bool containsTime(/* dxfg_session_t* */ void *session, std::int64_t time) noexcept; - static /* dxfg_session_t* */ void *getPrevSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *getNextSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *findPrevSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *findNextSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static std::size_t getHashCode(/* dxfg_session_t* */ void *session) noexcept; - static bool equals(/* dxfg_session_t* */ void *session, /* dxfg_session_t* */ void *otherSession) noexcept; - static std::string toString(/* dxfg_session_t* */ void *session) noexcept; -}; - struct Schedule { static /* dxfg_schedule_t* */ void *getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept; static /* dxfg_schedule_t* */ void *getInstance(const std::string &scheduleDefinition) noexcept; diff --git a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp index 790e1dab7..f166c9f5f 100644 --- a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedDay.hpp @@ -20,14 +20,6 @@ namespace IsolatedDayFilter { } -namespace IsolatedSessionList { - -bool release(/* dxfg_session_list* */ void *sessionList); - -std::unique_ptr toUnique(/* dxfg_session_list* */ void *sessionList); - -} - namespace IsolatedDay { /* dxfg_schedule_t* */ JavaObjectHandle getSchedule(/* dxfg_day_t* */ const JavaObjectHandle &day); diff --git a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSession.hpp b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSession.hpp new file mode 100644 index 000000000..a4be8c859 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSession.hpp @@ -0,0 +1,76 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include "../../schedule/Session.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::schedule { + +namespace IsolatedSessionFilter { + +/* dxfg_session_filter_t* */ JavaObjectHandle getInstance(std::uint32_t code); + +}; + +namespace IsolatedSession { + +/* dxfg_day_t* */ JavaObjectHandle +getDay(/* dxfg_session_t* */ const JavaObjectHandle &session); + +std::int32_t getType(/* dxfg_session_t* */ const JavaObjectHandle &session); + +bool isTrading(/* dxfg_session_t* */ const JavaObjectHandle &session); + +bool isEmpty(/* dxfg_session_t* */ const JavaObjectHandle &session); + +std::int64_t getStartTime(/* dxfg_session_t* */ const JavaObjectHandle &session); + +std::int64_t getEndTime(/* dxfg_session_t* */ const JavaObjectHandle &session); + +bool containsTime(/* dxfg_session_t* */ const JavaObjectHandle &session, std::int64_t time); + +/* dxfg_session_t* */ JavaObjectHandle +getPrevSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +getNextSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +findPrevSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +findNextSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +std::size_t getHashCode(/* dxfg_session_t* */ const JavaObjectHandle &session); + +bool equals(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_t* */ const JavaObjectHandle &otherSession); + +std::string toString(/* dxfg_session_t* */ const JavaObjectHandle &session); + +} // namespace IsolatedSession + +namespace IsolatedSessionList { + +bool release(/* dxfg_session_list* */ void *sessionList); + +std::unique_ptr toUnique(/* dxfg_session_list* */ void *sessionList); + +} // namespace IsolatedSessionList + +} // namespace isolated::schedule + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/schedule/Day.hpp b/include/dxfeed_graal_cpp_api/schedule/Day.hpp index 7fb24b84c..e2460fce5 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Day.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Day.hpp @@ -5,6 +5,8 @@ #include "../internal/Conf.hpp" +#include "../internal/JavaObjectHandle.hpp" + DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE @@ -146,19 +148,18 @@ struct DXFCPP_EXPORT Day { /** * Returns session belonging to this day that contains specified time. - * If no such session was found within this day this method will return Session::Ptr{nullptr} - * (std::shared_ptr{nullptr}). + * If no such session was found within this day this method will throw JavaException "NoSuchElementException" * * @param time The time to search for - * @return The session that contains specified time or Session::Ptr{nullptr} (std::shared_ptr{nullptr}) - * if no such session was found within this day + * @return The session that contains specified time. + * @throw JavaException "NoSuchElementException" if no such session was found within this day */ std::shared_ptr getSessionByTime(std::int64_t time) const; /** * Returns first session belonging to this day accepted by specified filter. * This method does not cross the day boundary. If no such session was found - * within this day this method will return Session::Ptr{nullptr} (std::shared_ptr{nullptr}) + * within this day this method will throw JavaException "NoSuchElementException" *

    * To find first trading session of any type use this code: *

    Session session = day->getFirstSession(SessionFilter::TRADING);
    @@ -166,15 +167,15 @@ struct DXFCPP_EXPORT Day { *
    Session session = day->getFirstSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return The first session that is accepted by the filter or Session::Ptr{nullptr} - * (std::shared_ptr{nullptr}) if no such session was found within this day + * @return The first session that is accepted by the filter. + * @throw JavaException "NoSuchElementException" if no such session was found within this day. */ std::shared_ptr getFirstSession(const SessionFilter &filter) const; /** * Returns last session belonging to this day accepted by specified filter. * This method does not cross the day boundary. If no such session was found - * within this day this method will return Session::Ptr{nullptr} (std::shared_ptr{nullptr}) + * within this day this method will throw JavaException "NoSuchElementException" *

    * To find last trading session of any type use this code: *

    auto session = day->getLastSession(SessionFilter::TRADING);
    @@ -182,8 +183,8 @@ struct DXFCPP_EXPORT Day { *
    auto session = day->getLastSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return The last session that is accepted by the filter or Session::Ptr{nullptr} - * (std::shared_ptr{nullptr}) if no such session was found within this day + * @return The last session that is accepted by the filter. + * @throw JavaException "NoSuchElementException" if no such session was found within this day. */ std::shared_ptr getLastSession(const SessionFilter &filter) const; @@ -198,7 +199,7 @@ struct DXFCPP_EXPORT Day { *
    auto session = day->findFirstSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return The first session that is accepted by the filter + * @return The first session that is accepted by the filter or Session::Ptr{nullptr} (std::shared_ptr{nullptr}) */ std::shared_ptr findFirstSession(const SessionFilter &filter) const; @@ -213,29 +214,29 @@ struct DXFCPP_EXPORT Day { *
    auto session = day->findLastSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return The last session that is accepted by the filter + * @return The last session that is accepted by the filter or Session::Ptr{nullptr} (std::shared_ptr{nullptr}) */ std::shared_ptr findLastSession(const SessionFilter &filter) const; /** * Returns previous day accepted by specified filter. * This method looks for appropriate day up to a year back in time. If no such day was found - * within one year this method will return Day::Ptr{nullptr} (std::shared_ptr{nullptr}). + * within one year this method will throw JavaException "NoSuchElementException". * - * @param The filter the filter to test days - * @return The nearest previous day that is accepted by the filter or Day::Ptr{nullptr} - * (std::shared_ptr{nullptr}) if no such day was found within one year + * @param filter The filter the filter to test days + * @return The nearest previous day that is accepted by the filter + * @throw JavaException "NoSuchElementException" if no such day was found within one year */ Day::Ptr getPrevDay(const DayFilter &filter) const; /** * Returns following day accepted by specified filter. * This method looks for appropriate day up to a year in the future. If no such day was found - * within one year this method will return Day::Ptr{nullptr} (std::shared_ptr{nullptr}). + * within one year this method will throw JavaException "NoSuchElementException". * - * @param The filter the filter to test days - * @return The nearest following day that is accepted by the filter or Day::Ptr{nullptr} - * (std::shared_ptr{nullptr}) if no such day was found within one year + * @param filter The filter the filter to test days + * @return The nearest following day that is accepted by the filter. + * @throw JavaException "NoSuchElementException" if no such day was found within one year */ Day::Ptr getNextDay(const DayFilter &filter) const; @@ -245,7 +246,7 @@ struct DXFCPP_EXPORT Day { * within one year this method will return Day::Ptr{nullptr} (std::shared_ptr{nullptr}). * * @param filter The filter to test days - * @return The nearest previous day that is accepted by the filter + * @return The nearest previous day that is accepted by the filter or Day::Ptr{nullptr} (std::shared_ptr{nullptr}) */ Day::Ptr findPrevDay(const DayFilter &filter) const; @@ -255,7 +256,7 @@ struct DXFCPP_EXPORT Day { * within one year this method will return Day::Ptr{nullptr} (std::shared_ptr{nullptr}). * * @param filter The filter to test days - * @return The nearest following day that is accepted by the filter + * @return The nearest following day that is accepted by the filter or Day::Ptr{nullptr} (std::shared_ptr{nullptr}) */ Day::Ptr findNextDay(const DayFilter &filter) const; diff --git a/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp b/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp index 4f9a188a7..2d4f314e4 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp @@ -9,6 +9,10 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE +struct InstrumentProfile; +struct Day; +struct Session; + /** * Schedule class provides API to retrieve and explore trading schedules of different exchanges * and different classes of financial instruments. Each instance of schedule covers separate trading schedule @@ -83,7 +87,7 @@ struct DXFCPP_EXPORT Schedule { * * @param downloadConfig download config */ - static void downloadDefaults(const std::string &downloadConfig) noexcept; + static void downloadDefaults(const std::string &downloadConfig); /** * Sets shared defaults that are used by individual schedule instances. @@ -91,7 +95,7 @@ struct DXFCPP_EXPORT Schedule { * @param data The content of default data * @return `true` if OK */ - static bool setDefaults(const std::vector &data) noexcept; + static bool setDefaults(const std::vector &data); /** * Returns session that contains specified time. @@ -102,7 +106,7 @@ struct DXFCPP_EXPORT Schedule { * @return session that contains specified time or `Session::Ptr{nullptr}` if specified time * falls outside of valid date range from 0001-01-02 to 9999-12-30. */ - Session::Ptr getSessionByTime(std::int64_t time) const noexcept; + std::shared_ptr getSessionByTime(std::int64_t time) const; /** * Returns day that contains specified time. @@ -113,7 +117,7 @@ struct DXFCPP_EXPORT Schedule { * @return The day that contains specified time or `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) if * specified time falls outside of valid date range */ - Day::Ptr getDayByTime(std::int64_t time) const noexcept; + std::shared_ptr getDayByTime(std::int64_t time) const; /** * Returns day for specified day identifier. @@ -125,7 +129,7 @@ struct DXFCPP_EXPORT Schedule { * specified day identifier falls outside of valid date range * @see Day::getDayId() */ - Day::Ptr getDayById(std::int32_t dayId) const noexcept; + std::shared_ptr getDayById(std::int32_t dayId) const; /** * Returns day for specified year, month and day numbers. @@ -143,7 +147,7 @@ struct DXFCPP_EXPORT Schedule { * if specified year, month and day numbers fall outside of valid date range * @see Day#getYearMonthDay() */ - Day::Ptr getDayByYearMonthDay(std::int32_t yearMonthDay) const noexcept; + std::shared_ptr getDayByYearMonthDay(std::int32_t yearMonthDay) const; /** * Returns session that is nearest to the specified time and that is accepted by specified filter. @@ -161,7 +165,7 @@ struct DXFCPP_EXPORT Schedule { * `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time falls outside of valid date range * or if no such day was found within one year */ - Session::Ptr getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept; + std::shared_ptr getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const; /** * Returns session that is nearest to the specified time and that is accepted by specified filter. @@ -180,28 +184,28 @@ struct DXFCPP_EXPORT Schedule { * @return The session that is nearest to the specified time and that is accepted by specified filter or * `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time falls outside of valid date range */ - Session::Ptr findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept; + std::shared_ptr findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const; /** * Returns name of this schedule. * * @return The name of this schedule */ - std::string getName() const noexcept; + std::string getName() const; /** * Returns time zone display name in which this schedule is defined. * * @return time zone display name in which this schedule is defined */ - std::string getTimeZoneDisplayName() const noexcept; + std::string getTimeZoneDisplayName() const; /** * Returns time zone id in which this schedule is defined. * * @return time zone id in which this schedule is defined */ - std::string getTimeZoneId() const noexcept; + std::string getTimeZoneId() const; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/schedule/Session.hpp b/include/dxfeed_graal_cpp_api/schedule/Session.hpp index 7cfb22fc4..41af2b50d 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Session.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Session.hpp @@ -9,6 +9,10 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE +struct Day; +struct Schedule; +struct SessionType; + /** * Session represents a continuous period of time during which apply same rules regarding trading activity. * For example, regular trading session is a period of time consisting of one day of business activities @@ -33,7 +37,7 @@ struct DXFCPP_EXPORT Session { private: JavaObjectHandle handle_; - explicit Session(JavaObjectHandle&& handle) noexcept; + explicit Session(JavaObjectHandle &&handle) noexcept; /** * Checks the handle, attempts to allocate memory for the pointer and return Session::Ptr @@ -41,7 +45,7 @@ struct DXFCPP_EXPORT Session { * @param handle The graal Session's handle * @return The smart pointer for the Session object. */ - static Session::Ptr create(JavaObjectHandle&& handle); + static Session::Ptr create(JavaObjectHandle &&handle); public: /** @@ -49,14 +53,14 @@ struct DXFCPP_EXPORT Session { * * @return The day to which this session belongs. */ - Day::Ptr getDay() const noexcept; + std::shared_ptr getDay() const; /** * Returns type of this session. * * @return The type of this session. */ - const SessionType &getType() const & noexcept; + const SessionType &getType() const &; /** * @return true if trading activity is allowed within this session. @@ -65,37 +69,37 @@ struct DXFCPP_EXPORT Session { * Some sessions may have zero duration - e.g. indices that post value once a day. * Such sessions can be of any appropriate type, trading or non-trading. */ - bool isTrading() const noexcept; + bool isTrading() const; /** * @return true if this session has zero duration. * Empty sessions can be used for indices that post value once a day or for convenience. * Such sessions can be of any appropriate type, trading or non-trading. */ - bool isEmpty() const noexcept; + bool isEmpty() const; /** * @return start time of this session (inclusive). * For normal sessions the start time is less than the end time, for empty sessions they are equal. */ - std::int64_t getStartTime() const noexcept; + std::int64_t getStartTime() const; /** * @return end time of this session (exclusive). * For normal sessions the end time is greater than the start time, for empty sessions they are equal. */ - std::int64_t getEndTime() const noexcept; + std::int64_t getEndTime() const; /** * @return true if specified time belongs to this session. */ - bool containsTime(std::int64_t time) const noexcept; + bool containsTime(std::int64_t time) const; /** * Returns previous session accepted by specified filter. * This method may cross the day boundary and return appropriate session from * previous days - up to a year back in time. If no such session was found - * within one year this method will return `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}). + * within one year this method will throw JavaException "NoSuchElementException". *

    * To find previous trading session of any type use this code: *

    session = session->getPrevSession(SessionFilter::TRADING);
    @@ -103,16 +107,16 @@ struct DXFCPP_EXPORT Session { *
    session = session->getPrevSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return The nearest previous session that is accepted by the filter or `Session::Ptr{nullptr}` - * (std::shared_ptr{nullptr}) if no such session was found within one year + * @return The nearest previous session that is accepted by the filter. + * @throw JavaException "NoSuchElementException" if no such session was found within one year. */ - Session::Ptr getPrevSession(const SessionFilter &filter) const noexcept; + Session::Ptr getPrevSession(const SessionFilter &filter) const; /** * Returns following session accepted by specified filter. * This method may cross the day boundary and return appropriate session from * following days - up to a year in the future. If no such session was found - * within one year this method will return `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}). + * within one year this method will throw JavaException "NoSuchElementException". *

    * To find following trading session of any type use this code: *

    session = session->getNextSession(SessionFilter::TRADING);
    @@ -120,11 +124,10 @@ struct DXFCPP_EXPORT Session { *
    session = session->getNextSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return The nearest following session that is accepted by the filter or `Session::Ptr{nullptr}` - * (std::shared_ptr{nullptr}) if no such - * session was found within one year + * @return The nearest following session that is accepted by the filter. + * @throw JavaException "NoSuchElementException" if no such session was found within one year. */ - Session::Ptr getNextSession(const SessionFilter &filter) const noexcept; + Session::Ptr getNextSession(const SessionFilter &filter) const; /** * Returns previous session accepted by specified filter. @@ -138,9 +141,9 @@ struct DXFCPP_EXPORT Session { *
    session = session->findPrevSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return nearest previous session that is accepted by the filter + * @return nearest previous session that is accepted by the filter or `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) */ - Session::Ptr findPrevSession(const SessionFilter &filter) const noexcept; + Session::Ptr findPrevSession(const SessionFilter &filter) const; /** * Returns following session accepted by specified filter. @@ -154,9 +157,9 @@ struct DXFCPP_EXPORT Session { *
    session = session->findNextSession(SessionFilter::REGULAR);
    * * @param filter The filter to test sessions - * @return nearest following session that is accepted by the filter + * @return nearest following session that is accepted by the filter or `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) */ - Session::Ptr findNextSession(const SessionFilter &filter) const noexcept; + Session::Ptr findNextSession(const SessionFilter &filter) const; /** * Returns `true` if this object is equal to `other` object @@ -164,7 +167,7 @@ struct DXFCPP_EXPORT Session { * @param other Another object * @return `true` if this object is equal to `other` object */ - bool operator==(const Session &other) const noexcept; + bool operator==(const Session &other) const; /** * Returns `true` if this object is equal to `other` object @@ -172,14 +175,14 @@ struct DXFCPP_EXPORT Session { * @param other Another object * @return `true` if this object is equal to `other` object */ - bool operator==(const Session::Ptr &other) const noexcept { + bool operator==(const Session::Ptr &other) const { return *this == *other; } /** * @return A hash code value for this object. */ - std::size_t getHashCode() const noexcept; + std::size_t getHashCode() const; /** * Returns a string representation of the current object. @@ -192,7 +195,7 @@ struct DXFCPP_EXPORT Session { DXFCPP_END_NAMESPACE template <> struct DXFCPP_EXPORT std::hash { - std::size_t operator()(const dxfcpp::Session &session) const noexcept { + std::size_t operator()(const dxfcpp::Session &session) const { return session.getHashCode(); } }; diff --git a/src/event/candle/CandleSession.cpp b/src/event/candle/CandleSession.cpp index ff1c25dd4..cd07465cd 100644 --- a/src/event/candle/CandleSession.cpp +++ b/src/event/candle/CandleSession.cpp @@ -23,8 +23,7 @@ const JavaObjectHandle &SessionFilter::getHandle() const & { std::lock_guard lock(mtx_); if (!handle_) { - handle_ = JavaObjectHandle( - isolated::schedule::SessionFilter::getInstance(static_cast(code_))); + handle_ = isolated::schedule::IsolatedSessionFilter::getInstance(static_cast(code_)); } return handle_; diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index afcdb4fe0..2051b548a 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -154,210 +154,6 @@ using NativeStringList = typename isolated::internal::NativeStringListWrapper(runIsolatedOrElse( - [](auto threadHandle, auto &&filter) { - return dxfg_SessionFilter_getInstance(static_cast(threadHandle), filter); - }, - nullptr, static_cast(code))); -} - -/* dxfg_day_t* */ void *Session::getDay(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_getDay(static_cast(threadHandle), session); - }, - nullptr, static_cast(session))); -} - -std::int32_t Session::getType(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_getType(static_cast(threadHandle), session); - }, - 0, static_cast(session)); -} - -bool Session::isTrading(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_isTrading(static_cast(threadHandle), session) == 1; - }, - false, static_cast(session)); -} - -bool Session::isEmpty(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_isEmpty(static_cast(threadHandle), session) == 1; - }, - false, static_cast(session)); -} - -std::int64_t Session::getStartTime(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_getStartTime(static_cast(threadHandle), session); - }, - 0, static_cast(session)); -} - -std::int64_t Session::getEndTime(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return 0; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_getEndTime(static_cast(threadHandle), session); - }, - 0, static_cast(session)); -} - -bool Session::containsTime(/* dxfg_session_t* */ void *session, std::int64_t time) noexcept { - if (!session) { - // TODO: Improve error handling - return false; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session, auto &&time) { - return dxfg_Session_containsTime(static_cast(threadHandle), session, time) == 1; - }, - false, static_cast(session), time); -} - -/* dxfg_session_t* */ void *Session::getPrevSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!session || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&session, auto &&filter) { - return dxfg_Session_getPrevSession(static_cast(threadHandle), session, filter); - }, - nullptr, static_cast(session), static_cast(filter))); -} - -/* dxfg_session_t* */ void *Session::getNextSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!session || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&session, auto &&filter) { - return dxfg_Session_getNextSession(static_cast(threadHandle), session, filter); - }, - nullptr, static_cast(session), static_cast(filter))); -} - -/* dxfg_session_t* */ void *Session::findPrevSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!session || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&session, auto &&filter) { - return dxfg_Session_findPrevSession(static_cast(threadHandle), session, filter); - }, - nullptr, static_cast(session), static_cast(filter))); -} - -/* dxfg_session_t* */ void *Session::findNextSession(/* dxfg_session_t* */ void *session, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!session || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&session, auto &&filter) { - return dxfg_Session_findNextSession(static_cast(threadHandle), session, filter); - }, - nullptr, static_cast(session), static_cast(filter))); -} - -std::size_t Session::getHashCode(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return dxfcpp::bit_cast(session); - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_hashCode(static_cast(threadHandle), session); - }, - 0, static_cast(session)); -} - -bool Session::equals(/* dxfg_session_t* */ void *session, /* dxfg_session_t* */ void *otherSession) noexcept { - if (!session || !otherSession) { - // TODO: Improve error handling - return false; - } - - if (session == otherSession) { - return true; - } - - return runIsolatedOrElse( - [](auto threadHandle, auto &&session, auto &&otherSession) { - return dxfg_Session_equals(static_cast(threadHandle), session, otherSession) == 1; - }, - false, static_cast(session), static_cast(otherSession)); -} - -std::string Session::toString(/* dxfg_session_t* */ void *session) noexcept { - if (!session) { - // TODO: Improve error handling - return dxfcpp::String::EMPTY; - } - - auto string = runIsolatedOrElse( - [](auto threadHandle, auto &&session) { - return dxfg_Session_toString(static_cast(threadHandle), session); - }, - nullptr, static_cast(session)); - - auto result = dxfcpp::toString(string); - - isolated::internal::IsolatedString::release(string); - - return result; -} - /* dxfg_schedule_t* */ void *Schedule::getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept { if (!instrumentProfile) { // TODO: Improve error handling diff --git a/src/ipf/live/IterableInstrumentProfile.cpp b/src/ipf/live/IterableInstrumentProfile.cpp index 5f766910e..206eea9e3 100644 --- a/src/ipf/live/IterableInstrumentProfile.cpp +++ b/src/ipf/live/IterableInstrumentProfile.cpp @@ -25,7 +25,7 @@ std::shared_ptr IterableInstrumentProfile::create(voi return std::shared_ptr(new IterableInstrumentProfile(handle)); } -[[nodiscard]] bool IterableInstrumentProfile::hasNext() const noexcept { +bool IterableInstrumentProfile::hasNext() const noexcept { if (!handle_) { return false; } @@ -33,11 +33,7 @@ std::shared_ptr IterableInstrumentProfile::create(voi return isolated::ipf::live::IsolatedInstrumentProfileIterator::hasNext(handle_.get()); } -[[nodiscard]] std::shared_ptr IterableInstrumentProfile::next() const { - if (!handle_) { - return {}; - } - +std::shared_ptr IterableInstrumentProfile::next() const { auto graalProfile = isolated::ipf::live::IsolatedInstrumentProfileIterator::next(handle_.get()); auto result = InstrumentProfile::create(JavaObjectHandle(graalProfile)); diff --git a/src/isolated/schedule/IsolatedDay.cpp b/src/isolated/schedule/IsolatedDay.cpp index efdcddc6f..8a7fe6e6f 100644 --- a/src/isolated/schedule/IsolatedDay.cpp +++ b/src/isolated/schedule/IsolatedDay.cpp @@ -20,25 +20,6 @@ namespace IsolatedDayFilter { } // namespace IsolatedDayFilter -// TODO: move to IsolatedSession -namespace IsolatedSessionList { - -bool release(/* dxfg_session_list* */ void *sessionList) { - if (!sessionList) { - throw InvalidArgumentException( - "Unable to execute function `dxfg_SessionList_wrapper_release`. The `sessionList` is nullptr"); - } - - return runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, - static_cast(sessionList)); -} - -std::unique_ptr toUnique(/* dxfg_session_list* */ void *sessionList) { - return {sessionList, release}; -} - -} // namespace IsolatedSessionList - namespace IsolatedDay { /* dxfg_schedule_t* */ JavaObjectHandle diff --git a/src/isolated/schedule/IsolatedSession.cpp b/src/isolated/schedule/IsolatedSession.cpp new file mode 100644 index 000000000..1064b0592 --- /dev/null +++ b/src/isolated/schedule/IsolatedSession.cpp @@ -0,0 +1,230 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::schedule { + +namespace IsolatedSessionFilter { + +/* dxfg_session_filter_t* */ JavaObjectHandle getInstance(std::uint32_t code) { + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_SessionFilter_getInstance, static_cast(code))}; +} + +}; // namespace IsolatedSessionFilter + +namespace IsolatedSession { + +/* dxfg_day_t* */ JavaObjectHandle +getDay(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getDay`. The `session` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Session_getDay, static_cast(session.get()))}; +} + +std::int32_t getType(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getType`. The `session` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_getType, static_cast(session.get())); +} + +bool isTrading(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_isTrading`. The `session` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_isTrading, static_cast(session.get())) == + 1; +} + +bool isEmpty(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_isEmpty`. The `session` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_isEmpty, static_cast(session.get())) == 1; +} + +std::int64_t getStartTime(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getStartTime`. The `session` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_getStartTime, static_cast(session.get())); +} + +std::int64_t getEndTime(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getEndTime`. The `session` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_getEndTime, static_cast(session.get())); +} + +bool containsTime(/* dxfg_session_t* */ const JavaObjectHandle &session, std::int64_t time) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_containsTime`. The `session` handle is invalid"); + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_containsTime, static_cast(session.get()), + time) == 1; +} + +/* dxfg_session_t* */ JavaObjectHandle +getPrevSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getPrevSession`. The `session` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getPrevSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Session_getPrevSession, static_cast(session.get()), + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +getNextSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getNextSession`. The `session` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getNextSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Session_getNextSession, static_cast(session.get()), + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +findPrevSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_findPrevSession`. The `session` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_findPrevSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Session_findPrevSession, static_cast(session.get()), + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +findNextSession(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_findNextSession`. The `session` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_findNextSession`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Session_findNextSession, static_cast(session.get()), + static_cast(filter.get()))}; +} + +std::size_t getHashCode(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_getHashCode`. The `session` handle is invalid"); + } + + return static_cast( + runGraalFunctionAndThrowIfMinusOne(dxfg_Session_hashCode, static_cast(session.get()))); +} + +bool equals(/* dxfg_session_t* */ const JavaObjectHandle &session, + /* dxfg_session_t* */ const JavaObjectHandle &otherSession) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_equals`. The `session` handle is invalid"); + } + + if (!otherSession) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_equals`. The `otherSession` handle is invalid"); + } + + if (session.get() == otherSession.get()) { + return true; + } + + return runGraalFunctionAndThrowIfMinusOne(dxfg_Session_equals, static_cast(session.get()), + static_cast(otherSession.get())) == 1; +} + +std::string toString(/* dxfg_session_t* */ const JavaObjectHandle &session) { + if (!session) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Session_toString`. The `session` handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique( + runGraalFunctionAndThrowIfNullptr(dxfg_Session_toString, static_cast(session.get()))); + + auto result = dxfcpp::toString(string.get()); + + return result; +} + +} // namespace IsolatedSession + +namespace IsolatedSessionList { + +bool release(/* dxfg_session_list* */ void *sessionList) { + if (!sessionList) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_SessionList_wrapper_release`. The `sessionList` is nullptr"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_SessionList_wrapper_release, + static_cast(sessionList)); +} + +std::unique_ptr toUnique(/* dxfg_session_list* */ void *sessionList) { + return {sessionList, IsolatedSessionList::release}; +} + +} // namespace IsolatedSessionList + +} // namespace isolated::schedule + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index 94406055f..8f6c21453 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -4,8 +4,16 @@ #include #include -#include -#include + +#include +#include +#include +#include +#include +#include + +#include +#include DXFCPP_BEGIN_NAMESPACE @@ -111,11 +119,23 @@ std::shared_ptr Day::getLastSession(const SessionFilter &filter) const } std::shared_ptr Day::findFirstSession(const SessionFilter &filter) const { - return Session::create(isolated::schedule::IsolatedDay::findFirstSession(handle_, filter.getHandle())); + auto sessionHandle = isolated::schedule::IsolatedDay::findFirstSession(handle_, filter.getHandle()); + + if (!sessionHandle) { + return {}; + } + + return Session::create(std::move(sessionHandle)); } std::shared_ptr Day::findLastSession(const SessionFilter &filter) const { - return Session::create(isolated::schedule::IsolatedDay::findLastSession(handle_, filter.getHandle())); + auto sessionHandle = isolated::schedule::IsolatedDay::findLastSession(handle_, filter.getHandle()); + + if (!sessionHandle) { + return {}; + } + + return Session::create(std::move(sessionHandle)); } Day::Ptr Day::getPrevDay(const DayFilter &filter) const { @@ -127,11 +147,23 @@ Day::Ptr Day::getNextDay(const DayFilter &filter) const { } Day::Ptr Day::findPrevDay(const DayFilter &filter) const { - return create(isolated::schedule::IsolatedDay::findPrevDay(handle_, filter.handle_)); + auto dayHandle = isolated::schedule::IsolatedDay::findPrevDay(handle_, filter.handle_); + + if (!dayHandle) { + return {}; + } + + return create(std::move(dayHandle)); } Day::Ptr Day::findNextDay(const DayFilter &filter) const { - return create(isolated::schedule::IsolatedDay::findNextDay(handle_, filter.handle_)); + auto dayHandle = isolated::schedule::IsolatedDay::findNextDay(handle_, filter.handle_); + + if (!dayHandle) { + return {}; + } + + return create(std::move(dayHandle)); } bool Day::operator==(const Day &other) const { diff --git a/src/schedule/Schedule.cpp b/src/schedule/Schedule.cpp index aae18221a..67f6b0119 100644 --- a/src/schedule/Schedule.cpp +++ b/src/schedule/Schedule.cpp @@ -55,15 +55,15 @@ std::vector Schedule::getTradingVenues(std::shared_ptr &data) noexcept { +bool Schedule::setDefaults(const std::vector &data) { return isolated::schedule::Schedule::setDefaults(data); } -Session::Ptr Schedule::getSessionByTime(std::int64_t time) const noexcept { +std::shared_ptr Schedule::getSessionByTime(std::int64_t time) const { if (!handle_) { return {}; } @@ -72,7 +72,7 @@ Session::Ptr Schedule::getSessionByTime(std::int64_t time) const noexcept { JavaObjectHandle{isolated::schedule::Schedule::getSessionByTime(handle_.get(), time)}); } -Day::Ptr Schedule::getDayByTime(std::int64_t time) const noexcept { +std::shared_ptr Schedule::getDayByTime(std::int64_t time) const { if (!handle_) { return {}; } @@ -80,7 +80,7 @@ Day::Ptr Schedule::getDayByTime(std::int64_t time) const noexcept { return Day::create(JavaObjectHandle{isolated::schedule::Schedule::getDayByTime(handle_.get(), time)}); } -Day::Ptr Schedule::getDayById(std::int32_t dayId) const noexcept { +std::shared_ptr Schedule::getDayById(std::int32_t dayId) const { if (!handle_) { return {}; } @@ -88,7 +88,7 @@ Day::Ptr Schedule::getDayById(std::int32_t dayId) const noexcept { return Day::create(JavaObjectHandle{isolated::schedule::Schedule::getDayById(handle_.get(), dayId)}); } -Day::Ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const noexcept { +std::shared_ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const { if (!handle_) { return {}; } @@ -97,7 +97,7 @@ Day::Ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const noexcep JavaObjectHandle{isolated::schedule::Schedule::getDayByYearMonthDay(handle_.get(), yearMonthDay)}); } -Session::Ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { +std::shared_ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const { if (!handle_ || !filter.getHandle()) { return {}; } @@ -106,7 +106,7 @@ Session::Ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionF isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.getHandle().get())}); } -Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const noexcept { +std::shared_ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const { if (!handle_ || !filter.getHandle()) { return {}; } @@ -115,7 +115,7 @@ Session::Ptr Schedule::findNearestSessionByTime(std::int64_t time, const Session isolated::schedule::Schedule::findNearestSessionByTime(handle_.get(), time, filter.getHandle().get())}); } -std::string Schedule::getName() const noexcept { +std::string Schedule::getName() const { if (!handle_) { return dxfcpp::String::EMPTY; } @@ -123,7 +123,7 @@ std::string Schedule::getName() const noexcept { return isolated::schedule::Schedule::getName(handle_.get()); } -std::string Schedule::getTimeZoneDisplayName() const noexcept { +std::string Schedule::getTimeZoneDisplayName() const { if (!handle_) { return dxfcpp::String::EMPTY; } @@ -131,7 +131,7 @@ std::string Schedule::getTimeZoneDisplayName() const noexcept { return isolated::schedule::Schedule::getTimeZoneDisplayName(handle_.get()); } -std::string Schedule::getTimeZoneId() const noexcept { +std::string Schedule::getTimeZoneId() const { if (!handle_) { return dxfcpp::String::EMPTY; } diff --git a/src/schedule/Session.cpp b/src/schedule/Session.cpp index e89c9e081..8fad6a16e 100644 --- a/src/schedule/Session.cpp +++ b/src/schedule/Session.cpp @@ -1,10 +1,16 @@ // Copyright (c) 2024 Devexperts LLC. // SPDX-License-Identifier: MPL-2.0 -#include - #include -#include + +#include +#include +#include +#include +#include +#include + +#include DXFCPP_BEGIN_NAMESPACE @@ -19,20 +25,12 @@ Session::Ptr Session::create(JavaObjectHandle &&handle) { return std::shared_ptr(new Session(std::move(handle))); } -Day::Ptr Session::getDay() const noexcept { - if (!handle_) { - return {}; - } - - return Day::create(JavaObjectHandle{isolated::schedule::Session::getDay(handle_.get())}); +std::shared_ptr Session::getDay() const { + return Day::create(isolated::schedule::IsolatedSession::getDay(handle_)); } -const SessionType &Session::getType() const & noexcept { - if (!handle_) { - return SessionType::NO_TRADING; - } - - switch (static_cast(isolated::schedule::Session::getType(handle_.get()))) { +const SessionType &Session::getType() const & { + switch (static_cast(isolated::schedule::IsolatedSession::getType(handle_))) { case SessionTypeEnum::NO_TRADING: return SessionType::NO_TRADING; case SessionTypeEnum::PRE_MARKET: @@ -46,108 +44,68 @@ const SessionType &Session::getType() const & noexcept { return SessionType::NO_TRADING; } -bool Session::isTrading() const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Session::isTrading(handle_.get()); +bool Session::isTrading() const { + return isolated::schedule::IsolatedSession::isTrading(handle_); } -bool Session::isEmpty() const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Session::isEmpty(handle_.get()); +bool Session::isEmpty() const { + return isolated::schedule::IsolatedSession::isEmpty(handle_); } -std::int64_t Session::getStartTime() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Session::getStartTime(handle_.get()); +std::int64_t Session::getStartTime() const { + return isolated::schedule::IsolatedSession::getStartTime(handle_); } -std::int64_t Session::getEndTime() const noexcept { - if (!handle_) { - return 0; - } - - return isolated::schedule::Session::getEndTime(handle_.get()); +std::int64_t Session::getEndTime() const { + return isolated::schedule::IsolatedSession::getEndTime(handle_); } -bool Session::containsTime(std::int64_t time) const noexcept { - if (!handle_) { - return false; - } - - return isolated::schedule::Session::containsTime(handle_.get(), time); +bool Session::containsTime(std::int64_t time) const { + return isolated::schedule::IsolatedSession::containsTime(handle_, time); } -Session::Ptr Session::getPrevSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(JavaObjectHandle{ - isolated::schedule::Session::getPrevSession(handle_.get(), filter.getHandle().get())}); +Session::Ptr Session::getPrevSession(const SessionFilter &filter) const { + return create(isolated::schedule::IsolatedSession::getPrevSession(handle_, filter.getHandle())); } -Session::Ptr Session::getNextSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(JavaObjectHandle{ - isolated::schedule::Session::getNextSession(handle_.get(), filter.getHandle().get())}); +Session::Ptr Session::getNextSession(const SessionFilter &filter) const { + return create(isolated::schedule::IsolatedSession::getNextSession(handle_, filter.getHandle())); } -Session::Ptr Session::findPrevSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { +Session::Ptr Session::findPrevSession(const SessionFilter &filter) const { + auto sessionHandle = isolated::schedule::IsolatedSession::findPrevSession(handle_, filter.getHandle()); + + if (!sessionHandle) { return {}; } - return Session::create(JavaObjectHandle{ - isolated::schedule::Session::findPrevSession(handle_.get(), filter.getHandle().get())}); + return create(std::move(sessionHandle)); } -Session::Ptr Session::findNextSession(const SessionFilter &filter) const noexcept { - if (!handle_ || !filter.getHandle()) { +Session::Ptr Session::findNextSession(const SessionFilter &filter) const { + auto sessionHandle = isolated::schedule::IsolatedSession::findNextSession(handle_, filter.getHandle()); + + if (!sessionHandle) { return {}; } - return Session::create(JavaObjectHandle{ - isolated::schedule::Session::findNextSession(handle_.get(), filter.getHandle().get())}); + return create(std::move(sessionHandle)); } -bool Session::operator==(const Session &other) const noexcept { - if (!handle_ || !other.handle_) { - return false; - } - +bool Session::operator==(const Session &other) const { if (this == &other) { return true; } - return isolated::schedule::Session::equals(handle_.get(), other.handle_.get()); + return isolated::schedule::IsolatedSession::equals(handle_, other.handle_); } -std::size_t Session::getHashCode() const noexcept { - if (!handle_) { - return dxfcpp::bit_cast(this); - } - - return isolated::schedule::Session::getHashCode(handle_.get()); +std::size_t Session::getHashCode() const { + return isolated::schedule::IsolatedSession::getHashCode(handle_); } std::string Session::toString() const { - if (!handle_) { - return dxfcpp::String::EMPTY; - } - - return isolated::schedule::Session::toString(handle_.get()); + return isolated::schedule::IsolatedSession::toString(handle_); } DXFCPP_END_NAMESPACE \ No newline at end of file From 41e0c5a88656bce965e6c45dd7f1dde1004beafd Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 19 Sep 2024 20:45:36 +0300 Subject: [PATCH 092/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. IsolatedSchedule --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 3 +- .../exceptions/GraalException.hpp | 2 + .../exceptions/InvalidArgumentException.hpp | 2 + .../exceptions/JavaException.hpp | 2 + .../exceptions/RuntimeException.hpp | 2 + .../isolated/Isolated.hpp | 56 ---- .../isolated/schedule/IsolatedSchedule.hpp | 67 +++++ .../schedule/Schedule.hpp | 53 ++-- samples/cpp/ScheduleSample/src/main.cpp | 4 +- src/api/DXEndpoint.cpp | 1 - src/exceptions/GraalException.cpp | 2 + src/exceptions/InvalidArgumentException.cpp | 2 + src/exceptions/JavaException.cpp | 36 +-- src/exceptions/RuntimeException.cpp | 4 +- src/internal/Isolate.cpp | 253 ------------------ src/ipf/live/InstrumentProfileCollector.cpp | 1 - .../ondemand/IsolatedOnDemandService.cpp | 1 - src/isolated/schedule/IsolatedSchedule.cpp | 199 ++++++++++++++ src/schedule/Schedule.cpp | 92 ++----- 20 files changed, 357 insertions(+), 426 deletions(-) delete mode 100644 include/dxfeed_graal_cpp_api/isolated/Isolated.hpp create mode 100644 include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSchedule.hpp create mode 100644 src/isolated/schedule/IsolatedSchedule.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d49c9afe..cb8b91198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/util/IsolatedTimePeriod.cpp src/isolated/schedule/IsolatedDay.cpp src/isolated/schedule/IsolatedSession.cpp + src/isolated/schedule/IsolatedSchedule.cpp ) set(dxFeedGraalCxxApi_Api_Sources diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index e824c7306..28436f611 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -50,8 +50,6 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "symbols/SymbolWrapper.hpp" #include "system/System.hpp" -#include "isolated/Isolated.hpp" - #include "exceptions/RuntimeException.hpp" #include "exceptions/InvalidArgumentException.hpp" #include "exceptions/JavaException.hpp" @@ -78,6 +76,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/util/IsolatedTimePeriod.hpp" #include "isolated/schedule/IsolatedDay.hpp" #include "isolated/schedule/IsolatedSession.hpp" +#include "isolated/schedule/IsolatedSchedule.hpp" #include "ondemand/OnDemandService.hpp" diff --git a/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp b/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp index 44424544f..50d4ab181 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/GraalException.hpp @@ -27,6 +27,8 @@ struct DXFCPP_EXPORT GraalException : RuntimeException { */ GraalException(CEntryPointErrorsEnum entryPointErrorsEnum); + GraalException(const GraalException& other) noexcept; + private: static inline std::string createMessage(CEntryPointErrorsEnum entryPointErrorsEnum) { auto result = CEntryPointErrorsEnumToStr(entryPointErrorsEnum); diff --git a/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp b/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp index 2ced4912b..32a958f2d 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/InvalidArgumentException.hpp @@ -21,6 +21,8 @@ DXFCPP_BEGIN_NAMESPACE struct DXFCPP_EXPORT InvalidArgumentException : RuntimeException { explicit InvalidArgumentException(const StringLikeWrapper &message, const StringLikeWrapper &additionalStackTrace = ""); + + InvalidArgumentException(const InvalidArgumentException& other) noexcept; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index b7648f676..a05f50823 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -32,6 +32,8 @@ struct DXFCPP_EXPORT JavaException : RuntimeException { JavaException(const StringLikeWrapper &message, const StringLikeWrapper &className, const StringLikeWrapper &stackTrace); + JavaException(const JavaException& other) noexcept; + /** * Creates an exception using native (GraalVM) Java exception handle * diff --git a/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp b/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp index 4c7bdb454..63634bc50 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/RuntimeException.hpp @@ -26,6 +26,8 @@ struct DXFCPP_EXPORT RuntimeException : std::runtime_error { */ explicit RuntimeException(const StringLikeWrapper& message, const StringLikeWrapper& additionalStackTrace = ""); + RuntimeException(const RuntimeException& other) noexcept; + /** * @return The current stacktrace + the additional stacktrace if present. */ diff --git a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp b/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp deleted file mode 100644 index 7c53063b9..000000000 --- a/include/dxfeed_graal_cpp_api/isolated/Isolated.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2024 Devexperts LLC. -// SPDX-License-Identifier: MPL-2.0 - -#pragma once - -#include "../internal/Conf.hpp" - -DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) - -#include "../internal/TimeFormat.hpp" - -#include "../api/DXEndpoint.hpp" - -#include "../ipf/live/InstrumentProfileConnection.hpp" - -#include -#include -#include -#include -#include - -DXFCPP_BEGIN_NAMESPACE - -namespace isolated { - -namespace schedule { - -struct Schedule { - static /* dxfg_schedule_t* */ void *getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept; - static /* dxfg_schedule_t* */ void *getInstance(const std::string &scheduleDefinition) noexcept; - static /* dxfg_schedule_t* */ void *getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile, - const std::string &venue) noexcept; - static std::vector getTradingVenues(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept; - static void downloadDefaults(const std::string &downloadConfig) noexcept; - static bool setDefaults(const std::vector &data) noexcept; - static /* dxfg_session_t* */ void *getSessionByTime(/* dxfg_schedule_t* */ void *schedule, - std::int64_t time) noexcept; - static /* dxfg_day_t* */ void *getDayByTime(/* dxfg_schedule_t* */ void *schedule, std::int64_t time) noexcept; - static /* dxfg_day_t* */ void *getDayById(/* dxfg_schedule_t* */ void *schedule, std::int32_t dayId) noexcept; - static /* dxfg_day_t* */ void *getDayByYearMonthDay(/* dxfg_schedule_t* */ void *schedule, - std::int32_t yearMonthDay) noexcept; - static /* dxfg_session_t* */ void *getNearestSessionByTime(/* dxfg_schedule_t* */ void *schedule, std::int64_t time, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static /* dxfg_session_t* */ void *findNearestSessionByTime(/* dxfg_schedule_t* */ void *schedule, - std::int64_t time, - /* dxfg_session_filter_t* */ void *filter) noexcept; - static std::string getName(/* dxfg_schedule_t* */ void *schedule) noexcept; - static std::string getTimeZoneDisplayName(/* dxfg_schedule_t* */ void *schedule) noexcept; - static std::string getTimeZoneId(/* dxfg_schedule_t* */ void *schedule) noexcept; -}; -} // namespace schedule -} // namespace isolated - -DXFCPP_END_NAMESPACE - -DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSchedule.hpp b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSchedule.hpp new file mode 100644 index 000000000..f0d4f75c8 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/schedule/IsolatedSchedule.hpp @@ -0,0 +1,67 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +#include "../../schedule/Schedule.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::schedule { + +namespace IsolatedSchedule { + +/* dxfg_schedule_t* */ JavaObjectHandle +getInstance(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &instrumentProfile); + +/* dxfg_schedule_t* */ JavaObjectHandle getInstance(const StringLikeWrapper &scheduleDefinition); + +/* dxfg_schedule_t* */ JavaObjectHandle +getInstance(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &instrumentProfile, + const StringLikeWrapper &venue); + +std::vector +getTradingVenues(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &instrumentProfile); + +void downloadDefaults(const StringLikeWrapper &downloadConfig); + +void setDefaults(const std::vector &data); + +/* dxfg_session_t* */ JavaObjectHandle +getSessionByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time); + +/* dxfg_day_t* */ JavaObjectHandle +getDayByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time); + +/* dxfg_day_t* */ JavaObjectHandle +getDayById(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int32_t dayId); + +/* dxfg_day_t* */ JavaObjectHandle +getDayByYearMonthDay(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, + std::int32_t yearMonthDay); + +/* dxfg_session_t* */ JavaObjectHandle +getNearestSessionByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +/* dxfg_session_t* */ JavaObjectHandle +findNearestSessionByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter); + +std::string getName(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule); + +std::string getTimeZoneDisplayName(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule); + +std::string getTimeZoneId(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule); + +} // namespace IsolatedSchedule + +} // namespace isolated::schedule + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp b/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp index 2d4f314e4..7ca356fbe 100644 --- a/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/Schedule.hpp @@ -12,6 +12,7 @@ DXFCPP_BEGIN_NAMESPACE struct InstrumentProfile; struct Day; struct Session; +struct StringLikeWrapper; /** * Schedule class provides API to retrieve and explore trading schedules of different exchanges @@ -57,7 +58,7 @@ struct DXFCPP_EXPORT Schedule { * @param scheduleDefinition The schedule definition of requested schedule * @return The default schedule instance for specified schedule definition */ - static Schedule::Ptr getInstance(const std::string &scheduleDefinition); + static Schedule::Ptr getInstance(const StringLikeWrapper &scheduleDefinition); /** * Returns schedule instance for specified instrument profile and trading venue. @@ -66,7 +67,7 @@ struct DXFCPP_EXPORT Schedule { * @param venue The trading venue those schedule is requested * @return The schedule instance for specified instrument profile and trading venue */ - static Schedule::Ptr getInstance(std::shared_ptr profile, const std::string &venue); + static Schedule::Ptr getInstance(std::shared_ptr profile, const StringLikeWrapper &venue); /** * Returns trading venues for specified instrument profile. @@ -87,46 +88,48 @@ struct DXFCPP_EXPORT Schedule { * * @param downloadConfig download config */ - static void downloadDefaults(const std::string &downloadConfig); + static void downloadDefaults(const StringLikeWrapper &downloadConfig); /** * Sets shared defaults that are used by individual schedule instances. * * @param data The content of default data - * @return `true` if OK */ - static bool setDefaults(const std::vector &data); + static void setDefaults(const std::vector &data); /** * Returns session that contains specified time. - * This method will return `Session::Ptr{nullptr}` if specified time + * This method will throw JavaException "IllegalArgumentException" if specified time * falls outside of valid date range from 0001-01-02 to 9999-12-30. * * @param time the time to search for * @return session that contains specified time or `Session::Ptr{nullptr}` if specified time * falls outside of valid date range from 0001-01-02 to 9999-12-30. + * + * @throw JavaException "IllegalArgumentException" if specified time falls outside of valid date range + * @throw JavaException "NoSuchElementException" if no such session was found within this day */ std::shared_ptr getSessionByTime(std::int64_t time) const; /** * Returns day that contains specified time. - * This method will return `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time - * falls outside of valid date range from 0001-01-02 to 9999-12-30. + * This method will throw JavaException "IllegalArgumentException" if specified time falls outside of valid date + * range from 0001-01-02 to 9999-12-30. * * @param time The time to search for - * @return The day that contains specified time or `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) if - * specified time falls outside of valid date range + * @return The day that contains specified time + * @throw JavaException "IllegalArgumentException" if specified time falls outside of valid date range */ std::shared_ptr getDayByTime(std::int64_t time) const; /** * Returns day for specified day identifier. - * This method will return `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified day identifier + * This method will throw JavaException "IllegalArgumentException" if specified day identifier * falls outside of valid date range from 0001-01-02 to 9999-12-30. * * @param dayId The day identifier to search for - * @return The day for specified day identifier or `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) if - * specified day identifier falls outside of valid date range + * @return The day for specified day identifier + * @throw JavaException "IllegalArgumentException" if specified day identifier falls outside of valid date range * @see Day::getDayId() */ std::shared_ptr getDayById(std::int32_t dayId) const; @@ -139,21 +142,21 @@ struct DXFCPP_EXPORT Schedule { *

    * If specified day does not exist then this method returns day with * the lowest valid YearMonthDay that is greater than specified one. - * This method will return `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified year, month and day + * This method will throw JavaException "IllegalArgumentException" if specified year, month and day * numbers fall outside of valid date range from 0001-01-02 to 9999-12-30. * * @param yearMonthDay The year, month and day numbers to search for - * @return The day for specified year, month and day numbers or `Day::Ptr{nullptr}` (std::shared_ptr{nullptr}) - * if specified year, month and day numbers fall outside of valid date range + * @return The day for specified year, month and day numbers + * @throw JavaException "IllegalArgumentException" if specified year, month and day numbers fall outside of valid date range * @see Day#getYearMonthDay() */ std::shared_ptr getDayByYearMonthDay(std::int32_t yearMonthDay) const; /** * Returns session that is nearest to the specified time and that is accepted by specified filter. - * This method will return `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time falls - * outside of valid date range from 0001-01-02 to 9999-12-30 or if no sessions acceptable by specified filter are - * found within one year this method + * This method will throw JavaException "IllegalArgumentException" if specified time falls + * outside of valid date range from 0001-01-02 to 9999-12-30. If no sessions acceptable by specified filter are + * found within one year this method this method will throw JavaException "NoSuchElementException". *

    To find nearest trading session of any type use this code: *

    session = schedule->getNearestSessionByTime(time, SessionFilter::TRADING);
    * To find nearest regular trading session use this code: @@ -161,15 +164,15 @@ struct DXFCPP_EXPORT Schedule { * * @param time The time to search for * @param filter the filter to test sessions - * @return session that is nearest to the specified time and that is accepted by specified filter or - * `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time falls outside of valid date range - * or if no such day was found within one year + * @return session that is nearest to the specified time and that is accepted by specified filter. + * @throw JavaException "IllegalArgumentException" if specified time falls outside of valid date range + * @throw JavaException "NoSuchElementException" if no such day was found within one year */ std::shared_ptr getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const; /** * Returns session that is nearest to the specified time and that is accepted by specified filter. - * This method will return `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time + * This method will throw JavaException "IllegalArgumentException" if specified time * falls outside of valid date range from 0001-01-02 to 9999-12-30. * If no sessions acceptable by specified filter are found within one year this method will return * `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}). @@ -181,8 +184,8 @@ struct DXFCPP_EXPORT Schedule { * * @param time The time to search for * @param filter The filter to test sessions - * @return The session that is nearest to the specified time and that is accepted by specified filter or - * `Session::Ptr{nullptr}` (std::shared_ptr{nullptr}) if specified time falls outside of valid date range + * @return The session that is nearest to the specified time and that is accepted by specified filter. + * @throw JavaException "IllegalArgumentException" if specified time falls outside of valid date range */ std::shared_ptr findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const; diff --git a/samples/cpp/ScheduleSample/src/main.cpp b/samples/cpp/ScheduleSample/src/main.cpp index f60b6b268..652872c57 100644 --- a/samples/cpp/ScheduleSample/src/main.cpp +++ b/samples/cpp/ScheduleSample/src/main.cpp @@ -34,9 +34,7 @@ void updateScheduleDefaults(const std::string &url) { std::vector buffer(std::istreambuf_iterator{is}, {}); - if (Schedule::setDefaults(buffer)) { - std::cout << "Schedule defaults updated successfully" << std::endl; - } + Schedule::setDefaults(buffer); } std::unordered_map> loadInstrumentProfiles(const std::string &url) { diff --git a/src/api/DXEndpoint.cpp b/src/api/DXEndpoint.cpp index 2be43b6a0..be058e665 100644 --- a/src/api/DXEndpoint.cpp +++ b/src/api/DXEndpoint.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include diff --git a/src/exceptions/GraalException.cpp b/src/exceptions/GraalException.cpp index 9a1ee17cf..58173c2ad 100644 --- a/src/exceptions/GraalException.cpp +++ b/src/exceptions/GraalException.cpp @@ -16,4 +16,6 @@ GraalException::GraalException(CEntryPointErrorsEnum entryPointErrorsEnum) : RuntimeException(createMessage(entryPointErrorsEnum)) { } +GraalException::GraalException(const GraalException& other) noexcept = default; + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/exceptions/InvalidArgumentException.cpp b/src/exceptions/InvalidArgumentException.cpp index 96575ef46..55d50e15d 100644 --- a/src/exceptions/InvalidArgumentException.cpp +++ b/src/exceptions/InvalidArgumentException.cpp @@ -13,4 +13,6 @@ InvalidArgumentException::InvalidArgumentException(const StringLikeWrapper &mess : RuntimeException(message, additionalStackTrace) { } +InvalidArgumentException::InvalidArgumentException(const InvalidArgumentException& other) noexcept = default; + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 9f489c679..489ee93dd 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -12,6 +12,24 @@ DXFCPP_BEGIN_NAMESPACE std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace); +JavaException::JavaException(const StringLikeWrapper &message, const StringLikeWrapper &className, + const StringLikeWrapper &stackTrace) + : RuntimeException(fmt::format("Java exception of type '{}' was thrown. {}", className.c_str(), message.c_str()), + stackTrace) { +} + +JavaException::JavaException(const JavaException& other) noexcept = default; + +JavaException JavaException::create(void *exceptionHandle) { + if (exceptionHandle == nullptr) { + return {"null", "", ""}; + } + + auto *exception = dxfcpp::bit_cast(exceptionHandle); + + return {toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)}; +} + void JavaException::throwIfJavaThreadExceptionExists() { dxfg_exception_t *exception = runIsolatedThrow([](auto threadHandle) { return dxfg_get_and_clear_thread_exception_t(static_cast(threadHandle)); @@ -21,7 +39,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { return; } - auto javaException = create(exception); + thread_local auto javaException = create(exception); runIsolatedThrow( [](auto threadHandle, auto &&...params) { @@ -38,20 +56,4 @@ void JavaException::throwException() { }); } -JavaException::JavaException(const StringLikeWrapper &message, const StringLikeWrapper &className, - const StringLikeWrapper &stackTrace) - : RuntimeException(fmt::format("Java exception of type '{}' was thrown. {}", className.c_str(), message.c_str()), - stackTrace) { -} - -JavaException JavaException::create(void *exceptionHandle) { - if (exceptionHandle == nullptr) { - return {"null", "", ""}; - } - - auto *exception = dxfcpp::bit_cast(exceptionHandle); - - return {toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)}; -} - DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/exceptions/RuntimeException.cpp b/src/exceptions/RuntimeException.cpp index 0e6ae776a..c4b67b8e9 100644 --- a/src/exceptions/RuntimeException.cpp +++ b/src/exceptions/RuntimeException.cpp @@ -64,12 +64,14 @@ std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace) } RuntimeException::RuntimeException(const StringLikeWrapper &message, const StringLikeWrapper &additionalStackTrace) - : runtime_error(message.c_str()), + : std::runtime_error(message.c_str()), stackTrace_(additionalStackTrace.empty() ? stackTraceToString(boost::stacktrace::stacktrace()) : fmt::format("{}\n{}", additionalStackTrace.c_str(), stackTraceToString(boost::stacktrace::stacktrace()))) { } +RuntimeException::RuntimeException(const RuntimeException& other) noexcept = default; + const std::string &RuntimeException::getStackTrace() const & { return stackTrace_; } diff --git a/src/internal/Isolate.cpp b/src/internal/Isolate.cpp index 2051b548a..7f3fc0c27 100644 --- a/src/internal/Isolate.cpp +++ b/src/internal/Isolate.cpp @@ -134,257 +134,4 @@ GraalIsolateThreadHandle Isolate::get() noexcept { return static_cast(graal_get_current_thread(dxfcpp::bit_cast(handle_))); } -// see isolated/isolated.hpp - -namespace isolated { - -constexpr auto equalsToZero = [](auto result) { - return result == 0; -}; - -constexpr auto runGraalFunction(auto resultCheckerConverter, auto graalFunction, auto defaultValue, auto &&...params) { - return runIsolatedOrElse( - [](auto threadHandle, auto &&resultCheckerConverter, auto &&graalFunction, auto &&...params) { - return resultCheckerConverter(graalFunction(static_cast(threadHandle), params...)); - }, - defaultValue, resultCheckerConverter, graalFunction, params...); -} - -using NativeStringList = typename isolated::internal::NativeStringListWrapper; - -namespace schedule { - -/* dxfg_schedule_t* */ void *Schedule::getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept { - if (!instrumentProfile) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&instrumentProfile) { - return dxfg_Schedule_getInstance(static_cast(threadHandle), instrumentProfile); - }, - nullptr, static_cast(instrumentProfile))); -} - -/* dxfg_schedule_t* */ void *Schedule::getInstance(const std::string &scheduleDefinition) noexcept { - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&scheduleDefinition) { - return dxfg_Schedule_getInstance2(static_cast(threadHandle), - scheduleDefinition.c_str()); - }, - nullptr, scheduleDefinition)); -} - -/* dxfg_schedule_t* */ void *Schedule::getInstance(/* dxfg_instrument_profile_t* */ void *instrumentProfile, - const std::string &venue) noexcept { - if (!instrumentProfile) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&instrumentProfile, auto &&venue) { - return dxfg_Schedule_getInstance3(static_cast(threadHandle), instrumentProfile, - venue.c_str()); - }, - nullptr, static_cast(instrumentProfile), venue)); -} - -std::vector Schedule::getTradingVenues(/* dxfg_instrument_profile_t* */ void *instrumentProfile) noexcept { - std::vector result{}; - - if (!instrumentProfile) { - // TODO: Improve error handling - return result; - } - - auto graalStringList = runIsolatedOrElse( - [](auto threadHandle, auto &&instrumentProfile) { - return dxfg_Schedule_getTradingVenues(static_cast(threadHandle), - instrumentProfile); - }, - nullptr, static_cast(instrumentProfile)); - - if (!graalStringList) { - // TODO: Improve error handling - return result; - } - - for (auto i = 0; i < graalStringList->size; i++) { - result.push_back(dxfcpp::toString(graalStringList->elements[i])); - } - - isolated::internal::IsolatedStringList::release(graalStringList); - - return result; -} - -void Schedule::downloadDefaults(const std::string &downloadConfig) noexcept { - runIsolatedOrElse( - [](auto threadHandle, auto &&downloadConfig) { - return dxfg_Schedule_downloadDefaults(static_cast(threadHandle), - downloadConfig.c_str()) == 0; - }, - false, downloadConfig); -} - -bool Schedule::setDefaults(const std::vector &data) noexcept { - return runIsolatedOrElse( - [](auto threadHandle, auto &&data) { - auto size = data.size() > std::numeric_limits::max() - ? std::numeric_limits::max() - : static_cast(data.size()); - - return dxfg_Schedule_setDefaults(static_cast(threadHandle), data.data(), size) == - 0; - }, - false, data); -} - -/* dxfg_session_t* */ void *Schedule::getSessionByTime(/* dxfg_schedule_t* */ void *schedule, - std::int64_t time) noexcept { - if (!schedule) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&schedule, auto &&time) { - return dxfg_Schedule_getSessionByTime(static_cast(threadHandle), schedule, time); - }, - nullptr, static_cast(schedule), time)); -} - -/* dxfg_day_t* */ void *Schedule::getDayByTime(/* dxfg_schedule_t* */ void *schedule, std::int64_t time) noexcept { - if (!schedule) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&schedule, auto &&time) { - return dxfg_Schedule_getDayByTime(static_cast(threadHandle), schedule, time); - }, - nullptr, static_cast(schedule), time)); -} - -/* dxfg_day_t* */ void *Schedule::getDayById(/* dxfg_schedule_t* */ void *schedule, std::int32_t dayId) noexcept { - if (!schedule) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&schedule, auto &&dayId) { - return dxfg_Schedule_getDayById(static_cast(threadHandle), schedule, dayId); - }, - nullptr, static_cast(schedule), dayId)); -} - -/* dxfg_day_t* */ void *Schedule::getDayByYearMonthDay(/* dxfg_schedule_t* */ void *schedule, - std::int32_t yearMonthDay) noexcept { - if (!schedule) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&schedule, auto &&yearMonthDay) { - return dxfg_Schedule_getDayByYearMonthDay(static_cast(threadHandle), schedule, - yearMonthDay); - }, - nullptr, static_cast(schedule), yearMonthDay)); -} - -/* dxfg_session_t* */ void *Schedule::getNearestSessionByTime(/* dxfg_schedule_t* */ void *schedule, std::int64_t time, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!schedule || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&schedule, auto &&time, auto &&filter) { - return dxfg_Schedule_getNearestSessionByTime(static_cast(threadHandle), schedule, - time, filter); - }, - nullptr, static_cast(schedule), time, static_cast(filter))); -} - -/* dxfg_session_t* */ void *Schedule::findNearestSessionByTime(/* dxfg_schedule_t* */ void *schedule, std::int64_t time, - /* dxfg_session_filter_t* */ void *filter) noexcept { - if (!schedule || !filter) { - // TODO: Improve error handling - return nullptr; - } - - return static_cast(runIsolatedOrElse( - [](auto threadHandle, auto &&schedule, auto &&time, auto &&filter) { - return dxfg_Schedule_findNearestSessionByTime(static_cast(threadHandle), schedule, - time, filter); - }, - nullptr, static_cast(schedule), time, static_cast(filter))); -} - -std::string Schedule::getName(/* dxfg_schedule_t* */ void *schedule) noexcept { - if (!schedule) { - // TODO: Improve error handling - return dxfcpp::String::EMPTY; - } - - auto string = runIsolatedOrElse( - [](auto threadHandle, auto &&schedule) { - return dxfg_Schedule_getName(static_cast(threadHandle), schedule); - }, - nullptr, static_cast(schedule)); - - auto result = dxfcpp::toString(string); - - isolated::internal::IsolatedString::release(string); - - return result; -} - -std::string Schedule::getTimeZoneDisplayName(/* dxfg_schedule_t* */ void *schedule) noexcept { - if (!schedule) { - // TODO: Improve error handling - return dxfcpp::String::EMPTY; - } - - auto string = runIsolatedOrElse( - [](auto threadHandle, auto &&schedule) { - return dxfg_Schedule_getTimeZone(static_cast(threadHandle), schedule); - }, - nullptr, static_cast(schedule)); - - auto result = dxfcpp::toString(string); - - isolated::internal::IsolatedString::release(string); - - return result; -} - -std::string Schedule::getTimeZoneId(/* dxfg_schedule_t* */ void *schedule) noexcept { - if (!schedule) { - // TODO: Improve error handling - return dxfcpp::String::EMPTY; - } - - auto string = runIsolatedOrElse( - [](auto threadHandle, auto &&schedule) { - return dxfg_Schedule_getTimeZone_getID(static_cast(threadHandle), schedule); - }, - nullptr, static_cast(schedule)); - - auto result = dxfcpp::toString(string); - - isolated::internal::IsolatedString::release(string); - - return result; -} - -} // namespace schedule -} // namespace isolated - DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/ipf/live/InstrumentProfileCollector.cpp b/src/ipf/live/InstrumentProfileCollector.cpp index 823345209..5b8eaad75 100644 --- a/src/ipf/live/InstrumentProfileCollector.cpp +++ b/src/ipf/live/InstrumentProfileCollector.cpp @@ -1,7 +1,6 @@ // Copyright (c) 2024 Devexperts LLC. // SPDX-License-Identifier: MPL-2.0 -#include "dxfeed_graal_cpp_api/isolated/Isolated.hpp" #include #include diff --git a/src/isolated/ondemand/IsolatedOnDemandService.cpp b/src/isolated/ondemand/IsolatedOnDemandService.cpp index 8db0d3534..7adc52486 100644 --- a/src/isolated/ondemand/IsolatedOnDemandService.cpp +++ b/src/isolated/ondemand/IsolatedOnDemandService.cpp @@ -4,7 +4,6 @@ #include #include -#include #include DXFCPP_BEGIN_NAMESPACE diff --git a/src/isolated/schedule/IsolatedSchedule.cpp b/src/isolated/schedule/IsolatedSchedule.cpp new file mode 100644 index 000000000..ec2d7e16b --- /dev/null +++ b/src/isolated/schedule/IsolatedSchedule.cpp @@ -0,0 +1,199 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::schedule { + +namespace IsolatedSchedule { + +/* dxfg_schedule_t* */ JavaObjectHandle +getInstance(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &instrumentProfile) { + if (!instrumentProfile) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getInstance`. The `instrumentProfile` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getInstance, static_cast(instrumentProfile.get()))}; +} + +/* dxfg_schedule_t* */ JavaObjectHandle getInstance(const StringLikeWrapper &scheduleDefinition) { + return JavaObjectHandle{ + runGraalFunctionAndThrowIfNullptr(dxfg_Schedule_getInstance2, scheduleDefinition.c_str())}; +} + +/* dxfg_schedule_t* */ JavaObjectHandle +getInstance(/* dxfg_instrument_profile_t* */ const JavaObjectHandle &instrumentProfile, + const StringLikeWrapper &venue) { + if (!instrumentProfile) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getInstance3`. The `instrumentProfile` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getInstance3, static_cast(instrumentProfile.get()), venue.c_str())}; +} + +std::vector getTradingVenues( + /* dxfg_instrument_profile_t* */ const JavaObjectHandle &instrumentProfile) { + if (!instrumentProfile) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getTradingVenues`. The `instrumentProfile` handle is invalid"); + } + + auto venues = isolated::internal::IsolatedStringList::toUnique(runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getTradingVenues, static_cast(instrumentProfile.get()))); + + std::vector result{}; + + for (auto i = 0; i < static_cast(venues.get())->size; i++) { + result.push_back(dxfcpp::toString(static_cast(venues.get())->elements[i])); + } + + return result; +} + +void downloadDefaults(const StringLikeWrapper &downloadConfig) { + runGraalFunctionAndThrowIfMinusOne(dxfg_Schedule_downloadDefaults, downloadConfig.c_str()); +} + +void setDefaults(const std::vector &data) { + runGraalFunctionAndThrowIfMinusOne(dxfg_Schedule_setDefaults, data.data(), fitToType(data.size())); +} + +/* dxfg_session_t* */ JavaObjectHandle +getSessionByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getSessionByTime`. The `schedule` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getSessionByTime, static_cast(schedule.get()), time)}; +} + +/* dxfg_day_t* */ JavaObjectHandle +getDayByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getDayByTime`. The `schedule` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getDayByTime, static_cast(schedule.get()), time)}; +} + +/* dxfg_day_t* */ JavaObjectHandle +getDayById(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int32_t dayId) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getDayById`. The `schedule` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getDayById, static_cast(schedule.get()), dayId)}; +} + +/* dxfg_day_t* */ JavaObjectHandle +getDayByYearMonthDay(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, + std::int32_t yearMonthDay) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getDayByYearMonthDay`. The `schedule` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getDayByYearMonthDay, static_cast(schedule.get()), yearMonthDay)}; +} + +/* dxfg_session_t* */ JavaObjectHandle +getNearestSessionByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getNearestSessionByTime`. The `schedule` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getNearestSessionByTime`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_getNearestSessionByTime, static_cast(schedule.get()), time, + static_cast(filter.get()))}; +} + +/* dxfg_session_t* */ JavaObjectHandle +findNearestSessionByTime(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule, std::int64_t time, + /* dxfg_session_filter_t* */ const JavaObjectHandle &filter) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_findNearestSessionByTime`. The `schedule` handle is invalid"); + } + + if (!filter) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_findNearestSessionByTime`. The `filter` handle is invalid"); + } + + return JavaObjectHandle{runGraalFunctionAndThrowIfNullptr( + dxfg_Schedule_findNearestSessionByTime, static_cast(schedule.get()), time, + static_cast(filter.get()))}; +} + +std::string getName(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getName`. The `schedule` handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique( + runGraalFunctionAndThrowIfNullptr(dxfg_Schedule_getName, static_cast(schedule.get()))); + + auto result = dxfcpp::toString(string.get()); + + return result; +} + +std::string getTimeZoneDisplayName(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getTimeZone`. The `schedule` handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique( + runGraalFunctionAndThrowIfNullptr(dxfg_Schedule_getTimeZone, static_cast(schedule.get()))); + + auto result = dxfcpp::toString(string.get()); + + return result; +} + +std::string getTimeZoneId(/* dxfg_schedule_t* */ const JavaObjectHandle &schedule) { + if (!schedule) { + throw InvalidArgumentException( + "Unable to execute function `dxfg_Schedule_getTimeZone_getID`. The `schedule` handle is invalid"); + } + + const auto string = internal::IsolatedString::toUnique( + runGraalFunctionAndThrowIfNullptr(dxfg_Schedule_getTimeZone_getID, static_cast(schedule.get()))); + + auto result = dxfcpp::toString(string.get()); + + return result; +} + + +} // namespace IsolatedSchedule + +} // namespace isolated::schedule + +DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/schedule/Schedule.cpp b/src/schedule/Schedule.cpp index 67f6b0119..fe38d18d9 100644 --- a/src/schedule/Schedule.cpp +++ b/src/schedule/Schedule.cpp @@ -21,28 +21,22 @@ Schedule::Ptr Schedule::create(JavaObjectHandle &&handle) { Schedule::Ptr Schedule::getInstance(std::shared_ptr profile) { if (!profile) { - throw InvalidArgumentException("The profile is nullptr"); + throw InvalidArgumentException("The `profile` is nullptr"); } - auto schedule = - create(JavaObjectHandle{isolated::schedule::Schedule::getInstance(profile->handle_.get())}); - - return schedule; + return create(isolated::schedule::IsolatedSchedule::getInstance(profile->handle_)); } -Schedule::Ptr Schedule::getInstance(const std::string &scheduleDefinition) { - return create(JavaObjectHandle{isolated::schedule::Schedule::getInstance(scheduleDefinition)}); +Schedule::Ptr Schedule::getInstance(const StringLikeWrapper &scheduleDefinition) { + return create(isolated::schedule::IsolatedSchedule::getInstance(scheduleDefinition)); } -Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, const std::string &venue) { +Schedule::Ptr Schedule::getInstance(std::shared_ptr profile, const StringLikeWrapper &venue) { if (!profile) { - throw InvalidArgumentException("The profile is nullptr"); + throw InvalidArgumentException("The `profile` is nullptr"); } - auto schedule = - create(JavaObjectHandle{isolated::schedule::Schedule::getInstance(profile->handle_.get(), venue)}); - - return schedule; + return create(isolated::schedule::IsolatedSchedule::getInstance(profile->handle_, venue)); } std::vector Schedule::getTradingVenues(std::shared_ptr profile) { @@ -50,93 +44,59 @@ std::vector Schedule::getTradingVenues(std::shared_ptrhandle_.get()); - - return result; + return isolated::schedule::IsolatedSchedule::getTradingVenues(profile->handle_); } -void Schedule::downloadDefaults(const std::string &downloadConfig) { - isolated::schedule::Schedule::downloadDefaults(downloadConfig); +void Schedule::downloadDefaults(const StringLikeWrapper &downloadConfig) { + isolated::schedule::IsolatedSchedule::downloadDefaults(downloadConfig); } -bool Schedule::setDefaults(const std::vector &data) { - return isolated::schedule::Schedule::setDefaults(data); +void Schedule::setDefaults(const std::vector &data) { + return isolated::schedule::IsolatedSchedule::setDefaults(data); } std::shared_ptr Schedule::getSessionByTime(std::int64_t time) const { - if (!handle_) { - return {}; - } - - return Session::create( - JavaObjectHandle{isolated::schedule::Schedule::getSessionByTime(handle_.get(), time)}); + return Session::create(isolated::schedule::IsolatedSchedule::getSessionByTime(handle_, time)); } std::shared_ptr Schedule::getDayByTime(std::int64_t time) const { - if (!handle_) { - return {}; - } - - return Day::create(JavaObjectHandle{isolated::schedule::Schedule::getDayByTime(handle_.get(), time)}); + return Day::create(isolated::schedule::IsolatedSchedule::getDayByTime(handle_, time)); } std::shared_ptr Schedule::getDayById(std::int32_t dayId) const { - if (!handle_) { - return {}; - } - - return Day::create(JavaObjectHandle{isolated::schedule::Schedule::getDayById(handle_.get(), dayId)}); + return Day::create(isolated::schedule::IsolatedSchedule::getDayById(handle_, dayId)); } std::shared_ptr Schedule::getDayByYearMonthDay(std::int32_t yearMonthDay) const { - if (!handle_) { - return {}; - } - - return Day::create( - JavaObjectHandle{isolated::schedule::Schedule::getDayByYearMonthDay(handle_.get(), yearMonthDay)}); + return Day::create(isolated::schedule::IsolatedSchedule::getDayByYearMonthDay(handle_, yearMonthDay)); } std::shared_ptr Schedule::getNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const { - if (!handle_ || !filter.getHandle()) { - return {}; - } - - return Session::create(JavaObjectHandle{ - isolated::schedule::Schedule::getNearestSessionByTime(handle_.get(), time, filter.getHandle().get())}); + return Session::create( + isolated::schedule::IsolatedSchedule::getNearestSessionByTime(handle_, time, filter.getHandle())); } std::shared_ptr Schedule::findNearestSessionByTime(std::int64_t time, const SessionFilter &filter) const { - if (!handle_ || !filter.getHandle()) { + auto sessionHandle = + isolated::schedule::IsolatedSchedule::findNearestSessionByTime(handle_, time, filter.getHandle()); + + if (!sessionHandle) { return {}; } - return Session::create(JavaObjectHandle{ - isolated::schedule::Schedule::findNearestSessionByTime(handle_.get(), time, filter.getHandle().get())}); + return Session::create(std::move(sessionHandle)); } std::string Schedule::getName() const { - if (!handle_) { - return dxfcpp::String::EMPTY; - } - - return isolated::schedule::Schedule::getName(handle_.get()); + return isolated::schedule::IsolatedSchedule::getName(handle_); } std::string Schedule::getTimeZoneDisplayName() const { - if (!handle_) { - return dxfcpp::String::EMPTY; - } - - return isolated::schedule::Schedule::getTimeZoneDisplayName(handle_.get()); + return isolated::schedule::IsolatedSchedule::getTimeZoneDisplayName(handle_); } std::string Schedule::getTimeZoneId() const { - if (!handle_) { - return dxfcpp::String::EMPTY; - } - - return isolated::schedule::Schedule::getTimeZoneId(handle_.get()); + return isolated::schedule::IsolatedSchedule::getTimeZoneId(handle_); } DXFCPP_END_NAMESPACE \ No newline at end of file From 67ce5ab12b41ab2c8675818403de80cecb28968f Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 19 Sep 2024 23:22:41 +0300 Subject: [PATCH 093/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. Normalize the Candle class structure. --- .../event/candle/Candle.hpp | 280 ++++------------- .../event/candle/CandleSymbol.hpp | 5 - .../schedule/SessionFilter.hpp | 1 + src/event/candle/Candle.cpp | 297 +++++++++++++++++- 4 files changed, 351 insertions(+), 232 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp index dffba65fd..14048a2ab 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/Candle.hpp @@ -7,25 +7,20 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) -#include #include #include #include -#include #include "../../internal/Common.hpp" -#include "../../exceptions/InvalidArgumentException.hpp" - #include "../EventType.hpp" -#include "../EventTypeEnum.hpp" -#include "../IndexedEventSource.hpp" #include "../LastingEvent.hpp" #include "../TimeSeriesEvent.hpp" #include "CandleSymbol.hpp" DXFCPP_BEGIN_NAMESPACE +class EventTypeEnum; struct EventMapper; /** @@ -162,8 +157,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * Creates new candle with the specified candle event symbol. * @param eventSymbol candle event symbol. */ - explicit Candle(CandleSymbol eventSymbol) noexcept : eventSymbol_{std::move(eventSymbol)} { - } + explicit Candle(CandleSymbol eventSymbol) noexcept; // EventType methods @@ -172,27 +166,17 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * * @return symbol of this event or dxfcpp::CandleSymbol::NUL (`dxfcpp::CandleSymbol{""}`) */ - const CandleSymbol &getEventSymbol() const & noexcept override { - if (!eventSymbol_) { - return CandleSymbol::NUL; - } - - return eventSymbol_.value(); - } + const CandleSymbol &getEventSymbol() const & noexcept override; /** * Returns symbol of this event. * * @return symbol of this event or `std::nullopt`. */ - const std::optional &getEventSymbolOpt() const & noexcept override { - return eventSymbol_; - } + const std::optional &getEventSymbolOpt() const & noexcept override; /// - void setEventSymbol(const CandleSymbol &eventSymbol) noexcept override { - eventSymbol_ = eventSymbol; - } + void setEventSymbol(const CandleSymbol &eventSymbol) noexcept override; /** * Changes event's symbol and returns the current candle. @@ -200,21 +184,13 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param eventSymbol The symbol of this event. * @return The current candle. */ - Candle &withEventSymbol(const CandleSymbol &eventSymbol) noexcept { - Candle::setEventSymbol(eventSymbol); - - return *this; - } + Candle &withEventSymbol(const CandleSymbol &eventSymbol) noexcept; /// - std::int64_t getEventTime() const noexcept override { - return data_.eventTime; - } + std::int64_t getEventTime() const noexcept override; /// - void setEventTime(std::int64_t eventTime) noexcept override { - data_.eventTime = eventTime; - } + void setEventTime(std::int64_t eventTime) noexcept override; /** * Changes event's creation time and returns the current candle. @@ -223,28 +199,18 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * midnight, January 1, 1970 UTC. * @return The current candle. */ - Candle &withEventTime(std::int64_t eventTime) noexcept { - Candle::setEventTime(eventTime); - - return *this; - } + Candle &withEventTime(std::int64_t eventTime) noexcept; // IndexedEvent methods /// - std::int32_t getEventFlags() const noexcept override { - return data_.eventFlags; - } + std::int32_t getEventFlags() const noexcept override; /// - EventFlagsMask getEventFlagsMask() const noexcept override { - return EventFlagsMask(data_.eventFlags); - } + EventFlagsMask getEventFlagsMask() const noexcept override; /// - void setEventFlags(std::int32_t eventFlags) noexcept override { - data_.eventFlags = eventFlags; - } + void setEventFlags(std::int32_t eventFlags) noexcept override; /** * Changes transactional event flags and returns the current candle. @@ -253,16 +219,10 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param eventFlags transactional event flags. * @return The current candle. */ - Candle &withEventFlags(std::int32_t eventFlags) noexcept { - Candle::setEventFlags(eventFlags); - - return *this; - } + Candle &withEventFlags(std::int32_t eventFlags) noexcept; /// - void setEventFlags(const EventFlagsMask &eventFlags) noexcept override { - data_.eventFlags = static_cast(eventFlags.getMask()); - } + void setEventFlags(const EventFlagsMask &eventFlags) noexcept override; /** * Changes transactional event flags and returns the current candle. @@ -271,16 +231,10 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param eventFlags transactional event flags' mask. * @return The current candle. */ - Candle &withEventFlags(const EventFlagsMask &eventFlags) noexcept { - Candle::setEventFlags(eventFlags); - - return *this; - } + Candle &withEventFlags(const EventFlagsMask &eventFlags) noexcept; /// - void setIndex(std::int64_t index) override { - data_.index = index; - } + void setIndex(std::int64_t index) override; /** * Changes unique per-symbol index of this event. @@ -289,25 +243,21 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param index unique per-symbol index of this candle. * @return The current candle. */ - Candle &withIndex(std::int64_t index) noexcept { - Candle::setIndex(index); + Candle &withIndex(std::int64_t index) noexcept; - return *this; - } + // TimeSeriesEvent methods /// - std::int64_t getIndex() const noexcept override { - return data_.index; - } + std::int64_t getIndex() const noexcept override; /** * Returns timestamp of the event in milliseconds. * * @return timestamp of the event in milliseconds */ - std::int64_t getTime() const noexcept override { - return sar(data_.index, SECONDS_SHIFT) * 1000 + andOp(sar(data_.index, MILLISECONDS_SHIFT), MILLISECONDS_MASK); - } + std::int64_t getTime() const noexcept override; + + // Candle methods /** * Changes timestamp of the event in milliseconds. @@ -315,11 +265,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param time timestamp of the event in milliseconds. * @see Candle::getTime() */ - void setTime(std::int64_t time) noexcept { - data_.index = orOp(orOp(sal(static_cast(time_util::getSecondsFromTime(time)), SECONDS_SHIFT), - sal(static_cast(time_util::getMillisFromTime(time)), MILLISECONDS_SHIFT)), - getSequence()); - } + void setTime(std::int64_t time) noexcept; /** * Changes timestamp of the event in milliseconds. @@ -328,11 +274,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param time timestamp of the event in milliseconds. * @return The current candle. */ - Candle &withTime(std::int64_t time) noexcept { - Candle::setTime(time); - - return *this; - } + Candle &withTime(std::int64_t time) noexcept; /** * Returns the sequence number of this event to distinguish events that have the same @ref Candle::getTime() "time". @@ -341,9 +283,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * * @return The sequence number of this event */ - std::int32_t getSequence() const noexcept { - return static_cast(andOp(data_.index, MAX_SEQUENCE)); - } + std::int32_t getSequence() const noexcept; /** * Changes @ref Candle::getSequence() "sequence number" of this event. @@ -352,15 +292,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @see Candle::getSequence() * @throws InvalidArgumentException if sequence is below zero or above ::MAX_SEQUENCE. */ - void setSequence(std::int32_t sequence) { - assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); - - if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { - throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); - } - - data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); - } + void setSequence(std::int32_t sequence); /** * Changes @ref Candle::getSequence() "sequence number" of this event. @@ -370,27 +302,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @return The current candle. * @see Candle::getSequence() */ - Candle &withSequence(std::int32_t sequence) noexcept { - Candle::setSequence(sequence); - - return *this; - } + Candle &withSequence(std::int32_t sequence) noexcept; /** * Returns total number of original trade (or quote) events in this candle. * @return Total number of original trade (or quote) events in this candle. */ - std::int64_t getCount() const noexcept { - return data_.count; - } + std::int64_t getCount() const noexcept; /** * Changes total number of original trade (or quote) events in this candle. * @param count Total number of original trade (or quote) events in this candle. */ - void setCount(std::int64_t count) noexcept { - data_.count = count; - } + void setCount(std::int64_t count) noexcept; /** * Changes total number of original trade (or quote) events in this candle. @@ -399,27 +323,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param count Total number of original trade (or quote) events in this candle. * @return The current candle. */ - Candle &withCount(std::int64_t count) noexcept { - Candle::setCount(count); - - return *this; - } + Candle &withCount(std::int64_t count) noexcept; /** * Returns the first (open) price of this candle. * @return The first (open) price of this candle. */ - double getOpen() const noexcept { - return data_.open; - } + double getOpen() const noexcept; /** * Changes the first (open) price of this candle. * @param open The first (open) price of this candle. */ - void setOpen(double open) noexcept { - data_.open = open; - } + void setOpen(double open) noexcept; /** * Changes the first (open) price of this candle. @@ -428,27 +344,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param open The first (open) price of this candle. * @return The current candle. */ - Candle &withOpen(double open) noexcept { - Candle::setOpen(open); - - return *this; - } + Candle &withOpen(double open) noexcept; /** * Returns the maximal (high) price of this candle. * @return The maximal (high) price of this candle. */ - double getHigh() const noexcept { - return data_.high; - } + double getHigh() const noexcept; /** * Changes the maximal (high) price of this candle. * @param high The maximal (high) price of this candle. */ - void setHigh(double high) noexcept { - data_.high = high; - } + void setHigh(double high) noexcept; /** * Changes the maximal (high) price of this candle. @@ -457,27 +365,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param high The maximal (high) price of this candle. * @return The current candle. */ - Candle &withHigh(double high) noexcept { - Candle::setHigh(high); - - return *this; - } + Candle &withHigh(double high) noexcept; /** * Returns the minimal (low) price of this candle. * @return The minimal (low) price of this candle. */ - double getLow() const noexcept { - return data_.low; - } + double getLow() const noexcept; /** * Changes the minimal (low) price of this candle. * @param low The minimal (low) price of this candle. */ - void setLow(double low) noexcept { - data_.low = low; - } + void setLow(double low) noexcept; /** * Changes the minimal (low) price of this candle. @@ -486,27 +386,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param low The minimal (low) price of this candle. * @return The current candle. */ - Candle &withLow(double low) noexcept { - Candle::setLow(low); - - return *this; - } + Candle &withLow(double low) noexcept; /** * Returns the last (close) price of this candle. * @return The last (close) price of this candle. */ - double getClose() const noexcept { - return data_.close; - } + double getClose() const noexcept; /** * Changes the last (close) price of this candle. * @param close The last (close) price of this candle. */ - void setClose(double close) noexcept { - data_.close = close; - } + void setClose(double close) noexcept; /** * Changes the last (close) price of this candle. @@ -515,27 +407,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param close The last (close) price of this candle. * @return The current candle. */ - Candle &withClose(double close) noexcept { - Candle::setClose(close); - - return *this; - } + Candle &withClose(double close) noexcept; /** * Returns total volume in this candle. * @return Total volume in this candle. */ - double getVolume() const noexcept { - return data_.volume; - } + double getVolume() const noexcept; /** * Changes total volume in this candle. * @param volume Total volume in this candle. */ - void setVolume(double volume) noexcept { - data_.volume = volume; - } + void setVolume(double volume) noexcept; /** * Changes total volume in this candle. @@ -544,11 +428,7 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param volume Total volume in this candle. * @return The current candle. */ - Candle &withVolume(double volume) noexcept { - Candle::setVolume(volume); - - return *this; - } + Candle &withVolume(double volume) noexcept; /** * Returns volume-weighted average price (VWAP) in this candle. @@ -556,17 +436,13 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * "getVolume"(). * @return Volume-weighted average price (VWAP) in this candle. */ - double getVWAP() const noexcept { - return data_.vwap; - } + double getVWAP() const noexcept; /** * Changes volume-weighted average price (VWAP) in this candle. * @param vwap Volume-weighted average price (VWAP) in this candle. */ - void setVWAP(double vwap) noexcept { - data_.vwap = vwap; - } + void setVWAP(double vwap) noexcept; /** * Changes volume-weighted average price (VWAP) in this candle. @@ -575,27 +451,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param vwap Volume-weighted average price (VWAP) in this candle. * @return The current candle. */ - Candle &withVWAP(double vwap) noexcept { - Candle::setVWAP(vwap); - - return *this; - } + Candle &withVWAP(double vwap) noexcept; /** * Returns bid volume in this candle. * @return Bid volume in this candle. */ - double getBidVolume() const noexcept { - return data_.bidVolume; - } + double getBidVolume() const noexcept; /** * Changes bid volume in this candle. * @param bidVolume Bid volume in this candle. */ - void setBidVolume(double bidVolume) noexcept { - data_.bidVolume = bidVolume; - } + void setBidVolume(double bidVolume) noexcept; /** * Changes bid volume in this candle. @@ -604,27 +472,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param bidVolume Bid volume in this candle. * @return The current candle. */ - Candle &withBidVolume(double bidVolume) noexcept { - Candle::setBidVolume(bidVolume); - - return *this; - } + Candle &withBidVolume(double bidVolume) noexcept; /** * Returns ask volume in this candle. * @return Ask volume in this candle. */ - double getAskVolume() const noexcept { - return data_.askVolume; - } + double getAskVolume() const noexcept; /** * Changes ask volume in this candle. * @param askVolume Ask volume in this candle. */ - void setAskVolume(double askVolume) noexcept { - data_.askVolume = askVolume; - } + void setAskVolume(double askVolume) noexcept; /** * Changes ask volume in this candle. @@ -633,27 +493,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param askVolume Ask volume in this candle. * @return The current candle. */ - Candle &withAskVolume(double askVolume) noexcept { - Candle::setAskVolume(askVolume); - - return *this; - } + Candle &withAskVolume(double askVolume) noexcept; /** * Returns the implied volatility. * @return The implied volatility. */ - double getImpVolatility() const noexcept { - return data_.impVolatility; - } + double getImpVolatility() const noexcept; /** * Changes the implied volatility. * @param impVolatility The implied volatility. */ - void setImpVolatility(double impVolatility) { - data_.impVolatility = impVolatility; - } + void setImpVolatility(double impVolatility); /** * Changes implied volatility. @@ -662,27 +514,19 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param impVolatility The implied volatility. * @return The current candle. */ - Candle &withImpVolatility(double impVolatility) noexcept { - Candle::setImpVolatility(impVolatility); - - return *this; - } + Candle &withImpVolatility(double impVolatility) noexcept; /** * Returns the open interest. * @return The open interest. */ - double getOpenInterest() const noexcept { - return data_.openInterest; - } + double getOpenInterest() const noexcept; /** * Changes the open interest. * @param openInterest The open interest. */ - void setOpenInterest(double openInterest) noexcept { - data_.openInterest = openInterest; - } + void setOpenInterest(double openInterest) noexcept; /** * Changes the open interest. @@ -691,11 +535,9 @@ class DXFCPP_EXPORT Candle final : public EventTypeWithSymbol, * @param openInterest The open interest. * @return The current candle. */ - Candle &withOpenInterest(double openInterest) noexcept { - Candle::setOpenInterest(openInterest); + Candle &withOpenInterest(double openInterest) noexcept; - return *this; - } + // EventType methods std::string toString() const override; }; diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp index 313d87dd2..de559d809 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleSymbol.hpp @@ -7,8 +7,6 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) -#include "../../symbols/SymbolWrapper.hpp" - #include "CandleAlignment.hpp" #include "CandleExchange.hpp" #include "CandlePeriod.hpp" @@ -20,7 +18,6 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include #include #include -#include #include #include @@ -32,8 +29,6 @@ DXFCPP_BEGIN_NAMESPACE using CandleSymbolAttributeVariant = std::variant; -struct SymbolWrapper; - /** * Symbol that should be used with DXFeedSubscription class to subscribe for Candle events. `DXFeedSubscription` also * accepts a string representation of the candle symbol for subscription. diff --git a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp index 3dec6bf88..00d9bbdaa 100644 --- a/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/SessionFilter.hpp @@ -7,6 +7,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include "../internal/JavaObjectHandle.hpp" #include "SessionType.hpp" #include diff --git a/src/event/candle/Candle.cpp b/src/event/candle/Candle.cpp index 11a977018..e32146055 100644 --- a/src/event/candle/Candle.cpp +++ b/src/event/candle/Candle.cpp @@ -4,22 +4,22 @@ #include #include -#include -#include #include -#include #include +#include + +#include + +#include + +#include +#include -#include #include -#include -#include DXFCPP_BEGIN_NAMESPACE -const EventTypeEnum &Candle::TYPE = EventTypeEnum::CANDLE; - void Candle::fillData(void *graalNative) { if (graalNative == nullptr) { return; @@ -82,6 +82,8 @@ void Candle::freeGraalData(void *graalNative) noexcept { delete[] graalCandle->event_symbol; } +const EventTypeEnum &Candle::TYPE = EventTypeEnum::CANDLE; + std::shared_ptr Candle::fromGraal(void *graalNative) { if (!graalNative) { throw InvalidArgumentException("Unable to create Candle. The `graalNative` parameter is nullptr"); @@ -139,6 +141,285 @@ void Candle::freeGraal(void *graalNative) { delete graalCandle; } +Candle::Candle(CandleSymbol eventSymbol) noexcept : eventSymbol_{std::move(eventSymbol)} { +} + +const CandleSymbol &Candle::getEventSymbol() const & noexcept { + if (!eventSymbol_) { + return CandleSymbol::NUL; + } + + return eventSymbol_.value(); +} + +const std::optional &Candle::getEventSymbolOpt() const & noexcept { + return eventSymbol_; +} + +void Candle::setEventSymbol(const CandleSymbol &eventSymbol) noexcept { + eventSymbol_ = eventSymbol; +} + +Candle &Candle::withEventSymbol(const CandleSymbol &eventSymbol) noexcept { + Candle::setEventSymbol(eventSymbol); + + return *this; +} + +std::int64_t Candle::getEventTime() const noexcept { + return data_.eventTime; +} + +void Candle::setEventTime(std::int64_t eventTime) noexcept { + data_.eventTime = eventTime; +} + +Candle &Candle::withEventTime(std::int64_t eventTime) noexcept { + Candle::setEventTime(eventTime); + + return *this; +} + +// IndexedEvent methods + +std::int32_t Candle::getEventFlags() const noexcept { + return data_.eventFlags; +} + +EventFlagsMask Candle::getEventFlagsMask() const noexcept { + return EventFlagsMask(data_.eventFlags); +} + +void Candle::setEventFlags(std::int32_t eventFlags) noexcept { + data_.eventFlags = eventFlags; +} + +Candle &Candle::withEventFlags(std::int32_t eventFlags) noexcept { + Candle::setEventFlags(eventFlags); + + return *this; +} + +void Candle::setEventFlags(const EventFlagsMask &eventFlags) noexcept { + data_.eventFlags = static_cast(eventFlags.getMask()); +} + +Candle &Candle::withEventFlags(const EventFlagsMask &eventFlags) noexcept { + Candle::setEventFlags(eventFlags); + + return *this; +} + +void Candle::setIndex(std::int64_t index) { + data_.index = index; +} + +Candle &Candle::withIndex(std::int64_t index) noexcept { + Candle::setIndex(index); + + return *this; +} + +// TimeSeriesEvent methods + +std::int64_t Candle::getIndex() const noexcept { + return data_.index; +} + +std::int64_t Candle::getTime() const noexcept { + return sar(data_.index, SECONDS_SHIFT) * 1000 + andOp(sar(data_.index, MILLISECONDS_SHIFT), MILLISECONDS_MASK); +} + +// Candle methods + +void Candle::setTime(std::int64_t time) noexcept { + data_.index = orOp(orOp(sal(static_cast(time_util::getSecondsFromTime(time)), SECONDS_SHIFT), + sal(static_cast(time_util::getMillisFromTime(time)), MILLISECONDS_SHIFT)), + getSequence()); +} + +Candle &Candle::withTime(std::int64_t time) noexcept { + Candle::setTime(time); + + return *this; +} + +std::int32_t Candle::getSequence() const noexcept { + return static_cast(andOp(data_.index, MAX_SEQUENCE)); +} + +void Candle::setSequence(std::int32_t sequence) { + assert(sequence >= 0 && static_cast(sequence) <= MAX_SEQUENCE); + + if (sequence < 0 || static_cast(sequence) > MAX_SEQUENCE) { + throw InvalidArgumentException("Invalid value for argument `sequence`: " + std::to_string(sequence)); + } + + data_.index = orOp(andOp(data_.index, ~MAX_SEQUENCE), sequence); +} + +Candle &Candle::withSequence(std::int32_t sequence) noexcept { + Candle::setSequence(sequence); + + return *this; +} + +std::int64_t Candle::getCount() const noexcept { + return data_.count; +} + +void Candle::setCount(std::int64_t count) noexcept { + data_.count = count; +} + +Candle &Candle::withCount(std::int64_t count) noexcept { + Candle::setCount(count); + + return *this; +} + +double Candle::getOpen() const noexcept { + return data_.open; +} + +void Candle::setOpen(double open) noexcept { + data_.open = open; +} + +Candle &Candle::withOpen(double open) noexcept { + Candle::setOpen(open); + + return *this; +} + +double Candle::getHigh() const noexcept { + return data_.high; +} + +void Candle::setHigh(double high) noexcept { + data_.high = high; +} + +Candle &Candle::withHigh(double high) noexcept { + Candle::setHigh(high); + + return *this; +} + +double Candle::getLow() const noexcept { + return data_.low; +} + +void Candle::setLow(double low) noexcept { + data_.low = low; +} + +Candle &Candle::withLow(double low) noexcept { + Candle::setLow(low); + + return *this; +} + +double Candle::getClose() const noexcept { + return data_.close; +} + +void Candle::setClose(double close) noexcept { + data_.close = close; +} + +Candle &Candle::withClose(double close) noexcept { + Candle::setClose(close); + + return *this; +} + +double Candle::getVolume() const noexcept { + return data_.volume; +} + +void Candle::setVolume(double volume) noexcept { + data_.volume = volume; +} + +Candle &Candle::withVolume(double volume) noexcept { + Candle::setVolume(volume); + + return *this; +} + +double Candle::getVWAP() const noexcept { + return data_.vwap; +} + +void Candle::setVWAP(double vwap) noexcept { + data_.vwap = vwap; +} + +Candle &Candle::withVWAP(double vwap) noexcept { + Candle::setVWAP(vwap); + + return *this; +} + +double Candle::getBidVolume() const noexcept { + return data_.bidVolume; +} + +void Candle::setBidVolume(double bidVolume) noexcept { + data_.bidVolume = bidVolume; +} + +Candle &Candle::withBidVolume(double bidVolume) noexcept { + Candle::setBidVolume(bidVolume); + + return *this; +} + +double Candle::getAskVolume() const noexcept { + return data_.askVolume; +} + +void Candle::setAskVolume(double askVolume) noexcept { + data_.askVolume = askVolume; +} + +Candle &Candle::withAskVolume(double askVolume) noexcept { + Candle::setAskVolume(askVolume); + + return *this; +} + +double Candle::getImpVolatility() const noexcept { + return data_.impVolatility; +} + +void Candle::setImpVolatility(double impVolatility) { + data_.impVolatility = impVolatility; +} + +Candle &Candle::withImpVolatility(double impVolatility) noexcept { + Candle::setImpVolatility(impVolatility); + + return *this; +} + +double Candle::getOpenInterest() const noexcept { + return data_.openInterest; +} + +void Candle::setOpenInterest(double openInterest) noexcept { + data_.openInterest = openInterest; +} + +Candle &Candle::withOpenInterest(double openInterest) noexcept { + Candle::setOpenInterest(openInterest); + + return *this; +} + +// EventType methods + std::string Candle::toString() const { return fmt::format( "Candle{{{}, eventTime={}, eventFlags={:#x}, time={}, sequence={}, count={}, open={}, high={}, low={}, " From 3f1278be133f76fc88545f172dc277212e12c0b5 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 20 Sep 2024 16:00:49 +0300 Subject: [PATCH 094/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. Normalize the CandleAlignment class structure. --- .../event/candle/CandleAlignment.hpp | 72 ++------------ .../event/candle/CandleSymbolAttribute.hpp | 2 + .../dxfeed_graal_cpp_api/internal/Common.hpp | 5 +- src/event/candle/Candle.cpp | 15 ++- src/event/candle/CandleAlignment.cpp | 95 ++++++++++++++++++- 5 files changed, 112 insertions(+), 77 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp index 9489686e9..4168519af 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp @@ -7,9 +7,6 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) -#include "../../internal/utils/StringUtils.hpp" -#include "../../exceptions/InvalidArgumentException.hpp" -#include "../market/MarketEventSymbols.hpp" #include "CandleSymbolAttribute.hpp" #include @@ -58,13 +55,13 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { static const std::unordered_map, dxfcpp::StringHash, std::equal_to<>> BY_STRING; + static const std::vector> VALUES; private: std::string string_{}; - explicit CandleAlignment(const dxfcpp::StringLikeWrapper &string) noexcept : string_{string} { - } + explicit CandleAlignment(const dxfcpp::StringLikeWrapper &string) noexcept; public: CandleAlignment() noexcept = default; @@ -76,10 +73,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * @param symbol The original candle event symbol. * @return candle event symbol string with this candle alignment set. */ - std::string changeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) const override { - return *this == DEFAULT ? MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY) - : MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, toString()); - } + std::string changeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) const override; /** * Returns string representation of this candle alignment. @@ -88,13 +82,9 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * * @return string representation of this candle alignment. */ - std::string toString() const { - return string_; - } + std::string toString() const; - bool operator==(const CandleAlignment &candleAlignment) const noexcept { - return string_ == candleAlignment.string_; - } + bool operator==(const CandleAlignment &candleAlignment) const noexcept; /** * Parses string representation of candle alignment into object. @@ -104,23 +94,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * @return The candle alignment (reference) * @throws InvalidArgumentException if the string representation is invalid. */ - static std::reference_wrapper parse(const dxfcpp::StringLikeWrapper &s) { - auto found = BY_STRING.find(s); - - if (found != BY_STRING.end()) { - return found->second; - } - - for (const auto &alignmentRef : VALUES) { - const auto &alignmentStr = alignmentRef.get().toString(); - - if (iEquals(alignmentStr, s)) { - return alignmentRef; - } - } - - throw InvalidArgumentException("Unknown candle alignment: " + s); - } + static std::reference_wrapper parse(const dxfcpp::StringLikeWrapper &s); /** * Returns candle alignment of the given candle symbol string. @@ -129,12 +103,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * @param symbol The candle symbol string. * @return candle alignment of the given candle symbol string. */ - static std::reference_wrapper - getAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) { - auto stringOpt = MarketEventSymbols::getAttributeStringByKey(symbol, ATTRIBUTE_KEY); - - return !stringOpt ? std::cref(DEFAULT) : parse(stringOpt.value()); - } + static std::reference_wrapper getAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol); /** * Returns candle symbol string with the normalized representation of the candle alignment attribute. @@ -142,32 +111,7 @@ struct DXFCPP_EXPORT CandleAlignment : public CandleSymbolAttribute { * @param symbol The candle symbol string. * @return candle symbol string with the normalized representation of the the candle alignment attribute. */ - static std::string - normalizeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) { - auto a = MarketEventSymbols::getAttributeStringByKey(symbol, ATTRIBUTE_KEY); - - if (!a) { - return symbol; - } - - try { - auto other = parse(a.value()); - - if (other.get() == DEFAULT) { - return MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY); - } - - if (a.value() != other.get().toString()) { - return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.get().toString()); - } - - return symbol; - } catch (const InvalidArgumentException &) { - return symbol; - } catch (const std::invalid_argument &) { - return symbol; - } - } + static std::string normalizeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol); }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleSymbolAttribute.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleSymbolAttribute.hpp index 7943bd626..bcc09f213 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleSymbolAttribute.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleSymbolAttribute.hpp @@ -11,6 +11,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE +struct StringLikeWrapper; + /** * Attribute of the CandleSymbol. */ diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index 342db5bf9..c3c082899 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -775,6 +775,7 @@ struct StringLikeWrapper { } }; +/// Universal functional object that allows searching std::unordered_map for string-like keys. struct StringHash { using HashType = std::hash; using is_transparent = void; @@ -783,8 +784,8 @@ struct StringHash { return HashType{}(str); } - std::size_t operator()(std::string_view str) const { - return HashType{}(str); + std::size_t operator()(std::string_view sw) const { + return HashType{}(sw); } std::size_t operator()(std::string const &str) const { diff --git a/src/event/candle/Candle.cpp b/src/event/candle/Candle.cpp index e32146055..773d8a368 100644 --- a/src/event/candle/Candle.cpp +++ b/src/event/candle/Candle.cpp @@ -1,21 +1,20 @@ // Copyright (c) 2024 Devexperts LLC. // SPDX-License-Identifier: MPL-2.0 -#include +#include +#include +#include +#include +#include + +#include #include #include #include #include -#include - -#include - -#include -#include - #include DXFCPP_BEGIN_NAMESPACE diff --git a/src/event/candle/CandleAlignment.cpp b/src/event/candle/CandleAlignment.cpp index 9bf3e3eda..bc9e8abba 100644 --- a/src/event/candle/CandleAlignment.cpp +++ b/src/event/candle/CandleAlignment.cpp @@ -1,10 +1,11 @@ // Copyright (c) 2024 Devexperts LLC. // SPDX-License-Identifier: MPL-2.0 -#include +#include -#include -#include +#include +#include +#include DXFCPP_BEGIN_NAMESPACE @@ -25,4 +26,92 @@ const std::vector> CandleAlignment std::cref(CandleAlignment::SESSION), }; +CandleAlignment::CandleAlignment(const dxfcpp::StringLikeWrapper &string) noexcept : string_{string} { +} + +std::string CandleAlignment::changeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) const { + return *this == DEFAULT ? MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY) + : MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, toString()); +} + +std::string CandleAlignment::toString() const { + return string_; +} + +bool CandleAlignment::operator==(const CandleAlignment &candleAlignment) const noexcept { + return string_ == candleAlignment.string_; +} + +/** + * Parses string representation of candle alignment into object. + * Any string that was returned by CandleAlignment::toString() can be parsed and case is ignored for parsing. + * + * @param s The string representation of candle alignment. + * @return The candle alignment (reference) + * @throws InvalidArgumentException if the string representation is invalid. + */ +std::reference_wrapper CandleAlignment::parse(const dxfcpp::StringLikeWrapper &s) { + auto found = BY_STRING.find(s); + + if (found != BY_STRING.end()) { + return found->second; + } + + for (const auto &alignmentRef : VALUES) { + const auto &alignmentStr = alignmentRef.get().toString(); + + if (iEquals(alignmentStr, s)) { + return alignmentRef; + } + } + + throw InvalidArgumentException("Unknown candle alignment: " + s); +} + +/** + * Returns candle alignment of the given candle symbol string. + * The result is CandleAlignment::DEFAULT if the symbol does not have candle alignment attribute. + * + * @param symbol The candle symbol string. + * @return candle alignment of the given candle symbol string. + */ +std::reference_wrapper +CandleAlignment::getAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) { + auto stringOpt = MarketEventSymbols::getAttributeStringByKey(symbol, ATTRIBUTE_KEY); + + return !stringOpt ? std::cref(DEFAULT) : parse(stringOpt.value()); +} + +/** + * Returns candle symbol string with the normalized representation of the candle alignment attribute. + * + * @param symbol The candle symbol string. + * @return candle symbol string with the normalized representation of the the candle alignment attribute. + */ +std::string CandleAlignment::normalizeAttributeForSymbol(const dxfcpp::StringLikeWrapper &symbol) { + auto a = MarketEventSymbols::getAttributeStringByKey(symbol, ATTRIBUTE_KEY); + + if (!a) { + return symbol; + } + + try { + auto other = parse(a.value()); + + if (other.get() == DEFAULT) { + return MarketEventSymbols::removeAttributeStringByKey(symbol, ATTRIBUTE_KEY); + } + + if (a.value() != other.get().toString()) { + return MarketEventSymbols::changeAttributeStringByKey(symbol, ATTRIBUTE_KEY, other.get().toString()); + } + + return symbol; + } catch (const InvalidArgumentException &) { + return symbol; + } catch (const std::invalid_argument &) { + return symbol; + } +} + DXFCPP_END_NAMESPACE \ No newline at end of file From 33ebbf72ff461c9b95127410352408ab1bd25a30 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 20 Sep 2024 18:27:41 +0300 Subject: [PATCH 095/178] [MDAPI-128] [C++] Split isolated (with GraalVM) entities into multiple translation units. Fix build on Linux. --- include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp | 1 + include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp | 1 + include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp | 1 + src/ipf/live/InstrumentProfileCollector.cpp | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp index 4168519af..101263506 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleAlignment.hpp @@ -8,6 +8,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "CandleSymbolAttribute.hpp" +#include "../../internal/Common.hpp" #include #include diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp index 50b98ba06..31a230b82 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandlePeriod.hpp @@ -4,6 +4,7 @@ #pragma once #include "../../internal/Conf.hpp" +#include "../../exceptions/InvalidArgumentException.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) diff --git a/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp b/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp index 60c0536f2..bb74fbbb4 100644 --- a/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp +++ b/include/dxfeed_graal_cpp_api/event/candle/CandleType.hpp @@ -4,6 +4,7 @@ #pragma once #include "../../internal/Conf.hpp" +#include "../../exceptions/InvalidArgumentException.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) diff --git a/src/ipf/live/InstrumentProfileCollector.cpp b/src/ipf/live/InstrumentProfileCollector.cpp index 5b8eaad75..a2817a344 100644 --- a/src/ipf/live/InstrumentProfileCollector.cpp +++ b/src/ipf/live/InstrumentProfileCollector.cpp @@ -113,7 +113,7 @@ void InstrumentProfileCollector::removeListenerHandle(std::size_t id) { isolated::ipf::live::IsolatedInstrumentProfileCollector::removeUpdateListener(handle_, listenerHandles_[id]); } -InstrumentProfileCollector::~InstrumentProfileCollector() { +InstrumentProfileCollector::~InstrumentProfileCollector() noexcept { std::lock_guard guard{listenersMutex_}; std::vector listenerIds{}; From a51adc5362ae8e57293435ab100d24d30dd6fef5 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 23 Sep 2024 18:43:18 +0300 Subject: [PATCH 096/178] [MDAPI-135] [C++] Add the ability to create a bundle to build with all dependencies. Add dxfcxx_ParseVersion CMake function. Add dxFeedGraalCxxApi.rc resource file. --- CMakeLists.txt | 35 +++++++++++++++---- cmake/ParseVersion.cmake | 63 ++++++++++++++++++++++++++++++++++ resources/dxFeedGraalCxxApi.rc | 38 ++++++++++++++++++++ 3 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 cmake/ParseVersion.cmake create mode 100644 resources/dxFeedGraalCxxApi.rc diff --git a/CMakeLists.txt b/CMakeLists.txt index cb8b91198..2a719cf2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,12 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) project(dxFeedGraalCxxApi) +include(cmake/ParseVersion.cmake) + set(DXFCXX_VERSION "v3.0.0-rc1" CACHE STRING "The dxFeed Graal CXX API package version") +dxfcxx_ParseVersion(${DXFCXX_VERSION} DXFCXX_MAJOR_VERSION DXFCXX_MINOR_VERSION DXFCXX_PATCH_VERSION DXFCXX_SUFFIX_VERSION) + set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.23" CACHE STRING "") set(FMTLIB_VERSION "10.2.1") set(BOOST_VERSION "1.84.0") @@ -389,10 +393,18 @@ add_library(${PROJECT_NAME}_static STATIC src/api.cpp ) -add_library(${PROJECT_NAME} SHARED - ${dxFeedGraalCxxApi_Sources} - src/api.cpp -) +if (WIN32) + add_library(${PROJECT_NAME} SHARED + ${dxFeedGraalCxxApi_Sources} + resources/dxFeedGraalCxxApi.rc + src/api.cpp + ) +else () + add_library(${PROJECT_NAME} SHARED + ${dxFeedGraalCxxApi_Sources} + src/api.cpp + ) +endif () add_library(dxfcxx ALIAS ${PROJECT_NAME}) add_library(dxfcxx::static ALIAS ${PROJECT_NAME}_static) @@ -509,8 +521,19 @@ add_custom_command(TARGET ${PROJECT_NAME}_static POST_BUILD COMMAND ${CMAKE_COMM add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $) -target_compile_definitions(${PROJECT_NAME} PUBLIC DXFCXX_VERSION="${DXFCXX_VERSION}") -target_compile_definitions(${PROJECT_NAME}_static PUBLIC DXFCXX_VERSION="${DXFCXX_VERSION}") +target_compile_definitions(${PROJECT_NAME} PUBLIC + DXFCXX_VERSION="${DXFCXX_VERSION}" + DXFCXX_MAJOR_VERSION=${DXFCXX_MAJOR_VERSION} + DXFCXX_MINOR_VERSION=${DXFCXX_MINOR_VERSION} + DXFCXX_PATCH_VERSION=${DXFCXX_PATCH_VERSION} +) + +target_compile_definitions(${PROJECT_NAME}_static PUBLIC + DXFCXX_VERSION="${DXFCXX_VERSION}" + DXFCXX_MAJOR_VERSION=${DXFCXX_MAJOR_VERSION} + DXFCXX_MINOR_VERSION=${DXFCXX_MINOR_VERSION} + DXFCXX_PATCH_VERSION=${DXFCXX_PATCH_VERSION} +) if (DXFCXX_BUILD_UNIT_TESTS) include(CTest) diff --git a/cmake/ParseVersion.cmake b/cmake/ParseVersion.cmake new file mode 100644 index 000000000..094fda860 --- /dev/null +++ b/cmake/ParseVersion.cmake @@ -0,0 +1,63 @@ +# Copyright (c) 2024 Devexperts LLC. +# SPDX-License-Identifier: MPL-2.0 + +## dxfcxx_ParseVersion(, [majorVersion, [minorVersion, [patchVersion, [suffixVersion]]]]) +function(dxfcxx_ParseVersion) + set(__dxfcxx_ParseVersion_Usage "dxfcxx_ParseVersion(, [majorVersion, [minorVersion, [patchVersion, [suffixVersion]]]])") + + if (ARGC EQUAL 0) + message(FATAL_ERROR "Empty function parameter list!\nUsage: ${__dxfcxx_ParseVersion_Usage}") + endif () + + set(version "${ARGV0}") + + set(_majorVersion "0") + set(_minorVersion "0") + set(_patchVersion "0") + set(_suffixVersion "") + + string(REGEX REPLACE "^v?([0-9]+).*$" "\\1" _majorVersion ${version}) + + if (${_majorVersion} STREQUAL "") + set(_majorVersion "0") + else () + string(REGEX REPLACE "^v?[0-9]+\\.([0-9]+).*$" "\\1" _minorVersion ${version}) + + if (${_minorVersion} STREQUAL "") + set(_minorVersion "0") + string(REGEX REPLACE "^v?[0-9]+(.*)$" "\\1" _suffixVersion ${version}) + else () + string(REGEX REPLACE "^v?[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" _patchVersion ${version}) + + if (${_patchVersion} STREQUAL "") + set(_patchVersion "0") + string(REGEX REPLACE "^v?[0-9]+\\.[0-9]+(.*)$" "\\1" _suffixVersion ${version}) + else () + string(REGEX REPLACE "^v?[0-9]+\\.[0-9]+\\.[0-9]+(.*)$" "\\1" _suffixVersion ${version}) + endif () + endif () + endif () + + if (ARGC EQUAL 1) + message(STATUS "Major version: '${_majorVersion}'") + message(STATUS "Minor version: '${_minorVersion}'") + message(STATUS "Patch version: '${_patchVersion}'") + message(STATUS "Suffix version: '${_suffixVersion}'") + endif () + + if (ARGC GREATER 1) + set(${ARGV1} "${_majorVersion}" PARENT_SCOPE) + + if (ARGC GREATER 2) + set(${ARGV2} "${_minorVersion}" PARENT_SCOPE) + + if (ARGC GREATER 3) + set(${ARGV3} "${_patchVersion}" PARENT_SCOPE) + + if (ARGC GREATER 4) + set(${ARGV4} "${_suffixVersion}" PARENT_SCOPE) + endif () + endif () + endif () + endif () +endfunction() \ No newline at end of file diff --git a/resources/dxFeedGraalCxxApi.rc b/resources/dxFeedGraalCxxApi.rc new file mode 100644 index 000000000..8c2930d49 --- /dev/null +++ b/resources/dxFeedGraalCxxApi.rc @@ -0,0 +1,38 @@ +#ifdef __MINGW32__ +#include +#else +#include "winres.h" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION DXFCXX_MAJOR_VERSION, DXFCXX_MINOR_VERSION, DXFCXX_PATCH_VERSION + PRODUCTVERSION DXFCXX_MAJOR_VERSION, DXFCXX_MINOR_VERSION, DXFCXX_PATCH_VERSION + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Devexperts LLC" + VALUE "FileDescription", "The library provides a common application programming interface (API) to real-time, delayed and historical market data feeds." + VALUE "FileVersion", DXFCXX_VERSION + VALUE "InternalName", "dxFeedGraalCxxApi.dll" + VALUE "LegalCopyright", "Copyright (C) 2024 Devexperts LLC" + VALUE "OriginalFilename", "dxFeedGraalCxxApi.dll" + VALUE "ProductName", "dxFeed Graal C++/C API" + VALUE "ProductVersion", DXFCXX_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file From 3773282178170e205a2e3bee1e7537519ef6c541 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 26 Sep 2024 14:28:09 +0300 Subject: [PATCH 097/178] Fix getMillisFromTime visibility during build. --- include/dxfeed_graal_cpp_api/internal/Common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index c3c082899..78aa7b6ad 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -198,7 +198,7 @@ static constexpr std::int64_t DAY = 24LL * HOUR; * @param timeMillis The timestamp in milliseconds * @return a correct number of milliseconds */ -static std::int32_t getMillisFromTime(std::int64_t timeMillis) { +static constexpr std::int32_t getMillisFromTime(std::int64_t timeMillis) { return static_cast(math::floorMod(timeMillis, SECOND)); } From 724f04fb4aa4f1f16bad00d93bf597375cff8f7a Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 30 Sep 2024 16:55:01 +0300 Subject: [PATCH 098/178] [MDAPI-135] [C++] Add the ability to create a bundle to build with all dependencies. Remove unreachable code. [MinGW] Fix build of resource file. --- resources/dxFeedGraalCxxApi.rc | 11 +++++++++-- src/symbols/SymbolWrapper.cpp | 2 -- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/dxFeedGraalCxxApi.rc b/resources/dxFeedGraalCxxApi.rc index 8c2930d49..2fead7a67 100644 --- a/resources/dxFeedGraalCxxApi.rc +++ b/resources/dxFeedGraalCxxApi.rc @@ -1,7 +1,14 @@ +#define DXFCXX_STRINGIFY(x) #x +#define DXFCXX_TO_STRING(x) DXFCXX_STRINGIFY(x) + #ifdef __MINGW32__ -#include +# include +# ifdef DXFCXX_VERSION +# undef DXFCXX_VERSION +# define DXFCXX_VERSION DXFCXX_TO_STRING(DXFCXX_MAJOR_VERSION.DXFCXX_MINOR_VERSION.DXFCXX_PATCH_VERSION) +# endif #else -#include "winres.h" +# include "winres.h" #endif VS_VERSION_INFO VERSIONINFO diff --git a/src/symbols/SymbolWrapper.cpp b/src/symbols/SymbolWrapper.cpp index 0c7df0fa5..a3cdadc43 100644 --- a/src/symbols/SymbolWrapper.cpp +++ b/src/symbols/SymbolWrapper.cpp @@ -201,8 +201,6 @@ SymbolWrapper SymbolWrapper::fromGraal(void *graalNative) { throw RuntimeException(fmt::format("Unable to create SymbolWrapper. Unknown symbol type: {}", static_cast(static_cast(graalNative)->type))); } - - return {}; } DXFCPP_END_NAMESPACE From 669a4993627f71ac3b5ce1a919aa545f8d0ad786 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 30 Sep 2024 18:26:39 +0300 Subject: [PATCH 099/178] [MDAPI-135] [C++] Add the ability to create a bundle to build with all dependencies. Fix warnings. [MinGW] Fix build of resource file. --- CMakeLists.txt | 4 ++++ .../dxfeed_graal_cpp_api/internal/Common.hpp | 2 ++ .../dxfeed_graal_cpp_api/internal/Conf.hpp | 20 ++++++++++++++++++- resources/dxFeedGraalCxxApi.rc | 7 ------- tools/Tools/src/Tools.cpp | 2 ++ 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a719cf2a..f51473b1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,6 +394,10 @@ add_library(${PROJECT_NAME}_static STATIC ) if (WIN32) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + list(APPEND CMAKE_RC_FLAGS "--use-temp-file") + endif() + add_library(${PROJECT_NAME} SHARED ${dxFeedGraalCxxApi_Sources} resources/dxFeedGraalCxxApi.rc diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index 78aa7b6ad..dfcca9185 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -250,7 +250,9 @@ template constexpr static T abs(T a) { namespace day_util { +DXFCXX_DISABLE_GCC_WARNINGS_PUSH("-Wunused-variable") static std::int32_t DAY_OF_YEAR[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; +DXFCXX_DISABLE_GCC_WARNINGS_POP() /** * Returns yyyymmdd integer in Gregorian calendar for a specified day identifier. diff --git a/include/dxfeed_graal_cpp_api/internal/Conf.hpp b/include/dxfeed_graal_cpp_api/internal/Conf.hpp index e1a21f052..004fa2093 100644 --- a/include/dxfeed_graal_cpp_api/internal/Conf.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Conf.hpp @@ -23,6 +23,22 @@ # endif #endif +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__NVCOMPILER) +# ifndef DXFCXX_DO_PRAGMA +# define DXFCXX_DO_PRAGMA(x) _Pragma(#x) +# endif +# ifndef DXFCXX_DISABLE_GCC_WARNINGS_PUSH +# define DXFCXX_DISABLE_GCC_WARNINGS_PUSH(...) \ + DXFCXX_DO_PRAGMA(GCC diagnostic push) DXFCXX_DO_PRAGMA(GCC diagnostic ignored __VA_ARGS__) +# define DXFCXX_DISABLE_GCC_WARNINGS_POP() DXFCXX_DO_PRAGMA(GCC diagnostic pop) +# endif +#else +# ifndef DXFCXX_DISABLE_GCC_WARNINGS_PUSH +# define DXFCXX_DISABLE_GCC_WARNINGS_PUSH(warnings) +# define DXFCXX_DISABLE_GCC_WARNINGS_POP() +# endif +#endif + #ifdef DXFCPP_EXPORT # error DXFCPP_EXPORT was previously defined #endif @@ -97,7 +113,9 @@ constexpr bool isUnknownSTL = true; #endif #ifndef DXFCPP_CXX20_CONSTEXPR_STRING -# if defined(__cpp_lib_constexpr_string) && ((defined(__GNUC__) && __GNUC__ >= 12) || (defined(__clang_major__) && __clang_major__ >= 15) || (defined(_MSC_VER) && _MSC_VER >= 1929)) +# if defined(__cpp_lib_constexpr_string) && \ + ((defined(__GNUC__) && __GNUC__ >= 12) || (defined(__clang_major__) && __clang_major__ >= 15) || \ + (defined(_MSC_VER) && _MSC_VER >= 1929)) # define DXFCPP_CXX20_CONSTEXPR_STRING constexpr # else # define DXFCPP_CXX20_CONSTEXPR_STRING diff --git a/resources/dxFeedGraalCxxApi.rc b/resources/dxFeedGraalCxxApi.rc index 2fead7a67..37d51d0e6 100644 --- a/resources/dxFeedGraalCxxApi.rc +++ b/resources/dxFeedGraalCxxApi.rc @@ -1,12 +1,5 @@ -#define DXFCXX_STRINGIFY(x) #x -#define DXFCXX_TO_STRING(x) DXFCXX_STRINGIFY(x) - #ifdef __MINGW32__ # include -# ifdef DXFCXX_VERSION -# undef DXFCXX_VERSION -# define DXFCXX_VERSION DXFCXX_TO_STRING(DXFCXX_MAJOR_VERSION.DXFCXX_MINOR_VERSION.DXFCXX_PATCH_VERSION) -# endif #else # include "winres.h" #endif diff --git a/tools/Tools/src/Tools.cpp b/tools/Tools/src/Tools.cpp index d829a470c..93147ce15 100644 --- a/tools/Tools/src/Tools.cpp +++ b/tools/Tools/src/Tools.cpp @@ -399,6 +399,8 @@ const std::vector Tools::ADDITIONAL_INFO{ {R"(To get detailed help on some tool use "Help ".)"}, }; +DXFCXX_DISABLE_GCC_WARNINGS_PUSH("-Waggressive-loop-optimizations") const std::vector Tools::ARGS{tools::HelpTool::ALL_TOOLS | ranges::views::values | ranges::to}; +DXFCXX_DISABLE_GCC_WARNINGS_POP() } // namespace dxfcpp::tools \ No newline at end of file From 04a83019d5e3b545003fec795d07fe468f3555ec Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 30 Sep 2024 19:24:34 +0300 Subject: [PATCH 100/178] [MDAPI-135] [C++] Add the ability to create a bundle to build with all dependencies. Fix the DayFilter lazy init --- include/dxfeed_graal_cpp_api/schedule/DayFilter.hpp | 9 ++++++--- src/schedule/Day.cpp | 8 ++++---- src/schedule/DayFilter.cpp | 10 +++++++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/schedule/DayFilter.hpp b/include/dxfeed_graal_cpp_api/schedule/DayFilter.hpp index ee68c027a..bdcb55aa1 100644 --- a/include/dxfeed_graal_cpp_api/schedule/DayFilter.hpp +++ b/include/dxfeed_graal_cpp_api/schedule/DayFilter.hpp @@ -67,8 +67,6 @@ enum class DayFilterEnum : std::uint32_t { * some only non-trading, and some ignore type of day altogether. */ struct DXFCPP_EXPORT DayFilter { - friend struct Day; - /// Accepts any day - useful for pure calendar navigation. static const DayFilter ANY; @@ -130,7 +128,8 @@ struct DXFCPP_EXPORT DayFilter { /// Required trading flag, Tristate::NONE if not relevant. Tristate trading_; - JavaObjectHandle handle_; + mutable std::mutex mtx_{}; + mutable JavaObjectHandle handle_; /** * Creates filter with specified conditions. @@ -152,6 +151,10 @@ struct DXFCPP_EXPORT DayFilter { */ DayFilter(DayFilterEnum code, std::string name, std::uint32_t dayOfWeekMask, Tristate holiday, Tristate shortDay, Tristate trading) noexcept; + +public: + + const JavaObjectHandle& getHandle() const&; }; DXFCPP_END_NAMESPACE diff --git a/src/schedule/Day.cpp b/src/schedule/Day.cpp index 8f6c21453..9dcf0a026 100644 --- a/src/schedule/Day.cpp +++ b/src/schedule/Day.cpp @@ -139,15 +139,15 @@ std::shared_ptr Day::findLastSession(const SessionFilter &filter) const } Day::Ptr Day::getPrevDay(const DayFilter &filter) const { - return create(isolated::schedule::IsolatedDay::getPrevDay(handle_, filter.handle_)); + return create(isolated::schedule::IsolatedDay::getPrevDay(handle_, filter.getHandle())); } Day::Ptr Day::getNextDay(const DayFilter &filter) const { - return create(isolated::schedule::IsolatedDay::getNextDay(handle_, filter.handle_)); + return create(isolated::schedule::IsolatedDay::getNextDay(handle_, filter.getHandle())); } Day::Ptr Day::findPrevDay(const DayFilter &filter) const { - auto dayHandle = isolated::schedule::IsolatedDay::findPrevDay(handle_, filter.handle_); + auto dayHandle = isolated::schedule::IsolatedDay::findPrevDay(handle_, filter.getHandle()); if (!dayHandle) { return {}; @@ -157,7 +157,7 @@ Day::Ptr Day::findPrevDay(const DayFilter &filter) const { } Day::Ptr Day::findNextDay(const DayFilter &filter) const { - auto dayHandle = isolated::schedule::IsolatedDay::findNextDay(handle_, filter.handle_); + auto dayHandle = isolated::schedule::IsolatedDay::findNextDay(handle_, filter.getHandle()); if (!dayHandle) { return {}; diff --git a/src/schedule/DayFilter.cpp b/src/schedule/DayFilter.cpp index b4fc2f3bc..41066096a 100644 --- a/src/schedule/DayFilter.cpp +++ b/src/schedule/DayFilter.cpp @@ -13,8 +13,16 @@ DayFilter::DayFilter(DayFilterEnum code, std::string name, std::uint32_t dayOfWe Tristate shortDay, Tristate trading) noexcept : code_{code}, name_{std::move(name)}, dayOfWeekMask_{dayOfWeekMask}, holiday_{holiday}, shortDay_{shortDay}, trading_{trading} { +} + +const JavaObjectHandle& DayFilter::getHandle() const& { + std::lock_guard lock(mtx_); + + if (!handle_) { + handle_ = isolated::schedule::IsolatedDayFilter::getInstance(static_cast(code_)); + } - handle_ = isolated::schedule::IsolatedDayFilter::getInstance(static_cast(code)); + return handle_; } /// Accepts any day - useful for pure calendar navigation. From 554213ecc4b2a8e4ad8587fbbb4b5584e1effbfd Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 2 Oct 2024 15:24:35 +0300 Subject: [PATCH 101/178] [MDAPI-135] [C++] Add the ability to create a bundle to build with all dependencies. Make the Boost dependency optional. --- CMakeLists.txt | 67 ++++++--------------- DEPENDENCIES.md | 6 +- HOW_TO_BUILD.md | 2 + src/exceptions/GraalException.cpp | 5 -- src/exceptions/InvalidArgumentException.cpp | 3 - src/exceptions/JavaException.cpp | 3 - src/exceptions/RuntimeException.cpp | 16 ++++- 7 files changed, 35 insertions(+), 67 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f51473b1d..30d149de1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ option(DXFCXX_ENABLE_ASAN_UBSAN "Enable address, UB sanitizers etc" OFF) option(DXFCXX_ENABLE_VS_ASAN "Enable VS address sanitizer" OFF) option(DXFCXX_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) -option(DXFCXX_FEATURE_STACKTRACE "Allow capturing stacktraces using boost::stacktrace" ON) +option(DXFCXX_FEATURE_STACKTRACE "Allow capturing stacktraces using boost::stacktrace" OFF) include(FetchContent) @@ -146,39 +146,19 @@ FetchContent_MakeAvailable(fmt) #set(USE_SYSTEM_TZ_DB ON) add_subdirectory(third_party/date-${DATE_VERSION}) -set(BOOST_INCLUDE_LIBRARIES stacktrace) - -CPMAddPackage( - NAME Boost - VERSION ${BOOST_VERSION} - URL https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.tar.xz - OPTIONS "BOOST_ENABLE_CMAKE ON" - USES_TERMINAL_DOWNLOAD TRUE - GIT_PROGRESS TRUE - OVERRIDE_FIND_PACKAGE -) - -# -#FetchContent_Declare( -# Boost -# URL https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.7z # downloading a zip release speeds up the download -# USES_TERMINAL_DOWNLOAD TRUE -# GIT_PROGRESS TRUE -# DOWNLOAD_NO_EXTRACT FALSE -# OVERRIDE_FIND_PACKAGE -#) -#FetchContent_MakeAvailable(Boost) - - -#find_package( -# Boost -# 1.84 -# REQUIRED -# stacktrace -#) +if (DXFCXX_FEATURE_STACKTRACE) + set(BOOST_INCLUDE_LIBRARIES stacktrace) -# find_package(utf8cpp) -# find_package(fmt) + CPMAddPackage( + NAME Boost + VERSION ${BOOST_VERSION} + URL https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.tar.xz + OPTIONS "BOOST_ENABLE_CMAKE ON" + USES_TERMINAL_DOWNLOAD TRUE + GIT_PROGRESS TRUE + OVERRIDE_FIND_PACKAGE + ) +endif () set(dxFeedGraalCxxApi_Internal_Sources src/internal/CEntryPointErrors.cpp @@ -396,7 +376,7 @@ add_library(${PROJECT_NAME}_static STATIC if (WIN32) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") list(APPEND CMAKE_RC_FLAGS "--use-temp-file") - endif() + endif () add_library(${PROJECT_NAME} SHARED ${dxFeedGraalCxxApi_Sources} @@ -493,25 +473,12 @@ endif () target_link_libraries(${PROJECT_NAME} PUBLIC DxFeedGraalNativeSdk utf8cpp fmt::fmt-header-only date::date) target_link_libraries(${PROJECT_NAME}_static PUBLIC DxFeedGraalNativeSdk utf8cpp fmt::fmt-header-only date::date) -if (TARGET Boost::stacktrace_windbg) - message(STATUS "Has Boost::stacktrace_windbg") -endif () - -if (TARGET Boost::stacktrace_backtrace) - message(STATUS "Has Boost::stacktrace_backtrace") -endif () - -if (TARGET Boost::stacktrace_addr2line) - message(STATUS "Has Boost::stacktrace_addr2line") -endif () - -if (TARGET Boost::stacktrace_basic) - message(STATUS "Has Boost::stacktrace_basic") -endif () - if (DXFCXX_FEATURE_STACKTRACE) LinkStacktrace(${PROJECT_NAME}) LinkStacktrace(${PROJECT_NAME}_static) + + target_compile_definitions(${PROJECT_NAME} PUBLIC DXFCXX_FEATURE_STACKTRACE) + target_compile_definitions(${PROJECT_NAME}_static PUBLIC DXFCXX_FEATURE_STACKTRACE) endif () if (DXFCXX_ENABLE_ASAN_UBSAN) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 9821fed7c..0fbe74a68 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -4,7 +4,7 @@ - [dxFeed Graal Native SDK](https://github.com/dxFeed/dxfeed-graal-native-sdk) v1.1.23 - [Bundles](https://dxfeed.jfrog.io/artifactory/maven-open/com/dxfeed/graal-native-sdk/) -- [Boost](https://github.com/boostorg/boost) v1.84.0 +- \[opt] [Boost](https://github.com/boostorg/boost) v1.84.0 - Boost.Stacktrace 1.0 - [utfcpp](https://github.com/nemtrif/utfcpp) v3.2.3 - [fmt](https://github.com/fmtlib/fmt) v10.2.1 @@ -22,7 +22,7 @@ - dbgeng \[opt] (Diagnostic backtraces) - On Linux \ MacOS - libbacktrace \[opt] (Diagnostic backtraces) - - libdl (Diagnostic backtraces) + - libdl \[opt] (Diagnostic backtraces) - addr2line \[opt] (Diagnostic backtraces) ## Run-time @@ -37,6 +37,6 @@ - dbgeng \[opt] (Diagnostic backtraces) - On Linux \ MacOS - libbacktrace \[opt] (Diagnostic backtraces) - - libdl (Diagnostic backtraces) + - libdl \[opt] (Diagnostic backtraces) - addr2line \[opt] (Diagnostic backtraces) diff --git a/HOW_TO_BUILD.md b/HOW_TO_BUILD.md index ec40bd3e5..44ceccd7a 100644 --- a/HOW_TO_BUILD.md +++ b/HOW_TO_BUILD.md @@ -15,6 +15,8 @@ cmake --build . --config Release ``` +or use the `scripts` dir. Make sure that you use `command prompt for VS` on Win. + ## Run Tests ```shell diff --git a/src/exceptions/GraalException.cpp b/src/exceptions/GraalException.cpp index 58173c2ad..e432a81c5 100644 --- a/src/exceptions/GraalException.cpp +++ b/src/exceptions/GraalException.cpp @@ -5,13 +5,8 @@ #include -#include -#include - DXFCPP_BEGIN_NAMESPACE -std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace); - GraalException::GraalException(CEntryPointErrorsEnum entryPointErrorsEnum) : RuntimeException(createMessage(entryPointErrorsEnum)) { } diff --git a/src/exceptions/InvalidArgumentException.cpp b/src/exceptions/InvalidArgumentException.cpp index 55d50e15d..853caf71b 100644 --- a/src/exceptions/InvalidArgumentException.cpp +++ b/src/exceptions/InvalidArgumentException.cpp @@ -3,9 +3,6 @@ #include -#include -#include - DXFCPP_BEGIN_NAMESPACE InvalidArgumentException::InvalidArgumentException(const StringLikeWrapper &message, diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 489ee93dd..efa3a15f6 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -5,13 +5,10 @@ #include -#include #include DXFCPP_BEGIN_NAMESPACE -std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace); - JavaException::JavaException(const StringLikeWrapper &message, const StringLikeWrapper &className, const StringLikeWrapper &stackTrace) : RuntimeException(fmt::format("Java exception of type '{}' was thrown. {}", className.c_str(), message.c_str()), diff --git a/src/exceptions/RuntimeException.cpp b/src/exceptions/RuntimeException.cpp index c4b67b8e9..7cac1375e 100644 --- a/src/exceptions/RuntimeException.cpp +++ b/src/exceptions/RuntimeException.cpp @@ -3,11 +3,15 @@ #include -#include +#ifdef DXFCXX_FEATURE_STACKTRACE +# include +#endif + #include DXFCPP_BEGIN_NAMESPACE +#ifdef DXFCXX_FEATURE_STACKTRACE std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace) { std::string result; @@ -62,15 +66,21 @@ std::string stackTraceToString(const boost::stacktrace::stacktrace &stacktrace) return result; } +#endif RuntimeException::RuntimeException(const StringLikeWrapper &message, const StringLikeWrapper &additionalStackTrace) : std::runtime_error(message.c_str()), +#ifdef DXFCXX_FEATURE_STACKTRACE stackTrace_(additionalStackTrace.empty() ? stackTraceToString(boost::stacktrace::stacktrace()) : fmt::format("{}\n{}", additionalStackTrace.c_str(), - stackTraceToString(boost::stacktrace::stacktrace()))) { + stackTraceToString(boost::stacktrace::stacktrace()))) +#else + stackTrace_(additionalStackTrace) +#endif +{ } -RuntimeException::RuntimeException(const RuntimeException& other) noexcept = default; +RuntimeException::RuntimeException(const RuntimeException &other) noexcept = default; const std::string &RuntimeException::getStackTrace() const & { return stackTrace_; From c1cf439c6bd62867098a81ac8fadb41650fc0eee Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 2 Oct 2024 16:09:42 +0300 Subject: [PATCH 102/178] [MDAPI-135] [C++] Add the ability to create a bundle to build with all dependencies. Add fmt, Console, Process libs as 3d-party subdirs. --- CMakeLists.txt | 41 +- DEPENDENCIES.md | 2 +- third_party/Console-1.0.1/.clang-format | 15 + .../Console-1.0.1/.github/workflows/build.yml | 59 + third_party/Console-1.0.1/.gitignore | 38 + third_party/Console-1.0.1/CMakeLists.txt | 36 + third_party/Console-1.0.1/LICENSE | 23 + third_party/Console-1.0.1/README.md | 65 + .../Console-1.0.1/include/console/console.hpp | 47 + third_party/Console-1.0.1/src/console.cpp | 80 + third_party/Console-1.0.1/test/main.cpp | 13 + third_party/Process-3.0.1/.clang-format | 15 + .../Process-3.0.1/.github/workflows/build.yml | 59 + third_party/Process-3.0.1/.gitignore | 38 + third_party/Process-3.0.1/CMakeLists.txt | 42 + third_party/Process-3.0.1/LICENSE | 23 + third_party/Process-3.0.1/README.md | 90 + .../Process-3.0.1/include/process/process.hpp | 113 + .../Process-3.0.1/scripts/build_and_run.cmd | 19 + .../Process-3.0.1/scripts/build_and_run.sh | 10 + third_party/Process-3.0.1/src/process.cpp | 471 + third_party/Process-3.0.1/test/main.cpp | 62 + third_party/fmt-11.0.2/.clang-format | 8 + third_party/fmt-11.0.2/CMakeLists.txt | 520 + third_party/fmt-11.0.2/CONTRIBUTING.md | 20 + third_party/fmt-11.0.2/ChangeLog.md | 2628 +++ third_party/fmt-11.0.2/LICENSE | 27 + third_party/fmt-11.0.2/README.md | 484 + third_party/fmt-11.0.2/doc-html/404.html | 430 + third_party/fmt-11.0.2/doc-html/api.html | 1978 +++ .../doc-html/assets/_mkdocstrings.css | 0 .../doc-html/assets/images/favicon.png | Bin 0 -> 1870 bytes .../assets/javascripts/bundle.081f42fc.min.js | 29 + .../javascripts/bundle.081f42fc.min.js.map | 7 + .../javascripts/lunr/min/lunr.ar.min.js | 1 + .../javascripts/lunr/min/lunr.da.min.js | 18 + .../javascripts/lunr/min/lunr.de.min.js | 18 + .../javascripts/lunr/min/lunr.du.min.js | 18 + .../javascripts/lunr/min/lunr.el.min.js | 1 + .../javascripts/lunr/min/lunr.es.min.js | 18 + .../javascripts/lunr/min/lunr.fi.min.js | 18 + .../javascripts/lunr/min/lunr.fr.min.js | 18 + .../javascripts/lunr/min/lunr.he.min.js | 1 + .../javascripts/lunr/min/lunr.hi.min.js | 1 + .../javascripts/lunr/min/lunr.hu.min.js | 18 + .../javascripts/lunr/min/lunr.hy.min.js | 1 + .../javascripts/lunr/min/lunr.it.min.js | 18 + .../javascripts/lunr/min/lunr.ja.min.js | 1 + .../javascripts/lunr/min/lunr.jp.min.js | 1 + .../javascripts/lunr/min/lunr.kn.min.js | 1 + .../javascripts/lunr/min/lunr.ko.min.js | 1 + .../javascripts/lunr/min/lunr.multi.min.js | 1 + .../javascripts/lunr/min/lunr.nl.min.js | 18 + .../javascripts/lunr/min/lunr.no.min.js | 18 + .../javascripts/lunr/min/lunr.pt.min.js | 18 + .../javascripts/lunr/min/lunr.ro.min.js | 18 + .../javascripts/lunr/min/lunr.ru.min.js | 18 + .../javascripts/lunr/min/lunr.sa.min.js | 1 + .../lunr/min/lunr.stemmer.support.min.js | 1 + .../javascripts/lunr/min/lunr.sv.min.js | 18 + .../javascripts/lunr/min/lunr.ta.min.js | 1 + .../javascripts/lunr/min/lunr.te.min.js | 1 + .../javascripts/lunr/min/lunr.th.min.js | 1 + .../javascripts/lunr/min/lunr.tr.min.js | 18 + .../javascripts/lunr/min/lunr.vi.min.js | 1 + .../javascripts/lunr/min/lunr.zh.min.js | 1 + .../assets/javascripts/lunr/tinyseg.js | 206 + .../assets/javascripts/lunr/wordcut.js | 6708 +++++++ .../workers/search.b8dbb3d2.min.js | 42 + .../workers/search.b8dbb3d2.min.js.map | 7 + .../assets/stylesheets/main.6543a935.min.css | 1 + .../stylesheets/main.6543a935.min.css.map | 1 + .../stylesheets/palette.06af60db.min.css | 1 + .../stylesheets/palette.06af60db.min.css.map | 1 + third_party/fmt-11.0.2/doc-html/fmt.css | 61 + third_party/fmt-11.0.2/doc-html/fmt.js | 4 + .../fmt-11.0.2/doc-html/get-started.html | 800 + third_party/fmt-11.0.2/doc-html/index.html | 617 + third_party/fmt-11.0.2/doc-html/perf.svg | 1 + .../fmt-11.0.2/doc-html/python-license.txt | 290 + .../doc-html/search/search_index.json | 1 + third_party/fmt-11.0.2/doc-html/sitemap.xml | 3 + .../fmt-11.0.2/doc-html/sitemap.xml.gz | Bin 0 -> 127 bytes third_party/fmt-11.0.2/doc-html/syntax.html | 1362 ++ third_party/fmt-11.0.2/doc/ChangeLog-old.md | 3290 ++++ third_party/fmt-11.0.2/doc/api.md | 650 + third_party/fmt-11.0.2/doc/fmt.css | 61 + third_party/fmt-11.0.2/doc/fmt.js | 4 + third_party/fmt-11.0.2/doc/get-started.md | 222 + third_party/fmt-11.0.2/doc/index.md | 151 + third_party/fmt-11.0.2/doc/perf.svg | 1 + third_party/fmt-11.0.2/doc/python-license.txt | 290 + third_party/fmt-11.0.2/doc/syntax.md | 887 + third_party/fmt-11.0.2/include/fmt/args.h | 228 + third_party/fmt-11.0.2/include/fmt/base.h | 3077 ++++ third_party/fmt-11.0.2/include/fmt/chrono.h | 2432 +++ third_party/fmt-11.0.2/include/fmt/color.h | 612 + third_party/fmt-11.0.2/include/fmt/compile.h | 529 + third_party/fmt-11.0.2/include/fmt/core.h | 5 + .../fmt-11.0.2/include/fmt/format-inl.h | 1928 +++ third_party/fmt-11.0.2/include/fmt/format.h | 4427 +++++ third_party/fmt-11.0.2/include/fmt/os.h | 439 + third_party/fmt-11.0.2/include/fmt/ostream.h | 211 + third_party/fmt-11.0.2/include/fmt/printf.h | 656 + third_party/fmt-11.0.2/include/fmt/ranges.h | 882 + third_party/fmt-11.0.2/include/fmt/std.h | 699 + third_party/fmt-11.0.2/include/fmt/xchar.h | 322 + third_party/fmt-11.0.2/src/fmt.cc | 135 + third_party/fmt-11.0.2/src/format.cc | 43 + third_party/fmt-11.0.2/src/os.cc | 403 + third_party/fmt-11.0.2/support/Android.mk | 15 + .../fmt-11.0.2/support/AndroidManifest.xml | 1 + .../fmt-11.0.2/support/C++.sublime-syntax | 2061 +++ third_party/fmt-11.0.2/support/README | 4 + third_party/fmt-11.0.2/support/Vagrantfile | 19 + .../fmt-11.0.2/support/bazel/.bazelversion | 1 + .../fmt-11.0.2/support/bazel/BUILD.bazel | 20 + .../fmt-11.0.2/support/bazel/MODULE.bazel | 6 + .../fmt-11.0.2/support/bazel/README.md | 28 + .../fmt-11.0.2/support/bazel/WORKSPACE.bazel | 2 + third_party/fmt-11.0.2/support/build.gradle | 132 + third_party/fmt-11.0.2/support/check-commits | 43 + .../fmt-11.0.2/support/cmake/FindSetEnv.cmake | 7 + .../fmt-11.0.2/support/cmake/JoinPaths.cmake | 26 + .../support/cmake/fmt-config.cmake.in | 7 + .../fmt-11.0.2/support/cmake/fmt.pc.in | 11 + third_party/fmt-11.0.2/support/docopt.py | 581 + third_party/fmt-11.0.2/support/manage.py | 218 + third_party/fmt-11.0.2/support/mkdocs | 44 + third_party/fmt-11.0.2/support/mkdocs.yml | 48 + third_party/fmt-11.0.2/support/printable.py | 201 + .../mkdocstrings_handlers/cxx/__init__.py | 317 + .../cxx/templates/README | 1 + third_party/fmt-11.0.2/test/CMakeLists.txt | 272 + .../test/add-subdirectory-test/CMakeLists.txt | 17 + .../test/add-subdirectory-test/main.cc | 5 + third_party/fmt-11.0.2/test/args-test.cc | 188 + third_party/fmt-11.0.2/test/assert-test.cc | 31 + third_party/fmt-11.0.2/test/base-test.cc | 899 + third_party/fmt-11.0.2/test/chrono-test.cc | 1063 ++ third_party/fmt-11.0.2/test/color-test.cc | 72 + .../test/compile-error-test/CMakeLists.txt | 241 + .../fmt-11.0.2/test/compile-fp-test.cc | 61 + third_party/fmt-11.0.2/test/compile-test.cc | 385 + .../fmt-11.0.2/test/cuda-test/CMakeLists.txt | 73 + .../fmt-11.0.2/test/cuda-test/cpp14.cc | 11 + .../fmt-11.0.2/test/cuda-test/cuda-cpp14.cu | 28 + third_party/fmt-11.0.2/test/detect-stdfs.cc | 18 + .../fmt-11.0.2/test/enforce-checks-test.cc | 65 + .../test/find-package-test/CMakeLists.txt | 17 + .../fmt-11.0.2/test/find-package-test/main.cc | 5 + .../fmt-11.0.2/test/format-impl-test.cc | 476 + third_party/fmt-11.0.2/test/format-test.cc | 2465 +++ .../fmt-11.0.2/test/fuzzing/CMakeLists.txt | 30 + third_party/fmt-11.0.2/test/fuzzing/README.md | 25 + third_party/fmt-11.0.2/test/fuzzing/build.sh | 90 + .../test/fuzzing/chrono-duration.cc | 136 + .../test/fuzzing/chrono-timepoint.cc | 32 + third_party/fmt-11.0.2/test/fuzzing/float.cc | 39 + .../fmt-11.0.2/test/fuzzing/fuzzer-common.h | 77 + third_party/fmt-11.0.2/test/fuzzing/main.cc | 22 + .../fmt-11.0.2/test/fuzzing/named-arg.cc | 102 + .../fmt-11.0.2/test/fuzzing/one-arg.cc | 92 + .../fmt-11.0.2/test/fuzzing/two-args.cc | 106 + .../fmt-11.0.2/test/gtest-extra-test.cc | 410 + third_party/fmt-11.0.2/test/gtest-extra.cc | 80 + third_party/fmt-11.0.2/test/gtest-extra.h | 165 + .../fmt-11.0.2/test/gtest/.clang-format | 3 + .../fmt-11.0.2/test/gtest/CMakeLists.txt | 32 + .../fmt-11.0.2/test/gtest/gmock-gtest-all.cc | 14434 ++++++++++++++++ .../fmt-11.0.2/test/gtest/gmock/gmock.h | 11645 +++++++++++++ .../fmt-11.0.2/test/gtest/gtest/gtest-spi.h | 238 + .../fmt-11.0.2/test/gtest/gtest/gtest.h | 12398 +++++++++++++ .../fmt-11.0.2/test/header-only-test.cc | 11 + third_party/fmt-11.0.2/test/mock-allocator.h | 77 + third_party/fmt-11.0.2/test/module-test.cc | 520 + .../fmt-11.0.2/test/noexception-test.cc | 18 + third_party/fmt-11.0.2/test/os-test.cc | 516 + third_party/fmt-11.0.2/test/ostream-test.cc | 308 + third_party/fmt-11.0.2/test/perf-sanity.cc | 25 + .../fmt-11.0.2/test/posix-mock-test.cc | 442 + third_party/fmt-11.0.2/test/posix-mock.h | 75 + third_party/fmt-11.0.2/test/printf-test.cc | 568 + .../fmt-11.0.2/test/ranges-odr-test.cc | 18 + third_party/fmt-11.0.2/test/ranges-test.cc | 789 + third_party/fmt-11.0.2/test/scan-test.cc | 184 + third_party/fmt-11.0.2/test/scan.h | 669 + .../test/static-export-test/CMakeLists.txt | 30 + .../test/static-export-test/library.cc | 5 + .../test/static-export-test/main.cc | 6 + third_party/fmt-11.0.2/test/std-test.cc | 390 + third_party/fmt-11.0.2/test/test-assert.h | 39 + third_party/fmt-11.0.2/test/test-main.cc | 43 + third_party/fmt-11.0.2/test/unicode-test.cc | 48 + third_party/fmt-11.0.2/test/util.cc | 49 + third_party/fmt-11.0.2/test/util.h | 83 + third_party/fmt-11.0.2/test/xchar-test.cc | 600 + 197 files changed, 96308 insertions(+), 15 deletions(-) create mode 100644 third_party/Console-1.0.1/.clang-format create mode 100644 third_party/Console-1.0.1/.github/workflows/build.yml create mode 100644 third_party/Console-1.0.1/.gitignore create mode 100644 third_party/Console-1.0.1/CMakeLists.txt create mode 100644 third_party/Console-1.0.1/LICENSE create mode 100644 third_party/Console-1.0.1/README.md create mode 100644 third_party/Console-1.0.1/include/console/console.hpp create mode 100644 third_party/Console-1.0.1/src/console.cpp create mode 100644 third_party/Console-1.0.1/test/main.cpp create mode 100644 third_party/Process-3.0.1/.clang-format create mode 100644 third_party/Process-3.0.1/.github/workflows/build.yml create mode 100644 third_party/Process-3.0.1/.gitignore create mode 100644 third_party/Process-3.0.1/CMakeLists.txt create mode 100644 third_party/Process-3.0.1/LICENSE create mode 100644 third_party/Process-3.0.1/README.md create mode 100644 third_party/Process-3.0.1/include/process/process.hpp create mode 100644 third_party/Process-3.0.1/scripts/build_and_run.cmd create mode 100644 third_party/Process-3.0.1/scripts/build_and_run.sh create mode 100644 third_party/Process-3.0.1/src/process.cpp create mode 100644 third_party/Process-3.0.1/test/main.cpp create mode 100644 third_party/fmt-11.0.2/.clang-format create mode 100644 third_party/fmt-11.0.2/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/CONTRIBUTING.md create mode 100644 third_party/fmt-11.0.2/ChangeLog.md create mode 100644 third_party/fmt-11.0.2/LICENSE create mode 100644 third_party/fmt-11.0.2/README.md create mode 100644 third_party/fmt-11.0.2/doc-html/404.html create mode 100644 third_party/fmt-11.0.2/doc-html/api.html create mode 100644 third_party/fmt-11.0.2/doc-html/assets/_mkdocstrings.css create mode 100644 third_party/fmt-11.0.2/doc-html/assets/images/favicon.png create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js.map create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.el.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.he.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.hy.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.kn.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.sa.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.te.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/tinyseg.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/lunr/wordcut.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/workers/search.b8dbb3d2.min.js create mode 100644 third_party/fmt-11.0.2/doc-html/assets/javascripts/workers/search.b8dbb3d2.min.js.map create mode 100644 third_party/fmt-11.0.2/doc-html/assets/stylesheets/main.6543a935.min.css create mode 100644 third_party/fmt-11.0.2/doc-html/assets/stylesheets/main.6543a935.min.css.map create mode 100644 third_party/fmt-11.0.2/doc-html/assets/stylesheets/palette.06af60db.min.css create mode 100644 third_party/fmt-11.0.2/doc-html/assets/stylesheets/palette.06af60db.min.css.map create mode 100644 third_party/fmt-11.0.2/doc-html/fmt.css create mode 100644 third_party/fmt-11.0.2/doc-html/fmt.js create mode 100644 third_party/fmt-11.0.2/doc-html/get-started.html create mode 100644 third_party/fmt-11.0.2/doc-html/index.html create mode 100644 third_party/fmt-11.0.2/doc-html/perf.svg create mode 100644 third_party/fmt-11.0.2/doc-html/python-license.txt create mode 100644 third_party/fmt-11.0.2/doc-html/search/search_index.json create mode 100644 third_party/fmt-11.0.2/doc-html/sitemap.xml create mode 100644 third_party/fmt-11.0.2/doc-html/sitemap.xml.gz create mode 100644 third_party/fmt-11.0.2/doc-html/syntax.html create mode 100644 third_party/fmt-11.0.2/doc/ChangeLog-old.md create mode 100644 third_party/fmt-11.0.2/doc/api.md create mode 100644 third_party/fmt-11.0.2/doc/fmt.css create mode 100644 third_party/fmt-11.0.2/doc/fmt.js create mode 100644 third_party/fmt-11.0.2/doc/get-started.md create mode 100644 third_party/fmt-11.0.2/doc/index.md create mode 100644 third_party/fmt-11.0.2/doc/perf.svg create mode 100644 third_party/fmt-11.0.2/doc/python-license.txt create mode 100644 third_party/fmt-11.0.2/doc/syntax.md create mode 100644 third_party/fmt-11.0.2/include/fmt/args.h create mode 100644 third_party/fmt-11.0.2/include/fmt/base.h create mode 100644 third_party/fmt-11.0.2/include/fmt/chrono.h create mode 100644 third_party/fmt-11.0.2/include/fmt/color.h create mode 100644 third_party/fmt-11.0.2/include/fmt/compile.h create mode 100644 third_party/fmt-11.0.2/include/fmt/core.h create mode 100644 third_party/fmt-11.0.2/include/fmt/format-inl.h create mode 100644 third_party/fmt-11.0.2/include/fmt/format.h create mode 100644 third_party/fmt-11.0.2/include/fmt/os.h create mode 100644 third_party/fmt-11.0.2/include/fmt/ostream.h create mode 100644 third_party/fmt-11.0.2/include/fmt/printf.h create mode 100644 third_party/fmt-11.0.2/include/fmt/ranges.h create mode 100644 third_party/fmt-11.0.2/include/fmt/std.h create mode 100644 third_party/fmt-11.0.2/include/fmt/xchar.h create mode 100644 third_party/fmt-11.0.2/src/fmt.cc create mode 100644 third_party/fmt-11.0.2/src/format.cc create mode 100644 third_party/fmt-11.0.2/src/os.cc create mode 100644 third_party/fmt-11.0.2/support/Android.mk create mode 100644 third_party/fmt-11.0.2/support/AndroidManifest.xml create mode 100644 third_party/fmt-11.0.2/support/C++.sublime-syntax create mode 100644 third_party/fmt-11.0.2/support/README create mode 100644 third_party/fmt-11.0.2/support/Vagrantfile create mode 100644 third_party/fmt-11.0.2/support/bazel/.bazelversion create mode 100644 third_party/fmt-11.0.2/support/bazel/BUILD.bazel create mode 100644 third_party/fmt-11.0.2/support/bazel/MODULE.bazel create mode 100644 third_party/fmt-11.0.2/support/bazel/README.md create mode 100644 third_party/fmt-11.0.2/support/bazel/WORKSPACE.bazel create mode 100644 third_party/fmt-11.0.2/support/build.gradle create mode 100644 third_party/fmt-11.0.2/support/check-commits create mode 100644 third_party/fmt-11.0.2/support/cmake/FindSetEnv.cmake create mode 100644 third_party/fmt-11.0.2/support/cmake/JoinPaths.cmake create mode 100644 third_party/fmt-11.0.2/support/cmake/fmt-config.cmake.in create mode 100644 third_party/fmt-11.0.2/support/cmake/fmt.pc.in create mode 100644 third_party/fmt-11.0.2/support/docopt.py create mode 100644 third_party/fmt-11.0.2/support/manage.py create mode 100644 third_party/fmt-11.0.2/support/mkdocs create mode 100644 third_party/fmt-11.0.2/support/mkdocs.yml create mode 100644 third_party/fmt-11.0.2/support/printable.py create mode 100644 third_party/fmt-11.0.2/support/python/mkdocstrings_handlers/cxx/__init__.py create mode 100644 third_party/fmt-11.0.2/support/python/mkdocstrings_handlers/cxx/templates/README create mode 100644 third_party/fmt-11.0.2/test/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/add-subdirectory-test/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/add-subdirectory-test/main.cc create mode 100644 third_party/fmt-11.0.2/test/args-test.cc create mode 100644 third_party/fmt-11.0.2/test/assert-test.cc create mode 100644 third_party/fmt-11.0.2/test/base-test.cc create mode 100644 third_party/fmt-11.0.2/test/chrono-test.cc create mode 100644 third_party/fmt-11.0.2/test/color-test.cc create mode 100644 third_party/fmt-11.0.2/test/compile-error-test/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/compile-fp-test.cc create mode 100644 third_party/fmt-11.0.2/test/compile-test.cc create mode 100644 third_party/fmt-11.0.2/test/cuda-test/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/cuda-test/cpp14.cc create mode 100644 third_party/fmt-11.0.2/test/cuda-test/cuda-cpp14.cu create mode 100644 third_party/fmt-11.0.2/test/detect-stdfs.cc create mode 100644 third_party/fmt-11.0.2/test/enforce-checks-test.cc create mode 100644 third_party/fmt-11.0.2/test/find-package-test/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/find-package-test/main.cc create mode 100644 third_party/fmt-11.0.2/test/format-impl-test.cc create mode 100644 third_party/fmt-11.0.2/test/format-test.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/fuzzing/README.md create mode 100644 third_party/fmt-11.0.2/test/fuzzing/build.sh create mode 100644 third_party/fmt-11.0.2/test/fuzzing/chrono-duration.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/chrono-timepoint.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/float.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/fuzzer-common.h create mode 100644 third_party/fmt-11.0.2/test/fuzzing/main.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/named-arg.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/one-arg.cc create mode 100644 third_party/fmt-11.0.2/test/fuzzing/two-args.cc create mode 100644 third_party/fmt-11.0.2/test/gtest-extra-test.cc create mode 100644 third_party/fmt-11.0.2/test/gtest-extra.cc create mode 100644 third_party/fmt-11.0.2/test/gtest-extra.h create mode 100644 third_party/fmt-11.0.2/test/gtest/.clang-format create mode 100644 third_party/fmt-11.0.2/test/gtest/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/gtest/gmock-gtest-all.cc create mode 100644 third_party/fmt-11.0.2/test/gtest/gmock/gmock.h create mode 100644 third_party/fmt-11.0.2/test/gtest/gtest/gtest-spi.h create mode 100644 third_party/fmt-11.0.2/test/gtest/gtest/gtest.h create mode 100644 third_party/fmt-11.0.2/test/header-only-test.cc create mode 100644 third_party/fmt-11.0.2/test/mock-allocator.h create mode 100644 third_party/fmt-11.0.2/test/module-test.cc create mode 100644 third_party/fmt-11.0.2/test/noexception-test.cc create mode 100644 third_party/fmt-11.0.2/test/os-test.cc create mode 100644 third_party/fmt-11.0.2/test/ostream-test.cc create mode 100644 third_party/fmt-11.0.2/test/perf-sanity.cc create mode 100644 third_party/fmt-11.0.2/test/posix-mock-test.cc create mode 100644 third_party/fmt-11.0.2/test/posix-mock.h create mode 100644 third_party/fmt-11.0.2/test/printf-test.cc create mode 100644 third_party/fmt-11.0.2/test/ranges-odr-test.cc create mode 100644 third_party/fmt-11.0.2/test/ranges-test.cc create mode 100644 third_party/fmt-11.0.2/test/scan-test.cc create mode 100644 third_party/fmt-11.0.2/test/scan.h create mode 100644 third_party/fmt-11.0.2/test/static-export-test/CMakeLists.txt create mode 100644 third_party/fmt-11.0.2/test/static-export-test/library.cc create mode 100644 third_party/fmt-11.0.2/test/static-export-test/main.cc create mode 100644 third_party/fmt-11.0.2/test/std-test.cc create mode 100644 third_party/fmt-11.0.2/test/test-assert.h create mode 100644 third_party/fmt-11.0.2/test/test-main.cc create mode 100644 third_party/fmt-11.0.2/test/unicode-test.cc create mode 100644 third_party/fmt-11.0.2/test/util.cc create mode 100644 third_party/fmt-11.0.2/test/util.h create mode 100644 third_party/fmt-11.0.2/test/xchar-test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 30d149de1..98332c46c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,12 +22,12 @@ set(DXFCXX_VERSION "v3.0.0-rc1" CACHE STRING "The dxFeed Graal CXX API package v dxfcxx_ParseVersion(${DXFCXX_VERSION} DXFCXX_MAJOR_VERSION DXFCXX_MINOR_VERSION DXFCXX_PATCH_VERSION DXFCXX_SUFFIX_VERSION) set(DXFEED_GRAAL_NATIVE_SDK_VERSION "1.1.23" CACHE STRING "") -set(FMTLIB_VERSION "10.2.1") +set(FMTLIB_VERSION "11.0.2") set(BOOST_VERSION "1.84.0") set(UTFCPP_VERSION "3.2.3") set(DATE_VERSION "3.0.1") -set(PROCESS_VERSION "v3.0.1") -set(CONSOLE_VERSION "v1.0.1") +set(PROCESS_VERSION "3.0.1") +set(CONSOLE_VERSION "1.0.1") set(RANGE_VERSION "0.12") set(DOCTEST_VERSION "2.4.11") set(CPM_CMAKE_VERSION "v0.40.2") @@ -125,22 +125,35 @@ endif () FetchContent_MakeAvailable(DxFeedGraalNativeSdk) # DxFeedGraalNativeSdk_SOURCE_DIR -CPMAddPackage("gh:ttldtor/Process#${PROCESS_VERSION}") -CPMAddPackage("gh:ttldtor/Console#${CONSOLE_VERSION}") +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Process-${PROCESS_VERSION}/CMakeLists.txt") + add_subdirectory(third_party/Process-${PROCESS_VERSION}) +else () + CPMAddPackage("gh:ttldtor/Process#v${PROCESS_VERSION}") +endif () + +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Console-${CONSOLE_VERSION}/CMakeLists.txt") + add_subdirectory(third_party/Console-${CONSOLE_VERSION}) +else () + CPMAddPackage("gh:ttldtor/Console#v${CONSOLE_VERSION}") +endif () add_subdirectory(third_party/utfcpp-${UTFCPP_VERSION}) set(FMT_INSTALL OFF) -FetchContent_Declare( - fmt - URL https://github.com/fmtlib/fmt/releases/download/${FMTLIB_VERSION}/fmt-${FMTLIB_VERSION}.zip # downloading a zip release speeds up the download - USES_TERMINAL_DOWNLOAD TRUE - GIT_PROGRESS TRUE - DOWNLOAD_NO_EXTRACT FALSE - OVERRIDE_FIND_PACKAGE -) -FetchContent_MakeAvailable(fmt) +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/fmt-${FMTLIB_VERSION}/CMakeLists.txt") + add_subdirectory(third_party/fmt-${FMTLIB_VERSION}) +else () + FetchContent_Declare( + fmt + URL https://github.com/fmtlib/fmt/releases/download/${FMTLIB_VERSION}/fmt-${FMTLIB_VERSION}.zip # downloading a zip release speeds up the download + USES_TERMINAL_DOWNLOAD TRUE + GIT_PROGRESS TRUE + DOWNLOAD_NO_EXTRACT FALSE + OVERRIDE_FIND_PACKAGE + ) + FetchContent_MakeAvailable(fmt) +endif () #set(BUILD_TZ_LIB ON) #set(USE_SYSTEM_TZ_DB ON) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 0fbe74a68..9efc078a4 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -7,7 +7,7 @@ - \[opt] [Boost](https://github.com/boostorg/boost) v1.84.0 - Boost.Stacktrace 1.0 - [utfcpp](https://github.com/nemtrif/utfcpp) v3.2.3 -- [fmt](https://github.com/fmtlib/fmt) v10.2.1 +- [fmt](https://github.com/fmtlib/fmt) v11.0.2 - [doctest](https://github.com/doctest/doctest) v2.4.11 (Tests) - [range-v3](https://github.com/ericniebler/range-v3) v0.12 - [date](https://github.com/HowardHinnant/date) v3.0.1 diff --git a/third_party/Console-1.0.1/.clang-format b/third_party/Console-1.0.1/.clang-format new file mode 100644 index 000000000..9d7c6296d --- /dev/null +++ b/third_party/Console-1.0.1/.clang-format @@ -0,0 +1,15 @@ +# Copyright (c) 2023 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +BasedOnStyle: LLVM +ColumnLimit: 120 +ContinuationIndentWidth: 4 +IndentPPDirectives: AfterHash +TabWidth: 4 +IndentWidth: 4 +UseTab: Never +AllowShortBlocksOnASingleLine: Never +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: None +AllowShortLoopsOnASingleLine: false diff --git a/third_party/Console-1.0.1/.github/workflows/build.yml b/third_party/Console-1.0.1/.github/workflows/build.yml new file mode 100644 index 000000000..484eafc3c --- /dev/null +++ b/third_party/Console-1.0.1/.github/workflows/build.yml @@ -0,0 +1,59 @@ +# Copyright (c) 2023 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +name: CI + +on: + pull_request: + workflow_dispatch: + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: 'Release' + XCODE_VERSION: '15.0' + GCC_VERSION: '12' + +jobs: + build: + strategy: + matrix: + # os: [windows-latest, macos-latest, ubuntu-latest] + os: [ windows-latest, macos-13, ubuntu-22.04 ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - name: Select Xcode version + if: ${{ contains(matrix.os, 'macos') }} + run: sudo xcode-select -s '/Applications/Xcode_${{env.XCODE_VERSION}}.app/Contents/Developer' + + - name: Prepare build + run: | + ls + mkdir ${{github.workspace}}/build + + - name: Configure CMake (!Ubuntu) + if: ${{ !contains(matrix.os, 'ubuntu') }} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Configure CMake (Ubuntu) + env: + CC: gcc-${{env.GCC_VERSION}} + CXX: g++-${{env.GCC_VERSION}} + if: ${{ contains(matrix.os, 'ubuntu') }} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test (!Win) + if: ${{ !contains(matrix.os, 'windows') }} + working-directory: ${{github.workspace}}/build + run: ./console_test + + - name: Test (Win) + if: ${{ contains(matrix.os, 'windows') }} + working-directory: ${{github.workspace}}/build/${{env.BUILD_TYPE}} + run: ./console_test diff --git a/third_party/Console-1.0.1/.gitignore b/third_party/Console-1.0.1/.gitignore new file mode 100644 index 000000000..3255e3f65 --- /dev/null +++ b/third_party/Console-1.0.1/.gitignore @@ -0,0 +1,38 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +cmake-build-*/** +.idea/** +build/** +scripts/build-*/ +.vs/** \ No newline at end of file diff --git a/third_party/Console-1.0.1/CMakeLists.txt b/third_party/Console-1.0.1/CMakeLists.txt new file mode 100644 index 000000000..e7cb1735f --- /dev/null +++ b/third_party/Console-1.0.1/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2023 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +cmake_minimum_required(VERSION 3.20) + +project(console) +include(GNUInstallDirs) + +set(TTLDTOR_CONSOLE "v1.0.1" CACHE STRING "The Console package version") + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_C_STANDARD 11) +set(CXX_EXTENSIONS OFF) +set(C_EXTENSIONS OFF) + +# Determine if console is built as a subproject (using add_subdirectory) +# or if it is the master project. +if (NOT DEFINED TTLDTOR_CONSOLE_ROOT_PROJECT) + set(TTLDTOR_CONSOLE_ROOT_PROJECT OFF) + if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(TTLDTOR_CONSOLE_ROOT_PROJECT ON) + message(STATUS "CMake version: ${CMAKE_VERSION}") + endif () +endif () + +option(TTLDTOR_CONSOLE_SAMPLES "Enable building samples for Console" ${TTLDTOR_CONSOLE_ROOT_PROJECT}) + +add_library(${PROJECT_NAME} src/console.cpp) +target_include_directories(${PROJECT_NAME} PUBLIC include) + +add_library(console::console ALIAS ${PROJECT_NAME}) + +if (TTLDTOR_CONSOLE_SAMPLES) + add_executable(${PROJECT_NAME}_test test/main.cpp) + target_link_libraries(${PROJECT_NAME}_test console) +endif () \ No newline at end of file diff --git a/third_party/Console-1.0.1/LICENSE b/third_party/Console-1.0.1/LICENSE new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/third_party/Console-1.0.1/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/third_party/Console-1.0.1/README.md b/third_party/Console-1.0.1/README.md new file mode 100644 index 000000000..ed4be6246 --- /dev/null +++ b/third_party/Console-1.0.1/README.md @@ -0,0 +1,65 @@ +# Console +Cross-platform library of utilities for working with the console. + +[![Build](https://github.com/ttldtor/Console/actions/workflows/build.yml/badge.svg?branch=default)](https://github.com/ttldtor/Console/actions/workflows/build.yml) +[![Release](https://img.shields.io/github/v/release/ttldtor/Console)](https://github.com/ttldtor/Console/releases/latest) +![](https://img.shields.io/badge/C++%20standard-C++11-blueviolet) +[![License](https://img.shields.io/badge/license-BSL--1.0-orange)](https://github.com/ttldtor/Console/blob/default/LICENSE) +[![Downloads](https://img.shields.io/github/downloads/ttldtor/Console/total)](https://github.com/ttldtor/Console/releases/latest) + +### Status: +* [x] Windows +* [x] Linux +* [x] MacOS +* [ ] Termux +* [ ] FreeBSD +* [ ] OpenBSD +* [ ] AIX +* [ ] ... + +### Example: + +_**CMakeLists.txt:**_ +```cmake +cmake_minimum_required(VERSION 3.20) + +project(Test LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_C_STANDARD 11) +set(CXX_EXTENSIONS OFF) +set(C_EXTENSIONS OFF) + +include(FetchContent) +FetchContent_Declare(Console GIT_REPOSITORY "https://github.com/ttldtor/Console.git" GIT_TAG default) +FetchContent_MakeAvailable(Console) + +add_executable(${PROJECT_NAME} + main.cpp +) + +target_link_libraries(${PROJECT_NAME} PRIVATE console::console) + +``` + +**_main.cpp:_** +```cpp +#include + +#include + +using namespace org::ttldtor::console; + +int main() { + auto consoleSize = Console::getSize(); + + std::cout << "Console size: " << consoleSize.first << " x " << consoleSize.second << std::endl; + + return 0; +} +``` + +_**Program output:**_ +```text +Console size: 120 x 27 +``` \ No newline at end of file diff --git a/third_party/Console-1.0.1/include/console/console.hpp b/third_party/Console-1.0.1/include/console/console.hpp new file mode 100644 index 000000000..205d9206b --- /dev/null +++ b/third_party/Console-1.0.1/include/console/console.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2023 ttldtor. +// SPDX-License-Identifier: BSL-1.0 + +#pragma once + +#ifdef TTLDTOR_CONSOLE_EXPORT +# error TTLDTOR_CONSOLE_EXPORT was previously defined +#endif + +#if defined(TTLDTOR_CONSOLE_USE_DLLS) && defined(_MSC_VER) +# if defined(LIB_TTLDTOR_CONSOLE_EXPORTS) +# define TTLDTOR_CONSOLE_EXPORT __declspec(dllexport) +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DECLARE +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DEFINE __declspec(dllexport) +# else +# define TTLDTOR_CONSOLE_EXPORT __declspec(dllimport) +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DECLARE +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DEFINE __declspec(dllimport) +# endif // defined(LIB_TTLDTOR_CONSOLE) +#elif defined(TTLDTOR_CONSOLE_USE_DLLS) && defined(LIB_TTLDTOR_CONSOLE_EXPORTS) +# define TTLDTOR_CONSOLE_EXPORT __attribute__((visibility("default"))) +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default"))) +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DEFINE +#else +# define TTLDTOR_CONSOLE_EXPORT +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DECLARE +# define TTLDTOR_CONSOLE_EXPORT_TEMPLATE_DEFINE +#endif + +#include +#include + +namespace org { +namespace ttldtor { +namespace console { + +struct TTLDTOR_CONSOLE_EXPORT Console { + /** + * Returns the width and height of the current console. + * @return The width and height of the current console. + */ + static std::pair getSize() noexcept; +}; + +} // namespace console +} // namespace ttldtor +} // namespace org diff --git a/third_party/Console-1.0.1/src/console.cpp b/third_party/Console-1.0.1/src/console.cpp new file mode 100644 index 000000000..29e316013 --- /dev/null +++ b/third_party/Console-1.0.1/src/console.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2023 ttldtor. +// SPDX-License-Identifier: BSL-1.0 + +#include + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +# include + +namespace org { +namespace ttldtor { +namespace console { + +std::pair Console::getSize() noexcept { + CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo{}; + std::size_t columns{}, rows{}; + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleScreenBufferInfo); + columns = + static_cast(consoleScreenBufferInfo.srWindow.Right - consoleScreenBufferInfo.srWindow.Left + 1); + rows = static_cast(consoleScreenBufferInfo.srWindow.Bottom - consoleScreenBufferInfo.srWindow.Top + 1); + + return {columns, rows}; +} + +} // namespace console +} // namespace ttldtor +} // namespace org + +#elif defined(__CYGWIN__) || defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__) +# include // open(), O_EVTONLY, O_NONBLOCK +# include // ioctl() +# include // close() + +namespace org { +namespace ttldtor { +namespace console { + +std::pair Console::getSize() noexcept { +# if defined(__APPLE__) + auto ttyFileDescriptor = open("/dev/tty", O_EVTONLY | O_NONBLOCK); +# else + auto ttyFileDescriptor = open("/dev/tty", O_RDWR); +# endif + + if (ttyFileDescriptor == -1) { + return {80, 25}; + } + + winsize winSize{}; + + auto result = ioctl(ttyFileDescriptor, TIOCGWINSZ, &winSize); + + close(ttyFileDescriptor); + + if (result == -1) { + return {80, 25}; + } + + return {static_cast(winSize.ws_col), static_cast(winSize.ws_row)}; +} + +} // namespace console +} // namespace ttldtor +} // namespace org + +#else + +namespace org { +namespace ttldtor { +namespace console { + +std::pair Console::getSize() noexcept { + return {80, 25}; +} + +} // namespace console +} // namespace ttldtor +} // namespace org + +#endif \ No newline at end of file diff --git a/third_party/Console-1.0.1/test/main.cpp b/third_party/Console-1.0.1/test/main.cpp new file mode 100644 index 000000000..8043f0c68 --- /dev/null +++ b/third_party/Console-1.0.1/test/main.cpp @@ -0,0 +1,13 @@ +#include + +#include + +using namespace org::ttldtor::console; + +int main() { + auto consoleSize = Console::getSize(); + + std::cout << "Console size: " << consoleSize.first << " x " << consoleSize.second << std::endl; + + return 0; +} \ No newline at end of file diff --git a/third_party/Process-3.0.1/.clang-format b/third_party/Process-3.0.1/.clang-format new file mode 100644 index 000000000..9d7c6296d --- /dev/null +++ b/third_party/Process-3.0.1/.clang-format @@ -0,0 +1,15 @@ +# Copyright (c) 2023 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +BasedOnStyle: LLVM +ColumnLimit: 120 +ContinuationIndentWidth: 4 +IndentPPDirectives: AfterHash +TabWidth: 4 +IndentWidth: 4 +UseTab: Never +AllowShortBlocksOnASingleLine: Never +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: None +AllowShortLoopsOnASingleLine: false diff --git a/third_party/Process-3.0.1/.github/workflows/build.yml b/third_party/Process-3.0.1/.github/workflows/build.yml new file mode 100644 index 000000000..f0bd4434c --- /dev/null +++ b/third_party/Process-3.0.1/.github/workflows/build.yml @@ -0,0 +1,59 @@ +# Copyright (c) 2023 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +name: CI + +on: + pull_request: + workflow_dispatch: + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: 'Release' + XCODE_VERSION: '15.0' + GCC_VERSION: '12' + +jobs: + build: + strategy: + matrix: + # os: [windows-latest, macos-latest, ubuntu-latest] + os: [ windows-latest, macos-13, ubuntu-22.04, macos-14 ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - name: Select Xcode version + if: ${{ contains(matrix.os, 'macos') }} + run: sudo xcode-select -s '/Applications/Xcode_${{env.XCODE_VERSION}}.app/Contents/Developer' + + - name: Prepare build + run: | + ls + mkdir ${{github.workspace}}/build + + - name: Configure CMake (!Ubuntu) + if: ${{ !contains(matrix.os, 'ubuntu') }} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Configure CMake (Ubuntu) + env: + CC: gcc-${{env.GCC_VERSION}} + CXX: g++-${{env.GCC_VERSION}} + if: ${{ contains(matrix.os, 'ubuntu') }} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test (!Win) + if: ${{ !contains(matrix.os, 'windows') }} + working-directory: ${{github.workspace}}/build + run: ./process_test + + - name: Test (Win) + if: ${{ contains(matrix.os, 'windows') }} + working-directory: ${{github.workspace}}/build/${{env.BUILD_TYPE}} + run: ./process_test diff --git a/third_party/Process-3.0.1/.gitignore b/third_party/Process-3.0.1/.gitignore new file mode 100644 index 000000000..3255e3f65 --- /dev/null +++ b/third_party/Process-3.0.1/.gitignore @@ -0,0 +1,38 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +cmake-build-*/** +.idea/** +build/** +scripts/build-*/ +.vs/** \ No newline at end of file diff --git a/third_party/Process-3.0.1/CMakeLists.txt b/third_party/Process-3.0.1/CMakeLists.txt new file mode 100644 index 000000000..87e9e7388 --- /dev/null +++ b/third_party/Process-3.0.1/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (c) 2023 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +cmake_minimum_required(VERSION 3.20) + +project(process) +include(GNUInstallDirs) + +set(TTLDTOR_PROCESS "v3.0.1" CACHE STRING "The Process package version") + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 11) +set(CXX_EXTENSIONS OFF) +set(C_EXTENSIONS OFF) + +# Determine if process is built as a subproject (using add_subdirectory) +# or if it is the master project. +if (NOT DEFINED TTLDTOR_PROCESS_ROOT_PROJECT) + set(TTLDTOR_PROCESS_ROOT_PROJECT OFF) + if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(TTLDTOR_PROCESS_ROOT_PROJECT ON) + message(STATUS "CMake version: ${CMAKE_VERSION}") + endif () +endif () + +option(TTLDTOR_PROCESS_SAMPLES "Enable building samples for Process" ${TTLDTOR_PROCESS_ROOT_PROJECT}) + +add_library(${PROJECT_NAME} src/process.cpp) +target_include_directories(${PROJECT_NAME} PUBLIC include) + +add_library(process::process ALIAS ${PROJECT_NAME}) + +if (WIN32) + target_link_libraries(process PRIVATE psapi) +else () + message(STATUS "Platform: " ${CMAKE_SYSTEM_NAME}) +endif () + +if (TTLDTOR_PROCESS_SAMPLES) + add_executable(${PROJECT_NAME}_test test/main.cpp) + target_link_libraries(${PROJECT_NAME}_test process) +endif () \ No newline at end of file diff --git a/third_party/Process-3.0.1/LICENSE b/third_party/Process-3.0.1/LICENSE new file mode 100644 index 000000000..36b7cd93c --- /dev/null +++ b/third_party/Process-3.0.1/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/third_party/Process-3.0.1/README.md b/third_party/Process-3.0.1/README.md new file mode 100644 index 000000000..435a796f8 --- /dev/null +++ b/third_party/Process-3.0.1/README.md @@ -0,0 +1,90 @@ +# Process +Cross-platform library of utilities for obtaining metrics of the current process + +[![Build](https://github.com/ttldtor/Process/actions/workflows/build.yml/badge.svg?branch=default)](https://github.com/ttldtor/Process/actions/workflows/build.yml) +[![Release](https://img.shields.io/github/v/release/ttldtor/Process)](https://github.com/ttldtor/Process/releases/latest) +![](https://img.shields.io/badge/C++%20standard-C++14-blueviolet) +[![License](https://img.shields.io/badge/license-BSL--1.0-orange)](https://github.com/ttldtor/Process/blob/default/LICENSE) +[![Downloads](https://img.shields.io/github/downloads/ttldtor/Process/total)](https://github.com/ttldtor/Process/releases/latest) + +### Status: +* [x] Windows +* [x] Linux +* [x] MacOS +* [x] Android. [Example](https://github.com/ttldtor/ProcessExample) +* [x] Termux +* [x] FreeBSD +* [ ] OpenBSD +* [ ] AIX +* [ ] ... + +### Example: + +_**CMakeLists.txt:**_ +```cmake +cmake_minimum_required(VERSION 3.20) + +project(Test LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_C_STANDARD 11) +set(CXX_EXTENSIONS OFF) +set(C_EXTENSIONS OFF) + +include(FetchContent) +FetchContent_Declare(Process GIT_REPOSITORY "https://github.com/ttldtor/Process.git" GIT_TAG default) +FetchContent_MakeAvailable(Process) + +add_executable(${PROJECT_NAME} + main.cpp +) + +target_link_libraries(${PROJECT_NAME} PRIVATE process::process) + +``` + +**_main.cpp:_** +```cpp +#include + +#include +#include +#include + +using namespace std::literals; +using namespace org::ttldtor::process; + +int main() { + auto now = [] { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count(); + }; + std::cout << "Physical memory usage: " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + std::cout << "Total CPU time: " << Process::getTotalProcessorTime().count() << "ms" << std::endl; + + auto t1 = now(); + + while (now() - t1 <= 5) { + static std::size_t i = 0; + (void)(i++); + } + + std::cout << "Total CPU time (+5s): " << Process::getTotalProcessorTime().count() << "ms" << std::endl; + std::cout << "Physical memory usage: " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + std::vector vb(10 * 1024 * 1024); + std::cout << "Physical memory usage (+10MB): " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + vb.resize(1); + vb.shrink_to_fit(); + std::cout << "Physical memory usage (-10MB): " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; +} +``` + +_**Program output:**_ +```text +Physical memory usage: 4168KB +Total CPU time: 0ms +Total CPU time (+5s): 5609ms +Physical memory usage: 4212KB +Physical memory usage (+10MB): 14460KB +Physical memory usage (-10MB): 4216KB +``` diff --git a/third_party/Process-3.0.1/include/process/process.hpp b/third_party/Process-3.0.1/include/process/process.hpp new file mode 100644 index 000000000..08be7ae6a --- /dev/null +++ b/third_party/Process-3.0.1/include/process/process.hpp @@ -0,0 +1,113 @@ +// Copyright (c) 2023 ttldtor. +// SPDX-License-Identifier: BSL-1.0 + +#pragma once + +#ifdef TTLDTOR_PROCESS_EXPORT +# error TTLDTOR_PROCESS_EXPORT was previously defined +#endif + +#if defined(TTLDTOR_PROCESS_USE_DLLS) && defined(_MSC_VER) +# if defined(LIB_TTLDTOR_PROCESS_EXPORTS) +# define TTLDTOR_PROCESS_EXPORT __declspec(dllexport) +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DECLARE +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DEFINE __declspec(dllexport) +# else +# define TTLDTOR_PROCESS_EXPORT __declspec(dllimport) +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DECLARE +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DEFINE __declspec(dllimport) +# endif // defined(LIB_TTLDTOR_PROCESS) +#elif defined(TTLDTOR_PROCESS_USE_DLLS) && defined(LIB_TTLDTOR_PROCESS_EXPORTS) +# define TTLDTOR_PROCESS_EXPORT __attribute__((visibility("default"))) +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default"))) +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DEFINE +#else +# define TTLDTOR_PROCESS_EXPORT +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DECLARE +# define TTLDTOR_PROCESS_EXPORT_TEMPLATE_DEFINE +#endif + +#include +#include + +namespace org { +namespace ttldtor { +namespace process { + +struct TTLDTOR_PROCESS_EXPORT Process { + + /** + * Returns the kernel (privileged, system) CPU time for the current process in ms. + * + * @return The kernel (privileged, system) CPU time for the current process in ms. + */ + static std::chrono::milliseconds getKernelProcessorTime() noexcept; + + /** + * Returns the kernel (privileged, system) CPU time for the current process in ms. + * + * @return The kernel (privileged, system) CPU time for the current process in ms. + */ + static std::chrono::milliseconds getPrivilegedProcessorTime() noexcept { + return getKernelProcessorTime(); + } + + /** + * Returns the kernel (privileged, system) CPU time for the current process in ms. + * + * @return The kernel (privileged, system) CPU time for the current process in ms. + */ + static std::chrono::milliseconds getSystemProcessorTime() noexcept { + return getKernelProcessorTime(); + } + + /** + * Returns the user CPU time for the current process in ms. + * + * @return The user CPU time for the current process in ms. + */ + static std::chrono::milliseconds getUserProcessorTime() noexcept; + + /** + * Returns the total (kernel + user) CPU time for the current process in ms. + * + * @return The total (kernel + user) CPU time for the current process in ms. + */ + static std::chrono::milliseconds getTotalProcessorTime() noexcept; + + /** + * Returns the size of physical memory equipped by the current process. + * + * @return The size of physical memory equipped by the current process. + */ + static std::uint64_t getWorkingSetSize() noexcept; + + /** + * Returns the size of physical memory equipped by the current process. + * + * @return The size of physical memory equipped by the current process. + */ + static std::uint64_t getPhysicalMemorySize() noexcept { + return getWorkingSetSize(); + } + + /** + * Returns the size of private (virtual) memory equipped by the current process. + * + * @return The size of private (virtual) memory equipped by the current process. + */ + static std::uint64_t getPrivateMemorySize() noexcept; + + /** + * Returns the size of private (virtual) memory equipped by the current process. + * + * @return The size of private (virtual) memory equipped by the current process. + */ + static std::uint64_t getVirtualMemorySize() noexcept { + return getPrivateMemorySize(); + } +}; + +} // namespace process +} // namespace ttldtor +} // namespace org \ No newline at end of file diff --git a/third_party/Process-3.0.1/scripts/build_and_run.cmd b/third_party/Process-3.0.1/scripts/build_and_run.cmd new file mode 100644 index 000000000..0f5b27a9e --- /dev/null +++ b/third_party/Process-3.0.1/scripts/build_and_run.cmd @@ -0,0 +1,19 @@ +@echo off +for /f %%i in ('dir /a:d /s /b build-win*') do rd /s /q %%i +set CUR_YYYY=%date:~10,4% +set CUR_MM=%date:~4,2% +set CUR_DD=%date:~7,2% +set CUR_HH=%time:~0,2% +if %CUR_HH% lss 10 (set CUR_HH=0%time:~1,1%) +set CUR_NN=%time:~3,2% +set CUR_SS=%time:~6,2% +set CUR_MS=%time:~9,2% +set SUBFILENAME=%CUR_YYYY%%CUR_MM%%CUR_DD%-%CUR_HH%%CUR_NN%%CUR_SS% +mkdir build-win-%SUBFILENAME% +cd build-win-%SUBFILENAME% +cmake -DCMAKE_BUILD_TYPE=Release ..\.. +cmake --build . --config Release -j 4 +@rem dir +Release\process_test.exe + +pause diff --git a/third_party/Process-3.0.1/scripts/build_and_run.sh b/third_party/Process-3.0.1/scripts/build_and_run.sh new file mode 100644 index 000000000..a8ca2daad --- /dev/null +++ b/third_party/Process-3.0.1/scripts/build_and_run.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +rm -rf build-x-* +SUBFILENAME=$(date "+%Y%m%d-%H%M%S") +mkdir "build-x-$SUBFILENAME" +cd build-x-$SUBFILENAME || exit +cmake -DCMAKE_BUILD_TYPE=Release ../.. +cmake --build . --config Release -j 4 +./process_test + diff --git a/third_party/Process-3.0.1/src/process.cpp b/third_party/Process-3.0.1/src/process.cpp new file mode 100644 index 000000000..d550cb52e --- /dev/null +++ b/third_party/Process-3.0.1/src/process.cpp @@ -0,0 +1,471 @@ +// Copyright (c) 2023 ttldtor. +// SPDX-License-Identifier: BSL-1.0 + +#include + +#include +#include +#include +#include +#include +#include + +namespace org { +namespace ttldtor { +namespace process { + +template constexpr void ignore_unused(const T &...) { +} + +constexpr inline auto is_constant_evaluated(bool default_value = false) noexcept -> bool { +#ifdef __cpp_lib_is_constant_evaluated + ignore_unused(default_value); + return std::is_constant_evaluated(); +#else + return default_value; +#endif +} + +// Implementation of std::bit_cast for pre-C++20. +template +constexpr To bit_cast(const From &from) +#if __cpp_concepts + requires(sizeof(To) == sizeof(From)) +#endif +{ +#ifdef __cpp_lib_bit_cast + if (is_constant_evaluated()) + return std::bit_cast(from); +#endif + auto to = To(); + // The cast suppresses a bogus -Wclass-memaccess on GCC. + std::memcpy(static_cast(&to), &from, sizeof(to)); + return to; +} + +} // namespace process +} // namespace ttldtor +} // namespace org + +#if defined(__linux__) || defined(__ANDROID__) || defined(__FreeBSD__) + +# include + +namespace org { +namespace ttldtor { +namespace process { + +struct RUsageResult { + std::chrono::milliseconds sysTime{}; + std::chrono::milliseconds userTime{}; + std::chrono::milliseconds totalTime{}; + + explicit RUsageResult(const rusage &ru) + : sysTime{static_cast(ru.ru_stime.tv_sec) * 1000ULL + + static_cast(ru.ru_stime.tv_usec) / 1000ULL}, + userTime{static_cast(ru.ru_utime.tv_sec) * 1000ULL + + static_cast(ru.ru_utime.tv_usec) / 1000ULL}, + totalTime{sysTime + userTime} { + } +}; + +} // namespace process +} // namespace ttldtor +} // namespace org + +#endif + +#ifdef WIN32 + +# include +# include +# include + +namespace org { +namespace ttldtor { +namespace process { +std::chrono::milliseconds Process::getKernelProcessorTime() noexcept { + FILETIME creationTime{}; + FILETIME exitTime{}; + FILETIME kernelTime{}; + FILETIME userTime{}; + auto h = GetCurrentProcess(); + + GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime); + + auto kernelTime2 = + static_cast(kernelTime.dwLowDateTime) | + (static_cast(kernelTime.dwHighDateTime) << (sizeof(kernelTime.dwLowDateTime) * 8ULL)); + + return std::chrono::milliseconds(kernelTime2 / 10'000); // 100 nanoseconds time-points +} + +std::chrono::milliseconds Process::getUserProcessorTime() noexcept { + FILETIME creationTime{}; + FILETIME exitTime{}; + FILETIME kernelTime{}; + FILETIME userTime{}; + auto h = GetCurrentProcess(); + + GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime); + + auto userTime2 = static_cast(userTime.dwLowDateTime) | + (static_cast(userTime.dwHighDateTime) << (sizeof(userTime.dwLowDateTime) * 8ULL)); + + return std::chrono::milliseconds(userTime2 / 10'000); // 100 nanoseconds time-points +} + +std::chrono::milliseconds Process::getTotalProcessorTime() noexcept { + FILETIME creationTime{}; + FILETIME exitTime{}; + FILETIME kernelTime{}; + FILETIME userTime{}; + auto h = GetCurrentProcess(); + + GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime); + + auto kernelTime2 = + static_cast(kernelTime.dwLowDateTime) | + (static_cast(kernelTime.dwHighDateTime) << (sizeof(kernelTime.dwLowDateTime) * 8ULL)); + auto userTime2 = static_cast(userTime.dwLowDateTime) | + (static_cast(userTime.dwHighDateTime) << (sizeof(userTime.dwLowDateTime) * 8ULL)); + + return std::chrono::milliseconds((kernelTime2 + userTime2) / 10'000); // 100 nanoseconds time-points +} + +std::uint64_t Process::getWorkingSetSize() noexcept { + PROCESS_MEMORY_COUNTERS_EX processMemoryCountersEx{}; + auto h = GetCurrentProcess(); + + GetProcessMemoryInfo(h, bit_cast(&processMemoryCountersEx), + sizeof(processMemoryCountersEx)); + + return static_cast(processMemoryCountersEx.WorkingSetSize); +} + +std::uint64_t Process::getPrivateMemorySize() noexcept { + PROCESS_MEMORY_COUNTERS_EX processMemoryCountersEx{}; + auto h = GetCurrentProcess(); + + GetProcessMemoryInfo(h, bit_cast(&processMemoryCountersEx), + sizeof(processMemoryCountersEx)); + + return static_cast(processMemoryCountersEx.PrivateUsage); +} +} // namespace process +} // namespace ttldtor +} // namespace org + +#elif defined(__linux__) || defined(__ANDROID__) + +namespace org { +namespace ttldtor { +namespace process { + +struct Parser { + enum ParseResultType { KEY_NOT_FOUND, VALUE_NOT_FOUND, OK }; + + struct ParseStatusResult { + ParseResultType resultType; + std::uint64_t value; + }; + + static ParseStatusResult parseStatus(const std::string &s, const std::string &key) noexcept { + auto foundKeyPos = s.find(key); + + if (foundKeyPos != std::string::npos) { + auto foundValuePos = s.find_first_of("0123456789", foundKeyPos + 6); + + if (foundValuePos != std::string::npos) { + try { + return {OK, static_cast(std::stoll(s.substr(foundValuePos)))}; + } catch (...) { + return {OK, 0}; + } + } else { + return {VALUE_NOT_FOUND, 0}; + } + } else { + return {KEY_NOT_FOUND, 0}; + } + } +}; + +std::chrono::milliseconds Process::getKernelProcessorTime() noexcept { + rusage ru{}; + + getrusage(RUSAGE_SELF, &ru); + + return RUsageResult{ru}.sysTime; +} + +std::chrono::milliseconds Process::getUserProcessorTime() noexcept { + rusage ru{}; + + getrusage(RUSAGE_SELF, &ru); + + return RUsageResult{ru}.userTime; +} + +std::chrono::milliseconds Process::getTotalProcessorTime() noexcept { + rusage ru{}; + + getrusage(RUSAGE_SELF, &ru); + + return RUsageResult{ru}.totalTime; +} + +std::uint64_t Process::getWorkingSetSize() noexcept { + std::ifstream is("/proc/self/status"); + + if (is.fail()) { + return 0ULL; + } + + std::string s{}; + + while (!std::getline(is, s).fail()) { + auto result = Parser::parseStatus(s, "VmRSS:"); + + if (result.resultType == Parser::KEY_NOT_FOUND) { + continue; + } else { + return result.value * 1024; + } + } + + return 0LL; +} + +std::uint64_t Process::getPrivateMemorySize() noexcept { + std::ifstream is("/proc/self/status"); + + if (is.fail()) { + return 0ULL; + } + + std::string s{}; + + while (!std::getline(is, s).fail()) { + auto result = Parser::parseStatus(s, "VmSize:"); + + if (result.resultType == Parser::KEY_NOT_FOUND) { + continue; + } else { + return result.value * 1024; + } + } + + return 0LL; +} +} // namespace process +} // namespace ttldtor +} // namespace org + +#elif defined(__APPLE__) && defined(__MACH__) +# include +# if __has_include() +# include +# else +# include +# include +// Some SDKs are missing the libproc.h header +int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +# endif +# include +# include +# include +# include + +namespace org { +namespace ttldtor { +namespace process { + +struct ProcPidRUsageResult { + static const std::uint64_t NSEC_TO_MSEC_RATIO = 1000000ULL; + + std::chrono::milliseconds sysTime{}; + std::chrono::milliseconds userTime{}; + std::chrono::milliseconds totalTime{}; + + struct StaticData { + mach_timebase_info_data_t timeBase; + + StaticData() { + timeBase.numer = 0; + timeBase.denom = 0; + + // Initialize time conversions. + mach_timebase_info(&timeBase); + } + }; + + static const StaticData staticData; + + explicit ProcPidRUsageResult(const rusage_info_v2 &rusage_info_data) { + // std::cout << "Time Base: " << staticData.timeBase.numer << " / " << staticData.timeBase.denom << std::endl; + + sysTime = std::chrono::milliseconds( + ((static_cast(rusage_info_data.ri_system_time) * staticData.timeBase.numer) / + staticData.timeBase.denom) / + ProcPidRUsageResult::NSEC_TO_MSEC_RATIO); + userTime = std::chrono::milliseconds( + ((static_cast(rusage_info_data.ri_user_time) * staticData.timeBase.numer) / + staticData.timeBase.denom) / + ProcPidRUsageResult::NSEC_TO_MSEC_RATIO); + totalTime = sysTime + userTime; + } +}; + +const ProcPidRUsageResult::StaticData ProcPidRUsageResult::staticData{}; + +std::chrono::milliseconds Process::getKernelProcessorTime() noexcept { + rusage_info_v2 rusage_info_data{}; + auto status = proc_pid_rusage(getpid(), RUSAGE_INFO_V2, bit_cast(&rusage_info_data)); + + return ProcPidRUsageResult{rusage_info_data}.sysTime; +} + +std::chrono::milliseconds Process::getUserProcessorTime() noexcept { + rusage_info_v2 rusage_info_data{}; + auto status = proc_pid_rusage(getpid(), RUSAGE_INFO_V2, bit_cast(&rusage_info_data)); + + return ProcPidRUsageResult{rusage_info_data}.userTime; +} + +std::chrono::milliseconds Process::getTotalProcessorTime() noexcept { + rusage_info_v2 rusage_info_data{}; + auto status = proc_pid_rusage(getpid(), RUSAGE_INFO_V2, bit_cast(&rusage_info_data)); + + return ProcPidRUsageResult{rusage_info_data}.totalTime; +} + +std::uint64_t Process::getWorkingSetSize() noexcept { + mach_task_basic_info info{}; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + + auto result = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, bit_cast(&info), &infoCount); + + return static_cast(info.resident_size); +} + +std::uint64_t Process::getPrivateMemorySize() noexcept { + mach_task_basic_info info{}; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + + auto result = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, bit_cast(&info), &infoCount); + + return static_cast(info.virtual_size); +} +} // namespace process +} // namespace ttldtor +} // namespace org + +#elif defined(__FreeBSD__) + +# include +# include +# include +# include +# include +# include + +namespace org { +namespace ttldtor { +namespace process { + +bool getProcInfo(int pid, kinfo_proc &info) noexcept { + const std::size_t MIB_SIZE = 4; // 6 - OpenBSD + // MIB - Management Information Base + int mib[MIB_SIZE] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; + std::size_t length = sizeof(kinfo_proc); + + if (sysctl(mib, MIB_SIZE, &info, &length, nullptr, 0) < 0) { + return false; + } + + return true; +} + +std::chrono::milliseconds Process::getKernelProcessorTime() noexcept { + kinfo_proc info{}; + + if (getProcInfo(getpid(), info)) { + return RUsageResult{info.ki_rusage}.sysTime; + } + + return std::chrono::milliseconds(0); +} + +std::chrono::milliseconds Process::getUserProcessorTime() noexcept { + kinfo_proc info{}; + + if (getProcInfo(getpid(), info)) { + return RUsageResult{info.ki_rusage}.userTime; + } + + return std::chrono::milliseconds(0); +} + +std::chrono::milliseconds Process::getTotalProcessorTime() noexcept { + kinfo_proc info{}; + + if (getProcInfo(getpid(), info)) { + return RUsageResult{info.ki_rusage}.totalTime; + } + + return std::chrono::milliseconds(0); +} + +std::uint64_t Process::getWorkingSetSize() noexcept { + kinfo_proc info{}; + + if (getProcInfo(getpid(), info)) { + return static_cast(info.ki_rssize) * getpagesize(); + } + + return 0ULL; +} + +std::uint64_t Process::getPrivateMemorySize() noexcept { + kinfo_proc info{}; + + if (getProcInfo(getpid(), info)) { + return static_cast(info.ki_size); + } + + return 0ULL; +} +} // namespace process +} // namespace ttldtor +} // namespace org + +#else + +namespace org { +namespace ttldtor { +namespace process { +std::chrono::milliseconds Process::getKernelProcessorTime() noexcept { + return std::chrono::milliseconds(0); +} + +std::chrono::milliseconds Process::getUserProcessorTime() noexcept { + return std::chrono::milliseconds(0); +} + +std::chrono::milliseconds Process::getTotalProcessorTime() noexcept { + return std::chrono::milliseconds(0); +} + +std::uint64_t Process::getWorkingSetSize() noexcept { + return 0ULL; +} + +std::uint64_t Process::getPrivateMemorySize() noexcept { + return 0ULL; +} +} // namespace process +} // namespace ttldtor +} // namespace org + +#endif diff --git a/third_party/Process-3.0.1/test/main.cpp b/third_party/Process-3.0.1/test/main.cpp new file mode 100644 index 000000000..49f31fb51 --- /dev/null +++ b/third_party/Process-3.0.1/test/main.cpp @@ -0,0 +1,62 @@ +#include + +#include +#include +#include +#include + +using namespace std::literals; +using namespace org::ttldtor::process; + +int main() { + auto now = [] { + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count(); + }; + std::cout << std::string(79, '=') << std::endl; + std::cout << "Physical memory usage: " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + std::cout << "Total CPU time: " << Process::getTotalProcessorTime().count() << "ms" << std::endl; + + auto t1 = now(); + + while (now() - t1 <= 5) { + static std::size_t i = 0; + (void)(i++); + } + + std::cout << "Total CPU time (+ ≈5s): " << Process::getTotalProcessorTime().count() << "ms" << std::endl; + std::cout << "Physical memory usage: " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + + { + std::vector vb(10 * 1024 * 1024, 0); + + for (std::size_t i = 0; i < vb.size(); i++) { + vb[i]++; + } + + std::cout << "Physical memory usage (+10MB vector): " << Process::getPhysicalMemorySize() / 1024 << "KB" + << std::endl; + } + + std::cout << "Physical memory usage (-10MB vector): " << Process::getPhysicalMemorySize() / 1024 << "KB" + << std::endl; + + for (auto n = 0; n < 5; n++) { + const std::size_t size = 5 * 1024 * 1024 * (n + 1); + auto *arr = new std::uint8_t[size]{0}; + + std::cout << "Physical memory usage (+" << 5 * (n + 1) + << "MB new byte[]): " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + + for (auto i = 0; i < size; i++) { + arr[i]++; + } + + delete[] arr; + + std::this_thread::sleep_for(1s); + + std::cout << "Physical memory usage (-" << 5 * (n + 1) + << "MB new byte[]): " << Process::getPhysicalMemorySize() / 1024 << "KB" << std::endl; + } +} diff --git a/third_party/fmt-11.0.2/.clang-format b/third_party/fmt-11.0.2/.clang-format new file mode 100644 index 000000000..df55d340f --- /dev/null +++ b/third_party/fmt-11.0.2/.clang-format @@ -0,0 +1,8 @@ +# Run manually to reformat a file: +# clang-format -i --style=file +Language: Cpp +BasedOnStyle: Google +IndentPPDirectives: AfterHash +IndentCaseLabels: false +AlwaysBreakTemplateDeclarations: false +DerivePointerAlignment: false diff --git a/third_party/fmt-11.0.2/CMakeLists.txt b/third_party/fmt-11.0.2/CMakeLists.txt new file mode 100644 index 000000000..e3b35110f --- /dev/null +++ b/third_party/fmt-11.0.2/CMakeLists.txt @@ -0,0 +1,520 @@ +cmake_minimum_required(VERSION 3.8...3.28) + +# Fallback for using newer policies on CMake <3.12. +if (${CMAKE_VERSION} VERSION_LESS 3.12) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +endif () + +# Determine if fmt is built as a subproject (using add_subdirectory) +# or if it is the master project. +if (NOT DEFINED FMT_MASTER_PROJECT) + set(FMT_MASTER_PROJECT OFF) + if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(FMT_MASTER_PROJECT ON) + message(STATUS "CMake version: ${CMAKE_VERSION}") + endif () +endif () + +# Joins arguments and places the results in ${result_var}. +function(join result_var) + set(result "") + foreach (arg ${ARGN}) + set(result "${result}${arg}") + endforeach () + set(${result_var} "${result}" PARENT_SCOPE) +endfunction() + +# DEPRECATED! Should be merged into add_module_library. +function(enable_module target) + if (MSVC) + set(BMI ${CMAKE_CURRENT_BINARY_DIR}/${target}.ifc) + target_compile_options(${target} + PRIVATE /interface /ifcOutput ${BMI} + INTERFACE /reference fmt=${BMI}) + set_target_properties(${target} PROPERTIES ADDITIONAL_CLEAN_FILES ${BMI}) + set_source_files_properties(${BMI} PROPERTIES GENERATED ON) + endif () +endfunction() + +set(FMT_USE_CMAKE_MODULES FALSE) +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.28 AND + CMAKE_GENERATOR STREQUAL "Ninja") + set(FMT_USE_CMAKE_MODULES TRUE) +endif () + +# Adds a library compiled with C++20 module support. +# `enabled` is a CMake variables that specifies if modules are enabled. +# If modules are disabled `add_module_library` falls back to creating a +# non-modular library. +# +# Usage: +# add_module_library( [sources...] FALLBACK [sources...] [IF enabled]) +function(add_module_library name) + cmake_parse_arguments(AML "" "IF" "FALLBACK" ${ARGN}) + set(sources ${AML_UNPARSED_ARGUMENTS}) + + add_library(${name}) + set_target_properties(${name} PROPERTIES LINKER_LANGUAGE CXX) + + if (NOT ${${AML_IF}}) + # Create a non-modular library. + target_sources(${name} PRIVATE ${AML_FALLBACK}) + set_target_properties(${name} PROPERTIES CXX_SCAN_FOR_MODULES OFF) + return() + endif () + + # Modules require C++20. + target_compile_features(${name} PUBLIC cxx_std_20) + if (CMAKE_COMPILER_IS_GNUCXX) + target_compile_options(${name} PUBLIC -fmodules-ts) + endif () + + target_compile_definitions(${name} PRIVATE FMT_MODULE) + + if (FMT_USE_CMAKE_MODULES) + target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES + FILES ${sources}) + else() + # `std` is affected by CMake options and may be higher than C++20. + get_target_property(std ${name} CXX_STANDARD) + + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(pcms) + foreach (src ${sources}) + get_filename_component(pcm ${src} NAME_WE) + set(pcm ${pcm}.pcm) + + # Propagate -fmodule-file=*.pcm to targets that link with this library. + target_compile_options( + ${name} PUBLIC -fmodule-file=${CMAKE_CURRENT_BINARY_DIR}/${pcm}) + + # Use an absolute path to prevent target_link_libraries prepending -l + # to it. + set(pcms ${pcms} ${CMAKE_CURRENT_BINARY_DIR}/${pcm}) + add_custom_command( + OUTPUT ${pcm} + COMMAND ${CMAKE_CXX_COMPILER} + -std=c++${std} -x c++-module --precompile -c + -o ${pcm} ${CMAKE_CURRENT_SOURCE_DIR}/${src} + "-I$,;-I>" + # Required by the -I generator expression above. + COMMAND_EXPAND_LISTS + DEPENDS ${src}) + endforeach () + + # Add .pcm files as sources to make sure they are built before the library. + set(sources) + foreach (pcm ${pcms}) + get_filename_component(pcm_we ${pcm} NAME_WE) + set(obj ${pcm_we}.o) + # Use an absolute path to prevent target_link_libraries prepending -l. + set(sources ${sources} ${pcm} ${CMAKE_CURRENT_BINARY_DIR}/${obj}) + add_custom_command( + OUTPUT ${obj} + COMMAND ${CMAKE_CXX_COMPILER} $ + -c -o ${obj} ${pcm} + DEPENDS ${pcm}) + endforeach () + endif () + target_sources(${name} PRIVATE ${sources}) + endif() +endfunction() + +include(CMakeParseArguments) + +# Sets a cache variable with a docstring joined from multiple arguments: +# set( ... CACHE ...) +# This allows splitting a long docstring for readability. +function(set_verbose) + # cmake_parse_arguments is broken in CMake 3.4 (cannot parse CACHE) so use + # list instead. + list(GET ARGN 0 var) + list(REMOVE_AT ARGN 0) + list(GET ARGN 0 val) + list(REMOVE_AT ARGN 0) + list(REMOVE_AT ARGN 0) + list(GET ARGN 0 type) + list(REMOVE_AT ARGN 0) + join(doc ${ARGN}) + set(${var} ${val} CACHE ${type} ${doc}) +endfunction() + +# Set the default CMAKE_BUILD_TYPE to Release. +# This should be done before the project command since the latter can set +# CMAKE_BUILD_TYPE itself (it does so for nmake). +if (FMT_MASTER_PROJECT AND NOT CMAKE_BUILD_TYPE) + set_verbose(CMAKE_BUILD_TYPE Release CACHE STRING + "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or " + "CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") +endif () + +project(FMT CXX) +include(GNUInstallDirs) +set_verbose(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING + "Installation directory for include files, a relative path that " + "will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute path.") + +option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF) +option(FMT_WERROR "Halt the compilation with an error on compiler warnings." + OFF) + +# Options that control generation of various targets. +option(FMT_DOC "Generate the doc target." ${FMT_MASTER_PROJECT}) +option(FMT_INSTALL "Generate the install target." ON) +option(FMT_TEST "Generate the test target." ${FMT_MASTER_PROJECT}) +option(FMT_FUZZ "Generate the fuzz target." OFF) +option(FMT_CUDA_TEST "Generate the cuda-test target." OFF) +option(FMT_OS "Include OS-specific APIs." ON) +option(FMT_MODULE "Build a module instead of a traditional library." OFF) +option(FMT_SYSTEM_HEADERS "Expose headers with marking them as system." OFF) +option(FMT_UNICODE "Enable Unicode support." ON) + +if (FMT_TEST AND FMT_MODULE) + # The tests require {fmt} to be compiled as traditional library + message(STATUS "Testing is incompatible with build mode 'module'.") +endif () +set(FMT_SYSTEM_HEADERS_ATTRIBUTE "") +if (FMT_SYSTEM_HEADERS) + set(FMT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) +endif () +if (CMAKE_SYSTEM_NAME STREQUAL "MSDOS") + set(FMT_TEST OFF) + message(STATUS "MSDOS is incompatible with gtest") +endif () + +# Get version from base.h +file(READ include/fmt/base.h base_h) +if (NOT base_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])") + message(FATAL_ERROR "Cannot get FMT_VERSION from base.h.") +endif () +# Use math to skip leading zeros if any. +math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1}) +math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2}) +math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3}) +join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}. + ${CPACK_PACKAGE_VERSION_PATCH}) +message(STATUS "{fmt} version: ${FMT_VERSION}") + +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") + +if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) +endif () + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/support/cmake") + +include(CheckCXXCompilerFlag) +include(JoinPaths) + +if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET) + set_verbose(CMAKE_CXX_VISIBILITY_PRESET hidden CACHE STRING + "Preset for the export of private symbols") + set_property(CACHE CMAKE_CXX_VISIBILITY_PRESET PROPERTY STRINGS + hidden default) +endif () + +if (FMT_MASTER_PROJECT AND NOT DEFINED CMAKE_VISIBILITY_INLINES_HIDDEN) + set_verbose(CMAKE_VISIBILITY_INLINES_HIDDEN ON CACHE BOOL + "Whether to add a compile flag to hide symbols of inline functions") +endif () + +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set(PEDANTIC_COMPILE_FLAGS -pedantic-errors -Wall -Wextra -pedantic + -Wold-style-cast -Wundef + -Wredundant-decls -Wwrite-strings -Wpointer-arith + -Wcast-qual -Wformat=2 -Wmissing-include-dirs + -Wcast-align + -Wctor-dtor-privacy -Wdisabled-optimization + -Winvalid-pch -Woverloaded-virtual + -Wconversion -Wundef + -Wno-ctor-dtor-privacy -Wno-format-nonliteral) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} + -Wno-dangling-else -Wno-unused-local-typedefs) + endif () + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wdouble-promotion + -Wtrampolines -Wzero-as-null-pointer-constant -Wuseless-cast + -Wvector-operation-performance -Wsized-deallocation -Wshadow) + endif () + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2 + -Wnull-dereference -Wduplicated-cond) + endif () + set(WERROR_FLAG -Werror) +endif () + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -pedantic -Wconversion -Wundef + -Wdeprecated -Wweak-vtables -Wshadow + -Wno-gnu-zero-variadic-macro-arguments) + check_cxx_compiler_flag(-Wzero-as-null-pointer-constant HAS_NULLPTR_WARNING) + if (HAS_NULLPTR_WARNING) + set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} + -Wzero-as-null-pointer-constant) + endif () + set(WERROR_FLAG -Werror) +endif () + +if (MSVC) + set(PEDANTIC_COMPILE_FLAGS /W3) + set(WERROR_FLAG /WX) +endif () + +if (FMT_MASTER_PROJECT AND CMAKE_GENERATOR MATCHES "Visual Studio") + # If Microsoft SDK is installed create script run-msbuild.bat that + # calls SetEnv.cmd to set up build environment and runs msbuild. + # It is useful when building Visual Studio projects with the SDK + # toolchain rather than Visual Studio. + include(FindSetEnv) + if (WINSDK_SETENV) + set(MSBUILD_SETUP "call \"${WINSDK_SETENV}\"") + endif () + # Set FrameworkPathOverride to get rid of MSB3644 warnings. + join(netfxpath + "C:\\Program Files\\Reference Assemblies\\Microsoft\\Framework\\" + ".NETFramework\\v4.0") + file(WRITE run-msbuild.bat " + ${MSBUILD_SETUP} + ${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*") +endif () + +function(add_headers VAR) + set(headers ${${VAR}}) + foreach (header ${ARGN}) + set(headers ${headers} include/fmt/${header}) + endforeach() + set(${VAR} ${headers} PARENT_SCOPE) +endfunction() + +# Define the fmt library, its includes and the needed defines. +add_headers(FMT_HEADERS args.h base.h chrono.h color.h compile.h core.h format.h + format-inl.h os.h ostream.h printf.h ranges.h std.h + xchar.h) +set(FMT_SOURCES src/format.cc) + +add_module_library(fmt src/fmt.cc FALLBACK + ${FMT_SOURCES} ${FMT_HEADERS} README.md ChangeLog.md + IF FMT_MODULE) +add_library(fmt::fmt ALIAS fmt) +if (FMT_MODULE) + enable_module(fmt) +elseif (FMT_OS) + target_sources(fmt PRIVATE src/os.cc) +else() + target_compile_definitions(fmt PRIVATE FMT_OS=0) +endif () + +if (FMT_WERROR) + target_compile_options(fmt PRIVATE ${WERROR_FLAG}) +endif () +if (FMT_PEDANTIC) + target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS}) +endif () + +if (cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES) + target_compile_features(fmt PUBLIC cxx_std_11) +else () + message(WARNING "Feature cxx_std_11 is unknown for the CXX compiler") +endif () + +target_include_directories(fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC + $ + $) + +set(FMT_DEBUG_POSTFIX d CACHE STRING "Debug library postfix.") + +set_target_properties(fmt PROPERTIES + VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR} + PUBLIC_HEADER "${FMT_HEADERS}" + DEBUG_POSTFIX "${FMT_DEBUG_POSTFIX}" + + # Workaround for Visual Studio 2017: + # Ensure the .pdb is created with the same name and in the same directory + # as the .lib. Newer VS versions already do this by default, but there is no + # harm in setting it for those too. Ignored by other generators. + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + COMPILE_PDB_NAME "fmt" + COMPILE_PDB_NAME_DEBUG "fmt${FMT_DEBUG_POSTFIX}") + +# Set FMT_LIB_NAME for pkg-config fmt.pc. We cannot use the OUTPUT_NAME target +# property because it's not set by default. +set(FMT_LIB_NAME fmt) +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(FMT_LIB_NAME ${FMT_LIB_NAME}${FMT_DEBUG_POSTFIX}) +endif () + +if (BUILD_SHARED_LIBS) + target_compile_definitions(fmt PRIVATE FMT_LIB_EXPORT INTERFACE FMT_SHARED) +endif () +if (FMT_SAFE_DURATION_CAST) + target_compile_definitions(fmt PUBLIC FMT_SAFE_DURATION_CAST) +endif () + +add_library(fmt-header-only INTERFACE) +add_library(fmt::fmt-header-only ALIAS fmt-header-only) + +if (NOT MSVC) + # Unicode is always supported on compilers other than MSVC. +elseif (FMT_UNICODE) + # Unicode support requires compiling with /utf-8. + target_compile_options(fmt PUBLIC $<$:/utf-8>) + target_compile_options(fmt-header-only INTERFACE $<$:/utf-8>) +else () + target_compile_definitions(fmt PUBLIC FMT_UNICODE=0) +endif () + +target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1) +target_compile_features(fmt-header-only INTERFACE cxx_std_11) + +target_include_directories(fmt-header-only + ${FMT_SYSTEM_HEADERS_ATTRIBUTE} INTERFACE + $ + $) + +# Install targets. +if (FMT_INSTALL) + include(CMakePackageConfigHelpers) + set_verbose(FMT_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/fmt CACHE STRING + "Installation directory for cmake files, a relative path that " + "will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute " + "path.") + set(version_config ${PROJECT_BINARY_DIR}/fmt-config-version.cmake) + set(project_config ${PROJECT_BINARY_DIR}/fmt-config.cmake) + set(pkgconfig ${PROJECT_BINARY_DIR}/fmt.pc) + set(targets_export_name fmt-targets) + + set_verbose(FMT_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING + "Installation directory for libraries, a relative path that " + "will be joined to ${CMAKE_INSTALL_PREFIX} or an absolute path.") + + set_verbose(FMT_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE STRING + "Installation directory for pkgconfig (.pc) files, a relative " + "path that will be joined with ${CMAKE_INSTALL_PREFIX} or an " + "absolute path.") + + # Generate the version, config and target files into the build directory. + write_basic_package_version_file( + ${version_config} + VERSION ${FMT_VERSION} + COMPATIBILITY AnyNewerVersion) + + join_paths(libdir_for_pc_file "\${exec_prefix}" "${FMT_LIB_DIR}") + join_paths(includedir_for_pc_file "\${prefix}" "${FMT_INC_DIR}") + + configure_file( + "${PROJECT_SOURCE_DIR}/support/cmake/fmt.pc.in" + "${pkgconfig}" + @ONLY) + configure_package_config_file( + ${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in + ${project_config} + INSTALL_DESTINATION ${FMT_CMAKE_DIR}) + + set(INSTALL_TARGETS fmt fmt-header-only) + + set(INSTALL_FILE_SET) + if (FMT_USE_CMAKE_MODULES) + set(INSTALL_FILE_SET FILE_SET fmt DESTINATION "${FMT_INC_DIR}/fmt") + endif() + + # Install the library and headers. + install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name} + LIBRARY DESTINATION ${FMT_LIB_DIR} + ARCHIVE DESTINATION ${FMT_LIB_DIR} + PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt" + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ${INSTALL_FILE_SET}) + + # Use a namespace because CMake provides better diagnostics for namespaced + # imported targets. + export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt:: + FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake) + + # Install version, config and target files. + install( + FILES ${project_config} ${version_config} + DESTINATION ${FMT_CMAKE_DIR}) + install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR} + NAMESPACE fmt::) + + install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}") +endif () + +function(add_doc_target) + find_program(DOXYGEN doxygen + PATHS "$ENV{ProgramFiles}/doxygen/bin" + "$ENV{ProgramFiles\(x86\)}/doxygen/bin") + if (NOT DOXYGEN) + message(STATUS "Target 'doc' disabled because doxygen not found") + return () + endif () + + find_program(MKDOCS mkdocs) + if (NOT MKDOCS) + message(STATUS "Target 'doc' disabled because mkdocs not found") + return () + endif () + + set(sources ) + foreach (source api.md index.md syntax.md get-started.md fmt.css fmt.js) + set(sources ${sources} doc/${source}) + endforeach() + + add_custom_target( + doc + COMMAND + ${CMAKE_COMMAND} + -E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}/support/python + ${MKDOCS} build -f ${CMAKE_CURRENT_SOURCE_DIR}/support/mkdocs.yml + # MkDocs requires the site dir to be outside of the doc dir. + --site-dir ${CMAKE_CURRENT_BINARY_DIR}/doc-html + --no-directory-urls + SOURCES ${sources}) + + include(GNUInstallDirs) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/ + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt OPTIONAL) +endfunction() + +if (FMT_DOC) + add_doc_target() +endif () + +if (FMT_TEST) + enable_testing() + add_subdirectory(test) +endif () + +# Control fuzzing independent of the unit tests. +if (FMT_FUZZ) + add_subdirectory(test/fuzzing) + + # The FMT_FUZZ macro is used to prevent resource exhaustion in fuzzing + # mode and make fuzzing practically possible. It is similar to + # FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION but uses a different name to + # avoid interfering with fuzzing of projects that use {fmt}. + # See also https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode. + target_compile_definitions(fmt PUBLIC FMT_FUZZ) +endif () + +set(gitignore ${PROJECT_SOURCE_DIR}/.gitignore) +if (FMT_MASTER_PROJECT AND EXISTS ${gitignore}) + # Get the list of ignored files from .gitignore. + file (STRINGS ${gitignore} lines) + list(REMOVE_ITEM lines /doc/html) + foreach (line ${lines}) + string(REPLACE "." "[.]" line "${line}") + string(REPLACE "*" ".*" line "${line}") + set(ignored_files ${ignored_files} "${line}$" "${line}/") + endforeach () + set(ignored_files ${ignored_files} /.git /build/doxyxml .vagrant) + + set(CPACK_SOURCE_GENERATOR ZIP) + set(CPACK_SOURCE_IGNORE_FILES ${ignored_files}) + set(CPACK_SOURCE_PACKAGE_FILE_NAME fmt-${FMT_VERSION}) + set(CPACK_PACKAGE_NAME fmt) + set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md) + include(CPack) +endif () diff --git a/third_party/fmt-11.0.2/CONTRIBUTING.md b/third_party/fmt-11.0.2/CONTRIBUTING.md new file mode 100644 index 000000000..b82f14506 --- /dev/null +++ b/third_party/fmt-11.0.2/CONTRIBUTING.md @@ -0,0 +1,20 @@ +Contributing to {fmt} +===================== + +By submitting a pull request or a patch, you represent that you have the right +to license your contribution to the {fmt} project owners and the community, +agree that your contributions are licensed under the {fmt} license, and agree +to future changes to the licensing. + +All C++ code must adhere to [Google C++ Style Guide]( +https://google.github.io/styleguide/cppguide.html) with the following +exceptions: + +* Exceptions are permitted +* snake_case should be used instead of UpperCamelCase for function and type + names + +All documentation must adhere to the [Google Developer Documentation Style +Guide](https://developers.google.com/style). + +Thanks for contributing! diff --git a/third_party/fmt-11.0.2/ChangeLog.md b/third_party/fmt-11.0.2/ChangeLog.md new file mode 100644 index 000000000..6ba567d1d --- /dev/null +++ b/third_party/fmt-11.0.2/ChangeLog.md @@ -0,0 +1,2628 @@ +# 11.0.2 - 2024-07-20 + +- Fixed compatibility with non-POSIX systems + (https://github.com/fmtlib/fmt/issues/4054, + https://github.com/fmtlib/fmt/issues/4060). + +- Fixed performance regressions when using `std::back_insert_iterator` with + `fmt::format_to` (https://github.com/fmtlib/fmt/issues/4070). + +- Fixed handling of `std::generator` and move-only iterators + (https://github.com/fmtlib/fmt/issues/4053, + https://github.com/fmtlib/fmt/pull/4057). Thanks @Arghnews. + +- Made `formatter::parse` work with types convertible to + `std::string_view` (https://github.com/fmtlib/fmt/issues/4036, + https://github.com/fmtlib/fmt/pull/4055). Thanks @Arghnews. + +- Made `volatile void*` formattable + (https://github.com/fmtlib/fmt/issues/4049, + https://github.com/fmtlib/fmt/pull/4056). Thanks @Arghnews. + +- Made `Glib::ustring` not be confused with `std::string` + (https://github.com/fmtlib/fmt/issues/4052). + +- Made `fmt::context` iterator compatible with STL algorithms that rely on + iterator category (https://github.com/fmtlib/fmt/issues/4079). + +# 11.0.1 - 2024-07-05 + +- Fixed version number in the inline namespace + (https://github.com/fmtlib/fmt/issues/4047). + +- Fixed disabling Unicode support via CMake + (https://github.com/fmtlib/fmt/issues/4051). + +- Fixed deprecated `visit_format_arg` (https://github.com/fmtlib/fmt/pull/4043). + Thanks @nebkat. + +- Fixed handling of a sign and improved the `std::complex` formater + (https://github.com/fmtlib/fmt/pull/4034, + https://github.com/fmtlib/fmt/pull/4050). Thanks @tesch1 and @phprus. + +- Fixed ADL issues in `fmt::printf` when using C++20 + (https://github.com/fmtlib/fmt/pull/4042). Thanks @toge. + +- Removed a redundant check in the formatter for `std::expected` + (https://github.com/fmtlib/fmt/pull/4040). Thanks @phprus. + +# 11.0.0 - 2024-07-01 + +- Added `fmt/base.h` which provides a subset of the API with minimal include + dependencies and enough functionality to replace all uses of the `printf` + family of functions. This brings the compile time of code using {fmt} much + closer to the equivalent `printf` code as shown on the following benchmark + that compiles 100 source files: + + | Method | Compile Time (s) | + |--------------|------------------| + | printf | 1.6 | + | IOStreams | 25.9 | + | fmt 10.x | 19.0 | + | fmt 11.0 | 4.8 | + | tinyformat | 29.1 | + | Boost Format | 55.0 | + + This gives almost 4x improvement in build speed compared to version 10. + Note that the benchmark is purely formatting code and includes. In real + projects the difference from `printf` will be smaller partly because common + standard headers will be included in almost any translation unit (TU) anyway. + In particular, in every case except `printf` above ~1s is spent in total on + including `` in all TUs. + +- Optimized includes in other headers such as `fmt/format.h` which is now + roughly equivalent to the old `fmt/core.h` in terms of build speed. + +- Migrated the documentation at https://fmt.dev/ from Sphinx to MkDocs. + +- Improved C++20 module support + (https://github.com/fmtlib/fmt/issues/3990, + https://github.com/fmtlib/fmt/pull/3991, + https://github.com/fmtlib/fmt/issues/3993, + https://github.com/fmtlib/fmt/pull/3994, + https://github.com/fmtlib/fmt/pull/3997, + https://github.com/fmtlib/fmt/pull/3998, + https://github.com/fmtlib/fmt/pull/4004, + https://github.com/fmtlib/fmt/pull/4005, + https://github.com/fmtlib/fmt/pull/4006, + https://github.com/fmtlib/fmt/pull/4013, + https://github.com/fmtlib/fmt/pull/4027, + https://github.com/fmtlib/fmt/pull/4029). In particular, native CMake support + for modules is now used if available. Thanks @yujincheng08 and @matt77hias. + +- Added an option to replace standard includes with `import std` enabled via + the `FMT_IMPORT_STD` macro (https://github.com/fmtlib/fmt/issues/3921, + https://github.com/fmtlib/fmt/pull/3928). Thanks @matt77hias. + +- Exported `fmt::range_format`, `fmt::range_format_kind` and + `fmt::compiled_string` from the `fmt` module + (https://github.com/fmtlib/fmt/pull/3970, + https://github.com/fmtlib/fmt/pull/3999). + Thanks @matt77hias and @yujincheng08. + +- Improved integration with stdio in `fmt::print`, enabling direct writes + into a C stream buffer in common cases. This may give significant + performance improvements ranging from tens of percent to [2x]( + https://stackoverflow.com/a/78457454/471164) and eliminates dynamic memory + allocations on the buffer level. It is currently enabled for built-in and + string types with wider availability coming up in future releases. + + For example, it gives ~24% improvement on a [simple benchmark]( + https://isocpp.org/files/papers/P3107R5.html#perf) compiled with Apple clang + version 15.0.0 (clang-1500.1.0.2.5) and run on macOS 14.2.1: + + ``` + ------------------------------------------------------- + Benchmark Time CPU Iterations + ------------------------------------------------------- + printf 81.8 ns 81.5 ns 8496899 + fmt::print (10.x) 63.8 ns 61.9 ns 11524151 + fmt::print (11.0) 51.3 ns 51.0 ns 13846580 + ``` + +- Improved safety of `fmt::format_to` when writing to an array + (https://github.com/fmtlib/fmt/pull/3805). + For example ([godbolt](https://www.godbolt.org/z/cYrn8dWY8)): + + ```c++ + auto volkswagen = char[4]; + auto result = fmt::format_to(volkswagen, "elephant"); + ``` + + no longer results in a buffer overflow. Instead the output will be truncated + and you can get the end iterator and whether truncation occurred from the + `result` object. Thanks @ThePhD. + +- Enabled Unicode support by default in MSVC, bringing it on par with other + compilers and making it unnecessary for users to enable it explicitly. + Most of {fmt} is encoding-agnostic but this prevents mojibake in places + where encoding matters such as path formatting and terminal output. + You can control the Unicode support via the CMake `FMT_UNICODE` option. + Note that some {fmt} packages such as the one in vcpkg have already been + compiled with Unicode enabled. + +- Added a formatter for `std::expected` + (https://github.com/fmtlib/fmt/pull/3834). Thanks @dominicpoeschko. + +- Added a formatter for `std::complex` + (https://github.com/fmtlib/fmt/issues/1467, + https://github.com/fmtlib/fmt/issues/3886, + https://github.com/fmtlib/fmt/pull/3892, + https://github.com/fmtlib/fmt/pull/3900). Thanks @phprus. + +- Added a formatter for `std::type_info` + (https://github.com/fmtlib/fmt/pull/3978). Thanks @matt77hias. + +- Specialized `formatter` for `std::basic_string` types with custom traits + and allocators (https://github.com/fmtlib/fmt/issues/3938, + https://github.com/fmtlib/fmt/pull/3943). Thanks @dieram3. + +- Added formatters for `std::chrono::day`, `std::chrono::month`, + `std::chrono::year` and `std::chrono::year_month_day` + (https://github.com/fmtlib/fmt/issues/3758, + https://github.com/fmtlib/fmt/issues/3772, + https://github.com/fmtlib/fmt/pull/3906, + https://github.com/fmtlib/fmt/pull/3913). For example: + + ```c++ + #include + #include + + int main() { + fmt::print(fg(fmt::color::green), "{}\n", std::chrono::day(7)); + } + ``` + + prints a green day: + + image + + Thanks @zivshek. + +- Fixed handling of precision in `%S` (https://github.com/fmtlib/fmt/issues/3794, + https://github.com/fmtlib/fmt/pull/3814). Thanks @js324. + +- Added support for the `-` specifier (glibc `strftime` extension) to day of + the month (`%d`) and week of the year (`%W`, `%U`, `%V`) specifiers + (https://github.com/fmtlib/fmt/pull/3976). Thanks @ZaheenJ. + +- Fixed the scope of the `-` extension in chrono formatting so that it doesn't + apply to subsequent specifiers (https://github.com/fmtlib/fmt/issues/3811, + https://github.com/fmtlib/fmt/pull/3812). Thanks @phprus. + +- Improved handling of `time_point::min()` + (https://github.com/fmtlib/fmt/issues/3282). + +- Added support for character range formatting + (https://github.com/fmtlib/fmt/issues/3857, + https://github.com/fmtlib/fmt/pull/3863). Thanks @js324. + +- Added `string` and `debug_string` range formatters + (https://github.com/fmtlib/fmt/pull/3973, + https://github.com/fmtlib/fmt/pull/4024). Thanks @matt77hias. + +- Enabled ADL for `begin` and `end` in `fmt::join` + (https://github.com/fmtlib/fmt/issues/3813, + https://github.com/fmtlib/fmt/pull/3824). Thanks @bbolli. + +- Made contiguous iterator optimizations apply to `std::basic_string` iterators + (https://github.com/fmtlib/fmt/pull/3798). Thanks @phprus. + +- Added support for ranges with mutable `begin` and `end` + (https://github.com/fmtlib/fmt/issues/3752, + https://github.com/fmtlib/fmt/pull/3800, + https://github.com/fmtlib/fmt/pull/3955). Thanks @tcbrindle and @Arghnews. + +- Added support for move-only iterators to `fmt::join` + (https://github.com/fmtlib/fmt/issues/3802, + https://github.com/fmtlib/fmt/pull/3946). Thanks @Arghnews. + +- Moved range and iterator overloads of `fmt::join` to `fmt/ranges.h`, next + to other overloads. + +- Fixed handling of types with `begin` returning `void` such as Eigen matrices + (https://github.com/fmtlib/fmt/issues/3839, + https://github.com/fmtlib/fmt/pull/3964). Thanks @Arghnews. + +- Added an `fmt::formattable` concept (https://github.com/fmtlib/fmt/pull/3974). + Thanks @matt77hias. + +- Added support for `__float128` (https://github.com/fmtlib/fmt/issues/3494). + +- Fixed rounding issues when formatting `long double` with fixed precision + (https://github.com/fmtlib/fmt/issues/3539). + +- Made `fmt::isnan` not trigger floating-point exception for NaN values + (https://github.com/fmtlib/fmt/issues/3948, + https://github.com/fmtlib/fmt/pull/3951). Thanks @alexdewar. + +- Removed dependency on `` for `std::allocator_traits` when possible + (https://github.com/fmtlib/fmt/pull/3804). Thanks @phprus. + +- Enabled compile-time checks in formatting functions that take text colors and + styles. + +- Deprecated wide stream overloads of `fmt::print` that take text styles. + +- Made format string compilation work with clang 12 and later despite + only partial non-type template parameter support + (https://github.com/fmtlib/fmt/issues/4000, + https://github.com/fmtlib/fmt/pull/4001). Thanks @yujincheng08. + +- Made `fmt::iterator_buffer`'s move constructor `noexcept` + (https://github.com/fmtlib/fmt/pull/3808). Thanks @waywardmonkeys. + +- Started enforcing that `formatter::format` is const for compatibility + with `std::format` (https://github.com/fmtlib/fmt/issues/3447). + +- Added `fmt::basic_format_arg::visit` and deprecated `fmt::visit_format_arg`. + +- Made `fmt::basic_string_view` not constructible from `nullptr` for + consistency with `std::string_view` in C++23 + (https://github.com/fmtlib/fmt/pull/3846). Thanks @dalle. + +- Fixed `fmt::group_digits` for negative integers + (https://github.com/fmtlib/fmt/issues/3891, + https://github.com/fmtlib/fmt/pull/3901). Thanks @phprus. + +- Fixed handling of negative ids in `fmt::basic_format_args::get` + (https://github.com/fmtlib/fmt/pull/3945). Thanks @marlenecota. + +- Improved named argument validation + (https://github.com/fmtlib/fmt/issues/3817). + +- Disabled copy construction/assignment for `fmt::format_arg_store` and + fixed moved construction (https://github.com/fmtlib/fmt/pull/3833). + Thanks @ivafanas. + +- Worked around a locale issue in RHEL/devtoolset + (https://github.com/fmtlib/fmt/issues/3858, + https://github.com/fmtlib/fmt/pull/3859). Thanks @g199209. + +- Added RTTI detection for MSVC (https://github.com/fmtlib/fmt/pull/3821, + https://github.com/fmtlib/fmt/pull/3963). Thanks @edo9300. + +- Migrated the documentation from Sphinx to MkDocs. + +- Improved documentation and README + (https://github.com/fmtlib/fmt/issues/3775, + https://github.com/fmtlib/fmt/pull/3784, + https://github.com/fmtlib/fmt/issues/3788, + https://github.com/fmtlib/fmt/pull/3789, + https://github.com/fmtlib/fmt/pull/3793, + https://github.com/fmtlib/fmt/issues/3818, + https://github.com/fmtlib/fmt/pull/3820, + https://github.com/fmtlib/fmt/pull/3822, + https://github.com/fmtlib/fmt/pull/3843, + https://github.com/fmtlib/fmt/pull/3890, + https://github.com/fmtlib/fmt/issues/3894, + https://github.com/fmtlib/fmt/pull/3895, + https://github.com/fmtlib/fmt/pull/3905, + https://github.com/fmtlib/fmt/issues/3942, + https://github.com/fmtlib/fmt/pull/4008). + Thanks @zencatalyst, WolleTD, @tupaschoal, @Dobiasd, @frank-weinberg, @bbolli, + @phprus, @waywardmonkeys, @js324 and @tchaikov. + +- Improved CI and tests + (https://github.com/fmtlib/fmt/issues/3878, + https://github.com/fmtlib/fmt/pull/3883, + https://github.com/fmtlib/fmt/issues/3897, + https://github.com/fmtlib/fmt/pull/3979, + https://github.com/fmtlib/fmt/pull/3980, + https://github.com/fmtlib/fmt/pull/3988, + https://github.com/fmtlib/fmt/pull/4010, + https://github.com/fmtlib/fmt/pull/4012, + https://github.com/fmtlib/fmt/pull/4038). + Thanks @vgorrX, @waywardmonkeys, @tchaikov and @phprus. + +- Fixed buffer overflow when using format string compilation with debug format + and `std::back_insert_iterator` (https://github.com/fmtlib/fmt/issues/3795, + https://github.com/fmtlib/fmt/pull/3797). Thanks @phprus. + +- Improved Bazel support + (https://github.com/fmtlib/fmt/pull/3792, + https://github.com/fmtlib/fmt/pull/3801, + https://github.com/fmtlib/fmt/pull/3962, + https://github.com/fmtlib/fmt/pull/3965). Thanks @Vertexwahn. + +- Improved/fixed the CMake config + (https://github.com/fmtlib/fmt/issues/3777, + https://github.com/fmtlib/fmt/pull/3783, + https://github.com/fmtlib/fmt/issues/3847, + https://github.com/fmtlib/fmt/pull/3907). Thanks @phprus and @xTachyon. + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/issues/3685, + https://github.com/fmtlib/fmt/issues/3769, + https://github.com/fmtlib/fmt/issues/3796, + https://github.com/fmtlib/fmt/issues/3803, + https://github.com/fmtlib/fmt/pull/3806, + https://github.com/fmtlib/fmt/pull/3807, + https://github.com/fmtlib/fmt/issues/3809, + https://github.com/fmtlib/fmt/pull/3810, + https://github.com/fmtlib/fmt/issues/3830, + https://github.com/fmtlib/fmt/pull/3832, + https://github.com/fmtlib/fmt/issues/3835, + https://github.com/fmtlib/fmt/pull/3844, + https://github.com/fmtlib/fmt/issues/3854, + https://github.com/fmtlib/fmt/pull/3856, + https://github.com/fmtlib/fmt/pull/3865, + https://github.com/fmtlib/fmt/pull/3866, + https://github.com/fmtlib/fmt/pull/3880, + https://github.com/fmtlib/fmt/issues/3881, + https://github.com/fmtlib/fmt/issues/3884, + https://github.com/fmtlib/fmt/issues/3898, + https://github.com/fmtlib/fmt/pull/3899, + https://github.com/fmtlib/fmt/pull/3909, + https://github.com/fmtlib/fmt/pull/3917, + https://github.com/fmtlib/fmt/pull/3923, + https://github.com/fmtlib/fmt/pull/3924, + https://github.com/fmtlib/fmt/issues/3925, + https://github.com/fmtlib/fmt/pull/3930, + https://github.com/fmtlib/fmt/pull/3931, + https://github.com/fmtlib/fmt/pull/3933, + https://github.com/fmtlib/fmt/issues/3935, + https://github.com/fmtlib/fmt/pull/3937, + https://github.com/fmtlib/fmt/pull/3967, + https://github.com/fmtlib/fmt/pull/3968, + https://github.com/fmtlib/fmt/pull/3972, + https://github.com/fmtlib/fmt/pull/3983, + https://github.com/fmtlib/fmt/issues/3992, + https://github.com/fmtlib/fmt/pull/3995, + https://github.com/fmtlib/fmt/pull/4009, + https://github.com/fmtlib/fmt/pull/4023). + Thanks @hmbj, @phprus, @res2k, @Baardi, @matt77hias, @waywardmonkeys, @hmbj, + @yakra, @prlw1, @Arghnews, @mtillmann0, @ShifftC, @eepp, @jimmy-park and + @ChristianGebhardt. + +# 10.2.1 - 2024-01-04 + +- Fixed ABI compatibility with earlier 10.x versions + (https://github.com/fmtlib/fmt/issues/3785, + https://github.com/fmtlib/fmt/pull/3786). Thanks @saraedum. + +# 10.2.0 - 2024-01-01 + +- Added support for the `%j` specifier (the number of days) for + `std::chrono::duration` (https://github.com/fmtlib/fmt/issues/3643, + https://github.com/fmtlib/fmt/pull/3732). Thanks @intelfx. + +- Added support for the chrono suffix for days and changed + the suffix for minutes from "m" to the correct "min" + (https://github.com/fmtlib/fmt/issues/3662, + https://github.com/fmtlib/fmt/pull/3664). + For example ([godbolt](https://godbolt.org/z/9KhMnq9ba)): + + ```c++ + #include + + int main() { + fmt::print("{}\n", std::chrono::days(42)); // prints "42d" + } + ``` + + Thanks @Richardk2n. + +- Fixed an overflow in `std::chrono::time_point` formatting with large dates + (https://github.com/fmtlib/fmt/issues/3725, + https://github.com/fmtlib/fmt/pull/3727). Thanks @cschreib. + +- Added a formatter for `std::source_location` + (https://github.com/fmtlib/fmt/pull/3730). + For example ([godbolt](https://godbolt.org/z/YajfKjhhr)): + + ```c++ + #include + #include + + int main() { + fmt::print("{}\n", std::source_location::current()); + } + ``` + + prints + + ``` + /app/example.cpp:5:51: int main() + ``` + + Thanks @felix642. + +- Added a formatter for `std::bitset` + (https://github.com/fmtlib/fmt/pull/3660). + For example ([godbolt](https://godbolt.org/z/bdEaGeYxe)): + + ```c++ + #include + #include + + int main() { + fmt::print("{}\n", std::bitset<6>(42)); // prints "101010" + } + ``` + + Thanks @muggenhor. + +- Added an experimental `nested_formatter` that provides an easy way of + applying a formatter to one or more subobjects while automatically handling + width, fill and alignment. For example: + + ```c++ + #include + + struct point { + double x, y; + }; + + template <> + struct fmt::formatter : nested_formatter { + auto format(point p, format_context& ctx) const { + return write_padded(ctx, [=](auto out) { + return format_to(out, "({}, {})", nested(p.x), nested(p.y)); + }); + } + }; + + int main() { + fmt::print("[{:>20.2f}]", point{1, 2}); + } + ``` + + prints + + ``` + [ (1.00, 2.00)] + ``` + +- Added the generic representation (`g`) to `std::filesystem::path` + (https://github.com/fmtlib/fmt/issues/3715, + https://github.com/fmtlib/fmt/pull/3729). For example: + + ```c++ + #include + #include + + int main() { + fmt::print("{:g}\n", std::filesystem::path("C:\\foo")); + } + ``` + + prints `"C:/foo"` on Windows. + + Thanks @js324. + +- Made `format_as` work with references + (https://github.com/fmtlib/fmt/pull/3739). Thanks @tchaikov. + +- Fixed formatting of invalid UTF-8 with precision + (https://github.com/fmtlib/fmt/issues/3284). + +- Fixed an inconsistency between `fmt::to_string` and `fmt::format` + (https://github.com/fmtlib/fmt/issues/3684). + +- Disallowed unsafe uses of `fmt::styled` + (https://github.com/fmtlib/fmt/issues/3625): + + ```c++ + auto s = fmt::styled(std::string("dangle"), fmt::emphasis::bold); + fmt::print("{}\n", s); // compile error + ``` + + Pass `fmt::styled(...)` as a parameter instead. + +- Added a null check when formatting a C string with the `s` specifier + (https://github.com/fmtlib/fmt/issues/3706). + +- Disallowed the `c` specifier for `bool` + (https://github.com/fmtlib/fmt/issues/3726, + https://github.com/fmtlib/fmt/pull/3734). Thanks @js324. + +- Made the default formatting unlocalized in `fmt::ostream_formatter` for + consistency with the rest of the library + (https://github.com/fmtlib/fmt/issues/3460). + +- Fixed localized formatting in bases other than decimal + (https://github.com/fmtlib/fmt/issues/3693, + https://github.com/fmtlib/fmt/pull/3750). Thanks @js324. + +- Fixed a performance regression in experimental `fmt::ostream::print` + (https://github.com/fmtlib/fmt/issues/3674). + +- Added synchronization with the underlying output stream when writing to + the Windows console + (https://github.com/fmtlib/fmt/pull/3668, + https://github.com/fmtlib/fmt/issues/3688, + https://github.com/fmtlib/fmt/pull/3689). + Thanks @Roman-Koshelev and @dimztimz. + +- Changed to only export `format_error` when {fmt} is built as a shared + library (https://github.com/fmtlib/fmt/issues/3626, + https://github.com/fmtlib/fmt/pull/3627). Thanks @phprus. + +- Made `fmt::streamed` `constexpr`. + (https://github.com/fmtlib/fmt/pull/3650). Thanks @muggenhor. + +- Made `fmt::format_int` `constexpr` + (https://github.com/fmtlib/fmt/issues/4031, + https://github.com/fmtlib/fmt/pull/4032). Thanks @dixlorenz. + +- Enabled `consteval` on older versions of MSVC + (https://github.com/fmtlib/fmt/pull/3757). Thanks @phprus. + +- Added an option to build without `wchar_t` support on Windows + (https://github.com/fmtlib/fmt/issues/3631, + https://github.com/fmtlib/fmt/pull/3636). Thanks @glebm. + +- Improved build and CI configuration + (https://github.com/fmtlib/fmt/pull/3679, + https://github.com/fmtlib/fmt/issues/3701, + https://github.com/fmtlib/fmt/pull/3702, + https://github.com/fmtlib/fmt/pull/3749). + Thanks @jcar87, @pklima and @tchaikov. + +- Fixed various warnings, compilation and test issues + (https://github.com/fmtlib/fmt/issues/3607, + https://github.com/fmtlib/fmt/pull/3610, + https://github.com/fmtlib/fmt/pull/3624, + https://github.com/fmtlib/fmt/pull/3630, + https://github.com/fmtlib/fmt/pull/3634, + https://github.com/fmtlib/fmt/pull/3638, + https://github.com/fmtlib/fmt/issues/3645, + https://github.com/fmtlib/fmt/issues/3646, + https://github.com/fmtlib/fmt/pull/3647, + https://github.com/fmtlib/fmt/pull/3652, + https://github.com/fmtlib/fmt/issues/3654, + https://github.com/fmtlib/fmt/pull/3663, + https://github.com/fmtlib/fmt/issues/3670, + https://github.com/fmtlib/fmt/pull/3680, + https://github.com/fmtlib/fmt/issues/3694, + https://github.com/fmtlib/fmt/pull/3695, + https://github.com/fmtlib/fmt/pull/3699, + https://github.com/fmtlib/fmt/issues/3705, + https://github.com/fmtlib/fmt/issues/3710, + https://github.com/fmtlib/fmt/issues/3712, + https://github.com/fmtlib/fmt/pull/3713, + https://github.com/fmtlib/fmt/issues/3714, + https://github.com/fmtlib/fmt/pull/3716, + https://github.com/fmtlib/fmt/pull/3723, + https://github.com/fmtlib/fmt/issues/3738, + https://github.com/fmtlib/fmt/issues/3740, + https://github.com/fmtlib/fmt/pull/3741, + https://github.com/fmtlib/fmt/pull/3743, + https://github.com/fmtlib/fmt/issues/3745, + https://github.com/fmtlib/fmt/pull/3747, + https://github.com/fmtlib/fmt/pull/3748, + https://github.com/fmtlib/fmt/pull/3751, + https://github.com/fmtlib/fmt/pull/3754, + https://github.com/fmtlib/fmt/pull/3755, + https://github.com/fmtlib/fmt/issues/3760, + https://github.com/fmtlib/fmt/pull/3762, + https://github.com/fmtlib/fmt/issues/3763, + https://github.com/fmtlib/fmt/pull/3764, + https://github.com/fmtlib/fmt/issues/3774, + https://github.com/fmtlib/fmt/pull/3779). + Thanks @danakj, @vinayyadav3016, @cyyever, @phprus, @qimiko, @saschasc, + @gsjaardema, @lazka, @Zhaojun-Liu, @carlsmedstad, @hotwatermorning, + @cptFracassa, @kuguma, @PeterJohnson, @H1X4Dev, @asantoni, @eltociear, + @msimberg, @tchaikov, @waywardmonkeys. + +- Improved documentation and README + (https://github.com/fmtlib/fmt/issues/2086, + https://github.com/fmtlib/fmt/issues/3637, + https://github.com/fmtlib/fmt/pull/3642, + https://github.com/fmtlib/fmt/pull/3653, + https://github.com/fmtlib/fmt/pull/3655, + https://github.com/fmtlib/fmt/pull/3661, + https://github.com/fmtlib/fmt/issues/3673, + https://github.com/fmtlib/fmt/pull/3677, + https://github.com/fmtlib/fmt/pull/3737, + https://github.com/fmtlib/fmt/issues/3742, + https://github.com/fmtlib/fmt/pull/3744). + Thanks @idzm, @perlun, @joycebrum, @fennewald, @reinhardt1053, @GeorgeLS. + +- Updated CI dependencies + (https://github.com/fmtlib/fmt/pull/3615, + https://github.com/fmtlib/fmt/pull/3622, + https://github.com/fmtlib/fmt/pull/3623, + https://github.com/fmtlib/fmt/pull/3666, + https://github.com/fmtlib/fmt/pull/3696, + https://github.com/fmtlib/fmt/pull/3697, + https://github.com/fmtlib/fmt/pull/3759, + https://github.com/fmtlib/fmt/pull/3782). + +# 10.1.1 - 2023-08-28 + +- Added formatters for `std::atomic` and `atomic_flag` + (https://github.com/fmtlib/fmt/pull/3574, + https://github.com/fmtlib/fmt/pull/3594). + Thanks @wangzw and @AlexGuteniev. +- Fixed an error about partial specialization of `formatter` + after instantiation when compiled with gcc and C++20 + (https://github.com/fmtlib/fmt/issues/3584). +- Fixed compilation as a C++20 module with gcc and clang + (https://github.com/fmtlib/fmt/issues/3587, + https://github.com/fmtlib/fmt/pull/3597, + https://github.com/fmtlib/fmt/pull/3605). + Thanks @MathewBensonCode. +- Made `fmt::to_string` work with types that have `format_as` + overloads (https://github.com/fmtlib/fmt/pull/3575). Thanks @phprus. +- Made `formatted_size` work with integral format specifiers at + compile time (https://github.com/fmtlib/fmt/pull/3591). + Thanks @elbeno. +- Fixed a warning about the `no_unique_address` attribute on clang-cl + (https://github.com/fmtlib/fmt/pull/3599). Thanks @lukester1975. +- Improved compatibility with the legacy GBK encoding + (https://github.com/fmtlib/fmt/issues/3598, + https://github.com/fmtlib/fmt/pull/3599). Thanks @YuHuanTin. +- Added OpenSSF Scorecard analysis + (https://github.com/fmtlib/fmt/issues/3530, + https://github.com/fmtlib/fmt/pull/3571). Thanks @joycebrum. +- Updated CI dependencies + (https://github.com/fmtlib/fmt/pull/3591, + https://github.com/fmtlib/fmt/pull/3592, + https://github.com/fmtlib/fmt/pull/3593, + https://github.com/fmtlib/fmt/pull/3602). + +# 10.1.0 - 2023-08-12 + +- Optimized format string compilation resulting in up to 40% speed up + in compiled `format_to` and \~4x speed up in compiled `format_to_n` + on a concatenation benchmark + (https://github.com/fmtlib/fmt/issues/3133, + https://github.com/fmtlib/fmt/issues/3484). + + {fmt} 10.0: + + --------------------------------------------------------- + Benchmark Time CPU Iterations + --------------------------------------------------------- + BM_format_to 78.9 ns 78.9 ns 8881746 + BM_format_to_n 568 ns 568 ns 1232089 + + {fmt} 10.1: + + --------------------------------------------------------- + Benchmark Time CPU Iterations + --------------------------------------------------------- + BM_format_to 54.9 ns 54.9 ns 12727944 + BM_format_to_n 133 ns 133 ns 5257795 + +- Optimized storage of an empty allocator in `basic_memory_buffer` + (https://github.com/fmtlib/fmt/pull/3485). Thanks @Minty-Meeo. + +- Added formatters for proxy references to elements of + `std::vector` and `std::bitset` + (https://github.com/fmtlib/fmt/issues/3567, + https://github.com/fmtlib/fmt/pull/3570). For example + ([godbolt](https://godbolt.org/z/zYb79Pvn8)): + + ```c++ + #include + #include + + int main() { + auto v = std::vector{true}; + fmt::print("{}", v[0]); + } + ``` + + Thanks @phprus and @felix642. + +- Fixed an ambiguous formatter specialization for containers that look + like container adaptors such as `boost::flat_set` + (https://github.com/fmtlib/fmt/issues/3556, + https://github.com/fmtlib/fmt/pull/3561). Thanks @5chmidti. + +- Fixed compilation when formatting durations not convertible from + `std::chrono::seconds` + (https://github.com/fmtlib/fmt/pull/3430). Thanks @patlkli. + +- Made the `formatter` specialization for `char*` const-correct + (https://github.com/fmtlib/fmt/pull/3432). Thanks @timsong-cpp. + +- Made `{}` and `{:}` handled consistently during compile-time checks + (https://github.com/fmtlib/fmt/issues/3526). + +- Disallowed passing temporaries to `make_format_args` to improve API + safety by preventing dangling references. + +- Improved the compile-time error for unformattable types + (https://github.com/fmtlib/fmt/pull/3478). Thanks @BRevzin. + +- Improved the floating-point formatter + (https://github.com/fmtlib/fmt/pull/3448, + https://github.com/fmtlib/fmt/pull/3450). + Thanks @florimond-collette. + +- Fixed handling of precision for `long double` larger than 64 bits. + (https://github.com/fmtlib/fmt/issues/3539, + https://github.com/fmtlib/fmt/issues/3564). + +- Made floating-point and chrono tests less platform-dependent + (https://github.com/fmtlib/fmt/issues/3337, + https://github.com/fmtlib/fmt/issues/3433, + https://github.com/fmtlib/fmt/pull/3434). Thanks @phprus. + +- Removed the remnants of the Grisu floating-point formatter that has + been replaced by Dragonbox in earlier versions. + +- Added `throw_format_error` to the public API + (https://github.com/fmtlib/fmt/pull/3551). Thanks @mjerabek. + +- Made `FMT_THROW` assert even if assertions are disabled when + compiling with exceptions disabled + (https://github.com/fmtlib/fmt/issues/3418, + https://github.com/fmtlib/fmt/pull/3439). Thanks @BRevzin. + +- Made `format_as` and `std::filesystem::path` formatter work with + exotic code unit types. + (https://github.com/fmtlib/fmt/pull/3457, + https://github.com/fmtlib/fmt/pull/3476). Thanks @gix and @hmbj. + +- Added support for the `?` format specifier to + `std::filesystem::path` and made the default unescaped for + consistency with strings. + +- Deprecated the wide stream overload of `printf`. + +- Removed unused `basic_printf_parse_context`. + +- Improved RTTI detection used when formatting exceptions + (https://github.com/fmtlib/fmt/pull/3468). Thanks @danakj. + +- Improved compatibility with VxWorks7 + (https://github.com/fmtlib/fmt/pull/3467). Thanks @wenshan1. + +- Improved documentation + (https://github.com/fmtlib/fmt/issues/3174, + https://github.com/fmtlib/fmt/issues/3423, + https://github.com/fmtlib/fmt/pull/3454, + https://github.com/fmtlib/fmt/issues/3458, + https://github.com/fmtlib/fmt/pull/3461, + https://github.com/fmtlib/fmt/issues/3487, + https://github.com/fmtlib/fmt/pull/3515). + Thanks @zencatalyst, @rlalik and @mikecrowe. + +- Improved build and CI configurations + (https://github.com/fmtlib/fmt/issues/3449, + https://github.com/fmtlib/fmt/pull/3451, + https://github.com/fmtlib/fmt/pull/3452, + https://github.com/fmtlib/fmt/pull/3453, + https://github.com/fmtlib/fmt/pull/3459, + https://github.com/fmtlib/fmt/issues/3481, + https://github.com/fmtlib/fmt/pull/3486, + https://github.com/fmtlib/fmt/issues/3489, + https://github.com/fmtlib/fmt/pull/3496, + https://github.com/fmtlib/fmt/issues/3517, + https://github.com/fmtlib/fmt/pull/3523, + https://github.com/fmtlib/fmt/pull/3563). + Thanks @joycebrum, @glebm, @phprus, @petrmanek, @setoye and @abouvier. + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/issues/3408, + https://github.com/fmtlib/fmt/issues/3424, + https://github.com/fmtlib/fmt/issues/3444, + https://github.com/fmtlib/fmt/pull/3446, + https://github.com/fmtlib/fmt/pull/3475, + https://github.com/fmtlib/fmt/pull/3482, + https://github.com/fmtlib/fmt/issues/3492, + https://github.com/fmtlib/fmt/pull/3493, + https://github.com/fmtlib/fmt/pull/3508, + https://github.com/fmtlib/fmt/issues/3509, + https://github.com/fmtlib/fmt/issues/3533, + https://github.com/fmtlib/fmt/pull/3542, + https://github.com/fmtlib/fmt/issues/3543, + https://github.com/fmtlib/fmt/issues/3540, + https://github.com/fmtlib/fmt/pull/3544, + https://github.com/fmtlib/fmt/issues/3548, + https://github.com/fmtlib/fmt/pull/3549, + https://github.com/fmtlib/fmt/pull/3550, + https://github.com/fmtlib/fmt/pull/3552). + Thanks @adesitter, @hmbj, @Minty-Meeo, @phprus, @TobiSchluter, + @kieranclancy, @alexeedm, @jurihock, @Ozomahtli and @razaqq. + +# 10.0.0 - 2023-05-09 + +- Replaced Grisu with a new floating-point formatting algorithm for + given precision (https://github.com/fmtlib/fmt/issues/3262, + https://github.com/fmtlib/fmt/issues/2750, + https://github.com/fmtlib/fmt/pull/3269, + https://github.com/fmtlib/fmt/pull/3276). The new algorithm + is based on Dragonbox already used for the shortest representation + and gives substantial performance improvement: + + ![](https://user-images.githubusercontent.com/33922675/211956670-84891a09-6867-47d9-82fc-3230da7abe0f.png) + + - Red: new algorithm + - Green: new algorithm with `FMT_USE_FULL_CACHE_DRAGONBOX` defined + to 1 + - Blue: old algorithm + + Thanks @jk-jeon. + +- Replaced `snprintf`-based hex float formatter with an internal + implementation (https://github.com/fmtlib/fmt/pull/3179, + https://github.com/fmtlib/fmt/pull/3203). This removes the + last usage of `s(n)printf` in {fmt}. Thanks @phprus. + +- Fixed alignment of floating-point numbers with localization + (https://github.com/fmtlib/fmt/issues/3263, + https://github.com/fmtlib/fmt/pull/3272). Thanks @ShawnZhong. + +- Made handling of `#` consistent with `std::format`. + +- Improved C++20 module support + (https://github.com/fmtlib/fmt/pull/3134, + https://github.com/fmtlib/fmt/pull/3254, + https://github.com/fmtlib/fmt/pull/3386, + https://github.com/fmtlib/fmt/pull/3387, + https://github.com/fmtlib/fmt/pull/3388, + https://github.com/fmtlib/fmt/pull/3392, + https://github.com/fmtlib/fmt/pull/3397, + https://github.com/fmtlib/fmt/pull/3399, + https://github.com/fmtlib/fmt/pull/3400). + Thanks @laitingsheng, @Orvid and @DanielaE. + +- Switched to the [modules CMake library](https://github.com/vitaut/modules) + which allows building {fmt} as a C++20 module with clang: + + CXX=clang++ cmake -DFMT_MODULE=ON . + make + +- Made `format_as` work with any user-defined type and not just enums. + For example ([godbolt](https://godbolt.org/z/b7rqhq5Kh)): + + ```c++ + #include + + struct floaty_mc_floatface { + double value; + }; + + auto format_as(floaty_mc_floatface f) { return f.value; } + + int main() { + fmt::print("{:8}\n", floaty_mc_floatface{0.42}); // prints " 0.42" + } + ``` + +- Removed deprecated implicit conversions for enums and conversions to + primitive types for compatibility with `std::format` and to prevent + potential ODR violations. Use `format_as` instead. + +- Added support for fill, align and width to the time point formatter + (https://github.com/fmtlib/fmt/issues/3237, + https://github.com/fmtlib/fmt/pull/3260, + https://github.com/fmtlib/fmt/pull/3275). For example + ([godbolt](https://godbolt.org/z/rKP6MGz6c)): + + ```c++ + #include + + int main() { + // prints " 2023" + fmt::print("{:>8%Y}\n", std::chrono::system_clock::now()); + } + ``` + + Thanks @ShawnZhong. + +- Implemented formatting of subseconds + (https://github.com/fmtlib/fmt/issues/2207, + https://github.com/fmtlib/fmt/issues/3117, + https://github.com/fmtlib/fmt/pull/3115, + https://github.com/fmtlib/fmt/pull/3143, + https://github.com/fmtlib/fmt/pull/3144, + https://github.com/fmtlib/fmt/pull/3349). For example + ([godbolt](https://godbolt.org/z/45738oGEo)): + + ```c++ + #include + + int main() { + // prints 01.234567 + fmt::print("{:%S}\n", std::chrono::microseconds(1234567)); + } + ``` + + Thanks @patrickroocks @phprus and @BRevzin. + +- Added precision support to `%S` + (https://github.com/fmtlib/fmt/pull/3148). Thanks @SappyJoy + +- Added support for `std::utc_time` + (https://github.com/fmtlib/fmt/issues/3098, + https://github.com/fmtlib/fmt/pull/3110). Thanks @patrickroocks. + +- Switched formatting of `std::chrono::system_clock` from local time + to UTC for compatibility with the standard + (https://github.com/fmtlib/fmt/issues/3199, + https://github.com/fmtlib/fmt/pull/3230). Thanks @ned14. + +- Added support for `%Ez` and `%Oz` to chrono formatters. + (https://github.com/fmtlib/fmt/issues/3220, + https://github.com/fmtlib/fmt/pull/3222). Thanks @phprus. + +- Improved validation of format specifiers for `std::chrono::duration` + (https://github.com/fmtlib/fmt/issues/3219, + https://github.com/fmtlib/fmt/pull/3232). Thanks @ShawnZhong. + +- Fixed formatting of time points before the epoch + (https://github.com/fmtlib/fmt/issues/3117, + https://github.com/fmtlib/fmt/pull/3261). For example + ([godbolt](https://godbolt.org/z/f7bcznb3W)): + + ```c++ + #include + + int main() { + auto t = std::chrono::system_clock::from_time_t(0) - + std::chrono::milliseconds(250); + fmt::print("{:%S}\n", t); // prints 59.750000000 + } + ``` + + Thanks @ShawnZhong. + +- Experimental: implemented glibc extension for padding seconds, + minutes and hours + (https://github.com/fmtlib/fmt/issues/2959, + https://github.com/fmtlib/fmt/pull/3271). Thanks @ShawnZhong. + +- Added a formatter for `std::exception` + (https://github.com/fmtlib/fmt/issues/2977, + https://github.com/fmtlib/fmt/issues/3012, + https://github.com/fmtlib/fmt/pull/3062, + https://github.com/fmtlib/fmt/pull/3076, + https://github.com/fmtlib/fmt/pull/3119). For example + ([godbolt](https://godbolt.org/z/8xoWGs9e4)): + + ```c++ + #include + #include + + int main() { + try { + std::vector().at(0); + } catch(const std::exception& e) { + fmt::print("{}", e); + } + } + ``` + + prints: + + vector::_M_range_check: __n (which is 0) >= this->size() (which is 0) + + on libstdc++. Thanks @zach2good and @phprus. + +- Moved `std::error_code` formatter from `fmt/os.h` to `fmt/std.h`. + (https://github.com/fmtlib/fmt/pull/3125). Thanks @phprus. + +- Added formatters for standard container adapters: + `std::priority_queue`, `std::queue` and `std::stack` + (https://github.com/fmtlib/fmt/issues/3215, + https://github.com/fmtlib/fmt/pull/3279). For example + ([godbolt](https://godbolt.org/z/74h1xY9qK)): + + ```c++ + #include + #include + #include + + int main() { + auto s = std::stack>(); + for (auto b: {true, false, true}) s.push(b); + fmt::print("{}\n", s); // prints [true, false, true] + } + ``` + + Thanks @ShawnZhong. + +- Added a formatter for `std::optional` to `fmt/std.h` + (https://github.com/fmtlib/fmt/issues/1367, + https://github.com/fmtlib/fmt/pull/3303). + Thanks @tom-huntington. + +- Fixed formatting of valueless by exception variants + (https://github.com/fmtlib/fmt/pull/3347). Thanks @TheOmegaCarrot. + +- Made `fmt::ptr` accept `unique_ptr` with a custom deleter + (https://github.com/fmtlib/fmt/pull/3177). Thanks @hmbj. + +- Fixed formatting of noncopyable ranges and nested ranges of chars + (https://github.com/fmtlib/fmt/pull/3158 + https://github.com/fmtlib/fmt/issues/3286, + https://github.com/fmtlib/fmt/pull/3290). Thanks @BRevzin. + +- Fixed issues with formatting of paths and ranges of paths + (https://github.com/fmtlib/fmt/issues/3319, + https://github.com/fmtlib/fmt/pull/3321 + https://github.com/fmtlib/fmt/issues/3322). Thanks @phprus. + +- Improved handling of invalid Unicode in paths. + +- Enabled compile-time checks on Apple clang 14 and later + (https://github.com/fmtlib/fmt/pull/3331). Thanks @cloyce. + +- Improved compile-time checks of named arguments + (https://github.com/fmtlib/fmt/issues/3105, + https://github.com/fmtlib/fmt/pull/3214). Thanks @rbrich. + +- Fixed formatting when both alignment and `0` are given + (https://github.com/fmtlib/fmt/issues/3236, + https://github.com/fmtlib/fmt/pull/3248). Thanks @ShawnZhong. + +- Improved Unicode support in the experimental file API on Windows + (https://github.com/fmtlib/fmt/issues/3234, + https://github.com/fmtlib/fmt/pull/3293). Thanks @Fros1er. + +- Unified UTF transcoding + (https://github.com/fmtlib/fmt/pull/3416). Thanks @phprus. + +- Added support for UTF-8 digit separators via an experimental locale + facet (https://github.com/fmtlib/fmt/issues/1861). For + example ([godbolt](https://godbolt.org/z/f7bcznb3W)): + + ```c++ + auto loc = std::locale( + std::locale(), new fmt::format_facet("’")); + auto s = fmt::format(loc, "{:L}", 1000); + ``` + + where `’` is U+2019 used as a digit separator in the de_CH locale. + +- Added an overload of `formatted_size` that takes a locale + (https://github.com/fmtlib/fmt/issues/3084, + https://github.com/fmtlib/fmt/pull/3087). Thanks @gerboengels. + +- Removed the deprecated `FMT_DEPRECATED_OSTREAM`. + +- Fixed a UB when using a null `std::string_view` with + `fmt::to_string` or format string compilation + (https://github.com/fmtlib/fmt/issues/3241, + https://github.com/fmtlib/fmt/pull/3244). Thanks @phprus. + +- Added `starts_with` to the fallback `string_view` implementation + (https://github.com/fmtlib/fmt/pull/3080). Thanks @phprus. + +- Added `fmt::basic_format_string::get()` for compatibility with + `basic_format_string` + (https://github.com/fmtlib/fmt/pull/3111). Thanks @huangqinjin. + +- Added `println` for compatibility with C++23 + (https://github.com/fmtlib/fmt/pull/3267). Thanks @ShawnZhong. + +- Renamed the `FMT_EXPORT` macro for shared library usage to + `FMT_LIB_EXPORT`. + +- Improved documentation + (https://github.com/fmtlib/fmt/issues/3108, + https://github.com/fmtlib/fmt/issues/3169, + https://github.com/fmtlib/fmt/pull/3243). + https://github.com/fmtlib/fmt/pull/3404, + https://github.com/fmtlib/fmt/pull/4002). + Thanks @Cleroth, @Vertexwahn and @yujincheng08. + +- Improved build configuration and tests + (https://github.com/fmtlib/fmt/pull/3118, + https://github.com/fmtlib/fmt/pull/3120, + https://github.com/fmtlib/fmt/pull/3188, + https://github.com/fmtlib/fmt/issues/3189, + https://github.com/fmtlib/fmt/pull/3198, + https://github.com/fmtlib/fmt/pull/3205, + https://github.com/fmtlib/fmt/pull/3207, + https://github.com/fmtlib/fmt/pull/3210, + https://github.com/fmtlib/fmt/pull/3240, + https://github.com/fmtlib/fmt/pull/3256, + https://github.com/fmtlib/fmt/pull/3264, + https://github.com/fmtlib/fmt/issues/3299, + https://github.com/fmtlib/fmt/pull/3302, + https://github.com/fmtlib/fmt/pull/3312, + https://github.com/fmtlib/fmt/issues/3317, + https://github.com/fmtlib/fmt/pull/3328, + https://github.com/fmtlib/fmt/pull/3333, + https://github.com/fmtlib/fmt/pull/3369, + https://github.com/fmtlib/fmt/issues/3373, + https://github.com/fmtlib/fmt/pull/3395, + https://github.com/fmtlib/fmt/pull/3406, + https://github.com/fmtlib/fmt/pull/3411). + Thanks @dimztimz, @phprus, @DavidKorczynski, @ChrisThrasher, + @FrancoisCarouge, @kennyweiss, @luzpaz, @codeinred, @Mixaill, @joycebrum, + @kevinhwang and @Vertexwahn. + +- Fixed a regression in handling empty format specifiers after a colon + (`{:}`) (https://github.com/fmtlib/fmt/pull/3086). Thanks @oxidase. + +- Worked around a broken implementation of + `std::is_constant_evaluated` in some versions of libstdc++ on clang + (https://github.com/fmtlib/fmt/issues/3247, + https://github.com/fmtlib/fmt/pull/3281). Thanks @phprus. + +- Fixed formatting of volatile variables + (https://github.com/fmtlib/fmt/pull/3068). + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/pull/3057, + https://github.com/fmtlib/fmt/pull/3066, + https://github.com/fmtlib/fmt/pull/3072, + https://github.com/fmtlib/fmt/pull/3082, + https://github.com/fmtlib/fmt/pull/3091, + https://github.com/fmtlib/fmt/issues/3092, + https://github.com/fmtlib/fmt/pull/3093, + https://github.com/fmtlib/fmt/pull/3095, + https://github.com/fmtlib/fmt/issues/3096, + https://github.com/fmtlib/fmt/pull/3097, + https://github.com/fmtlib/fmt/issues/3128, + https://github.com/fmtlib/fmt/pull/3129, + https://github.com/fmtlib/fmt/pull/3137, + https://github.com/fmtlib/fmt/pull/3139, + https://github.com/fmtlib/fmt/issues/3140, + https://github.com/fmtlib/fmt/pull/3142, + https://github.com/fmtlib/fmt/issues/3149, + https://github.com/fmtlib/fmt/pull/3150, + https://github.com/fmtlib/fmt/issues/3154, + https://github.com/fmtlib/fmt/issues/3163, + https://github.com/fmtlib/fmt/issues/3178, + https://github.com/fmtlib/fmt/pull/3184, + https://github.com/fmtlib/fmt/pull/3196, + https://github.com/fmtlib/fmt/issues/3204, + https://github.com/fmtlib/fmt/pull/3206, + https://github.com/fmtlib/fmt/pull/3208, + https://github.com/fmtlib/fmt/issues/3213, + https://github.com/fmtlib/fmt/pull/3216, + https://github.com/fmtlib/fmt/issues/3224, + https://github.com/fmtlib/fmt/issues/3226, + https://github.com/fmtlib/fmt/issues/3228, + https://github.com/fmtlib/fmt/pull/3229, + https://github.com/fmtlib/fmt/pull/3259, + https://github.com/fmtlib/fmt/issues/3274, + https://github.com/fmtlib/fmt/issues/3287, + https://github.com/fmtlib/fmt/pull/3288, + https://github.com/fmtlib/fmt/issues/3292, + https://github.com/fmtlib/fmt/pull/3295, + https://github.com/fmtlib/fmt/pull/3296, + https://github.com/fmtlib/fmt/issues/3298, + https://github.com/fmtlib/fmt/issues/3325, + https://github.com/fmtlib/fmt/pull/3326, + https://github.com/fmtlib/fmt/issues/3334, + https://github.com/fmtlib/fmt/issues/3342, + https://github.com/fmtlib/fmt/pull/3343, + https://github.com/fmtlib/fmt/issues/3351, + https://github.com/fmtlib/fmt/pull/3352, + https://github.com/fmtlib/fmt/pull/3362, + https://github.com/fmtlib/fmt/issues/3365, + https://github.com/fmtlib/fmt/pull/3366, + https://github.com/fmtlib/fmt/pull/3374, + https://github.com/fmtlib/fmt/issues/3377, + https://github.com/fmtlib/fmt/pull/3378, + https://github.com/fmtlib/fmt/issues/3381, + https://github.com/fmtlib/fmt/pull/3398, + https://github.com/fmtlib/fmt/pull/3413, + https://github.com/fmtlib/fmt/issues/3415). + Thanks @phprus, @gsjaardema, @NewbieOrange, @EngineLessCC, @asmaloney, + @HazardyKnusperkeks, @sergiud, @Youw, @thesmurph, @czudziakm, + @Roman-Koshelev, @chronoxor, @ShawnZhong, @russelltg, @glebm, @tmartin-gh, + @Zhaojun-Liu, @louiswins and @mogemimi. + +# 9.1.0 - 2022-08-27 + +- `fmt::formatted_size` now works at compile time + (https://github.com/fmtlib/fmt/pull/3026). For example + ([godbolt](https://godbolt.org/z/1MW5rMdf8)): + + ```c++ + #include + + int main() { + using namespace fmt::literals; + constexpr size_t n = fmt::formatted_size("{}"_cf, 42); + fmt::print("{}\n", n); // prints 2 + } + ``` + + Thanks @marksantaniello. + +- Fixed handling of invalid UTF-8 + (https://github.com/fmtlib/fmt/pull/3038, + https://github.com/fmtlib/fmt/pull/3044, + https://github.com/fmtlib/fmt/pull/3056). + Thanks @phprus and @skeeto. + +- Improved Unicode support in `ostream` overloads of `print` + (https://github.com/fmtlib/fmt/pull/2994, + https://github.com/fmtlib/fmt/pull/3001, + https://github.com/fmtlib/fmt/pull/3025). Thanks @dimztimz. + +- Fixed handling of the sign specifier in localized formatting on + systems with 32-bit `wchar_t` + (https://github.com/fmtlib/fmt/issues/3041). + +- Added support for wide streams to `fmt::streamed` + (https://github.com/fmtlib/fmt/pull/2994). Thanks @phprus. + +- Added the `n` specifier that disables the output of delimiters when + formatting ranges (https://github.com/fmtlib/fmt/pull/2981, + https://github.com/fmtlib/fmt/pull/2983). For example + ([godbolt](https://godbolt.org/z/roKqGdj8c)): + + ```c++ + #include + #include + + int main() { + auto v = std::vector{1, 2, 3}; + fmt::print("{:n}\n", v); // prints 1, 2, 3 + } + ``` + + Thanks @BRevzin. + +- Worked around problematic `std::string_view` constructors introduced + in C++23 (https://github.com/fmtlib/fmt/issues/3030, + https://github.com/fmtlib/fmt/issues/3050). Thanks @strega-nil-ms. + +- Improve handling (exclusion) of recursive ranges + (https://github.com/fmtlib/fmt/issues/2968, + https://github.com/fmtlib/fmt/pull/2974). Thanks @Dani-Hub. + +- Improved error reporting in format string compilation + (https://github.com/fmtlib/fmt/issues/3055). + +- Improved the implementation of + [Dragonbox](https://github.com/jk-jeon/dragonbox), the algorithm + used for the default floating-point formatting + (https://github.com/fmtlib/fmt/pull/2984). Thanks @jk-jeon. + +- Fixed issues with floating-point formatting on exotic platforms. + +- Improved the implementation of chrono formatting + (https://github.com/fmtlib/fmt/pull/3010). Thanks @phprus. + +- Improved documentation + (https://github.com/fmtlib/fmt/pull/2966, + https://github.com/fmtlib/fmt/pull/3009, + https://github.com/fmtlib/fmt/issues/3020, + https://github.com/fmtlib/fmt/pull/3037). + Thanks @mwinterb, @jcelerier and @remiburtin. + +- Improved build configuration + (https://github.com/fmtlib/fmt/pull/2991, + https://github.com/fmtlib/fmt/pull/2995, + https://github.com/fmtlib/fmt/issues/3004, + https://github.com/fmtlib/fmt/pull/3007, + https://github.com/fmtlib/fmt/pull/3040). + Thanks @dimztimz and @hwhsu1231. + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/issues/2969, + https://github.com/fmtlib/fmt/pull/2971, + https://github.com/fmtlib/fmt/issues/2975, + https://github.com/fmtlib/fmt/pull/2982, + https://github.com/fmtlib/fmt/pull/2985, + https://github.com/fmtlib/fmt/issues/2988, + https://github.com/fmtlib/fmt/issues/2989, + https://github.com/fmtlib/fmt/issues/3000, + https://github.com/fmtlib/fmt/issues/3006, + https://github.com/fmtlib/fmt/issues/3014, + https://github.com/fmtlib/fmt/issues/3015, + https://github.com/fmtlib/fmt/pull/3021, + https://github.com/fmtlib/fmt/issues/3023, + https://github.com/fmtlib/fmt/pull/3024, + https://github.com/fmtlib/fmt/pull/3029, + https://github.com/fmtlib/fmt/pull/3043, + https://github.com/fmtlib/fmt/issues/3052, + https://github.com/fmtlib/fmt/pull/3053, + https://github.com/fmtlib/fmt/pull/3054). + Thanks @h-friederich, @dimztimz, @olupton, @bernhardmgruber and @phprus. + +# 9.0.0 - 2022-07-04 + +- Switched to the internal floating point formatter for all decimal + presentation formats. In particular this results in consistent + rounding on all platforms and removing the `s[n]printf` fallback for + decimal FP formatting. + +- Compile-time floating point formatting no longer requires the + header-only mode. For example + ([godbolt](https://godbolt.org/z/G37PTeG3b)): + + ```c++ + #include + #include + + consteval auto compile_time_dtoa(double value) -> std::array { + auto result = std::array(); + fmt::format_to(result.data(), FMT_COMPILE("{}"), value); + return result; + } + + constexpr auto answer = compile_time_dtoa(0.42); + ``` + + works with the default settings. + +- Improved the implementation of + [Dragonbox](https://github.com/jk-jeon/dragonbox), the algorithm + used for the default floating-point formatting + (https://github.com/fmtlib/fmt/pull/2713, + https://github.com/fmtlib/fmt/pull/2750). Thanks @jk-jeon. + +- Made `fmt::to_string` work with `__float128`. This uses the internal + FP formatter and works even on system without `__float128` support + in `[s]printf`. + +- Disabled automatic `std::ostream` insertion operator (`operator<<`) + discovery when `fmt/ostream.h` is included to prevent ODR + violations. You can get the old behavior by defining + `FMT_DEPRECATED_OSTREAM` but this will be removed in the next major + release. Use `fmt::streamed` or `fmt::ostream_formatter` to enable + formatting via `std::ostream` instead. + +- Added `fmt::ostream_formatter` that can be used to write `formatter` + specializations that perform formatting via `std::ostream`. For + example ([godbolt](https://godbolt.org/z/5sEc5qMsf)): + + ```c++ + #include + + struct date { + int year, month, day; + + friend std::ostream& operator<<(std::ostream& os, const date& d) { + return os << d.year << '-' << d.month << '-' << d.day; + } + }; + + template <> struct fmt::formatter : ostream_formatter {}; + + std::string s = fmt::format("The date is {}", date{2012, 12, 9}); + // s == "The date is 2012-12-9" + ``` + +- Added the `fmt::streamed` function that takes an object and formats + it via `std::ostream`. For example + ([godbolt](https://godbolt.org/z/5G3346G1f)): + + ```c++ + #include + #include + + int main() { + fmt::print("Current thread id: {}\n", + fmt::streamed(std::this_thread::get_id())); + } + ``` + + Note that `fmt/std.h` provides a `formatter` specialization for + `std::thread::id` so you don\'t need to format it via + `std::ostream`. + +- Deprecated implicit conversions of unscoped enums to integers for + consistency with scoped enums. + +- Added an argument-dependent lookup based `format_as` extension API + to simplify formatting of enums. + +- Added experimental `std::variant` formatting support + (https://github.com/fmtlib/fmt/pull/2941). For example + ([godbolt](https://godbolt.org/z/KG9z6cq68)): + + ```c++ + #include + #include + + int main() { + auto v = std::variant(42); + fmt::print("{}\n", v); + } + ``` + + prints: + + variant(42) + + Thanks @jehelset. + +- Added experimental `std::filesystem::path` formatting support + (https://github.com/fmtlib/fmt/issues/2865, + https://github.com/fmtlib/fmt/pull/2902, + https://github.com/fmtlib/fmt/issues/2917, + https://github.com/fmtlib/fmt/pull/2918). For example + ([godbolt](https://godbolt.org/z/o44dMexEb)): + + ```c++ + #include + #include + + int main() { + fmt::print("There is no place like {}.", std::filesystem::path("/home")); + } + ``` + + prints: + + There is no place like "/home". + + Thanks @phprus. + +- Added a `std::thread::id` formatter to `fmt/std.h`. For example + ([godbolt](https://godbolt.org/z/j1azbYf3E)): + + ```c++ + #include + #include + + int main() { + fmt::print("Current thread id: {}\n", std::this_thread::get_id()); + } + ``` + +- Added `fmt::styled` that applies a text style to an individual + argument (https://github.com/fmtlib/fmt/pull/2793). For + example ([godbolt](https://godbolt.org/z/vWGW7v5M6)): + + ```c++ + #include + #include + + int main() { + auto now = std::chrono::system_clock::now(); + fmt::print( + "[{}] {}: {}\n", + fmt::styled(now, fmt::emphasis::bold), + fmt::styled("error", fg(fmt::color::red)), + "something went wrong"); + } + ``` + + prints + + ![](https://user-images.githubusercontent.com/576385/175071215-12809244-dab0-4005-96d8-7cd911c964d5.png) + + Thanks @rbrugo. + +- Made `fmt::print` overload for text styles correctly handle UTF-8 + (https://github.com/fmtlib/fmt/issues/2681, + https://github.com/fmtlib/fmt/pull/2701). Thanks @AlexGuteniev. + +- Fixed Unicode handling when writing to an ostream. + +- Added support for nested specifiers to range formatting + (https://github.com/fmtlib/fmt/pull/2673). For example + ([godbolt](https://godbolt.org/z/xd3Gj38cf)): + + ```c++ + #include + #include + + int main() { + fmt::print("{::#x}\n", std::vector{10, 20, 30}); + } + ``` + + prints `[0xa, 0x14, 0x1e]`. + + Thanks @BRevzin. + +- Implemented escaping of wide strings in ranges + (https://github.com/fmtlib/fmt/pull/2904). Thanks @phprus. + +- Added support for ranges with `begin` / `end` found via the + argument-dependent lookup + (https://github.com/fmtlib/fmt/pull/2807). Thanks @rbrugo. + +- Fixed formatting of certain kinds of ranges of ranges + (https://github.com/fmtlib/fmt/pull/2787). Thanks @BRevzin. + +- Fixed handling of maps with element types other than `std::pair` + (https://github.com/fmtlib/fmt/pull/2944). Thanks @BrukerJWD. + +- Made tuple formatter enabled only if elements are formattable + (https://github.com/fmtlib/fmt/issues/2939, + https://github.com/fmtlib/fmt/pull/2940). Thanks @jehelset. + +- Made `fmt::join` compatible with format string compilation + (https://github.com/fmtlib/fmt/issues/2719, + https://github.com/fmtlib/fmt/pull/2720). Thanks @phprus. + +- Made compile-time checks work with named arguments of custom types + and `std::ostream` `print` overloads + (https://github.com/fmtlib/fmt/issues/2816, + https://github.com/fmtlib/fmt/issues/2817, + https://github.com/fmtlib/fmt/pull/2819). Thanks @timsong-cpp. + +- Removed `make_args_checked` because it is no longer needed for + compile-time checks + (https://github.com/fmtlib/fmt/pull/2760). Thanks @phprus. + +- Removed the following deprecated APIs: `_format`, `arg_join`, the + `format_to` overload that takes a memory buffer, `[v]fprintf` that + takes an `ostream`. + +- Removed the deprecated implicit conversion of `[const] signed char*` + and `[const] unsigned char*` to C strings. + +- Removed the deprecated `fmt/locale.h`. + +- Replaced the deprecated `fileno()` with `descriptor()` in + `buffered_file`. + +- Moved `to_string_view` to the `detail` namespace since it\'s an + implementation detail. + +- Made access mode of a created file consistent with `fopen` by + setting `S_IWGRP` and `S_IWOTH` + (https://github.com/fmtlib/fmt/pull/2733). Thanks @arogge. + +- Removed a redundant buffer resize when formatting to `std::ostream` + (https://github.com/fmtlib/fmt/issues/2842, + https://github.com/fmtlib/fmt/pull/2843). Thanks @jcelerier. + +- Made precision computation for strings consistent with width + (https://github.com/fmtlib/fmt/issues/2888). + +- Fixed handling of locale separators in floating point formatting + (https://github.com/fmtlib/fmt/issues/2830). + +- Made sign specifiers work with `__int128_t` + (https://github.com/fmtlib/fmt/issues/2773). + +- Improved support for systems such as CHERI with extra data stored in + pointers (https://github.com/fmtlib/fmt/pull/2932). + Thanks @davidchisnall. + +- Improved documentation + (https://github.com/fmtlib/fmt/pull/2706, + https://github.com/fmtlib/fmt/pull/2712, + https://github.com/fmtlib/fmt/pull/2789, + https://github.com/fmtlib/fmt/pull/2803, + https://github.com/fmtlib/fmt/pull/2805, + https://github.com/fmtlib/fmt/pull/2815, + https://github.com/fmtlib/fmt/pull/2924). + Thanks @BRevzin, @Pokechu22, @setoye, @rtobar, @rbrugo, @anoonD and + @leha-bot. + +- Improved build configuration + (https://github.com/fmtlib/fmt/pull/2766, + https://github.com/fmtlib/fmt/pull/2772, + https://github.com/fmtlib/fmt/pull/2836, + https://github.com/fmtlib/fmt/pull/2852, + https://github.com/fmtlib/fmt/pull/2907, + https://github.com/fmtlib/fmt/pull/2913, + https://github.com/fmtlib/fmt/pull/2914). + Thanks @kambala-decapitator, @mattiasljungstrom, @kieselnb, @nathannaveen + and @Vertexwahn. + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/issues/2408, + https://github.com/fmtlib/fmt/issues/2507, + https://github.com/fmtlib/fmt/issues/2697, + https://github.com/fmtlib/fmt/issues/2715, + https://github.com/fmtlib/fmt/issues/2717, + https://github.com/fmtlib/fmt/pull/2722, + https://github.com/fmtlib/fmt/pull/2724, + https://github.com/fmtlib/fmt/pull/2725, + https://github.com/fmtlib/fmt/issues/2726, + https://github.com/fmtlib/fmt/pull/2728, + https://github.com/fmtlib/fmt/pull/2732, + https://github.com/fmtlib/fmt/issues/2738, + https://github.com/fmtlib/fmt/pull/2742, + https://github.com/fmtlib/fmt/issues/2744, + https://github.com/fmtlib/fmt/issues/2745, + https://github.com/fmtlib/fmt/issues/2746, + https://github.com/fmtlib/fmt/issues/2754, + https://github.com/fmtlib/fmt/pull/2755, + https://github.com/fmtlib/fmt/issues/2757, + https://github.com/fmtlib/fmt/pull/2758, + https://github.com/fmtlib/fmt/issues/2761, + https://github.com/fmtlib/fmt/pull/2762, + https://github.com/fmtlib/fmt/issues/2763, + https://github.com/fmtlib/fmt/pull/2765, + https://github.com/fmtlib/fmt/issues/2769, + https://github.com/fmtlib/fmt/pull/2770, + https://github.com/fmtlib/fmt/issues/2771, + https://github.com/fmtlib/fmt/issues/2777, + https://github.com/fmtlib/fmt/pull/2779, + https://github.com/fmtlib/fmt/pull/2782, + https://github.com/fmtlib/fmt/pull/2783, + https://github.com/fmtlib/fmt/issues/2794, + https://github.com/fmtlib/fmt/issues/2796, + https://github.com/fmtlib/fmt/pull/2797, + https://github.com/fmtlib/fmt/pull/2801, + https://github.com/fmtlib/fmt/pull/2802, + https://github.com/fmtlib/fmt/issues/2808, + https://github.com/fmtlib/fmt/issues/2818, + https://github.com/fmtlib/fmt/pull/2819, + https://github.com/fmtlib/fmt/issues/2829, + https://github.com/fmtlib/fmt/issues/2835, + https://github.com/fmtlib/fmt/issues/2848, + https://github.com/fmtlib/fmt/issues/2860, + https://github.com/fmtlib/fmt/pull/2861, + https://github.com/fmtlib/fmt/pull/2882, + https://github.com/fmtlib/fmt/issues/2886, + https://github.com/fmtlib/fmt/issues/2891, + https://github.com/fmtlib/fmt/pull/2892, + https://github.com/fmtlib/fmt/issues/2895, + https://github.com/fmtlib/fmt/issues/2896, + https://github.com/fmtlib/fmt/pull/2903, + https://github.com/fmtlib/fmt/issues/2906, + https://github.com/fmtlib/fmt/issues/2908, + https://github.com/fmtlib/fmt/pull/2909, + https://github.com/fmtlib/fmt/issues/2920, + https://github.com/fmtlib/fmt/pull/2922, + https://github.com/fmtlib/fmt/pull/2927, + https://github.com/fmtlib/fmt/pull/2929, + https://github.com/fmtlib/fmt/issues/2936, + https://github.com/fmtlib/fmt/pull/2937, + https://github.com/fmtlib/fmt/pull/2938, + https://github.com/fmtlib/fmt/pull/2951, + https://github.com/fmtlib/fmt/issues/2954, + https://github.com/fmtlib/fmt/pull/2957, + https://github.com/fmtlib/fmt/issues/2958, + https://github.com/fmtlib/fmt/pull/2960). + Thanks @matrackif @Tobi823, @ivan-volnov, @VasiliPupkin256, + @federico-busato, @barcharcraz, @jk-jeon, @HazardyKnusperkeks, @dalboris, + @seanm, @gsjaardema, @timsong-cpp, @seanm, @frithrah, @chronoxor, @Agga, + @madmaxoft, @JurajX, @phprus and @Dani-Hub. + +# 8.1.1 - 2022-01-06 + +- Restored ABI compatibility with version 8.0.x + (https://github.com/fmtlib/fmt/issues/2695, + https://github.com/fmtlib/fmt/pull/2696). Thanks @saraedum. +- Fixed chrono formatting on big endian systems + (https://github.com/fmtlib/fmt/issues/2698, + https://github.com/fmtlib/fmt/pull/2699). + Thanks @phprus and @xvitaly. +- Fixed a linkage error with mingw + (https://github.com/fmtlib/fmt/issues/2691, + https://github.com/fmtlib/fmt/pull/2692). Thanks @rbberger. + +# 8.1.0 - 2022-01-02 + +- Optimized chrono formatting + (https://github.com/fmtlib/fmt/pull/2500, + https://github.com/fmtlib/fmt/pull/2537, + https://github.com/fmtlib/fmt/issues/2541, + https://github.com/fmtlib/fmt/pull/2544, + https://github.com/fmtlib/fmt/pull/2550, + https://github.com/fmtlib/fmt/pull/2551, + https://github.com/fmtlib/fmt/pull/2576, + https://github.com/fmtlib/fmt/issues/2577, + https://github.com/fmtlib/fmt/pull/2586, + https://github.com/fmtlib/fmt/pull/2591, + https://github.com/fmtlib/fmt/pull/2594, + https://github.com/fmtlib/fmt/pull/2602, + https://github.com/fmtlib/fmt/pull/2617, + https://github.com/fmtlib/fmt/issues/2628, + https://github.com/fmtlib/fmt/pull/2633, + https://github.com/fmtlib/fmt/issues/2670, + https://github.com/fmtlib/fmt/pull/2671). + + Processing of some specifiers such as `%z` and `%Y` is now up to + 10-20 times faster, for example on GCC 11 with libstdc++: + + ---------------------------------------------------------------------------- + Benchmark Before After + ---------------------------------------------------------------------------- + FMTFormatter_z 261 ns 26.3 ns + FMTFormatterCompile_z 246 ns 11.6 ns + FMTFormatter_Y 263 ns 26.1 ns + FMTFormatterCompile_Y 244 ns 10.5 ns + ---------------------------------------------------------------------------- + + Thanks @phprus and @toughengineer. + +- Implemented subsecond formatting for chrono durations + (https://github.com/fmtlib/fmt/pull/2623). For example + ([godbolt](https://godbolt.org/z/es7vWTETe)): + + ```c++ + #include + + int main() { + fmt::print("{:%S}", std::chrono::milliseconds(1234)); + } + ``` + + prints \"01.234\". + + Thanks @matrackif. + +- Fixed handling of precision 0 when formatting chrono durations + (https://github.com/fmtlib/fmt/issues/2587, + https://github.com/fmtlib/fmt/pull/2588). Thanks @lukester1975. + +- Fixed an overflow on invalid inputs in the `tm` formatter + (https://github.com/fmtlib/fmt/pull/2564). Thanks @phprus. + +- Added `fmt::group_digits` that formats integers with a non-localized + digit separator (comma) for groups of three digits. For example + ([godbolt](https://godbolt.org/z/TxGxG9Poq)): + + ```c++ + #include + + int main() { + fmt::print("{} dollars", fmt::group_digits(1000000)); + } + ``` + + prints \"1,000,000 dollars\". + +- Added support for faint, conceal, reverse and blink text styles + (https://github.com/fmtlib/fmt/pull/2394): + + + + Thanks @benit8 and @data-man. + +- Added experimental support for compile-time floating point + formatting (https://github.com/fmtlib/fmt/pull/2426, + https://github.com/fmtlib/fmt/pull/2470). It is currently + limited to the header-only mode. Thanks @alexezeder. + +- Added UDL-based named argument support to compile-time format string + checks (https://github.com/fmtlib/fmt/issues/2640, + https://github.com/fmtlib/fmt/pull/2649). For example + ([godbolt](https://godbolt.org/z/ohGbbvonv)): + + ```c++ + #include + + int main() { + using namespace fmt::literals; + fmt::print("{answer:s}", "answer"_a=42); + } + ``` + + gives a compile-time error on compilers with C++20 `consteval` and + non-type template parameter support (gcc 10+) because `s` is not a + valid format specifier for an integer. + + Thanks @alexezeder. + +- Implemented escaping of string range elements. For example + ([godbolt](https://godbolt.org/z/rKvM1vKf3)): + + ```c++ + #include + #include + + int main() { + fmt::print("{}", std::vector{"\naan"}); + } + ``` + + is now printed as: + + ["\naan"] + + instead of: + + [" + aan"] + +- Added an experimental `?` specifier for escaping strings. + (https://github.com/fmtlib/fmt/pull/2674). Thanks @BRevzin. + +- Switched to JSON-like representation of maps and sets for + consistency with Python\'s `str.format`. For example + ([godbolt](https://godbolt.org/z/seKjoY9W5)): + + ```c++ + #include + #include + + int main() { + fmt::print("{}", std::map{{"answer", 42}}); + } + ``` + + is now printed as: + + {"answer": 42} + +- Extended `fmt::join` to support C++20-only ranges + (https://github.com/fmtlib/fmt/pull/2549). Thanks @BRevzin. + +- Optimized handling of non-const-iterable ranges and implemented + initial support for non-const-formattable types. + +- Disabled implicit conversions of scoped enums to integers that was + accidentally introduced in earlier versions + (https://github.com/fmtlib/fmt/pull/1841). + +- Deprecated implicit conversion of `[const] signed char*` and + `[const] unsigned char*` to C strings. + +- Deprecated `_format`, a legacy UDL-based format API + (https://github.com/fmtlib/fmt/pull/2646). Thanks @alexezeder. + +- Marked `format`, `formatted_size` and `to_string` as `[[nodiscard]]` + (https://github.com/fmtlib/fmt/pull/2612). @0x8000-0000. + +- Added missing diagnostic when trying to format function and member + pointers as well as objects convertible to pointers which is + explicitly disallowed + (https://github.com/fmtlib/fmt/issues/2598, + https://github.com/fmtlib/fmt/pull/2609, + https://github.com/fmtlib/fmt/pull/2610). Thanks @AlexGuteniev. + +- Optimized writing to a contiguous buffer with `format_to_n` + (https://github.com/fmtlib/fmt/pull/2489). Thanks @Roman-Koshelev. + +- Optimized writing to non-`char` buffers + (https://github.com/fmtlib/fmt/pull/2477). Thanks @Roman-Koshelev. + +- Decimal point is now localized when using the `L` specifier. + +- Improved floating point formatter implementation + (https://github.com/fmtlib/fmt/pull/2498, + https://github.com/fmtlib/fmt/pull/2499). Thanks @Roman-Koshelev. + +- Fixed handling of very large precision in fixed format + (https://github.com/fmtlib/fmt/pull/2616). + +- Made a table of cached powers used in FP formatting static + (https://github.com/fmtlib/fmt/pull/2509). Thanks @jk-jeon. + +- Resolved a lookup ambiguity with C++20 format-related functions due + to ADL (https://github.com/fmtlib/fmt/issues/2639, + https://github.com/fmtlib/fmt/pull/2641). Thanks @mkurdej. + +- Removed unnecessary inline namespace qualification + (https://github.com/fmtlib/fmt/issues/2642, + https://github.com/fmtlib/fmt/pull/2643). Thanks @mkurdej. + +- Implemented argument forwarding in `format_to_n` + (https://github.com/fmtlib/fmt/issues/2462, + https://github.com/fmtlib/fmt/pull/2463). Thanks @owent. + +- Fixed handling of implicit conversions in `fmt::to_string` and + format string compilation + (https://github.com/fmtlib/fmt/issues/2565). + +- Changed the default access mode of files created by + `fmt::output_file` to `-rw-r--r--` for consistency with `fopen` + (https://github.com/fmtlib/fmt/issues/2530). + +- Make `fmt::ostream::flush` public + (https://github.com/fmtlib/fmt/issues/2435). + +- Improved C++14/17 attribute detection + (https://github.com/fmtlib/fmt/pull/2615). Thanks @AlexGuteniev. + +- Improved `consteval` detection for MSVC + (https://github.com/fmtlib/fmt/pull/2559). Thanks @DanielaE. + +- Improved documentation + (https://github.com/fmtlib/fmt/issues/2406, + https://github.com/fmtlib/fmt/pull/2446, + https://github.com/fmtlib/fmt/issues/2493, + https://github.com/fmtlib/fmt/issues/2513, + https://github.com/fmtlib/fmt/pull/2515, + https://github.com/fmtlib/fmt/issues/2522, + https://github.com/fmtlib/fmt/pull/2562, + https://github.com/fmtlib/fmt/pull/2575, + https://github.com/fmtlib/fmt/pull/2606, + https://github.com/fmtlib/fmt/pull/2620, + https://github.com/fmtlib/fmt/issues/2676). + Thanks @sobolevn, @UnePierre, @zhsj, @phprus, @ericcurtin and @Lounarok. + +- Improved fuzzers and added a fuzzer for chrono timepoint formatting + (https://github.com/fmtlib/fmt/pull/2461, + https://github.com/fmtlib/fmt/pull/2469). @pauldreik, + +- Added the `FMT_SYSTEM_HEADERS` CMake option setting which marks + {fmt}\'s headers as system. It can be used to suppress warnings + (https://github.com/fmtlib/fmt/issues/2644, + https://github.com/fmtlib/fmt/pull/2651). Thanks @alexezeder. + +- Added the Bazel build system support + (https://github.com/fmtlib/fmt/pull/2505, + https://github.com/fmtlib/fmt/pull/2516). Thanks @Vertexwahn. + +- Improved build configuration and tests + (https://github.com/fmtlib/fmt/issues/2437, + https://github.com/fmtlib/fmt/pull/2558, + https://github.com/fmtlib/fmt/pull/2648, + https://github.com/fmtlib/fmt/pull/2650, + https://github.com/fmtlib/fmt/pull/2663, + https://github.com/fmtlib/fmt/pull/2677). + Thanks @DanielaE, @alexezeder and @phprus. + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/pull/2353, + https://github.com/fmtlib/fmt/pull/2356, + https://github.com/fmtlib/fmt/pull/2399, + https://github.com/fmtlib/fmt/issues/2408, + https://github.com/fmtlib/fmt/pull/2414, + https://github.com/fmtlib/fmt/pull/2427, + https://github.com/fmtlib/fmt/pull/2432, + https://github.com/fmtlib/fmt/pull/2442, + https://github.com/fmtlib/fmt/pull/2434, + https://github.com/fmtlib/fmt/issues/2439, + https://github.com/fmtlib/fmt/pull/2447, + https://github.com/fmtlib/fmt/pull/2450, + https://github.com/fmtlib/fmt/issues/2455, + https://github.com/fmtlib/fmt/issues/2465, + https://github.com/fmtlib/fmt/issues/2472, + https://github.com/fmtlib/fmt/issues/2474, + https://github.com/fmtlib/fmt/pull/2476, + https://github.com/fmtlib/fmt/issues/2478, + https://github.com/fmtlib/fmt/issues/2479, + https://github.com/fmtlib/fmt/issues/2481, + https://github.com/fmtlib/fmt/pull/2482, + https://github.com/fmtlib/fmt/pull/2483, + https://github.com/fmtlib/fmt/issues/2490, + https://github.com/fmtlib/fmt/pull/2491, + https://github.com/fmtlib/fmt/pull/2510, + https://github.com/fmtlib/fmt/pull/2518, + https://github.com/fmtlib/fmt/issues/2528, + https://github.com/fmtlib/fmt/pull/2529, + https://github.com/fmtlib/fmt/pull/2539, + https://github.com/fmtlib/fmt/issues/2540, + https://github.com/fmtlib/fmt/pull/2545, + https://github.com/fmtlib/fmt/pull/2555, + https://github.com/fmtlib/fmt/issues/2557, + https://github.com/fmtlib/fmt/issues/2570, + https://github.com/fmtlib/fmt/pull/2573, + https://github.com/fmtlib/fmt/pull/2582, + https://github.com/fmtlib/fmt/issues/2605, + https://github.com/fmtlib/fmt/pull/2611, + https://github.com/fmtlib/fmt/pull/2647, + https://github.com/fmtlib/fmt/issues/2627, + https://github.com/fmtlib/fmt/pull/2630, + https://github.com/fmtlib/fmt/issues/2635, + https://github.com/fmtlib/fmt/issues/2638, + https://github.com/fmtlib/fmt/issues/2653, + https://github.com/fmtlib/fmt/issues/2654, + https://github.com/fmtlib/fmt/issues/2661, + https://github.com/fmtlib/fmt/pull/2664, + https://github.com/fmtlib/fmt/pull/2684). + Thanks @DanielaE, @mwinterb, @cdacamar, @TrebledJ, @bodomartin, @cquammen, + @white238, @mmarkeloff, @palacaze, @jcelerier, @mborn-adi, @BrukerJWD, + @spyridon97, @phprus, @oliverlee, @joshessman-llnl, @akohlmey, @timkalu, + @olupton, @Acretock, @alexezeder, @andrewcorrigan, @lucpelletier and + @HazardyKnusperkeks. + +# 8.0.1 - 2021-07-02 + +- Fixed the version number in the inline namespace + (https://github.com/fmtlib/fmt/issues/2374). +- Added a missing presentation type check for `std::string` + (https://github.com/fmtlib/fmt/issues/2402). +- Fixed a linkage error when mixing code built with clang and gcc + (https://github.com/fmtlib/fmt/issues/2377). +- Fixed documentation issues + (https://github.com/fmtlib/fmt/pull/2396, + https://github.com/fmtlib/fmt/issues/2403, + https://github.com/fmtlib/fmt/issues/2406). Thanks @mkurdej. +- Removed dead code in FP formatter ( + https://github.com/fmtlib/fmt/pull/2398). Thanks @javierhonduco. +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/issues/2351, + https://github.com/fmtlib/fmt/issues/2359, + https://github.com/fmtlib/fmt/pull/2365, + https://github.com/fmtlib/fmt/issues/2368, + https://github.com/fmtlib/fmt/pull/2370, + https://github.com/fmtlib/fmt/pull/2376, + https://github.com/fmtlib/fmt/pull/2381, + https://github.com/fmtlib/fmt/pull/2382, + https://github.com/fmtlib/fmt/issues/2386, + https://github.com/fmtlib/fmt/pull/2389, + https://github.com/fmtlib/fmt/pull/2395, + https://github.com/fmtlib/fmt/pull/2397, + https://github.com/fmtlib/fmt/issues/2400, + https://github.com/fmtlib/fmt/issues/2401, + https://github.com/fmtlib/fmt/pull/2407). + Thanks @zx2c4, @AidanSun05, @mattiasljungstrom, @joemmett, @erengy, + @patlkli, @gsjaardema and @phprus. + +# 8.0.0 - 2021-06-21 + +- Enabled compile-time format string checks by default. For example + ([godbolt](https://godbolt.org/z/sMxcohGjz)): + + ```c++ + #include + + int main() { + fmt::print("{:d}", "I am not a number"); + } + ``` + + gives a compile-time error on compilers with C++20 `consteval` + support (gcc 10+, clang 11+) because `d` is not a valid format + specifier for a string. + + To pass a runtime string wrap it in `fmt::runtime`: + + ```c++ + fmt::print(fmt::runtime("{:d}"), "I am not a number"); + ``` + +- Added compile-time formatting + (https://github.com/fmtlib/fmt/pull/2019, + https://github.com/fmtlib/fmt/pull/2044, + https://github.com/fmtlib/fmt/pull/2056, + https://github.com/fmtlib/fmt/pull/2072, + https://github.com/fmtlib/fmt/pull/2075, + https://github.com/fmtlib/fmt/issues/2078, + https://github.com/fmtlib/fmt/pull/2129, + https://github.com/fmtlib/fmt/pull/2326). For example + ([godbolt](https://godbolt.org/z/Mxx9d89jM)): + + ```c++ + #include + + consteval auto compile_time_itoa(int value) -> std::array { + auto result = std::array(); + fmt::format_to(result.data(), FMT_COMPILE("{}"), value); + return result; + } + + constexpr auto answer = compile_time_itoa(42); + ``` + + Most of the formatting functionality is available at compile time + with a notable exception of floating-point numbers and pointers. + Thanks @alexezeder. + +- Optimized handling of format specifiers during format string + compilation. For example, hexadecimal formatting (`"{:x}"`) is now + 3-7x faster than before when using `format_to` with format string + compilation and a stack-allocated buffer + (https://github.com/fmtlib/fmt/issues/1944). + + Before (7.1.3): + + ---------------------------------------------------------------------------- + Benchmark Time CPU Iterations + ---------------------------------------------------------------------------- + FMTCompileOld/0 15.5 ns 15.5 ns 43302898 + FMTCompileOld/42 16.6 ns 16.6 ns 43278267 + FMTCompileOld/273123 18.7 ns 18.6 ns 37035861 + FMTCompileOld/9223372036854775807 19.4 ns 19.4 ns 35243000 + ---------------------------------------------------------------------------- + + After (8.x): + + ---------------------------------------------------------------------------- + Benchmark Time CPU Iterations + ---------------------------------------------------------------------------- + FMTCompileNew/0 1.99 ns 1.99 ns 360523686 + FMTCompileNew/42 2.33 ns 2.33 ns 279865664 + FMTCompileNew/273123 3.72 ns 3.71 ns 190230315 + FMTCompileNew/9223372036854775807 5.28 ns 5.26 ns 130711631 + ---------------------------------------------------------------------------- + + It is even faster than `std::to_chars` from libc++ compiled with + clang on macOS: + + ---------------------------------------------------------------------------- + Benchmark Time CPU Iterations + ---------------------------------------------------------------------------- + ToChars/0 4.42 ns 4.41 ns 160196630 + ToChars/42 5.00 ns 4.98 ns 140735201 + ToChars/273123 7.26 ns 7.24 ns 95784130 + ToChars/9223372036854775807 8.77 ns 8.75 ns 75872534 + ---------------------------------------------------------------------------- + + In other cases, especially involving `std::string` construction, the + speed up is usually lower because handling format specifiers takes a + smaller fraction of the total time. + +- Added the `_cf` user-defined literal to represent a compiled format + string. It can be used instead of the `FMT_COMPILE` macro + (https://github.com/fmtlib/fmt/pull/2043, + https://github.com/fmtlib/fmt/pull/2242): + + ```c++ + #include + + using namespace fmt::literals; + auto s = fmt::format(FMT_COMPILE("{}"), 42); // 🙁 not modern + auto s = fmt::format("{}"_cf, 42); // 🙂 modern as hell + ``` + + It requires compiler support for class types in non-type template + parameters (a C++20 feature) which is available in GCC 9.3+. + Thanks @alexezeder. + +- Format string compilation now requires `format` functions of + `formatter` specializations for user-defined types to be `const`: + + ```c++ + template <> struct fmt::formatter: formatter { + template + auto format(my_type obj, FormatContext& ctx) const { // Note const here. + // ... + } + }; + ``` + +- Added UDL-based named argument support to format string compilation + (https://github.com/fmtlib/fmt/pull/2243, + https://github.com/fmtlib/fmt/pull/2281). For example: + + ```c++ + #include + + using namespace fmt::literals; + auto s = fmt::format(FMT_COMPILE("{answer}"), "answer"_a = 42); + ``` + + Here the argument named \"answer\" is resolved at compile time with + no runtime overhead. Thanks @alexezeder. + +- Added format string compilation support to `fmt::print` + (https://github.com/fmtlib/fmt/issues/2280, + https://github.com/fmtlib/fmt/pull/2304). Thanks @alexezeder. + +- Added initial support for compiling {fmt} as a C++20 module + (https://github.com/fmtlib/fmt/pull/2235, + https://github.com/fmtlib/fmt/pull/2240, + https://github.com/fmtlib/fmt/pull/2260, + https://github.com/fmtlib/fmt/pull/2282, + https://github.com/fmtlib/fmt/pull/2283, + https://github.com/fmtlib/fmt/pull/2288, + https://github.com/fmtlib/fmt/pull/2298, + https://github.com/fmtlib/fmt/pull/2306, + https://github.com/fmtlib/fmt/pull/2307, + https://github.com/fmtlib/fmt/pull/2309, + https://github.com/fmtlib/fmt/pull/2318, + https://github.com/fmtlib/fmt/pull/2324, + https://github.com/fmtlib/fmt/pull/2332, + https://github.com/fmtlib/fmt/pull/2340). Thanks @DanielaE. + +- Made symbols private by default reducing shared library size + (https://github.com/fmtlib/fmt/pull/2301). For example + there was a \~15% reported reduction on one platform. Thanks @sergiud. + +- Optimized includes making the result of preprocessing `fmt/format.h` + \~20% smaller with libstdc++/C++20 and slightly improving build + times (https://github.com/fmtlib/fmt/issues/1998). + +- Added support of ranges with non-const `begin` / `end` + (https://github.com/fmtlib/fmt/pull/1953). Thanks @kitegi. + +- Added support of `std::byte` and other formattable types to + `fmt::join` (https://github.com/fmtlib/fmt/issues/1981, + https://github.com/fmtlib/fmt/issues/2040, + https://github.com/fmtlib/fmt/pull/2050, + https://github.com/fmtlib/fmt/issues/2262). For example: + + ```c++ + #include + #include + #include + + int main() { + auto bytes = std::vector{std::byte(4), std::byte(2)}; + fmt::print("{}", fmt::join(bytes, "")); + } + ``` + + prints \"42\". + + Thanks @kamibo. + +- Implemented the default format for `std::chrono::system_clock` + (https://github.com/fmtlib/fmt/issues/2319, + https://github.com/fmtlib/fmt/pull/2345). For example: + + ```c++ + #include + + int main() { + fmt::print("{}", std::chrono::system_clock::now()); + } + ``` + + prints \"2021-06-18 15:22:00\" (the output depends on the current + date and time). Thanks @sunmy2019. + +- Made more chrono specifiers locale independent by default. Use the + `'L'` specifier to get localized formatting. For example: + + ```c++ + #include + + int main() { + std::locale::global(std::locale("ru_RU.UTF-8")); + auto monday = std::chrono::weekday(1); + fmt::print("{}\n", monday); // prints "Mon" + fmt::print("{:L}\n", monday); // prints "пн" + } + ``` + +- Improved locale handling in chrono formatting + (https://github.com/fmtlib/fmt/issues/2337, + https://github.com/fmtlib/fmt/pull/2349, + https://github.com/fmtlib/fmt/pull/2350). Thanks @phprus. + +- Deprecated `fmt/locale.h` moving the formatting functions that take + a locale to `fmt/format.h` (`char`) and `fmt/xchar` (other + overloads). This doesn\'t introduce a dependency on `` so + there is virtually no compile time effect. + +- Deprecated an undocumented `format_to` overload that takes + `basic_memory_buffer`. + +- Made parameter order in `vformat_to` consistent with `format_to` + (https://github.com/fmtlib/fmt/issues/2327). + +- Added support for time points with arbitrary durations + (https://github.com/fmtlib/fmt/issues/2208). For example: + + ```c++ + #include + + int main() { + using tp = std::chrono::time_point< + std::chrono::system_clock, std::chrono::seconds>; + fmt::print("{:%S}", tp(std::chrono::seconds(42))); + } + ``` + + prints \"42\". + +- Formatting floating-point numbers no longer produces trailing zeros + by default for consistency with `std::format`. For example: + + ```c++ + #include + + int main() { + fmt::print("{0:.3}", 1.1); + } + ``` + + prints \"1.1\". Use the `'#'` specifier to keep trailing zeros. + +- Dropped a limit on the number of elements in a range and replaced + `{}` with `[]` as range delimiters for consistency with Python\'s + `str.format`. + +- The `'L'` specifier for locale-specific numeric formatting can now + be combined with presentation specifiers as in `std::format`. For + example: + + ```c++ + #include + #include + + int main() { + std::locale::global(std::locale("fr_FR.UTF-8")); + fmt::print("{0:.2Lf}", 0.42); + } + ``` + + prints \"0,42\". The deprecated `'n'` specifier has been removed. + +- Made the `0` specifier ignored for infinity and NaN + (https://github.com/fmtlib/fmt/issues/2305, + https://github.com/fmtlib/fmt/pull/2310). Thanks @Liedtke. + +- Made the hexfloat formatting use the right alignment by default + (https://github.com/fmtlib/fmt/issues/2308, + https://github.com/fmtlib/fmt/pull/2317). Thanks @Liedtke. + +- Removed the deprecated numeric alignment (`'='`). Use the `'0'` + specifier instead. + +- Removed the deprecated `fmt/posix.h` header that has been replaced + with `fmt/os.h`. + +- Removed the deprecated `format_to_n_context`, `format_to_n_args` and + `make_format_to_n_args`. They have been replaced with + `format_context`, `` format_args` and ``make_format_args\`\` + respectively. + +- Moved `wchar_t`-specific functions and types to `fmt/xchar.h`. You + can define `FMT_DEPRECATED_INCLUDE_XCHAR` to automatically include + `fmt/xchar.h` from `fmt/format.h` but this will be disabled in the + next major release. + +- Fixed handling of the `'+'` specifier in localized formatting + (https://github.com/fmtlib/fmt/issues/2133). + +- Added support for the `'s'` format specifier that gives textual + representation of `bool` + (https://github.com/fmtlib/fmt/issues/2094, + https://github.com/fmtlib/fmt/pull/2109). For example: + + ```c++ + #include + + int main() { + fmt::print("{:s}", true); + } + ``` + + prints \"true\". Thanks @powercoderlol. + +- Made `fmt::ptr` work with function pointers + (https://github.com/fmtlib/fmt/pull/2131). For example: + + ```c++ + #include + + int main() { + fmt::print("My main: {}\n", fmt::ptr(main)); + } + ``` + + Thanks @mikecrowe. + +- The undocumented support for specializing `formatter` for pointer + types has been removed. + +- Fixed `fmt::formatted_size` with format string compilation + (https://github.com/fmtlib/fmt/pull/2141, + https://github.com/fmtlib/fmt/pull/2161). Thanks @alexezeder. + +- Fixed handling of empty format strings during format string + compilation (https://github.com/fmtlib/fmt/issues/2042): + + ```c++ + auto s = fmt::format(FMT_COMPILE("")); + ``` + + Thanks @alexezeder. + +- Fixed handling of enums in `fmt::to_string` + (https://github.com/fmtlib/fmt/issues/2036). + +- Improved width computation + (https://github.com/fmtlib/fmt/issues/2033, + https://github.com/fmtlib/fmt/issues/2091). For example: + + ```c++ + #include + + int main() { + fmt::print("{:-<10}{}\n", "你好", "世界"); + fmt::print("{:-<10}{}\n", "hello", "world"); + } + ``` + + prints + + ![](https://user-images.githubusercontent.com/576385/119840373-cea3ca80-beb9-11eb-91e0-54266c48e181.png) + + on a modern terminal. + +- The experimental fast output stream (`fmt::ostream`) is now + truncated by default for consistency with `fopen` + (https://github.com/fmtlib/fmt/issues/2018). For example: + + ```c++ + #include + + int main() { + fmt::ostream out1 = fmt::output_file("guide"); + out1.print("Zaphod"); + out1.close(); + fmt::ostream out2 = fmt::output_file("guide"); + out2.print("Ford"); + } + ``` + + writes \"Ford\" to the file \"guide\". To preserve the old file + content if any pass `fmt::file::WRONLY | fmt::file::CREATE` flags to + `fmt::output_file`. + +- Fixed moving of `fmt::ostream` that holds buffered data + (https://github.com/fmtlib/fmt/issues/2197, + https://github.com/fmtlib/fmt/pull/2198). Thanks @vtta. + +- Replaced the `fmt::system_error` exception with a function of the + same name that constructs `std::system_error` + (https://github.com/fmtlib/fmt/issues/2266). + +- Replaced the `fmt::windows_error` exception with a function of the + same name that constructs `std::system_error` with the category + returned by `fmt::system_category()` + (https://github.com/fmtlib/fmt/issues/2274, + https://github.com/fmtlib/fmt/pull/2275). The latter is + similar to `std::system_category` but correctly handles UTF-8. + Thanks @phprus. + +- Replaced `fmt::error_code` with `std::error_code` and made it + formattable (https://github.com/fmtlib/fmt/issues/2269, + https://github.com/fmtlib/fmt/pull/2270, + https://github.com/fmtlib/fmt/pull/2273). Thanks @phprus. + +- Added speech synthesis support + (https://github.com/fmtlib/fmt/pull/2206). + +- Made `format_to` work with a memory buffer that has a custom + allocator (https://github.com/fmtlib/fmt/pull/2300). + Thanks @voxmea. + +- Added `Allocator::max_size` support to `basic_memory_buffer`. + (https://github.com/fmtlib/fmt/pull/1960). Thanks @phprus. + +- Added wide string support to `fmt::join` + (https://github.com/fmtlib/fmt/pull/2236). Thanks @crbrz. + +- Made iterators passed to `formatter` specializations via a format + context satisfy C++20 `std::output_iterator` requirements + (https://github.com/fmtlib/fmt/issues/2156, + https://github.com/fmtlib/fmt/pull/2158, + https://github.com/fmtlib/fmt/issues/2195, + https://github.com/fmtlib/fmt/pull/2204). Thanks @randomnetcat. + +- Optimized the `printf` implementation + (https://github.com/fmtlib/fmt/pull/1982, + https://github.com/fmtlib/fmt/pull/1984, + https://github.com/fmtlib/fmt/pull/2016, + https://github.com/fmtlib/fmt/pull/2164). + Thanks @rimathia and @moiwi. + +- Improved detection of `constexpr` `char_traits` + (https://github.com/fmtlib/fmt/pull/2246, + https://github.com/fmtlib/fmt/pull/2257). Thanks @phprus. + +- Fixed writing to `stdout` when it is redirected to `NUL` on Windows + (https://github.com/fmtlib/fmt/issues/2080). + +- Fixed exception propagation from iterators + (https://github.com/fmtlib/fmt/issues/2097). + +- Improved `strftime` error handling + (https://github.com/fmtlib/fmt/issues/2238, + https://github.com/fmtlib/fmt/pull/2244). Thanks @yumeyao. + +- Stopped using deprecated GCC UDL template extension. + +- Added `fmt/args.h` to the install target + (https://github.com/fmtlib/fmt/issues/2096). + +- Error messages are now passed to assert when exceptions are disabled + (https://github.com/fmtlib/fmt/pull/2145). Thanks @NobodyXu. + +- Added the `FMT_MASTER_PROJECT` CMake option to control build and + install targets when {fmt} is included via `add_subdirectory` + (https://github.com/fmtlib/fmt/issues/2098, + https://github.com/fmtlib/fmt/pull/2100). + Thanks @randomizedthinking. + +- Improved build configuration + (https://github.com/fmtlib/fmt/pull/2026, + https://github.com/fmtlib/fmt/pull/2122). + Thanks @luncliff and @ibaned. + +- Fixed various warnings and compilation issues + (https://github.com/fmtlib/fmt/issues/1947, + https://github.com/fmtlib/fmt/pull/1959, + https://github.com/fmtlib/fmt/pull/1963, + https://github.com/fmtlib/fmt/pull/1965, + https://github.com/fmtlib/fmt/issues/1966, + https://github.com/fmtlib/fmt/pull/1974, + https://github.com/fmtlib/fmt/pull/1975, + https://github.com/fmtlib/fmt/pull/1990, + https://github.com/fmtlib/fmt/issues/2000, + https://github.com/fmtlib/fmt/pull/2001, + https://github.com/fmtlib/fmt/issues/2002, + https://github.com/fmtlib/fmt/issues/2004, + https://github.com/fmtlib/fmt/pull/2006, + https://github.com/fmtlib/fmt/pull/2009, + https://github.com/fmtlib/fmt/pull/2010, + https://github.com/fmtlib/fmt/issues/2038, + https://github.com/fmtlib/fmt/issues/2039, + https://github.com/fmtlib/fmt/issues/2047, + https://github.com/fmtlib/fmt/pull/2053, + https://github.com/fmtlib/fmt/issues/2059, + https://github.com/fmtlib/fmt/pull/2065, + https://github.com/fmtlib/fmt/pull/2067, + https://github.com/fmtlib/fmt/pull/2068, + https://github.com/fmtlib/fmt/pull/2073, + https://github.com/fmtlib/fmt/issues/2103, + https://github.com/fmtlib/fmt/issues/2105, + https://github.com/fmtlib/fmt/pull/2106, + https://github.com/fmtlib/fmt/pull/2107, + https://github.com/fmtlib/fmt/issues/2116, + https://github.com/fmtlib/fmt/pull/2117, + https://github.com/fmtlib/fmt/issues/2118, + https://github.com/fmtlib/fmt/pull/2119, + https://github.com/fmtlib/fmt/issues/2127, + https://github.com/fmtlib/fmt/pull/2128, + https://github.com/fmtlib/fmt/issues/2140, + https://github.com/fmtlib/fmt/issues/2142, + https://github.com/fmtlib/fmt/pull/2143, + https://github.com/fmtlib/fmt/pull/2144, + https://github.com/fmtlib/fmt/issues/2147, + https://github.com/fmtlib/fmt/issues/2148, + https://github.com/fmtlib/fmt/issues/2149, + https://github.com/fmtlib/fmt/pull/2152, + https://github.com/fmtlib/fmt/pull/2160, + https://github.com/fmtlib/fmt/issues/2170, + https://github.com/fmtlib/fmt/issues/2175, + https://github.com/fmtlib/fmt/issues/2176, + https://github.com/fmtlib/fmt/pull/2177, + https://github.com/fmtlib/fmt/issues/2178, + https://github.com/fmtlib/fmt/pull/2179, + https://github.com/fmtlib/fmt/issues/2180, + https://github.com/fmtlib/fmt/issues/2181, + https://github.com/fmtlib/fmt/pull/2183, + https://github.com/fmtlib/fmt/issues/2184, + https://github.com/fmtlib/fmt/issues/2185, + https://github.com/fmtlib/fmt/pull/2186, + https://github.com/fmtlib/fmt/pull/2187, + https://github.com/fmtlib/fmt/pull/2190, + https://github.com/fmtlib/fmt/pull/2192, + https://github.com/fmtlib/fmt/pull/2194, + https://github.com/fmtlib/fmt/pull/2205, + https://github.com/fmtlib/fmt/issues/2210, + https://github.com/fmtlib/fmt/pull/2211, + https://github.com/fmtlib/fmt/pull/2215, + https://github.com/fmtlib/fmt/pull/2216, + https://github.com/fmtlib/fmt/pull/2218, + https://github.com/fmtlib/fmt/pull/2220, + https://github.com/fmtlib/fmt/issues/2228, + https://github.com/fmtlib/fmt/pull/2229, + https://github.com/fmtlib/fmt/pull/2230, + https://github.com/fmtlib/fmt/issues/2233, + https://github.com/fmtlib/fmt/pull/2239, + https://github.com/fmtlib/fmt/issues/2248, + https://github.com/fmtlib/fmt/issues/2252, + https://github.com/fmtlib/fmt/pull/2253, + https://github.com/fmtlib/fmt/pull/2255, + https://github.com/fmtlib/fmt/issues/2261, + https://github.com/fmtlib/fmt/issues/2278, + https://github.com/fmtlib/fmt/issues/2284, + https://github.com/fmtlib/fmt/pull/2287, + https://github.com/fmtlib/fmt/pull/2289, + https://github.com/fmtlib/fmt/pull/2290, + https://github.com/fmtlib/fmt/pull/2293, + https://github.com/fmtlib/fmt/issues/2295, + https://github.com/fmtlib/fmt/pull/2296, + https://github.com/fmtlib/fmt/pull/2297, + https://github.com/fmtlib/fmt/issues/2311, + https://github.com/fmtlib/fmt/pull/2313, + https://github.com/fmtlib/fmt/pull/2315, + https://github.com/fmtlib/fmt/issues/2320, + https://github.com/fmtlib/fmt/pull/2321, + https://github.com/fmtlib/fmt/pull/2323, + https://github.com/fmtlib/fmt/issues/2328, + https://github.com/fmtlib/fmt/pull/2329, + https://github.com/fmtlib/fmt/pull/2333, + https://github.com/fmtlib/fmt/pull/2338, + https://github.com/fmtlib/fmt/pull/2341). + Thanks @darklukee, @fagg, @killerbot242, @jgopel, @yeswalrus, @Finkman, + @HazardyKnusperkeks, @dkavolis, @concatime, @chronoxor, @summivox, @yNeo, + @Apache-HB, @alexezeder, @toojays, @Brainy0207, @vadz, @imsherlock, @phprus, + @white238, @yafshar, @BillyDonahue, @jstaahl, @denchat, @DanielaE, + @ilyakurdyukov, @ilmai, @JessyDL, @sergiud, @mwinterb, @sven-herrmann, + @jmelas, @twoixter, @crbrz and @upsj. + +- Improved documentation + (https://github.com/fmtlib/fmt/issues/1986, + https://github.com/fmtlib/fmt/pull/2051, + https://github.com/fmtlib/fmt/issues/2057, + https://github.com/fmtlib/fmt/pull/2081, + https://github.com/fmtlib/fmt/issues/2084, + https://github.com/fmtlib/fmt/pull/2312). + Thanks @imba-tjd, @0x416c69 and @mordante. + +- Continuous integration and test improvements + (https://github.com/fmtlib/fmt/issues/1969, + https://github.com/fmtlib/fmt/pull/1991, + https://github.com/fmtlib/fmt/pull/2020, + https://github.com/fmtlib/fmt/pull/2110, + https://github.com/fmtlib/fmt/pull/2114, + https://github.com/fmtlib/fmt/issues/2196, + https://github.com/fmtlib/fmt/pull/2217, + https://github.com/fmtlib/fmt/pull/2247, + https://github.com/fmtlib/fmt/pull/2256, + https://github.com/fmtlib/fmt/pull/2336, + https://github.com/fmtlib/fmt/pull/2346). + Thanks @jgopel, @alexezeder and @DanielaE. + +The change log for versions 0.8.0 - 7.1.3 is available [here]( +doc/ChangeLog-old.md). diff --git a/third_party/fmt-11.0.2/LICENSE b/third_party/fmt-11.0.2/LICENSE new file mode 100644 index 000000000..1cd1ef926 --- /dev/null +++ b/third_party/fmt-11.0.2/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. diff --git a/third_party/fmt-11.0.2/README.md b/third_party/fmt-11.0.2/README.md new file mode 100644 index 000000000..5f9249d4b --- /dev/null +++ b/third_party/fmt-11.0.2/README.md @@ -0,0 +1,484 @@ +{fmt} + +[![image](https://github.com/fmtlib/fmt/workflows/linux/badge.svg)](https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux) +[![image](https://github.com/fmtlib/fmt/workflows/macos/badge.svg)](https://github.com/fmtlib/fmt/actions?query=workflow%3Amacos) +[![image](https://github.com/fmtlib/fmt/workflows/windows/badge.svg)](https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows) +[![fmt is continuously fuzzed at oss-fuzz](https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?\%0Acolspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\%0ASummary&q=proj%3Dfmt&can=1) +[![Ask questions at StackOverflow with the tag fmt](https://img.shields.io/badge/stackoverflow-fmt-blue.svg)](https://stackoverflow.com/questions/tagged/fmt) +[![image](https://api.securityscorecards.dev/projects/github.com/fmtlib/fmt/badge)](https://securityscorecards.dev/viewer/?uri=github.com/fmtlib/fmt) + +**{fmt}** is an open-source formatting library providing a fast and safe +alternative to C stdio and C++ iostreams. + +If you like this project, please consider donating to one of the funds +that help victims of the war in Ukraine: . + +[Documentation](https://fmt.dev) + +[Cheat Sheets](https://hackingcpp.com/cpp/libs/fmt.html) + +Q&A: ask questions on [StackOverflow with the tag +fmt](https://stackoverflow.com/questions/tagged/fmt). + +Try {fmt} in [Compiler Explorer](https://godbolt.org/z/8Mx1EW73v). + +# Features + +- Simple [format API](https://fmt.dev/latest/api/) with positional + arguments for localization +- Implementation of [C++20 + std::format](https://en.cppreference.com/w/cpp/utility/format) and + [C++23 std::print](https://en.cppreference.com/w/cpp/io/print) +- [Format string syntax](https://fmt.dev/latest/syntax/) similar + to Python\'s + [format](https://docs.python.org/3/library/stdtypes.html#str.format) +- Fast IEEE 754 floating-point formatter with correct rounding, + shortness and round-trip guarantees using the + [Dragonbox](https://github.com/jk-jeon/dragonbox) algorithm +- Portable Unicode support +- Safe [printf + implementation](https://fmt.dev/latest/api/#printf-formatting) + including the POSIX extension for positional arguments +- Extensibility: [support for user-defined + types](https://fmt.dev/latest/api/#formatting-user-defined-types) +- High performance: faster than common standard library + implementations of `(s)printf`, iostreams, `to_string` and + `to_chars`, see [Speed tests](#speed-tests) and [Converting a + hundred million integers to strings per + second](http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html) +- Small code size both in terms of source code with the minimum + configuration consisting of just three files, `core.h`, `format.h` + and `format-inl.h`, and compiled code; see [Compile time and code + bloat](#compile-time-and-code-bloat) +- Reliability: the library has an extensive set of + [tests](https://github.com/fmtlib/fmt/tree/master/test) and is + [continuously fuzzed](https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1) +- Safety: the library is fully type-safe, errors in format strings can + be reported at compile time, automatic memory management prevents + buffer overflow errors +- Ease of use: small self-contained code base, no external + dependencies, permissive MIT + [license](https://github.com/fmtlib/fmt/blob/master/LICENSE) +- [Portability](https://fmt.dev/latest/#portability) with + consistent output across platforms and support for older compilers +- Clean warning-free codebase even on high warning levels such as + `-Wall -Wextra -pedantic` +- Locale independence by default +- Optional header-only configuration enabled with the + `FMT_HEADER_ONLY` macro + +See the [documentation](https://fmt.dev) for more details. + +# Examples + +**Print to stdout** ([run](https://godbolt.org/z/Tevcjh)) + +``` c++ +#include + +int main() { + fmt::print("Hello, world!\n"); +} +``` + +**Format a string** ([run](https://godbolt.org/z/oK8h33)) + +``` c++ +std::string s = fmt::format("The answer is {}.", 42); +// s == "The answer is 42." +``` + +**Format a string using positional arguments** +([run](https://godbolt.org/z/Yn7Txe)) + +``` c++ +std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy"); +// s == "I'd rather be happy than right." +``` + +**Print dates and times** ([run](https://godbolt.org/z/c31ExdY3W)) + +``` c++ +#include + +int main() { + auto now = std::chrono::system_clock::now(); + fmt::print("Date and time: {}\n", now); + fmt::print("Time: {:%H:%M}\n", now); +} +``` + +Output: + + Date and time: 2023-12-26 19:10:31.557195597 + Time: 19:10 + +**Print a container** ([run](https://godbolt.org/z/MxM1YqjE7)) + +``` c++ +#include +#include + +int main() { + std::vector v = {1, 2, 3}; + fmt::print("{}\n", v); +} +``` + +Output: + + [1, 2, 3] + +**Check a format string at compile time** + +``` c++ +std::string s = fmt::format("{:d}", "I am not a number"); +``` + +This gives a compile-time error in C++20 because `d` is an invalid +format specifier for a string. + +**Write a file from a single thread** + +``` c++ +#include + +int main() { + auto out = fmt::output_file("guide.txt"); + out.print("Don't {}", "Panic"); +} +``` + +This can be [5 to 9 times faster than +fprintf](http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html). + +**Print with colors and text styles** + +``` c++ +#include + +int main() { + fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, + "Hello, {}!\n", "world"); + fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) | + fmt::emphasis::underline, "Olá, {}!\n", "Mundo"); + fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic, + "你好{}!\n", "世界"); +} +``` + +Output on a modern terminal with Unicode support: + +![image](https://github.com/fmtlib/fmt/assets/%0A576385/2a93c904-d6fa-4aa6-b453-2618e1c327d7) + +# Benchmarks + +## Speed tests + +| Library | Method | Run Time, s | +|-------------------|---------------|-------------| +| libc | printf | 0.91 | +| libc++ | std::ostream | 2.49 | +| {fmt} 9.1 | fmt::print | 0.74 | +| Boost Format 1.80 | boost::format | 6.26 | +| Folly Format | folly::format | 1.87 | + +{fmt} is the fastest of the benchmarked methods, \~20% faster than +`printf`. + +The above results were generated by building `tinyformat_test.cpp` on +macOS 12.6.1 with `clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT`, and +taking the best of three runs. In the test, the format string +`"%0.10f:%04d:%+g:%s:%p:%c:%%\n"` or equivalent is filled 2,000,000 +times with output sent to `/dev/null`; for further details refer to the +[source](https://github.com/fmtlib/format-benchmark/blob/master/src/tinyformat-test.cc). + +{fmt} is up to 20-30x faster than `std::ostringstream` and `sprintf` on +IEEE754 `float` and `double` formatting +([dtoa-benchmark](https://github.com/fmtlib/dtoa-benchmark)) and faster +than [double-conversion](https://github.com/google/double-conversion) +and [ryu](https://github.com/ulfjack/ryu): + +[![image](https://user-images.githubusercontent.com/576385/95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png)](https://fmt.dev/unknown_mac64_clang12.0.html) + +## Compile time and code bloat + +The script [bloat-test.py][test] from [format-benchmark][bench] tests compile +time and code bloat for nontrivial projects. It generates 100 translation units +and uses `printf()` or its alternative five times in each to simulate a +medium-sized project. The resulting executable size and compile time (Apple +clang version 15.0.0 (clang-1500.1.0.2.5), macOS Sonoma, best of three) is shown +in the following tables. + +[test]: https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py +[bench]: https://github.com/fmtlib/format-benchmark + +**Optimized build (-O3)** + +| Method | Compile Time, s | Executable size, KiB | Stripped size, KiB | +|---------------|-----------------|----------------------|--------------------| +| printf | 1.6 | 54 | 50 | +| IOStreams | 25.9 | 98 | 84 | +| fmt 83652df | 4.8 | 54 | 50 | +| tinyformat | 29.1 | 161 | 136 | +| Boost Format | 55.0 | 530 | 317 | + +{fmt} is fast to compile and is comparable to `printf` in terms of per-call +binary size (within a rounding error on this system). + +**Non-optimized build** + +| Method | Compile Time, s | Executable size, KiB | Stripped size, KiB | +|---------------|-----------------|----------------------|--------------------| +| printf | 1.4 | 54 | 50 | +| IOStreams | 23.4 | 92 | 68 | +| {fmt} 83652df | 4.4 | 89 | 85 | +| tinyformat | 24.5 | 204 | 161 | +| Boost Format | 36.4 | 831 | 462 | + +`libc`, `lib(std)c++`, and `libfmt` are all linked as shared libraries +to compare formatting function overhead only. Boost Format is a +header-only library so it doesn\'t provide any linkage options. + +## Running the tests + +Please refer to [Building the +library](https://fmt.dev/latest/get-started/#building-from-source) for +instructions on how to build the library and run the unit tests. + +Benchmarks reside in a separate repository, +[format-benchmarks](https://github.com/fmtlib/format-benchmark), so to +run the benchmarks you first need to clone this repository and generate +Makefiles with CMake: + + $ git clone --recursive https://github.com/fmtlib/format-benchmark.git + $ cd format-benchmark + $ cmake . + +Then you can run the speed test: + + $ make speed-test + +or the bloat test: + + $ make bloat-test + +# Migrating code + +[clang-tidy](https://clang.llvm.org/extra/clang-tidy/) v18 provides the +[modernize-use-std-print](https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-std-print.html) +check that is capable of converting occurrences of `printf` and +`fprintf` to `fmt::print` if configured to do so. (By default it +converts to `std::print`.) + +# Notable projects using this library + +- [0 A.D.](https://play0ad.com/): a free, open-source, cross-platform + real-time strategy game +- [AMPL/MP](https://github.com/ampl/mp): an open-source library for + mathematical programming +- [Apple's FoundationDB](https://github.com/apple/foundationdb): an open-source, + distributed, transactional key-value store +- [Aseprite](https://github.com/aseprite/aseprite): animated sprite + editor & pixel art tool +- [AvioBook](https://www.aviobook.aero/en): a comprehensive aircraft + operations suite +- [Blizzard Battle.net](https://battle.net/): an online gaming + platform +- [Celestia](https://celestia.space/): real-time 3D visualization of + space +- [Ceph](https://ceph.com/): a scalable distributed storage system +- [ccache](https://ccache.dev/): a compiler cache +- [ClickHouse](https://github.com/ClickHouse/ClickHouse): an + analytical database management system +- [Contour](https://github.com/contour-terminal/contour/): a modern + terminal emulator +- [CUAUV](https://cuauv.org/): Cornell University\'s autonomous + underwater vehicle +- [Drake](https://drake.mit.edu/): a planning, control, and analysis + toolbox for nonlinear dynamical systems (MIT) +- [Envoy](https://github.com/envoyproxy/envoy): C++ L7 proxy and + communication bus (Lyft) +- [FiveM](https://fivem.net/): a modification framework for GTA V +- [fmtlog](https://github.com/MengRao/fmtlog): a performant + fmtlib-style logging library with latency in nanoseconds +- [Folly](https://github.com/facebook/folly): Facebook open-source + library +- [GemRB](https://gemrb.org/): a portable open-source implementation + of Bioware's Infinity Engine +- [Grand Mountain + Adventure](https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/): + a beautiful open-world ski & snowboarding game +- [HarpyWar/pvpgn](https://github.com/pvpgn/pvpgn-server): Player vs + Player Gaming Network with tweaks +- [KBEngine](https://github.com/kbengine/kbengine): an open-source + MMOG server engine +- [Keypirinha](https://keypirinha.com/): a semantic launcher for + Windows +- [Kodi](https://kodi.tv/) (formerly xbmc): home theater software +- [Knuth](https://kth.cash/): high-performance Bitcoin full-node +- [libunicode](https://github.com/contour-terminal/libunicode/): a + modern C++17 Unicode library +- [MariaDB](https://mariadb.org/): relational database management + system +- [Microsoft Verona](https://github.com/microsoft/verona): research + programming language for concurrent ownership +- [MongoDB](https://mongodb.com/): distributed document database +- [MongoDB Smasher](https://github.com/duckie/mongo_smasher): a small + tool to generate randomized datasets +- [OpenSpace](https://openspaceproject.com/): an open-source + astrovisualization framework +- [PenUltima Online (POL)](https://www.polserver.com/): an MMO server, + compatible with most Ultima Online clients +- [PyTorch](https://github.com/pytorch/pytorch): an open-source + machine learning library +- [quasardb](https://www.quasardb.net/): a distributed, + high-performance, associative database +- [Quill](https://github.com/odygrd/quill): asynchronous low-latency + logging library +- [QKW](https://github.com/ravijanjam/qkw): generalizing aliasing to + simplify navigation, and execute complex multi-line terminal + command sequences +- [redis-cerberus](https://github.com/HunanTV/redis-cerberus): a Redis + cluster proxy +- [redpanda](https://vectorized.io/redpanda): a 10x faster Kafka® + replacement for mission-critical systems written in C++ +- [rpclib](http://rpclib.net/): a modern C++ msgpack-RPC server and + client library +- [Salesforce Analytics + Cloud](https://www.salesforce.com/analytics-cloud/overview/): + business intelligence software +- [Scylla](https://www.scylladb.com/): a Cassandra-compatible NoSQL + data store that can handle 1 million transactions per second on a + single server +- [Seastar](http://www.seastar-project.org/): an advanced, open-source + C++ framework for high-performance server applications on modern + hardware +- [spdlog](https://github.com/gabime/spdlog): super fast C++ logging + library +- [Stellar](https://www.stellar.org/): financial platform +- [Touch Surgery](https://www.touchsurgery.com/): surgery simulator +- [TrinityCore](https://github.com/TrinityCore/TrinityCore): + open-source MMORPG framework +- [🐙 userver framework](https://userver.tech/): open-source + asynchronous framework with a rich set of abstractions and database + drivers +- [Windows Terminal](https://github.com/microsoft/terminal): the new + Windows terminal + +[More\...](https://github.com/search?q=fmtlib&type=Code) + +If you are aware of other projects using this library, please let me +know by [email](mailto:victor.zverovich@gmail.com) or by submitting an +[issue](https://github.com/fmtlib/fmt/issues). + +# Motivation + +So why yet another formatting library? + +There are plenty of methods for doing this task, from standard ones like +the printf family of function and iostreams to Boost Format and +FastFormat libraries. The reason for creating a new library is that +every existing solution that I found either had serious issues or +didn\'t provide all the features I needed. + +## printf + +The good thing about `printf` is that it is pretty fast and readily +available being a part of the C standard library. The main drawback is +that it doesn\'t support user-defined types. `printf` also has safety +issues although they are somewhat mitigated with [\_\_attribute\_\_ +((format (printf, +\...))](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html) in +GCC. There is a POSIX extension that adds positional arguments required +for +[i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization) +to `printf` but it is not a part of C99 and may not be available on some +platforms. + +## iostreams + +The main issue with iostreams is best illustrated with an example: + +``` c++ +std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; +``` + +which is a lot of typing compared to printf: + +``` c++ +printf("%.2f\n", 1.23456); +``` + +Matthew Wilson, the author of FastFormat, called this \"chevron hell\". +iostreams don\'t support positional arguments by design. + +The good part is that iostreams support user-defined types and are safe +although error handling is awkward. + +## Boost Format + +This is a very powerful library that supports both `printf`-like format +strings and positional arguments. Its main drawback is performance. +According to various benchmarks, it is much slower than other methods +considered here. Boost Format also has excessive build times and severe +code bloat issues (see [Benchmarks](#benchmarks)). + +## FastFormat + +This is an interesting library that is fast, safe and has positional +arguments. However, it has significant limitations, citing its author: + +> Three features that have no hope of being accommodated within the +> current design are: +> +> - Leading zeros (or any other non-space padding) +> - Octal/hexadecimal encoding +> - Runtime width/alignment specification + +It is also quite big and has a heavy dependency, on STLSoft, which might be +too restrictive for use in some projects. + +## Boost Spirit.Karma + +This is not a formatting library but I decided to include it here for +completeness. As iostreams, it suffers from the problem of mixing +verbatim text with arguments. The library is pretty fast, but slower on +integer formatting than `fmt::format_to` with format string compilation +on Karma\'s own benchmark, see [Converting a hundred million integers to +strings per +second](http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html). + +# License + +{fmt} is distributed under the MIT +[license](https://github.com/fmtlib/fmt/blob/master/LICENSE). + +# Documentation License + +The [Format String Syntax](https://fmt.dev/latest/syntax/) section +in the documentation is based on the one from Python [string module +documentation](https://docs.python.org/3/library/string.html#module-string). +For this reason, the documentation is distributed under the Python +Software Foundation license available in +[doc/python-license.txt](https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt). +It only applies if you distribute the documentation of {fmt}. + +# Maintainers + +The {fmt} library is maintained by Victor Zverovich +([vitaut](https://github.com/vitaut)) with contributions from many other +people. See +[Contributors](https://github.com/fmtlib/fmt/graphs/contributors) and +[Releases](https://github.com/fmtlib/fmt/releases) for some of the +names. Let us know if your contribution is not listed or mentioned +incorrectly and we\'ll make it right. + +# Security Policy + +To report a security issue, please disclose it at [security +advisory](https://github.com/fmtlib/fmt/security/advisories/new). + +This project is maintained by a team of volunteers on a +reasonable-effort basis. As such, please give us at least *90* days to +work on a fix before public exposure. diff --git a/third_party/fmt-11.0.2/doc-html/404.html b/third_party/fmt-11.0.2/doc-html/404.html new file mode 100644 index 000000000..994f85e51 --- /dev/null +++ b/third_party/fmt-11.0.2/doc-html/404.html @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + + + + + + {fmt} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + +
    +
    +
    + + + + +
    +
    + +

    404 - Not found

    + +
    +
    + + + +
    + + + +
    + +
    + + +
    + +
    +
    +
    +
    + + + + + + + + + + + + + + \ No newline at end of file diff --git a/third_party/fmt-11.0.2/doc-html/api.html b/third_party/fmt-11.0.2/doc-html/api.html new file mode 100644 index 000000000..45ee46df4 --- /dev/null +++ b/third_party/fmt-11.0.2/doc-html/api.html @@ -0,0 +1,1978 @@ + + + + + + + + + + + + + + + + + + + + + + + API - {fmt} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +
    + + +
    + +
    + + + + + + + + + +
    +
    + + + + + + + + +
    +
    + + + + + + + +

    API Reference

    +

    The {fmt} library API consists of the following components:

    + +

    All functions and types provided by the library reside in namespace fmt +and macros have prefix FMT_.

    +

    Base API

    +

    fmt/base.h defines the base API which provides main formatting functions +for char/UTF-8 with C++20 compile-time checks. It has minimal include +dependencies for better compile times. This header is only beneficial when +using {fmt} as a library (the default) and not in the header-only mode. +It also provides formatter specializations for the following types:

    +
      +
    • int, long long,
    • +
    • unsigned, unsigned long long
    • +
    • float, double, long double
    • +
    • bool
    • +
    • char
    • +
    • const char*, fmt::string_view
    • +
    • const void*
    • +
    +

    The following functions use format string syntax similar to that +of str.format +in Python. They take fmt and args as arguments.

    +

    fmt is a format string that contains literal text and replacement fields +surrounded by braces {}. The fields are replaced with formatted arguments +in the resulting string. fmt::format_string is a format +string which can be implicitly constructed from a string literal or a +constexpr string and is checked at compile time in C++20. To pass a runtime +format string wrap it in fmt::runtime.

    +

    args is an argument list representing objects to be formatted.

    +

    I/O errors are reported as std::system_error exceptions unless +specified otherwise.

    +
    + +
    template <typename... T> +
    void print(format_string<T...> fmt, T&&... args);
    +
    +
    +

    Formats args according to specifications in fmt and writes the output to stdout.

    +

    Example:

    fmt::print("The answer is {}.", 42);
    +

    +
    +
    +
    + +
    template <typename... T> +
    void print(FILE* f, format_string<T...> fmt, T&&... args);
    +
    +
    +

    Formats args according to specifications in fmt and writes the output to the file f.

    +

    Example:

    fmt::print(stderr, "Don't {}!", "panic");
    +

    +
    +
    +
    + +
    template <typename... T> +
    void println(format_string<T...> fmt, T&&... args);
    +
    +
    +

    Formats args according to specifications in fmt and writes the output to stdout followed by a newline.

    +
    +
    +
    + +
    template <typename... T> +
    void println(FILE* f, format_string<T...> fmt, T&&... args);
    +
    +
    +

    Formats args according to specifications in fmt and writes the output to the file f followed by a newline.

    +
    +
    +
    + +
    template <typename OutputIt, typename... T> +
    auto format_to(OutputIt&& out, format_string<T...> fmt, T&&... args) -⁠> remove_cvref_t<OutputIt>;
    +
    +
    +

    Formats args according to specifications in fmt, writes the result to the output iterator out and returns the iterator past the end of the output range. format_to does not append a terminating null character.

    +

    Example:

    auto out = std::vector<char>();
    +fmt::format_to(std::back_inserter(out), "{}", 42);
    +

    +
    +
    +
    + +
    template <typename OutputIt, typename... T> +
    auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt, T&&... args) -⁠> format_to_n_result<OutputIt>;
    +
    +
    +

    Formats args according to specifications in fmt, writes up to n characters of the result to the output iterator out and returns the total (not truncated) output size and the iterator past the end of the output range. format_to_n does not append a terminating null character.

    +
    +
    +
    + +
    template <typename OutputIt> +
    struct format_to_n_result;
    +
    +
    +
    +
    OutputIt out;
    +
    +

    Iterator past the end of the output range.

    +
    +
    +
    +
    size_t size;
    +
    +

    Total (not truncated) output size.

    +
    +
    +
    +
    +
    + +
    template <typename... T> +
    auto formatted_size(format_string<T...> fmt, T&&... args) -⁠> size_t;
    +
    +
    +

    Returns the number of chars in the output of format(fmt, args...).

    +
    +
    +

    +

    Formatting User-Defined Types

    +

    The {fmt} library provides formatters for many standard C++ types. +See fmt/ranges.h for ranges and tuples including standard +containers such as std::vector, fmt/chrono.h for date and +time formatting and fmt/std.h for other standard library types.

    +

    There are two ways to make a user-defined type formattable: providing a +format_as function or specializing the formatter struct template.

    +

    Use format_as if you want to make your type formattable as some other +type with the same format specifiers. The format_as function should +take an object of your type and return an object of a formattable type. +It should be defined in the same namespace as your type.

    +

    Example (run):

    +
    #include <fmt/format.h>
    +
    +namespace kevin_namespacy {
    +
    +enum class film {
    +  house_of_cards, american_beauty, se7en = 7
    +};
    +
    +auto format_as(film f) { return fmt::underlying(f); }
    +
    +}
    +
    +int main() {
    +  fmt::print("{}\n", kevin_namespacy::film::se7en); // Output: 7
    +}
    +

    Using specialization is more complex but gives you full control over +parsing and formatting. To use this method specialize the formatter +struct template for your type and implement parse and format +methods.

    +

    The recommended way of defining a formatter is by reusing an existing +one via inheritance or composition. This way you can support standard +format specifiers without implementing them yourself. For example:

    +
    // color.h:
    +#include <fmt/base.h>
    +
    +enum class color {red, green, blue};
    +
    +template <> struct fmt::formatter<color>: formatter<string_view> {
    +  // parse is inherited from formatter<string_view>.
    +
    +  auto format(color c, format_context& ctx) const
    +    -> format_context::iterator;
    +};
    +
    +
    // color.cc:
    +#include "color.h"
    +#include <fmt/format.h>
    +
    +auto fmt::formatter<color>::format(color c, format_context& ctx) const
    +    -> format_context::iterator {
    +  string_view name = "unknown";
    +  switch (c) {
    +  case color::red:   name = "red"; break;
    +  case color::green: name = "green"; break;
    +  case color::blue:  name = "blue"; break;
    +  }
    +  return formatter<string_view>::format(name, ctx);
    +}
    +
    +

    Note that formatter<string_view>::format is defined in fmt/format.h +so it has to be included in the source file. Since parse is inherited +from formatter<string_view> it will recognize all string format +specifications, for example

    +
    fmt::format("{:>10}", color::blue)
    +
    +

    will return " blue".

    + + +

    In general the formatter has the following form:

    +
    template <> struct fmt::formatter<T> {
    +  // Parses format specifiers and stores them in the formatter.
    +  //
    +  // [ctx.begin(), ctx.end()) is a, possibly empty, character range that
    +  // contains a part of the format string starting from the format
    +  // specifications to be parsed, e.g. in
    +  //
    +  //   fmt::format("{:f} continued", ...);
    +  //
    +  // the range will contain "f} continued". The formatter should parse
    +  // specifiers until '}' or the end of the range. In this example the
    +  // formatter should parse the 'f' specifier and return an iterator
    +  // pointing to '}'.
    +  constexpr auto parse(format_parse_context& ctx)
    +    -> format_parse_context::iterator;
    +
    +  // Formats value using the parsed format specification stored in this
    +  // formatter and writes the output to ctx.out().
    +  auto format(const T& value, format_context& ctx) const
    +    -> format_context::iterator;
    +};
    +

    It is recommended to at least support fill, align and width that apply +to the whole object and have the same semantics as in standard +formatters.

    +

    You can also write a formatter for a hierarchy of classes:

    +
    // demo.h:
    +#include <type_traits>
    +#include <fmt/core.h>
    +
    +struct A {
    +  virtual ~A() {}
    +  virtual std::string name() const { return "A"; }
    +};
    +
    +struct B : A {
    +  virtual std::string name() const { return "B"; }
    +};
    +
    +template <typename T>
    +struct fmt::formatter<T, std::enable_if_t<std::is_base_of_v<A, T>, char>> :
    +    fmt::formatter<std::string> {
    +  auto format(const A& a, format_context& ctx) const {
    +    return formatter<std::string>::format(a.name(), ctx);
    +  }
    +};
    +
    +
    // demo.cc:
    +#include "demo.h"
    +#include <fmt/format.h>
    +
    +int main() {
    +  B b;
    +  A& a = b;
    +  fmt::print("{}", a); // Output: B
    +}
    +
    +

    Providing both a formatter specialization and a format_as overload is +disallowed.

    +
    + +
    template <typename Char> +
    class basic_format_parse_context;
    +
    +
    +

    Parsing context consisting of a format string range being parsed and an argument counter for automatic indexing. You can use the format_parse_context type alias for char instead.

    +
    +
    constexpr auto begin() -⁠> iterator;
    +
    +

    Returns an iterator to the beginning of the format string range being parsed.

    +
    +
    +
    +
    constexpr auto end() -⁠> iterator;
    +
    +

    Returns an iterator past the end of the format string range being parsed.

    +
    +
    +
    +
    void advance_to(iterator it);
    +
    +

    Advances the begin iterator to it.

    +
    +
    +
    +
    auto next_arg_id() -⁠> int;
    +
    +

    Reports an error if using the manual argument indexing; otherwise returns the next argument index and switches to the automatic indexing.

    +
    +
    +
    +
    void check_arg_id(int id);
    +
    +

    Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing.

    +
    +
    +
    +
    +
    + +
    class context;
    +
    +
    +
    +
    context(iterator out, basic_format_args<context> ctx_args, detail::locale_ref loc);
    +
    +

    Constructs a basic_format_context object. References to the arguments are stored in the object so make sure they have appropriate lifetimes.

    +
    +
    +
    +
    + +

    Compile-Time Checks

    +

    Compile-time format string checks are enabled by default on compilers +that support C++20 consteval. On older compilers you can use the +FMT_STRING macro defined in fmt/format.h instead.

    +

    Unused arguments are allowed as in Python's str.format and ordinary functions.

    + + +
    + +
    auto runtime(string_view s) -⁠> runtime_format_string<>;
    +
    +
    +

    Creates a runtime format string.

    +

    Example:

    // Check format string at runtime instead of compile-time.
    +fmt::print(fmt::runtime("{:d}"), "I am not a number");
    +

    +
    +
    +

    Named Arguments

    +
    + +
    template <typename Char, typename T> +
    auto arg(const Char* name, const T& arg) -⁠> detail::named_arg<Char, T>;
    +
    +
    +

    Returns a named argument to be used in a formatting function. It should only be used in a call to a formatting function or dynamic_format_arg_store::push_back.

    +

    Example:

    fmt::print("The answer is {answer}.", fmt::arg("answer", 42));
    +

    +
    +
    +

    Named arguments are not supported in compile-time checks at the moment.

    +

    Type Erasure

    +

    You can create your own formatting function with compile-time checks and +small binary footprint, for example (run):

    +
    #include <fmt/format.h>
    +
    +void vlog(const char* file, int line,
    +          fmt::string_view fmt, fmt::format_args args) {
    +  fmt::print("{}: {}: {}", file, line, fmt::vformat(fmt, args));
    +}
    +
    +template <typename... T>
    +void log(const char* file, int line,
    +         fmt::format_string<T...> fmt, T&&... args) {
    +  vlog(file, line, fmt, fmt::make_format_args(args...));
    +}
    +
    +#define MY_LOG(fmt, ...) log(__FILE__, __LINE__, fmt, __VA_ARGS__)
    +
    +MY_LOG("invalid squishiness: {}", 42);
    +
    +

    Note that vlog is not parameterized on argument types which improves +compile times and reduces binary code size compared to a fully +parameterized version.

    +
    + +
    template <typename Context, typename... T, size_t NUM_ARGS, size_t NUM_NAMED_ARGS, unsigned long long DESC> +
    constexpr auto make_format_args(T&... args) -⁠> detail::format_arg_store<Context, NUM_ARGS, 0, DESC>;
    +
    +
    +

    Constructs an object that stores references to arguments and can be implicitly converted to format_args. Context can be omitted in which case it defaults to format_context. See arg for lifetime considerations.

    +
    +
    +
    + +
    template <typename Context> +
    class basic_format_args;
    +
    +
    +

    A view of a collection of formatting arguments. To avoid lifetime issues it should only be used as a parameter type in type-erased functions such as vformat:

    void vlog(fmt::string_view fmt, fmt::format_args args);  // OK
    +fmt::format_args args = fmt::make_format_args();  // Dangling reference
    +

    +
    +
    constexpr basic_format_args(const detail::format_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>& store);
    +
    +

    Constructs a basic_format_args object from format_arg_store.

    +
    +
    +
    +
    constexpr basic_format_args(const dynamic_format_arg_store<Context>& store);
    +
    +

    Constructs a basic_format_args object from dynamic_format_arg_store.

    +
    +
    +
    +
    constexpr basic_format_args(const format_arg* args, int count);
    +
    +

    Constructs a basic_format_args object from a dynamic list of arguments.

    +
    +
    +
    +
    auto get(int id) -⁠> format_arg;
    +
    +

    Returns the argument with the specified id.

    +
    +
    +
    +
    +
    + +
    using format_args = basic_format_args<format_context>;
    +
    +
    +

    An alias for basic_format_args<format_context>.

    +
    +
    +
    + +
    template <typename Context> +
    class basic_format_arg;
    +
    +
    +
    +
    auto visit(Visitor&& vis) -⁠> decltype(vis(0));
    +
    +

    Visits an argument dispatching to the appropriate visit method based on the argument type. For example, if the argument type is double then vis(value) will be called with the value of type double.

    +
    +
    +
    +
    +

    Compatibility

    +
    + +
    template <typename Char> +
    class basic_string_view;
    +
    +
    +

    An implementation of std::basic_string_view for pre-C++17. It provides a subset of the API. fmt::basic_string_view is used for format strings even if std::basic_string_view is available to prevent issues when a library is compiled with a different -std option than the client code (which is not recommended).

    +
    +
    constexpr basic_string_view(const Char* s, size_t count);
    +
    +

    Constructs a string reference object from a C string and a size.

    +
    +
    +
    +
    basic_string_view(const Char* s);
    +
    +

    Constructs a string reference object from a C string.

    +
    +
    +
    +
    basic_string_view(const S& s);
    +
    +

    Constructs a string reference from a std::basic_string or a std::basic_string_view object.

    +
    +
    +
    +
    constexpr auto data() -⁠> const Char*;
    +
    +

    Returns a pointer to the string data.

    +
    +
    +
    +
    constexpr auto size() -⁠> size_t;
    +
    +

    Returns the string size.

    +
    +
    +
    +
    + +

    Format API

    +

    fmt/format.h defines the full format API providing additional +formatting functions and locale support.

    +

    +

    +
    + +
    template <typename... T> +
    auto format(format_string<T...> fmt, T&&... args) -⁠> std::string;
    +
    +
    +

    Formats args according to specifications in fmt and returns the result as a string.

    +

    Example:

    #include <fmt/format.h>
    +std::string message = fmt::format("The answer is {}.", 42);
    +

    +
    +
    + +
    + +
    template <detail_exported::fixed_string Str> +
    constexpr auto operator""_a();
    +
    +
    +

    User-defined literal equivalent of fmt::arg.

    +

    Example:

    using namespace fmt::literals;
    +fmt::print("The answer is {answer}.", "answer"_a=42);
    +

    +
    +
    +

    Utilities

    +
    + +
    template <typename T> +
    auto ptr(T p) -⁠> const void*;
    +
    +
    +

    Converts p to const void* for pointer formatting.

    +

    Example:

    auto s = fmt::format("{}", fmt::ptr(p));
    +

    +
    +
    +
    + +
    template <typename Enum> +
    constexpr auto underlying(Enum e) -⁠> underlying_t<Enum>;
    +
    +
    +

    Converts e to the underlying type.

    +

    Example:

    enum class color { red, green, blue };
    +auto s = fmt::format("{}", fmt::underlying(color::red));
    +

    +
    +
    +
    + +
    template <typename T> +
    auto to_string(const T& value) -⁠> std::string;
    +
    +
    +

    Converts value to std::string using the default format for type T.

    +

    Example:

    std::string answer = fmt::to_string(42);
    +

    +
    +
    +
    + +
    template <typename T> +
    auto group_digits(T value) -⁠> group_digits_view<T>;
    +
    +
    +

    Returns a view that formats an integer value using ',' as a locale-independent thousands separator.

    +

    Example:

    fmt::print("{}", fmt::group_digits(12345));
    +// Output: "12,345"
    +

    +
    +
    +
    + +
    template <typename T> +
    class detail::buffer;
    +
    +
    +

    A contiguous memory buffer with an optional growing ability. It is an internal class and shouldn't be used directly, only via memory_buffer.

    +
    +
    constexpr auto size() -⁠> size_t;
    +
    +

    Returns the size of this buffer.

    +
    +
    +
    +
    constexpr auto capacity() -⁠> size_t;
    +
    +

    Returns the capacity of this buffer.

    +
    +
    +
    +
    auto data() -⁠> T*;
    +
    +

    Returns a pointer to the buffer data (not null-terminated).

    +
    +
    +
    +
    void clear();
    +
    +

    Clears this buffer.

    +
    +
    +
    +
    void append(const U* begin, const U* end);
    +
    +

    Appends data to the end of the buffer.

    +
    +
    +
    +
    +
    + +
    template <typename T, size_t SIZE, typename Allocator> +
    class basic_memory_buffer;
    +
    +
    +

    A dynamically growing memory buffer for trivially copyable/constructible types with the first SIZE elements stored in the object itself. Most commonly used via the memory_buffer alias for char.

    +

    Example:

    auto out = fmt::memory_buffer();
    +fmt::format_to(std::back_inserter(out), "The answer is {}.", 42);
    +
    This will append "The answer is 42." to out. The buffer content can be converted to std::string with to_string(out).

    +
    +
    basic_memory_buffer(basic_memory_buffer&& other);
    +
    +

    Constructs a basic_memory_buffer object moving the content of the other object to it.

    +
    +
    +
    +
    auto operator=(basic_memory_buffer&& other) -⁠> basic_memory_buffer&;
    +
    +

    Moves the content of the other basic_memory_buffer object to this one.

    +
    +
    +
    +
    void resize(size_t count);
    +
    +

    Resizes the buffer to contain count elements. If T is a POD type new elements may not be initialized.

    +
    +
    +
    +
    void reserve(size_t new_capacity);
    +
    +

    Increases the buffer capacity to new_capacity.

    +
    +
    +
    +
    +

    System Errors

    +

    {fmt} does not use errno to communicate errors to the user, but it may +call system functions which set errno. Users should not make any +assumptions about the value of errno being preserved by library +functions.

    +
    + +
    template <typename... T> +
    auto system_error(int error_code, format_string<T...> fmt, T&&... args) -⁠> std::system_error;
    +
    +
    +

    Constructs std::system_error with a message formatted with fmt::format(fmt, args...). error_code is a system error code as given by errno.

    +

    Example:

    // This throws std::system_error with the description
    +//   cannot open file 'madeup': No such file or directory
    +// or similar (system message may vary).
    +const char* filename = "madeup";
    +std::FILE* file = std::fopen(filename, "r");
    +if (!file)
    +  throw fmt::system_error(errno, "cannot open file '{}'", filename);
    +

    +
    +
    +
    + +
    void format_system_error(detail::buffer<char>& out, int error_code, const char* message);
    +
    +
    +

    Formats an error message for an error returned by an operating system or a language runtime, for example a file opening error, and writes it to out. The format is the same as the one used by std::system_error(ec, message) where ec is std::error_code(error_code, std::generic_category()). It is implementation-defined but normally looks like:

    <message>: <system-message>
    +
    where <message> is the passed message and <system-message> is the system message corresponding to the error code. error_code is a system error code as given by errno.

    +
    +
    +

    Custom Allocators

    +

    The {fmt} library supports custom dynamic memory allocators. A custom +allocator class can be specified as a template argument to +fmt::basic_memory_buffer:

    +
    using custom_memory_buffer = 
    +  fmt::basic_memory_buffer<char, fmt::inline_buffer_size, custom_allocator>;
    +

    It is also possible to write a formatting function that uses a custom +allocator:

    +
    using custom_string =
    +  std::basic_string<char, std::char_traits<char>, custom_allocator>;
    +
    +custom_string vformat(custom_allocator alloc, fmt::string_view format_str,
    +                      fmt::format_args args) {
    +  auto buf = custom_memory_buffer(alloc);
    +  fmt::vformat_to(std::back_inserter(buf), format_str, args);
    +  return custom_string(buf.data(), buf.size(), alloc);
    +}
    +
    +template <typename ...Args>
    +inline custom_string format(custom_allocator alloc,
    +                            fmt::string_view format_str,
    +                            const Args& ... args) {
    +  return vformat(alloc, format_str, fmt::make_format_args(args...));
    +}
    +

    The allocator will be used for the output container only. Formatting +functions normally don't do any allocations for built-in and string +types except for non-default floating-point formatting that occasionally +falls back on sprintf.

    +

    Locale

    +

    All formatting is locale-independent by default. Use the 'L' format +specifier to insert the appropriate number separator characters from the +locale:

    +
    #include <fmt/core.h>
    +#include <locale>
    +
    +std::locale::global(std::locale("en_US.UTF-8"));
    +auto s = fmt::format("{:L}", 1000000);  // s == "1,000,000"
    +

    fmt/format.h provides the following overloads of formatting functions +that take std::locale as a parameter. The locale type is a template +parameter to avoid the expensive <locale> include.

    + + + +

    +

    Legacy Compile-Time Checks

    +

    FMT_STRING enables compile-time checks on older compilers. It requires +C++14 or later and is a no-op in C++11.

    +
    + +
    FMT_STRING(s)
    +
    +
    +

    Constructs a compile-time format string from a string literal s.

    +

    Example:

    // A compile-time error because 'd' is an invalid specifier for strings.
    +std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
    +

    +
    +
    +

    To force the use of legacy compile-time checks, define the preprocessor +variable FMT_ENFORCE_COMPILE_STRING. When set, functions accepting +FMT_STRING will fail to compile with regular strings.

    +

    +

    Range and Tuple Formatting

    +

    fmt/ranges.h provides formatting support for ranges and tuples:

    +
    #include <fmt/ranges.h>
    +
    +fmt::print("{}", std::tuple<char, int>{'a', 42});
    +// Output: ('a', 42)
    +

    Using fmt::join, you can separate tuple elements with a custom separator:

    +
    #include <fmt/ranges.h>
    +
    +auto t = std::tuple<int, char>{1, 'a'};
    +fmt::print("{}", fmt::join(t, ", "));
    +// Output: 1, a
    +
    + +
    template <typename Range> +
    auto join(Range&& r, string_view sep) -⁠> join_view<decltype(detail::range_begin(r)), decltype(detail::range_end(r))>;
    +
    +
    +

    Returns a view that formats range with elements separated by sep.

    +

    Example:

    auto v = std::vector<int>{1, 2, 3};
    +fmt::print("{}", fmt::join(v, ", "));
    +// Output: 1, 2, 3
    +
    fmt::join applies passed format specifiers to the range elements:
    fmt::print("{:02}", fmt::join(v, ", "));
    +// Output: 01, 02, 03
    +

    +
    +
    +
    + +
    template <typename It, typename Sentinel> +
    auto join(It begin, Sentinel end, string_view sep) -⁠> join_view<It, Sentinel>;
    +
    +
    +

    Returns a view that formats the iterator range [begin, end) with elements separated by sep.

    +
    +
    +
    + +
    template <typename T> +
    auto join(std::initializer_list<T> list, string_view sep) -⁠> join_view<const T*, const T*>;
    +
    +
    +

    Returns an object that formats std::initializer_list with elements separated by sep.

    +

    Example:

    fmt::print("{}", fmt::join({1, 2, 3}, ", "));
    +// Output: "1, 2, 3"
    +

    +
    +
    +

    +

    Date and Time Formatting

    +

    fmt/chrono.h provides formatters for

    + +

    The format syntax is described in Chrono Format Specifications.

    +

    Example:

    +
    #include <fmt/chrono.h>
    +
    +int main() {
    +  std::time_t t = std::time(nullptr);
    +
    +  fmt::print("The date is {:%Y-%m-%d}.", fmt::localtime(t));
    +  // Output: The date is 2020-11-07.
    +  // (with 2020-11-07 replaced by the current date)
    +
    +  using namespace std::literals::chrono_literals;
    +
    +  fmt::print("Default format: {} {}\n", 42s, 100ms);
    +  // Output: Default format: 42s 100ms
    +
    +  fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
    +  // Output: strftime-like format: 03:15:30
    +}
    +
    + +
    auto localtime(std::time_t time) -⁠> std::tm;
    +
    +
    +

    Converts given time since epoch as std::time_t value into calendar time, expressed in local time. Unlike std::localtime, this function is thread-safe on most platforms.

    +
    +
    +
    + +
    auto gmtime(std::time_t time) -⁠> std::tm;
    +
    +
    +

    Converts given time since epoch as std::time_t value into calendar time, expressed in Coordinated Universal Time (UTC). Unlike std::gmtime, this function is thread-safe on most platforms.

    +
    +
    +

    +

    Standard Library Types Formatting

    +

    fmt/std.h provides formatters for:

    + + + +

    Formatting Variants

    +

    A std::variant is only formattable if every variant alternative is +formattable, and requires the __cpp_lib_variant library +feature.

    +

    Example:

    +
    #include <fmt/std.h>
    +
    +fmt::print("{}", std::variant<char, float>('x'));
    +// Output: variant('x')
    +
    +fmt::print("{}", std::variant<std::monostate, char>());
    +// Output: variant(monostate)
    +

    +

    Format String Compilation

    +

    fmt/compile.h provides format string compilation enabled via the +FMT_COMPILE macro or the _cf user-defined literal defined in +namespace fmt::literals. Format strings marked with FMT_COMPILE +or _cf are parsed, checked and converted into efficient formatting +code at compile-time. This supports arguments of built-in and string +types as well as user-defined types with format functions taking +the format context type as a template parameter in their formatter +specializations. For example:

    +
    template <> struct fmt::formatter<point> {
    +  constexpr auto parse(format_parse_context& ctx);
    +
    +  template <typename FormatContext>
    +  auto format(const point& p, FormatContext& ctx) const;
    +};
    +

    Format string compilation can generate more binary code compared to the +default API and is only recommended in places where formatting is a +performance bottleneck.

    +
    + +
    FMT_COMPILE(s)
    +
    +
    +

    Converts a string literal s into a format string that will be parsed at compile time and converted into efficient formatting code. Requires C++17 constexpr if compiler support.

    +

    Example:

    // Converts 42 into std::string using the most efficient method and no
    +// runtime format string processing.
    +std::string s = fmt::format(FMT_COMPILE("{}"), 42);
    +

    +
    +
    + +

    +

    Terminal Colors and Text Styles

    +

    fmt/color.h provides support for terminal color and text style output.

    +
    + +
    template <typename... T> +
    void print(const text_style& ts, format_string<T...> fmt, T&&... args);
    +
    +
    +

    Formats a string and prints it to stdout using ANSI escape sequences to specify text formatting.

    +

    Example:

    fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
    +           "Elapsed time: {0:.2f} seconds", 1.23);
    +

    +
    +
    +
    + +
    auto fg(detail::color_type foreground) -⁠> text_style;
    +
    +
    +

    Creates a text style from the foreground (text) color.

    +
    +
    +
    + +
    auto bg(detail::color_type background) -⁠> text_style;
    +
    +
    +

    Creates a text style from the background color.

    +
    +
    +
    + +
    template <typename T> +
    auto styled(const T& value, text_style ts) -⁠> detail::styled_arg<remove_cvref_t<T>>;
    +
    +
    +

    Returns an argument that will be formatted using ANSI escape sequences, to be used in a formatting function.

    +

    Example:

    fmt::print("Elapsed time: {0:.2f} seconds",
    +           fmt::styled(1.23, fmt::fg(fmt::color::green) |
    +                             fmt::bg(fmt::color::blue)));
    +

    +
    +
    +

    +

    System APIs

    +
    + +
    class ostream;
    +
    +
    +

    A fast output stream for writing from a single thread. Writing from multiple threads without external synchronization may result in a data race.

    +
    +
    void print(format_string<T...> fmt, T&&... args);
    +
    +

    Formats args according to specifications in fmt and writes the output to the file.

    +
    +
    +
    +
    +
    + +
    template <typename... Args> +
    std::system_error windows_error(int error_code, string_view message, const Args&... args);
    +
    +
    +

    Constructs a std::system_error object with the description of the form

    <message>: <system-message>
    +
    where <message> is the formatted message and <system-message> is the system message corresponding to the error code. error_code is a Windows error code as given by GetLastError. If error_code is not a valid error code such as -1, the system message will look like "error -1".

    +

    Example:

    // This throws a system_error with the description
    +//   cannot open file 'madeup': The system cannot find the file
    +
    specified. // or similar (system message may vary). const char *filename = "madeup"; LPOFSTRUCT of = LPOFSTRUCT(); HFILE file = OpenFile(filename, &of, OF_READ); if (file == HFILE_ERROR) { throw fmt::windows_error(GetLastError(), "cannot open file '{}'", filename); }

    +
    +
    +

    +

    std::ostream Support

    +

    fmt/ostream.h provides std::ostream support including formatting of +user-defined types that have an overloaded insertion operator +(operator<<). In order to make a type formattable via std::ostream +you should provide a formatter specialization inherited from +ostream_formatter:

    +
    #include <fmt/ostream.h>
    +
    +struct date {
    +  int year, month, day;
    +
    +  friend std::ostream& operator<<(std::ostream& os, const date& d) {
    +    return os << d.year << '-' << d.month << '-' << d.day;
    +  }
    +};
    +
    +template <> struct fmt::formatter<date> : ostream_formatter {};
    +
    +std::string s = fmt::format("The date is {}", date{2012, 12, 9});
    +// s == "The date is 2012-12-9"
    +
    + +
    template <typename T> +
    constexpr auto streamed(const T& value) -⁠> detail::streamed_view<T>;
    +
    +
    +

    Returns a view that formats value via an ostream operator<<.

    +

    Example:

    fmt::print("Current thread id: {}\n",
    +           fmt::streamed(std::this_thread::get_id()));
    +

    +
    +
    +
    + +
    template <typename... T> +
    void print(std::ostream& os, format_string<T...> fmt, T&&... args);
    +
    +
    +

    Prints formatted data to the stream os.

    +

    Example:

    fmt::print(cerr, "Don't {}!", "panic");
    +

    +
    +
    +

    +

    Dynamic Argument Lists

    +

    The header fmt/args.h provides dynamic_format_arg_store, a builder-like API +that can be used to construct format argument lists dynamically.

    +
    + +
    template <typename Context> +
    class dynamic_format_arg_store;
    +
    +
    +

    A dynamic list of formatting arguments with storage.

    +

    It can be implicitly converted into fmt::basic_format_args for passing into type-erased formatting functions such as fmt::vformat.

    +
    +
    void push_back(const T& arg);
    +
    +

    Adds an argument into the dynamic store for later passing to a formatting function.

    +

    Note that custom types and string types (but not string views) are copied into the store dynamically allocating memory if necessary.

    +

    Example:

    fmt::dynamic_format_arg_store<fmt::format_context> store;
    +store.push_back(42);
    +store.push_back("abc");
    +store.push_back(1.5f);
    +std::string result = fmt::vformat("{} and {} and {}", store);
    +

    +
    +
    +
    +
    void push_back(std::reference_wrapper<T> arg);
    +
    +

    Adds a reference to the argument into the dynamic store for later passing to a formatting function.

    +

    Example:

    fmt::dynamic_format_arg_store<fmt::format_context> store;
    +char band[] = "Rolling Stones";
    +store.push_back(std::cref(band));
    +band[9] = 'c'; // Changing str affects the output.
    +std::string result = fmt::vformat("{}", store);
    +// result == "Rolling Scones"
    +

    +
    +
    +
    +
    void push_back(const detail::named_arg<char_type, T>& arg);
    +
    +

    Adds named argument into the dynamic store for later passing to a formatting function. std::reference_wrapper is supported to avoid copying of the argument. The name is always copied into the store.

    +
    +
    +
    +
    void clear();
    +
    +

    Erase all elements from the store.

    +
    +
    +
    +
    void reserve(size_t new_cap, size_t new_cap_named);
    +
    +

    Reserves space to store at least new_cap arguments including new_cap_named named arguments.

    +
    +
    +
    +
    +

    +

    Safe printf

    +

    The header fmt/printf.h provides printf-like formatting +functionality. The following functions use printf format string +syntax +with the POSIX extension for positional arguments. Unlike their standard +counterparts, the fmt functions are type-safe and throw an exception +if an argument type doesn't match its format specification.

    +
    + +
    template <typename... T> +
    auto printf(string_view fmt, const T&... args) -⁠> int;
    +
    +
    +

    Formats args according to specifications in fmt and writes the output to stdout.

    +

    Example:

    +

    fmt::printf("Elapsed time: %.2f seconds", 1.23);

    +
    +
    +
    + +
    template <typename S, typename... T, typename Char> +
    auto fprintf(std::FILE* f, const S& fmt, const T&... args) -⁠> int;
    +
    +
    +

    Formats args according to specifications in fmt and writes the output to f.

    +

    Example:

    fmt::fprintf(stderr, "Don't %s!", "panic");
    +

    +
    +
    +
    + +
    template <typename S, typename... T, typename Char> +
    auto sprintf(const S& fmt, const T&... args) -⁠> std::basic_string<Char>;
    +
    +
    +

    Formats args according to specifications in fmt and returns the result as as string.

    +

    Example:

    std::string message = fmt::sprintf("The answer is %d", 42);
    +

    +
    +
    +

    +

    Wide Strings

    +

    The optional header fmt/xchar.h provides support for wchar_t and +exotic character types.

    +
    + +
    template <typename T> +
    struct is_char;
    +
    +
    +

    Specifies if T is a character type. Can be specialized by users.

    +
    +
    + + +
    + +
    template <typename T> +
    auto to_wstring(const T& value) -⁠> std::wstring;
    +
    +
    +

    Converts value to std::wstring using the default format for type T.

    +
    +
    +

    Compatibility with C++20 std::format

    +

    {fmt} implements nearly all of the C++20 formatting +library with the +following differences:

    +
      +
    • Names are defined in the fmt namespace instead of std to avoid + collisions with standard library implementations.
    • +
    • Width calculation doesn't use grapheme clusterization. The latter has + been implemented in a separate branch but hasn't been integrated yet.
    • +
    + + + + + + + + + + + + + +
    +
    + + + +
    + + + +
    + +
    + + +
    + +
    +
    +
    +
    + + + + + + + + + + + + + + \ No newline at end of file diff --git a/third_party/fmt-11.0.2/doc-html/assets/_mkdocstrings.css b/third_party/fmt-11.0.2/doc-html/assets/_mkdocstrings.css new file mode 100644 index 000000000..e69de29bb diff --git a/third_party/fmt-11.0.2/doc-html/assets/images/favicon.png b/third_party/fmt-11.0.2/doc-html/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js b/third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js new file mode 100644 index 000000000..32734cd37 --- /dev/null +++ b/third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Fi=Object.create;var gr=Object.defineProperty;var ji=Object.getOwnPropertyDescriptor;var Wi=Object.getOwnPropertyNames,Dt=Object.getOwnPropertySymbols,Ui=Object.getPrototypeOf,xr=Object.prototype.hasOwnProperty,no=Object.prototype.propertyIsEnumerable;var oo=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,R=(e,t)=>{for(var r in t||(t={}))xr.call(t,r)&&oo(e,r,t[r]);if(Dt)for(var r of Dt(t))no.call(t,r)&&oo(e,r,t[r]);return e};var io=(e,t)=>{var r={};for(var o in e)xr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Dt)for(var o of Dt(e))t.indexOf(o)<0&&no.call(e,o)&&(r[o]=e[o]);return r};var yr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Di=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Wi(t))!xr.call(e,n)&&n!==r&&gr(e,n,{get:()=>t[n],enumerable:!(o=ji(t,n))||o.enumerable});return e};var Vt=(e,t,r)=>(r=e!=null?Fi(Ui(e)):{},Di(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var ao=(e,t,r)=>new Promise((o,n)=>{var i=p=>{try{s(r.next(p))}catch(c){n(c)}},a=p=>{try{s(r.throw(p))}catch(c){n(c)}},s=p=>p.done?o(p.value):Promise.resolve(p.value).then(i,a);s((r=r.apply(e,t)).next())});var co=yr((Er,so)=>{(function(e,t){typeof Er=="object"&&typeof so!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Er,function(){"use strict";function e(r){var o=!0,n=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(H){return!!(H&&H!==document&&H.nodeName!=="HTML"&&H.nodeName!=="BODY"&&"classList"in H&&"contains"in H.classList)}function p(H){var mt=H.type,ze=H.tagName;return!!(ze==="INPUT"&&a[mt]&&!H.readOnly||ze==="TEXTAREA"&&!H.readOnly||H.isContentEditable)}function c(H){H.classList.contains("focus-visible")||(H.classList.add("focus-visible"),H.setAttribute("data-focus-visible-added",""))}function l(H){H.hasAttribute("data-focus-visible-added")&&(H.classList.remove("focus-visible"),H.removeAttribute("data-focus-visible-added"))}function f(H){H.metaKey||H.altKey||H.ctrlKey||(s(r.activeElement)&&c(r.activeElement),o=!0)}function u(H){o=!1}function h(H){s(H.target)&&(o||p(H.target))&&c(H.target)}function w(H){s(H.target)&&(H.target.classList.contains("focus-visible")||H.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(H.target))}function A(H){document.visibilityState==="hidden"&&(n&&(o=!0),te())}function te(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function ie(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(H){H.target.nodeName&&H.target.nodeName.toLowerCase()==="html"||(o=!1,ie())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",A,!0),te(),r.addEventListener("focus",h,!0),r.addEventListener("blur",w,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var Yr=yr((Rt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Rt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Rt=="object"?Rt.ClipboardJS=r():t.ClipboardJS=r()})(Rt,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Ii}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function u(V){try{return document.execCommand(V)}catch(_){return!1}}var h=function(_){var O=f()(_);return u("cut"),O},w=h;function A(V){var _=document.documentElement.getAttribute("dir")==="rtl",O=document.createElement("textarea");O.style.fontSize="12pt",O.style.border="0",O.style.padding="0",O.style.margin="0",O.style.position="absolute",O.style[_?"right":"left"]="-9999px";var j=window.pageYOffset||document.documentElement.scrollTop;return O.style.top="".concat(j,"px"),O.setAttribute("readonly",""),O.value=V,O}var te=function(_,O){var j=A(_);O.container.appendChild(j);var D=f()(j);return u("copy"),j.remove(),D},ie=function(_){var O=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},j="";return typeof _=="string"?j=te(_,O):_ instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(_==null?void 0:_.type)?j=te(_.value,O):(j=f()(_),u("copy")),j},J=ie;function H(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?H=function(O){return typeof O}:H=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},H(V)}var mt=function(){var _=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},O=_.action,j=O===void 0?"copy":O,D=_.container,Y=_.target,ke=_.text;if(j!=="copy"&&j!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(Y!==void 0)if(Y&&H(Y)==="object"&&Y.nodeType===1){if(j==="copy"&&Y.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(j==="cut"&&(Y.hasAttribute("readonly")||Y.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(ke)return J(ke,{container:D});if(Y)return j==="cut"?w(Y):J(Y,{container:D})},ze=mt;function Ie(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(O){return typeof O}:Ie=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},Ie(V)}function _i(V,_){if(!(V instanceof _))throw new TypeError("Cannot call a class as a function")}function ro(V,_){for(var O=0;O<_.length;O++){var j=_[O];j.enumerable=j.enumerable||!1,j.configurable=!0,"value"in j&&(j.writable=!0),Object.defineProperty(V,j.key,j)}}function Ai(V,_,O){return _&&ro(V.prototype,_),O&&ro(V,O),V}function Ci(V,_){if(typeof _!="function"&&_!==null)throw new TypeError("Super expression must either be null or a function");V.prototype=Object.create(_&&_.prototype,{constructor:{value:V,writable:!0,configurable:!0}}),_&&br(V,_)}function br(V,_){return br=Object.setPrototypeOf||function(j,D){return j.__proto__=D,j},br(V,_)}function Hi(V){var _=Pi();return function(){var j=Wt(V),D;if(_){var Y=Wt(this).constructor;D=Reflect.construct(j,arguments,Y)}else D=j.apply(this,arguments);return ki(this,D)}}function ki(V,_){return _&&(Ie(_)==="object"||typeof _=="function")?_:$i(V)}function $i(V){if(V===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return V}function Pi(){if(typeof Reflect=="undefined"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(V){return!1}}function Wt(V){return Wt=Object.setPrototypeOf?Object.getPrototypeOf:function(O){return O.__proto__||Object.getPrototypeOf(O)},Wt(V)}function vr(V,_){var O="data-clipboard-".concat(V);if(_.hasAttribute(O))return _.getAttribute(O)}var Ri=function(V){Ci(O,V);var _=Hi(O);function O(j,D){var Y;return _i(this,O),Y=_.call(this),Y.resolveOptions(D),Y.listenClick(j),Y}return Ai(O,[{key:"resolveOptions",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof D.action=="function"?D.action:this.defaultAction,this.target=typeof D.target=="function"?D.target:this.defaultTarget,this.text=typeof D.text=="function"?D.text:this.defaultText,this.container=Ie(D.container)==="object"?D.container:document.body}},{key:"listenClick",value:function(D){var Y=this;this.listener=c()(D,"click",function(ke){return Y.onClick(ke)})}},{key:"onClick",value:function(D){var Y=D.delegateTarget||D.currentTarget,ke=this.action(Y)||"copy",Ut=ze({action:ke,container:this.container,target:this.target(Y),text:this.text(Y)});this.emit(Ut?"success":"error",{action:ke,text:Ut,trigger:Y,clearSelection:function(){Y&&Y.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(D){return vr("action",D)}},{key:"defaultTarget",value:function(D){var Y=vr("target",D);if(Y)return document.querySelector(Y)}},{key:"defaultText",value:function(D){return vr("text",D)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(D){var Y=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(D,Y)}},{key:"cut",value:function(D){return w(D)}},{key:"isSupported",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],Y=typeof D=="string"?[D]:D,ke=!!document.queryCommandSupported;return Y.forEach(function(Ut){ke=ke&&!!document.queryCommandSupported(Ut)}),ke}}]),O}(s()),Ii=Ri},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==n;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}o.exports=a},438:function(o,n,i){var a=i(828);function s(l,f,u,h,w){var A=c.apply(this,arguments);return l.addEventListener(u,A,w),{destroy:function(){l.removeEventListener(u,A,w)}}}function p(l,f,u,h,w){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof u=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(A){return s(A,f,u,h,w)}))}function c(l,f,u,h){return function(w){w.delegateTarget=a(w.target,f),w.delegateTarget&&h.call(l,w)}}o.exports=p},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(o,n,i){var a=i(879),s=i(438);function p(u,h,w){if(!u&&!h&&!w)throw new Error("Missing required arguments");if(!a.string(h))throw new TypeError("Second argument must be a String");if(!a.fn(w))throw new TypeError("Third argument must be a Function");if(a.node(u))return c(u,h,w);if(a.nodeList(u))return l(u,h,w);if(a.string(u))return f(u,h,w);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(u,h,w){return u.addEventListener(h,w),{destroy:function(){u.removeEventListener(h,w)}}}function l(u,h,w){return Array.prototype.forEach.call(u,function(A){A.addEventListener(h,w)}),{destroy:function(){Array.prototype.forEach.call(u,function(A){A.removeEventListener(h,w)})}}}function f(u,h,w){return s(document.body,u,h,w)}o.exports=p},817:function(o){function n(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var ts=/["'&<>]/;ei.exports=rs;function rs(e){var t=""+e,r=ts.exec(t);if(!r)return t;var o,n="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function N(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],a;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(s){a={error:s}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(a)throw a.error}}return i}function q(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||s(u,h)})})}function s(u,h){try{p(o[u](h))}catch(w){f(i[0][3],w)}}function p(u){u.value instanceof nt?Promise.resolve(u.value.v).then(c,l):f(i[0][2],u)}function c(u){s("next",u)}function l(u){s("throw",u)}function f(u,h){u(h),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof de=="function"?de(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(a){return new Promise(function(s,p){a=e[i](a),n(s,p,a.done,a.value)})}}function n(i,a,s,p){Promise.resolve(p).then(function(c){i({value:c,done:s})},a)}}function k(e){return typeof e=="function"}function ft(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var zt=ft(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function qe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=de(a),p=s.next();!p.done;p=s.next()){var c=p.value;c.remove(this)}}catch(A){t={error:A}}finally{try{p&&!p.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var l=this.initialTeardown;if(k(l))try{l()}catch(A){i=A instanceof zt?A.errors:[A]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=de(f),h=u.next();!h.done;h=u.next()){var w=h.value;try{fo(w)}catch(A){i=i!=null?i:[],A instanceof zt?i=q(q([],N(i)),N(A.errors)):i.push(A)}}}catch(A){o={error:A}}finally{try{h&&!h.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new zt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)fo(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&qe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&qe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Tr=Fe.EMPTY;function qt(e){return e instanceof Fe||e&&"closed"in e&&k(e.remove)&&k(e.add)&&k(e.unsubscribe)}function fo(e){k(e)?e():e.unsubscribe()}var $e={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var ut={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,a=n.isStopped,s=n.observers;return i||a?Tr:(this.currentObservers=null,s.push(r),new Fe(function(){o.currentObservers=null,qe(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,a=o.isStopped;n?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,o){return new Eo(r,o)},t}(F);var Eo=function(e){re(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Tr},t}(g);var _r=function(e){re(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(g);var Lt={now:function(){return(Lt.delegate||Date).now()},delegate:void 0};var _t=function(e){re(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=Lt);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,a=o._infiniteTimeWindow,s=o._timestampProvider,p=o._windowTime;n||(i.push(r),!a&&i.push(s.now()+p)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,a=n._buffer,s=a.slice(),p=0;p0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(vt);var So=function(e){re(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(gt);var Hr=new So(To);var Oo=function(e){re(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=bt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var a=r.actions;o!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==o&&(bt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(vt);var Mo=function(e){re(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(gt);var me=new Mo(Oo);var M=new F(function(e){return e.complete()});function Yt(e){return e&&k(e.schedule)}function kr(e){return e[e.length-1]}function Xe(e){return k(kr(e))?e.pop():void 0}function He(e){return Yt(kr(e))?e.pop():void 0}function Bt(e,t){return typeof kr(e)=="number"?e.pop():t}var xt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Gt(e){return k(e==null?void 0:e.then)}function Jt(e){return k(e[ht])}function Xt(e){return Symbol.asyncIterator&&k(e==null?void 0:e[Symbol.asyncIterator])}function Zt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Gi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var er=Gi();function tr(e){return k(e==null?void 0:e[er])}function rr(e){return lo(this,arguments,function(){var r,o,n,i;return Nt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,nt(r.read())];case 3:return o=a.sent(),n=o.value,i=o.done,i?[4,nt(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,nt(n)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function or(e){return k(e==null?void 0:e.getReader)}function W(e){if(e instanceof F)return e;if(e!=null){if(Jt(e))return Ji(e);if(xt(e))return Xi(e);if(Gt(e))return Zi(e);if(Xt(e))return Lo(e);if(tr(e))return ea(e);if(or(e))return ta(e)}throw Zt(e)}function Ji(e){return new F(function(t){var r=e[ht]();if(k(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Xi(e){return new F(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?v(function(n,i){return e(n,i,o)}):le,Te(1),r?Be(t):zo(function(){return new ir}))}}function Fr(e){return e<=0?function(){return M}:y(function(t,r){var o=[];t.subscribe(T(r,function(n){o.push(n),e=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new g}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,p=s===void 0?!0:s;return function(c){var l,f,u,h=0,w=!1,A=!1,te=function(){f==null||f.unsubscribe(),f=void 0},ie=function(){te(),l=u=void 0,w=A=!1},J=function(){var H=l;ie(),H==null||H.unsubscribe()};return y(function(H,mt){h++,!A&&!w&&te();var ze=u=u!=null?u:r();mt.add(function(){h--,h===0&&!A&&!w&&(f=Wr(J,p))}),ze.subscribe(mt),!l&&h>0&&(l=new at({next:function(Ie){return ze.next(Ie)},error:function(Ie){A=!0,te(),f=Wr(ie,n,Ie),ze.error(Ie)},complete:function(){w=!0,te(),f=Wr(ie,a),ze.complete()}}),W(H).subscribe(l))})(c)}}function Wr(e,t){for(var r=[],o=2;oe.next(document)),e}function $(e,t=document){return Array.from(t.querySelectorAll(e))}function P(e,t=document){let r=fe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function fe(e,t=document){return t.querySelector(e)||void 0}function Re(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var xa=S(d(document.body,"focusin"),d(document.body,"focusout")).pipe(_e(1),Q(void 0),m(()=>Re()||document.body),B(1));function et(e){return xa.pipe(m(t=>e.contains(t)),K())}function kt(e,t){return C(()=>S(d(e,"mouseenter").pipe(m(()=>!0)),d(e,"mouseleave").pipe(m(()=>!1))).pipe(t?Ht(r=>Me(+!r*t)):le,Q(e.matches(":hover"))))}function Bo(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Bo(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)Bo(o,n);return o}function sr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function wt(e){let t=x("script",{src:e});return C(()=>(document.head.appendChild(t),S(d(t,"load"),d(t,"error").pipe(b(()=>$r(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),L(()=>document.head.removeChild(t)),Te(1))))}var Go=new g,ya=C(()=>typeof ResizeObserver=="undefined"?wt("https://unpkg.com/resize-observer-polyfill"):I(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>Go.next(t)))),b(e=>S(Ke,I(e)).pipe(L(()=>e.disconnect()))),B(1));function ce(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return ya.pipe(E(r=>r.observe(t)),b(r=>Go.pipe(v(o=>o.target===t),L(()=>r.unobserve(t)))),m(()=>ce(e)),Q(ce(e)))}function Tt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function Jo(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Ue(e){return{x:e.offsetLeft,y:e.offsetTop}}function Xo(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function Zo(e){return S(d(window,"load"),d(window,"resize")).pipe(Le(0,me),m(()=>Ue(e)),Q(Ue(e)))}function pr(e){return{x:e.scrollLeft,y:e.scrollTop}}function De(e){return S(d(e,"scroll"),d(window,"scroll"),d(window,"resize")).pipe(Le(0,me),m(()=>pr(e)),Q(pr(e)))}var en=new g,Ea=C(()=>I(new IntersectionObserver(e=>{for(let t of e)en.next(t)},{threshold:0}))).pipe(b(e=>S(Ke,I(e)).pipe(L(()=>e.disconnect()))),B(1));function tt(e){return Ea.pipe(E(t=>t.observe(e)),b(t=>en.pipe(v(({target:r})=>r===e),L(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function tn(e,t=16){return De(e).pipe(m(({y:r})=>{let o=ce(e),n=Tt(e);return r>=n.height-o.height-t}),K())}var lr={drawer:P("[data-md-toggle=drawer]"),search:P("[data-md-toggle=search]")};function rn(e){return lr[e].checked}function Je(e,t){lr[e].checked!==t&&lr[e].click()}function Ve(e){let t=lr[e];return d(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function wa(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ta(){return S(d(window,"compositionstart").pipe(m(()=>!0)),d(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function on(){let e=d(window,"keydown").pipe(v(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:rn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),v(({mode:t,type:r})=>{if(t==="global"){let o=Re();if(typeof o!="undefined")return!wa(o,r)}return!0}),pe());return Ta().pipe(b(t=>t?M:e))}function xe(){return new URL(location.href)}function pt(e,t=!1){if(G("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function nn(){return new g}function an(){return location.hash.slice(1)}function sn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Sa(e){return S(d(window,"hashchange"),e).pipe(m(an),Q(an()),v(t=>t.length>0),B(1))}function cn(e){return Sa(e).pipe(m(t=>fe(`[id="${t}"]`)),v(t=>typeof t!="undefined"))}function $t(e){let t=matchMedia(e);return ar(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function pn(){let e=matchMedia("print");return S(d(window,"beforeprint").pipe(m(()=>!0)),d(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function Nr(e,t){return e.pipe(b(r=>r?t():M))}function zr(e,t){return new F(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let a=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+a*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function Ne(e,t){return zr(e,t).pipe(b(r=>r.text()),m(r=>JSON.parse(r)),B(1))}function ln(e,t){let r=new DOMParser;return zr(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),B(1))}function mn(e,t){let r=new DOMParser;return zr(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),B(1))}function fn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function un(){return S(d(window,"scroll",{passive:!0}),d(window,"resize",{passive:!0})).pipe(m(fn),Q(fn()))}function dn(){return{width:innerWidth,height:innerHeight}}function hn(){return d(window,"resize",{passive:!0}).pipe(m(dn),Q(dn()))}function bn(){return z([un(),hn()]).pipe(m(([e,t])=>({offset:e,size:t})),B(1))}function mr(e,{viewport$:t,header$:r}){let o=t.pipe(Z("size")),n=z([o,r]).pipe(m(()=>Ue(e)));return z([r,t,n]).pipe(m(([{height:i},{offset:a,size:s},{x:p,y:c}])=>({offset:{x:a.x-p,y:a.y-c+i},size:s})))}function Oa(e){return d(e,"message",t=>t.data)}function Ma(e){let t=new g;return t.subscribe(r=>e.postMessage(r)),t}function vn(e,t=new Worker(e)){let r=Oa(t),o=Ma(t),n=new g;n.subscribe(o);let i=o.pipe(X(),ne(!0));return n.pipe(X(),Pe(r.pipe(U(i))),pe())}var La=P("#__config"),St=JSON.parse(La.textContent);St.base=`${new URL(St.base,xe())}`;function ye(){return St}function G(e){return St.features.includes(e)}function Ee(e,t){return typeof t!="undefined"?St.translations[e].replace("#",t.toString()):St.translations[e]}function Se(e,t=document){return P(`[data-md-component=${e}]`,t)}function ae(e,t=document){return $(`[data-md-component=${e}]`,t)}function _a(e){let t=P(".md-typeset > :first-child",e);return d(t,"click",{once:!0}).pipe(m(()=>P(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function gn(e){if(!G("announce.dismiss")||!e.childElementCount)return M;if(!e.hidden){let t=P(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return C(()=>{let t=new g;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),_a(e).pipe(E(r=>t.next(r)),L(()=>t.complete()),m(r=>R({ref:e},r)))})}function Aa(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function xn(e,t){let r=new g;return r.subscribe(({hidden:o})=>{e.hidden=o}),Aa(e,t).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))}function Pt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function yn(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function En(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Pt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Pt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function wn(e){return x("button",{class:"md-clipboard md-icon",title:Ee("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}function qr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(p=>!e.terms[p]).reduce((p,c)=>[...p,x("del",null,c)," "],[]).slice(0,-1),i=ye(),a=new URL(e.location,i.base);G("search.highlight")&&a.searchParams.set("h",Object.entries(e.terms).filter(([,p])=>p).reduce((p,[c])=>`${p} ${c}`.trim(),""));let{tags:s}=ye();return x("a",{href:`${a}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&e.tags.map(p=>{let c=s?p in s?`md-tag-icon md-tag--${s[p]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${c}`},p)}),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Ee("search.result.term.missing"),": ",...n)))}function Tn(e){let t=e[0].score,r=[...e],o=ye(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),a=r.findIndex(l=>l.scoreqr(l,1)),...p.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,p.length>0&&p.length===1?Ee("search.result.more.one"):Ee("search.result.more.other",p.length))),...p.map(l=>qr(l,1)))]:[]];return x("li",{class:"md-search-result__item"},c)}function Sn(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?sr(r):r)))}function Qr(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function On(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function Ca(e){var o;let t=ye(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function Mn(e,t){var o;let r=ye();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Ee("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map(Ca)))}var Ha=0;function ka(e){let t=z([et(e),kt(e)]).pipe(m(([o,n])=>o||n),K()),r=C(()=>Jo(e)).pipe(oe(De),ct(1),m(()=>Xo(e)));return t.pipe(Ae(o=>o),b(()=>z([t,r])),m(([o,n])=>({active:o,offset:n})),pe())}function $a(e,t){let{content$:r,viewport$:o}=t,n=`__tooltip2_${Ha++}`;return C(()=>{let i=new g,a=new _r(!1);i.pipe(X(),ne(!1)).subscribe(a);let s=a.pipe(Ht(c=>Me(+!c*250,Hr)),K(),b(c=>c?r:M),E(c=>c.id=n),pe());z([i.pipe(m(({active:c})=>c)),s.pipe(b(c=>kt(c,250)),Q(!1))]).pipe(m(c=>c.some(l=>l))).subscribe(a);let p=a.pipe(v(c=>c),ee(s,o),m(([c,l,{size:f}])=>{let u=e.getBoundingClientRect(),h=u.width/2;if(l.role==="tooltip")return{x:h,y:8+u.height};if(u.y>=f.height/2){let{height:w}=ce(l);return{x:h,y:-16-w}}else return{x:h,y:16+u.height}}));return z([s,i,p]).subscribe(([c,{offset:l},f])=>{c.style.setProperty("--md-tooltip-host-x",`${l.x}px`),c.style.setProperty("--md-tooltip-host-y",`${l.y}px`),c.style.setProperty("--md-tooltip-x",`${f.x}px`),c.style.setProperty("--md-tooltip-y",`${f.y}px`),c.classList.toggle("md-tooltip2--top",f.y<0),c.classList.toggle("md-tooltip2--bottom",f.y>=0)}),a.pipe(v(c=>c),ee(s,(c,l)=>l),v(c=>c.role==="tooltip")).subscribe(c=>{let l=ce(P(":scope > *",c));c.style.setProperty("--md-tooltip-width",`${l.width}px`),c.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(K(),be(me),ee(s)).subscribe(([c,l])=>{l.classList.toggle("md-tooltip2--active",c)}),z([a.pipe(v(c=>c)),s]).subscribe(([c,l])=>{l.role==="dialog"?(e.setAttribute("aria-controls",n),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",n)}),a.pipe(v(c=>!c)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),ka(e).pipe(E(c=>i.next(c)),L(()=>i.complete()),m(c=>R({ref:e},c)))})}function lt(e,{viewport$:t},r=document.body){return $a(e,{content$:new F(o=>{let n=e.title,i=yn(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t})}function Pa(e,t){let r=C(()=>z([Zo(e),De(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:a,height:s}=ce(e);return{x:o-i.x+a/2,y:n-i.y+s/2}}));return et(e).pipe(b(o=>r.pipe(m(n=>({active:o,offset:n})),Te(+!o||1/0))))}function Ln(e,t,{target$:r}){let[o,n]=Array.from(e.children);return C(()=>{let i=new g,a=i.pipe(X(),ne(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),tt(e).pipe(U(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),S(i.pipe(v(({active:s})=>s)),i.pipe(_e(250),v(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Le(16,me)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(ct(125,me),v(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),d(n,"click").pipe(U(a),v(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),d(n,"mousedown").pipe(U(a),ee(i)).subscribe(([s,{active:p}])=>{var c;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(p){s.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(c=Re())==null||c.blur()}}),r.pipe(U(a),v(s=>s===o),Ge(125)).subscribe(()=>e.focus()),Pa(e,t).pipe(E(s=>i.next(s)),L(()=>i.complete()),m(s=>R({ref:e},s)))})}function Ra(e){return e.tagName==="CODE"?$(".c, .c1, .cm",e):[e]}function Ia(e){let t=[];for(let r of Ra(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,p]=a;if(typeof p=="undefined"){let c=i.splitText(a.index);i=c.splitText(s.length),t.push(c)}else{i.textContent=s,t.push(i);break}}}}return t}function _n(e,t){t.append(...Array.from(e.childNodes))}function fr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,a=new Map;for(let s of Ia(t)){let[,p]=s.textContent.match(/\((\d+)\)/);fe(`:scope > li:nth-child(${p})`,e)&&(a.set(p,En(p,i)),s.replaceWith(a.get(p)))}return a.size===0?M:C(()=>{let s=new g,p=s.pipe(X(),ne(!0)),c=[];for(let[l,f]of a)c.push([P(".md-typeset",f),P(`:scope > li:nth-child(${l})`,e)]);return o.pipe(U(p)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of c)l?_n(f,u):_n(u,f)}),S(...[...a].map(([,l])=>Ln(l,t,{target$:r}))).pipe(L(()=>s.complete()),pe())})}function An(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return An(t)}}function Cn(e,t){return C(()=>{let r=An(e);return typeof r!="undefined"?fr(r,e,t):M})}var Hn=Vt(Yr());var Fa=0;function kn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return kn(t)}}function ja(e){return ge(e).pipe(m(({width:t})=>({scrollable:Tt(e).width>t})),Z("scrollable"))}function $n(e,t){let{matches:r}=matchMedia("(hover)"),o=C(()=>{let n=new g,i=n.pipe(Fr(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[];if(Hn.default.isSupported()&&(e.closest(".copy")||G("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${Fa++}`;let l=wn(c.id);c.insertBefore(l,e),G("content.tooltips")&&a.push(lt(l,{viewport$}))}let s=e.closest(".highlight");if(s instanceof HTMLElement){let c=kn(s);if(typeof c!="undefined"&&(s.classList.contains("annotate")||G("content.code.annotate"))){let l=fr(c,e,t);a.push(ge(s).pipe(U(i),m(({width:f,height:u})=>f&&u),K(),b(f=>f?l:M)))}}return $(":scope > span[id]",e).length&&e.classList.add("md-code__content"),ja(e).pipe(E(c=>n.next(c)),L(()=>n.complete()),m(c=>R({ref:e},c)),Pe(...a))});return G("content.lazy")?tt(e).pipe(v(n=>n),Te(1),b(()=>o)):o}function Wa(e,{target$:t,print$:r}){let o=!0;return S(t.pipe(m(n=>n.closest("details:not([open])")),v(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(v(n=>n||!o),E(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Pn(e,t){return C(()=>{let r=new g;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),Wa(e,t).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))})}var Rn=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel rect,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel rect{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var Br,Da=0;function Va(){return typeof mermaid=="undefined"||mermaid instanceof Element?wt("https://unpkg.com/mermaid@10/dist/mermaid.min.js"):I(void 0)}function In(e){return e.classList.remove("mermaid"),Br||(Br=Va().pipe(E(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Rn,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),B(1))),Br.subscribe(()=>ao(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${Da++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),a=r.attachShadow({mode:"closed"});a.innerHTML=n,e.replaceWith(r),i==null||i(a)})),Br.pipe(m(()=>({ref:e})))}var Fn=x("table");function jn(e){return e.replaceWith(Fn),Fn.replaceWith(On(e)),I({ref:e})}function Na(e){let t=e.find(r=>r.checked)||e[0];return S(...e.map(r=>d(r,"change").pipe(m(()=>P(`label[for="${r.id}"]`))))).pipe(Q(P(`label[for="${t.id}"]`)),m(r=>({active:r})))}function Wn(e,{viewport$:t,target$:r}){let o=P(".tabbed-labels",e),n=$(":scope > input",e),i=Qr("prev");e.append(i);let a=Qr("next");return e.append(a),C(()=>{let s=new g,p=s.pipe(X(),ne(!0));z([s,ge(e)]).pipe(U(p),Le(1,me)).subscribe({next([{active:c},l]){let f=Ue(c),{width:u}=ce(c);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let h=pr(o);(f.xh.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),z([De(o),ge(o)]).pipe(U(p)).subscribe(([c,l])=>{let f=Tt(o);i.hidden=c.x<16,a.hidden=c.x>f.width-l.width-16}),S(d(i,"click").pipe(m(()=>-1)),d(a,"click").pipe(m(()=>1))).pipe(U(p)).subscribe(c=>{let{width:l}=ce(o);o.scrollBy({left:l*c,behavior:"smooth"})}),r.pipe(U(p),v(c=>n.includes(c))).subscribe(c=>c.click()),o.classList.add("tabbed-labels--linked");for(let c of n){let l=P(`label[for="${c.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),d(l.firstElementChild,"click").pipe(U(p),v(f=>!(f.metaKey||f.ctrlKey)),E(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return G("content.tabs.link")&&s.pipe(Ce(1),ee(t)).subscribe(([{active:c},{offset:l}])=>{let f=c.innerText.trim();if(c.hasAttribute("data-md-switching"))c.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let w of $("[data-tabs]"))for(let A of $(":scope > input",w)){let te=P(`label[for="${A.id}"]`);if(te!==c&&te.innerText.trim()===f){te.setAttribute("data-md-switching",""),A.click();break}}window.scrollTo({top:e.offsetTop-u});let h=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...h])])}}),s.pipe(U(p)).subscribe(()=>{for(let c of $("audio, video",e))c.pause()}),tt(e).pipe(b(()=>Na(n)),E(c=>s.next(c)),L(()=>s.complete()),m(c=>R({ref:e},c)))}).pipe(Qe(se))}function Un(e,{viewport$:t,target$:r,print$:o}){return S(...$(".annotate:not(.highlight)",e).map(n=>Cn(n,{target$:r,print$:o})),...$("pre:not(.mermaid) > code",e).map(n=>$n(n,{target$:r,print$:o})),...$("pre.mermaid",e).map(n=>In(n)),...$("table:not([class])",e).map(n=>jn(n)),...$("details",e).map(n=>Pn(n,{target$:r,print$:o})),...$("[data-tabs]",e).map(n=>Wn(n,{viewport$:t,target$:r})),...$("[title]",e).filter(()=>G("content.tooltips")).map(n=>lt(n,{viewport$:t})))}function za(e,{alert$:t}){return t.pipe(b(r=>S(I(!0),I(!1).pipe(Ge(2e3))).pipe(m(o=>({message:r,active:o})))))}function Dn(e,t){let r=P(".md-typeset",e);return C(()=>{let o=new g;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),za(e,t).pipe(E(n=>o.next(n)),L(()=>o.complete()),m(n=>R({ref:e},n)))})}var qa=0;function Qa(e,t){document.body.append(e);let{width:r}=ce(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=cr(t),n=typeof o!="undefined"?De(o):I({x:0,y:0}),i=S(et(t),kt(t)).pipe(K());return z([i,n]).pipe(m(([a,s])=>{let{x:p,y:c}=Ue(t),l=ce(t),f=t.closest("table");return f&&t.parentElement&&(p+=f.offsetLeft+t.parentElement.offsetLeft,c+=f.offsetTop+t.parentElement.offsetTop),{active:a,offset:{x:p-s.x+l.width/2-r/2,y:c-s.y+l.height+8}}}))}function Vn(e){let t=e.title;if(!t.length)return M;let r=`__tooltip_${qa++}`,o=Pt(r,"inline"),n=P(".md-typeset",o);return n.innerHTML=t,C(()=>{let i=new g;return i.subscribe({next({offset:a}){o.style.setProperty("--md-tooltip-x",`${a.x}px`),o.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),S(i.pipe(v(({active:a})=>a)),i.pipe(_e(250),v(({active:a})=>!a))).subscribe({next({active:a}){a?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Le(16,me)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(ct(125,me),v(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?o.style.setProperty("--md-tooltip-0",`${-a}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Qa(o,e).pipe(E(a=>i.next(a)),L(()=>i.complete()),m(a=>R({ref:e},a)))}).pipe(Qe(se))}function Ka({viewport$:e}){if(!G("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Ye(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),K()),o=Ve("search");return z([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),K(),b(n=>n?r:I(!1)),Q(!1))}function Nn(e,t){return C(()=>z([ge(e),Ka(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),K((r,o)=>r.height===o.height&&r.hidden===o.hidden),B(1))}function zn(e,{header$:t,main$:r}){return C(()=>{let o=new g,n=o.pipe(X(),ne(!0));o.pipe(Z("active"),We(t)).subscribe(([{active:a},{hidden:s}])=>{e.classList.toggle("md-header--shadow",a&&!s),e.hidden=s});let i=ue($("[title]",e)).pipe(v(()=>G("content.tooltips")),oe(a=>Vn(a)));return r.subscribe(o),t.pipe(U(n),m(a=>R({ref:e},a)),Pe(i.pipe(U(n))))})}function Ya(e,{viewport$:t,header$:r}){return mr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=ce(e);return{active:o>=n}}),Z("active"))}function qn(e,t){return C(()=>{let r=new g;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=fe(".md-content h1");return typeof o=="undefined"?M:Ya(o,t).pipe(E(n=>r.next(n)),L(()=>r.complete()),m(n=>R({ref:e},n)))})}function Qn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),K()),n=o.pipe(b(()=>ge(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),Z("bottom"))));return z([o,n,t]).pipe(m(([i,{top:a,bottom:s},{offset:{y:p},size:{height:c}}])=>(c=Math.max(0,c-Math.max(0,a-p,i)-Math.max(0,c+p-s)),{offset:a-i,height:c,active:a-i<=p})),K((i,a)=>i.offset===a.offset&&i.height===a.height&&i.active===a.active))}function Ba(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return I(...e).pipe(oe(o=>d(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),B(1))}function Kn(e){let t=$("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=$t("(prefers-color-scheme: light)");return C(()=>{let i=new g;return i.subscribe(a=>{if(document.body.setAttribute("data-md-color-switching",""),a.color.media==="(prefers-color-scheme)"){let s=matchMedia("(prefers-color-scheme: light)"),p=document.querySelector(s.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");a.color.scheme=p.getAttribute("data-md-color-scheme"),a.color.primary=p.getAttribute("data-md-color-primary"),a.color.accent=p.getAttribute("data-md-color-accent")}for(let[s,p]of Object.entries(a.color))document.body.setAttribute(`data-md-color-${s}`,p);for(let s=0;sa.key==="Enter"),ee(i,(a,s)=>s)).subscribe(({index:a})=>{a=(a+1)%t.length,t[a].click(),t[a].focus()}),i.pipe(m(()=>{let a=Se("header"),s=window.getComputedStyle(a);return o.content=s.colorScheme,s.backgroundColor.match(/\d+/g).map(p=>(+p).toString(16).padStart(2,"0")).join("")})).subscribe(a=>r.content=`#${a}`),i.pipe(be(se)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),Ba(t).pipe(U(n.pipe(Ce(1))),st(),E(a=>i.next(a)),L(()=>i.complete()),m(a=>R({ref:e},a)))})}function Yn(e,{progress$:t}){return C(()=>{let r=new g;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(E(o=>r.next({value:o})),L(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Gr=Vt(Yr());function Ga(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Bn({alert$:e}){Gr.default.isSupported()&&new F(t=>{new Gr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||Ga(P(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(E(t=>{t.trigger.focus()}),m(()=>Ee("clipboard.copied"))).subscribe(e)}function Gn(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function Ja(e,t){let r=new Map;for(let o of $("url",e)){let n=P("loc",o),i=[Gn(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let a of $("[rel=alternate]",o)){let s=a.getAttribute("href");s!=null&&i.push(Gn(new URL(s),t))}}return r}function ur(e){return mn(new URL("sitemap.xml",e)).pipe(m(t=>Ja(t,new URL(e))),ve(()=>I(new Map)))}function Xa(e,t){if(!(e.target instanceof Element))return M;let r=e.target.closest("a");if(r===null)return M;if(r.target||e.metaKey||e.ctrlKey)return M;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),I(new URL(r.href))):M}function Jn(e){let t=new Map;for(let r of $(":scope > *",e.head))t.set(r.outerHTML,r);return t}function Xn(e){for(let t of $("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return I(e)}function Za(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...G("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=fe(o),i=fe(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=Jn(document);for(let[o,n]of Jn(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Se("container");return je($("script",r)).pipe(b(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new F(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),M}),X(),ne(document))}function Zn({location$:e,viewport$:t,progress$:r}){let o=ye();if(location.protocol==="file:")return M;let n=ur(o.base);I(document).subscribe(Xn);let i=d(document.body,"click").pipe(We(n),b(([p,c])=>Xa(p,c)),pe()),a=d(window,"popstate").pipe(m(xe),pe());i.pipe(ee(t)).subscribe(([p,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",p)}),S(i,a).subscribe(e);let s=e.pipe(Z("pathname"),b(p=>ln(p,{progress$:r}).pipe(ve(()=>(pt(p,!0),M)))),b(Xn),b(Za),pe());return S(s.pipe(ee(e,(p,c)=>c)),s.pipe(b(()=>e),Z("pathname"),b(()=>e),Z("hash")),e.pipe(K((p,c)=>p.pathname===c.pathname&&p.hash===c.hash),b(()=>i),E(()=>history.back()))).subscribe(p=>{var c,l;history.state!==null||!p.hash?window.scrollTo(0,(l=(c=history.state)==null?void 0:c.y)!=null?l:0):(history.scrollRestoration="auto",sn(p.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),d(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(Z("offset"),_e(100)).subscribe(({offset:p})=>{history.replaceState(p,"")}),s}var ri=Vt(ti());function oi(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,a)=>`${i}${a}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return a=>(0,ri.default)(a).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function It(e){return e.type===1}function dr(e){return e.type===3}function ni(e,t){let r=vn(e);return S(I(location.protocol!=="file:"),Ve("search")).pipe(Ae(o=>o),b(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:G("search.suggest")}}})),r}function ii({document$:e}){let t=ye(),r=Ne(new URL("../versions.json",t.base)).pipe(ve(()=>M)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:a,aliases:s})=>a===i||s.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),b(n=>d(document.body,"click").pipe(v(i=>!i.metaKey&&!i.ctrlKey),ee(o),b(([i,a])=>{if(i.target instanceof Element){let s=i.target.closest("a");if(s&&!s.target&&n.has(s.href)){let p=s.href;return!i.target.closest(".md-version")&&n.get(p)===a?M:(i.preventDefault(),I(p))}}return M}),b(i=>ur(new URL(i)).pipe(m(a=>{let p=xe().href.replace(t.base,i);return a.has(p.split("#")[0])?new URL(p):new URL(i)})))))).subscribe(n=>pt(n,!0)),z([r,o]).subscribe(([n,i])=>{P(".md-header__topic").appendChild(Mn(n,i))}),e.pipe(b(()=>o)).subscribe(n=>{var a;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let s=((a=t.version)==null?void 0:a.default)||"latest";Array.isArray(s)||(s=[s]);e:for(let p of s)for(let c of n.aliases.concat(n.version))if(new RegExp(p,"i").test(c)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let s of ae("outdated"))s.hidden=!1})}function ns(e,{worker$:t}){let{searchParams:r}=xe();r.has("q")&&(Je("search",!0),e.value=r.get("q"),e.focus(),Ve("search").pipe(Ae(i=>!i)).subscribe(()=>{let i=xe();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=et(e),n=S(t.pipe(Ae(It)),d(e,"keyup"),o).pipe(m(()=>e.value),K());return z([n,o]).pipe(m(([i,a])=>({value:i,focus:a})),B(1))}function ai(e,{worker$:t}){let r=new g,o=r.pipe(X(),ne(!0));z([t.pipe(Ae(It)),r],(i,a)=>a).pipe(Z("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(Z("focus")).subscribe(({focus:i})=>{i&&Je("search",i)}),d(e.form,"reset").pipe(U(o)).subscribe(()=>e.focus());let n=P("header [for=__search]");return d(n,"click").subscribe(()=>e.focus()),ns(e,{worker$:t}).pipe(E(i=>r.next(i)),L(()=>r.complete()),m(i=>R({ref:e},i)),B(1))}function si(e,{worker$:t,query$:r}){let o=new g,n=tn(e.parentElement).pipe(v(Boolean)),i=e.parentElement,a=P(":scope > :first-child",e),s=P(":scope > :last-child",e);Ve("search").subscribe(l=>s.setAttribute("role",l?"list":"presentation")),o.pipe(ee(r),Ur(t.pipe(Ae(It)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:a.textContent=f.length?Ee("search.result.none"):Ee("search.result.placeholder");break;case 1:a.textContent=Ee("search.result.one");break;default:let u=sr(l.length);a.textContent=Ee("search.result.other",u)}});let p=o.pipe(E(()=>s.innerHTML=""),b(({items:l})=>S(I(...l.slice(0,10)),I(...l.slice(10)).pipe(Ye(4),Vr(n),b(([f])=>f)))),m(Tn),pe());return p.subscribe(l=>s.appendChild(l)),p.pipe(oe(l=>{let f=fe("details",l);return typeof f=="undefined"?M:d(f,"toggle").pipe(U(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(v(dr),m(({data:l})=>l)).pipe(E(l=>o.next(l)),L(()=>o.complete()),m(l=>R({ref:e},l)))}function is(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=xe();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function ci(e,t){let r=new g,o=r.pipe(X(),ne(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),d(e,"click").pipe(U(o)).subscribe(n=>n.preventDefault()),is(e,t).pipe(E(n=>r.next(n)),L(()=>r.complete()),m(n=>R({ref:e},n)))}function pi(e,{worker$:t,keyboard$:r}){let o=new g,n=Se("search-query"),i=S(d(n,"keydown"),d(n,"focus")).pipe(be(se),m(()=>n.value),K());return o.pipe(We(i),m(([{suggest:s},p])=>{let c=p.split(/([\s-]+)/);if(s!=null&&s.length&&c[c.length-1]){let l=s[s.length-1];l.startsWith(c[c.length-1])&&(c[c.length-1]=l)}else c.length=0;return c})).subscribe(s=>e.innerHTML=s.join("").replace(/\s/g," ")),r.pipe(v(({mode:s})=>s==="search")).subscribe(s=>{switch(s.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(v(dr),m(({data:s})=>s)).pipe(E(s=>o.next(s)),L(()=>o.complete()),m(()=>({ref:e})))}function li(e,{index$:t,keyboard$:r}){let o=ye();try{let n=ni(o.search,t),i=Se("search-query",e),a=Se("search-result",e);d(e,"click").pipe(v(({target:p})=>p instanceof Element&&!!p.closest("a"))).subscribe(()=>Je("search",!1)),r.pipe(v(({mode:p})=>p==="search")).subscribe(p=>{let c=Re();switch(p.type){case"Enter":if(c===i){let l=new Map;for(let f of $(":first-child [href]",a)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,h])=>h-u);f.click()}p.claim()}break;case"Escape":case"Tab":Je("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof c=="undefined")i.focus();else{let l=[i,...$(":not(details) > [href], summary, details[open] [href]",a)],f=Math.max(0,(Math.max(0,l.indexOf(c))+l.length+(p.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}p.claim();break;default:i!==Re()&&i.focus()}}),r.pipe(v(({mode:p})=>p==="global")).subscribe(p=>{switch(p.type){case"f":case"s":case"/":i.focus(),i.select(),p.claim();break}});let s=ai(i,{worker$:n});return S(s,si(a,{worker$:n,query$:s})).pipe(Pe(...ae("search-share",e).map(p=>ci(p,{query$:s})),...ae("search-suggest",e).map(p=>pi(p,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,Ke}}function mi(e,{index$:t,location$:r}){return z([t,r.pipe(Q(xe()),v(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>oi(o.config)(n.searchParams.get("h"))),m(o=>{var a;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let s=i.nextNode();s;s=i.nextNode())if((a=s.parentElement)!=null&&a.offsetHeight){let p=s.textContent,c=o(p);c.length>p.length&&n.set(s,c)}for(let[s,p]of n){let{childNodes:c}=x("span",null,p);s.replaceWith(...Array.from(c))}return{ref:e,nodes:n}}))}function as(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return z([r,t]).pipe(m(([{offset:i,height:a},{offset:{y:s}}])=>(a=a+Math.min(n,Math.max(0,s-i))-n,{height:a,locked:s>=i+n})),K((i,a)=>i.height===a.height&&i.locked===a.locked))}function Jr(e,o){var n=o,{header$:t}=n,r=io(n,["header$"]);let i=P(".md-sidebar__scrollwrap",e),{y:a}=Ue(i);return C(()=>{let s=new g,p=s.pipe(X(),ne(!0)),c=s.pipe(Le(0,me));return c.pipe(ee(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*a}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),c.pipe(Ae()).subscribe(()=>{for(let l of $(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:h}=ce(f);f.scrollTo({top:u-h/2})}}}),ue($("label[tabindex]",e)).pipe(oe(l=>d(l,"click").pipe(be(se),m(()=>l),U(p)))).subscribe(l=>{let f=P(`[id="${l.htmlFor}"]`);P(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),as(e,r).pipe(E(l=>s.next(l)),L(()=>s.complete()),m(l=>R({ref:e},l)))})}function fi(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return Ct(Ne(`${r}/releases/latest`).pipe(ve(()=>M),m(o=>({version:o.tag_name})),Be({})),Ne(r).pipe(ve(()=>M),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),Be({}))).pipe(m(([o,n])=>R(R({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return Ne(r).pipe(m(o=>({repositories:o.public_repos})),Be({}))}}function ui(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return Ne(r).pipe(ve(()=>M),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),Be({}))}function di(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return fi(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return ui(r,o)}return M}var ss;function cs(e){return ss||(ss=C(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(ae("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return M}return di(e.href).pipe(E(o=>__md_set("__source",o,sessionStorage)))}).pipe(ve(()=>M),v(t=>Object.keys(t).length>0),m(t=>({facts:t})),B(1)))}function hi(e){let t=P(":scope > :last-child",e);return C(()=>{let r=new g;return r.subscribe(({facts:o})=>{t.appendChild(Sn(o)),t.classList.add("md-source__repository--active")}),cs(e).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))})}function ps(e,{viewport$:t,header$:r}){return ge(document.body).pipe(b(()=>mr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),Z("hidden"))}function bi(e,t){return C(()=>{let r=new g;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(G("navigation.tabs.sticky")?I({hidden:!1}):ps(e,t)).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))})}function ls(e,{viewport$:t,header$:r}){let o=new Map,n=$(".md-nav__link",e);for(let s of n){let p=decodeURIComponent(s.hash.substring(1)),c=fe(`[id="${p}"]`);typeof c!="undefined"&&o.set(s,c)}let i=r.pipe(Z("height"),m(({height:s})=>{let p=Se("main"),c=P(":scope > :first-child",p);return s+.8*(c.offsetTop-p.offsetTop)}),pe());return ge(document.body).pipe(Z("height"),b(s=>C(()=>{let p=[];return I([...o].reduce((c,[l,f])=>{for(;p.length&&o.get(p[p.length-1]).tagName>=f.tagName;)p.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let h=f.offsetParent;for(;h;h=h.offsetParent)u+=h.offsetTop;return c.set([...p=[...p,l]].reverse(),u)},new Map))}).pipe(m(p=>new Map([...p].sort(([,c],[,l])=>c-l))),We(i),b(([p,c])=>t.pipe(jr(([l,f],{offset:{y:u},size:h})=>{let w=u+h.height>=Math.floor(s.height);for(;f.length;){let[,A]=f[0];if(A-c=u&&!w)f=[l.pop(),...f];else break}return[l,f]},[[],[...p]]),K((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([s,p])=>({prev:s.map(([c])=>c),next:p.map(([c])=>c)})),Q({prev:[],next:[]}),Ye(2,1),m(([s,p])=>s.prev.length{let i=new g,a=i.pipe(X(),ne(!0));if(i.subscribe(({prev:s,next:p})=>{for(let[c]of p)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[l]]of s.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",c===s.length-1)}),G("toc.follow")){let s=S(t.pipe(_e(1),m(()=>{})),t.pipe(_e(250),m(()=>"smooth")));i.pipe(v(({prev:p})=>p.length>0),We(o.pipe(be(se))),ee(s)).subscribe(([[{prev:p}],c])=>{let[l]=p[p.length-1];if(l.offsetHeight){let f=cr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:h}=ce(f);f.scrollTo({top:u-h/2,behavior:c})}}})}return G("navigation.tracking")&&t.pipe(U(a),Z("offset"),_e(250),Ce(1),U(n.pipe(Ce(1))),st({delay:250}),ee(i)).subscribe(([,{prev:s}])=>{let p=xe(),c=s[s.length-1];if(c&&c.length){let[l]=c,{hash:f}=new URL(l.href);p.hash!==f&&(p.hash=f,history.replaceState({},"",`${p}`))}else p.hash="",history.replaceState({},"",`${p}`)}),ls(e,{viewport$:t,header$:r}).pipe(E(s=>i.next(s)),L(()=>i.complete()),m(s=>R({ref:e},s)))})}function ms(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:a}})=>a),Ye(2,1),m(([a,s])=>a>s&&s>0),K()),i=r.pipe(m(({active:a})=>a));return z([i,n]).pipe(m(([a,s])=>!(a&&s)),K(),U(o.pipe(Ce(1))),ne(!0),st({delay:250}),m(a=>({hidden:a})))}function gi(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new g,a=i.pipe(X(),ne(!0));return i.subscribe({next({hidden:s}){e.hidden=s,s?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(U(a),Z("height")).subscribe(({height:s})=>{e.style.top=`${s+16}px`}),d(e,"click").subscribe(s=>{s.preventDefault(),window.scrollTo({top:0})}),ms(e,{viewport$:t,main$:o,target$:n}).pipe(E(s=>i.next(s)),L(()=>i.complete()),m(s=>R({ref:e},s)))}function xi({document$:e,viewport$:t}){e.pipe(b(()=>$(".md-ellipsis")),oe(r=>tt(r).pipe(U(e.pipe(Ce(1))),v(o=>o),m(()=>r),Te(1))),v(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,lt(n,{viewport$:t}).pipe(U(e.pipe(Ce(1))),L(()=>n.removeAttribute("title")))})).subscribe(),e.pipe(b(()=>$(".md-status")),oe(r=>lt(r,{viewport$:t}))).subscribe()}function yi({document$:e,tablet$:t}){e.pipe(b(()=>$(".md-toggle--indeterminate")),E(r=>{r.indeterminate=!0,r.checked=!1}),oe(r=>d(r,"change").pipe(Dr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),ee(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function fs(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Ei({document$:e}){e.pipe(b(()=>$("[data-md-scrollfix]")),E(t=>t.removeAttribute("data-md-scrollfix")),v(fs),oe(t=>d(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function wi({viewport$:e,tablet$:t}){z([Ve("search"),t]).pipe(m(([r,o])=>r&&!o),b(r=>I(r).pipe(Ge(r?400:100))),ee(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function us(){return location.protocol==="file:"?wt(`${new URL("search/search_index.js",Xr.base)}`).pipe(m(()=>__index),B(1)):Ne(new URL("search/search_index.json",Xr.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ot=Yo(),jt=nn(),Ot=cn(jt),Zr=on(),Oe=bn(),hr=$t("(min-width: 960px)"),Si=$t("(min-width: 1220px)"),Oi=pn(),Xr=ye(),Mi=document.forms.namedItem("search")?us():Ke,eo=new g;Bn({alert$:eo});var to=new g;G("navigation.instant")&&Zn({location$:jt,viewport$:Oe,progress$:to}).subscribe(ot);var Ti;((Ti=Xr.version)==null?void 0:Ti.provider)==="mike"&&ii({document$:ot});S(jt,Ot).pipe(Ge(125)).subscribe(()=>{Je("drawer",!1),Je("search",!1)});Zr.pipe(v(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=fe("link[rel=prev]");typeof t!="undefined"&&pt(t);break;case"n":case".":let r=fe("link[rel=next]");typeof r!="undefined"&&pt(r);break;case"Enter":let o=Re();o instanceof HTMLLabelElement&&o.click()}});xi({viewport$:Oe,document$:ot});yi({document$:ot,tablet$:hr});Ei({document$:ot});wi({viewport$:Oe,tablet$:hr});var rt=Nn(Se("header"),{viewport$:Oe}),Ft=ot.pipe(m(()=>Se("main")),b(e=>Qn(e,{viewport$:Oe,header$:rt})),B(1)),ds=S(...ae("consent").map(e=>xn(e,{target$:Ot})),...ae("dialog").map(e=>Dn(e,{alert$:eo})),...ae("header").map(e=>zn(e,{viewport$:Oe,header$:rt,main$:Ft})),...ae("palette").map(e=>Kn(e)),...ae("progress").map(e=>Yn(e,{progress$:to})),...ae("search").map(e=>li(e,{index$:Mi,keyboard$:Zr})),...ae("source").map(e=>hi(e))),hs=C(()=>S(...ae("announce").map(e=>gn(e)),...ae("content").map(e=>Un(e,{viewport$:Oe,target$:Ot,print$:Oi})),...ae("content").map(e=>G("search.highlight")?mi(e,{index$:Mi,location$:jt}):M),...ae("header-title").map(e=>qn(e,{viewport$:Oe,header$:rt})),...ae("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Nr(Si,()=>Jr(e,{viewport$:Oe,header$:rt,main$:Ft})):Nr(hr,()=>Jr(e,{viewport$:Oe,header$:rt,main$:Ft}))),...ae("tabs").map(e=>bi(e,{viewport$:Oe,header$:rt})),...ae("toc").map(e=>vi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Ot})),...ae("top").map(e=>gi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Ot})))),Li=ot.pipe(b(()=>hs),Pe(ds),B(1));Li.subscribe();window.document$=ot;window.location$=jt;window.target$=Ot;window.keyboard$=Zr;window.viewport$=Oe;window.tablet$=hr;window.screen$=Si;window.print$=Oi;window.alert$=eo;window.progress$=to;window.component$=Li;})(); +//# sourceMappingURL=bundle.081f42fc.min.js.map + diff --git a/third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js.map b/third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js.map new file mode 100644 index 000000000..e055db5ac --- /dev/null +++ b/third_party/fmt-11.0.2/doc-html/assets/javascripts/bundle.081f42fc.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/clipboard/dist/clipboard.js", "node_modules/escape-html/index.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/rxjs/node_modules/tslib/tslib.es6.js", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/BehaviorSubject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/QueueAction.ts", "node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts", "node_modules/rxjs/src/internal/scheduler/queue.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounce.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip2/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*\n * Copyright (c) 2016-2024 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ viewport$, document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject\n */\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n *\n * @class BehaviorSubject\n */\nexport class BehaviorSubject extends Subject {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction extends AsyncAction {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n", "import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n", "import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * Put every next task on a queue, instead of executing it immediately\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
    \n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an