CConfigurableObject

Name

CConfigurableObject -- base class for devices that have a configuration

Synopsis


            class CConfigurableObject {
           
  CConfigurableObject(std::string name);
        
   const std::string  getName();
          std::string cget(std::string name);
          ConfigurationArray cget();
          int getIntegerParameter(std::string name);
          unsigned int  getUnsignedParameter(std::string name);
          bool getBoolParameter(std::string name);
          double getFloatParameter(std::string name);
          std::vector<int> getIntegerList(std::string name);
          void addParameter(std::string  name, typeChecker checker, void* arg, std::string defaultValue = std::string(""));
          void clearConfiguration();
          void configure(std::string name, std::string value);
          void addIntegerParameter(std::string name, int defaultVal = 0);
          void addIntegerParameter(std::string name, int low, int high, int defaultVal = 0);
          void addBooleanParameter(std::string name, bool defaultVal =  true);
          void addEnumParameter(std::string name, const char** pValues, std::string defaultValue = std::string(""));
          void addBoolListParameter(std::string name, unsigned size, bool  defaultVal = true);
          void addBoolListParameter(std::string name, unsigned minLength, unsigned maxLength, bool defaultVal = true, int  defaultSize = -1);
          void addIntListParameter(std::string name, unsigned size, int defaultVal = 0);
          void addIntListParameter(std::string name, unsigned minlength, unsigned maxLength, int defaultVal = 0, int defaultSize = -1);
          void addBooleanParameter(std::string name, bool defaultVal = true);
          void addEnumParameter(std::string name, const char** pValues, std::string defaultValue = std::string(""));
          void addBoolListParameter(std::string name, unsigned size, bool defaultVal = true);
           void addBoolListParameter(std::string name, unsigned minLength, unsigned maxLength, bool defaultVal = true, int defaultSize = -1);
         void addIntListParameter(std::string name, unsigned size, int defaultVal = 0);
        void addIntListParameter(std::string name, unsigned minlength, unsigned maxLength, int defaultVal = 0, int defaultSize = -1);
        void addStringListParameter(std::string name, unsigned size, std::string defaultVal = "");
        void addStringListParameter(std::string name, unsigned minLength, unsigned maxLength, std::string defaultVal = "", int defaultLength = -1);
        static bool isInteger(std::string name, std::string value, void* arg);
        static bool isBool(std::string name, std::string value, void* arg);
        static bool isEnum(std::string name, std::string value, void* arg);
      static bool isList(std::string name, std::string value, void* arg);
      static bool isBoolList(std::string name, std::string value, void* arg);
      static bool isIntList(std::string name, std::string value, void* arg);
      static bool isStringList(std::string name, std::string value, void* arg);
      static isEnumParameter makeEnumSet(const char** values);
      static bool strToBool(std::string value);
      typedef std::pair<typeChecker, void*> TypeCheckInfo;
      typedef std::vector<std::pair<std::string, std::string> > ConfigurationArray;
    

      struct  limit {
        bool s_checkMe;
        long s_value;
        limit();
        limit(long value);
    } ;
      typedef std::pair<limit, limit> Limits;
      typedef std::set<std::string> isEnumParameter;
    typedef struct _ListSizeConstraint {
          limit s_atLeast;
          limit s_atMost;
    } ListSizeConstraint
    typedef struct _isListParameter {
        ListSizeConstraint s_allowedSize;
        TypeCheckInfo s_checker;
    } isListParameter;
      typedef void (*ConstraintFreer)(void*);

     typedef struct _DynamicConstraint { 
        ConstraintFreer s_Releaser;
        void* s_pObject;
    } DynamicConstraint, *pDynamicConstraint;
  
    struct  flimit {
        bool s_checkMe;
        float s_value;
        flimit();
    
        flimit(float value);
    
    };
      typedef std::pair<flimit, flimit> FloatingLimits;
      typedef std::vector<isEnumParameter*> EnumCheckers;

};
        

DESCRIPTION

This class is the ultimate base class of the CReadoutModule object passed to device driver onAttach methods. It manages the configuration database of a configurable object.

