Simple Types

To help structure your input file, Inlet categorizes the information into two types: Fields and Containers.

Fields refer to the individual scalar values that are either at the global level or that are contained inside of a Container.

Containers can contain multiple Fields, other sub-Containers, as well as a single array or a single dictionary.

Note

There is a global Container that holds all top-level Fields. This can be accessed via your Inlet class instance.

Fields

In Inlet, Fields represent an individual scalar value of primitive type. There are four supported field types: bool, int, double, and string.

In this example we will be using the following part of an input file:

a_simple_bool = true
a_simple_int = 5
a_simple_double = 7.5
a_simple_string = 'such simplicity'

Defining And Storing

This example shows how to add the four simple field types with descriptions to the input file schema and add their values, if present in the input file, to the Sidre DataStore to be accessed later.

  // Define and store the values in the input file

  // Add an optional top-level boolean
  inlet.addBool("a_simple_bool", "A description of a_simple_bool");

  // Add an optional top-level integer
  inlet.addInt("a_simple_int", "A description of a_simple_int");

  // Add a required top-level double
  inlet.addDouble("a_simple_double", "A description of a_simple_double").required();

  // Add an optional top-level string
  inlet.addString("a_simple_string", "A description of a_simple_string");

  // Add an optional top-level integer with a default value of 17 if not defined by the user
  inlet.addInt("a_defaulted_int", "An int that has a default value").defaultValue(17);

  // Add an optional top-level string not defined in the input file for example purposes
  inlet.addString("does_not_exist",
                  "Shows that not all fields need to be present in input file");

You can also add default values to Fields to fall back to if they are not defined in your input file. The last added Field was intentionally not present in the input file. Not all fields need to be present, unless they are marked required, like a_simple_double.

Accessing

Accessing field values stored in Inlet can be accessed via their name with the [] operator or through the templated get<T> function. The [] operator is more streamlined but can lead to compile time ambiquity depending on how it is used. The example below shows an example of this.

Prior to accessing optional fields, you should verify they were provided by the user via the contains function.

The contains function returns true if the field was either provided by the user or via a default. To check if the field was provided by the user (and not via a default), you can use the isUserProvided method, which returns true if the value was provided by the user in the input file.

Accessing a value that was not provided by the user, or a default value, will result in a runtime error.

  // Access values stored in the Datastore via Inlet

  // Check if input file contained info before accessing optional fields
  if(inlet.contains("a_simple_bool"))
  {
    // Access field via "[]" operator, save value first to avoid type ambiquity
    bool a_simple_bool = inlet["a_simple_bool"];
    std::cout << "a_simple_bool = " << a_simple_bool << std::endl;
  }

  if(inlet.contains("a_simple_int"))
  {
    // Access field via `get<T>` directly, no ambiquity
    std::cout << "a_simple_int = " << inlet.get<int>("a_simple_int") << std::endl;
  }

  // Because this field was marked required, we do not have to call contains before accessing
  std::cout << "a_simple_double = " << inlet.get<double>("a_simple_double")
            << std::endl;

  if(inlet.contains("a_simple_string"))
  {
    std::string a_simple_string = inlet["a_simple_string"];
    std::cout << "a_simple_string = " << a_simple_string << std::endl;
  }

  // If the user did not provide a value, the default value will be used.  Safe to use
  // without checking contains
  int a_defaulted_int = inlet["a_defaulted_int"];
  std::cout << "a_defaulted_int = " << a_defaulted_int << std::endl;
  // We can also verify that the user did not provided a value
  std::cout << "a_defaulted_int provided by user: "
            << inlet.isUserProvided("a_defaulted_int") << std::endl;

Note

The field does_not_exist was purposefully left this out of the user-provided input file to show no warnings/errors are thrown during runtime for defining optional fields in the schema.

Containers

Containers help with grouping associated data together into a single collection. Containers can contain multiple individually named Fields, multiple sub-Containers, as well as a single array or a single dictionary.

In this example, we will be using the following part of an input file:

driver = {
    name = "Speed Racer",
    car = {
        make = "BestCompany",
        seats = 2,
        horsepower = 200
    }
}

Defining And Storing

This example shows how to add a Container with a nested Container to the input file schema and add the underlying field values to the Sidre DataStore to be accessed later.

  auto& driver_schema = inlet.addStruct("driver", "A description of driver");
  driver_schema.addString("name", "Name of driver");

  auto& car_schema = driver_schema.addStruct("car", "Car of driver");
  car_schema.addString("make", "Make of car");
  car_schema.addString("color", "Color of car").defaultValue("red");
  car_schema.addInt("seats", "Number of seats");
  car_schema.addInt("horsepower", "Amount of horsepower");

This example also shows that the color Field that was not given in the input file but used the default value that was specified in the schema.

Note

Inlet also has an addStruct member for defining more complex types, such as nested structures. See Advanced Types for more details

Accessing

Field values stored inside a container can be accessed via their name with the [] operator. They can be accessed from the Inlet class instance with their fully qualified name or you can get the Container instance first, then access it with the relative name.

  // Access values by fully qualified name from Inlet instance
  std::string name = inlet["driver/name"];

  // ... or... Get car container then access values from there
  auto car = inlet["driver/car"];
  std::string make = car["make"];
  std::string color = car["color"];
  int seats = car["seats"];
  int horsepower = car["horsepower"];

Arrays

Coming soon!

Defining And Storing

Coming soon!

Accessing

Coming soon!

Dictionaries

Coming soon!

Defining And Storing

Coming soon!

Accessing

Coming soon!