# Variables

Values in wreport are represented as variables (`wreport::Var`), which contain the value annotated with metadata (`wreport::Varcode` and `wreport::Varinfo`) about its measurement unit, description and encoding/decoding information.

Variables are described in BUFR/CREX B tables (`wreport::Vartable`), defined by WMO and shipped with the wreport library.

## Variable metadata

Each variable type is represented by a numeric WMO B table variable code:

typedef uint16_t wreport::Varcode

  Holds the WMO variable code of a variable.

There are a few accessor macros for `wreport::Varcode`:

WR_VAR(f, x, y)

  Create a WMO variable code from its F, X and Y components.

WR_STRING_TO_VAR(str)

  Convert a XXYYY string to a WMO variable code.

  This is useful only in rare cases, such as when parsing tables; use descriptor_code() to parse proper entry names such as “B01003” or “D21301”.

WR_VAR_F(code)

  Get the F part of a WMO variable code.

WR_VAR_X(code)

  Get the X part of a WMO variable code.

WR_VAR_Y(code)

  Get the Y part of a WMO variable code.

WR_VAR_FXY(code)

  Expands to WR_VAR_F(code), WR_VAR_X(code), WR_VAR_Y(code).

  This is intended as a convenient shortcut to pass a broken down varcode to functions like printf, but not much more than that. Of course it evaluates its argument multiple times.

There are functions for parsing/formatting `wreport::Varcode` values:

std::string wreport::varcode_format(Varcode code)

  Format a varcode into a string.

Varcode wreport::varcode_parse(const char *desc)

  Convert a FXXYYY string descriptor code into its short integer representation.

  Parameters:

    desc – The 6-byte string descriptor as FXXYYY

  Returns:

    The short integer code that can be queried with the WR_GET_* macros

Detailed information on a variable are accessed via `wreport::Varinfo`:

typedef const _Varinfo *wreport::Varinfo

  Varinfo reference.

  Since the actual structures are allocated inside the Vartable objects and never deallocated until the program quits, we do not need to track memory allocation and we can just refer to variable information with const pointers.

which is a pointer to a `wreport::_Varinfo`:

struct _Varinfo

  Information about a variable.

  The normal value of a variable is considered expressed in unit

  Public Functions

  int encode_decimal(double fval) const

    Encode a double value into a decimal integer value using Varinfo decimal encoding informations (scale).

    Parameters:

      fval – Value to encode

    Returns:

      The double value encoded as an integer

  double round_decimal(double val) const

    Round val so that it only fits the significant digits given in scale.

  uint32_t encode_binary(double fval) const

    Encode a double value into a positive integer value using Varinfo binary encoding informations (bit_ref and scale).

    Parameters:

      fval – Value to encode

    Returns:

      The double value encoded as an unsigned integer

  double decode_decimal(int val) const

    Decode a double value from a decimal integer value using Varinfo decimal encoding informations (scale).

    Parameters:

      val – Value to decode

    Returns:

      The decoded double value

  double decode_binary(uint32_t val) const

    Decode a double value from a decimal integer value using Varinfo binary encoding informations (bit_ref and scale).

    Parameters:

      val – Value to decode

    Returns:

      The decoded double value

  void set_bufr(Varcode code, const char *desc, const char *unit, int scale = 0, unsigned len = 0, int bit_ref = 0, int bit_len = 0)

    Set all the base Varinfo fields, then call compute_range.

  void set_crex(Varcode code, const char *desc, const char *unit, int scale = 0, unsigned len = 0)

    Set all the base Varinfo fields, then call compute_range.

  void set_string(Varcode code, const char *desc, unsigned len)

    Set all the fields to represent a string variable.

    Parameters:

      - code – the variable code

      - desc – the variable description

      - len – the maximum string length

  void set_binary(Varcode code, const char *desc, unsigned bit_len)

    Set all the fields to represent an opaque binary variable.

    Parameters:

      - code – the variable code

      - desc – the variable description

      - bit_len – the variable length in bits

  void compute_range()

    Compute the widest ranges for imin, imax, dmin and dmax that can fit any value that can be encoded both with (scale, len) and with (scale, bit_ref, bit_len).

  Public Members

  Varcode code

    Variable code, as in WMO BUFR/CREX table B.

  Vartype type

    Type of the value stored in the variable.

  char desc[64]

    Freeform variable description.

  char unit[24]

    Measurement unit of the variable, using the units defined in WMO BUFR/CREX table B.

  int scale

    Scale of the variable, defining its decimal precision.

    The value of the variable can be encoded as a decimal integer by computing value * exp10(scale).

  unsigned len

    Length in digits of the variable encoded as a decimal integer.

  int bit_ref

    Binary reference value for the variable.

    The value of the variable can be encoded as an unsigned binary value by computing value * exp10(scale) + bit_ref.

  unsigned bit_len

    Length in bits of the variable when encoded as an unsigned binary value.

  int imin

    Minimum unscaled decimal integer value the field can have.

  int imax

    Minimum unscaled decimal integer value the field can have.

  double dmin

    Minimum value the field can have.

  double dmax

    Maximum value the field can have.