The interaction of a configurable object or an object that embeds configuration via delegation is:

  1. The object defines a configuration that consists of a set of named parameters and initial values. Each configuration value can have a constraint function attached to it that is called prior to allowing the value to assume a new value.

    Through these constraint functions parameter values can' be very strongly typed (e.g. not just parameter must be an integer but parameter must be an integer in this range).

    Pre packaged constraint functions and convenience functions make it easy to set up most types of constraints, however if something special is required client code can implement a special constraint.

  2. At some point in the lifetime of a configurable object, the object is configured. This is usually done by creating (the CCUSB framework does this for you) a command or command ensemble that accepts configuration name/value pairs and passes them to the configure method. This method will invoke the constraint checker and, if successful, modify the value of the configuration parameter. If the new value fails the constraint, a std::string exception is thrown and should be caught and reported at some level by the caller.

    Again for CCUSB device drivers this is transparent.

  3. Configurable objects can query their configuration. The constraint checkers ensure that each value has the type and range constraints required of that parameter. Semantics, however must be enforced and applied by the object that uses the configuration.

    It is always possible to get a stringified value for each configuration item (in fact configuration items are stored as strings). Convenience methods allow for clients to fetch conversions of those strings to a rich set of types.

    CCUSB device drivers normally fetch and process their configurations when their Initialize and addReadoutList methods are invoked.

For the full set of methods see the METHODS section below. The pre-defined constraint checkers additionally make use of several data types which are described in PUBLIC VARIABLES, TYPES and CONSTANTS further below.

METHODS

CConfigurableObject(std::string name);

Constructs a configurable object. CCUSB device drivers have this construction performed for them. Configurable objects have names to allow them to be placed in some sort of configuration dictionary by the application. the name parameter supplies the configuration name.

If names are used, it's likely a good thing to ensure that unique names are chose for each configuration namespace the application maintains. This is not enforced by the constructor, however.

const std::string getName();

Returns the name of the configuration. This is the value of the parameter passed to the constructor.

std::string cget(std::string name);

Returns the string value of the configuration parameter name. If the parameter was not defined a string exception is thrown.

In situations where you don't know the set of configuration parameters that have been defined, see the overloaded cget method described next.

CConfigurableObject::ConfigurationArray cget();

Gets the entire configuration of the module as name value pairs. CConfigurableObject::ConfigurationArray is described fully in PUBLIC VARIABLES, TYPES and CONSTANTS below, however you can think iof it as a vector of std::string pairs of configuration parameter name and value.

int getIntegerParameter(std::string name);

Invokes cget on the name configuration parameter. The resulting string is converted to an integer and returned, if possible. If the string is not a valid integer, a string exception is thrown.

Note that this and other convenience methods for getting parameter values converted to specific data types pass any exceptions from cget on up to the caller.

unsigned int getUnsignedParameter(std::string name);

Same as getIntegerParameter, however the conversion to an unsigned value is attempted. This is recommended for e.g. base addresses.

bool getBoolParameter(std::string name);

Invokes cget and attempts to convert the resulting string to a bool value which is returned if successful. A rather rich set of values can be converted to bools.

StringBool Value
truetrue
yestrue
1true
ontrue
enabledtrue
falsefalse
nofalse
0false
offfalse
disabledfalse

Failure to convert to a bool throws a string exception.

double getFloatParameter(std::string name);

Uses cget to retrieve the value of the name configuration parameter. The string is converted to a float and returned. If the string is not a valid float, a string exception is thrown.

std::vector<int> getIntegerList(std::string name);

Uses the cget method to obtain the configuration parameter name. The string is treated as a Tcl list which is composed entirely of integers. If this assumption is correct, a std::vector of the integers that made up the list is returned. If the string is either an invalid list or not entirely composed of elements that can be converted to int, a string exception is thrown.

void addParameter(std::string name, typeChecker checker, void* arg, std::string defaultValue = std::string(""));

This is the base mechanism for defining a configuration parameter. See the convenience methods below before using this as they may be easier to use.

name is the name of the parameter being added. By convention, this starts with the - character (like options in Tk). For example a module slot might be defined as a -slot configuration parameter.

checker is a pointer to the constraint checking function. If no constraint checking is required (e.g. the paramter is a pure string), pass NULL for this parameter.

arg is a parameter that is passed without interpretation to the constraint checker. See CONSTRAINT CHECKING below for more about how constraint checkers are defined and called. See also the descriptions of the built in constraint checkers that are static members of this class, documented later in this section.

defaultValue is the initial value supplied to the parameter. Note that this is not constraint checked. This is intentional as it allows you to require a parameter setting by providing an invalid initial parameter value.

