66
77#pragma once
88
9+ #include < charconv>
910#include < string>
1011#include < string_view>
1112#include < vector>
1213#include < functional>
1314#include < exception>
15+ #include < system_error>
1416#include < unordered_map>
17+ #include < utility>
1518
1619#include < nlohmann/json.hpp>
1720
@@ -47,37 +50,79 @@ namespace foundry_local::detail {
4750 return core->call (command, logger, &payload, callback, userData);
4851 }
4952
53+ inline bool TryParseFloatToken (std::string_view token, float & value) {
54+ if (token.empty ()) {
55+ return false ;
56+ }
57+
58+ const auto * begin = token.data ();
59+ const auto * end = begin + token.size ();
60+ const auto result = std::from_chars (begin, end, value);
61+ return result.ec == std::errc{} && result.ptr == end;
62+ }
63+
64+ inline bool TryParseDoubleToken (std::string_view token, double & value) {
65+ if (token.empty ()) {
66+ return false ;
67+ }
68+
69+ const auto * begin = token.data ();
70+ const auto * end = begin + token.size ();
71+ const auto result = std::from_chars (begin, end, value);
72+ return result.ec == std::errc{} && result.ptr == end;
73+ }
74+
5075 // Serialize + call with a streaming chunk handler.
5176 // Wraps the caller-supplied onChunk with the native callback boilerplate
5277 // (null/length checks, exception capture, rethrow after the call).
5378 // The errorContext string is used to prefix any core-layer error message.
5479 inline CoreResponse CallWithStreamingCallback (Internal::IFoundryLocalCore* core, std::string_view command,
55- const std::string& payload, ILogger& logger,
56- const std::function<void (const std::string&)>& onChunk,
57- std::string_view errorContext) {
80+ const std::string* payload, ILogger& logger,
81+ const std::function<void (const std::string&)>& onChunk,
82+ std::string_view errorContext,
83+ CancellationCallback isCancellationRequested = nullptr) {
5884 struct State {
5985 const std::function<void (const std::string&)>* cb;
86+ CancellationCallback isCancellationRequested;
87+ bool cancellationObserved = false ;
6088 std::exception_ptr exception;
61- } state{&onChunk, nullptr };
62-
63- auto nativeCallback = [](void * data, int32_t len, void * user) {
64- if (!data || len <= 0 )
65- return ;
89+ } state{&onChunk, std::move (isCancellationRequested), false , nullptr };
6690
91+ auto nativeCallback = [](const void * data, int32_t len, void * user) -> int32_t {
6792 auto * st = static_cast <State*>(user);
68- if (st->exception )
69- return ;
93+ if (!st) {
94+ return 0 ;
95+ }
96+
97+ if (st->exception || st->cancellationObserved ) {
98+ return 1 ;
99+ }
100+
101+ if (!data || len <= 0 )
102+ return 0 ;
70103
71104 try {
105+ if (st->isCancellationRequested && st->isCancellationRequested ()) {
106+ st->cancellationObserved = true ;
107+ return 1 ;
108+ }
109+
72110 std::string chunk (static_cast <const char *>(data), static_cast <size_t >(len));
73111 (*(st->cb ))(chunk);
74112 }
75113 catch (...) {
76114 st->exception = std::current_exception ();
115+ return 1 ;
77116 }
117+
118+ return 0 ;
78119 };
79120
80- auto response = core->call (command, logger, &payload, +nativeCallback, &state);
121+ auto response = core->call (command, logger, payload, +nativeCallback, &state);
122+ if (state.cancellationObserved ) {
123+ throw Exception (" Operation cancelled" , logger);
124+ }
125+
81126 if (response.HasError ()) {
82127 throw Exception (std::string (errorContext) + response.error , logger);
83128 }
@@ -89,6 +134,15 @@ namespace foundry_local::detail {
89134 return response;
90135 }
91136
137+ inline CoreResponse CallWithStreamingCallback (Internal::IFoundryLocalCore* core, std::string_view command,
138+ const std::string& payload, ILogger& logger,
139+ const std::function<void (const std::string&)>& onChunk,
140+ std::string_view errorContext,
141+ CancellationCallback isCancellationRequested = nullptr) {
142+ return CallWithStreamingCallback (core, command, &payload, logger, onChunk, errorContext,
143+ std::move (isCancellationRequested));
144+ }
145+
92146 // Overload: allow Params object directly
93147 inline CoreResponse CallWithParams (Internal::IFoundryLocalCore* core, std::string_view command,
94148 const nlohmann::json& params, ILogger& logger) {
0 commit comments