diff --git a/CMakeLists.txt b/CMakeLists.txt index f30add7c..4d317e56 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 26a9222f..4bda7b53 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 3eac60a5..2e0543de 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 010e7e68..74c5d5b0 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 217d17e3..e5c8a501 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 00000000..4a5967a5 --- /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 00000000..70380a92 --- /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 d45ac45a..daa05915 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 6c233e20..c2057b7a 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 b07cae28..e09ccdb7 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 00000000..4aa3d3f0 --- /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 00000000..1a9cfeed --- /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