Iniciando#

Difficulty: Beginner

Este tutorial proporciona una introducción amable para el uso de TOML Fortran. Tratará de la lectura y creacción de estructuras de datos TOML usando la interfaz de construcción de alto nivel y como obtener una estructura de datos desde un documento TOML o convertir una estrutura de datos en un documento TOML totalmente nuevo.

En este proyecto trabajaremos con fpm, no obstante usted puede usar cualquier herramienta de construcción con la que esté familiarizado, consulte la guía de integración para encontrar una configuración coincidente. Comenzamos creando un manifiesto de paquete mínimo para usar TOML Fortran en nuestro proyecto fpm.

fpm.toml#
name = "demo"

[dependencies]
toml-f.git = "https://github.com/toml-f/toml-f.git"

La API pública TOML Fortran es definida en el módulo tomlf, en este curso completo solo usaremos este módulo. Las estructuras de datos principales con las que interactuaremos son lala interfaz genérica get_value.

src/reader.f90#
module reader
  use tomlf, only : toml_table, toml_array, get_value, len
  implicit none
  private

  public :: read_data

contains

  subroutine read_data(table, title, spectrum)
    type(toml_table), intent(inout) :: table
    character(len=:), allocatable, intent(out) :: title
    real, allocatable, intent(out) :: spectrum(:)

    type(toml_table), pointer :: child
    type(toml_array), pointer :: array
    logical :: reverse
    integer :: ival

    ! Get character value from entry "title"
    call get_value(table, "title", title)

    ! Get subtable reference from entry "spectrum"
    call get_value(table, "spectrum", child)

    ! Get array reference from entry "data"
    call get_value(child, "data", array)

    ! Read all values from the data array
    allocate(spectrum(len(array)))
    do ival = 1, size(spectrum)
      call get_value(array, ival, spectrum(ival))
    end do

    ! Data is stored in reverse order
    call get_value(child, "reverse", reverse, .false.)
    if (reverse) spectrum(:) = spectrum(size(spectrum):1:-1)
  end subroutine read_data

end module reader

Note que definimos la estructura de datos TOML como mutable, es decir, intent(inout) en lugar de solo intent(in), como la interfaz get_value puede modificar la estructura de datos. Iniciamos con un programa de prueba simple, que realmente no está leyendo ningún documento TOML, sino solo pasando una tabla vacía a nuesto lector.

app/defaults.f90#
program defaults
  use reader, only : read_data
  use tomlf, only : toml_table
  implicit none

  type(toml_table), allocatable :: table
  character(len=:), allocatable :: title
  real, allocatable :: spectrum(:)

  table = toml_table()

  call read_data(table, title, spectrum)

  if (allocated(title)) then
    print '(a)', "Title: '"//title//"'"
  end if

  print '(*(g0, 1x))', "Entries:", size(spectrum)
  if (size(spectrum) > 0) then
    print '(*(g0, 1x))', "Spectrum:", spectrum
  end if
end program defaults

La interfaz get_value para el procesamiento de la estructura de datos TOML asegura que la estructura de datos esté completa a lo largo del proceso de lectura y agregará los nodos solicitados sino están presentes o los completará con valores predeterminados. Verifique que la tabla vacía realmente cambió durante la lectura pasandole un serializador.

block
  use tomlf, only : toml_serialize

  print '(a)', "# Final TOML data structure"
  print '(a)', toml_serialize(table)
end block
! Expected output:
! # Final TOML data structure
! [spectrum]
! data = [ ]
! reverse = false

Este comportamiento es muy conveniente porque nos permite definir nuestros valores predeterminados al definir como leemos la estructura de datos TOML.

Nota

La interfaz de construcción get_value es solo una forma de acceder a la estrutura de datos TOML proporcionado por TOML Fortran. Este toma una aproximación pragmática para la lectura y modificación de la estructura de datos, que es apropiada en la mayoria de las aplicaciones.

Ahora leeremos realmente un documento TOML y pasaremos este a nuestro lector.

input.toml#
title = "Example"
spectrum.data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

Adaptamos nuestro controlador de linea de comandos para leer el archivo input.toml y muestra los valores como antes

app/readin.f90#
program readin
  use reader, only : read_data
  use tomlf, only : toml_table, toml_parse, toml_error
  implicit none

  type(toml_table), allocatable :: table
  character(len=:), allocatable :: title
  real, allocatable :: spectrum(:)


  block
    integer :: io
    type(toml_error), allocatable :: error

    open(file="input.toml", newunit=io, status="old")
    call toml_parse(table, io, error)
    close(io)
    if (allocated(error)) then
      print '(a)', "Error: "//error%message
      stop 1
    end if
  end block

  call read_data(table, title, spectrum)

  if (allocated(title)) then
    print '(a)', "Title: '"//title//"'"
  end if

  print '(*(g0, 1x))', "Entries:", size(spectrum)
  if (size(spectrum) > 0) then
    print '(*(g0, 1x))', "Spectrum:", spectrum
  end if
end program readin

Ejecutar el programa con fpm muestra que pudimos leer los valores correctos desde el documento

❯ fpm run readin
Title: 'Example'
Entries: 10
Spectrum: 0.00000000 1.00000000 2.00000000 3.00000000 4.00000000 5.00000000 6.00000000 7.00000000 8.00000000 9.00000000

Usted puede volver a usar el serializador para escribir la estructura de datos final, si desea verficar si la interfaz get_value ha adicionado los valores predeterminados.

Importante

En este tutorial usted ha aprendido a leer estructuras de datos desde documentos TOML. Ahora puede

  • definir la lógica para leer datos desde estructuras TOML

  • proporcione valores predeterminados en su analizador a medida que define la estructura de entrada

  • leer un documento TOML real desde un archivo

  • escribir documentos TOML desde sus estructuras de datos