From 2414724d12793d4768bbc4b2743ab983392ab5c2 Mon Sep 17 00:00:00 2001 From: peplxx <91543105+peplxx@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:44:08 +0300 Subject: [PATCH 1/3] feat: graph model, YAML I/O and builder API (0.1.0) --- .clangd => .clangd.in | 2 + .gitignore | 1 + .pre-commit-config.yaml | 2 + CMakeLists.txt | 21 +- README.md | 199 +++++++++++++ assets/libstgx-banner.png | Bin 0 -> 232476 bytes cmake/ProjectSettings.cmake | 10 + include/stgx/builder.hpp | 154 ++++++++++ include/stgx/diagnostics.hpp | 133 +++++++++ include/stgx/graph.hpp | 136 +++++++++ include/stgx/model.hpp | 80 ++++++ include/stgx/result.hpp | 45 +++ include/stgx/stgx.hpp | 11 + include/stgx/yaml.hpp | 43 +++ src/builder.cpp | 24 ++ src/diagnostics.cpp | 157 +++++++++++ src/graph.cpp | 207 +++++++++++++- src/validate.cpp | 118 ++++++++ src/validate.hpp | 23 ++ src/yaml_load.cpp | 374 +++++++++++++++++++++++++ src/yaml_save.cpp | 127 +++++++++ tests/CMakeLists.txt | 5 + tests/builder_test.cpp | 138 +++++++++ tests/data/aliases.yaml | 17 ++ tests/data/invalid_bad_int.yaml | 5 + tests/data/invalid_bad_release.yaml | 5 + tests/data/invalid_bad_yaml.yaml | 4 + tests/data/invalid_dangling.yaml | 6 + tests/data/invalid_duplicate_id.yaml | 4 + tests/data/invalid_empty_id.yaml | 3 + tests/data/invalid_empty_nodes.yaml | 2 + tests/data/invalid_no_initial.yaml | 3 + tests/data/invalid_no_nodes.yaml | 3 + tests/data/invalid_schema_version.yaml | 4 + tests/data/invalid_task_arity.yaml | 9 + tests/data/invalid_two_initial.yaml | 5 + tests/data/invalid_wrong_type.yaml | 4 + tests/data/minimal.yaml | 4 + tests/data/two-tasks.yaml | 25 ++ tests/data/unsupported.yaml | 16 ++ tests/graph_test.cpp | 205 +++++++++++++- tests/helpers.hpp | 32 +++ tests/validate_test.cpp | 146 ++++++++++ tests/yaml_load_test.cpp | 206 ++++++++++++++ tests/yaml_roundtrip_test.cpp | 104 +++++++ 45 files changed, 2811 insertions(+), 11 deletions(-) rename .clangd => .clangd.in (89%) create mode 100644 README.md create mode 100644 assets/libstgx-banner.png create mode 100644 include/stgx/builder.hpp create mode 100644 include/stgx/diagnostics.hpp create mode 100644 include/stgx/model.hpp create mode 100644 include/stgx/result.hpp create mode 100644 include/stgx/stgx.hpp create mode 100644 include/stgx/yaml.hpp create mode 100644 src/builder.cpp create mode 100644 src/diagnostics.cpp create mode 100644 src/validate.cpp create mode 100644 src/validate.hpp create mode 100644 src/yaml_load.cpp create mode 100644 src/yaml_save.cpp create mode 100644 tests/builder_test.cpp create mode 100644 tests/data/aliases.yaml create mode 100644 tests/data/invalid_bad_int.yaml create mode 100644 tests/data/invalid_bad_release.yaml create mode 100644 tests/data/invalid_bad_yaml.yaml create mode 100644 tests/data/invalid_dangling.yaml create mode 100644 tests/data/invalid_duplicate_id.yaml create mode 100644 tests/data/invalid_empty_id.yaml create mode 100644 tests/data/invalid_empty_nodes.yaml create mode 100644 tests/data/invalid_no_initial.yaml create mode 100644 tests/data/invalid_no_nodes.yaml create mode 100644 tests/data/invalid_schema_version.yaml create mode 100644 tests/data/invalid_task_arity.yaml create mode 100644 tests/data/invalid_two_initial.yaml create mode 100644 tests/data/invalid_wrong_type.yaml create mode 100644 tests/data/minimal.yaml create mode 100644 tests/data/two-tasks.yaml create mode 100644 tests/data/unsupported.yaml create mode 100644 tests/helpers.hpp create mode 100644 tests/validate_test.cpp create mode 100644 tests/yaml_load_test.cpp create mode 100644 tests/yaml_roundtrip_test.cpp diff --git a/.clangd b/.clangd.in similarity index 89% rename from .clangd rename to .clangd.in index f11186d..e675b71 100644 --- a/.clangd +++ b/.clangd.in @@ -5,3 +5,5 @@ # Pin clangd to the tree that has both the library and the tests. CompileFlags: CompilationDatabase: build + Add: + - -I@CMAKE_CURRENT_SOURCE_DIR@/include diff --git a/.gitignore b/.gitignore index 822c84f..59a97c3 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ out/ # clangd .cache/ +.clangd diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 75a87b8..dc92fe0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,6 +19,8 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml + exclude: ^tests/data/invalid_bad_yaml\.yaml$ + - id: check-added-large-files - id: check-merge-conflict - id: mixed-line-ending diff --git a/CMakeLists.txt b/CMakeLists.txt index e4bc0bc..d5a30d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) project(libstgx VERSION 0.1.0 @@ -6,21 +6,24 @@ project(libstgx LANGUAGES CXX ) -include(cmake/ProjectSettings.cmake) +# Developer conveniences +if(PROJECT_IS_TOP_LEVEL) + include(cmake/ProjectSettings.cmake) +endif() set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -option(STGX_BUILD_TESTS "Build unit tests" ON) +option(STGX_BUILD_TESTS "Build unit tests" ${PROJECT_IS_TOP_LEVEL}) option(STGX_BUILD_EXAMPLES "Build examples" OFF) option(STGX_ENABLE_CLANG_TIDY "Enable clang-tidy on stgx targets" OFF) -# --- dependencies ----------------------------------------------------------- +# --- dependencies add_subdirectory(thirdparty) -# --- library ---------------------------------------------------------------- +# --- library file(GLOB_RECURSE libstg_sources CONFIGURE_DEPENDS @@ -44,6 +47,10 @@ target_link_libraries(stgx target_compile_features(stgx PUBLIC cxx_std_23) target_compile_options(stgx PRIVATE -Wall -Wextra -Wpedantic) +# Carried on the target rather than picked up from ProjectSettings.cmake, so it +# also holds when a consumer links stgx into a shared library. +set_target_properties(stgx PROPERTIES POSITION_INDEPENDENT_CODE ON) + if(STGX_ENABLE_CLANG_TIDY) find_program(CLANG_TIDY_EXE NAMES clang-tidy @@ -59,14 +66,14 @@ if(STGX_ENABLE_CLANG_TIDY) endif() -# --- examples --------------------------------------------------------------- +# --- examples if(STGX_BUILD_EXAMPLES) add_subdirectory(examples) endif() -# --- tests ------------------------------------------------------------------ +# --- tests if(STGX_BUILD_TESTS) enable_testing() diff --git a/README.md b/README.md new file mode 100644 index 0000000..c065fbd --- /dev/null +++ b/README.md @@ -0,0 +1,199 @@ +
+ +libstgx + +[![CI](https://github.com/peplxx/libstgx/actions/workflows/ci.yml/badge.svg)](https://github.com/peplxx/libstgx/actions/workflows/ci.yml) +![C++23](https://img.shields.io/badge/C%2B%2B-23-00599C?logo=cplusplus&logoColor=white) +![CMake 3.21+](https://img.shields.io/badge/CMake-3.21%2B-064F8C?logo=cmake&logoColor=white) +![version](https://img.shields.io/badge/version-0.1.0-blue) + +
+ +**S**tate **T**ransition **G**raph e**X**tended — a C++ library for building, editing and +validating state-transition graphs of real-time task systems. + +--- + +libstgx reads and writes the YAML that +[state-graph-visualizer](https://github.com/peplxx/state-graph-visualizer) renders, and is the +source of truth for that format — it validates stricter than the viewer does. + + +## Add to project + +```cmake +include(FetchContent) + +FetchContent_Declare( + libstgx + GIT_REPOSITORY https://github.com/peplxx/libstgx.git + GIT_TAG v0.1.0 + GIT_SHALLOW TRUE +) +FetchContent_MakeAvailable(libstgx) + +target_link_libraries(my_app PRIVATE stgx::stgx) +``` + +**As a subdirectory** — submodule or vendored copy: + +```cmake +add_subdirectory(libstgx) +target_link_libraries(my_app PRIVATE stgx::stgx) +``` + +There is no `install()` / `find_package(stgx)` yet — both routes above go through +`add_subdirectory`. + +## Building the library itself + +```bash +cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug +cmake --build build -j +ctest --test-dir build --output-on-failure +``` + +CMake 3.21+ and a C++23 compiler (Apple Clang 17, GCC 13, Clang 17). Catch2 v3 is used for tests — +taken from the system if present, otherwise fetched. + +| Option | Default | | +|---|---|---| +| `STGX_BUILD_TESTS` | on for a top-level build, off as a subproject | build the Catch2 test binary | +| `STGX_BUILD_EXAMPLES` | `OFF` | build the two example programs | +| `STGX_ENABLE_CLANG_TIDY` | `OFF` | run clang-tidy over the library sources | + +## Graphs and the visualizer format + +Everything below is the half of libstgx that faces +[state-graph-visualizer](https://github.com/peplxx/state-graph-visualizer): a model of the picture +— states, transitions, styling — and the YAML document the viewer reads. + +
+The API and the wire format + +
+ +### Usage + +```cpp +#include + +#include + +int main() { + auto graph = stgx::GraphBuilder() + .system([](auto& s) { s.description("EDF").m(1).task(2, 5, "τ₁").task(3, 7, "τ₂"); }) + .node("n00", [](auto& n) { n.initial().task(0, 0).task(0, 0).to("n10").to("n20"); }) + .node("n10", [](auto& n) { n.task(2, 5, stgx::Release::Up).task(0, 0).to("n20"); }) + .node("n20", [](auto& n) { n.task(0, 3, stgx::Release::Down).task(0, 0).loop_to("n00"); }) + .build(); + + if (!graph) { + std::println("{}", graph.error().to_string()); + return 1; + } + if (auto saved = stgx::save_yaml_file(*graph, "graph.yaml"); !saved) { + std::println("{}", saved.error().to_string()); + return 1; + } +} +``` +> Graph is not checked until `build()`, which then reports everything that is wrong at once + + +```cpp +stgx::Diagnostics warnings; +auto graph = stgx::load_yaml_file("graph.yaml", &warnings); +if (!graph) return std::println("{}", graph.error().to_string()), 1; +if (!warnings.empty()) std::println("{}", warnings.to_string()); // fields we drop when saving +``` +> Reading one back. Warnings cannot ride along in `expected`'s success case, so loading takes an +optional `Diagnostics*` for them + +## Model + +| Type | Holds | +|---|---| +| `System` | `description`, `m` (processor count), `tasks` — the `(c, d)` parameters, one per task | +| `Node` | `id`, `initial`, `label`, `border_color`, `fill_color`, `tasks` — per-task `(c, d, release)` state | +| `Edge` | `source`, `target`, `kind`: `Transition` (`children`) or `Release` (`loopback`) | + +`Graph` owns nodes and edges and keeps them indexed: `find_node`, `has_node`, `initial_node`, and +`out_edges(id)` — which returns a `std::span` into the edge storage, no copies. Edges stay grouped +by source, so every mutation re-groups them in O(V+E); deliberate, and fine at the sizes these +graphs come in. + +
+Mutations — each one keeps the graph referentially sound + +`add_node`, `remove_node`, `rename_node`, `add_edge`, `remove_edge`, `set_initial`, +`set_node_tasks`, `set_node_label`, `set_node_border_color`, `set_node_fill_color`. + +Removing a node takes every edge touching it with it; renaming one repoints them. A dangling edge +cannot be produced through this API. + +
+ +
+Diagnostic codes — {code, severity, path, message} + +| Code | Meaning | +|---|---| +| `yaml_parse` | the bytes are not YAML, or the document is empty | +| `wrong_type` | a value has the wrong YAML shape (mapping expected, etc.) | +| `schema_version` | `schemaVersion` is not a version this build reads | +| `nodes_missing` | `nodes` is absent or empty | +| `node_id_empty` / `node_id_duplicate` | node ids must be present and unique | +| `dangling_edge` | an edge names a node that does not exist | +| `initial_count` | `initial` must be set on exactly one node | +| `task_arity_mismatch` | a node has a different number of tasks than `system.tasks` | +| `not_an_int` | `c`, `d`, `m`, `schemaVersion` must be plain integers — `2.0` and `2e1` are not | +| `bad_release` | `release` is not `up` / `down` / `none` (or `↑` / `↓` / `1` / `-1`) | +| `unsupported_field` | recognised but not modelled yet; dropped on save *(warning)* | +| `unknown_field` | not part of the wire format *(warning)* | +| `io_error` | a file could not be opened, read or written | + +One `load_yaml_file` on a badly broken document reports the bad integer *and* the dangling edge +*and* the missing initial node. + +
+ +## Wire format + +```yaml +schemaVersion: 1 +system: + description: EDF feasibility graph + m: 1 + tasks: + - {c: 2, d: 5, name: τ₁} + - {c: 3, d: 7, name: τ₂} +nodes: + - id: n00 + initial: true + tasks: + - {c: 0, d: 0} + - {c: 0, d: 0} + children: [n10, n20] + - id: n10 + tasks: + - {c: 2, d: 5, release: up} + - {c: 0, d: 0} + children: [n20] + - id: n20 + label: "custom: label" + borderColor: "#C0392B" + fillColor: "#F9D5D3" + tasks: + - {c: 0, d: 3, release: down} + - {c: 0, d: 0} + loopback: [n00] +``` + +**On read** — `schemaVersion` may be omitted (assumed 1); `isInitial` is accepted as a legacy +spelling of `initial`; `release` accepts `↑` / `1` for up and `↓` / `-1` for down; absent fields +take their defaults. + +**On write** — key order is as above, and defaults are omitted: `initial: false`, empty `tasks` / +`children` / `loopback`, `release: none`, absent `label` and colours. Colours are passed through +verbatim, any CSS value the viewer accepts. diff --git a/assets/libstgx-banner.png b/assets/libstgx-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..6034cd38f60a82f3b509bfa25492db6786fd9848 GIT binary patch literal 232476 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%0D!f}dpDymgYt&E$3!#xAvAU_qqNl8-nwyjJ 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
ezsf@STEO=gg$4jtftw1Xqa{mkSwyax}*rZ4UA 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 O& z#^DJXtL^SlUGysEX>@3RitOeVZmGo}lV=}|wC**;GGpf?$QQp|Fka@8P0T=`5;cc^ zv*4^T{7-P;v6%DcUNQz}TB)my!j`+gx34W8`X$j@N`xp34d+fD?O>_k6zY`u=d@1R z@%{VSlJdS;I4N2M>?csKE8u>#^2 z(3$y?gKjX6fWaj2=SCs#JwKD9t9&e$I`TLQZb=W$4zw3?ZQ~PP1DuPLi6r`xIrR%N zNj#F5XTfK$yti{?tBm*NEd*Lqt~+CvQuyFyVXENR%Z$hiU(r*P-l|q)-Dy-t>ZK&h z1m5kEl6;KJ?-4J~&Fge>znp^S6pFhX(ZbC0+T!;yuoWF+uo3y%c+4%#X+r9;R%~mL z1PZZoc}BVj+Ey*@Lgq+9^{1pN*gTPo*pZ~f3Oshqk)$>V1WP1&Zxr$&9?pr4sd~ug zOXm~ijUeXV`FfPObi@;S356xx9eK58V^ZRd-_estVq5dSO-^=WVi1MqDBhSKzmE5& zCkqtLV@?CC-yTRBuDV^Jw-h`$$PhUFy5@1zx$GhFUB^I&!}>-Bji4aUL`M(0x$0du zFCC_I)zH=ki7y&2Pvw4m*$kBcSUzD{Uk)pJNU}qq-EsLBf7Y2UPT$?>@_WbN zi^doMmwpXBd}1WH|8^1KE!BgA-E0vw=Fqx#GFeGRajET660%PyD?a?n<5wBRVy_nm z6_h+qzMCHXW_oabaw*VNBl#iCN#}-bMhcSnivc$;<=dLi1OxSDcP~A9NkN$;on7bl z*)_A|NgsCBzzZq%H$9g&aJ@98 zbBp`m_BpO#I1D`Sp7i$XAjO=O_xXH$wEg+w@2%;=K27p%s~d~;xE4}uQUt`(^kh1d zp*B^uI?lOT^&F83L|8aD^J!`MR{s1wHqsw|jFEUYulj3YSa$E$2Ezf$b}Lbl`Kb^_ zVc2Y^ir#nX=X?v_>t|Lk0-7wjtQSuoPmE0^&9~dggz1tvm5;uArycVX@^14OSKM5^ z*5s923V8pXM`37c%XobOzM%NMfu8arWW-QWJ=K$1gakw^GfC72OfsGSI*#vL#N?(F zlU^@KGo}7lQxV2b7Y_5WgJ43ngpAl*DQ@K`0AO>4+;PAIT+j8rcQ}EbomLD1F5~}L zy2^m4)~-ABkPh7~QVK|i)F6s<8Z;sx-6)8HFd!nLNOwqsbcd9PG!oL%Ati!{NPTilfLYSG?y-9j#rEEF-1)G9fVrC3$o zpC9sS7x=@r9LRwm6R4m6r;b#JLHxn`YQKq3i3zFJi$P|(wjXr={jHIEuXZ+q(kee6 z619xo*>0FWhjseDe__B=1o1OaZ|gG!p3Z5_V4DGz6LLV1)fWpPp8YeVqWJDD>q=cL zwjy}~loM17Vecsz|B_uAx;GE#reCAb{LNs?4f!EnW^dlS!P@9_aB~}W{<7=L31RQV zX-9oY(g@!!a;u+B0N^R%J)>l07IWO_V%PL@I{p2_e@**=O%?|| zn{XYD3#uep)|uh8^h&VCg@vsx?tq*LCv}SPc<0$mOSUq*tJAI)!#}BR7zI*^kf3!}JwZpu0%}TvR9FM@cTIYkS6VBqB zLpUtb$d1y&-VGg$9x}>H**d<%_xHS&8%`>{jxDX1SzGfhwmjV%G0#P%x$ZjopJ%Fg z?C(pJ{AKke*xfjDO;dTc^}i=}fx0}0du?T_xOY}v2ku5;*&cgRWKD4!_4rfbsDB} z(5F!BJW0y!Pq?}SCYCX|Q()$Lvh5n6(%P3Z?Y zwrn)Rr?pPNgg{3F5*@z>HE;Cu$MAEvTIpir9Qo8dL4$Ge7rHPPK*g` z^Ar;m(@A$3&8K|j7Whud)a|9{6&myqEm27j^N_zt1ej~)u*uH6cU3fTx=d5VRP?{j z(OLJ#yzXOuLeTmzF~;Jls77IQY;9TVb0kd?Vq%uPWIa7RUSG;0RhZQ)Jcm6~UIrcA2Sw-~m37#4&6Y~Np8l=^U7sX8s` z{yLiAJp%vvWj)9L%Ab`U^=M+P)5OC{tLq?|)Yl&d`I3jHC#+ybCnSWqU2QaCKqCzj z#y7DkXkcGvUpozCV?ZSB_y>!XcQivACKr>f@${|y|^7SpB5{$Um2 zsPPqB7f@W??|-A9+e&<$$9*N-4#M#REuR$*QO7JtJ|vhI!`U z_D7_0s%^nd-1WPuu?>hoFY{0n?iF0a?g+y&`j*cVNST6W0=2O^ilZs!1di4ZdK^1M z$U5r43lK_P8#z`S26<7s>ijv6X1$>gZeDqBn0I_jLJ6VHV1P8h!R-vqSNqiY6&y3a zd-R%}`#$Y!J`5ZlghuFhfacWM5t;S4_VOy1BE7k=7i%bm6$&L*A{zEK@`AF%-Dl=$ z8HT#=lGAS@@KOT5*pv#SK1XpD%2?kn>r&2vWC<@>RuTf7ipolx)9I#@lli9)ITF1& zB|ozaEa&!Xr^&{qr;?&MBGf-OQw35@(9p4t9b|nU;H%BFM~8*y>i!2ZmzCwCtTGc~ z(;d>)#_TaDfE^c8AkPXq8iz!hP!g??NXXs-%QGspzXI08ddsKLyL2$TWHUGV=+jGT zP%G*oFmFNh`5j(Og0vu*vmpee$*Lpt{Ae)Xaugx=$e4$&2y=crEdixa-Hcl!mE0p% z(S>g})1Jar^OfjuJ780>R4etQ=bNg=-}0p|gTcJ)<`=}-rNe(zEmX`9FjRPn8vjc2&l)6eR$vF z>zq|scvOj6Y&k#u2}BpDx<4@-|LS5FZrrMH?Wv_Bjk8GR79 zyV2nBCBu~BGw#$ATOxPQIKV*;tPMlv?fE_bB_(|xw|R6m^!q+*Dfh^hPcGVuqaJ@1>YF5dQB zk~U&1T8H44l^|TCAs)$79W0$uRwi9rz)a$tpc$0o`4cc3Fp!Oji>m=q)}X@iFwHCKjzF#dTk!$fJJOvoFwSu5usLqlgn4AJ0#2;HgtmjEY>Rd_qrZL!Fq4!beYZxzJe=Hh2xqpU)<$z4kiq5(>-FwaiU;+M%;D_eF~Al-W${OygJS%)f-(h zo?^BG>Mmmyc5~1AWgk5sq4%svyEYK!+7q0DoGjWY|N2&h+hfN_sK4M~GpmR$}NqGb_M5Nr#+aEnH;3oje z#Z%Wu=g!}@?p5#46CJaW;g21!`VnuVyQ3}Sy#-QHK*Q0gNTK-{?SEOS^Egan=pi%^Vuc`gjSvM+^g}8a z+DP__FT)zzT)??}j$t8w%0BFEU^TL%gL<45jiI;lR#bb&Xg*w3A?Cxg)-{w)(WU+L zIm>20a>*rW_h0fO&3{k8bA1p#benbbS%PS1qtz7;QN6bptO9k<%V;Gl~+iUAu_4V!*gIhd`j?HRz~*wC+*vyIJ)(nDD2ht$49z+fX;WJGQI5`Y|j z0_%aI%`$-?cJhW<3QSlHy))fujFtw;yy*h@eqZ3lAaRxX$|t!uJL|Yi^CH>Se0@=| zObf3zT4y|D{&#uh-)g_FeUE9l6M}fEAxn?U+XNBF3_sh^ZpWJk(>pEaXG2Lhv|=+N zwUca)W!B6~4?!s(FFOI2>&b852I@A(kE?3BgLynwFDTM)3Xc(+SW?c_UEPOGYlVRu z>!AtqEw~tyK#3{M|DXUhAa_#@U z_}P3ouzzlTw66o6j9+@6*9JarhJY_EQhPAMt>ehg%BZZU0BNT0n9&{na5UozXmYXk zAT5m5>cP(1>?VD8y30rOR|s7();-(yhlBR9*0o5SKq zR8$mTIW)9k_pkVeP~MCF5wYF*M`-UwtFIb@6MyZ-bxkMD<_X|_efRcSU%%52h!xr? zd^z;MLf24|Ymb%L0!au$ErzU1YIEQ~WO(i1H+70*U>)2EkR#3D@QX%v zC5a-X^O{V@qEK9rlK|&3Nac03v}n~s_^qbTW`GIPEsxLNBE^7k>YM6uGT2uz#uJq`^N0Y{z1 z1#W$2!C@+MkLezAdfdP)5tm)1RMV(Cx`A9bepGT}ChFX+wY3KT!R&i2BO?Ro8MBCG zV9Dl4u8tU)^=?Mnrc|-;djpWsY5v#vS3z=c8vMS??=)ysZ{50e^^sfSETlgfgB%FZ z9>b_(hP&fS7>0`(PxJ$WsIA;uKEzRNxH3z*{z`lrh(gma6%4l z;HL!s6T=Y2O9}bash-wyX~zY{82#pjQ08~h(JHego*29H zgDr4SMlgg%B`3oSdAD?2a8}N7@}D!qjc3n34z7u5B=}upd(%bjKx{T(D15-$FHAzV$b+~u25Cj4YF}wAIa4^ef0Jfz>n~oU(!m-FZ6>G4fmu}`Lp}x z=H@OgF7{nfKccWXmr+sW(Dnw0+`Cv=Wxd`OS|fR-a(4tIOwdRvX#;_{II${*hH}V{0rXnrGveBAD_*9{ zSDBzuBCH=6bbVVh_0gybaM^0yX>bHZg>Cbq@p{7^O;YZW|Ht`I`=ng^q*)h5dM`X& zJ`xPBZJ>zw8;1bpkw4>Pg9;vxS1RUKwbQM}f4i79_^eOg)N;YkBPGEz$ecR)l_-9f z(5SlS+m{2%cd@ZNtb9SWj!CO-(r{BGCMQor&iB@qli4`=`_T-8fqE2|fPe$Y?h6b5 z{G6L}simJ*6c8xP$Y|X>kY$O~HFF($uS{UTBw?T8Bl_CTrk;D&^7711l)sv+%x6VGR|w0)4OVEqr?QY0t1rJw&BZ|U>k=N$ahE29HfDrD_p@o0cMQ8n3A zA|c(&pAn%K*xAqqC-p>`7vY0|2P8oLf_!`;WY&p6TTb z@F|R(pU1!cFH4m0-pbf!NI&aJ8M(SPTHEDz&p@@~?Wel~=Ue4hXN8)|JP+CaVE*ks z&J?f|V8F?g=4Mj#H#8aW_3{!A1hV{?R9J7(OBQUhv8!}2A7T^iwtehuY$ly*=4JIe z-K1G!hT%to`P>@L8iWB|x$*%{LEF;|ctW<71>sCn7bikojv}5^3ivM&t*R>ypAC=4 z^rk*Oee!t%lxvr2k(_*)u!?mGAH0OoTMGoT*oFj@QLrA?8`G(21-BnI-xc0oFSB@( zTd-IR&mC|P=!_bn5B}nhf5*%_cGTA9;SRihK*i9f$!ccH^|1cX)KDZyzqFL^m>0DW zbD>F6Bu7ASIK=9IEj3cA-Pl(ejICiY68KS?sk))6s;cg2-rjqiV8?L}26_?S&Yr{O zksn~ZUv0%;Uit`@D>GdT2~cP<7U?q3;6dL2-@#|4Pn7Nw_Vhwq0RfOsgvII@6a*Sg zkW0;QjFZ9?_zakDqXGRpGTFX=QZQ+m{T{mJPV_w-eEE2kLf1cMs1~ihFKs?cADlfq z>|&B|k`7qy(@8s8`{&vs>9f=NW8_nj@(8DN9gY4j(2#!_hDj8+jx4#GQ8F)Rv~|R z-#7b@36_S&r~W4J38*#cH7MvL+pjhtqy|6{oFSMo0O})OFg!HM4c-6~Z2v>oi89X7 zD}^x4LEH#d>JDpp*!^v3;u;|jP*hK5EbGa1B^raIc*))qShDR5_^dWT|D7 zUTC>X=a%D@um0DiT3`3jO7XP2id^EVu}5zkxJ*IG$0}yq z2X|4|Yvx+mk%g6%ME5}E6IjKIh>Y9;FzxzvjOi^-3;-bhkahx;Y!Y;p&>x?lZvCW0 zZq5hkB#9TmiUWMVBGVcly`KW+i^^2clx4&E~FdpO*wyvxPPr zFhk;6xv@eQ6w-zJ;_w7Qovy82lai_hmqA5EMJXvMUf#T_&9NY)_w;`S8m)4-YY40Y zL}g|FwUY{yS?wi&P)0}L2&3=7@OimA8jOX}$se*AJcK4PRfxX49o0(Syq(25;0tpp ztZx>`#rP~_y7=C;TL1il{VCt}etCI0tYZk*h_{mOc*(ByC61I^-+a@hg7gLcQV9HZ zAs=Scw1BsgJ*nGuh0b0hO2$=i>P|dg6ZU%mQqJVc(k$|2+npEQ?crF)4%Aq}Ckdg%i$X`JVLnac%%s31L( zftL~Z2O4Ems!oUuI3ntD!x`Iv61^B?^9I668Cr&u$=?N#m* zMw=J`L>>(})5VX6-y1uVl=x>MM4;dHcs}^T$vP((HudU%g-E zQM95_V1#)H2pEPZOLuc)7JgIBlvGUdjcaN!^8~S5ReIk3#k$PSQ^z3VvHbn?xR1NH z?%_+y?8cr`h`NELN~-v`x{Fr_FTDu&hjl8rzE6;jA%9?tfgNOpkcWuQS7Hj~bfy4{ z3TB!67u$uS$vLwDR}{6|s@b0QG85+hn%`Luz6)}^CL6Q}P}n5GplTTshia#}v>AqV zgM{uku4fshgYn{faD^r}R3klvI70ffle#$&sv-SRGxZuC$u(bkwWeDFM!vlUe}_ot zn3)Dt290TO`qvuzBVzeNAs6XH6jvD1}6^^i2bmfS+1Mc#)jzLPx~j=~L}o2#p<4E6P( z_nQy;mQ8|<@9XR9gS%I((n>>3uO0*wRSk};b)>EY0GJh@uuxmr)VrAt~%%;Ht5H&pbL7!nklMQKsXny1eZ^Y|#5 ztipjZeTjGPwe;U#>{-9pp9dudXe_sSQv?AFqLarOMa3uM7Q(#OK2N-hA|)hw?bf(g z;pwSkSO5O~OHF+0_i4IOIsE!Nt;FcvI14=*1p8EuZ_WZ&oHLZB_(k9o)Sk2x?Ba6Oq|>m|{T=Hw zfq=)$3pXJ%P2Ta_WduJzKY+gDp!z~TWnGgBsgL64BjA}QWQmcj&Sia{RO5UhU26aD zOV;UH0m++Qrl&W$Uq8g);bMlAN@hik`1N>HHGJ4S5i!g;ybdpqHN3}HJaFbs<8i8N z4C|tfli$m?TYJeTYf2*u`J%3V{eE(?715W!{!kZ3|MZA71QlXbs$M=6o;795_$cp0 zR~-tdIDD>s!qg+7xZVfDswd#T0((&(bM4um{k0k^P14QUY_NzW_qZ%2ysOC{lDr>- zodZ-q=nvixs@9^}HnUrukA2TW zjyj2Lr3~|R!w5Cash=UbP}XO9QdU>G!Iuj z0{s<86_sfkS@pM!`pVHp0ygivHNWi`K!9+S$n3 zHTZ3A_)7IZ7$s|m>KmQ$D-SMe)`0zfDRdYJbmF5rxT_LIBDbe&u}Loghtz)ea|Go8 zOy#nn_5urp=cjMxu&(nm(N6$d&dIZw^pxYoOmBna%?H-cvscz&ZrB(t7|Dq@C%HFM zN5Xm&xp3eIXrsna(e!rBq*G_%En?2Sy*-7K^$uW>i;Ih!nyw*0P$M<#1!hgFUMEf5 zeC^^HaYtfgdW1+4u9RQDuH4V!j5vwrH86Oy^SzN*Qb?ix7WETDvW(}{D2g^^WZ3+3 z7YE^czjJX5GB)i~CE3R75$vb;$*CeNI9P zfilbk{r#*EUIpv3WF5eUs{$M|_`KWV%F-PHK3@Phb8fo<6boRSW&=}Prc;7hmO+;` zl+~KcEb7Smqt)c`4<<0yGz-|$MAz;?UadR;35uWP_*%-ZBcsyN&Y*%O*|I11U!tAT z?Ulf|1tw|7R=HUta070c$l=gak~7yhB;cnDZ!f=0oi+%|^L z)rG8uxQ*N&Z$%3=`}u4Pzox3NIsPUg7{@-<{9YYZk&YzI5MO$?)l7hhp~zphc5wF zeIbIQ{D4Z%YXgKm=1+xdifYVEYUsBnOYP_<@<~eMoP7v&b%ij6G2^(d>)1?RHvio= zzzxMGf`3D`hE>-9pct{<6ZJWLCFnmpvjI!wOH@=F#q7nce|eXALErAEG@ zyr^D2@T)<&&W+xl-%54rbZyqJ{0?VJ@Eo9#1d$BfTIN6 z&cMcVf1r;5*4mk1PH$Wf#XuL(rK zmh|fC@|WLv?@Q`$xN)K)kBZt^&|hF;ULJ%+i@9V8=i4uXk(>$bup;yiB8IR19#R=* z@&S_s7g(1CPlz^EWx*-Qfg|X2dA*k^XsLWp0KM#W($7~liRVOEb6of1W)?wGVn{lW z6W8?2JLEVoiiz#R^TIw5;y~S&@~4ob1Ax^rxZHqNK;CmrG|Ot+=NRg|oX4_S<7|n& zF%0bh61IRU1EexvD#_RtQc&3ZJov4V%r!YHDLu~0s z`D(Apo;~2ooB2+lYt=6W3<%wjhGoP4u2g z%y6%8OA}1QKtYO|z0!c8;Gn+S*Gue4z@4vsqi-IX}vZzX0$_EP}5 zqaH{+U5>iRV9oaCrjb$OtPs6$&*Ly^Dk}KlgO$RZ031Mo5<21AIQVB{SAoHT6m--T z=eQUS%w;ehi8FD@j2VC<0C-7eoI^;tmoe!pPpW|k#~S00e@&M&ZMW z2PDa|-VXZu?+g{-zx@TO)@WdJV#^~u3oC>Y{94<-l~PzJ`WdLWXNiR*R^O~U7~gb7 zM@Mr92r;E=B1n?SBS>_yTVS+}{-2ONCR8u~<2XMjkd;fmeD&(p%a_VZ+u~l_(go9r z-Vwo1qGnyrVY$j#(gd2LJ_RNI?cto>wqT;l%E}N_1=}9H)ZnBS_4ci0?KB`Chgh>c zLj}{n+ru;SC|rG%_qVfv+w3{_uWpP5%^6k9yveRtvofrwat*of9!$D?d%W7@Zp?Gw zL&#J{s<;Nt=D9JHzbOj~Nwg~}J#cuO@@DAh)({JSz1#<2fjOhl0Zu%n;c&ApfpP(8 z0-E+CQ)J0lWvjq-Htwjb;jP#>Y%YiEZv3LDo7vecX^hlwp;Q_5h?%a(MzER!(F{8EU6~1ZWMmebSG32kNaD!n087L067= zzM&+0FP#I81kh?dET}EFx(tH_A~^8$^=Z1e<%*~mlx%__+)wZ@h5s*%08H>+I{2ET zu!>d2S6{YqPt(1~ZW0w$?Ut$Vc5=Xv@A74bxU%Hy>O?g_fWzAjK(PJg52^Iafabx3 zK%#{F1xMPXw|OkY^xWBxq;2;X^&~h6PQ*#G_5va{!By zF(7`W=KL!s6bJ|iJXBSfHbPK7HP-Q<+mMOk8I^Y|Eg6I3yo3#~ga;T2?9TV#t-fF)D13Cqd zWh5pn^5xO=>?5&G_7>+vJ3)2wW+n(QJy}x}Zdm6k$ojHz+34CT+|_Fy^#e0P^dI1! z#Sl|3)2WmeCNKJ`0!#@7k)ulx0S`DyG2je#I~xu+CadmMI);)5{A_V8o+uaNk+(kl zF(MP=hl6MOVyJhGqKEuDu<+2hCD&NIOmrS_%><}PW=$b|aOoF~97Q0o^jJn8yPg5= ziizcuz)FO}E%^F1`GCqL9nSG~%{RY?k&WXMz7aN=)zSeOS!%WiRIkiTgnrS{RjV+H zJs&dcTTID=zua7CM(-N+nuwNf@PZC|9UIbkGX;tp15V?8GtS4w#p=C|>m|L*LI^%U z_b$9FrSDRD5cDK;qxgbv36+0(E)3c(Zjtexc8I9WW=Y@`C;ItJYnTj;n)%raKp97jAb8<9lDuIjRB?lHGS2PPL8l_xsPzj(!fd?9SMY zSe#jXf6uOI*5Fxt0TqbmRI6Y9O!F;IhrL4tJ}`q*c5EsJwRqr{s%=;H2hD#9GEZpz zc0lb@+2OX{_~=~1Qt8~h`H9n1RkzC>V#+|p+i{*Q>z@I&ho`mSB}*BTAAwr*s3+@q zt1X+;+wMvwWBn$Byd6O{`tH5Xw%&~yCz+X~peOd-^51MLfvl?h(z1RF2e_+yX&HVc zQA%%>++*h7gs6rg2S_bHyVD$Ma;hqD%p-Vjk6DwxV!F7+#>1!-3v3_=0*n&^zxdMT zc)^4y+N};axG=2p!ZJ>~TSq!N*z+S)sF)ZU%xi6z^&2iO;L78DRtXd@gc~i$)gCD5d?wxfA3D!8?4#(Ct=0v;`x|GfbOse z8#G-Bo*%)77=B1wU@hTquN3H+n(1x0Zw?<{)3=a^Mq=E>3~ux3TE}xRhSp3H|M8MH zP5P;RMV@YMU>!v-mfB{wXKHh6HptT{bz2F4&3{U6{KfJl81$`q2fq ziS0kSwX;}sa`A*~i^f<*3VgC#K*xX`qUf}{Xl@|82L_&jZhaYZ23{-iKbIP47x<$K z5a8yg0TwhMTW^AF@ew=WD%~3(`g4c6+BnNbP3;Mg8kbYdc0*7mGjQ}kC+)oB7OOk5{PsScN^W&Kb5N zt#+se6cK2opNV#9x3sik1GYyCqET7U@vWj7Y!4i2r&Ci>t~vfG#!eWZKvL{G;uKcY z5m19{TL2@}H8okJTv%+X?y_UUXlcLE1;2=I5P$dL0?cLDxTYQ-XzPF<-t7D)xOVnG zal#mSqWK5^d(2zt4nM+MR_%F%^AqT0664|sGwxN|j+;F)%eT?xf%oYl17Qx-YsFZF zY0f*W^=(l4p)3>4gL*gY&6}HMCc;P=%sXiI*Pzjyf&&c!B97XA`lL_KgAak*U5>+E zp5L2%W2IvY!JEsM1M8d-z|bf#D#SqPass1qMXU{p31eweS*W zTl@>e!SnF&xTKlDQHL@`a=O%6^+DewH`Z?YM+85p$F?fI475{zR>z>O(zf&8J3j$!L0Gy5P1(;@ili0pRNMv ztpQ9DtP8WrpEe>ADS9eoTIB}4s{TW`ZI#G-ML0PZ0FSHRY1n*#F2(My&bL0NJ-GOQ zBsyI8{{2N27$V_54ML$%=t~jobA{eTC{n4*!~@|E=$ar99(XnAg6BZ=1}s>%Z=61p z>F!927(UKc_;A55g29ON`QfJ&pIOrUNl;2_d~sC;;(a9&u*(T-7-8}cC&}ca(wCDu zet))n0Zb)ieKD2a-&8ffM6C`aZ~)-%Fa*cVhI(+lBBWG8V0y%-VyFm3ba920+|xc; z-0lsc&k=`Bw}n#D3#>dI|M%zJt$X7sY0E%QhzMpLfg*h6=S`!|&j%yzrRdsj7fXdvzJ_&`3ri{yqp{(A)j~@6|>1t z_BV>!d^seI&|VtX+T#V@opM5;Pc^RX5owLkUB2rE@Mx{mqzA0|KrU{~_s-m1>^KDK zk`gmHe5d*t{m*xsF`v$l|DJzL7bDWlkB~JYu~4q+;Kawz5PcV)eCKOTY+f=5Bed5h z%B_3FFjVN^*sKjMxY$O-adef8jO;Uw42{0c5mXN^-Hs6ZsqLn}Db~CHg_cnx_J8l& z(*ehj+ivI6k6`%6ULaqhxN|5kk8T%|wT*?5e@;l2>adnY0Bh)nZ7G3P;6)|~JD6#@Lfh^ngExyK{vyK$rm zs>{9mIDEUGtj`%F7LzoDf1Ib^v4{@67m%Ap!jczZSBdU?(!RqeH5Lr23T&t(7Vvd(OBV!Ux2DPM|ljdpsbni3u<=iuF|RS|9pgA~omJwXMrXqx!PUy@O*$ zE#kEe0#96pMZv#rIESle$F-A1w^s=%L{F`Euos~`*WdSLl&lSbr_0Az$B_{elp(^L zs9Mj70kaGLN6S>nzCXjQ;=C$8{|~7&4vjm?^K7~wm)MwfSE5t5w&-0#yc?)hz6kz< z_NcB+P~4)pq|tow7J!z6KsFZ?I$T+fr{??w))Xfo2}g1=SYv(aj(GW%D9ji0eskmU z2n4X0(rJBtde*|2q9?f!N8Bvya~p@ke|IOQZ;3Z^v(vGaDuJMkf>;8S0%= z;^X25TCEG-DS3d8*iyRhb@{6d{k2O96opzzwu6FsZwpIk5J-lGev1_<6MOpxhirwK zfD=Be*TvV{Kd4uC*1wQ>K+HL?WtP)~P{t7`KC{;&E4pdOyTG90xK5avy(19EnFl=T ze?%WP1N{XBy8~R*+k$U97mMrKniYNmE&xJJKC|~KSF&XTW4=3LCv$M z50!DNZ^kKik)_4cZ+;$5ra|ynk_9POKOYMGp501TfPcX_k$7^-)NPO+42ibklmfZ| zugwv_G+>8HqZ;++E?Ny*B!GvoG85=E*jEK^wEi-&&0C91?|j4S*buC4f^ew`XcY5Z!vmrWlI;j>+S*m-2*RSrv43b6&#_56K_#b zUA~*2Z&{LMa1>wG`hsox+S{`RsC-DAq45Q966?+YLhaCoE8ejny20umV2fHI-4$3t zAkTnlsP!JRP*z>w6koT?;?u02q_Oqv`t;diXkt>D zv0H1ttiv|Ahpgo4SmYvU8mGBtln%I(m_Py*yk1Ri3+Ojp+}?&G#?!E)fmOuA)e2=; zVSgc32Neh_;4SB8$Iy|)&#!VtnaQFu^NijI7&uiZ~~wyU~Gj3Pk^*F^!f{NuciLl?XXSV}8{2fy&v(9|qiIm(~l7E5y3A*s+V?PJ4$Dw(xsoe6ju5ntc+Sq4$H$o3MD z7p6I^%PKAfEmQXOx5o9#?TN`LIuHuxWQ#BW1sJ>P9MtP_qP@?#APiMuvI( z4@A$rf13NK@8jI;xbbj`CI&sETWXC}C&Aw+&4R=jH99*d2Nb5D9!MJT391hA95&>` z)GdY!LN92I{sN`Hu&emaFUj?Ww0H0JK2hs1gkFVw%(^;hBO{wc)85TGGR@vU!*g-i zv;4gdYg>~~M;(2RU@=AYfDM}5O^wN4YcoGdBiXER$(XZGw=Mn+iPG5_CvwO*diHa+f=?qEUf7&OE(bpgSX%MsQc{$wJ##`$!;Es}@ z03U*+QpU(68`WNPB!1=5^tT+7nlX6gV3jXRi&>f*rOan#>NXTeUT+)2Z0{%G{2`Z> z7G&6LZ`ShI1Cl_H3Of&b`}_S>=HXckpdyXB%2P&hZD9{gG|T zIJ#~VP6(ZcBR5`pIV!kT2rd>zI=6hU5ySn0XAY|z#an&nO@Aype~2&PhL64cKunn$ z>+zkTrJOw@=9%O{^b59ULrVt}2;NTwB%5;|S)0D6_*;~o;VBvMsi%I!YL?oG2I{G7 zUuDA_gp>-QQvzWJDl4~l4ao`ZzZ8Ve!0xR*wApKE#?zH{I(Z{Mem$muG>G-x%;n_= z5KmK29y5gHHAKh|pdp7M(KH`K3e~-yciZ8UCT%axAE=-j5=%*rB`_g8txmfU$UG#o z*Ib|x=akaYy3Ox~7^O{2iu&k2lFLeT;lb)-|3Dmu2wGiN4Jgn0=6^y{=0(8FOtz41-6 z^820e``Gjhc@m=4MlNY3OSwXe=kunk68x}#c$@Y*Tav(Cnps$wlZz|GzgtN4sp#FFAT^~F+P4D`KQ7K^@sqo-6b;Fxd9I84VWF*8PK6!g-?oOS<$0|q zFwaL~`sv=j=u5DX3H{$Kmg0y>MZ?AuKLR8{64^&;q!aK10VL4D0Gabq9Sg_<)jQ`B zOfz*bv+C>XV?gP{Sj}E0(A-t)JZ;NB$e9g;AFR1xV&ijIzNBIOz5#fFSsc4&_Y=_S zYF3sYH)Z@6J9708e%0`3STh=!{+TRG`GBi$Jy__#W7B;JOJ&^UxuGHN+G(jgn_aaiTEQfQh*jdbd~;WvQ=473;^$CQa!Fm5ujYfQ5?7Oo z2{y{FUcdP!j8Hi@#u)ecO=|onVZeqgByjq2qS@X**cf95IRgMJQ=t2pe|UGlaqKWq zw>7YzSc+ZbS-VcOMFpcDCU-7iyV?TC@(u2r`_FNauTgKTvRUPme11Q)CnBL!C@84ec{4PpL-k$PT_msWdEKhrWgY{;i zIC!N)wFk`MA^dYax*h^d6zX*x=of=UKPSq42AUXfq*GrR)C4qd3>pLy?Y6V$IaE#p zdJQ|9eK%Fcy(@VluIlU4-8U*|vXc|!5xHf>v$mKM;n!@gH3CqLuPnC;=O~d1QB&*j zD|($KFQs10-@BQve|=p%j&G|UN0zA~lT&q(oNBRJRUteDxbM3_H-UwU!AS}>H4IAB zMLq)-`@|f~hp>xzu<--gSd_~qJ1ubzOab96A)<(~n;e;K^Nl-aM@tuG&AIg-@6;{6 zQy{uLm;Qw=3n7At@KV@OWi(8!dnF~#%yhew8u4QKPu6N}ES5ie8b z5(iU@p2eAbp7U`8#3k$f`|WUtk0BCTVgb3zE1r+vqM4hTv+x@e;(i(<*G%1_qLVA# zXLAp~2R!b@pf8UaI*B6nu^6$$8R=TNoaR9YgXQTzj~&TSJJ$^b^sw` zCk%+E()?-q<4&K9j<)tkSkA_-sT3ISP8yHe>WlZ_XI|ubSK}hL)kYL>HYZol$XMPt zS>(G<*WFDtB3jEP?SE1JikQ@N;O_c!QSH5!_PgJ>a^5|>CDfL|Q&e^B%US|y+i7=7 zot4`_!kr-&vtDX9)jFmdH;yVioEntt2SPa2+?q-(NhEX@4QXQe0RV`mrZVP{axfMa z`nn*}l!n_MtzkdiEA0C0Kq)gnadJ{JeVmq6g$4(Oq7XWHU2}3B`ij8eYtjN6zuZgu z7cM&_w%0bkxlgs`a!!Rc@UIz2^#E(KC;?r+8-qa8MkxGKmm1IyC0&9 z&4p{s^GoY;cjd%!k#{W}4z^-0->bM@vry416m0*lBKI9_=0Db-^@uh9!?dmDC)C{U zwP}~NEUJEA)J6QoM4{4mmxL9;FJPn?Wz9qtf+{SGn_#$2zG20a83UHHvi~XsiA;S~ z0wKEA{7HX)Qwqx))J=|$cN^A!a=%dJTmF4^`mbhNeeTsQ?`(p1q&GnJ1=H0r07C&F z+yZJb;oxzOCId5|8n8`$^}!buXtAi3yT5(&V36U&CkgHdvHcKw?YOjGv2U{3Up40D z8?T8cqdHrj%GT*6PsmH$;i@n=eGsm1EWgn1NH*L}tG^c>i&PiZWQ=9{fTK(-h)``# zpr1Rp)bSD8+kbJPslg(-=9+we$q@$Cq?@^dz=$Apad7ivCKGU#Y%rVVoOL_>y}N&% zUPlYF%lCXO;5L+dZv2L-bX6`jwo|5ddRr(yn9s**9V3$XyUy)&M!3MZk(Z9nJ2-sG z;<2ia0x9iNwxaW+E7J}}bZzx`_&7-Eg0ie<-{S5WayL~a>xMotz4an<&l34h_{7V& zg)@n!B|N-F)UvCD%_6jr+J|Ht{0KpOVwE>?Po+zkj}HsSW_v^ZcFBwg=QynN#1kuj zTe1mZc_OH0pV>k&QBj~eFE$H-0O7I}6}niuhD5J_RzDDht2I~eSKW(XaXKp0N^G?c z#4C4q4=6V0*%U}zBR|WmBCE~3a!6IoZtgQ_Q#5`yS+25%JIfo`!REY_CjZo=+QZYj ztH&tS@9=qk=$&3@xq-9!18_BL^@@jWb2Pmt>(IiRm=7(y4;~ zdg2Bmb#c-MyOg|KXdZ@YlL@bVJ&68iHZwTeD0M%}sSUwD5%T{S1f{q` z2{U3-JKbi8wpSV#DwzP+K|^jUsnk*i@A_@JmG>8&s0)H5>r zW1Q-#|0$+(KKU@N?R=tK zBR6od6(HF$@b2^75TiAY0SA;nlfTmCE&ZG)8xCSFd~aEcoR(LjDC4rZIsV7lbiUxp zBOlpV!gvjapmO~#`ATG2ahtUZ4I0qdRj^w62ffhY&p933FHgE;-n@JXa;e{-p~n)- z0dJ8iFVgJ(5^fn~ z4$ufzd-S~PJzscLk4HO#Px&gT!vmTelFEX@USH*X+t<@oxmroE@sf8JWciMP(m*?^$Lx*?VU1O-3@y z%1HJK*+Mo+2)V5LeeV1B>-y{J@yIymd_SM}c)gylQcDr6X+yfdPF0lz25+$28*)`{ z^OnJoECGc(pPI*5TRYbAs*Sj*JKMkS2TvdtaVr}_$~{;~<$1;33)hlq9l4&Q4;>1* z6@>oGVVh&c{jLKrv@uN$cT!B`4jwnRK?YBF1#yNOCviXv*iu>={E`gJSV{eRsTo?{ zY7^e?{P-OtS;V^2Ga2bOe|Y}YyuOGhJW?(b;qYMLd8ri#1CD>17icBUT@kmju-;(F zNlU4H-pihJJx~03^H!bYqYQ_}$Im1GxBmE@}6-ty^9vF_2_!^xqNR1c~anX<%o`_F1WEcw_)M(n)Hqu_?{4w5~$(x z5D`>#(AC4t1Kq~%4J8Tx-Vy=n8{y*a-?;BO??Dc~B`TV9EZqURgCc40AA7c;`wqFD<5mY@)F?Sz4 zm|WhY4F+D>{7Vfq2xLn2TRdQ*18OmFI?BPu!^FhIPKX}s@dLK}_8HrGw2j;%Qh+#s zGEb>5;>gd~CTEq*XQ}1}gNZ?wplg0;wT3*&L7ttMswaCe#naRqUTww?$~3cG8+6S+ zaV3u5DG8V7{5>cgkk*M!ifki9RLloGaN1PwQzd%BbDGsKqW-Nr`#u^2P#e`aG2&)ut8yU7c2E=ic?lroDT?%VOf{8 zT>YMEZ3<)D20;vlngG)D(l~y?HwS06#M}!vS@S`2n@X>A3w*&mELg^$l}o>o*9fhD zqGF+X5XE@#%W3#JLK%xeq5oH^vsCo%-?*038Rt!WnI$%)OQQ2P4RoT4^+s1xh0bRf zSAu!L2ToZmw!$^dc9^>z{+>St*-|U?hIFv9_KN+JS^u9Pnh1vtOCx8hP2dd*Ywi!t zNG<~o8@GY2l?IJ%5aP#^kq#R1_1I_HfsYX-90J^eH}$Rv8@|cHpI{IX{~hc1NvjKxkJ46pjoos^);9I0P0sKZEGtl zXAp@1i$-neTS2G>*F6B81~;r@k>CA`A<(CEXbGqy;4 zEQ9)@)W<)@Q15H6DgBX050Y<(8zrCn;bgmRjuvv5VT6Dp>vO!9Ju*r|F7lheJ{tPX zCq>kX#SzW$Ot0273~_%4Kiyq~eSBQ7g?B-GJ;=sL=|#Hh_Gk-{Yu){fO{Y%0 z<26sX^qicWU^e9aFuQws4?4KY$+;&9qYH9z7i|cnBX$op`KG-vOc^p1Ea3Npw%~?I z!Z*X3(i4VEad$_!P#fQGH@;M-{L{~?SwBaH0?`~?6aqG*YGVSa-&y~?7`$pBn&F4w zF%mBCcuMV(2=V5oCdw4R}Bo7FW=u?lCoH)K8c z+J0vW`w%ylkLmZBP@E~O7um9B4B^OIE_WRjMdiu{o>2_bfcp%D^eb-_;k{%lgc*<= z+>I+_y6Zpqs8OV8@ISUwCCV>2Ym08V=v_j6RA>tun5&EMAb>1I4^kdWR>`CPeZLg| zjpjUP0x$)znDd4`_*K!q!&F!_4b#Ph$cHZr*4Kz|c-s6Pww&??w&{InWXtn$`c|WH zPs!T;J+_sId*C~w+`BPMHYOWnEQM}Fw80SFRthWRA(&l(9AoYE*lIlA1O&vv6X65S zVo<^!WOHxm*>v>cjh2R-%WW|}W-9vjJ z9~�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%0A4^u29(C&odmjTrp4W6 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 Ydxl?Pzutp!^$3KryauvT&NB3W05_5jx&QzG literal 0 HcmV?d00001 diff --git a/cmake/ProjectSettings.cmake b/cmake/ProjectSettings.cmake index d6ed36b..bbf60fb 100644 --- a/cmake/ProjectSettings.cmake +++ b/cmake/ProjectSettings.cmake @@ -1,3 +1,13 @@ +# Developer-only settings for a top-level libstgx build. Every one of these +# reaches outside the project's own scope — the source tree, the cache, global +# properties — so the caller only includes this file when PROJECT_IS_TOP_LEVEL. + +configure_file( + "${PROJECT_SOURCE_DIR}/.clangd.in" + "${PROJECT_SOURCE_DIR}/.clangd" + @ONLY +) + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") set(CMAKE_BUILD_TYPE diff --git a/include/stgx/builder.hpp b/include/stgx/builder.hpp new file mode 100644 index 0000000..39c35c2 --- /dev/null +++ b/include/stgx/builder.hpp @@ -0,0 +1,154 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace stgx { + +class SystemBuilder { + public: + SystemBuilder& description(std::string text) { + system_.description = std::move(text); + return *this; + } + + /// Number of processors. + SystemBuilder& m(int processors) { + system_.m = processors; + return *this; + } + + SystemBuilder& task(int c, int d) { + system_.tasks.push_back(TaskParam{.c = c, .d = d, .name = std::nullopt}); + return *this; + } + + SystemBuilder& task(int c, int d, std::string name) { + system_.tasks.push_back(TaskParam{.c = c, .d = d, .name = std::move(name)}); + return *this; + } + + private: + friend class GraphBuilder; + + System system_; +}; + +class NodeBuilder { + public: + NodeBuilder& initial(bool value = true) { + node_.initial = value; + return *this; + } + + NodeBuilder& label(std::string text) { + node_.label = std::move(text); + return *this; + } + + /// Node styling, any CSS colour. + NodeBuilder& border_color(std::string color) { + node_.border_color = std::move(color); + return *this; + } + + NodeBuilder& fill_color(std::string color) { + node_.fill_color = std::move(color); + return *this; + } + + NodeBuilder& task(int c, int d, Release release = Release::None) { + node_.tasks.push_back(TaskState{.c = c, .d = d, .release = release}); + return *this; + } + + NodeBuilder& task(TaskState state) { + node_.tasks.push_back(state); + return *this; + } + + /// `children` in YAML. + NodeBuilder& to(std::string target) { + edges_.push_back( + Edge{.source = node_.id, .target = std::move(target), .kind = EdgeKind::Transition}); + return *this; + } + + /// `loopback` in YAML. + NodeBuilder& loop_to(std::string target) { + edges_.push_back( + Edge{.source = node_.id, .target = std::move(target), .kind = EdgeKind::Loopback}); + return *this; + } + + private: + friend class GraphBuilder; + + explicit NodeBuilder(std::string id) { node_.id = std::move(id); } + + Node node_; + std::vector edges_; +}; + +/// Assemble a graph declaratively. +/// +/// Nothing is checked while building, +// `build()` validates once and reports everything +/// +/// ```cpp +/// auto graph = stgx::GraphBuilder() +/// .system([](auto& s) { s.m(1).task(2, 5, "τ₁").task(3, 7, "τ₂"); }) +/// .node("n00", [](auto& n) { n.initial().task(0, 0).task(0, 0).to("n10"); }) +/// .node("n10", [](auto& n) { n.task(2, 5, stgx::Release::Up).task(0, 0).loop_to("n00"); }) +/// .build(); +/// ``` +class GraphBuilder { + public: + /// Configure the system through a callback taking `SystemBuilder&`. + template SbFn> + GraphBuilder& system(SbFn&& configure) { + SystemBuilder builder; + std::forward(configure)(builder); + + system_ = std::move(builder.system_); + return *this; + } + + GraphBuilder& system(System value) { + system_ = std::move(value); + return *this; + } + + /// Add a node with `id`, configured through a callback taking `NodeBuilder&`. + template NbFn> + GraphBuilder& node(std::string id, NbFn&& configure) { + NodeBuilder builder{std::move(id)}; + std::forward(configure)(builder); + + nodes_.push_back(std::move(builder.node_)); + edges_.insert(edges_.end(), std::make_move_iterator(builder.edges_.begin()), + std::make_move_iterator(builder.edges_.end())); + return *this; + } + + GraphBuilder& node(Node value); + + /// Add an edge without going through a node callback. + GraphBuilder& edge(std::string source, std::string target, EdgeKind kind = EdgeKind::Transition); + + /// Build and validate. The builder stays usable afterwards. + [[nodiscard]] Result build() const; + + private: + System system_; + std::vector nodes_; + std::vector edges_; +}; + +} // namespace stgx diff --git a/include/stgx/diagnostics.hpp b/include/stgx/diagnostics.hpp new file mode 100644 index 0000000..df1afb1 --- /dev/null +++ b/include/stgx/diagnostics.hpp @@ -0,0 +1,133 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace stgx { + +/// Severity of a single diagnostic. +enum class Severity : uint8_t { Error, Warning }; + +/// Machine-readable diagnostic codes. +// NOLINTNEXTLINE(performance-enum-size) +enum class DiagCode : uint16_t { + /// The input is not well-formed YAML, or its shape is not a graph document. + YamlParse, + /// `schemaVersion` is not a positive int, or names a version we cannot read. + SchemaVersion, + /// `nodes` is absent or empty — a graph needs at least one node. + NodesMissing, + /// A node has an empty `id`. + NodeIdEmpty, + /// Two nodes share the same `id`. + NodeIdDuplicate, + /// A requested node does not exist. + NodeNotFound, + /// An edge points at a node that does not exist. + DanglingEdge, + /// `initial` is not set on exactly one node. + InitialCount, + /// `system.tasks` is set and a node carries a different number of tasks. + TaskArityMismatch, + /// A value that must be an int is not one (`2.0`, `2e1`, `true`, ...). + NotAnInt, + /// A value has the wrong YAML shape — a scalar where a sequence is required, + /// a sequence where a mapping is required, a non-boolean `initial`, ... + WrongType, + /// A `release` value is neither `up`/`down`/`none` nor a known alias. + BadRelease, + /// A field of the wire format that this version does not model (warning). + UnsupportedField, + /// A field that is not part of the wire format at all (warning). + UnknownField, + /// A file could not be read or written. + IoError, +}; + +/// Stable lower_case name of a diagnostic code. +[[nodiscard]] std::string_view to_string(DiagCode code); + +/// Stable lower_case name of a severity. +[[nodiscard]] std::string_view to_string(Severity severity); + +/// One problem found while loading, validating or saving a graph. +struct Diagnostic { + DiagCode code = DiagCode::YamlParse; + Severity severity = Severity::Error; + /// Location in wire-format terms, e.g. `nodes[3].children[0]`. May be empty. + std::string path; + /// Human-readable explanation. + std::string message; + + [[nodiscard]] bool is_error() const noexcept { return severity == Severity::Error; } + + /// `error[dangling_edge] nodes[3].children[0]: unknown node "n99"` + [[nodiscard]] std::string to_string() const; + + bool operator==(const Diagnostic&) const = default; +}; + +class Diagnostics { + public: + using value_type = Diagnostic; + using const_iterator = std::vector::const_iterator; + + Diagnostics() = default; + Diagnostics(std::initializer_list items) : items_(items) {} + + void add(Diagnostic diag) { items_.push_back(std::move(diag)); } + + void add(DiagCode code, std::string path, std::string message, + Severity severity = Severity::Error) { + items_.push_back(Diagnostic{.code = code, + .severity = severity, + .path = std::move(path), + .message = std::move(message)}); + } + + /// Append everything from `other`, keeping order. + void merge(const Diagnostics& other) { + items_.insert(items_.end(), other.items_.begin(), other.items_.end()); + } + + [[nodiscard]] bool empty() const noexcept { return items_.empty(); } + [[nodiscard]] std::size_t size() const noexcept { return items_.size(); } + [[nodiscard]] const Diagnostic& operator[](std::size_t index) const { return items_[index]; } + [[nodiscard]] const_iterator begin() const noexcept { return items_.begin(); } + [[nodiscard]] const_iterator end() const noexcept { return items_.end(); } + + /// True if at least one diagnostic has `Severity::Error`. + [[nodiscard]] bool has_errors() const noexcept; + + /// True if any diagnostic carries `code` — handy in tests and dispatch. + [[nodiscard]] bool contains(DiagCode code) const noexcept; + + /// Only the diagnostics with `Severity::Error`. + [[nodiscard]] Diagnostics errors() const; + + /// Only the diagnostics with `Severity::Warning`. + [[nodiscard]] Diagnostics warnings() const; + + /// One diagnostic per line, in order. No trailing newline. + [[nodiscard]] std::string to_string() const; + + bool operator==(const Diagnostics&) const = default; + + private: + std::vector items_; +}; + +namespace diag { + +[[nodiscard]] Diagnostic node_not_found(std::string_view id); +[[nodiscard]] Diagnostic node_id_empty(); +[[nodiscard]] Diagnostic node_id_duplicate(std::string_view id); + +} // namespace diag + +} // namespace stgx diff --git a/include/stgx/graph.hpp b/include/stgx/graph.hpp index 0856e27..59b2ab5 100644 --- a/include/stgx/graph.hpp +++ b/include/stgx/graph.hpp @@ -1,10 +1,146 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + namespace stgx { +namespace detail { + +/// Hash that lets the id maps be queried with `std::string_view` without +/// materializing a `std::string`. +struct StringHash { + using is_transparent = void; + [[nodiscard]] std::size_t operator()(std::string_view key) const noexcept { + return std::hash{}(key); + } +}; + +} // namespace detail + +/// A state-transition graph: system metadata, nodes and edges. class Graph { public: Graph() = default; + + /// Build a graph and validate it. On failure returns every diagnostic found. + [[nodiscard]] static Result create(System system, std::vector nodes, + std::vector edges); + + // --- reading + + [[nodiscard]] const System& system() const noexcept { return system_; } + [[nodiscard]] std::span nodes() const noexcept { return nodes_; } + [[nodiscard]] std::span edges() const noexcept { return edges_; } + [[nodiscard]] std::size_t node_count() const noexcept { return nodes_.size(); } + [[nodiscard]] std::size_t edge_count() const noexcept { return edges_.size(); } + + /// Node with this id, or `nullptr`. The pointer is invalidated by mutations. + [[nodiscard]] const Node* find_node(std::string_view id) const; + [[nodiscard]] bool has_node(std::string_view id) const; + + /// The node flagged `initial`, or `nullptr` if none is. + [[nodiscard]] const Node* initial_node() const; + + /// Edges leaving `id`, in insertion order. Empty for an unknown id. + [[nodiscard]] std::span out_edges(std::string_view id) const; + + [[nodiscard]] bool has_edge(std::string_view source, std::string_view target, + EdgeKind kind) const; + + // --- mutating + + void set_system(System system) { system_ = std::move(system); } + + /// Add a node. Fails on an empty or already used id. + [[nodiscard]] Result add_node(Node node); + + /// Remove a node together with every edge touching it. + /// Returns false if there was no such node. + bool remove_node(std::string_view id); + + /// Rename a node and repoint every edge at it. + /// Fails if `from` is unknown, or `to` is empty or already taken. + [[nodiscard]] Result rename_node(std::string_view from, std::string_view to); + + /// Add an edge. Fails if either endpoint is unknown. Adding an edge that is + /// already there succeeds and changes nothing. + [[nodiscard]] Result add_edge(std::string_view source, std::string_view target, + EdgeKind kind); + + /// Remove one edge. Returns false if there was no such edge. + bool remove_edge(std::string_view source, std::string_view target, EdgeKind kind); + + /// Flag `id` as the initial node, clearing the flag on whichever node had it. + /// Fails if `id` is unknown. + [[nodiscard]] Result set_initial(std::string_view id) { + return mutate_node(id, [this](Node& node) { + for (Node& other : nodes_) other.initial = false; + node.initial = true; + }); + } + + /// Replace the task states of a node. Fails if `id` is unknown. + [[nodiscard]] Result set_node_tasks(std::string_view id, std::vector tasks) { + return mutate_node(id, [&tasks](Node& node) { node.tasks = std::move(tasks); }); + } + + /// Set or clear the label override of a node. Fails if `id` is unknown. + [[nodiscard]] Result set_node_label(std::string_view id, std::optional label) { + return mutate_node(id, [&label](Node& node) { node.label = std::move(label); }); + } + + /// Set or clear the styling of a node; `std::nullopt` falls back to the theme + /// of the visualizer. Fails if `id` is unknown. + [[nodiscard]] Result set_node_border_color(std::string_view id, + std::optional color) { + return mutate_node(id, [&color](Node& node) { node.border_color = std::move(color); }); + } + [[nodiscard]] Result set_node_fill_color(std::string_view id, + std::optional color) { + return mutate_node(id, [&color](Node& node) { node.fill_color = std::move(color); }); + } + + // --- checking + + /// Run every graph-level check. Warnings are never produced here. + [[nodiscard]] Result validate() const; + + [[nodiscard]] bool operator==(const Graph& other) const; + + private: + /// Half-open slice of `edges_` belonging to one source node. + struct EdgeRange { + std::size_t first = 0; + std::size_t count = 0; + }; + + template + using IdMap = std::unordered_map>; + + /// Regroup `edges_` by source node and refill both indexes. + void rebuild_indexes(); + + [[nodiscard]] Node* find_node_mut(std::string_view id); + + System system_; + std::vector nodes_; + /// Grouped by source in node order; within a group, insertion order. + std::vector edges_; + IdMap node_index_; + IdMap out_index_; + + [[nodiscard]] Result mutate_node(std::string_view id, std::function mutation); }; } // namespace stgx diff --git a/include/stgx/model.hpp b/include/stgx/model.hpp new file mode 100644 index 0000000..b279b2f --- /dev/null +++ b/include/stgx/model.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace stgx { + +/// Job release event attached to a task inside a node. +/// +/// Wire values: `up` / `down` / `none`. On load the aliases `↑`, `1` map to +/// `Up` and `↓`, `-1` map to `Down`. +enum class Release : uint8_t { None, Up, Down }; + +/// What an edge means. +enum class EdgeKind : uint8_t { Transition, Loopback }; + +[[nodiscard]] std::string_view to_string(Release release); +[[nodiscard]] std::string_view to_string(EdgeKind kind); + +/// Task parameters of the system +struct TaskParam { + int c = 0; + int d = 0; + std::optional name; + + bool operator==(const TaskParam&) const = default; +}; + +/// Scheduling-system metadata: what the graph is a graph of. +struct System { + std::optional description; + /// Number of processors. + std::optional m; + std::vector tasks; + + /// True when nothing is set — such a `system` is omitted on save. + [[nodiscard]] bool empty() const noexcept { + return !description.has_value() && !m.has_value() && tasks.empty(); + } + + bool operator==(const System&) const = default; +}; + +/// State of one task inside one node: remaining computation and deadline. +struct TaskState { + int c = 0; + int d = 0; + Release release = Release::None; + + bool operator==(const TaskState&) const = default; +}; + +/// A global state of the system. +struct Node { + std::string id; + bool initial = false; + + std::vector tasks; + std::optional label; + std::optional border_color; + std::optional fill_color; + + bool operator==(const Node&) const = default; +}; + +struct Edge { + std::string source; + std::string target; + EdgeKind kind = EdgeKind::Transition; + + bool operator==(const Edge&) const = default; +}; + +/// Wire-format version this build reads and writes. +inline constexpr int kSchemaVersion = 1; + +} // namespace stgx diff --git a/include/stgx/result.hpp b/include/stgx/result.hpp new file mode 100644 index 0000000..21adc54 --- /dev/null +++ b/include/stgx/result.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include + +namespace stgx { + +/// Fallible outcome of a libstgx operation. +/// +/// On failure the error side carries every diagnostic that was found, not just +/// the first one: +/// +/// ```cpp +/// auto graph = stgx::load_yaml_file("in.yaml"); +/// if (!graph) { +/// std::cerr << graph.error().to_string() << '\n'; +/// return 1; +/// } +/// ``` +template +using Result = std::expected; + +/// Wrap a single diagnostic as a failed `Result`. +[[nodiscard]] inline std::unexpected fail(Diagnostic diag) { + Diagnostics diags; + diags.add(std::move(diag)); + return std::unexpected{std::move(diags)}; +} + +/// Wrap a single diagnostic as a failed `Result`. +[[nodiscard]] inline std::unexpected fail(DiagCode code, std::string path, + std::string message) { + return fail(Diagnostic{.code = code, + .severity = Severity::Error, + .path = std::move(path), + .message = std::move(message)}); +} + +/// Wrap a collection of diagnostics as a failed `Result`. +[[nodiscard]] inline std::unexpected fail(Diagnostics diags) { + return std::unexpected{std::move(diags)}; +} + +} // namespace stgx diff --git a/include/stgx/stgx.hpp b/include/stgx/stgx.hpp new file mode 100644 index 0000000..dc5a603 --- /dev/null +++ b/include/stgx/stgx.hpp @@ -0,0 +1,11 @@ +#pragma once + +/// @file +/// Everything libstgx offers, in one include. + +#include +#include +#include +#include +#include +#include diff --git a/include/stgx/yaml.hpp b/include/stgx/yaml.hpp new file mode 100644 index 0000000..5732a49 --- /dev/null +++ b/include/stgx/yaml.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace stgx { + +/// Parse a graph document. +/// +/// Errors are collected, not thrown: a failed load reports every problem it +/// found at once. Warnings — fields of the wire format this version does not +/// model, unknown fields — cannot ride on the error side of a successful load, +/// so pass `warnings` if you care about them. They are filled in on failure +/// too. +/// +/// ```cpp +/// stgx::Diagnostics warnings; +/// auto graph = stgx::load_yaml_file("in.yaml", &warnings); +/// if (!graph) return std::cerr << graph.error().to_string() << '\n', 1; +/// if (!warnings.empty()) std::cerr << warnings.to_string() << '\n'; +/// ``` +[[nodiscard]] Result load_yaml_string(std::string_view yaml, + Diagnostics* warnings = nullptr); + +/// Read and parse a graph document from disk. +[[nodiscard]] Result load_yaml_file(const std::filesystem::path& path, + Diagnostics* warnings = nullptr); + +/// Serialize a graph. Validates first — an invalid graph is never written. +/// +/// Fields left at their default are omitted, so the output stays as close to a +/// hand-written document as the model allows. +[[nodiscard]] Result save_yaml_string(const Graph& graph); + +/// Serialize a graph to disk. Validates first. +[[nodiscard]] Result save_yaml_file(const Graph& graph, const std::filesystem::path& path); + +} // namespace stgx diff --git a/src/builder.cpp b/src/builder.cpp new file mode 100644 index 0000000..f09cad0 --- /dev/null +++ b/src/builder.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include + +#include +#include +#include + +namespace stgx { + +GraphBuilder& GraphBuilder::node(Node value) { + nodes_.push_back(std::move(value)); + return *this; +} + +GraphBuilder& GraphBuilder::edge(std::string source, std::string target, EdgeKind kind) { + edges_.push_back(Edge{.source = std::move(source), .target = std::move(target), .kind = kind}); + return *this; +} + +Result GraphBuilder::build() const { return Graph::create(system_, nodes_, edges_); } + +} // namespace stgx diff --git a/src/diagnostics.cpp b/src/diagnostics.cpp new file mode 100644 index 0000000..edc308a --- /dev/null +++ b/src/diagnostics.cpp @@ -0,0 +1,157 @@ +#include + +#include +#include +#include +#include + +#include + +namespace stgx::diag { + +Diagnostic node_not_found(std::string_view id) { + return { + .code = DiagCode::NodeNotFound, + .severity = Severity::Error, + .path = {}, + .message = std::format(R"(node "{}" does not exist)", id), + }; +} + +Diagnostic node_id_empty() { + return { + .code = DiagCode::NodeIdEmpty, + .severity = Severity::Error, + .path = {}, + .message = "node id must not be empty", + }; +} + +Diagnostic node_id_duplicate(std::string_view id) { + return { + .code = DiagCode::NodeIdDuplicate, + .severity = Severity::Error, + .path = {}, + .message = std::format(R"(node "{}" already exists)", id), + }; +} +} // namespace stgx::diag + +namespace stgx { + +std::string_view to_string(DiagCode code) { + switch (code) { + case DiagCode::YamlParse: + return "yaml_parse"; + case DiagCode::SchemaVersion: + return "schema_version"; + case DiagCode::NodesMissing: + return "nodes_missing"; + case DiagCode::NodeIdEmpty: + return "node_id_empty"; + case DiagCode::NodeIdDuplicate: + return "node_id_duplicate"; + case DiagCode::NodeNotFound: + return "node_not_found"; + case DiagCode::DanglingEdge: + return "dangling_edge"; + case DiagCode::InitialCount: + return "initial_count"; + case DiagCode::TaskArityMismatch: + return "task_arity_mismatch"; + case DiagCode::NotAnInt: + return "not_an_int"; + case DiagCode::WrongType: + return "wrong_type"; + case DiagCode::BadRelease: + return "bad_release"; + case DiagCode::UnsupportedField: + return "unsupported_field"; + case DiagCode::UnknownField: + return "unknown_field"; + case DiagCode::IoError: + return "io_error"; + } + return "unknown"; +} + +std::string_view to_string(Severity severity) { + switch (severity) { + case Severity::Error: + return "error"; + case Severity::Warning: + return "warning"; + } + return "unknown"; +} + +std::string_view to_string(Release release) { + switch (release) { + case Release::None: + return "none"; + case Release::Up: + return "up"; + case Release::Down: + return "down"; + } + return "none"; +} + +std::string_view to_string(EdgeKind kind) { + switch (kind) { + case EdgeKind::Transition: + return "transition"; + case EdgeKind::Loopback: + return "loopback"; + } + return "transition"; +} + +std::string Diagnostic::to_string() const { + std::string out = std::format("{}[{}]", stgx::to_string(severity), stgx::to_string(code)); + + if (!path.empty()) { + std::format_to(std::back_inserter(out), " {}", path); + } + + if (!message.empty()) { + std::format_to(std::back_inserter(out), ": {}", message); + } + + return out; +} + +bool Diagnostics::has_errors() const noexcept { + return std::ranges::any_of(items_, [](const Diagnostic& diag) { return diag.is_error(); }); +} + +bool Diagnostics::contains(DiagCode code) const noexcept { + return std::ranges::any_of(items_, [code](const Diagnostic& diag) { return diag.code == code; }); +} + +Diagnostics Diagnostics::errors() const { + Diagnostics out; + for (const Diagnostic& diag : items_) { + if (diag.is_error()) out.add(diag); + } + return out; +} + +Diagnostics Diagnostics::warnings() const { + Diagnostics out; + for (const Diagnostic& diag : items_) { + if (!diag.is_error()) out.add(diag); + } + return out; +} + +std::string Diagnostics::to_string() const { + std::string out; + for (const Diagnostic& diag : items_) { + if (!out.empty()) out += '\n'; + out += diag.to_string(); + } + return out; +} + +} // namespace stgx diff --git a/src/graph.cpp b/src/graph.cpp index eab6d7e..df550f1 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -1,3 +1,208 @@ #include -namespace stgx {} // namespace stgx +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "validate.hpp" + +namespace stgx { + +Result Graph::mutate_node(std::string_view id, std::function mutation) { + Node* node = find_node_mut(id); + if (node == nullptr) { + return fail(diag::node_not_found(id)); + } + + mutation(*node); + return {}; +} + +Result Graph::create(System system, std::vector nodes, std::vector edges) { + Graph graph; + graph.system_ = std::move(system); + graph.nodes_ = std::move(nodes); + graph.edges_ = std::move(edges); + graph.rebuild_indexes(); + + if (Diagnostics diags = detail::validate_graph(graph.system_, graph.nodes_, graph.edges_); + diags.has_errors()) { + return fail(std::move(diags)); + } + return graph; +} + +void Graph::rebuild_indexes() { + // Build the node lookup table. + node_index_.clear(); + node_index_.reserve(nodes_.size()); + + for (std::size_t node_index = 0; node_index < nodes_.size(); ++node_index) { + // Keep the first occurrence; validation reports duplicate IDs. + node_index_.try_emplace(nodes_[node_index].id, node_index); + } + + // Assign each edge to its source node's bucket. + // Edges with an unknown source go into the final bucket. + const std::size_t unknown_source_bucket = nodes_.size(); + const std::size_t bucket_count = nodes_.size() + 1; + + std::vector edge_counts(bucket_count); + std::vector edge_buckets(edges_.size()); + + for (std::size_t edge_index = 0; edge_index < edges_.size(); ++edge_index) { + const auto source = node_index_.find(edges_[edge_index].source); + const std::size_t bucket = source == node_index_.end() ? unknown_source_bucket : source->second; + + edge_buckets[edge_index] = bucket; + ++edge_counts[bucket]; + } + + // Compute the start position of each bucket. + std::vector bucket_offsets(bucket_count + 1); + std::partial_sum(edge_counts.begin(), edge_counts.end(), bucket_offsets.begin() + 1); + + // Group edges by source while preserving insertion order. + std::vector next_positions(bucket_offsets.begin(), bucket_offsets.end() - 1); + + std::vector grouped_edges(edges_.size()); + + for (std::size_t edge_index = 0; edge_index < edges_.size(); ++edge_index) { + const std::size_t bucket = edge_buckets[edge_index]; + grouped_edges[next_positions[bucket]++] = std::move(edges_[edge_index]); + } + + edges_ = std::move(grouped_edges); + + // Build outgoing-edge ranges. + out_index_.clear(); + out_index_.reserve(nodes_.size()); + + for (std::size_t node_index = 0; node_index < nodes_.size(); ++node_index) { + out_index_.try_emplace(nodes_[node_index].id, EdgeRange{ + .first = bucket_offsets[node_index], + .count = edge_counts[node_index], + }); + } +} + +const Node* Graph::find_node(std::string_view id) const { + const auto it = node_index_.find(id); + return it == node_index_.end() ? nullptr : &nodes_[it->second]; +} + +Node* Graph::find_node_mut(std::string_view id) { + const auto it = node_index_.find(id); + return it == node_index_.end() ? nullptr : &nodes_[it->second]; +} + +bool Graph::has_node(std::string_view id) const { return node_index_.contains(id); } + +const Node* Graph::initial_node() const { + const auto it = std::ranges::find_if(nodes_, [](const Node& node) { return node.initial; }); + return it == nodes_.end() ? nullptr : &*it; +} + +std::span Graph::out_edges(std::string_view id) const { + const auto it = out_index_.find(id); + if (it == out_index_.end()) return {}; + return std::span{edges_}.subspan(it->second.first, it->second.count); +} + +bool Graph::has_edge(std::string_view source, std::string_view target, EdgeKind kind) const { + const std::span out = out_edges(source); + return std::ranges::any_of( + out, [target, kind](const Edge& edge) { return edge.kind == kind && edge.target == target; }); +} + +Result Graph::add_node(Node node) { + if (node.id.empty()) { + return fail(diag::node_id_empty()); + } + if (has_node(node.id)) { + return fail(diag::node_id_duplicate(node.id)); + } + + nodes_.push_back(std::move(node)); + rebuild_indexes(); + return {}; +} + +bool Graph::remove_node(std::string_view id) { + const auto it = node_index_.find(id); + if (it == node_index_.end()) return false; + + nodes_.erase(nodes_.begin() + static_cast(it->second)); + const auto touches_id = [id](const Edge& edge) { return edge.source == id || edge.target == id; }; + edges_.erase(std::ranges::remove_if(edges_, touches_id).begin(), edges_.end()); + + rebuild_indexes(); + return true; +} + +Result Graph::rename_node(std::string_view from, std::string_view to) { + if (to.empty()) { + return fail(diag::node_id_empty()); + } + Node* node = find_node_mut(from); + if (node == nullptr) { + return fail(diag::node_not_found(from)); + } + if (from == to) return {}; + if (has_node(to)) { + return fail(diag::node_id_duplicate(to)); + } + const std::string old_id = node->id; + node->id = std::string{to}; + for (Edge& edge : edges_) { + if (edge.source == old_id) edge.source = to; + if (edge.target == old_id) edge.target = to; + } + + rebuild_indexes(); + return {}; +} + +Result Graph::add_edge(std::string_view source, std::string_view target, EdgeKind kind) { + if (!has_node(source)) return fail(diag::node_not_found(source)); + if (!has_node(target)) return fail(diag::node_not_found(target)); + if (has_edge(source, target, kind)) return {}; + + edges_.push_back( + Edge{.source = std::string{source}, .target = std::string{target}, .kind = kind}); + rebuild_indexes(); + return {}; +} + +bool Graph::remove_edge(std::string_view source, std::string_view target, EdgeKind kind) { + const auto it = std::ranges::find_if(edges_, [source, target, kind](const Edge& edge) { + return edge.kind == kind && edge.source == source && edge.target == target; + }); + if (it == edges_.end()) return false; + + edges_.erase(it); + rebuild_indexes(); + return true; +} + +Result Graph::validate() const { + if (Diagnostics diags = detail::validate_graph(system_, nodes_, edges_); diags.has_errors()) { + return fail(std::move(diags)); + } + return {}; +} +bool Graph::operator==(const Graph& other) const { + return system_ == other.system_ && nodes_ == other.nodes_ && edges_ == other.edges_; +} + +} // namespace stgx diff --git a/src/validate.cpp b/src/validate.cpp new file mode 100644 index 0000000..1b97f0d --- /dev/null +++ b/src/validate.cpp @@ -0,0 +1,118 @@ +#include "validate.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace stgx::detail { +namespace { + +std::string node_path(std::size_t index) { return "nodes[" + std::to_string(index) + "]"; } + +std::string_view edge_field(EdgeKind kind) { + return kind == EdgeKind::Transition ? "children" : "loopback"; +} + +/// Per-source running counters, so a dangling edge can be reported at the +/// position it occupies in the source node's `children` / `loopback` list. +struct EdgeOrdinals { + std::size_t transitions = 0; + std::size_t releases = 0; + + std::size_t next(EdgeKind kind) { + return kind == EdgeKind::Transition ? transitions++ : releases++; + } +}; + +void check_nodes(std::span nodes, Diagnostics& diags, + std::unordered_map& first_index) { + std::size_t initial_count = 0; + for (std::size_t i = 0; i < nodes.size(); ++i) { + const Node& node = nodes[i]; + + if (node.id.empty()) { + diags.add(DiagCode::NodeIdEmpty, node_path(i) + ".id", "node id must not be empty"); + } else if (const auto [it, inserted] = first_index.try_emplace(node.id, i); !inserted) { + diags.add(DiagCode::NodeIdDuplicate, node_path(i) + ".id", + "duplicate node id \"" + node.id + "\", first seen at " + node_path(it->second)); + } + + if (node.initial) ++initial_count; + } + + if (initial_count != 1) { + diags.add(DiagCode::InitialCount, "nodes", + "exactly one node must be initial, found " + std::to_string(initial_count)); + } +} + +void check_task_arity(const System& system, std::span nodes, Diagnostics& diags) { + if (system.tasks.empty()) return; + + const std::size_t expected = system.tasks.size(); + for (std::size_t i = 0; i < nodes.size(); ++i) { + if (nodes[i].tasks.size() == expected) continue; + diags.add(DiagCode::TaskArityMismatch, node_path(i) + ".tasks", + "node \"" + nodes[i].id + "\" has " + std::to_string(nodes[i].tasks.size()) + + " task(s), expected " + std::to_string(expected) + " from system.tasks"); + } +} + +void check_edges(std::span edges, Diagnostics& diags, + const std::unordered_map& first_index) { + std::unordered_map ordinals; + std::unordered_set unknown_sources; + + for (std::size_t e = 0; e < edges.size(); ++e) { + const Edge& edge = edges[e]; + const auto source_it = first_index.find(edge.source); + + if (source_it == first_index.end()) { + // Report an unknown source once, not once per outgoing edge. + if (unknown_sources.insert(edge.source).second) { + diags.add(DiagCode::DanglingEdge, "edges[" + std::to_string(e) + "].source", + "edge leaves unknown node \"" + edge.source + "\""); + } + continue; + } + + const std::size_t ordinal = ordinals[edge.source].next(edge.kind); + if (!first_index.contains(edge.target)) { + diags.add(DiagCode::DanglingEdge, + node_path(source_it->second) + "." + std::string{edge_field(edge.kind)} + "[" + + std::to_string(ordinal) + "]", + "unknown node \"" + edge.target + "\" referenced from \"" + edge.source + "\""); + } + } +} + +} // namespace + +Diagnostics validate_graph(const System& system, std::span nodes, + std::span edges) { + Diagnostics diags; + + if (nodes.empty()) { + diags.add(DiagCode::NodesMissing, "nodes", "a graph needs at least one node"); + // Every remaining check is about nodes; with none there is nothing to say. + return diags; + } + + std::unordered_map first_index; + first_index.reserve(nodes.size()); + + check_nodes(nodes, diags, first_index); + check_task_arity(system, nodes, diags); + check_edges(edges, diags, first_index); + + return diags; +} + +} // namespace stgx::detail diff --git a/src/validate.hpp b/src/validate.hpp new file mode 100644 index 0000000..d1da396 --- /dev/null +++ b/src/validate.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include +#include + +namespace stgx::detail { + +/// Run every graph-level check over a raw model triple. +/// +/// Works on loose vectors rather than a `Graph` so that both the YAML loader +/// and `Graph::create()` can validate before a graph exists. Collects all +/// findings instead of stopping at the first one. +/// +/// Diagnostic paths are expressed in wire-format terms — `nodes[3].id`, +/// `nodes[3].children[0]` — which requires `edges` to be grouped by source in +/// node order, exactly how `Graph` and the loader keep them. Edges whose source +/// is unknown are reported as `edges[i]`. +[[nodiscard]] Diagnostics validate_graph(const System& system, std::span nodes, + std::span edges); + +} // namespace stgx::detail diff --git a/src/yaml_load.cpp b/src/yaml_load.cpp new file mode 100644 index 0000000..5dbfb65 --- /dev/null +++ b/src/yaml_load.cpp @@ -0,0 +1,374 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "validate.hpp" + +namespace stgx { +namespace { + +// --- paths + +std::string field_path(std::string_view base, std::string_view field) { + std::string out{base}; + if (!out.empty()) out += '.'; + out += field; + return out; +} + +std::string index_path(std::string_view base, std::size_t index) { + return std::string{base} + "[" + std::to_string(index) + "]"; +} + +// --- scalar readers + +/// A key that is present but null counts as absent. +bool is_absent(const YAML::Node& node) { return !node.IsDefined() || node.IsNull(); } + +std::optional read_string(const YAML::Node& node, const std::string& path, + Diagnostics& diags) { + if (!node.IsScalar()) { + diags.add(DiagCode::WrongType, path, "expected a string"); + return std::nullopt; + } + return node.Scalar(); +} + +/// Strict decimal int. Rejects `2.0`, `2e1`, `0x10`, `true` and empty values — +/// the wire format says `c`, `d` and `m` are ints, and a silent truncation here +/// would be a data bug in whatever produced the file. +std::optional read_int(const YAML::Node& node, const std::string& path, Diagnostics& diags) { + if (!node.IsScalar()) { + diags.add(DiagCode::WrongType, path, "expected an integer"); + return std::nullopt; + } + + const std::string& text = node.Scalar(); + std::string_view digits{text}; + if (digits.starts_with('+')) digits.remove_prefix(1); + + int value = 0; + const auto* const last = digits.data() + digits.size(); + // from_chars takes both ends, so the view needs no terminator. + // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) + const auto result = std::from_chars(digits.data(), last, value); + if (result.ec != std::errc{} || result.ptr != last) { + diags.add(DiagCode::NotAnInt, path, "expected an integer, got \"" + text + "\""); + return std::nullopt; + } + return value; +} + +std::optional read_bool(const YAML::Node& node, const std::string& path, Diagnostics& diags) { + if (node.IsScalar()) { + const std::string& text = node.Scalar(); + for (std::string_view yes : {"true", "True", "TRUE", "yes", "Yes", "on", "On"}) { + if (text == yes) return true; + } + for (std::string_view no : {"false", "False", "FALSE", "no", "No", "off", "Off"}) { + if (text == no) return false; + } + } + diags.add(DiagCode::WrongType, path, "expected a boolean"); + return std::nullopt; +} + +/// `up` / `down` / `none`, plus the aliases the wire format documents: +/// `↑` and `1` for up, `↓` and `-1` for down. +std::optional read_release(const YAML::Node& node, const std::string& path, + Diagnostics& diags) { + if (node.IsScalar()) { + const std::string& text = node.Scalar(); + if (text == "up" || text == "↑" || text == "1") return Release::Up; + if (text == "down" || text == "↓" || text == "-1") return Release::Down; + if (text == "none") return Release::None; + diags.add(DiagCode::BadRelease, path, + "expected up/down/none (or ↑/↓/1/-1), got \"" + text + "\""); + return std::nullopt; + } + diags.add(DiagCode::BadRelease, path, "expected up/down/none (or ↑/↓/1/-1)"); + return std::nullopt; +} + +// --- key checking + +bool contains(std::initializer_list keys, std::string_view key) { + for (std::string_view candidate : keys) { + if (candidate == key) return true; + } + return false; +} + +/// Report fields we recognise but do not model yet, and fields we do not know +/// at all. Both are warnings: the document still loads, but a later save will +/// not carry them over, and silently eating someone's annotations would be +/// worse than saying so. +void check_keys(const YAML::Node& map, const std::string& path, + std::initializer_list known, + std::initializer_list unsupported, Diagnostics& diags) { + for (const auto& entry : map) { + if (!entry.first.IsScalar()) { + diags.add(DiagCode::UnknownField, path, "non-scalar key", Severity::Warning); + continue; + } + const std::string key = entry.first.Scalar(); + if (contains(unsupported, key)) { + diags.add(DiagCode::UnsupportedField, field_path(path, key), + "not modelled in this version; it will be dropped when saving", Severity::Warning); + } else if (!contains(known, key)) { + diags.add(DiagCode::UnknownField, field_path(path, key), "not part of the wire format", + Severity::Warning); + } + } +} + +// --- section readers --------------------------------------------------------- + +TaskParam read_task_param(const YAML::Node& node, const std::string& path, Diagnostics& diags) { + TaskParam task; + if (!node.IsMap()) { + diags.add(DiagCode::WrongType, path, "expected a mapping with c, d and an optional name"); + return task; + } + check_keys(node, path, {"c", "d", "name"}, {}, diags); + + if (const auto value = read_int(node["c"], field_path(path, "c"), diags)) task.c = *value; + if (const auto value = read_int(node["d"], field_path(path, "d"), diags)) task.d = *value; + if (!is_absent(node["name"])) { + task.name = read_string(node["name"], field_path(path, "name"), diags); + } + return task; +} + +System read_system(const YAML::Node& node, const std::string& path, Diagnostics& diags) { + System system; + if (!node.IsMap()) { + diags.add(DiagCode::WrongType, path, "expected a mapping"); + return system; + } + check_keys(node, path, {"description", "m", "tasks"}, {}, diags); + + if (!is_absent(node["description"])) { + system.description = read_string(node["description"], field_path(path, "description"), diags); + } + if (!is_absent(node["m"])) { + system.m = read_int(node["m"], field_path(path, "m"), diags); + } + + const YAML::Node tasks = node["tasks"]; + if (!is_absent(tasks)) { + const std::string tasks_path = field_path(path, "tasks"); + if (!tasks.IsSequence()) { + diags.add(DiagCode::WrongType, tasks_path, "expected a sequence"); + } else { + system.tasks.reserve(tasks.size()); + for (std::size_t i = 0; i < tasks.size(); ++i) { + system.tasks.push_back(read_task_param(tasks[i], index_path(tasks_path, i), diags)); + } + } + } + return system; +} + +TaskState read_task_state(const YAML::Node& node, const std::string& path, Diagnostics& diags) { + TaskState task; + if (!node.IsMap()) { + diags.add(DiagCode::WrongType, path, "expected a mapping with c, d and an optional release"); + return task; + } + check_keys(node, path, {"c", "d", "release"}, {}, diags); + + if (!is_absent(node["c"])) { + if (const auto value = read_int(node["c"], field_path(path, "c"), diags)) task.c = *value; + } + if (!is_absent(node["d"])) { + if (const auto value = read_int(node["d"], field_path(path, "d"), diags)) task.d = *value; + } + if (!is_absent(node["release"])) { + if (const auto value = read_release(node["release"], field_path(path, "release"), diags)) { + task.release = *value; + } + } + return task; +} + +/// Turn a `children` / `loopback` list into edges leaving `source`. +void read_targets(const YAML::Node& node, const std::string& path, EdgeKind kind, + const std::string& source, std::vector& edges, Diagnostics& diags) { + if (is_absent(node)) return; + if (!node.IsSequence()) { + diags.add(DiagCode::WrongType, path, "expected a sequence of node ids"); + return; + } + for (std::size_t i = 0; i < node.size(); ++i) { + if (auto target = read_string(node[i], index_path(path, i), diags)) { + edges.push_back(Edge{.source = source, .target = *std::move(target), .kind = kind}); + } + } +} + +Node read_node(const YAML::Node& node, const std::string& path, std::vector& edges, + Diagnostics& diags) { + Node out; + if (!node.IsMap()) { + diags.add(DiagCode::WrongType, path, "expected a mapping"); + return out; + } + check_keys(node, path, + {"id", "initial", "isInitial", "tasks", "children", "loopback", "label", "borderColor", + "fillColor"}, + {"hatch", "metadata"}, diags); + + if (auto id = read_string(node["id"], field_path(path, "id"), diags)) { + out.id = *std::move(id); + } + + // `isInitial` is a legacy spelling the visualizer still accepts on read. + for (std::string_view key : {"initial", "isInitial"}) { + const YAML::Node flag = node[std::string{key}]; + if (is_absent(flag)) continue; + if (const auto value = read_bool(flag, field_path(path, key), diags)) out.initial |= *value; + } + + if (!is_absent(node["label"])) { + out.label = read_string(node["label"], field_path(path, "label"), diags); + } + if (!is_absent(node["borderColor"])) { + out.border_color = read_string(node["borderColor"], field_path(path, "borderColor"), diags); + } + if (!is_absent(node["fillColor"])) { + out.fill_color = read_string(node["fillColor"], field_path(path, "fillColor"), diags); + } + + const YAML::Node tasks = node["tasks"]; + if (!is_absent(tasks)) { + const std::string tasks_path = field_path(path, "tasks"); + if (!tasks.IsSequence()) { + diags.add(DiagCode::WrongType, tasks_path, "expected a sequence"); + } else { + out.tasks.reserve(tasks.size()); + for (std::size_t i = 0; i < tasks.size(); ++i) { + out.tasks.push_back(read_task_state(tasks[i], index_path(tasks_path, i), diags)); + } + } + } + + // Keep edges grouped by source, children before loopback — the order both + // Graph and the diagnostics paths assume. + read_targets(node["children"], field_path(path, "children"), EdgeKind::Transition, out.id, edges, + diags); + read_targets(node["loopback"], field_path(path, "loopback"), EdgeKind::Loopback, out.id, edges, + diags); + return out; +} + +void read_schema_version(const YAML::Node& node, Diagnostics& diags) { + if (is_absent(node)) return; // absent means version 1 + + const auto version = read_int(node, "schemaVersion", diags); + if (!version.has_value()) return; + if (*version < 1) { + diags.add(DiagCode::SchemaVersion, "schemaVersion", + "must be a positive integer, got " + std::to_string(*version)); + } else if (*version > kSchemaVersion) { + diags.add(DiagCode::SchemaVersion, "schemaVersion", + "document is version " + std::to_string(*version) + ", this build reads up to " + + std::to_string(kSchemaVersion)); + } +} + +/// Hand the collected diagnostics to the caller and build the graph if the +/// document was sound. +/// +/// Field-level problems do not stop the structural checks: one load reports +/// everything that is wrong with the document, not just the first layer of it. +Result finish(System system, std::vector nodes, std::vector edges, + const Diagnostics& diags, Diagnostics* warnings) { + if (warnings != nullptr) warnings->merge(diags.warnings()); + + Diagnostics errors = diags.errors(); + errors.merge(detail::validate_graph(system, nodes, edges)); + if (!errors.empty()) return fail(std::move(errors)); + + return Graph::create(std::move(system), std::move(nodes), std::move(edges)); +} + +Result load_document(const YAML::Node& root, Diagnostics* warnings) { + if (is_absent(root)) { + return fail(DiagCode::YamlParse, "", "document is empty"); + } + if (!root.IsMap()) { + return fail(DiagCode::WrongType, "", "top level must be a mapping"); + } + + Diagnostics diags; + + check_keys(root, "", {"schemaVersion", "system", "nodes"}, {"areas", "layout"}, diags); + read_schema_version(root["schemaVersion"], diags); + + System system; + if (!is_absent(root["system"])) { + system = read_system(root["system"], "system", diags); + } + + std::vector nodes; + std::vector edges; + const YAML::Node nodes_node = root["nodes"]; + if (is_absent(nodes_node)) { + // Left to validate_graph, so that "key absent" and "empty list" read alike. + } else if (!nodes_node.IsSequence()) { + diags.add(DiagCode::WrongType, "nodes", "expected a sequence"); + } else { + nodes.reserve(nodes_node.size()); + for (std::size_t i = 0; i < nodes_node.size(); ++i) { + nodes.push_back(read_node(nodes_node[i], index_path("nodes", i), edges, diags)); + } + } + + return finish(std::move(system), std::move(nodes), std::move(edges), diags, warnings); +} + +} // namespace + +Result load_yaml_string(std::string_view yaml, Diagnostics* warnings) { + YAML::Node root; + try { + root = YAML::Load(std::string{yaml}); + } catch (const YAML::Exception& error) { + return fail(DiagCode::YamlParse, "", error.what()); + } + return load_document(root, warnings); +} + +Result load_yaml_file(const std::filesystem::path& path, Diagnostics* warnings) { + std::ifstream file(path, std::ios::binary); + if (!file) { + return fail(DiagCode::IoError, path.string(), "cannot open file for reading"); + } + + std::ostringstream buffer; + buffer << file.rdbuf(); + if (!file && !file.eof()) { + return fail(DiagCode::IoError, path.string(), "cannot read file"); + } + return load_yaml_string(buffer.str(), warnings); +} + +} // namespace stgx diff --git a/src/yaml_save.cpp b/src/yaml_save.cpp new file mode 100644 index 0000000..3eb348c --- /dev/null +++ b/src/yaml_save.cpp @@ -0,0 +1,127 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace stgx { +namespace { + +void emit_system(YAML::Emitter& out, const System& system) { + out << YAML::Key << "system" << YAML::Value << YAML::BeginMap; + if (system.description.has_value()) { + out << YAML::Key << "description" << YAML::Value << *system.description; + } + if (system.m.has_value()) { + out << YAML::Key << "m" << YAML::Value << *system.m; + } + if (!system.tasks.empty()) { + out << YAML::Key << "tasks" << YAML::Value << YAML::BeginSeq; + for (const TaskParam& task : system.tasks) { + out << YAML::Flow << YAML::BeginMap; + out << YAML::Key << "c" << YAML::Value << task.c; + out << YAML::Key << "d" << YAML::Value << task.d; + if (task.name.has_value()) out << YAML::Key << "name" << YAML::Value << *task.name; + out << YAML::EndMap; + } + out << YAML::EndSeq; + } + out << YAML::EndMap; +} + +/// Write the `children` or `loopback` list of one node, skipping it entirely +/// when the node has no edges of that kind. +void emit_targets(YAML::Emitter& out, std::string_view field, std::span edges, + EdgeKind kind) { + bool opened = false; + for (const Edge& edge : edges) { + if (edge.kind != kind) continue; + if (!opened) { + out << YAML::Key << std::string{field} << YAML::Value << YAML::Flow << YAML::BeginSeq; + opened = true; + } + out << edge.target; + } + if (opened) out << YAML::EndSeq; +} + +void emit_node(YAML::Emitter& out, const Node& node, std::span out_edges) { + out << YAML::BeginMap; + out << YAML::Key << "id" << YAML::Value << node.id; + if (node.initial) out << YAML::Key << "initial" << YAML::Value << true; + if (node.label.has_value()) out << YAML::Key << "label" << YAML::Value << *node.label; + if (node.border_color.has_value()) { + out << YAML::Key << "borderColor" << YAML::Value << *node.border_color; + } + if (node.fill_color.has_value()) { + out << YAML::Key << "fillColor" << YAML::Value << *node.fill_color; + } + + if (!node.tasks.empty()) { + out << YAML::Key << "tasks" << YAML::Value << YAML::BeginSeq; + for (const TaskState& task : node.tasks) { + out << YAML::Flow << YAML::BeginMap; + out << YAML::Key << "c" << YAML::Value << task.c; + out << YAML::Key << "d" << YAML::Value << task.d; + if (task.release != Release::None) { + out << YAML::Key << "release" << YAML::Value << std::string{to_string(task.release)}; + } + out << YAML::EndMap; + } + out << YAML::EndSeq; + } + + emit_targets(out, "children", out_edges, EdgeKind::Transition); + emit_targets(out, "loopback", out_edges, EdgeKind::Loopback); + out << YAML::EndMap; +} + +} // namespace + +Result save_yaml_string(const Graph& graph) { + if (auto valid = graph.validate(); !valid) { + return fail(std::move(valid).error()); + } + + YAML::Emitter out; + out << YAML::BeginMap; + out << YAML::Key << "schemaVersion" << YAML::Value << kSchemaVersion; + if (!graph.system().empty()) emit_system(out, graph.system()); + + out << YAML::Key << "nodes" << YAML::Value << YAML::BeginSeq; + for (const Node& node : graph.nodes()) { + emit_node(out, node, graph.out_edges(node.id)); + } + out << YAML::EndSeq; + out << YAML::EndMap; + + if (!out.good()) { + return fail(DiagCode::YamlParse, "", "emitter failed: " + out.GetLastError()); + } + return std::string{out.c_str()} + "\n"; +} + +Result save_yaml_file(const Graph& graph, const std::filesystem::path& path) { + auto text = save_yaml_string(graph); + if (!text) return fail(std::move(text).error()); + + std::ofstream file(path, std::ios::binary | std::ios::trunc); + if (!file) { + return fail(DiagCode::IoError, path.string(), "cannot open file for writing"); + } + file << *text; + if (!file) { + return fail(DiagCode::IoError, path.string(), "cannot write file"); + } + return {}; +} + +} // namespace stgx diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 35295bc..820bab8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,6 +13,11 @@ target_link_libraries(stgx_tests Catch2::Catch2 ) +target_compile_definitions(stgx_tests + PRIVATE + STGX_TEST_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" +) + include(Catch OPTIONAL RESULT_VARIABLE STGX_CATCH_MODULE) if(STGX_CATCH_MODULE) catch_discover_tests(stgx_tests) diff --git a/tests/builder_test.cpp b/tests/builder_test.cpp new file mode 100644 index 0000000..f981651 --- /dev/null +++ b/tests/builder_test.cpp @@ -0,0 +1,138 @@ +#include + +#include + +#include +#include + +using stgx::DiagCode; +using stgx::EdgeKind; +using stgx::GraphBuilder; +using stgx::Release; + +TEST_CASE("the example from the design document builds", "[builder]") { + const auto graph = + GraphBuilder() + .system([](auto& s) { s.description("EDF").m(2).task(1, 2, "τ1").task(1, 2, "τ2"); }) + .node("n0", [](auto& n) { n.initial().task(0, 0).task(0, 0).to("n11").to("n12"); }) + .node("n11", [](auto& n) { n.task(1, 2, Release::Up).task(0, 0).loop_to("n0"); }) + .node("n12", [](auto& n) { n.task(0, 0).task(1, 2, Release::Up).loop_to("n0"); }) + .build(); + + REQUIRE(graph.has_value()); + CHECK(graph->node_count() == 3); + CHECK(graph->edge_count() == 4); + + const stgx::System& system = graph->system(); + CHECK(system.description == "EDF"); + CHECK(system.m == 2); + REQUIRE(system.tasks.size() == 2); + CHECK(system.tasks[1].name == "τ2"); + + REQUIRE(graph->initial_node() != nullptr); + CHECK(graph->initial_node()->id == "n0"); + + const auto out = graph->out_edges("n0"); + REQUIRE(out.size() == 2); + CHECK(out[0].target == "n11"); + CHECK(out[0].kind == EdgeKind::Transition); + CHECK(out[1].target == "n12"); + + const auto loopback = graph->out_edges("n11"); + REQUIRE(loopback.size() == 1); + CHECK(loopback[0].kind == EdgeKind::Loopback); + CHECK(loopback[0].target == "n0"); + + CHECK(graph->find_node("n11")->tasks[0].release == Release::Up); +} + +TEST_CASE("declaration order does not matter", "[builder]") { + // n0 points at n1 before n1 exists. + const auto graph = GraphBuilder() + .node("n0", [](auto& n) { n.initial().to("n1"); }) + .node("n1", [](auto& n) { n.loop_to("n0"); }) + .build(); + + REQUIRE(graph.has_value()); + CHECK(graph->has_edge("n0", "n1", EdgeKind::Transition)); + CHECK(graph->has_edge("n1", "n0", EdgeKind::Loopback)); +} + +TEST_CASE("labels and explicit task states go through", "[builder]") { + const auto graph = GraphBuilder() + .node("only", + [](auto& n) { + n.initial() + .label("the only one") + .border_color("#C0392B") + .fill_color("#F9D5D3") + .task(stgx::TaskState{1, 3, Release::Down}); + }) + .build(); + + REQUIRE(graph.has_value()); + const stgx::Node* only = graph->find_node("only"); + REQUIRE(only != nullptr); + CHECK(only->label == "the only one"); + CHECK(only->border_color == "#C0392B"); + CHECK(only->fill_color == "#F9D5D3"); + REQUIRE(only->tasks.size() == 1); + CHECK(only->tasks[0].c == 1); + CHECK(only->tasks[0].d == 3); + CHECK(only->tasks[0].release == Release::Down); +} + +TEST_CASE("prebuilt model values can be handed over directly", "[builder]") { + stgx::System system; + system.m = 1; + + stgx::Node first; + first.id = "a"; + first.initial = true; + stgx::Node second; + second.id = "b"; + + const auto graph = GraphBuilder() + .system(system) + .node(first) + .node(second) + .edge("a", "b") + .edge("b", "a", EdgeKind::Loopback) + .build(); + + REQUIRE(graph.has_value()); + CHECK(graph->system().m == 1); + CHECK(graph->has_edge("a", "b", EdgeKind::Transition)); + CHECK(graph->has_edge("b", "a", EdgeKind::Loopback)); +} + +TEST_CASE("build reports everything that is wrong at once", "[builder]") { + const auto graph = GraphBuilder() + .node("dup", [](auto& n) { n.to("ghost"); }) + .node("dup", [](auto& n) { n.initial(); }) + .build(); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::NodeIdDuplicate)); + CHECK(graph.error().contains(DiagCode::DanglingEdge)); +} + +TEST_CASE("a builder without nodes fails", "[builder]") { + const auto graph = GraphBuilder().build(); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::NodesMissing)); +} + +TEST_CASE("the builder stays usable after build", "[builder]") { + GraphBuilder builder; + builder.node("a", [](auto& n) { n.initial().to("b"); }); + + const auto incomplete = builder.build(); + CHECK_FALSE(incomplete.has_value()); // b is missing + + builder.node("b", [](auto&) {}); + const auto complete = builder.build(); + REQUIRE(complete.has_value()); + CHECK(complete->node_count() == 2); +} diff --git a/tests/data/aliases.yaml b/tests/data/aliases.yaml new file mode 100644 index 0000000..9e8f3b4 --- /dev/null +++ b/tests/data/aliases.yaml @@ -0,0 +1,17 @@ +# release aliases, the legacy isInitial spelling, and omitted fields +nodes: + - id: a + isInitial: true + tasks: + - { c: 1, d: 3, release: ↑ } + - { d: 2 } + children: [b, c] + - id: b + tasks: + - { c: 0, d: 2, release: ↓ } + - { c: 0, d: 0, release: none } + loopback: [a] + - id: c + tasks: + - { c: 1, d: 3, release: 1 } + - { c: 2, d: 4, release: -1 } diff --git a/tests/data/invalid_bad_int.yaml b/tests/data/invalid_bad_int.yaml new file mode 100644 index 0000000..6c28182 --- /dev/null +++ b/tests/data/invalid_bad_int.yaml @@ -0,0 +1,5 @@ +nodes: + - id: n0 + initial: true + tasks: + - {c: 2.5, d: 5} diff --git a/tests/data/invalid_bad_release.yaml b/tests/data/invalid_bad_release.yaml new file mode 100644 index 0000000..e284d19 --- /dev/null +++ b/tests/data/invalid_bad_release.yaml @@ -0,0 +1,5 @@ +nodes: + - id: n0 + initial: true + tasks: + - {c: 1, d: 2, release: sideways} diff --git a/tests/data/invalid_bad_yaml.yaml b/tests/data/invalid_bad_yaml.yaml new file mode 100644 index 0000000..730a855 --- /dev/null +++ b/tests/data/invalid_bad_yaml.yaml @@ -0,0 +1,4 @@ +nodes: + - id: n0 + initial: true + children: [oops diff --git a/tests/data/invalid_dangling.yaml b/tests/data/invalid_dangling.yaml new file mode 100644 index 0000000..51fb2e7 --- /dev/null +++ b/tests/data/invalid_dangling.yaml @@ -0,0 +1,6 @@ +nodes: + - id: n0 + initial: true + children: [n1] + - id: n1 + loopback: [n99] diff --git a/tests/data/invalid_duplicate_id.yaml b/tests/data/invalid_duplicate_id.yaml new file mode 100644 index 0000000..d3bd975 --- /dev/null +++ b/tests/data/invalid_duplicate_id.yaml @@ -0,0 +1,4 @@ +nodes: + - id: n0 + initial: true + - id: n0 diff --git a/tests/data/invalid_empty_id.yaml b/tests/data/invalid_empty_id.yaml new file mode 100644 index 0000000..5393548 --- /dev/null +++ b/tests/data/invalid_empty_id.yaml @@ -0,0 +1,3 @@ +nodes: + - id: "" + initial: true diff --git a/tests/data/invalid_empty_nodes.yaml b/tests/data/invalid_empty_nodes.yaml new file mode 100644 index 0000000..2c026b8 --- /dev/null +++ b/tests/data/invalid_empty_nodes.yaml @@ -0,0 +1,2 @@ +schemaVersion: 1 +nodes: [] diff --git a/tests/data/invalid_no_initial.yaml b/tests/data/invalid_no_initial.yaml new file mode 100644 index 0000000..28bde26 --- /dev/null +++ b/tests/data/invalid_no_initial.yaml @@ -0,0 +1,3 @@ +nodes: + - id: n0 + - id: n1 diff --git a/tests/data/invalid_no_nodes.yaml b/tests/data/invalid_no_nodes.yaml new file mode 100644 index 0000000..aed90a8 --- /dev/null +++ b/tests/data/invalid_no_nodes.yaml @@ -0,0 +1,3 @@ +schemaVersion: 1 +system: + m: 1 diff --git a/tests/data/invalid_schema_version.yaml b/tests/data/invalid_schema_version.yaml new file mode 100644 index 0000000..dca67a6 --- /dev/null +++ b/tests/data/invalid_schema_version.yaml @@ -0,0 +1,4 @@ +schemaVersion: 99 +nodes: + - id: n0 + initial: true diff --git a/tests/data/invalid_task_arity.yaml b/tests/data/invalid_task_arity.yaml new file mode 100644 index 0000000..49d36c6 --- /dev/null +++ b/tests/data/invalid_task_arity.yaml @@ -0,0 +1,9 @@ +system: + tasks: + - {c: 1, d: 2} + - {c: 1, d: 2} +nodes: + - id: n0 + initial: true + tasks: + - {c: 0, d: 0} diff --git a/tests/data/invalid_two_initial.yaml b/tests/data/invalid_two_initial.yaml new file mode 100644 index 0000000..8301201 --- /dev/null +++ b/tests/data/invalid_two_initial.yaml @@ -0,0 +1,5 @@ +nodes: + - id: n0 + initial: true + - id: n1 + initial: true diff --git a/tests/data/invalid_wrong_type.yaml b/tests/data/invalid_wrong_type.yaml new file mode 100644 index 0000000..c8ca1a2 --- /dev/null +++ b/tests/data/invalid_wrong_type.yaml @@ -0,0 +1,4 @@ +nodes: + - id: n0 + initial: maybe + children: n1 diff --git a/tests/data/minimal.yaml b/tests/data/minimal.yaml new file mode 100644 index 0000000..6e17362 --- /dev/null +++ b/tests/data/minimal.yaml @@ -0,0 +1,4 @@ +schemaVersion: 1 +nodes: + - id: n0 + initial: true diff --git a/tests/data/two-tasks.yaml b/tests/data/two-tasks.yaml new file mode 100644 index 0000000..d7d370f --- /dev/null +++ b/tests/data/two-tasks.yaml @@ -0,0 +1,25 @@ +schemaVersion: 1 +system: + description: EDF feasibility graph + m: 1 + tasks: + - {c: 2, d: 5, name: τ₁} + - {c: 3, d: 7, name: τ₂} +nodes: + - id: n00 + initial: true + tasks: + - {c: 0, d: 0} + - {c: 0, d: 0} + children: [n10, n20] + - id: n10 + tasks: + - {c: 2, d: 5, release: up} + - {c: 0, d: 0} + children: [n20] + - id: n20 + label: "custom: label" + tasks: + - {c: 0, d: 3, release: down} + - {c: 0, d: 0} + loopback: [n00] diff --git a/tests/data/unsupported.yaml b/tests/data/unsupported.yaml new file mode 100644 index 0000000..8c6893d --- /dev/null +++ b/tests/data/unsupported.yaml @@ -0,0 +1,16 @@ +schemaVersion: 1 +nodes: + - id: n0 + initial: true + borderColor: "#C0392B" + fillColor: "#E8F4F8" + hatch: single + metadata: { origin: solver } + children: [n1] + - id: n1 + dangerouslyUnknown: 42 +areas: + - id: burst + nodes: [n0, n1] +layout: + algorithm: concentric diff --git a/tests/graph_test.cpp b/tests/graph_test.cpp index ec15ddf..7a0676e 100644 --- a/tests/graph_test.cpp +++ b/tests/graph_test.cpp @@ -1,8 +1,207 @@ #include #include +#include +#include -TEST_CASE("Graph default construction", "[graph]") { - stgx::Graph g; - SUCCEED("Graph constructs"); +#include + +using stgx::DiagCode; +using stgx::Edge; +using stgx::EdgeKind; +using stgx::Graph; +using stgx::Node; + +namespace { + +/// a --> b --> c, and c loops back to a. +Graph triangle() { + Node a; + a.id = "a"; + a.initial = true; + Node b; + b.id = "b"; + Node c; + c.id = "c"; + + auto graph = + Graph::create({}, {a, b, c}, + {Edge{"a", "b", EdgeKind::Transition}, Edge{"b", "c", EdgeKind::Transition}, + Edge{"c", "a", EdgeKind::Loopback}}); + REQUIRE(graph.has_value()); + return *graph; +} + +} // namespace + +TEST_CASE("an empty graph is empty", "[graph]") { + const Graph graph; + + CHECK(graph.node_count() == 0); + CHECK(graph.edge_count() == 0); + CHECK(graph.initial_node() == nullptr); + CHECK(graph.find_node("nope") == nullptr); + CHECK(graph.out_edges("nope").empty()); + // An empty graph is not a valid document. + CHECK_FALSE(graph.validate().has_value()); +} + +TEST_CASE("reading a graph", "[graph]") { + const Graph graph = triangle(); + + CHECK(graph.node_count() == 3); + CHECK(graph.edge_count() == 3); + REQUIRE(graph.initial_node() != nullptr); + CHECK(graph.initial_node()->id == "a"); + CHECK(graph.has_node("b")); + CHECK_FALSE(graph.has_node("z")); + + const auto out = graph.out_edges("c"); + REQUIRE(out.size() == 1); + CHECK(out[0].target == "a"); + CHECK(out[0].kind == EdgeKind::Loopback); + + CHECK(graph.has_edge("a", "b", EdgeKind::Transition)); + CHECK_FALSE(graph.has_edge("a", "b", EdgeKind::Loopback)); +} + +TEST_CASE("out_edges keeps insertion order per source", "[graph]") { + Graph graph = triangle(); + REQUIRE(graph.add_edge("a", "c", EdgeKind::Transition).has_value()); + REQUIRE(graph.add_edge("a", "b", EdgeKind::Loopback).has_value()); + + const auto out = graph.out_edges("a"); + REQUIRE(out.size() == 3); + CHECK(out[0].target == "b"); + CHECK(out[0].kind == EdgeKind::Transition); + CHECK(out[1].target == "c"); + CHECK(out[2].kind == EdgeKind::Loopback); +} + +TEST_CASE("add_node rejects empty and duplicate ids", "[graph]") { + Graph graph = triangle(); + + Node duplicate; + duplicate.id = "b"; + const auto added = graph.add_node(duplicate); + REQUIRE_FALSE(added.has_value()); + CHECK(added.error().contains(DiagCode::NodeIdDuplicate)); + + const auto empty = graph.add_node(Node{}); + REQUIRE_FALSE(empty.has_value()); + CHECK(empty.error().contains(DiagCode::NodeIdEmpty)); + + CHECK(graph.node_count() == 3); +} + +TEST_CASE("remove_node drops the edges that touched it", "[graph]") { + Graph graph = triangle(); + + CHECK(graph.remove_node("b")); + CHECK_FALSE(graph.remove_node("b")); + + CHECK(graph.node_count() == 2); + // a->b and b->c are gone, c->a survives. + REQUIRE(graph.edge_count() == 1); + CHECK(graph.edges()[0].source == "c"); + CHECK(graph.out_edges("a").empty()); + CHECK(graph.validate().has_value()); +} + +TEST_CASE("rename_node repoints its edges", "[graph]") { + Graph graph = triangle(); + + REQUIRE(graph.rename_node("a", "start").has_value()); + CHECK(graph.has_node("start")); + CHECK_FALSE(graph.has_node("a")); + REQUIRE(graph.initial_node() != nullptr); + CHECK(graph.initial_node()->id == "start"); + CHECK(graph.has_edge("start", "b", EdgeKind::Transition)); + CHECK(graph.has_edge("c", "start", EdgeKind::Loopback)); + CHECK(graph.validate().has_value()); + + SECTION("renaming onto a taken id fails") { + const auto renamed = graph.rename_node("b", "c"); + REQUIRE_FALSE(renamed.has_value()); + CHECK(renamed.error().contains(DiagCode::NodeIdDuplicate)); + } + + SECTION("renaming an unknown node fails") { + CHECK_FALSE(graph.rename_node("ghost", "x").has_value()); + } + + SECTION("renaming to itself is a no-op") { + CHECK(graph.rename_node("b", "b").has_value()); + CHECK(graph.node_count() == 3); + } +} + +TEST_CASE("edges cannot be added to unknown nodes", "[graph]") { + Graph graph = triangle(); + + CHECK_FALSE(graph.add_edge("a", "ghost", EdgeKind::Transition).has_value()); + CHECK_FALSE(graph.add_edge("ghost", "a", EdgeKind::Transition).has_value()); + CHECK(graph.edge_count() == 3); +} + +TEST_CASE("adding an edge twice changes nothing", "[graph]") { + Graph graph = triangle(); + + REQUIRE(graph.add_edge("a", "b", EdgeKind::Transition).has_value()); + CHECK(graph.edge_count() == 3); +} + +TEST_CASE("remove_edge removes exactly one kind", "[graph]") { + Graph graph = triangle(); + + CHECK_FALSE(graph.remove_edge("c", "a", EdgeKind::Transition)); + CHECK(graph.remove_edge("c", "a", EdgeKind::Loopback)); + CHECK(graph.edge_count() == 2); + CHECK(graph.out_edges("c").empty()); +} + +TEST_CASE("set_initial moves the flag", "[graph]") { + Graph graph = triangle(); + + REQUIRE(graph.set_initial("c").has_value()); + REQUIRE(graph.initial_node() != nullptr); + CHECK(graph.initial_node()->id == "c"); + CHECK_FALSE(graph.find_node("a")->initial); + CHECK(graph.validate().has_value()); + + CHECK_FALSE(graph.set_initial("ghost").has_value()); +} + +TEST_CASE("node tasks and labels can be replaced", "[graph]") { + Graph graph = triangle(); + + REQUIRE(graph.set_node_tasks("b", {{1, 2, stgx::Release::Up}}).has_value()); + REQUIRE(graph.find_node("b")->tasks.size() == 1); + CHECK(graph.find_node("b")->tasks[0].release == stgx::Release::Up); + + REQUIRE(graph.set_node_label("b", "burst").has_value()); + CHECK(graph.find_node("b")->label == "burst"); + REQUIRE(graph.set_node_label("b", std::nullopt).has_value()); + CHECK_FALSE(graph.find_node("b")->label.has_value()); + + REQUIRE(graph.set_node_border_color("b", "#C0392B").has_value()); + REQUIRE(graph.set_node_fill_color("b", "#F9D5D3").has_value()); + CHECK(graph.find_node("b")->border_color == "#C0392B"); + CHECK(graph.find_node("b")->fill_color == "#F9D5D3"); + REQUIRE(graph.set_node_fill_color("b", std::nullopt).has_value()); + CHECK_FALSE(graph.find_node("b")->fill_color.has_value()); + + CHECK_FALSE(graph.set_node_tasks("ghost", {}).has_value()); + CHECK_FALSE(graph.set_node_label("ghost", "x").has_value()); + CHECK_FALSE(graph.set_node_border_color("ghost", "#000").has_value()); + CHECK_FALSE(graph.set_node_fill_color("ghost", "#000").has_value()); +} + +TEST_CASE("graphs compare by content", "[graph]") { + const Graph one = triangle(); + Graph other = triangle(); + + CHECK(one == other); + REQUIRE(other.set_initial("b").has_value()); + CHECK_FALSE(one == other); } diff --git a/tests/helpers.hpp b/tests/helpers.hpp new file mode 100644 index 0000000..3ae258a --- /dev/null +++ b/tests/helpers.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace stgx_test { + +inline std::filesystem::path data_file(std::string_view name) { + return std::filesystem::path{STGX_TEST_DATA_DIR} / name; +} + +inline std::string read_file(const std::filesystem::path& path) { + std::ifstream file(path, std::ios::binary); + return std::string{std::istreambuf_iterator{file}, std::istreambuf_iterator{}}; +} + +/// First diagnostic carrying `code`, so a test can assert on its path. +inline std::optional find(const stgx::Diagnostics& diags, stgx::DiagCode code) { + const auto it = std::ranges::find_if( + diags, [code](const stgx::Diagnostic& diag) { return diag.code == code; }); + if (it == diags.end()) return std::nullopt; + return *it; +} + +} // namespace stgx_test diff --git a/tests/validate_test.cpp b/tests/validate_test.cpp new file mode 100644 index 0000000..36eb9fb --- /dev/null +++ b/tests/validate_test.cpp @@ -0,0 +1,146 @@ +#include +#include +#include + +#include +#include + +#include "helpers.hpp" + +using stgx::DiagCode; +using stgx::Edge; +using stgx::EdgeKind; +using stgx::Graph; +using stgx::Node; +using stgx::System; + +namespace { + +Node node(std::string id, bool initial = false) { + Node out; + out.id = std::move(id); + out.initial = initial; + return out; +} + +} // namespace + +TEST_CASE("a graph needs at least one node", "[validate]") { + const auto graph = Graph::create({}, {}, {}); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::NodesMissing)); +} + +TEST_CASE("exactly one node must be initial", "[validate]") { + SECTION("none") { + const auto graph = Graph::create({}, {node("a"), node("b")}, {}); + REQUIRE_FALSE(graph.has_value()); + + const auto diag = stgx_test::find(graph.error(), DiagCode::InitialCount); + REQUIRE(diag.has_value()); + CHECK(diag->message.find("found 0") != std::string::npos); + } + + SECTION("two") { + const auto graph = Graph::create({}, {node("a", true), node("b", true)}, {}); + REQUIRE_FALSE(graph.has_value()); + + const auto diag = stgx_test::find(graph.error(), DiagCode::InitialCount); + REQUIRE(diag.has_value()); + CHECK(diag->message.find("found 2") != std::string::npos); + } +} + +TEST_CASE("node ids must be unique and non-empty", "[validate]") { + SECTION("duplicate") { + const auto graph = Graph::create({}, {node("a", true), node("a")}, {}); + REQUIRE_FALSE(graph.has_value()); + + const auto diag = stgx_test::find(graph.error(), DiagCode::NodeIdDuplicate); + REQUIRE(diag.has_value()); + CHECK(diag->path == "nodes[1].id"); + } + + SECTION("empty") { + const auto graph = Graph::create({}, {node("", true)}, {}); + REQUIRE_FALSE(graph.has_value()); + + const auto diag = stgx_test::find(graph.error(), DiagCode::NodeIdEmpty); + REQUIRE(diag.has_value()); + CHECK(diag->path == "nodes[0].id"); + } +} + +TEST_CASE("edges may not dangle", "[validate]") { + SECTION("unknown target is reported at its position in the source node") { + const std::vector nodes{node("a", true), node("b")}; + const std::vector edges{ + Edge{"b", "a", EdgeKind::Transition}, + Edge{"b", "gone", EdgeKind::Transition}, + Edge{"b", "also-gone", EdgeKind::Loopback}, + }; + const auto graph = Graph::create({}, nodes, edges); + REQUIRE_FALSE(graph.has_value()); + + const auto diag = stgx_test::find(graph.error(), DiagCode::DanglingEdge); + REQUIRE(diag.has_value()); + CHECK(diag->path == "nodes[1].children[1]"); + // The release arc is reported separately, indexed within loopback. + CHECK(graph.error().to_string().find("nodes[1].loopback[0]") != std::string::npos); + } + + SECTION("unknown source is reported once") { + const std::vector edges{ + Edge{"ghost", "a", EdgeKind::Transition}, + Edge{"ghost", "a", EdgeKind::Loopback}, + }; + const auto graph = Graph::create({}, {node("a", true)}, edges); + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().size() == 1); + CHECK(graph.error()[0].code == DiagCode::DanglingEdge); + } +} + +TEST_CASE("node task count must match system.tasks", "[validate]") { + System system; + system.tasks = {{1, 2}, {1, 2}}; + + Node only = node("a", true); + only.tasks = {{0, 0}}; + + const auto graph = Graph::create(system, {only}, {}); + REQUIRE_FALSE(graph.has_value()); + + const auto diag = stgx_test::find(graph.error(), DiagCode::TaskArityMismatch); + REQUIRE(diag.has_value()); + CHECK(diag->path == "nodes[0].tasks"); +} + +TEST_CASE("validation collects every problem at once", "[validate]") { + const auto graph = + Graph::create({}, {node("a"), node("a")}, {Edge{"a", "nowhere", EdgeKind::Transition}}); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::NodeIdDuplicate)); + CHECK(graph.error().contains(DiagCode::InitialCount)); + CHECK(graph.error().contains(DiagCode::DanglingEdge)); +} + +TEST_CASE("a sound graph validates", "[validate]") { + System system; + system.m = 1; + system.tasks = {{2, 5, "τ₁"}}; + + Node first = node("a", true); + first.tasks = {{0, 0}}; + Node second = node("b"); + second.tasks = {{2, 5, stgx::Release::Up}}; + + const auto graph = + Graph::create(system, {first, second}, + {Edge{"a", "b", EdgeKind::Transition}, Edge{"b", "a", EdgeKind::Loopback}}); + + REQUIRE(graph.has_value()); + CHECK(graph->validate().has_value()); +} diff --git a/tests/yaml_load_test.cpp b/tests/yaml_load_test.cpp new file mode 100644 index 0000000..cda40c7 --- /dev/null +++ b/tests/yaml_load_test.cpp @@ -0,0 +1,206 @@ +#include +#include +#include + +#include +#include +#include + +#include "helpers.hpp" + +using stgx::DiagCode; +using stgx::EdgeKind; +using stgx::Release; +using stgx_test::data_file; + +TEST_CASE("a minimal document loads", "[load]") { + stgx::Diagnostics warnings; + const auto graph = stgx::load_yaml_file(data_file("minimal.yaml"), &warnings); + + REQUIRE(graph.has_value()); + CHECK(warnings.empty()); + CHECK(graph->node_count() == 1); + CHECK(graph->edge_count() == 0); + REQUIRE(graph->initial_node() != nullptr); + CHECK(graph->initial_node()->id == "n0"); + CHECK(graph->initial_node()->tasks.empty()); + CHECK(graph->system().empty()); +} + +TEST_CASE("a full document loads", "[load]") { + const auto graph = stgx::load_yaml_file(data_file("two-tasks.yaml")); + + REQUIRE(graph.has_value()); + CHECK(graph->node_count() == 3); + CHECK(graph->edge_count() == 4); + + const stgx::System& system = graph->system(); + REQUIRE(system.description.has_value()); + CHECK(*system.description == "EDF feasibility graph"); + CHECK(system.m == 1); + REQUIRE(system.tasks.size() == 2); + CHECK(system.tasks[0].c == 2); + CHECK(system.tasks[0].d == 5); + CHECK(system.tasks[0].name == "τ₁"); + + const auto children = graph->out_edges("n00"); + REQUIRE(children.size() == 2); + CHECK(children[0].target == "n10"); + CHECK(children[0].kind == EdgeKind::Transition); + CHECK(children[1].target == "n20"); + + const auto loopback = graph->out_edges("n20"); + REQUIRE(loopback.size() == 1); + CHECK(loopback[0].kind == EdgeKind::Loopback); + CHECK(loopback[0].target == "n00"); + + const stgx::Node* n20 = graph->find_node("n20"); + REQUIRE(n20 != nullptr); + CHECK(n20->label == "custom: label"); + REQUIRE(n20->tasks.size() == 2); + CHECK(n20->tasks[0].release == Release::Down); + CHECK(n20->tasks[1].release == Release::None); +} + +TEST_CASE("release aliases and omitted fields are normalized", "[load]") { + stgx::Diagnostics warnings; + const auto graph = stgx::load_yaml_file(data_file("aliases.yaml"), &warnings); + + REQUIRE(graph.has_value()); + CHECK(warnings.empty()); + + // isInitial is the legacy spelling of initial. + REQUIRE(graph->initial_node() != nullptr); + CHECK(graph->initial_node()->id == "a"); + + const stgx::Node* a = graph->find_node("a"); + REQUIRE(a != nullptr); + CHECK(a->tasks[0].release == Release::Up); // ↑ + // An omitted c defaults to 0, d comes from the file. + CHECK(a->tasks[1].c == 0); + CHECK(a->tasks[1].d == 2); + CHECK(a->tasks[1].release == Release::None); + + CHECK(graph->find_node("b")->tasks[0].release == Release::Down); // ↓ + CHECK(graph->find_node("c")->tasks[0].release == Release::Up); // 1 + CHECK(graph->find_node("c")->tasks[1].release == Release::Down); // -1 +} + +TEST_CASE("fields we do not model yet warn instead of vanishing quietly", "[load]") { + stgx::Diagnostics warnings; + const auto graph = stgx::load_yaml_file(data_file("unsupported.yaml"), &warnings); + + REQUIRE(graph.has_value()); + CHECK_FALSE(warnings.has_errors()); + CHECK(warnings.contains(DiagCode::UnsupportedField)); + CHECK(warnings.contains(DiagCode::UnknownField)); + + const std::string report = warnings.to_string(); + for (std::string_view expected : {"areas", "layout", "nodes[0].hatch", "nodes[0].metadata"}) { + CHECK(report.find(expected) != std::string::npos); + } + CHECK(report.find("nodes[1].dangerouslyUnknown") != std::string::npos); + + // Styling is modelled, so it loads instead of warning. + CHECK(report.find("Color") == std::string::npos); + const stgx::Node* styled = graph->find_node("n0"); + REQUIRE(styled != nullptr); + CHECK(styled->border_color == "#C0392B"); + CHECK(styled->fill_color == "#E8F4F8"); +} + +TEST_CASE("warnings are optional", "[load]") { + // Passing no sink must not crash and must not change the outcome. + CHECK(stgx::load_yaml_file(data_file("unsupported.yaml")).has_value()); +} + +namespace { + +struct BadFixture { + std::string_view file; + DiagCode code; + std::string_view path; +}; + +} // namespace + +TEST_CASE("broken documents report the expected diagnostic", "[load]") { + const BadFixture fixtures[] = { + {.file = "invalid_no_nodes.yaml", .code = DiagCode::NodesMissing, .path = "nodes"}, + {.file = "invalid_empty_nodes.yaml", .code = DiagCode::NodesMissing, .path = "nodes"}, + {.file = "invalid_duplicate_id.yaml", + .code = DiagCode::NodeIdDuplicate, + .path = "nodes[1].id"}, + {.file = "invalid_empty_id.yaml", .code = DiagCode::NodeIdEmpty, .path = "nodes[0].id"}, + {.file = "invalid_dangling.yaml", + .code = DiagCode::DanglingEdge, + .path = "nodes[1].loopback[0]"}, + {.file = "invalid_two_initial.yaml", .code = DiagCode::InitialCount, .path = "nodes"}, + {.file = "invalid_no_initial.yaml", .code = DiagCode::InitialCount, .path = "nodes"}, + {.file = "invalid_task_arity.yaml", + .code = DiagCode::TaskArityMismatch, + .path = "nodes[0].tasks"}, + {.file = "invalid_bad_int.yaml", .code = DiagCode::NotAnInt, .path = "nodes[0].tasks[0].c"}, + {.file = "invalid_bad_release.yaml", + .code = DiagCode::BadRelease, + .path = "nodes[0].tasks[0].release"}, + {.file = "invalid_schema_version.yaml", + .code = DiagCode::SchemaVersion, + .path = "schemaVersion"}, + {.file = "invalid_wrong_type.yaml", .code = DiagCode::WrongType, .path = "nodes[0].initial"}, + }; + + for (const BadFixture& fixture : fixtures) { + CAPTURE(fixture.file); + const auto graph = stgx::load_yaml_file(data_file(fixture.file)); + + REQUIRE_FALSE(graph.has_value()); + const auto diag = stgx_test::find(graph.error(), fixture.code); + REQUIRE(diag.has_value()); + CHECK(diag->path == fixture.path); + CHECK(diag->severity == stgx::Severity::Error); + } +} + +TEST_CASE("malformed YAML is a parse error", "[load]") { + const auto graph = stgx::load_yaml_file(data_file("invalid_bad_yaml.yaml")); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::YamlParse)); +} + +TEST_CASE("a missing file is an io error", "[load]") { + const auto graph = stgx::load_yaml_file(data_file("does-not-exist.yaml")); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::IoError)); +} + +TEST_CASE("an empty document is rejected", "[load]") { + const auto graph = stgx::load_yaml_string(""); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::YamlParse)); +} + +TEST_CASE("a scalar document is rejected", "[load]") { + const auto graph = stgx::load_yaml_string("just a string"); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::WrongType)); +} + +TEST_CASE("loading collects every problem at once", "[load]") { + const auto graph = stgx::load_yaml_string(R"(nodes: + - id: n0 + tasks: + - {c: oops, d: 1} + children: [ghost] +)"); + + REQUIRE_FALSE(graph.has_value()); + CHECK(graph.error().contains(DiagCode::NotAnInt)); + // Structural checks still run once the fields have been read. + CHECK(graph.error().contains(DiagCode::InitialCount)); + CHECK(graph.error().contains(DiagCode::DanglingEdge)); +} diff --git a/tests/yaml_roundtrip_test.cpp b/tests/yaml_roundtrip_test.cpp new file mode 100644 index 0000000..94fffa0 --- /dev/null +++ b/tests/yaml_roundtrip_test.cpp @@ -0,0 +1,104 @@ +#include +#include +#include + +#include +#include +#include + +#include "helpers.hpp" + +using stgx_test::data_file; + +TEST_CASE("the canonical document survives a round trip byte for byte", "[roundtrip]") { + const std::string original = stgx_test::read_file(data_file("two-tasks.yaml")); + REQUIRE_FALSE(original.empty()); + + const auto graph = stgx::load_yaml_string(original); + REQUIRE(graph.has_value()); + + const auto written = stgx::save_yaml_string(*graph); + REQUIRE(written.has_value()); + CHECK(*written == original); +} + +TEST_CASE("every valid fixture round trips through the model", "[roundtrip]") { + for (std::string_view name : + {"minimal.yaml", "two-tasks.yaml", "aliases.yaml", "unsupported.yaml"}) { + CAPTURE(name); + const auto first = stgx::load_yaml_file(data_file(name)); + REQUIRE(first.has_value()); + + const auto written = stgx::save_yaml_string(*first); + REQUIRE(written.has_value()); + + const auto second = stgx::load_yaml_string(*written); + REQUIRE(second.has_value()); + CHECK(*second == *first); + } +} + +TEST_CASE("saving omits everything left at its default", "[roundtrip]") { + stgx::Node only; + only.id = "n0"; + only.initial = true; + + const auto graph = stgx::Graph::create({}, {only}, {}); + REQUIRE(graph.has_value()); + + const auto written = stgx::save_yaml_string(*graph); + REQUIRE(written.has_value()); + CHECK(*written == "schemaVersion: 1\nnodes:\n - id: n0\n initial: true\n"); +} + +TEST_CASE("node styling survives a round trip", "[roundtrip]") { + const std::string original = + "schemaVersion: 1\n" + "nodes:\n" + " - id: n0\n" + " initial: true\n" + " borderColor: \"#C0392B\"\n" + " fillColor: \"#F9D5D3\"\n"; + + const auto graph = stgx::load_yaml_string(original); + REQUIRE(graph.has_value()); + CHECK(graph->find_node("n0")->border_color == "#C0392B"); + CHECK(graph->find_node("n0")->fill_color == "#F9D5D3"); + + const auto written = stgx::save_yaml_string(*graph); + REQUIRE(written.has_value()); + CHECK(*written == original); +} + +TEST_CASE("an invalid graph is never written", "[roundtrip]") { + const stgx::Graph empty; + + const auto written = stgx::save_yaml_string(empty); + REQUIRE_FALSE(written.has_value()); + CHECK(written.error().contains(stgx::DiagCode::NodesMissing)); +} + +TEST_CASE("saving to a file produces the same bytes", "[roundtrip]") { + const auto graph = stgx::load_yaml_file(data_file("two-tasks.yaml")); + REQUIRE(graph.has_value()); + + const std::filesystem::path out = + std::filesystem::temp_directory_path() / "stgx_roundtrip_two_tasks.yaml"; + REQUIRE(stgx::save_yaml_file(*graph, out).has_value()); + + const auto written = stgx::save_yaml_string(*graph); + REQUIRE(written.has_value()); + CHECK(stgx_test::read_file(out) == *written); + + std::filesystem::remove(out); +} + +TEST_CASE("saving to an unwritable path is an io error", "[roundtrip]") { + const auto graph = stgx::load_yaml_file(data_file("minimal.yaml")); + REQUIRE(graph.has_value()); + + const auto written = + stgx::save_yaml_file(*graph, std::filesystem::path{"/no/such/directory/out.yaml"}); + REQUIRE_FALSE(written.has_value()); + CHECK(written.error().contains(stgx::DiagCode::IoError)); +} From 636b791212a1b4b50087760565becab75360f33a Mon Sep 17 00:00:00 2001 From: peplxx <91543105+peplxx@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:50:40 +0300 Subject: [PATCH 2/3] fix: readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c065fbd..121bf94 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ **S**tate **T**ransition **G**raph e**X**tended — a C++ library for building, editing and -validating state-transition graphs of real-time task systems. +validating state-transition graphs of schedules for real-time systems. --- From 88a75b9e7c565810c14aab8261423a84c8b6f069 Mon Sep 17 00:00:00 2001 From: peplxx <91543105+peplxx@users.noreply.github.com> Date: Sun, 2 Aug 2026 22:04:44 +0300 Subject: [PATCH 3/3] fix(ci): clang tidy --- .github/workflows/ci.yml | 20 ++++++++++++++++++-- CMakeLists.txt | 6 +++++- include/stgx/graph.hpp | 3 ++- include/stgx/result.hpp | 4 ++++ src/graph.cpp | 2 +- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e28364..c9991d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,9 @@ jobs: style: runs-on: ubuntu-latest + env: + LLVM_VERSION: "21" + steps: - uses: actions/checkout@v4 @@ -25,7 +28,18 @@ jobs: - name: Install clang-tidy and Ninja run: | sudo apt-get update - sudo apt-get install -y clang-tidy ninja-build + sudo apt-get install -y ninja-build lsb-release wget software-properties-common gnupg + wget -q https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh "$LLVM_VERSION" + sudo apt-get install -y "clang-tidy-$LLVM_VERSION" + + - name: Report toolchain + run: | + "clang++-$LLVM_VERSION" --version + "clang-tidy-$LLVM_VERSION" --version + "clang++-$LLVM_VERSION" -std=c++23 -x c++ -E -dM /dev/null \ + | grep -E '__cplusplus|__cpp_concepts' - name: Install pre-commit run: pip install pre-commit @@ -42,8 +56,10 @@ jobs: cmake -B build-lint -S . \ -G Ninja \ -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_COMPILER="clang++-$LLVM_VERSION" \ -DSTGX_BUILD_TESTS=OFF \ - -DSTGX_ENABLE_CLANG_TIDY=ON + -DSTGX_ENABLE_CLANG_TIDY=ON \ + -DSTGX_CLANG_TIDY="clang-tidy-$LLVM_VERSION" - name: Build with clang-tidy run: cmake --build build-lint -j "$(nproc)" diff --git a/CMakeLists.txt b/CMakeLists.txt index d5a30d2..23c6069 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) option(STGX_BUILD_TESTS "Build unit tests" ${PROJECT_IS_TOP_LEVEL}) option(STGX_BUILD_EXAMPLES "Build examples" OFF) option(STGX_ENABLE_CLANG_TIDY "Enable clang-tidy on stgx targets" OFF) +set(STGX_CLANG_TIDY "" CACHE STRING "clang-tidy executable to use (name or full path)") # --- dependencies @@ -53,7 +54,10 @@ set_target_properties(stgx PROPERTIES POSITION_INDEPENDENT_CODE ON) if(STGX_ENABLE_CLANG_TIDY) find_program(CLANG_TIDY_EXE - NAMES clang-tidy + NAMES + ${STGX_CLANG_TIDY} + clang-tidy-22 clang-tidy-21 clang-tidy-20 clang-tidy-19 + clang-tidy HINTS "$ENV{HOMEBREW_PREFIX}/opt/llvm/bin" /opt/homebrew/opt/llvm/bin diff --git a/include/stgx/graph.hpp b/include/stgx/graph.hpp index 59b2ab5..e6627fb 100644 --- a/include/stgx/graph.hpp +++ b/include/stgx/graph.hpp @@ -140,7 +140,8 @@ class Graph { IdMap node_index_; IdMap out_index_; - [[nodiscard]] Result mutate_node(std::string_view id, std::function mutation); + [[nodiscard]] Result mutate_node(std::string_view id, + const std::function& mutation); }; } // namespace stgx diff --git a/include/stgx/result.hpp b/include/stgx/result.hpp index 21adc54..c58358a 100644 --- a/include/stgx/result.hpp +++ b/include/stgx/result.hpp @@ -2,6 +2,10 @@ #include +#ifndef __cpp_lib_expected +#error "libstgx needs std::expected: build as C++23 with a toolchain that provides ." +#endif + #include namespace stgx { diff --git a/src/graph.cpp b/src/graph.cpp index df550f1..66833aa 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -18,7 +18,7 @@ namespace stgx { -Result Graph::mutate_node(std::string_view id, std::function mutation) { +Result Graph::mutate_node(std::string_view id, const std::function& mutation) { Node* node = find_node_mut(id); if (node == nullptr) { return fail(diag::node_not_found(id));