## Variable

class Var

  A physical variable.

  A wreport::Var contains:

  - a wreport::Varinfo describing the variable

  - a value, that can be integer, floating point, string or opaque binary data as specified by the Varinfo

  - zero or more attributes, represented by other wreport::Var objects

  Unnamed Group

  inline void set(int val)

    Shortcuts (use with care, as the semanthics are slightly different depending on the type).

  inline void set(double val)

    Shortcuts (use with care, as the semanthics are slightly different depending on the type).

  inline void set(const char *val)

    Shortcuts (use with care, as the semanthics are slightly different depending on the type).

  inline void set(const std::string &val)

    Shortcuts (use with care, as the semanthics are slightly different depending on the type).

  inline void set(const Var &var)

    Shortcuts (use with care, as the semanthics are slightly different depending on the type).

  Public Functions

  Var(Varinfo info)

    Create a new Var, with undefined value.

  Var(Varinfo info, int val)

    Create a new Var, with integer value.

    The value is taken as the unscaled raw version. See :func:`seti` for details.

  Var(Varinfo info, double val)

    Create a new Var, with double value.

  Var(Varinfo info, const char *val)

    Create a new Var, with character value.

    The value is taken as the unscaled raw version. See :func:`setc` for details.

  Var(Varinfo info, const std::string &val)

    Create a new Var, with character value.

    The value is taken as the unscaled raw version. See :func:`setc` for details.

  Var(Varinfo info, const Var &var)

    Create a new Var with the value from another one.

    Conversions are applied if necessary, attributes are not copied.

    Parameters:

      - info – The wreport::Varinfo describing the variable to create

      - var – The variable with the value to use

  Var(const Var &var)

    Copy constructor.

  Var(Var &&var)

    Move constructor.

    After movement, var will still a valid variable, but it will be unset and without attributes.

  Var &operator=(const Var &var)

    Assignment.

  Var &operator=(Var &&var)

    Move assignment.

    After movement, var will still a valid variable, but it will be unset and without attributes.

  bool value_equals(const Var &var) const

    Test if the values are the same, regardless of variable codes or attributes.

  inline Varcode code() const

    Retrieve the Varcode for a variable.

  inline Varinfo info() const

    Get informations about the variable.

  inline bool isset() const
    Returns:

      true if the variable is defined, else false

  int enqi() const

    Get the value as an integer.

    If the variable is a scaled decimal value, it is returned unscaled. This can be used to access the exact underlying representation without hitting limits from the floating point representation

  double enqd() const

    Get the value as a double.

  const char *enqc() const

    Get the value as a string.

    If the variable is a scaled decimal value, it is returned unscaled. This can be used to access the exact underlying representation without hitting limits from the floating point representation

  std::string enqs() const

    Get the value as a std::string.

    If the variable is a scaled decimal value, it is returned unscaled. This can be used to access the exact underlying representation without hitting limits from the floating point representation

  template<typename T>
  inline T enq() const

    Templated version of enq.

  template<typename T>
  inline T enq(T default_value) const

    Return the variable value, or the given default value if the variable is not set.

  void seti(int val)

    Set the value from an integer value.

    If the variable is a scaled decimal value, it sets its unscaled version, making it possible, together with :func:`enqi`, to work with the exact underlying representation of values.

  void setd(double val)

    Set the value from a double value.

  void setc(const char *val)

    Set the value from a string or opaque binary value.

    If the variable is a scaled decimal value, it sets its unscaled version, making it possible, together with :func:`enqc`, to work with the exact underlying representation of values.

  void sets(const std::string &val)

    Set the value from a string or opaque binary value.

    If the variable is a scaled decimal value, it sets its unscaled version, making it possible, together with :func:`enqs`, to work with the exact underlying representation of values.

  void setf(const char *val)

    Set from a value formatted with the format() method.

    This will assume the input value is represented as scaled to its actual physical value

  void setc_truncate(const char *val)

    Set the value from a string value, truncating it if it is too long.

    If a value is truncated, the last character is set to ‘>’ to mark the truncation.

  void setval(const Var &src)

    Set the value from another variable, performing conversions if needed.

    The attributes of src will be ignored.

  void setattrs(const Var &src)

    Replace all attributes in this variable with all the attributes from src.

  void unset()

    Unset the value.

  void clear_attrs()

    Remove all attributes.

  const Var *enqa(Varcode code) const

    Query variable attributes.

    Parameters:

      code – The wreport::Varcode of the attribute requested. See vartable.h

    Returns:

      attr A pointer to the attribute if it exists, else NULL. The pointer points to the internal representation and must not be deallocated by the caller.

  void seta(const Var &attr)

    Set an attribute of the variable.

    An existing attribute with the same wreport::Varcode will be replaced.

    Parameters:

      attr – The attribute to add. It will be copied inside var, and memory management will still be in charge of the caller.

  void seta(Var &&attr)

    Set an attribute of the variable.

    An existing attribute with the same wreport::Varcode will be replaced.

    Parameters:

      attr – The attribute to add. Its value will be moved inside the destination attribute, and attr will be unset.

  void seta(std::unique_ptr<Var> &&attr)

    Set an attribute of the variable.

    An existing attribute with the same wreport::Varcode will be replaced.

    Parameters:

      attr – The attribute to add. It will be used directly, and var will take care of its memory management.

  void unseta(Varcode code)

    Remove the attribute with the given code.

  const Var *next_attr() const

    Get the next attribute in the attribute list.

    Example attribute iteration:

    for (const Var* a = var.next_attr(); a != NULL; a = a->next_attr()) // Do something with a

  std::string format(const char *ifundef = "") const

    Create a formatted string representation of the variable value.

    If the variable is a scaled decimal value, it is formatted as a scaled decimal value with the right amount of digits.

    Parameters:

      ifundef – String to use if the variable is undefiend

  void format(FILE *out, const char *ifundef = "") const

    Write the formatted value of this variable to an output stream.

  void print(FILE *out) const

    Print the variable to an output stream.

    Parameters:

      out – The output stream to use for printing

  void print(std::ostream &out) const

    Print the variable to an output stream.

    Parameters:

      out – The output stream to use for printing

  void print_without_attrs(FILE *out, const char *end = "\n") const

    Print the variable to an output stream, without its attributes.

    Parameters:

      out – The output stream to use for printing

  void print_without_attrs(std::ostream &out) const

    Print the variable to an output stream, without its attributes.

    Parameters:

      out – The output stream to use for printing

  unsigned diff(const Var &var) const

    Compare two Var and return the number of differences.

    Details of the differences found will be formatted using the notes system (

    See also

    notes.h).

    Parameters:

      var – The variable to compare with this one

    Returns:

      The number of differences found and reported

  void lua_push(struct lua_State *L)

    Push the variable as an object in the lua stack.

  void lua_push(struct lua_State *L) const

    Push the variable as an object in the lua stack, with only read-only methods.

  Public Static Functions

  static Var *lua_check(struct lua_State *L, int idx)

    Check that the element at idx is a Var.

    Returns:

      the Var element, or NULL if the check failed

  static const Var *lua_const_check(struct lua_State *L, int idx)

    Check that the element at idx is a Var.

    Returns:

      the Var element, or NULL if the check failed