void clearConfiguration();

Clear the configuration. This removes any parameter definitions as well as their value from the configuration database. In most cases this function is not necessary.

void configure(std::string name, std::string value);

Attempts to configure a parameter name should be a configuration parameter name that has been defined by addParameter or its convenience methods. value is the new proposed value of the parameter. The constraint checker, if any, is called for that parameter and if it fails a string exception is thrown. Otherwise, the new parameter value replaces the old one.

void addIntegerParameter(std::string name, int defaultVal = 0);

Convenience method to add an parameter name which is constrained to be an integer parameter that has no range requirements. The initial value of this parameter will be defaultVal

void addIntegerParameter(std::string name, int low, int high, int defaultVal = 0);

Convenience methos that creates a parameter (name) that is constrained to be an integer in the range [low..high].

The initial value of the parameters is set to defaultVal which is not checked against the limits.

void addBooleanParameter(std::string name, bool defaultVal = true);

Adds a parameter name to the configuration database which is contrained to be a string that converts to a bool. The initial value of the parameter will be defaultVal

void addEnumParameter(std::string name, const char** pValues, std::string defaultValue = std::string(""));

Adds a parameter name that is constrained to be one of the values pointed to by the pValues array. The initial value is defaultValue

The pValues parameter should be a pointer to a null terminated set of character pointers. This sounds much harder than it is:


const char* enumValues[] = {"red", "green", "blue", NULL};
                            

In the code fragment above, enumValues can be passed in as the pValues argument and will constrain the values of the configuration parameter to be in the set {red, greeen, blue}.

void addBoolListParameter(std::string name, unsigned size, bool defaultVal = true);

Adds a new configuration parameter name that is constrained to be a valid Tcl list of bool strings of exactly size elements long.

The initial value will be set to size elements of defaultVal

void addBoolListParameter(std::string name, unsigned minLength, unsigned maxLength, bool defaultVal = true, int defaultSize = -1);

Same as the previous method, however the list size is constrained to be at least minLength and at most maxLength elements long. The initial value is defaultSize elements of defaultVal If defaultSize is outside the length limits, it is forced to the closest limit.

void addIntListParameter(std::string name, unsigned size, int defaultVal = 0);

Adds a parameter that is constrained to be a fixed length Tcl list of size integer values. The initial value of the list is size copies of defaultValue

The range of values in the list is unconstrained. See the overloads below however.

void addIntListParameter(std::string name, unsigned minlength, unsigned maxLength, int defaultVal = 0, int defaultSize = -1);

Same as the previous method however the list can have a size in the range [minlength..maxLength]. the initial value of the list is defaultSize elements of defaultVal.

As for addBoolListParameter, if the defaultSize parameter is outside the range of valid list length it is forced to the closest value. Thus the default value really creates minlength elements.

static bool isInteger(std::string name, std::string value, void* arg);

This is a static method that can be used as a constraint checker for integer parameters. When it is used, the constraint parameter shoule be NULL if no range checking is desired or a pointer to a Limits struct as described in PUBLIC VARIABLES, TYPES and CONSTANTS to describe which limits are desired and their values.

static bool isBool(std::string name, std::string value, void* arg);

This is a static method that can be used as a constraint checker for boolean parameters. When used, the constraint parameter should be NULL.

static bool isEnum(std::string name, std::string value, void* arg);

Constriaint checker fora n enumerated type. When used, the constraint parameter should be a pointer to an std::set<string> which has elements for each valid enumerator value.

static bool isList(std::string name, std::string value, void* arg);

General constraint checker for a parameter that must look like a Tcl list. The constraint parameter is a pointer to an isListParameter struct as defined in PUBLIC VARIABLES, TYPES and CONSTANTS This structure should be filled in to provide limits on the number of list elements the list can have. A constraint checker that is applied to each list element can also be supplied.

static bool isBoolList(std::string name, std::string value, void* arg);

Constraint checker for a Tcl formatted list of booleans. The constraint parameter shouild be a pointer to a ListSizeConstraint described in PUBLIC VARIABLES, TYPES and CONSTANTS. This should set limits on the size of the list. isBoolList will ensure that the elements of the list are booleans.

static bool isIntList(std::string name, std::string value, void* arg);

Constraint checker for a list of integers. The constraint parameter should be a ListSizeConstraint that describes the allowed list sizes. The checker will ensure that the elements fo the list are all valid integers. At present, this checker does not support checking the values of the list elemeents against range limits.

