| 252 | } |
| 253 | |
| 254 | bool TextStreamPlugin::continueDataModelStreaming( |
| 255 | const std::string& buffer, |
| 256 | std::vector<ProtocolStreamExtractor::ParseResult>& outResults, |
| 257 | size_t& outEndPosition) { |
| 258 | |
| 259 | // 1. Check whether the complete JSON is closed |
| 260 | size_t jsonStart = 0; |
| 261 | while (jsonStart < buffer.length()) { |
| 262 | char c = buffer[jsonStart]; |
| 263 | if (c != ' ' && c != '\n' && c != '\r' && c != '\t') { |
| 264 | break; |
| 265 | } |
| 266 | jsonStart++; |
| 267 | } |
| 268 | |
| 269 | if (jsonStart < buffer.length() && buffer[jsonStart] == '{') { |
| 270 | size_t endPos = 0; |
| 271 | if (ProtocolStreamExtractor::isJsonObjectComplete(buffer, jsonStart, endPos)) { |
| 272 | // JSON is complete; send the final appendDataModel delta for each entry |
| 273 | for (auto& entry : _streamingEntries) { |
| 274 | size_t closePos = 0; |
| 275 | if (!isStringValueClosed(buffer, entry.leafValueStart, closePos)) { |
| 276 | continue; |
| 277 | } |
| 278 | std::string delta = extractDelta(buffer, entry.lastSentEnd, closePos); |
| 279 | |
| 280 | if (!delta.empty()) { |
| 281 | std::string eventJson = buildAppendDataModelJson(entry, delta); |
| 282 | if (!eventJson.empty()) { |
| 283 | ProtocolStreamExtractor::ParseResult result; |
| 284 | result.type = ProtocolStreamExtractor::ParseResult::Type::NormalEvent; |
| 285 | result.eventType = ProtocolStreamExtractor::EventType::AppendDataModel; |
| 286 | result.eventJson = eventJson; |
| 287 | outResults.emplace_back(std::move(result)); |
| 288 | } |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | // Build the set of actively streamed binding paths |
| 293 | std::set<std::string> activeStreamingPaths; |
| 294 | for (const auto& entry : _streamingEntries) { |
| 295 | activeStreamingPaths.insert(entry.bindingPath); |
| 296 | } |
| 297 | |
| 298 | // Parse the complete JSON and dispatch non-streaming leaf fields |
| 299 | { |
| 300 | std::string eventJsonStr = buffer.substr(jsonStart, endPos - jsonStart + 1); |
| 301 | nlohmann::json fullEvent = nlohmann::json::parse(eventJsonStr, nullptr, false); |
| 302 | if (!fullEvent.is_discarded() && fullEvent.contains("updateDataModel")) { |
| 303 | auto& udm = fullEvent["updateDataModel"]; |
| 304 | if (udm.contains("value") && udm.contains("surfaceId")) { |
| 305 | nlohmann::json value = udm["value"]; |
| 306 | std::string sid = udm["surfaceId"].get<std::string>(); |
| 307 | std::string ePath = udm.contains("path") |
| 308 | ? udm["path"].get<std::string>() : "/"; |
| 309 | std::string basePath = (ePath == "/") ? "" : ePath; |
| 310 | |
| 311 | dispatchLeafFieldEvents(value, sid, basePath, |
no test coverage detected