API Reference
This document provides a complete reference for all public procedures and types in HSD-Fortran.
Module: hsd
The main module that re-exports all public types and procedures. This is the only module you need to use in most cases.
use hsd
Types
Core Types
hsd_node_t
The unified node type used for all nodes in the HSD tree. The node_type field
discriminates between table (container) nodes and value (leaf) nodes:
NODE_TYPE_TABLE— a container node that holds child nodesNODE_TYPE_VALUE— a leaf node containing a scalar value or array
type(hsd_node_t) :: root ! a table node (after hsd_load)
type(hsd_node_t) :: val ! a value node (after new_value)
hsd_error_t
Error information returned from parsing and validation operations.
type :: hsd_error_t
integer :: code ! Error code (HSD_STAT_*)
character(len=:), allocatable :: message ! Human-readable message
character(len=:), allocatable :: filename ! Source file
integer :: line_start, line_end ! Line range
integer :: column ! Column number
character(len=:), allocatable :: expected ! What was expected
character(len=:), allocatable :: actual ! What was found
character(len=:), allocatable :: hint ! Helpful suggestion
contains
procedure :: print ! Print formatted error
end type
hsd_iterator_t
Iterator for traversing table children.
type(hsd_iterator_t) :: iter
hsd_access_t
High-level access object for reading and writing values in the tree. Accumulates errors internally so they can be checked after a batch of operations.
type(hsd_access_t) :: access
Precision Constants
integer, parameter :: dp = kind(1.0d0) ! Double precision
Node Type Constants
integer, parameter :: NODE_TYPE_TABLE = 1 ! Container node
integer, parameter :: NODE_TYPE_VALUE = 2 ! Leaf node
Value Type Constants
integer, parameter :: VALUE_TYPE_NONE = 0
integer, parameter :: VALUE_TYPE_STRING = 1
integer, parameter :: VALUE_TYPE_INTEGER = 2
integer, parameter :: VALUE_TYPE_REAL = 3
integer, parameter :: VALUE_TYPE_LOGICAL = 4
integer, parameter :: VALUE_TYPE_ARRAY = 5
integer, parameter :: VALUE_TYPE_COMPLEX = 6
Error Codes
integer, parameter :: HSD_STAT_OK = 0 ! Success
integer, parameter :: HSD_STAT_SYNTAX_ERROR = 1 ! Generic syntax error
integer, parameter :: HSD_STAT_UNCLOSED_TAG = 2 ! Block not closed
integer, parameter :: HSD_STAT_UNCLOSED_ATTRIB = 3 ! Attribute bracket not closed
integer, parameter :: HSD_STAT_UNCLOSED_QUOTE = 4 ! String quote not closed
integer, parameter :: HSD_STAT_ORPHAN_TEXT = 5 ! Text outside any block
integer, parameter :: HSD_STAT_INCLUDE_CYCLE = 6 ! Circular include detected
integer, parameter :: HSD_STAT_INCLUDE_DEPTH = 7 ! Too many nested includes
integer, parameter :: HSD_STAT_FILE_NOT_FOUND = 8 ! File doesn't exist
integer, parameter :: HSD_STAT_IO_ERROR = 9 ! I/O operation failed
integer, parameter :: HSD_STAT_TYPE_ERROR = 10 ! Type conversion failed
integer, parameter :: HSD_STAT_NOT_FOUND = 11 ! Key not found in tree
I/O Procedures
hsd_load
Load and parse an HSD file.
subroutine hsd_load_file(filename, root, error)
character(len=*), intent(in) :: filename
type(hsd_node_t), intent(out) :: root
type(hsd_error_t), allocatable, intent(out), optional :: error
end subroutine
hsd_load_string
Parse HSD from a string.
subroutine hsd_load_string(source, root, error, filename)
character(len=*), intent(in) :: source
type(hsd_node_t), intent(out) :: root
type(hsd_error_t), allocatable, intent(out), optional :: error
character(len=*), intent(in), optional :: filename ! For error messages
end subroutine
hsd_dump
Write a tree to a file.
subroutine hsd_dump(root, filename, error)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: filename
type(hsd_error_t), allocatable, intent(out), optional :: error
end subroutine
hsd_dump_to_string
Serialize a tree to a string.
subroutine hsd_dump_to_string(root, output)
type(hsd_node_t), intent(in) :: root
character(len=:), allocatable, intent(out) :: output
end subroutine
Accessor Procedures
hsd_access_t (Access Object)
The primary API for reading and writing values is the hsd_access_t object.
It wraps a root node and accumulates errors internally.
type :: hsd_access_t
contains
procedure :: init ! Initialize with a root node
procedure :: get ! Get a value at a path (generic)
procedure :: get_matrix ! Get a 2D array from multi-line data
procedure :: set ! Set a value at a path (generic)
procedure :: has_errors ! Check if any errors accumulated
procedure :: print_errors ! Print all accumulated errors
end type
Initialization:
subroutine init(self, root, on_missing, mark_processed)
type(hsd_node_t), intent(in), target :: root
integer, intent(in), optional :: on_missing ! HSD_ON_MISSING_SET (default) or HSD_ON_MISSING_RETURN
logical, intent(in), optional :: mark_processed ! default .true.
end subroutine
on_missing=HSD_ON_MISSING_SET(default): when a key is missing and a default is provided, the default value is written back into the tree.on_missing=HSD_ON_MISSING_RETURN: the default is returned to the caller without modifying the tree.mark_processed: when.true.(default), accessed nodes are marked as processed.
access%get:
Get a value at the specified path. Supports multiple output types via generic interface.
! Scalar types
call access%get(path, value)
call access%get(path, value, default=fallback)
! Array types
call access%get(path, array)
call access%get(path, array, default=fallback_array)
Supported types: integer, real(dp), logical, character, and allocatable arrays thereof.
Examples:
integer :: count
real(dp) :: temperature
character(len=:), allocatable :: name
integer, allocatable :: values(:)
call access%get("Settings/Count", count)
call access%get("Physics/Temperature", temperature, default=300.0_dp)
call access%get("Geometry/Name", name)
call access%get("Data/Values", values)
access%get_matrix:
Get a 2D array from multi-line data.
call access%get_matrix(path, matrix, nrows, ncols)
access%set:
Set a value at the specified path (creates intermediate tables as needed).
call access%set(path, value)
Supported types: integer, real(dp), logical, character, and arrays thereof.
Error handling:
if (access%has_errors()) then
call access%print_errors()
end if
Legacy Free Functions (hsd_api)
The free-function accessors hsd_get, hsd_set, hsd_get_or_set, and
hsd_get_matrix are still available via use hsd_api but are no longer
exported from use hsd. New code should use hsd_access_t instead.
hsd_get_inline_text
Get concatenated text content of all unnamed value children. Iterates
children of the table, collecting text from unnamed or #text
value nodes (node_type == NODE_TYPE_VALUE). Multiple values are separated by spaces.
How #text is created:
When a table block contains inline text (not a named Key = Value child),
the parser stores that inline text as an internal value child named
#text. For example, Tag { 42 } creates a Tag table with one
#text child containing 42; Tag { 42; Sub = x } creates both the
#text child (42) and the named Sub child.
subroutine hsd_get_inline_text(table, text, stat)
type(hsd_node_t), intent(in), target :: table
character(len=:), allocatable, intent(out) :: text
integer, intent(out), optional :: stat
end subroutine
Example:
character(len=:), allocatable :: text
integer :: stat
call hsd_get_inline_text(root, text, stat)
if (stat == HSD_STAT_OK) print *, "Inline text: ", text
Query Procedures
hsd_has_child
Check if a path exists in the tree.
logical function hsd_has_child(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
end function
hsd_is_table
Check if the node at path is a table (container).
logical function hsd_is_table(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
end function
hsd_is_value
Check if the node at path is a value (leaf).
logical function hsd_is_value(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
end function
hsd_is_array
Check if the value at path contains an array.
logical function hsd_is_array(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
end function
hsd_child_count
Get the number of children in a table.
integer function hsd_child_count(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path ! Empty string for root
end function
hsd_get_keys
Get all child key names.
subroutine hsd_get_keys(root, path, keys)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
character(len=:), allocatable, intent(out) :: keys(:)
end subroutine
hsd_get_type
Get the value type at a path.
integer function hsd_get_type(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
end function
! Returns VALUE_TYPE_* constant
hsd_get_attrib
Get the attribute (e.g., unit) at a path.
subroutine hsd_get_attrib(root, path, attrib, stat)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
character(len=:), allocatable, intent(out) :: attrib
integer, intent(out), optional :: stat
end subroutine
hsd_has_attrib
Check if a node has an attribute.
logical function hsd_has_attrib(root, path)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
end function
hsd_get_child
Get a child node by name.
subroutine hsd_get_child(root, name, child, stat)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: name
type(hsd_node_t), pointer, intent(out) :: child
integer, intent(out), optional :: stat
end subroutine
hsd_get_table
Get a child table by path.
subroutine hsd_get_table(root, path, table, stat)
type(hsd_node_t), intent(in) :: root
character(len=*), intent(in) :: path
type(hsd_node_t), pointer, intent(out) :: table
integer, intent(out), optional :: stat
end subroutine
hsd_get_children
Collect all children matching a (possibly path-qualified) name.
subroutine hsd_get_children(root, path, children, stat)
type(hsd_node_t), intent(in), target :: root
character(len=*), intent(in) :: path
type(hsd_node_ptr_t), allocatable, intent(out) :: children(:)
integer, intent(out), optional :: stat
end subroutine
hsd_get_child_tables
Collect all matching table children. Both hsd_get_children and
hsd_get_child_tables use hsd_node_ptr_t with a %node pointer component.
subroutine hsd_get_child_tables(root, path, children, stat)
type(hsd_node_t), intent(in), target :: root
character(len=*), intent(in) :: path
type(hsd_node_ptr_t), allocatable, intent(out) :: children(:)
integer, intent(out), optional :: stat
end subroutine
hsd_has_value_children
Check whether a table has any value children (inline data).
logical function hsd_has_value_children(table)
type(hsd_node_t), intent(in), target :: table
end function
Example:
if (hsd_has_value_children(root)) then
print *, "Table contains inline values"
end if
hsd_get_name
Get the lowercased name of a node. If the node’s name is unset or blank,
returns the default string (which itself defaults to "" if not
provided).
subroutine hsd_get_name(node, name, default)
type(hsd_node_t), intent(in) :: node
character(len=:), allocatable, intent(out) :: name
character(len=*), intent(in), optional :: default
end subroutine
Example:
character(len=:), allocatable :: name
call hsd_get_name(node, name)
call hsd_get_name(node, name, default="#text")
Mutation Procedures
Values are typically modified via access%set (see hsd_access_t above).
The following tree-level mutation procedures remain public:
hsd_remove_child
Remove a child node.
subroutine hsd_remove_child(root, path, stat)
type(hsd_node_t), intent(inout) :: root
character(len=*), intent(in) :: path
integer, intent(out), optional :: stat
end subroutine
Tree Operations
hsd_clone
Create a deep copy of a tree.
subroutine hsd_clone(source, dest)
type(hsd_node_t), intent(in) :: source
type(hsd_node_t), intent(out) :: dest
end subroutine
hsd_merge
Merge source into target (source values override target on conflict).
subroutine hsd_merge(target, source)
type(hsd_node_t), intent(inout) :: target
type(hsd_node_t), intent(in) :: source
end subroutine
Validation Procedures
hsd_require
Check that a required field exists (optionally check its type).
subroutine hsd_require(table, path, error, expected_type, context)
type(hsd_node_t), intent(in), target :: table
character(len=*), intent(in) :: path
type(hsd_error_t), allocatable, intent(out) :: error
integer, intent(in), optional :: expected_type ! FIELD_TYPE_* constant
character(len=*), intent(in), optional :: context
end subroutine
hsd_validate_range
Validate that a numeric value at a path is within a range.
subroutine hsd_validate_range(table, path, min_val, max_val, error, context)
type(hsd_node_t), intent(in), target :: table
character(len=*), intent(in) :: path
real(dp), intent(in) :: min_val, max_val
type(hsd_error_t), allocatable, intent(out) :: error
character(len=*), intent(in), optional :: context
end subroutine
hsd_validate_one_of
Validate that a string value at a path is one of the allowed choices.
subroutine hsd_validate_one_of(table, path, choices, error, context)
type(hsd_node_t), intent(in), target :: table
character(len=*), intent(in) :: path
character(len=*), intent(in) :: choices(:)
type(hsd_error_t), allocatable, intent(out) :: error
character(len=*), intent(in), optional :: context
end subroutine
hsd_get_with_unit
Get a value with unit conversion via a user-supplied converter function.
subroutine hsd_get_with_unit(table, path, val, target_unit, converter, stat)
type(hsd_node_t), intent(in), target :: table
character(len=*), intent(in) :: path
real(dp), intent(out) :: val
character(len=*), intent(in) :: target_unit
interface
pure function converter(value, from_unit, to_unit) result(converted)
import :: dp
real(dp), intent(in) :: value
character(len=*), intent(in) :: from_unit, to_unit
real(dp) :: converted
end function
end interface
integer, intent(out), optional :: stat
end subroutine
Constructor Functions
new_table
Create a new table node.
function new_table(name) result(table)
character(len=*), intent(in) :: name
type(hsd_node_t) :: table
end function
new_value
Create a new value node.
function new_value(name, val) result(value)
character(len=*), intent(in) :: name
<type>, intent(in) :: val
type(hsd_node_t) :: value
end function