You could manually construct the isListParameter structure to do this and use isList if required.

static bool isStringList(std::string name, std::string value, void* arg);

Constraint checker for lists of strings. The constraint parametr is a ListSizeConstraint that defines the allowed sizes of the list.

static isEnumParameter makeEnumSet(const char** values);

Helper function that converts a null terminated array of pointers to strings into a isEnumParameter constraint parameter.

static bool strToBool(std::string value);

Convenience function that converts a string to a boolean or throws an exception if the resulting string cannot be converted.

PUBLIC VARIABLES, TYPES and CONSTANTS

The class definition in the SYNOPSIS section above shows a large number of type definitions for this class. Almost all of these types are structures used by the built in constraint checkers.In most cases, if you use the convenience functions to define your parameters you won't need to know the details of these types.

The remainder of this section describes these types and the constraint checkers they belong to.

typedef std::vector<std::pair<std::string, std::string> > ConfigurationArray;

The ConfigurationArray is returned from one of the overloads of the cget method. This type is a vector of pair. The first element of each pair is the name of a parameter while the second element is it's current value.

The following fragment of code shows how to use this to dump the current configuration of a configurable object pointed to by pConfig


ConfigurationArray config = pConfig->cget();
for (int i = 0; i < config.size(); i++) {
   cout << config[i].first << " is set to " << config[i].second << endl;
}
                            

struct limit { bool s_checkMe; long s_value; limit(); limit(long value); } ;, typedef std::pair<limit, limit> Limits;

These data types are used with the isInteger constraint checker. Each limit data type represents a range limit that may or may not be checked according to the state of its s_checkMe flag.

Limits is a pair of limit structs where the first one represents the lower limit and the second one the upper limit.

typedef std::set<std::string> isEnumParameter;

The isEnumParameter is used by the isEnum method to validate parameters that are enumerate parameter. The actual type is a set of the character strings that are allowed to be assigned to the parameter value.

typedef std::pair<typeChecker, void*> TypeCheckInfo; , typedef struct _ListSizeConstraint { limit s_atLeast; limit s_atMost; } ListSizeConstraint, typedef struct _isListParameter { ListSizeConstraint s_allowedSize; TypeCheckInfo s_checker; } isListParameter;

This set of types are used to validate lists. The isListParameter is what is used to validate lists. This consists of two chunks;

s_allowedSize is used to validate the size of a list. It is a ListSizeConstraint which allows you to specify minimum and maximum list sizes. The list size limits are inclusive so you can specify a fixed size list by setting both s_atLeast and s_atMost to be the same.

s_checker is a constraint checker and its parameter used to validate each item in the list. This is applied after the string is determined to be a valid list and after the size of the list has been checked against the limits defined by s_allowedSize s_checker TypeCheckInfo which is a pair whose first element is a pointer to the actual constraint checking function and whose second is a pointer to data passed to the constraint checker without interpretation. For more information about how constratin checkers work see CONSTRAINT CHECKING below.

struct flimit { bool s_checkMe; float s_value; flimit(); flimit(float value); };, typedef std::pair<flimit, flimit> FloatingLimits;

These types specify floating point limits in a mannger analgous to integer limits.

CONSTRAINT CHECKING

Constraint checking is the CConfigurableObject class's way to enforce type safety and other constraints on the values of configuration parameters. When a parameter is created with addParameter, The caller has an option to provide a constraint checker and a parameter that provides extra information to the constraint checker that can parameterize the constraints it checks.

A constraint checker is just a function of the form:


bool myConstraintChecker(std::string name, std::string newValue,
                        void* pClientData);
                    

When the configure method is called for a parameter name that has a constraint checker attached to it, that checker is called and passed the parameters shown in the code fragment above:

name

Is the name of the parameter being configured.

newValue

Is the proposed new value for the parameter.

pClientData

Is the constraint parameter passed to addParameter passed without interpretation or modification.

The constraint checker is expected to return true if the proposed newValue is acceptable by the constraint checker and false if not. If true is returned the parameter value is modified to newValue otherwise a string exception is thrown and the parameter value is not modified.

The CCUSB framework catches string exceptions thrown by CConfigurableObject and converts those into configuration file processing error messages. Any configuration file processing error is reported and aborts the start of the run that caused it.