User Guide
Overview
hsd-data provides a unified interface for loading and dumping structured data
across multiple file formats. The in-memory representation is always the
hsd_table / hsd_value tree from hsd-fortran.
┌─────────┐
│ .hsd │──╮
├──────────┤ │
│ .xml │──┤ data_load() ┌──────────────┐ data_dump() ┌──────────┐
├──────────┤ ├────────────────▶│ hsd_table │────────────────▶│ .json │
│ .json │──┤ │ hsd_value │ │ .xml │
├──────────┤ │ └──────────────┘ │ .hsd │
│ .yaml │──┤ │ .yaml │
├──────────┤ │ │ .toml │
│ .toml │──┤ │ .h5 │
├──────────┤ │ └──────────┘
│ .h5 │──╯
└──────────┘
Loading Data
From a File
use hsd_data
type(hsd_table) :: root
type(hsd_error_t), allocatable :: error
! Auto-detect format from file extension
call data_load("config.hsd", root, error)
if (allocated(error)) then
call error%print()
stop 1
end if
Supported extensions for auto-detection:
Extension |
Format |
|---|---|
|
HSD |
|
XML |
|
JSON |
|
YAML |
|
TOML |
|
HDF5 |
With Explicit Format
call data_load("input.dat", root, error, fmt=DATA_FMT_JSON)
From a String
character(len=*), parameter :: json_str = '{"key": "value"}'
call data_load_string(json_str, root, DATA_FMT_JSON, error)
With Root Wrapping
When loading formats that may not have a single root element, use wrap_name
to wrap the content under a named root table:
call data_load("input.hsd", root, error, wrap_name="Geometry")
Dumping Data
To a File
call data_dump(root, "output.json", error)
To a String
character(len=:), allocatable :: output
call data_dump_to_string(root, output, DATA_FMT_JSON)
Pretty vs Compact Output
! Pretty-printed (default)
call data_dump(root, "output.json", error, pretty=.true.)
! Compact (no indentation)
call data_dump(root, "output.json", error, pretty=.false.)
Converting Between Formats
Programmatic
call data_convert("input.hsd", "output.json", error)
Command Line
hsd-convert input.hsd output.json
Working with the Tree
Once data is loaded, you work with hsd_table / hsd_value types using the
hsd-fortran API. hsd-data re-exports the full hsd-fortran public API, so you
only need use hsd_data:
use hsd_data
type(hsd_table) :: root
type(hsd_error_t), allocatable :: error
integer :: max_steps, stat
real(dp) :: temperature
character(len=:), allocatable :: method
call data_load("config.hsd", root, error)
! Read values
call hsd_get(root, "Driver/MaxSteps", max_steps, stat)
call hsd_get(root, "Hamiltonian/Method", method, stat)
! Read with defaults
call hsd_get_or(root, "Driver/MaxSteps", max_steps, 100, stat)
! Check existence
if (hsd_has_child(root, "Analysis")) then
! ...
end if
! Modify values
call hsd_set(root, "Driver/MaxSteps", 200)
! Save back
call data_dump(root, "config_modified.json", error)
Format Detection
integer :: fmt
fmt = data_detect_format("input.hsd")
! Returns DATA_FMT_HSD
if (.not. data_format_available(DATA_FMT_TOML)) then
print *, "TOML backend not available (built without WITH_TOML)"
end if
Error Handling
All IO operations accept an optional error argument of type hsd_error_t:
type(hsd_error_t), allocatable :: error
call data_load("missing.hsd", root, error)
if (allocated(error)) then
! error%message contains the error description
! error%stat contains the status code
call error%print() ! prints to stderr
stop 1
end if
If the error argument is not provided and an error occurs, the library
will print the error and abort the program.
Status Codes
All status codes from hsd-fortran are available:
Constant |
Value |
Meaning |
|---|---|---|
|
0 |
Success |
|
1 |
Parse error |
|
8 |
File not found |
|
9 |
IO operation failed |
|
10 |
Type conversion failed |
|
11 |
Key not found |
See the hsd-fortran error handling guide for the complete list.
Backend-Specific Access
While the unified API is recommended, you can also use backend-specific functions directly:
use hsd_data
! XML-specific
call xml_parse_file("input.xml", root, error)
call xml_dump_file(root, "output.xml", error)
! JSON-specific
call json_parse_file("input.json", root, error)
call json_dump_file(root, "output.json", error)
! YAML-specific
call yaml_parse_file("input.yaml", root, error)
call yaml_dump_file(root, "output.yaml", error)
! HSD-specific (equivalent to hsd_load/hsd_dump)
call hsd_backend_load("input.hsd", root, error)
call hsd_backend_dump(root, "output.hsd", error)