xentara-plugin v2.0.1
The Xentara Plugin Framework
Loading...
Searching...
No Matches
xentara::data::ReadHandle Class Referencefinal

A handle for reading a data value. More...

#include <xentara/data/ReadHandle.hpp>

Public Types

enum class  Error {
  NoError , NullHandle , Unknown , WriteOnly ,
  NoData , TypeMismatch , Defunct
}
 An enum describing read errors. More...
 

Public Member Functions

 ReadHandle ()
 Default constructor.
 
 ReadHandle (Error error)
 Constructor for an error handle that always returns a read error.
 
 ReadHandle (std::error_code error)
 Constructor for an error handle that returns an arbitrary std::error_code.
 
template<typename Structure >
requires (!std::same_as<Structure, memory::RawMemory>)
 ReadHandle (const memory::MemoryHandle< Structure > &memoryHandle)
 Constructor using a memory handle.
 
template<typename Structure >
requires (!std::same_as<Structure, memory::RawMemory>)
 ReadHandle (memory::MemoryHandle< Structure > &&memoryHandle)
 Constructor that moves a memory handle.
 
template<typename Type >
 ReadHandle (const std::shared_ptr< Type > &value)
 Constructor for a handle that reads a non-dynamic value, like a configuration parameter.
 
template<typename Type >
 ReadHandle (const std::weak_ptr< Type > &value)
 Constructor for a handle that reads a non-dynamic value, like a configuration parameter.
 
template<typename Type >
 ReadHandle (FixedValue< Type > value)
 Constructor for a handle that always returns a fixed value.
 
template<typename Type >
 ReadHandle (std::reference_wrapper< Type > value)
 Constructor for a handle that always returns a fixed value referenced by a reference.
 
auto nativeType () const noexcept -> NativeType
 Gets the native type of the handle.
 
auto bitSize () const noexcept -> int
 Gets the number of bits that a numeric handle supports.
 
auto typeId () const noexcept -> const std::type_info &
 Gets the precise type ID of the internal type used by the handle.
 
template<typename Type >
requires (std::same_as<Type, std::remove_cvref_t<Type>> && !utils::tools::StringViewType<Type>)
auto read () const -> utils::eh::expected< Type, std::error_code >
 Reads the current value.
 
auto hardError () const -> std::error_code
 Gets the error of an error handle.
 
auto hasChangeEvent () const noexcept -> bool
 Checks whether this handle supports change events.
 
auto addChangeHandler (std::reference_wrapper< process::EventHandler > handler) const -> void
 Adds a change event handler.
 
auto removeChangeHandler (std::reference_wrapper< process::EventHandler > handler) const -> void
 Removes a change event handler.
 
auto operator== (Error error) const -> bool
 Checks whether the handle is an error handle that returns a certain error.
 
auto operator== (const std::error_code &error) const -> bool
 Checks whether the handle is an error handle that returns a certain error.
 

Static Public Member Functions

static auto errorCategory () -> const std::error_category &
 Gets the error category for error codes of type [Error].
 

Detailed Description

A handle for reading a data value.

Member Enumeration Documentation

◆ Error

An enum describing read errors.

Enumerator
NoError 

No error occurred.

NullHandle 

The handle is not associated with any value.

Unknown 

The value's identity could not be resolved. This value is returned for unknown or unsupported attributes, for example.

WriteOnly 

The value is write-only.

NoData 

The value contains no data.

TypeMismatch 

The value could not be converted to the desired type.

Defunct 

The source for the value no longer exists.

Constructor & Destructor Documentation

◆ ReadHandle() [1/9]

xentara::data::ReadHandle::ReadHandle ( )

Default constructor.

This constructor creates a null handle that is not associated with any value. Reading the handle will always return make_error_code(Error::NullHandle).

◆ ReadHandle() [2/9]

xentara::data::ReadHandle::ReadHandle ( Error  error)

Constructor for an error handle that always returns a read error.

This constructor creates a handle that always returns a certain error when reading. Reading the handle will always return make_error_code(error).

Parameters
errorThe error the handle should return when attempting to read from it.

◆ ReadHandle() [3/9]

xentara::data::ReadHandle::ReadHandle ( std::error_code  error)

Constructor for an error handle that returns an arbitrary std::error_code.

This constructor creates a handle that always returns a certain error when reading. Reading the handle will always return the given error.

Parameters
errorThe error code the handle should return when attempting to read from it.

◆ ReadHandle() [4/9]

template<typename Structure >
requires (!std::same_as<Structure, memory::RawMemory>)
xentara::data::ReadHandle::ReadHandle ( const memory::MemoryHandle< Structure > &  memoryHandle)

Constructor using a memory handle.

Parameters
memoryHandleA handle to the memory containing the value. Must not be a raw memory handle.

◆ ReadHandle() [5/9]

template<typename Structure >
requires (!std::same_as<Structure, memory::RawMemory>)
xentara::data::ReadHandle::ReadHandle ( memory::MemoryHandle< Structure > &&  memoryHandle)

