Skip to content

Commit

Permalink
Merge pull request #334 from odin-detector/dpdk_support
Browse files Browse the repository at this point in the history
Add utilities to support camera and DPDK developments
  • Loading branch information
timcnicholls authored Feb 29, 2024
2 parents 36284dd + e2d1387 commit f11b8bf
Show file tree
Hide file tree
Showing 7 changed files with 714 additions and 7 deletions.
3 changes: 3 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ include_directories(${CMAKE_BINARY_DIR}/include)
# Add common/include directory to include path
include_directories(${COMMON_DIR}/include)

# Add the cmake subdirectory so that CMake finders are installed
add_subdirectory(cmake)

# Add the common subdirectory
add_subdirectory(${COMMON_DIR})

Expand Down
3 changes: 3 additions & 0 deletions cpp/cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
file(GLOB CMAKE_FILES *.cmake *.cmake.in)

install(FILES ${CMAKE_FILES} DESTINATION cmake)
1 change: 1 addition & 0 deletions cpp/common/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ SET(HEADERS ClassLoader.h
Json.h
logging.h
OdinDataException.h
ParamContainer.h
SegFaultHandler.h
SharedBufferManager.h
stringparse.h)
Expand Down
18 changes: 11 additions & 7 deletions cpp/common/include/IpcMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class IpcMessageException : public std::exception
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/error/en.h"

#include "rapidjson/pointer.h"

namespace OdinData
{
Expand Down Expand Up @@ -121,14 +121,12 @@ class IpcMessage
MsgVal msg_val=MsgValIllegal,
bool strict_validation=true);

//! Update parameters from another IPCMessage.
//!
//! This will iterate the parameters in the given IPCMessage and set them on this instance.
//!
//! \param other - IPCMessage to take parameters from

//! Updates parameters from another IPCMessage.
void update(const IpcMessage& other);

//! Updates parameters from a rapidJSON object.
void update(const rapidjson::Value& param_val, std::string param_prefix="");

//! Gets the value of a named parameter in the message.
//!
//! This template method returns the value of the specified parameter stored in the
Expand Down Expand Up @@ -311,6 +309,12 @@ class IpcMessage
//! Returns a JSON-encoded string of the message
const char* encode(void);

//! Returns a JSON-encoded string of the message parameters at a specified path
const char* encode_params(const std::string& param_path = std::string());

//! Copies parameters at a specified into the specified JSON value object
void copy_params(rapidjson::Value& param_obj, const std::string& param_path = std::string());

//! Overloaded equality relational operator
friend bool operator ==(IpcMessage const& lhs_msg, IpcMessage const& rhs_msg);

Expand Down
309 changes: 309 additions & 0 deletions cpp/common/include/ParamContainer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
/*!
* ParamContainer.h - abstract parameter container class with JSON encoding/decoding
*
* Created on: Oct 7, 2021
* Author: Tim Nicholls, STFC Detector Systems Software Group
*/

#ifndef PARAMCONTAINER_H_
#define PARAMCONTAINER_H_

#include <map>
#include <vector>
#include <boost/function.hpp>
#include <boost/bind/bind.hpp>

namespace OdinData
{

//! ParamContainerException - custom exception class for ParamContainer implementing "what" for
//! error string
class ParamContainerException : public std::exception
{
public:

//! Create ParamContainerException with no message
ParamContainerException(void) throw() :
what_("")
{ };

//! Create ParamContainerException with informational message
ParamContainerException(const std::string what) throw() :
what_(what)
{};

//! Return the content of the informational message
virtual const char* what(void) const throw()
{
return what_.c_str();
};

//! Destructor
~ParamContainerException(void) throw() {};

private:

// Member variables
const std::string what_; //!< Informational message about the exception

};

} // namespace OdinData

// Override RapidJSON assertion mechanism before including appropriate headers
#ifdef RAPIDJSON_ASSERT
#undef RAPIDJSON_ASSERT
#endif
#define RAPIDJSON_ASSERT(x) if (!(x)) throw OdinData::ParamContainerException("rapidjson assertion thrown");
#include "rapidjson/document.h"
#include "rapidjson/pointer.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/error/en.h"

namespace OdinData
{

//! ParamContainer - parameter container with JSON encoding/decoding
class ParamContainer
{

//! Parameter setter function type definition
typedef boost::function<void(rapidjson::Value&)> SetterFunc;
//! Parameter setter function map type definition
typedef std::map<std::string, SetterFunc> SetterFuncMap;
//! Parameter getter function type definition
typedef boost::function<void(rapidjson::Value&)> GetterFunc;
//! Parameter getter function map type definition
typedef std::map<std::string, GetterFunc> GetterFuncMap;

public:

//! Use the RapidJSON Document and Value types throughout
typedef rapidjson::Document Document;
typedef rapidjson::Value Value;

//! Default constructor
ParamContainer() {};

//! Copy constructor
ParamContainer(const ParamContainer& container);

//! Encode the parameter container to a JSON-formatted string
std::string encode(void);

//! Encode the parameter container into an existing document, using the specified path
//! as a prefix for all parameter paths
void encode(ParamContainer::Document& doc_obj, std::string prefix_path = std::string()) const;

//! Update the values of parameters from the specified JSON-formatted string
void update(std::string json);

//! Update the values of the parameters from the specified JSON-formatted character array
void update(const char* json);

//! Update the values of the parameters from the specified parameter container
void update(const ParamContainer& container);

//! Update the values of the parameters from the specified value object
void update(const ParamContainer::Value& value_obj);

//! Update the values of the parameters from the specified JSON document
void update(ParamContainer::Document& doc_obj);

protected:

//! Bind a parameter to a path in the container.
//!
//! This template method binds the specified parameter to the specified path in the
//! container, allowing the value of the parameter to be read or updated from an appropriate
//! JSON message.
//!
//! \param param - reference to the parameter to bind
//! \param path - JSON pointer-like path to bind the parameter to

template<typename T>
void bind_param(T& param, const std::string& path)
{
// Bind the parameter into the setter function map
setter_map_[path] = boost::bind(
&ParamContainer::param_set<T>, this, boost::ref(param), boost::placeholders::_1
);

// Bind the parameter into the getter function map
getter_map_[path] = boost::bind(
&ParamContainer::param_get<T>, this, boost::ref(param), boost::placeholders::_1
);

}

//! Bind a vector parameter to a path in the container.
//!
//! This template method binds the specified vector parameter of a given type to the
//! specified path in the parameter container, allowing the value of the parameter to be
//! read or updated from an appropriate JSON message.
//!
//! \param param - reference to the vector parameter to bind
//! \param path - JSON pointer-like path to bind the parameter to

template<typename T>
void bind_vector_param(std::vector<T>& param, const std::string& path)
{
// Bind the vector parameter into the setter function map
setter_map_[path] = boost::bind(
&ParamContainer::vector_param_set<T>, this, boost::ref(param),
boost::placeholders::_1
);

// Bind the vector parameter into the getter function map
getter_map_[path] = boost::bind(
&ParamContainer::vector_param_get<T>, this, boost::ref(param),
boost::placeholders::_1
);
}

//! Set the value of a parameter in the container.
//!
//! This template method sets the value of of a parameter in the container to the value
//! given the JSON object passed as an argument. This method is bound into the setter
//! function map of the container and invoked by the update method. The type-specific
//! set_value method is used to update the parameter value from the JSON object.
//!
//! \param param - reference to the parameter to update
//! \param value_obj - reference to a RapidJSON value object containing the value to set

template<typename T>
void param_set(T& param, rapidjson::Value& value_obj)
{
set_value<T>(param, value_obj);
}

//! Get the value of a parameter in the container.
//!
//! This template method gets the value of a parameter in the container, setting that value
//! in the JSON object passed as an argument. This method is bound into the getter
//! function map of the container and invoked by the encode method. The type-specific
//! get_value method is used to udpate the JSON object with the parameter value.
//!
//! \param param - reference to the parameter to retrieve
//! \param value_obj - reference to a RapidJSON value object to be set with the value

template<typename T> const
void param_get(T& param, rapidjson::Value& value_obj)
{
get_value<T>(param, value_obj);
}

//! Set the value of a vector parameter in the container.
//!
//! This template method sets the value of of a vector parameter in the container to the
//! values given the JSON object passed as an argument. This method is bound into the setter
//! function map of the container and invoked by the update method. The type-specific
//! set_value method is used to update the parameter values from the JSON object.
//!
//! \param param - reference to the vector parameter to update
//! \param value_obj - reference to a RapidJSON value object containing the value to set

template<typename T>
void vector_param_set(std::vector<T>& param, rapidjson::Value& value_obj)
{
// Clear the existing values in the parameter vector
param.clear();

// Iterate through the values of the parameter in the value object and add to the
// parameter vector
for (rapidjson::Value::ValueIterator itr = value_obj.Begin();
itr != value_obj.End(); ++itr)
{
T val;
set_value<T>(val, *itr);
param.push_back(val);
}
}

//! Get the value of a vector parameter in the container.
//!
//! This template method gets the value of a vector parameter in the container, setting
//! those values in the JSON object passed as an argument. This method is bound into the
//! getter function map of the container and invoked by the encode method. The type-specific
//! get_value method is used to udpate the JSON object with the parameter values.
//!
//! \param param - reference to the vector parameter to retrieve
//! \param value_obj - reference to a RapidJSON value object to be set with the values

template<typename T>
void vector_param_get(std::vector<T>& param, rapidjson::Value& value_obj)
{
// Create a new JSON array object to hold the parameter values using RapidJSON swap
// semantics
rapidjson::Document::AllocatorType& allocator = doc_.GetAllocator();
rapidjson::Value vec_obj(rapidjson::kArrayType);
value_obj.Swap(vec_obj);

// Iterate through the values in the parameter vector and add to the value object
for (typename std::vector<T>::iterator itr = param.begin(); itr != param.end(); ++itr)
{
rapidjson::Value val;
get_value<T>(*itr, val);
value_obj.PushBack(val, allocator);
}
}

private:

//! Bind parameters - virtual method which must be defined in derived classes
virtual void bind_params(void) = 0;

//! Set the value of a parameter.
//!
//! This private template method is used by the param_set method to set the value of a
//! parameter from the specified JSON object. Explicit specialisations of this method
//! are provided, mapping each of the RapidJSON types onto the appropriate parameter types,
//! which is returned as a value.
//!
//! \param value_obj - reference to a RapidJSON value object containing the value
//! \return the value of the appropriate type

template<typename T> void set_value(T& param, rapidjson::Value& value_obj) const;

//! Get the value of a parameter.
//!
//! This private template method is used by the param_get method to get the value of a
//! parameter and place it in the specified JSON object. Explicit specialisations of this
//! method are provided, mapping each of the parameter types on the appropriate RapidJSON
//! types.
//!
//! \param param - reference to the parameter to get the value of
//! \param value_obj - RapidJSON value object to update with the value of the parameter

template<typename T> void get_value(T& param, rapidjson::Value& value_obj) const;

//! Construct a valid JSON pointer path.
//!
//! This private utility method is used to construct a valid JSON pointer path, ensuring
//! that the leading / prefix is present.
//!
//! \param path - reference to path string
//! \return valid pointer path string

inline const std::string pointer_path(const std::string& path) const
{
// Set the pointer to the specified path
std::string pointer_path(path);

// If the pointer is not prefixed with the required slash, insert it
if (*pointer_path.begin() != '/')
{
pointer_path.insert(0, "/");
}
return pointer_path;
}

SetterFuncMap setter_map_; //!< Paramter setter function map
GetterFuncMap getter_map_; //!< Parameter getter function map
ParamContainer::Document doc_; //!< JSON document object used for encoding
};

} // namespace OdinData

#endif // PARAMCONTAINER_H_
Loading

0 comments on commit f11b8bf

Please sign in to comment.