## Variable metadata tables

Variable tables can be identified by `wreport::BufrTableID` and `wreport::CrexTableID`, and are accessed via a `wreport::Vartable`:

class BufrTableID

  Identifying information for one distinct instance of BUFR tables.

  Public Functions

  inline BufrTableID()
  inline BufrTableID(uint16_t originating_centre, uint16_t originating_subcentre, uint8_t master_table_number, uint8_t master_table_version_number, uint8_t master_table_version_number_local)
  bool operator<(const BufrTableID &o) const
  bool is_acceptable_replacement(const BufrTableID &id) const
  bool is_acceptable_replacement(const CrexTableID &id) const
  int closest_match(const BufrTableID &first, const BufrTableID &second) const
  int closest_match(const CrexTableID &first, const CrexTableID &second) const
  int closest_match(const BufrTableID &first, const CrexTableID &second) const
  void print(FILE *out) const

  Public Members

  uint16_t originating_centre = 0xffff
  uint16_t originating_subcentre = 0xffff
  uint8_t master_table_number = 0xff
  uint8_t master_table_version_number = 0xff
  uint8_t master_table_version_number_local = 0xff

class CrexTableID

  Identifying information for one distinct instance of CREX tables.

  Public Functions

  inline CrexTableID()
  inline CrexTableID(uint8_t edition_number, uint16_t originating_centre, uint16_t originating_subcentre, uint8_t master_table_number, uint8_t master_table_version_number, uint8_t master_table_version_number_bufr, uint8_t master_table_version_number_local)
  bool operator<(const CrexTableID &o) const
  bool is_acceptable_replacement(const BufrTableID &id) const
  bool is_acceptable_replacement(const CrexTableID &id) const
  int closest_match(const BufrTableID &first, const BufrTableID &second) const
  int closest_match(const CrexTableID &first, const CrexTableID &second) const
  int closest_match(const BufrTableID &first, const CrexTableID &second) const
  void print(FILE *out) const

  Public Members

  uint8_t edition_number = 0xff
  uint16_t originating_centre = 0xffff
  uint16_t originating_subcentre = 0xffff
  uint8_t master_table_number = 0xff
  uint8_t master_table_version_number = 0xff
  uint8_t master_table_version_number_bufr = 0xff
  uint8_t master_table_version_number_local = 0xff