Constructor that moves a memory handle.

Parameters
memoryHandleA handle to the memory containing the value. Must not be a raw memory handle.

◆ ReadHandle() [6/9]

template<typename Type >
xentara::data::ReadHandle::ReadHandle ( const std::shared_ptr< Type > &  value)

Constructor for a handle that reads a non-dynamic value, like a configuration parameter.

This constructor creates a handle that gets its value directly from a variable. The value must be static, meaning it must never change while the read handle or any copy of it exists. This constructor is usually only used to expose configuration parameters as attributes.

This function only stores a weak pointer to the value. If the weak pointer has expired (lock() returns nullptr) when the value is read, then read() will return Error::Defunct.

Parameters
valueA pointer to the value. You can use the aliasing constructor (8) of std::shared_ptr or skill::EnableSharedFromThis::sharedFromThis<Alias>() to create a shared pointer to a member variable from a shared pointer to the enclosing object.

◆ ReadHandle() [7/9]

template<typename Type >
xentara::data::ReadHandle::ReadHandle ( const std::weak_ptr< Type > &  value)

Constructor for a handle that reads a non-dynamic value, like a configuration parameter.

This constructor creates a handle that gets its value directly from a variable. The value must be static, meaning it must never change while the read handle or any copy of it exists. This constructor is usually only used to expose configuration parameters as attributes.

If the weak pointer has expired (lock() returns nullptr) when the value is read, then read() will return Error::Defunct.

Parameters
valueA pointer to the value. You can use the aliasing constructor (8) of std::shared_ptr or skill::EnableSharedFromThis::sharedFromThis<Alias>() to create a shared pointer to a member variable from a shared pointer to the enclosing object.

◆ ReadHandle() [8/9]

template<typename Type >
xentara::data::ReadHandle::ReadHandle ( FixedValue< Type >  value)

Constructor for a handle that always returns a fixed value.

This constructor creates a handle that always returns the same fixed value. You can use this constructor to construct a value that always returns true for the state of a device that cannot be offline, or that always returns Quality::Good for a skill data point whose value is always available, for example.

Template Parameters
Type

The type of the value to store. The type must meet the following criteria:

  • it must be nothrow destructible
  • it must be copy constructible
  • it must be nothrow move constructible
  • it must be copy assignable
  • it must be nothrow move assignable
  • it must be nothrow swappable

The value should also be small and inexpensive to copy and move.

