fgof-state Public
fgof-state
Persistent app and workspace state helpers for modern Fortran.
fgof-state is intended to be a small, standalone library for durable local
state, atomic save flows, and version-aware app data that CLI tools and
interactive apps keep hand-rolling.
It is part of the FortranGoingOnForty lib-modules
catalog, but it is intended to stand on its own as a normal fpm package.
Current v1 target:
- stable state option, root, and document types
- predictable state-root resolution from explicit paths or XDG defaults
- atomic save or replace semantics for app and workspace state
- simple version-aware load or save flows with room for migrations later
Future scope:
- richer schema migration helpers
- backup or recovery helpers for state upgrades
- higher-level workspace and session persistence flows
Status
Sprint 04 is in place.
Tracked today:
- explicit state-root resolution from
root_dir,XDG_STATE_HOME, orHOME - namespace and scope-aware root layout
- document-path helpers and document resolution
- text-focused state save, load, and remove helpers
fgof-temp-backed atomic replace semantics for saves- side-effect-free reads and removes when state roots are missing
- version-aware state envelopes with explicit mismatch handling
- explicit
version_checked/version_matchedresult semantics for version-aware loads - malformed or unsupported state payloads rejected as version errors
- unreadable state files reported as
iofailures - invalid version arguments rejected before filesystem writes
- tracked round-trip and version-mismatch examples
- POSIX root creation and existence checks
- focused scaffold coverage in
fpm test - CI on macOS and Ubuntu, including direct example execution
Why Use It
- app and workspace state shows up everywhere once tools grow past trivial size
- atomic persistence is easy to get subtly wrong
- a focused state layer builds naturally on the released temp and cache modules
Public API Shape
Primary modules:
fgof_statefgof_state_types
Public types:
state_optionsstate_rootstate_documentstate_text_result
Public constants:
FGOF_STATE_OKFGOF_STATE_ERR_INVALID_OPTIONSFGOF_STATE_ERR_NOT_FOUNDFGOF_STATE_ERR_IOFGOF_STATE_ERR_VERSIONFGOF_STATE_ERR_INTERNAL
Current public procedures:
clear_state_optionsclear_state_rootclear_state_documentclear_state_text_resultensure_state_rootsave_state_textload_state_textremove_state_documentstate_relative_path_for_namestate_path_for_nameresolve_state_documentstate_backend_namestate_error_name
Current semantics:
ensure_state_root()resolves from explicitroot_dir, or fromXDG_STATE_HOME/HOMEwhenroot_diris absent- explicit
namespaceandscopevalues extend the resolved root path as validated path segments create_root=.true.creates state directories on demand;create_root=.false.requires the root to already existstate_relative_path_for_name()andstate_path_for_name()expose the stable document path shape for valid document namesresolve_state_document()returns the resolved root path, relative path, full path, and current presence state for a state documentsave_state_text()writes exact Fortran character payloads with same-directory atomic replacement throughfgof-tempload_state_text()reads stored text back without creating missing roots as a side effectremove_state_document()removes stored state files without creating missing roots as a side effectsave_state_text()stores a small internal format header plus a positive document version; the default version is1load_state_text()surfaces the stored version onstate_text_result%document%versionstate_text_result%version_checkedtells callers whetherexpected_version=was actually applied for that loadload_state_text(..., expected_version=...)reportsversionerrors explicitly when the stored document version does not match the caller expectationstate_text_result%version_matchedis only meaningful whenstate_text_result%version_checkedis.true.- unsupported or malformed state payloads also report
versionerrors instead of pretending to be valid text - unreadable state files report
ioerrors during load - missing documents report
not-foundfor load or remove flows - document names, namespaces, and scopes must not be empty, contain
/, or be./..
Build And Test
fpm test
That is the baseline verification command locally and in CI.
Tracked examples:
Supported Platforms
- macOS
- Linux
Boundaries
- intended to stay independently versioned and releasable
- focused on state ergonomics, not full database or cache policy management
- should stay useful on its own even if future higher-level app packages build on top
License
MIT
View source
| 1 | # fgof-state |
| 2 | |
| 3 | Persistent app and workspace state helpers for modern Fortran. |
| 4 | |
| 5 | `fgof-state` is intended to be a small, standalone library for durable local |
| 6 | state, atomic save flows, and version-aware app data that CLI tools and |
| 7 | interactive apps keep hand-rolling. |
| 8 | |
| 9 | It is part of the [FortranGoingOnForty lib-modules](https://github.com/FortranGoingOnForty/lib-modules) |
| 10 | catalog, but it is intended to stand on its own as a normal `fpm` package. |
| 11 | |
| 12 | Current v1 target: |
| 13 | |
| 14 | - stable state option, root, and document types |
| 15 | - predictable state-root resolution from explicit paths or XDG defaults |
| 16 | - atomic save or replace semantics for app and workspace state |
| 17 | - simple version-aware load or save flows with room for migrations later |
| 18 | |
| 19 | Future scope: |
| 20 | |
| 21 | - richer schema migration helpers |
| 22 | - backup or recovery helpers for state upgrades |
| 23 | - higher-level workspace and session persistence flows |
| 24 | |
| 25 | ## Status |
| 26 | |
| 27 | Sprint 04 is in place. |
| 28 | |
| 29 | Tracked today: |
| 30 | |
| 31 | - explicit state-root resolution from `root_dir`, `XDG_STATE_HOME`, or `HOME` |
| 32 | - namespace and scope-aware root layout |
| 33 | - document-path helpers and document resolution |
| 34 | - text-focused state save, load, and remove helpers |
| 35 | - `fgof-temp`-backed atomic replace semantics for saves |
| 36 | - side-effect-free reads and removes when state roots are missing |
| 37 | - version-aware state envelopes with explicit mismatch handling |
| 38 | - explicit `version_checked` / `version_matched` result semantics for version-aware loads |
| 39 | - malformed or unsupported state payloads rejected as version errors |
| 40 | - unreadable state files reported as `io` failures |
| 41 | - invalid version arguments rejected before filesystem writes |
| 42 | - tracked round-trip and version-mismatch examples |
| 43 | - POSIX root creation and existence checks |
| 44 | - focused scaffold coverage in `fpm test` |
| 45 | - CI on macOS and Ubuntu, including direct example execution |
| 46 | |
| 47 | ## Why Use It |
| 48 | |
| 49 | - app and workspace state shows up everywhere once tools grow past trivial size |
| 50 | - atomic persistence is easy to get subtly wrong |
| 51 | - a focused state layer builds naturally on the released temp and cache modules |
| 52 | |
| 53 | ## Public API Shape |
| 54 | |
| 55 | Primary modules: |
| 56 | |
| 57 | - `fgof_state` |
| 58 | - `fgof_state_types` |
| 59 | |
| 60 | Public types: |
| 61 | |
| 62 | - `state_options` |
| 63 | - `state_root` |
| 64 | - `state_document` |
| 65 | - `state_text_result` |
| 66 | |
| 67 | Public constants: |
| 68 | |
| 69 | - `FGOF_STATE_OK` |
| 70 | - `FGOF_STATE_ERR_INVALID_OPTIONS` |
| 71 | - `FGOF_STATE_ERR_NOT_FOUND` |
| 72 | - `FGOF_STATE_ERR_IO` |
| 73 | - `FGOF_STATE_ERR_VERSION` |
| 74 | - `FGOF_STATE_ERR_INTERNAL` |
| 75 | |
| 76 | Current public procedures: |
| 77 | |
| 78 | - `clear_state_options` |
| 79 | - `clear_state_root` |
| 80 | - `clear_state_document` |
| 81 | - `clear_state_text_result` |
| 82 | - `ensure_state_root` |
| 83 | - `save_state_text` |
| 84 | - `load_state_text` |
| 85 | - `remove_state_document` |
| 86 | - `state_relative_path_for_name` |
| 87 | - `state_path_for_name` |
| 88 | - `resolve_state_document` |
| 89 | - `state_backend_name` |
| 90 | - `state_error_name` |
| 91 | |
| 92 | Current semantics: |
| 93 | |
| 94 | - `ensure_state_root()` resolves from explicit `root_dir`, or from `XDG_STATE_HOME` / `HOME` when `root_dir` is absent |
| 95 | - explicit `namespace` and `scope` values extend the resolved root path as validated path segments |
| 96 | - `create_root=.true.` creates state directories on demand; `create_root=.false.` requires the root to already exist |
| 97 | - `state_relative_path_for_name()` and `state_path_for_name()` expose the stable document path shape for valid document names |
| 98 | - `resolve_state_document()` returns the resolved root path, relative path, full path, and current presence state for a state document |
| 99 | - `save_state_text()` writes exact Fortran character payloads with same-directory atomic replacement through `fgof-temp` |
| 100 | - `load_state_text()` reads stored text back without creating missing roots as a side effect |
| 101 | - `remove_state_document()` removes stored state files without creating missing roots as a side effect |
| 102 | - `save_state_text()` stores a small internal format header plus a positive document version; the default version is `1` |
| 103 | - `load_state_text()` surfaces the stored version on `state_text_result%document%version` |
| 104 | - `state_text_result%version_checked` tells callers whether `expected_version=` was actually applied for that load |
| 105 | - `load_state_text(..., expected_version=...)` reports `version` errors explicitly when the stored document version does not match the caller expectation |
| 106 | - `state_text_result%version_matched` is only meaningful when `state_text_result%version_checked` is `.true.` |
| 107 | - unsupported or malformed state payloads also report `version` errors instead of pretending to be valid text |
| 108 | - unreadable state files report `io` errors during load |
| 109 | - missing documents report `not-found` for load or remove flows |
| 110 | - document names, namespaces, and scopes must not be empty, contain `/`, or be `.` / `..` |
| 111 | |
| 112 | ## Build And Test |
| 113 | |
| 114 | ```bash |
| 115 | fpm test |
| 116 | ``` |
| 117 | |
| 118 | That is the baseline verification command locally and in CI. |
| 119 | |
| 120 | Tracked examples: |
| 121 | |
| 122 | - [state_roundtrip_demo.f90](example/state_roundtrip_demo.f90) |
| 123 | - [state_version_demo.f90](example/state_version_demo.f90) |
| 124 | |
| 125 | ## Supported Platforms |
| 126 | |
| 127 | - macOS |
| 128 | - Linux |
| 129 | |
| 130 | ## Boundaries |
| 131 | |
| 132 | - intended to stay independently versioned and releasable |
| 133 | - focused on state ergonomics, not full database or cache policy management |
| 134 | - should stay useful on its own even if future higher-level app packages build on top |
| 135 | |
| 136 | ## License |
| 137 | |
| 138 | MIT |