class Vartable

  Holds a variable information table.

  It never needs to be deallocated, as all the Vartable returned by wreport are pointers to memory-cached versions that are guaranteed to exist for all the lifetime of the program.

  There are many B tables with slight differences used by different meteorological centre or equipment. This module allows to access different vartables using Vartable::get().

  Vartable and Varinfo have special memory management: they are never deallocated. This is an explicit design choice to speed up passing and copying Varinfo values, that are used very intensely as they accompany all the physical values processed by wreport. This behaviour should not be a cause of memory leaks, since a software would only need to access a limited amount of distinct variable informations during its lifetime.

  Public Functions

  virtual std::string pathname() const = 0

    Return the pathname of the file from which this table has been loaded.

  virtual Varinfo query(Varcode code) const = 0

    Query the Vartable.

    Throws an exception if not found.

    Parameters:

      code – wreport::Varcode to query

    Returns:

      the wreport::varinfo with the results of the query.

  virtual bool contains(Varcode code) const = 0

    Check if the code can be resolved to a varinfo.

  virtual Varinfo query_altered(Varcode code, int new_scale, unsigned new_bit_len, int new_bit_ref) const = 0

    Query an altered version of the vartable.

    Parameters:

      - code – wreport::Varcode to query

      - new_scale – Scale to use instead of the default

      - new_bit_len – Bit length to use instead of the default

      - new_bit_ref – bit_ref to use instead of the default

    Returns:

      the wreport::Varinfo with the results of the query. The resulting Varinfo is stored inside the Vartable, can be freely copied around and does not need to be deallocated.

  virtual bool iterate(std::function<bool(Varinfo)> dest) const = 0

    Iterate the whole contents of the table.

    Return false from dest to stop iteration.

    Returns:

      true if iteration ended normally, false if dest returned false.

  Public Static Functions

  static const Vartable *load_bufr(const std::string &pathname)

    Return a BUFR vartable, by file name.

    Once loaded, the table will be cached in memory for reuse, and further calls to load_bufr() will return the cached version.

  static const Vartable *load_crex(const std::string &pathname)

    Return a CREX vartable, by file name.

    Once loaded, the table will be cached in memory for reuse, and further calls to load_crex() will return the cached version.

  static const Vartable *get_bufr(const BufrTableID &id)

    Find a BUFR table.

  static const Vartable *get_crex(const CrexTableID &id)

    Find a CREX table.

  static const Vartable *get_bufr(const std::string &basename)

    Find a BUFR table, by file name (without extension).

  static const Vartable *get_crex(const std::string &basename)

    Find a CREX table, by file name (without extension).