#pragma once #include "../vendor/json.hpp" #include "platform.h" #include namespace ks { using DiagnosticJson = nlohmann::json; struct OperationLogRow { std::wstring time, process, command, source, target, outcome, details; bool problem = true; }; inline std::vector parseOperationLog(const std::wstring &contents) { std::vector rows; std::wistringstream stream(contents); std::wstring line; OperationLogRow *legacy = nullptr; while (std::getline(stream, line)) { if (!line.empty() && line.back() == L'\r') line.pop_back(); if (line.empty()) continue; auto marker = line.find(L" Operation {"); if (marker != line.npos) { try { auto j = DiagnosticJson::parse(utf8(line.substr(marker + 11))); auto field = [&](const char *key) { return wide(j.value(key, std::string{})); }; OperationLogRow row{line.substr(0, marker), field("process"), field("command"), field("source"), field("target"), field("outcome")}; row.problem = j.value("problem", true); row.details = L"Operation: " + field("attempt") + L"\r\nResult: " + row.outcome + L"\r\nVerification: " + field("verification") + L"\r\nElapsed: " + std::to_wstring(j.value("elapsedMs", 0ULL)) + L" ms\r\n\r\nOriginal:\r\n" + field("original") + L"\r\n\r\nExpected result:\r\n" + field("expected") + L"\r\n\r\nRead back:\r\n" + field("actual") + L"\r\n\r\nForeground unchanged: " + (j.value("foregroundSame", false) ? L"yes" : L"no") + L"\r\nInput context unchanged: " + (j.value("inputSame", false) ? L"yes" : L"no") + L"\r\nText truncated: " + (j.value("textTruncated", false) ? L"yes (4096 UTF-16 units per field)" : L"no") + L"\r\n\r\nContext and stages:\r\n" + field("context"); for (size_t at = 0; (at = row.details.find(L'\n', at)) != row.details.npos; ++at) if (at == 0 || row.details[at - 1] != L'\r') row.details.insert(at++, 1, L'\r'); rows.push_back(std::move(row)); legacy = nullptr; continue; } catch (...) { } // Preserve malformed and old records for diagnosis. } if (line.front() != L' ' || !legacy) { rows.push_back({L"", L"", L"Legacy / event", L"", L"", L"Unstructured event", line}); legacy = &rows.back(); } else legacy->details += L"\r\n" + line; } return rows; } inline std::wstring conversionReadbackOutcome(const std::wstring &actual, const std::wstring &original, const std::wstring &expected) { if (actual == expected) return L"Paste verified"; if (actual == original) return L"Original text remained"; return L"Readback differs"; } } // namespace ks