Parameters
valueThe value, wrapped in the helper class FixedValue. The value will be copied or moved into the read handle, so it should not be an object that is very large or that is expensive to copy or move. For large or expensive objects, It is preferrable to store a reference or a reference-like object (like std::string_view or std::span) in the read handle. To store a reference, use the [constructor that takes an std::reference_wrapper as a parameter](ReadHandle(std::reference_wrapper<const Type>).

◆ ReadHandle() [9/9]

template<typename Type >
xentara::data::ReadHandle::ReadHandle ( std::reference_wrapper< Type >  value)

Constructor for a handle that always returns a fixed value referenced by a reference.

This constructor creates a handle that always returns the same fixed value. The value must be constant, meaning it must remain valid and must not change as long as the read handle or any copy of it exists. This constructor is usually used instead of the [fixed value constructor](ReadHandle(FixedValue<Type>)) for large or expensive values, or for values that do not meet the criteria listed in the documentation of FixedValue.

Parameters
valueA reference to the value. You should use std::cref to create the reference, to allow the compiler to select the correct constructor. The value must remain valid and constant as long as the read handle or any copy of it exists.

Member Function Documentation

◆ addChangeHandler()

auto xentara::data::ReadHandle::addChangeHandler ( std::reference_wrapper< process::EventHandler handler) const -> void

Adds a change event handler.

Parameters
handlerThe handler
Exceptions
std::runtime_errorThis type of handle does not support change events
See also
hasChangeEvent()

◆ bitSize()

auto xentara::data::ReadHandle::bitSize ( ) const -> int
noexcept

Gets the number of bits that a numeric handle supports.

This function can be used to determine how many bits a handle supports. The meaning of the bit size depends on the native type:

  • for NativeType::Boolean, the bit size is always 1.
  • for NativeType::Integer, the bit size is the number of bits the integer uses, including the sign bit. For example, for a 32-bit signed integer, the bit size is 32 (31 significant bits + one sign bit).
  • for NativeType::UnsignedInteger, the bit size is the number of bits the integer uses. For example, for a 32-bit unsigned integer, the bit size is 32.
  • For NativeType::FloatingPoint, the bit size is the size of all bits used by the type, including mantissa, exponent, and sign bits. For example, for a double precision IEEE floating point number, the bit size is 64.
  • For all other types, the function returns 0.
    Returns
    The number of supported numeric bits, or 0 for non-numeric handles (including error handles).

◆ errorCategory()

static auto xentara::data::ReadHandle::errorCategory ( ) -> const std::error_category &
static

Gets the error category for error codes of type [Error].

◆ hardError()

auto xentara::data::ReadHandle::hardError ( ) const -> std::error_code

Gets the error of an error handle.

This function returns the error code of an error handle created using ReadHandle(Error error) or ReadHandle(const std::error_code &error). An error handle will always return the given error when calling read(), and will never return a valid value.

Soft errors, meaning errors that might go away at some point, can only be gotten using read().

Returns
The hard error stored in the handle, or std::error_code() if this is not an error handle

◆ hasChangeEvent()

auto xentara::data::ReadHandle::hasChangeEvent ( ) const -> bool
noexcept

Checks whether this handle supports change events.

This function checks whether the handle can automatically generate a change event if the valkue changes. Some handles to custom types cannot generate change events, e.g. if the objects contained in the handles are not equality comparable. Also, bit field handles for bit fields that do not fit into an std::uintmax_t do not support change events.

Handles that can never change, like [error handles](hardError()), support change events, but such events are never raised. A change event is only not supported if a change can happen, but it cannot be detected automatically.

See also
memory::ObjectHandle::hasChangeEvent()
memory::BitFieldHandle::hasChangeEvent()
Returns
Returns true if the handle type supports change events, or false if not.

◆ nativeType()

auto xentara::data::ReadHandle::nativeType ( ) const -> NativeType
noexcept

Gets the native type of the handle.

This function can be used to determine what is the best type is to use as a template parameter for the read() function. You can use this function if you want to treat certain data types separately, and not rely on the built-in conversions. For example, you can use this function if you want to normally read the value as a string, but handle numbers and Booleans differently.

Returns
A hint as to which type would be best suited to store the value read. For error handles, NativeType::None is returned.

◆ operator==() [1/2]

auto xentara::data::ReadHandle::operator== ( const std::error_code error) const -> bool

Checks whether the handle is an error handle that returns a certain error.

This operator checks whether the handle is an error handle created using ReadHandle(const std::error_code &error) or ReadHandle(Error error). An error handle will always return the given error when calling read(), and will never return a valid value.

Soft errors, meaning errors that might go away at some point, can only be gotten using read().

Returns
Returns true if the handle is an error handle and the stored error matches error.

◆ operator==() [2/2]

auto xentara::data::ReadHandle::operator== ( Error  error) const -> bool

Checks whether the handle is an error handle that returns a certain error.

This operator checks whether the handle is an error handle created using ReadHandle(Error error) or ReadHandle(const std::error_code &error). An error handle will always return the given error when calling read(), and will never return a valid value.

Soft errors, meaning errors that might go away at some point, can only be gotten using read().

Returns
Returns true if the handle is an error handle and the stored error matches error.

◆ read()

template<typename Type >
requires (std::same_as<Type, std::remove_cvref_t<Type>> && !utils::tools::StringViewType<Type>)
template auto xentara::data::ReadHandle::read< Quality > ( ) const -> utils::eh::expected< Type, std::error_code >

Reads the current value.

The read value will be converted to the type specified by the Type template parameter, if possible. If the value cannot be converted, the function will return Error::TypeMismatch.

You can use std::any as template parameter to retrieve the value without knowing the type beforehand. The returned object will then contain the value wrapped in an std::any object. To reduce the number of possible types the std::any object can contain, the value is first converted to the canonical read type for its native type. The canonical types for the individual NativeType enumeration values are listed in their respective documentation. You can also use NativeTypeToCppType<nativeType, TypeUsage::Get> to programmatically determine the correct type. Values with native type NativeType::Custom are not converted, but are stored in the std::any object as is.

Template Parameters
Type

The type that the value should be converted to, or std::any to return the value as a type-erased std::any object.

Type must not be a reference, and must not be CV-qualified. Also, specializations of std::basic_string_view are not allowed, because that would create a reference to internal string data, which may no longer be valid after the function returns.

Returns
The value read, or an error if an error occurred

◆ removeChangeHandler()

auto xentara::data::ReadHandle::removeChangeHandler ( std::reference_wrapper< process::EventHandler handler) const -> void

Removes a change event handler.

Parameters
handlerThe handler. If the handler is not attached to the change event, this function does nothing.
Exceptions
std::runtime_errorThis type of handle does not support change events
See also
hasChangeEvent()

◆ typeId()

auto xentara::data::ReadHandle::typeId ( ) const -> const std::type_info &
noexcept

Gets the precise type ID of the internal type used by the handle.

This function can be used to check what the exact internal type used by the handle is. Wjile this function will work for any type of handle, generally it should only be used for handles with [native type](nativeType()] NativeType::Custom. For other types, the results may be misleading. Checking whether a handle contains a 32-bit signed integral type by checking whether this function returns typeid(std::uint32_t), for example, will not work, because there may be multiple distinct 32-bit unsigned integer types. Under Windows, for example, both unsigned int and unsigned long are 32 bit unsigned integers, but they have different type IDs. Under 64-bit Linux, the same goes for unsigned long and unsigned long long, which are both 64-bit unsigned integer types.

Returns
The type ID of the internal type used by the handle. For error handles, a type ID for a dummy type is returned.