Skip to content
Snippets Groups Projects
Commit 509ff83a authored by Chao Peng's avatar Chao Peng
Browse files

Remove all online related stuff, they will be moved to a new repo

parent 3e4d4ebd
No related branches found
No related tags found
No related merge requests found
Showing with 1 addition and 3644 deletions
......@@ -24,9 +24,6 @@ else()
get_target_property(SPDLOG_INCLUDE_DIR spdlog::spdlog INTERFACE_INCLUDE_DIRECTORIES)
endif()
find_package(coda_et REQUIRED)
get_target_property(CODA_ET_INCLUDE_DIR coda_et::coda_et INTERFACE_INCLUDE_DIRECTORIES)
find_package(EVIO REQUIRED)
get_target_property(EVIO_INCLUDE_DIR EVIO::EVIO INTERFACE_INCLUDE_DIRECTORIES)
......@@ -69,4 +66,3 @@ if(HCANA_BUILTIN_PODD)
endif()
add_subdirectory(src)
add_subdirectory(cmake)
add_subdirectory(tools)
......@@ -8,7 +8,7 @@ include(FindThreads)
#----------------------------------------------------------------------------
# Sources and headers
file(GLOB src "*.cxx" "*.cpp")
file(GLOB src "*.cxx")
file(GLOB allheaders RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
list(REMOVE_ITEM allheaders
"${CMAKE_CURRENT_SOURCE_DIR}/${LIBNAME}_LinkDef.h"
......@@ -66,7 +66,6 @@ target_include_directories(${LIBNAME}
$<BUILD_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<BUILD_INTERFACE:${FMT_INCLUDE_DIR}>
$<BUILD_INTERFACE:${CODA_ET_INCLUDE_DIR}>
)
target_compile_options(${LIBNAME}
......@@ -83,7 +82,6 @@ target_link_libraries(${LIBNAME}
PUBLIC
Podd::Podd
Podd::Decode
coda_et::coda_et
)
set_target_properties(${LIBNAME} PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
......@@ -109,7 +107,6 @@ build_root_dictionary(${LIBNAME} ${headers}
INCLUDEDIRS
$<BUILD_INTERFACE:-I${SPDLOG_INCLUDE_DIR}>
$<BUILD_INTERFACE:-I${FMT_INCLUDE_DIR}>
$<BUILD_INTERFACE:-I${CODA_ET_INCLUDE_DIR}>
-I${CMAKE_CURRENT_SOURCE_DIR}
-I${CMAKE_CURRENT_SOURCE_DIR}/include
-I${CMAKE_CURRENT_SOURCE_DIR}/include/hcana
......
//============================================================================//
// A class based on the support from ConfigParser and ConfigValue //
// It provides a simple way to read text file as configuration file, and read //
// or modify a parameter in the inherited class //
// The Configure() function should be overloaded according to specialized //
// requirements, and be called after the parameters being configured //
// //
// Chao Peng //
// 10/31/2016 //
//============================================================================//
#include <fstream>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include "ConfigObject.h"
//============================================================================//
// Constructor, Destructor //
//============================================================================//
// constructor
ConfigObject::ConfigObject(const std::string &splitter, const std::string &ignore, bool case_ins)
: split_chars(splitter), ignore_chars(ignore), case_insensitive(case_ins), __empty_value("")
{
// set default replace bracket
replace_pair = std::make_pair("{", "}");
}
// destructor
ConfigObject::~ConfigObject()
{
// place holder
}
//============================================================================//
// Public Member Function //
//============================================================================//
// configure the cluster method
void ConfigObject::Configure(const std::string &path)
{
// save the path
config_path = path;
// clear the map
config_map.clear();
// read configuration file in
ReadConfigFile(path);
}
// clear all the loaded configuration values
void ConfigObject::ClearConfig()
{
config_path = "";
config_map.clear();
}
// read configuration file and build the configuration map
bool ConfigObject::ReadConfigFile(const std::string &path)
{
ConfigParser c_parser;
c_parser.SetSplitters(split_chars); // self-defined splitters
if (c_parser.ReadFile(path)) {
// current directory
parserProcess(c_parser, path);
return true;
} else {
std::cerr << "Cannot open configuration file "
<< "\"" << path << "\""
<< std::endl;
return false;
}
}
// read the configuration string directly
void ConfigObject::ReadConfigString(const std::string &content)
{
ConfigParser c_parser;
c_parser.SetSplitters(split_chars);
c_parser.ReadBuffer(content.c_str());
parserProcess(c_parser, "buffer_string");
}
// continue parse the terms
void ConfigObject::parserProcess(ConfigParser &c_parser, const std::string &source)
{
std::string cur_dir = ConfigParser::decompose_path(source).dir;
while (c_parser.ParseLine()) {
// possible control words
if (c_parser.NbofElements() == 1) {
std::string control = c_parser.TakeFirst();
size_t pos = control.find("{THIS_DIR}");
if(pos != std::string::npos)
control.replace(pos, 10, cur_dir);
parseControl(control);
// var_name and var_value
} else if (c_parser.NbofElements() == 2) {
std::string var_name, key, var_value;
c_parser >> var_name >> var_value;
size_t pos = var_value.find("{THIS_DIR}");
if(pos != std::string::npos)
var_value.replace(pos, 10, cur_dir);
parseTerm(std::move(var_name), std::move(var_value));
// unsupported format
} else {
std::cout << "Warning: Unsupported format at line "
<< c_parser.LineNumber() << " from " << source << "\n"
<< "\"" << c_parser.CurrentLine() << "\""
<< std::endl;
}
}
}
// check if a certain term is configured
bool ConfigObject::HasKey(const std::string &var_name)
const
{
auto key = formKey(var_name);
if (config_map.find(key) != config_map.end())
return true;
return false;
}
// list all the existing configuration keys
void ConfigObject::ListKeys()
const
{
for (auto &it : config_map) {
std::cout << it.first << std::endl;
}
}
// get all the existing configuration keys
std::vector<std::string> ConfigObject::GetKeyList()
const
{
std::vector<std::string> res;
for (auto &it : config_map) {
res.push_back(it.first);
}
return res;
}
// save current configuration into a file
void ConfigObject::SaveConfig(const std::string &path)
const
{
std::string save_path;
if (path.empty())
save_path = config_path;
if(save_path.empty())
save_path = "latest.conf";
std::ofstream save(save_path);
for (auto &it : config_map) {
save << it.first
<< " " << split_chars.front() << " "
<< it.second
<< std::endl;
}
}
// get configuration value by its name/key
ConfigValue ConfigObject::GetConfigValue(const std::string &var_name)
const
{
// convert to lower case and remove uninterested characters
auto key = formKey(var_name);
auto it = config_map.find(key);
if (it == config_map.end()) {
return __empty_value;
} else {
ConfigValue result(it->second);
reform(result._value, replace_pair.first, replace_pair.second);
return result;
}
}
// set configuration value by its name/key
void ConfigObject::SetConfigValue(const std::string &var_name, const ConfigValue &c_value)
{
// convert to lower case and remove uninterested characters
auto key = formKey(var_name);
config_map[key] = c_value;
}
// get configuration value from the map
// if no such config value exists, it will fill the default value in
ConfigValue ConfigObject::GetConfigValue(const std::string &var_name, const ConfigValue &def_value, bool verbose)
{
auto key = formKey(var_name);
auto it = config_map.find(key);
if (it == config_map.end()) {
if (def_value.IsEmpty())
return __empty_value;
if (verbose) {
std::cout << var_name << " (key: " << key << ")"
<< " not defined in configuration file, set to default value "
<< def_value
<< std::endl;
}
config_map[key] = def_value;
return def_value;
}
ConfigValue result(it->second);
reform(result._value, replace_pair.first, replace_pair.second);
return result;
}
//============================================================================//
// Protected Member Function //
//============================================================================//
// build the key
std::string ConfigObject::formKey(const std::string &rawKey)
const
{
std::string key = ConfigParser::str_remove(rawKey, ignore_chars);
if (case_insensitive) {
key = ConfigParser::str_lower(key);
}
return key;
}
// replace the contents inside replace_pair with the configuration value
void ConfigObject::reform(std::string &input, const std::string &op, const std::string &cl)
const
{
// loop until no pair found
while (true) {
auto rpair = ConfigParser::find_pair(input, op, cl);
if (rpair.first != std::string::npos && rpair.second != std::string::npos) {
// get content inside the bracket
std::string var = input.substr(rpair.first + op.size(),
rpair.second - op.size() - rpair.first);
// deal with nested structure
reform(var, op, cl);
// replace content
std::string val;
// environment variable
if (rpair.first > 0 && input.at(rpair.first - 1) == '$') {
val = std::getenv(var.c_str());
// replace $ mark also
rpair.first--;
// ConfigObject variable
} else {
val = GetConfigValue(var)._value;
}
// replace variable with configuration value
input.replace(rpair.first, rpair.second - rpair.first + cl.size(), val);
} else {
// no pair found any more
return;
}
}
}
//============================================================================//
// Private Member Function //
//============================================================================//
// parse the control word and respond
void ConfigObject::parseControl(const std::string &word)
{
if (ConfigParser::str_upper(word.substr(0, 7)) == "INCLUDE") {
// need the most outer pair
auto p = ConfigParser::find_pair(word, "(", ")");
// not find pair
if (p.first == std::string::npos || p.second == std::string::npos) {
std::cout << "Unsupported control word format: " << word << "."
<< "Expected: INCLUDE(path)"
<< std::endl;
return;
}
int begin = p.first + 1;
int length = p.second - begin;
std::string new_path = word.substr(begin, length);
reform(new_path, replace_pair.first, replace_pair.second);
ReadConfigFile(new_path);
}
else {
std::cout << "Unsupported control word: " << word << std::endl;
}
}
// parse the configuration term
void ConfigObject::parseTerm(std::string &&var_name, std::string &&var_value)
{
// convert to lower case and remove uninterested characters
auto key = formKey(var_name);
if (key.back() == '+') {
key.pop_back();
auto it = config_map.find(key);
if (it != config_map.end())
it->second += var_value;
else
config_map[key] = var_value;
} else {
config_map[key] = var_value;
}
}
#ifndef CONFIG_OBJECT_H
#define CONFIG_OBJECT_H
#include <string>
#include <utility>
#include <vector>
#include <unordered_map>
#include "ConfigParser.h"
#define CONF_CONN(val, str, def, warn) val=GetConfigValue<decltype(val)>(str, def, warn)
#define CONF_CONN2(val, def, warn) val=GetConfiValue<decltype(val)>(str, def, warn)
#define GET_CONF(obj, val, str, def, warn) val=obj.GetConfiValue<decltype(val)>(str, def, warn)
#define GET_CONF2(obj, val, def, warn) val=GetConfiValue<decltype(val)>(#val, def, warn)
class ConfigObject
{
public:
// constructor, desctructor
ConfigObject(const std::string &spliiter = ":=", const std::string &ignore = " _\t", bool case_ins = true);
virtual ~ConfigObject();
// public member functions
void ClearConfig();
void SaveConfig(const std::string &path = "") const;
void ListKeys() const;
bool HasKey(const std::string &name) const;
bool ReadConfigFile(const std::string &path);
void ReadConfigString(const std::string &content);
void SetConfigValue(const std::string &var_name, const ConfigValue &c_value);
void SetIgnoreChars(const std::string &ignore) {ignore_chars = ignore;}
void SetSplitChars(const std::string &splitter) {split_chars = splitter;}
void SetReplacePair(const std::string &open, const std::string &close)
{
replace_pair = std::make_pair(open, close);
}
// get members
ConfigValue GetConfigValue(const std::string &var_name) const;
template<typename T>
T GetConfigValue(const std::string &var_name)
const
{
return GetConfigValue(var_name).Convert<T>();
}
ConfigValue GetConfigValue(const std::string &var_name, const ConfigValue &def_value, bool verbose = true);
template<typename T>
T GetConfigValue(const std::string &var_name, const T &val, bool verbose = true)
{
return GetConfigValue(var_name, ConfigValue(val), verbose).Convert<T>();
}
const std::string &GetConfigPath() const {return config_path;}
const std::string &GetSplitChars() const {return split_chars;}
const std::string &GetSpaceChars() const {return ignore_chars;}
const std::pair<std::string, std::string> &GetReplacePair() const {return replace_pair;}
std::vector<std::string> GetKeyList() const;
// functions that to be overloaded
virtual void Configure(const std::string &path = "");
protected:
// protected member functions
void reform(std::string &input, const std::string &open, const std::string &close) const;
std::string formKey(const std::string &raw_key) const;
private:
void parserProcess(ConfigParser &p, const std::string &source);
void parseControl(const std::string &control_word);
void parseTerm(std::string &&var_name, std::string &&var_value);
protected:
std::string split_chars;
std::string ignore_chars;
bool case_insensitive;
std::pair<std::string, std::string> replace_pair;
std::string config_path;
std::unordered_map<std::string, std::string> config_map;
// return this reference when there is no value found in the map
ConfigValue __empty_value;
};
#endif
//============================================================================//
// A class to simplify the argument parsing procedure //
// //
// Chao Peng //
// 07/26/2017 //
//============================================================================//
#include "ConfigOption.h"
#include "ConfigParser.h"
#include <iostream>
#include <cstring>
ConfigOption::ConfigOption()
{
// place holder
}
ConfigOption::~ConfigOption()
{
// place holder
}
void ConfigOption::AddOpt(OptType type, char s_term)
{
AddOpt(type, s_term, s_term);
}
void ConfigOption::AddLongOpt(OptType type, const char *l_term)
{
AddLongOpt(type, l_term, *l_term);
}
void ConfigOption::AddOpts(OptType type, char s_term, const char *l_term)
{
AddOpts(type, s_term, l_term, s_term);
}
void ConfigOption::AddOpt(OptType type, char s_term, char mark)
{
if(s_opt_map.find(s_term) != s_opt_map.end()) {
std::cerr << "ConfigOption: Short option " << s_term
<< " has already been added, abort AddOpt."
<< std::endl;
return;
}
s_opt_map[s_term] = Opt(mark, type);
}
void ConfigOption::AddLongOpt(OptType type, const char *l_term, char mark)
{
if(l_opt_map.find(l_term) != l_opt_map.end()) {
std::cerr << "ConfigOption: Long option " << l_term
<< " has already been added, abort AddOpt."
<< std::endl;
return;
}
l_opt_map[l_term] = Opt(mark, type);
}
void ConfigOption::AddOpts(OptType type, char s_term, const char *l_term, char mark)
{
AddOpt(type, s_term, mark);
AddLongOpt(type, l_term, mark);
}
bool ConfigOption::parseLongOpt(const char *arg)
{
auto vars = ConfigParser::split(arg, strlen(arg), "=");
std::string key = std::move(vars.front());
vars.pop_front();
auto it = l_opt_map.find(key);
if(it == l_opt_map.end()) {
std::cerr << "Unknown option --" << key << std::endl;
return false;
}
switch(it->second.type)
{
case arg_require:
if(vars.empty()) {
std::cerr << "Lack of argument for option --" << key << std::endl;
return false;
}
opt_pack.emplace_back(it->second.mark, it->second.type, std::move(vars.front()));
break;
case arg_none:
opt_pack.emplace_back(it->second.mark, it->second.type);
break;
case help_message:
return false;
}
return true;
}
bool ConfigOption::parseShortOpt(char key, int argc, char *argv[], int &idx)
{
auto it = s_opt_map.find(key);
if(it == s_opt_map.end()) {
std::cerr << "Unknown option -" << key << std::endl;
return false;
}
switch(it->second.type)
{
case arg_require:
if((idx + 1) >= argc || *argv[idx + 1] == '-') {
std::cerr << "Lack of argument for option -" << key << std::endl;
return false;
}
opt_pack.emplace_back(it->second.mark, it->second.type, ConfigValue(argv[++idx]));
break;
case arg_none:
opt_pack.emplace_back(it->second.mark, it->second.type);
break;
case help_message:
return false;
}
return true;
}
bool ConfigOption::ParseArgs(int argc, char *argv[])
{
if (argc < 1)
return false;
argv0 = argv[0];
bool success = true;
arg_pack.clear();
opt_pack.clear();
for(int i = 1; i < argc; ++i)
{
char* ptr = argv[i];
// option
if(*ptr == '-') {
// long option
if(*(ptr + 1) == '-') {
success &= parseLongOpt(ptr + 2);
// short option
} else {
success &= parseShortOpt(*(ptr + 1), argc, argv, i);
}
// arguments
} else {
arg_pack.emplace_back(ptr);
}
}
return success;
}
void ConfigOption::SetDesc(const char *desc)
{
base_desc = desc;
}
void ConfigOption::SetDesc(char mark, const char *desc)
{
std::string option;
bool found_mark = false;
for(auto &it : s_opt_map)
{
if(it.second.mark != mark) continue;
option = " - ";
option.back() = it.first;
if(it.second.type == arg_require)
option += " <arg>";
option += ",";
found_mark = true;
}
for(auto &it : l_opt_map)
{
if(it.second.mark != mark) continue;
option += " --" + it.first;
if(it.second.type == arg_require)
option += "=<arg>";
option += ",";
found_mark = true;
}
if(!found_mark) {
std::cerr << "Config Option: Cannot find any option with mark <"
<< mark << ">, abort adding description." << std::endl;
return;
}
option.back() = ':';
option += " ";
option += desc;
option_desc.emplace_back(option);
}
std::string ConfigOption::GetInstruction()
{
std::string res = base_desc + "\noptions:\n";
auto pvar = res.find("%0");
if (pvar != std::string::npos) {
res.replace(pvar, 2, argv0);
}
for(auto &option : option_desc)
{
res += "\t" + option + "\n";
}
return res;
}
#ifndef CONFIG_OPTION_H
#define CONFIG_OPTION_H
#include "ConfigValue.h"
#include <vector>
#include <string>
#include <unordered_map>
class ConfigOption
{
public:
enum OptType : int
{
arg_none = 0,
arg_require,
help_message,
};
struct Opt
{
char mark;
OptType type;
ConfigValue var;
Opt() : mark(-1), type(arg_none) {}
Opt(char m, OptType t) : mark(m), type(t) {}
Opt(char m, OptType t, ConfigValue v) : mark(m), type(t), var(v) {}
};
public:
ConfigOption();
virtual ~ConfigOption();
void AddOpt(OptType type, char s_term);
void AddOpt(OptType type, char s_term, char mark);
void AddLongOpt(OptType type, const char *l_term);
void AddLongOpt(OptType type, const char *l_term, char mark);
void AddOpts(OptType type, char s_term, const char *l_term);
void AddOpts(OptType type, char s_term, const char *l_term, char mark);
void SetDesc(const char *desc);
void SetDesc(char mark, const char *desc);
std::string GetInstruction();
bool ParseArgs(int argc, char *argv[]);
size_t NbofArgs() const {return arg_pack.size();}
size_t NbofOpts() const {return opt_pack.size();}
const std::string &GetArgv0() {return argv0;}
const ConfigValue &GetArgument(size_t i) {return arg_pack.at(i);}
const std::vector<ConfigValue> &GetArguments() {return arg_pack;}
const std::vector<Opt> &GetOptions() {return opt_pack;}
private:
bool parseLongOpt(const char *arg);
bool parseShortOpt(char key, int argc, char *argv[], int &idx);
private:
std::unordered_map<char, Opt> s_opt_map;
std::unordered_map<std::string, Opt> l_opt_map;
std::vector<Opt> opt_pack;
std::vector<ConfigValue> arg_pack;
std::string argv0;
std::string base_desc;
std::vector<std::string> option_desc;
};
#endif // CONFIG_OPTION_H
This diff is collapsed.
#ifndef CONFIG_PARSER_H
#define CONFIG_PARSER_H
#include <string>
#include <vector>
#include <deque>
#include <fstream>
#include "ConfigValue.h"
// a macro to auto generate enum2str and str2enum
// name mapping begins at bias and continuously increase, split by '|'
// an example:
// enum ABC {a = 3, b, c};
// ENUM_MAP(ABC, 3, "a|b|c")
// ABC2str(3) = "a"
// str2ABC("b") = 4
#define ENUM_MAP(type, bias, strings) \
static std::string type ## 2str(int T) \
{ \
return ConfigParser::get_split_part(T - (bias), strings, '|'); \
}; \
static type str2 ## type(const char *str) \
{ \
return static_cast<type>(bias + ConfigParser::get_part_count(str, strings, '|')); \
}
// config parser class
class ConfigParser
{
typedef std::pair<std::string, std::string> string_pair;
public:
struct Format
{
std::string split; // element splitters (chars)
std::string white; // white spaces (chars)
std::string delim; // line delimiter (string)
std::string glue; // line glue (string)
std::string cmtmark; // comment marks (string), until the line breaker '\n'
std::string cmtopen; // comment-block opening mark (string)
std::string cmtclose; // comment-block closing mark (string)
static Format Basic() {return {" \t,", " \t", "\n", "", "", "", ""};}
static Format BashLike() {return {" \t,", " \t", "\n", "\\", "#", "\'", "\'"};}
static Format CLike() {return {" \t,\n", " \t\n", ";", "", "//", "/*", "*/"};}
};
struct CharBuffer
{
std::vector<char> data;
size_t begin, end;
CharBuffer(size_t cap = 256) : begin(0), end(0)
{
data.resize(cap);
}
void Reset() {begin = 0; end = 0; data.clear();}
void Add(char ch)
{
if(data.size() <= end)
data.resize(2*data.size());
data[end++] = ch;
}
std::string String()
const
{
std::string str;
if(end > begin)
str.assign(&data[begin], end - begin);
return str;
}
inline const char &operator [] (size_t idx) const {return data[idx];}
inline char &operator [] (size_t idx) {return data[idx];}
};
public:
ConfigParser(Format f = Format::BashLike());
ConfigParser(ConfigParser &&that);
ConfigParser(const ConfigParser &that);
virtual ~ConfigParser();
ConfigParser &operator = (ConfigParser &&rhs);
ConfigParser &operator = (const ConfigParser &rhs);
// format related
inline void SetFormat(Format &&f) {form = f;}
inline void SetFormat(const Format &f) {form = f;}
inline void SetSplitters(std::string s) {form.split = s;}
inline void SetWhiteSpaces(std::string w) {form.white = w;}
inline void SetCommentMark(std::string c) {form.cmtmark = c;}
inline void SetCommentPair(std::string o, std::string c) {form.cmtopen = o; form.cmtclose = c;}
inline void SetLineGlues(std::string g) {form.glue = g;}
inline void SetLineBreaks(std::string b) {form.delim = b;}
const Format &GetFormat() const {return form;}
// dealing with file/buffer
bool OpenFile(const std::string &path, size_t cap = 64*1024);
bool ReadFile(const std::string &path);
void ReadBuffer(const char*);
void CloseFile();
void Clear();
// parse line, return false if no more line to parse
bool ParseLine();
// parse the whole file or buffer, return false if no elements found
bool ParseAll();
// parse a string, trim and split it into elements
int ParseString(const std::string &line);
// get current parsing status
bool CheckElements(int num, int optional = 0);
int NbofElements() const {return elements.size();}
int LineNumber() const {return line_number;}
std::string CurrentLine() const {return cur_line.String();}
// take the elements
ConfigValue TakeFirst();
template<typename T>
T TakeFirst()
{
return TakeFirst().Convert<T>();
}
template<typename T>
ConfigParser &operator >>(T &t)
{
t = (*this).TakeFirst().Convert<T>();
return *this;
}
template<class BidirIt>
int Take(BidirIt first, BidirIt last)
{
int count = 0;
for(auto it = first; it != last; ++it, ++count)
{
if(elements.empty())
break;
*it = elements.front();
elements.pop_front();
}
return count;
}
template<template<class, class> class Container>
Container<ConfigValue, std::allocator<ConfigValue>> TakeAll()
{
Container<ConfigValue, std::allocator<ConfigValue>> res;
while(elements.size())
{
res.emplace_back(std::move(elements.front()));
elements.pop_front();
}
return res;
}
template<template<class, class> class Container, class T>
Container<T, std::allocator<T>> TakeAll()
{
Container<T, std::allocator<T>> res;
while(elements.size())
{
ConfigValue tmp(std::move(elements.front()));
elements.pop_front();
res.emplace_back(tmp.Convert<T>());
}
return res;
}
private:
// private functions
bool getBuffer();
bool getLine(CharBuffer &line_buf, bool recursive = false);
int parseBuffer(const CharBuffer &line);
private:
// private members
Format form;
std::ifstream infile;
CharBuffer buf, cur_line;
int line_number;
std::deque<std::string> elements;
public:
// static functions
static void comment_line(std::string &str, const std::string &cmt, const std::string &brk);
static void comment_between(std::string &str, const std::string &open, const std::string &close);
static std::string trim(const std::string &str, const std::string &w);
static std::deque<std::string> split(const std::string &str, const std::string &s);
static std::deque<std::string> split(const char* str, const size_t &len, const std::string &s);
static std::string get_split_part(int num, const char *str, const char &s);
static int get_part_count(const char *cmp, const char *str, const char &s);
static std::vector<int> stois(const std::string &str, const std::string &s, const std::string &w);
static std::vector<float> stofs(const std::string &str, const std::string &s, const std::string &w);
static std::vector<double> stods(const std::string &str, const std::string &s, const std::string &w);
static std::string str_remove(const std::string &str, const std::string &ignore);
static std::string str_replace(const std::string &str, const std::string &ignore, const char &rc = ' ');
static std::string str_lower(const std::string &str);
static std::string str_upper(const std::string &str);
static std::pair<size_t, size_t> find_pair(const std::string &str,
const std::string &open,
const std::string &close,
size_t pos = 0);
static bool case_ins_equal(const std::string &str1, const std::string &str2);
static int find_integer(const std::string &str, const size_t &pos = 0);
static std::vector<int> find_integers(const std::string &str);
static void find_integer_helper(const std::string &str, std::vector<int> &result);
struct PathInfo { std::string dir, name, ext; };
static PathInfo decompose_path(const std::string &path);
static std::string compose_path(const PathInfo &path);
static std::string form_path(const std::string &dir, const std::string &file);
static std::string file_to_string(const std::string &path);
// break text file into several blocks in the format
// <label> <open_mark> <content> <close_mark>, this structure can be separated by sep characters
// return extracted <residual> {<label> <content>} with white characters trimmed
struct TextBlock {std::string label, content;};
struct TextBlocks {std::string residual; std::vector<TextBlock> blocks;};
static TextBlocks break_into_blocks(const std::string &buf,
const std::string &open = "{",
const std::string &close = "}",
const std::string &seps = " \t\n");
};
#endif
//============================================================================//
// A string wrapper class that convert string to other data types //
// //
// Chao Peng //
// 06/07/2016 //
//============================================================================//
#include "ConfigValue.h"
#include "ConfigParser.h"
#include <climits>
#include <algorithm>
using namespace std;
//============================================================================//
// Constructors, Destructor and Assignment Operators //
//============================================================================//
ConfigValue::ConfigValue(const string &value)
: _value(value)
{}
ConfigValue::ConfigValue(string &&value)
: _value(move(value))
{}
ConfigValue::ConfigValue(const char *value)
: _value(value)
{}
ConfigValue::ConfigValue(const bool &value)
{
if(value)
_value = "1";
else
_value = "0";
}
ConfigValue::ConfigValue(const int &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const long &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const long long &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const unsigned &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const unsigned long &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const unsigned long long &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const float &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const double &value)
: _value(to_string(value))
{}
ConfigValue::ConfigValue(const long double &value)
: _value(to_string(value))
{}
ConfigValue &ConfigValue::operator =(const string &str)
{
(*this)._value = str;
return *this;
}
ConfigValue &ConfigValue::operator =(string &&str)
{
(*this)._value = move(str);
return *this;
}
//============================================================================//
// Public Member functions //
//============================================================================//
bool ConfigValue::Bool()
const
{
if((_value == "1") ||
(ConfigParser::case_ins_equal(_value, "T")) ||
(ConfigParser::case_ins_equal(_value, "True")) ||
(ConfigParser::case_ins_equal(_value, "Y")) ||
(ConfigParser::case_ins_equal(_value, "Yes")))
return true;
if((_value == "0") ||
(ConfigParser::case_ins_equal(_value, "F")) ||
(ConfigParser::case_ins_equal(_value, "False")) ||
(ConfigParser::case_ins_equal(_value, "N")) ||
(ConfigParser::case_ins_equal(_value, "No")))
return false;
cout << "Config Value: Failed to convert "
<< _value << " to bool type. Return false."
<< endl;
return false;
}
char ConfigValue::Char()
const
{
try {
int value = stoi(_value);
if(value > CHAR_MAX)
cout << "Config Value: Limit exceeded while converting "
<< _value << " to char." << endl;
return (char) value;
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to char. 0 returned." << endl;
return 0;
}
}
unsigned char ConfigValue::UChar()
const
{
try {
unsigned long value = stoul(_value);
if(value > UCHAR_MAX)
cout << "Config Value: Limit exceeded while converting "
<< _value << " to unsigned char." << endl;
return (unsigned char) value;
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to unsigned char. 0 returned." << endl;
return 0;
}
}
short ConfigValue::Short()
const
{
try {
int value = stoi(_value);
if(value > SHRT_MAX)
cout << "Config Value: Limit exceeded while converting "
<< _value << " to short." << endl;
return (short) value;
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to short. 0 returned." << endl;
return 0;
}
}
unsigned short ConfigValue::UShort()
const
{
try {
unsigned long value = stoul(_value);
if(value > USHRT_MAX)
cout << "Config Value: Limit exceeded while converting "
<< _value << " to unsigned short." << endl;
return (unsigned short) value;
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to unsigned short. 0 returned." << endl;
return 0;
}
}
int ConfigValue::Int()
const
{
try {
return stoi(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to int. 0 returned." << endl;
return 0;
}
}
unsigned int ConfigValue::UInt()
const
{
try {
return (unsigned int)stoul(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to unsigned int. 0 returned." << endl;
return 0;
}
}
long ConfigValue::Long()
const
{
try {
return stol(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to long. 0 returned." << endl;
return 0;
}
}
long long ConfigValue::LongLong()
const
{
try {
return stoll(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to long long. 0 returned." << endl;
return 0;
}
}
unsigned long ConfigValue::ULong()
const
{
try {
return stoul(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to unsigned long. 0 returned." << endl;
return 0;
}
}
unsigned long long ConfigValue::ULongLong()
const
{
try {
return stoull(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to unsigned long long. 0 returned." << endl;
return 0;
}
}
float ConfigValue::Float()
const
{
try {
return stof(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to float. 0 returned." << endl;
return 0;
}
}
double ConfigValue::Double()
const
{
try {
return stod(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to double. 0 returned." << endl;
return 0;
}
}
long double ConfigValue::LongDouble()
const
{
try {
return stold(_value);
} catch (exception &e) {
cerr << e.what() << endl;
cerr << "Config Value: Failed to convert "
<< _value << " to long double. 0 returned." << endl;
return 0;
}
}
const char *ConfigValue::c_str()
const
{
return _value.c_str();
}
//============================================================================//
// Other functions //
//============================================================================//
ostream &operator << (ostream &os, const ConfigValue &b)
{
return os << b.c_str();
}
#ifndef CONFIG_VALUE_H
#define CONFIG_VALUE_H
#include <string>
#include <iostream>
#include <sstream>
#include <utility>
#include <typeinfo>
// demangle type name
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
// gnu compiler needs to demangle type info
static inline std::string demangle(const char* name)
{
int status = 0;
//enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
#else
// do nothing if not gnu compiler
static inline std::string demangle(const char* name)
{
return name;
}
#endif
// this helps template specialization in class
template <typename T>
struct __cv_id { typedef T type; };
class ConfigValue
{
public:
friend class ConfigParser;
friend class ConfigObject;
public:
ConfigValue() {}
ConfigValue(const std::string &value);
ConfigValue(std::string &&value);
ConfigValue(const int &value);
ConfigValue(const double &value);
explicit ConfigValue(const char *value);
explicit ConfigValue(const bool &value);
explicit ConfigValue(const long &value);
explicit ConfigValue(const long long &value);
explicit ConfigValue(const unsigned &value);
explicit ConfigValue(const unsigned long &value);
explicit ConfigValue(const unsigned long long &value);
explicit ConfigValue(const float &value);
explicit ConfigValue(const long double &value);
ConfigValue &operator =(const std::string &str);
ConfigValue &operator =(std::string &&str);
bool Bool() const;
char Char() const;
unsigned char UChar() const;
short Short() const;
unsigned short UShort() const;
int Int() const;
unsigned int UInt() const;
long Long() const;
long long LongLong() const;
unsigned long ULong() const;
unsigned long long ULongLong() const;
float Float() const;
double Double() const;
long double LongDouble() const;
const char *c_str() const;
const std::string &String() const {return _value;}
bool IsEmpty() const {return _value.empty();}
operator std::string()
const
{
return _value;
}
bool operator ==(const std::string &rhs)
const
{
return _value == rhs;
}
template<typename T>
T Convert()
const
{
return convert( __cv_id<T>());
}
private:
std::string _value;
template<typename T>
T convert(__cv_id<T> &&)
const
{
std::stringstream iss(_value);
T _cvalue;
if(!(iss >> _cvalue)) {
std::cerr << "Config Value Warning: Undefined value returned, failed to convert "
<< _value
<< " to "
<< demangle(typeid(T).name())
<< std::endl;
}
return _cvalue;
}
ConfigValue convert(__cv_id<ConfigValue>) const {return *this;}
bool convert(__cv_id<bool> &&) const {return (*this).Bool();}
float convert(__cv_id<float> &&) const {return (*this).Float();}
double convert(__cv_id<double> &&) const {return (*this).Double();}
long double convert(__cv_id<long double> &&) const {return (*this).LongDouble();}
std::string convert(__cv_id<std::string> &&) const {return (*this)._value;}
const char* convert(__cv_id<const char*> &&) const {return (*this)._value.c_str();}
};
// show string content of the config value to ostream
std::ostream &operator << (std::ostream &os, const ConfigValue &b);
#endif
//============================================================================//
// A C++ wrapper class for C based ET //
// //
// Chao Peng //
// 02/27/2016 //
//============================================================================//
#include "PRadETChannel.h"
#include "PRadETStation.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
using namespace std;
PRadETChannel::PRadETChannel(size_t size)
: curr_stat(nullptr), et_id(nullptr), bufferSize(size)
{
buffer = new uint32_t[bufferSize];
}
PRadETChannel::~PRadETChannel()
{
if(buffer != nullptr)
delete[](buffer), buffer = nullptr;
// force close ET
ForceClose();
}
// Close ET connection
void PRadETChannel::ForceClose()
{
if((et_id != nullptr) && et_alive(et_id)) {
et_forcedclose(et_id);
et_id = nullptr;
}
}
// Open ET
void PRadETChannel::Open(const char* ipAddr, int tcpPort, const char* etFile)
{
// Use a direct connection to the ET system
config.SetCast(ET_DIRECT);
// Set the ip address and tcp port
config.SetHost(ipAddr);
config.SetServerPort(tcpPort);
int charSize = strlen(etFile)+1;
char *fileName = new char[charSize];
strncpy(fileName, etFile, charSize);
// Open et client
int status = et_open(&et_id, fileName, config.Get());
delete fileName;
if(status != ET_OK) {
throw(PRadException(PRadException::ET_CONNECT_ERROR, "et_client: cannot open et client!"));
}
/* set level of debug output */
et_system_setdebug(et_id, ET_DEBUG_INFO);
}
void PRadETChannel::NewStation(const string &name, int mode)
{
auto it = stations.find(name);
if(it == stations.end()) {
curr_stat = new PRadETStation(this, name, mode);
stations[string(name)] = curr_stat;
}
}
void PRadETChannel::SwitchStation(const string &name)
{
auto it = stations.find(name);
if(it != stations.end()) {
curr_stat = it->second;
} else {
cout << "ET Channel Warning: station " << name << " does not exist!" << endl;
}
}
void PRadETChannel::RemoveStation(const string &name)
{
try {
if(et_id != nullptr && et_alive(et_id)) {
auto it = stations.find(name);
if(it != stations.end()) {
it->second->Remove();
stations.erase(it);
} else {
cout << "ET Channel Warning: station " << name << " does not exist!" << endl;
}
} else {
cout << "ET Channel Warning: cannot remove station while disconnected from ET!" << endl;
}
} catch (PRadException e) {
throw e;
}
}
PRadETStation* PRadETChannel::GetStation(const string &name)
{
auto it = stations.find(name);
if(it != stations.end()) {
return it->second;
} else {
return nullptr;
}
}
// Attach station
void PRadETChannel::AttachStation()
{
try {
curr_stat->Create();
curr_stat->Attach();
} catch (PRadException e) {
throw(e);
}
cout << "Successfully attached to ET!" << endl;
}
// Read one event from ET station, return true if success
bool PRadETChannel::Read()
{
// check if et is opened or alive
if(et_id == nullptr || !et_alive(et_id))
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is not opened or dead!"));
et_att_id att = curr_stat->GetAttachID();
// get the event
int status = et_event_get(et_id, att, &etEvent, ET_ASYNC, nullptr);
switch(status)
{
case ET_OK:
break;
case ET_ERROR_EMPTY:
return false;
case ET_ERROR_DEAD:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is dead!"));
case ET_ERROR_TIMEOUT:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: got timeout!!"));
case ET_ERROR_BUSY:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: station is busy!"));
case ET_ERROR_WAKEUP:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: someone told me to wake up."));
default:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: unkown error!"));
}
// copy the data buffer
copyEvent();
// put back the event
status = et_event_put(et_id, att, etEvent);
switch(status)
{
case ET_OK:
break;
case ET_ERROR_DEAD:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is dead!"));
default:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: unkown error!"));
}
return true;
}
bool PRadETChannel::Write(void *buf, int nbytes)
{
// check if et is opened or alive
if(et_id == nullptr || !et_alive(et_id))
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is not opened or dead!"));
et_att_id att = curr_stat->GetAttachID();
int status = et_event_new(et_id, att, &etEvent, ET_SLEEP, nullptr, nbytes);
switch(status) {
case ET_OK:
break;
case ET_ERROR_EMPTY:
return false;
case ET_ERROR_DEAD:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is dead!"));
case ET_ERROR_TIMEOUT:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: got timeout!!"));
case ET_ERROR_BUSY:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: station is busy!"));
case ET_ERROR_WAKEUP:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: someone told me to wake up."));
default:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: unkown error!"));
}
// build et event
void *data;
et_event_getdata(etEvent, &data);
memcpy((void *) data, (const void *) buf, nbytes);
et_event_setlength(etEvent, nbytes);
// put back the event
status = et_event_put(et_id, att, etEvent);
switch(status)
{
case ET_OK:
break;
case ET_ERROR_DEAD:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: et is dead!"));
default:
throw(PRadException(PRadException::ET_READ_ERROR,"et_client: unkown error!"));
}
return true;
}
void PRadETChannel::copyEvent()
{
void *data;
et_event_getdata(etEvent, &data);
et_event_getlength(etEvent, &bufferSize);
bufferSize /= 4; // from byte to int32 words
uint32_t *data_buffer = (uint32_t*) data;
size_t index = 0;
// check if it is a block header
if(bufferSize >= 8 && data_buffer[7] == 0xc0da0100) {
index += 8;
bufferSize -= 8;
}
for(size_t i = 0; i < bufferSize; ++i)
{
buffer[i] = data_buffer[index+i];
}
}
// nested config classes
// et_openconfig
PRadETChannel::Configuration::Configuration()
{
Initialize();
}
PRadETChannel::Configuration::~Configuration()
{
et_open_config_destroy(config);
}
// wrapper functions
void PRadETChannel::Configuration::Initialize()
{
et_open_config_init(&config);
}
void PRadETChannel::Configuration::SetWait(int val)
{
et_open_config_setwait(config, val);
}
void PRadETChannel::Configuration::SetTimeOut(struct timespec val)
{
et_open_config_settimeout(config, val);
}
void PRadETChannel::Configuration::SetHost(const char *val)
{
et_open_config_sethost(config, val);
}
void PRadETChannel::Configuration::SetCast(int val)
{
et_open_config_setcast(config, val);
}
void PRadETChannel::Configuration::SetTTL(int val)
{
et_open_config_setTTL(config, val);
}
void PRadETChannel::Configuration::SetPort(unsigned short val)
{
et_open_config_setport(config, val);
}
void PRadETChannel::Configuration::SetServerPort(unsigned short val)
{
et_open_config_setserverport(config, val);
}
void PRadETChannel::Configuration::AddBroadCast(const char *val)
{
et_open_config_addbroadcast(config, val);
}
void PRadETChannel::Configuration::RemoveBroadCast(const char *val)
{
et_open_config_removebroadcast(config, val);
}
void PRadETChannel::Configuration::AddMultiCast(const char *val)
{
et_open_config_addmulticast(config, val);
}
void PRadETChannel::Configuration::RemoveMultiCast(const char *val)
{
et_open_config_removemulticast(config, val);
}
void PRadETChannel::Configuration::SetPolicy(int val)
{
et_open_config_setpolicy(config, val);
}
void PRadETChannel::Configuration::SetMode(int val)
{
et_open_config_setmode(config, val);
}
void PRadETChannel::Configuration::SetDebugDefault(int val)
{
et_open_config_setdebugdefault(config, val);
}
void PRadETChannel::Configuration::SetInterface(const char *val)
{
et_open_config_setinterface(config, val);
}
void PRadETChannel::Configuration::SetTCP(int rBufSize, int sBufSize, int noDelay)
{
et_open_config_settcp(config, rBufSize, sBufSize, noDelay);
}
#ifndef PRAD_ET_CHANNEL_H
#define PRAD_ET_CHANNEL_H
#include <unordered_map>
#include <string>
#include <stdint.h>
#include "et.h"
#include "PRadException.h"
#include "PRadETStation.h"
#define ET_CHUNK_SIZE 500
class PRadETChannel
{
public:
class Configuration
{
public:
Configuration();
virtual ~Configuration();
et_openconfig &Get() {return config;}
// wrapper functions
void Initialize();
void SetWait(int val);
void SetTimeOut(struct timespec val);
void SetHost(const char *val);
void SetCast(int val);
void SetTTL(int val);
void SetPort(unsigned short val);
void SetServerPort(unsigned short val);
void AddBroadCast(const char *val);
void RemoveBroadCast(const char *val);
void AddMultiCast(const char *val);
void RemoveMultiCast(const char *val);
void SetPolicy(int val);
void SetMode(int val);
void SetDebugDefault(int val);
void SetInterface(const char *val);
void SetTCP(int rBufSize, int sBufSize, int noDelay);
private:
et_openconfig config;
};
public:
PRadETChannel(size_t size = 1048576);
virtual ~PRadETChannel();
void Open(const char *ipAddr, int tcpPort, const char *etFile);
void NewStation(const std::string &name, int mode=2);
void SwitchStation(const std::string &name);
void RemoveStation(const std::string &name);
void AttachStation();
void DetachStation();
void ForceClose();
bool Read();
bool Write(void *buf, int nbytes);
void *GetBuffer() {return (void*) buffer;}
size_t GetBufferLength() {return bufferSize;}
Configuration &GetConfig() {return config;}
et_sys_id &GetID() {return et_id;}
PRadETStation *GetCurrentStation() {return curr_stat;}
PRadETStation *GetStation(const std::string &name);
private:
Configuration config;
PRadETStation *curr_stat;
std::unordered_map<std::string, PRadETStation*> stations;
et_sys_id et_id;
et_event *etEvent;
uint32_t *buffer;
size_t bufferSize;
void copyEvent();
};
#endif
//============================================================================//
// A C++ wrapper class for C based ET station //
// //
// Chao Peng //
// 04/01/2016 //
//============================================================================//
#include "PRadETStation.h"
#include "PRadETChannel.h"
PRadETStation::PRadETStation(PRadETChannel *p, std::string n, int mode)
: et_system(p), name(n)
{
PreSetting(mode);
}
PRadETStation::~PRadETStation()
{
Remove();
}
void PRadETStation::PreSetting(int mode)
{
// Generic settings
config.SetUser(ET_STATION_USER_MULTI);
config.SetRestore(ET_STATION_RESTORE_OUT);
config.SetPrescale(1);
config.SetCUE(ET_CHUNK_SIZE);
// TODO, change to meaningful settings
int selections[] = {17,15,-1,-1};
char fName[] = "et_my_function";
char libName[] = "libet_user.so";
// some pre-defined settings
// TODO, make these settings selectable
switch(mode)
{
case 1:
config.SetSelect(ET_STATION_SELECT_ALL);
config.SetBlock(ET_STATION_BLOCKING);
break;
case 2:
config.SetSelect(ET_STATION_SELECT_ALL);
config.SetBlock(ET_STATION_NONBLOCKING);
break;
case 3:
config.SetSelect(ET_STATION_SELECT_MATCH);
config.SetBlock(ET_STATION_BLOCKING);
config.SetSelectWords(selections);
break;
case 4:
config.SetSelect(ET_STATION_SELECT_MATCH);
config.SetBlock(ET_STATION_NONBLOCKING);
config.SetSelectWords(selections);
break;
case 5:
config.SetSelect(ET_STATION_SELECT_USER);
config.SetBlock(ET_STATION_BLOCKING);
config.SetSelectWords(selections);
config.SetFunction(fName);
config.SetLib(libName);
break;
case 6:
config.SetSelect(ET_STATION_SELECT_USER);
config.SetBlock(ET_STATION_NONBLOCKING);
config.SetSelectWords(selections);
config.SetFunction(fName);
config.SetLib(libName);
break;
}
}
// Create station
void PRadETStation::Create()
{
char s_name[256];
strcpy(s_name, name.c_str());
/* create the station */
int status = et_station_create(et_system->GetID(), &station_id, s_name, config.Get());
if(status < ET_OK) {
if(status == ET_ERROR_EXISTS) {
/* station_id contains pointer to existing station */;
throw(PRadException(PRadException::ET_STATION_CREATE_ERROR, "et_client: station already exists!"));
} else if(status == ET_ERROR_TOOMANY) {
throw(PRadException(PRadException::ET_STATION_CREATE_ERROR, "et_client: too many stations created!"));
} else {
throw(PRadException(PRadException::ET_STATION_CREATE_ERROR, "et_client: error in station creation!"));
}
}
}
void PRadETStation::Attach()
{
if(et_station_attach(et_system->GetID(), station_id, &attach_id) < ET_OK) {
throw(PRadException(PRadException::ET_STATION_ATTACH_ERROR, "et_client: error in station attach!"));
}
}
void PRadETStation::Detach()
{
if(et_station_detach(et_system->GetID(), attach_id) < ET_OK) {
throw(PRadException(PRadException::ET_STATION_ATTACH_ERROR, "et_client: error in station dettach!"));
}
}
void PRadETStation::Remove()
{
if(et_station_remove(et_system->GetID(), station_id) < ET_OK) {
throw(PRadException(PRadException::ET_STATION_ATTACH_ERROR, "et_client: error in station remove!"));
}
}
// et_station_config
PRadETStation::Configuration::Configuration()
{
Initialize();
}
PRadETStation::Configuration::~Configuration()
{
et_station_config_destroy(config);
}
// wrapper functions
void PRadETStation::Configuration::Initialize()
{
et_station_config_init(&config);
}
void PRadETStation::Configuration::SetBlock(int val)
{
et_station_config_setblock(config, val);
}
void PRadETStation::Configuration::SetFlow(int val)
{
et_station_config_setflow(config, val);
}
void PRadETStation::Configuration::SetSelect(int val)
{
et_station_config_setselect(config, val);
}
void PRadETStation::Configuration::SetUser(int val)
{
et_station_config_setuser(config, val);
}
void PRadETStation::Configuration::SetRestore(int val)
{
et_station_config_setrestore(config, val);
}
void PRadETStation::Configuration::SetCUE(int val)
{
et_station_config_setcue(config, val);
}
void PRadETStation::Configuration::SetPrescale(int val)
{
et_station_config_setprescale(config, val);
}
void PRadETStation::Configuration::SetSelectWords(int val[])
{
et_station_config_setselectwords(config, val);
}
void PRadETStation::Configuration::SetFunction(const char *val)
{
et_station_config_setfunction(config, val);
}
void PRadETStation::Configuration::SetLib(const char *val)
{
et_station_config_setlib(config, val);
}
void PRadETStation::Configuration::SetClass(const char *val)
{
et_station_config_setclass(config, val);
}
#ifndef PRAD_ET_STATION_H
#define PRAD_ET_STATION_H
#include "et.h"
#include "PRadException.h"
#include <string>
class PRadETChannel;
class PRadETStation
{
public:
class Configuration
{
public:
Configuration();
virtual ~Configuration();
et_statconfig &Get() {return config;}
//wrapper functions
void Initialize();
void SetBlock(int val);
void SetFlow(int val);
void SetSelect(int val);
void SetUser(int val);
void SetRestore(int val);
void SetCUE(int val);
void SetPrescale(int val);
void SetSelectWords(int val[]);
void SetFunction(const char *val);
void SetLib(const char *val);
void SetClass(const char *val);
private:
et_statconfig config;
};
public:
PRadETStation(PRadETChannel *p, std::string n, int mode = 2);
virtual ~PRadETStation();
Configuration &GetConfig() {return config;}
et_stat_id &GetID() {return station_id;}
et_att_id &GetAttachID() {return attach_id;}
std::string GetName() {return name;}
void PreSetting(int mode);
void Create();
void Attach();
void Detach();
void Remove();
private:
PRadETChannel *et_system;
std::string name;
et_att_id attach_id;
et_stat_id station_id;
Configuration config;
};
#endif
//============================================================================//
// A exception class for PRad Event Viewer //
// //
// Chao Peng //
// 02/27/2016 //
//============================================================================//
#include "PRadException.h"
using namespace std;
PRadException::PRadException(const string &typ, const string &txt, const string &aux)
: title(typ), text(txt), auxText(aux)
{
}
PRadException::PRadException(PRadExceptionType typ, const string &txt, const string &aux)
: type(typ), text(txt), auxText(aux)
{
}
PRadException::PRadException(PRadExceptionType typ, const string &txt, const string &file, const string &func, int line)
: type(typ), text(txt)
{
ostringstream oss;
oss << " evioException occured in file " << file << ", function " << func << ", line " << line;
auxText=oss.str();
}
string PRadException::FailureDesc(void) const
{
ostringstream oss;
oss << text << endl
<< auxText;
return(oss.str());
}
string PRadException::FailureType(void) const
{
if(!title.empty())
return title;
string oss;
switch(type)
{
case ET_CONNECT_ERROR:
oss = "ET CONNECT ERROR";
break;
case ET_CONFIG_ERROR:
oss = "ET CONFIG ERROR";
break;
case ET_STATION_CONFIG_ERROR:
oss = "ET STATION CONFIG ERROR";
break;
case ET_STATION_CREATE_ERROR:
oss = "ET STATION CREATE ERROR";
break;
case ET_STATION_ATTACH_ERROR:
oss = "ET ATTACH ERROR";
break;
case ET_READ_ERROR:
oss = "ET READ ERROR";
break;
case ET_PUT_ERROR:
oss = "ET PUT ERROR";
break;
case HIGH_VOLTAGE_ERROR:
oss = "HIGH VOLTAGE SYSTEM ERROR";
break;
default:
oss = "UNKNOWN ERROR";
break;
}
return(oss);
}
const char* PRadException::what() const noexcept
{
string failure = FailureType() + ": " + FailureDesc();
return failure.c_str();
}
#ifndef PRAD_EXCEPTION_H
#define PRAD_EXCEPTION_H
#include <stdlib.h>
#include <string.h>
#include <exception>
#include <string>
#include <sstream>
class PRadException : public std::exception
{
public:
enum PRadExceptionType
{
UNKNOWN_ERROR,
ET_CONNECT_ERROR,
ET_CONFIG_ERROR,
ET_STATION_CONFIG_ERROR,
ET_STATION_CREATE_ERROR,
ET_STATION_ATTACH_ERROR,
ET_READ_ERROR,
ET_PUT_ERROR,
HIGH_VOLTAGE_ERROR,
};
PRadException(const std::string &typ, const std::string &txt = "", const std::string &aux = "");
PRadException(PRadExceptionType typ = UNKNOWN_ERROR, const std::string &txt = "", const std::string &aux = "");
PRadException(PRadExceptionType typ, const std::string &txt, const std::string &file, const std::string &func, int line);
virtual ~PRadException(void) {}
virtual std::string FailureDesc(void) const;
virtual std::string FailureType(void) const;
const char *what() const noexcept;
public:
PRadExceptionType type; // exception type
std::string title;
std::string text; // primary text
std::string auxText; // auxiliary text
};
#endif
///////////////////////////////////////////////////////////////////////////////
// Class THcOnlineRun //
// Read event from ET instead of CODA file //
// //
// Developer: //
// Chao Peng //
// 11/22/2019 //
///////////////////////////////////////////////////////////////////////////////
#include "THcOnlineRun.h"
#include "THcGlobals.h"
#include <string>
template<class Interval>
auto get_next_time(Interval itvl)
{
return std::chrono::system_clock::now() + itvl;
}
std::string et_error_to_string(int error)
{
switch(error) {
case ET_ERROR_EMPTY: return "et_client: empty et event.";
case ET_ERROR_DEAD: return "et client: et is dead!";
case ET_ERROR_TIMEOUT: return "et client: got timeout!";
case ET_ERROR_BUSY: return "et client: et is busy!";
case ET_ERROR_WAKEUP: return "et_client: et is waking up.";
default: break;
}
return "et_client: unknown et error.";
}
// Constructors
THcOnlineRun::THcOnlineRun(UInt_t size, std::chrono::milliseconds itvl, Int_t mtries, Int_t vers)
: THcRun(), version(vers), bSize(size), eSize(0), interval(itvl), max_tries(mtries),
et_id(nullptr), stat_id(ID_NULL), att_id(ID_NULL)
{
buffer = new UInt_t[size];
clock = get_next_time(itvl);
}
// Copy constructor
THcOnlineRun::THcOnlineRun(const THcOnlineRun& rhs)
: THcRun(rhs)
{
interval = rhs.interval;
max_tries = rhs.max_tries;
// do not copy the ownership of et system
et_id = nullptr;
stat_id = ID_NULL;
att_id = ID_NULL;
}
// Missing move constructor, not implementing for consistency with the analyzer
// Copy assignment operator
THcOnlineRun& THcOnlineRun::operator=(const THcOnlineRun& rhs)
{
if (this != &rhs) {
interval = rhs.interval;
max_tries = rhs.max_tries;
et_id = nullptr;
stat_id = ID_NULL;
att_id = ID_NULL;
THcRun::operator=(rhs);
}
return *this;
}
// Missing move assignment operator, not implementing for consistency with the analyzer
// Destructor.
THcOnlineRun::~THcOnlineRun()
{
// delete buffer
if (buffer != nullptr) {
delete[](buffer), buffer = nullptr;
}
// do not touch et_event as it is managed by the et system
Close();
}
// Connect a ET system and create a monitor station with pre-settings
Int_t THcOnlineRun::Connect(const char *ip_addr, int port, const char *et_file, const char *s_name)
{
// open et system
auto conf = PRadETChannel::Configuration();
// use a direct connection to the ET system
conf.SetCast(ET_DIRECT);
conf.SetHost(ip_addr);
conf.SetServerPort(port);
auto status = Open(et_file, conf);
if (status < ET_OK) {
_logger->error("THcOnlineRun::Connect : Failed to open ET system, abort connection.");
Close();
return status;
}
// create a station
auto sconf = PRadETStation::Configuration();
sconf.SetUser(ET_STATION_USER_MULTI);
sconf.SetRestore(ET_STATION_RESTORE_OUT);
sconf.SetPrescale(1);
sconf.SetCUE(ET_CHUNK_SIZE);
sconf.SetSelect(ET_STATION_SELECT_ALL);
sconf.SetBlock(ET_STATION_NONBLOCKING);
status = CreateStation(s_name, sconf);
if (status < ET_OK) {
_logger->error("THcOnlineRun::Connect : Failed to create a station, abort connection.");
Close();
return status;
}
status = Attach();
if (status < ET_OK) {
_logger->error("THcOnlineRun::Connect : Failed to attach to the station, abort connection.");
Close();
return status;
}
return ET_OK;
}
// Open ET from configuration
Int_t THcOnlineRun::Open(const char *et_file, PRadETChannel::Configuration conf)
{
if (IsOpen()) {
_logger->warn("THcOnlineRun::Open : ET system is already opened, close it before re-open");
return ID_NULL;
}
char fname[256];
strncpy(fname, et_file, 256);
return et_open(&et_id, fname, conf.Get());
}
// Close ET
Int_t THcOnlineRun::Close()
{
if ( (et_id != nullptr) && IsOpen() ) {
et_forcedclose(et_id);
et_id = nullptr;
return 1;
}
return 0;
}
// create a station from configuration
Int_t THcOnlineRun::CreateStation(const char *station_name, PRadETStation::Configuration conf)
{
if (!IsOpen()) {
_logger->warn("THcOnlineRun::CreateStation : ET System is not opened, abort creating a station.");
return ID_NULL;
} else if (stat_id != ID_NULL) {
_logger->warn("THcOnlineRun::CreateStation : A station has alreadly been created, remove it before re-create a station.");
return ID_NULL;
}
char sname[256];
strncpy(sname, station_name, 256);
return et_station_create(et_id, &stat_id, sname, conf.Get());
}
// remove the station from et system
Int_t THcOnlineRun::RemoveStation()
{
if (IsOpen() && (stat_id != ID_NULL)) {
auto status = et_station_remove(et_id, stat_id);
if (status == ET_OK) {
stat_id = ID_NULL;
return status;
}
}
return ID_NULL;
}
// Attach to a station
Int_t THcOnlineRun::Attach()
{
return Attach(stat_id);
}
// Attach to a station with station id
Int_t THcOnlineRun::Attach(et_stat_id sid)
{
if (!IsOpen()) {
_logger->warn("THcOnlineRun::Attach : ET System is not opened, abort attaching to a station.");
return ID_NULL;
}
return et_station_attach(et_id, sid, &att_id);
}
// Detach the station
Int_t THcOnlineRun::Detach()
{
if (IsOpen() && (att_id != ID_NULL)) {
auto status = et_station_detach(et_id, att_id);
if (status == ET_OK) {
att_id = ID_NULL;
return status;
}
}
return ID_NULL;
}
// copy event to the buffer
bool THcOnlineRun::copyEvent()
{
void *data;
size_t size;
et_event_getdata(ev, &data);
et_event_getlength(ev, &size);
// from byte to the buffer type
auto *dBuffer = (decltype(buffer)) data;
size_t bytes = sizeof(decltype(buffer[0]));
eSize = size/bytes + ((size % bytes) ? 1 : 0);
if (eSize > bSize) {
_logger->warn("THcOnlineRun::copyEvent et event size {} exceeds the buffer size {}.", eSize, bSize);
return false;
}
for (UInt_t i = 0; i < eSize; ++i) {
buffer[i] = dBuffer[i];
}
return true;
}
// read event from et channel
Int_t THcOnlineRun::ReadEvent()
{
const char *here = "THcOnlineRun::ReadEvent";
UInt_t ntries = 0;
if (!IsOpen() || att_id == ID_NULL) {
_logger->error("{} Did not connect to an ET system, abort Reading.", here);
return THaRunBase::READ_FATAL;
}
Int_t read = THaRunBase::READ_OK;
while(ntries++ < max_tries) {
std::this_thread::sleep_until(clock);
clock = get_next_time(interval);
auto status = et_event_get(et_id, att_id, &ev, ET_ASYNC, nullptr);
switch(status) {
case ET_OK:
// copy event to buffer
if (!copyEvent()) {
read = THaRunBase::READ_EMPTY;
}
// put back the event
if (et_event_put(et_id, att_id, ev) != ET_OK) {
_logger->error("{} failed to put back et_event to ET system, abort monitoring.", here);
read = THaRunBase::READ_EOF;
}
return read;
case ET_ERROR_EMPTY:
break;
default:
_logger->error("{} {}", here, et_error_to_string(status).c_str());
return THaRunBase::READ_FATAL;
}
}
_logger->info("THcOnlineRun::ReadEvent : Tried {} times and no event obtained from ET.", max_tries);
return THaRunBase::READ_EMPTY;
}
#ifndef ROOT_THcOnlineRun
#define ROOT_THcOnlineRun
////////////////////////////////////////////////////////////////////////////////
// THcOnline Run //
// a class inherited from THcRun <- THaRun <- THaCodaRun <- THaRunBase so it //
// The main purpose is to overwrite the communication with ThaCodaData //
// directly read events from the ET channel //
// //
// Chao Peng, 11/22/2019 //
////////////////////////////////////////////////////////////////////////////////
#include "THcRun.h"
#include "THcParmList.h"
#include "PRadETChannel.h"
#include "PRadETStation.h"
#include <chrono>
#define ID_NULL -9999
class THcOnlineRun : public THcRun
{
public:
THcOnlineRun(UInt_t size = 1048576, std::chrono::milliseconds itvl = std::chrono::milliseconds(100),
Int_t mtries = 10, Int_t vers = 2);
THcOnlineRun(const THcOnlineRun &rhs);
THcOnlineRun& operator=(const THcOnlineRun& rhs);
virtual ~THcOnlineRun();
virtual Int_t Connect(const char *ip, int port, const char *etfile, const char *sname = "Monitor");
virtual Int_t Open(const char *etfile, PRadETChannel::Configuration conf);
virtual Int_t Close();
virtual Int_t CreateStation(const char *sname, PRadETStation::Configuration conf);
virtual Int_t RemoveStation();
virtual Int_t Attach();
virtual Int_t Attach(et_stat_id sid);
virtual Int_t Detach();
virtual Bool_t IsOpen() const { return (et_id != nullptr) && et_alive(et_id); }
virtual const UInt_t *GetEvBuffer() const { return buffer; }
virtual const UInt_t &GetEvLength() const { return eSize; }
virtual Int_t ReadEvent();
virtual Int_t SkipToEndOfFile(Int_t skip_max = -1) { return 1; }
virtual Int_t GetDataVersion() { return version; }
virtual Int_t SetDataVersion(Int_t vers) { version = vers; return 1; }
private:
bool copyEvent();
std::chrono::milliseconds interval;
std::chrono::time_point<std::chrono::system_clock> clock;
et_event *ev;
Int_t version;
UInt_t *buffer;
UInt_t max_tries, bSize, eSize;
et_sys_id et_id;
et_stat_id stat_id;
et_att_id att_id;
ClassDef(THcOnlineRun, 2);
};
#endif // ROOT_THcOnlineRun
file(GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_LIST_DIR} "*.cpp")
foreach(exe_src ${APP_SOURCES})
string(REPLACE ".cpp" "" exe ${exe_src})
add_executable(${exe} ${exe_src})
target_include_directories(${exe}
PUBLIC #$<INSTALL_INTERFACE:include>
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hcana>
$<BUILD_INTERFACE:${Podd_DIR}/../../include/podd2>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for hc_compiledata.h
$<BUILD_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<BUILD_INTERFACE:${FMT_INCLUDE_DIR}>
$<BUILD_INTERFACE:${CODA_ET_INCLUDE_DIR}>
$<BUILD_INTERFACE:${EVIO_INCLUDE_DIR}>
)
target_link_libraries(${exe}
PUBLIC
${PROJECT_NAME}::HallC
Podd::Podd
Podd::Decode
coda_et::coda_et
EVIO::evioxx
)
install(TARGETS ${exe} DESTINATION ${CMAKE_INSTALL_BINDIR})
endforeach(exe_src ${APP_SOURCES})
#include "ConfigOption.h"
#include "PRadETChannel.h"
#include "et.h"
#include <csignal>
#include <thread>
#include <chrono>
#include <iostream>
#define PROGRESS_COUNT 10
using namespace std::chrono;
volatile std::sig_atomic_t gSignalStatus;
void signal_handler(int signal) {
gSignalStatus = signal;
}
int main(int argc, char* argv[]) try
{
// setup input arguments
ConfigOption conf_opt;
conf_opt.AddLongOpt(ConfigOption::help_message, "help");
conf_opt.AddOpt(ConfigOption::arg_require, 'h');
conf_opt.AddOpt(ConfigOption::arg_require, 'p');
conf_opt.AddOpt(ConfigOption::arg_require, 'f');
conf_opt.AddOpt(ConfigOption::arg_require, 'i');
conf_opt.SetDesc("usage: %0");
conf_opt.SetDesc('h', "host address of the ET system, default \"localhost\".");
conf_opt.SetDesc('p', "port to connect, default 11111.");
conf_opt.SetDesc('f', "memory mapped et file, default \"/tmp/et_feeder\".");
conf_opt.SetDesc('i', "interval in milliseconds to write data, default \"100\"");
if (!conf_opt.ParseArgs(argc, argv) || conf_opt.NbofArgs() != 0) {
std::cout << conf_opt.GetInstruction() << std::endl;
return -1;
}
std::string host = "localhost";
int port = 11111;
std::string etf = "/tmp/et_feeder";
int interval = 100;
for (auto &opt : conf_opt.GetOptions()) {
switch (opt.mark) {
case 'h':
host = opt.var.String();
break;
case 'c':
port = opt.var.Int();
break;
case 'f':
etf = opt.var.String();
break;
case 'i':
interval = opt.var.Int();
break;
default :
std::cout << conf_opt.GetInstruction() << std::endl;
return -1;
}
}
// attach to ET system
auto ch = new PRadETChannel;
ch->Open(host.c_str(), port, etf.c_str());
ch->NewStation("Data Catcher");
ch->AttachStation();
// install signal handler
std::signal(SIGINT, signal_handler);
int count = 0;
while (true) {
if (gSignalStatus == SIGINT) {
std::cout << "Received control-C, exiting..." << std::endl;
ch->ForceClose();
break;
}
system_clock::time_point start(system_clock::now());
system_clock::time_point next(start + std::chrono::milliseconds(interval));
count += ch->Read();
std::cout << "Read " << count << " events from ET." << "\r" << std::flush;
std::this_thread::sleep_until(next);
}
std::cout << "Read " << count << " events from ET." << std::endl;
return 0;
} catch (PRadException e) {
std::cerr << e.FailureType() << ": " << e.FailureDesc() << std::endl;
return -1;
} catch (...) {
std::cerr << "?unknown exception" << std::endl;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment