diff --git a/src/config_reader.cpp b/src/config_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5baadcebe6c9cfaaed8c3cdc4ed1de0bda644790 --- /dev/null +++ b/src/config_reader.cpp @@ -0,0 +1,217 @@ +// config.cpp +// +// original from https://cppsecrets.com/users/41129711010797106994610011511264103109971051084699111109/C00-Config-Reader.php +// +// Code Specific Header File(s) +#include "config_reader.h" + +// C++ Header File(s) +#include <fstream> +#include <algorithm> + +using namespace std; + +#define NULL_PTR 0 + +ConfigReader* ConfigReader::m_pInstance = NULL_PTR; + +ConfigReader::ConfigReader() +{ + m_ConfigSettingMap.clear(); +} + +ConfigReader::~ConfigReader() +{ + m_ConfigSettingMap.clear(); +} + +ConfigReader* ConfigReader::getInstance() +{ + // No need to use double re-check lock mechanism here + // because this getInstance() will call at the time of + // initialization only and mostly, at the time of + // initialization, there will be only one thread. + + if(NULL_PTR == m_pInstance) + { + m_pInstance = new ConfigReader; + } + return m_pInstance; +} + +bool ConfigReader::getValue(std::string group, std::string tag, int& value) +{ + string _tag = group + "/" + tag; + map<string, string>::iterator it ; + it = m_ConfigSettingMap.find(_tag); + if(it != m_ConfigSettingMap.end()) + { + value = atoi((it->second).c_str()); + return true; + } + return false; +} + +bool ConfigReader::getValue(std::string group, std::string tag, std::string& value) +{ + string _tag = group + "/" + tag; + map<string, string>::iterator it ; + it = m_ConfigSettingMap.find(_tag); + if(it != m_ConfigSettingMap.end()) + { + value = it->second; + return true; + } + return false; +} + +bool ConfigReader::parseFile(string fileName) +{ + ifstream inputFile; + inputFile.open(fileName.c_str()); + string delimeter = "="; + string group_label = ""; + int initPos = 0; + + if (inputFile.fail()) + { + cout << "Unable to find defaultConfig file" << endl; + return false; + } + + string line; + while(getline(inputFile, line)) + { + // Remove comment Lines + size_t found = line.find_first_of('#'); + string configData = line.substr(0, found); + + // Remove ^M from configData + configData.erase(std::remove(configData.begin(), configData.end(), '\r'), configData.end()); + + if(configData.empty()) + continue; + + size_t gr_start = configData.find("["); + size_t gr_stop = configData.find("]"); + if ((gr_start != string::npos) && (gr_stop != string::npos)) { + group_label = configData.substr(gr_start+1, gr_stop-1); + // cout << "group_label=" << group_label << endl; + continue; + } + size_t length = configData.find(delimeter); + + string tag, value; + + if (length != string::npos) { + tag = configData.substr(initPos, length); + value = configData.substr(length+1); + } + + // Trim white spaces + tag = reduce(tag); + value = reduce(value); + // cout << tag << "=" << value << endl; + + if(tag.empty() || value.empty()) + continue; + + // add group_name to tag + tag = group_label + "/" + tag; + + // Check if any of the tags is repeated more than one times + // it needs to pick the latest one instead of the old one. + + // Search, if the tag is already present or not + // If it is already present, then delete an existing one + + std::map<std::string, std::string>::iterator itr = m_ConfigSettingMap.find(tag); + if(itr != m_ConfigSettingMap.end()) + { + m_ConfigSettingMap.erase(tag); + } + + m_ConfigSettingMap.insert(std::pair<string, string>(tag, value)); + } + return true; +} + +std::string ConfigReader::trim(const std::string& str, const std::string& whitespace) +{ + size_t strBegin = str.find_first_not_of(whitespace); + if (strBegin == std::string::npos) + return ""; + + size_t strEnd = str.find_last_not_of(whitespace); + size_t strRange = strEnd - strBegin + 1; + + return str.substr(strBegin, strRange); +} + +std::string ConfigReader::reduce(const std::string& str, + const std::string& fill, + const std::string& whitespace) +{ + // trim first + string result = trim(str, whitespace); + + // replace sub ranges + size_t beginSpace = result.find_first_of(whitespace); + while (beginSpace != std::string::npos) + { + size_t endSpace = result.find_first_not_of(whitespace, beginSpace); + size_t range = endSpace - beginSpace; + + result.replace(beginSpace, range, fill); + + size_t newStart = beginSpace + fill.length(); + beginSpace = result.find_first_of(whitespace, newStart); + } + + return result; +} + +void ConfigReader::dumpFileValues() +{ + map<string, string>::iterator it; + for(it=m_ConfigSettingMap.begin(); it!=m_ConfigSettingMap.end(); ++it) + { + cout << it->first << " = " << it->second << endl; + } +} + +// int main() +// { +// // Create object of the class ConfigReader +// ConfigReader* p = ConfigReader::getInstance(); + +// // parse the configuration file +// p->parseFile(); + +// // Dump map on the console after parsing it +// p->dumpFileValues(); + +// // Print divider on the console to understand the output properly +// cout << endl << "=================================================" << endl << endl; + +// // Define variables to store the value +// string name(""); +// string skill(""); +// string website(""); +// int age = 0; + +// // Update the variable by the value present in the configuration file. +// p->getValue("Name", name); +// p->getValue("Skill", skill); +// p->getValue("Website", website); +// p->getValue("Age", age); + +// // Variables has been updated. Now print it on the console. +// cout << "Name = " << name << endl; +// cout << "Skill = " << skill << endl; +// cout << "Website = " << website << endl; +// cout << "Age = " << age << endl; + +// // Return sucees to the caller +// return 0; +// } \ No newline at end of file diff --git a/src/config_reader.h b/src/config_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..df7413d7db3af281fa4fdf258660cf16718591a3 --- /dev/null +++ b/src/config_reader.h @@ -0,0 +1,97 @@ +// config.h +#ifndef _CONFIG_READER_H_ +#define _CONFIG_READER_H_ + +// C++ Header File(s) +#include <iostream> +#include <map> + +// Define namespace for this class. so that anyonelo +// can easily integrate it. The class name is vary generic +// so the chance to collapse the class name is high. +// So need to define the class inside the namespace. + +// Defining ConfigReader as singleton class +// Easy to access across the multiple classes +// +// The responsibility of this class is to parse the +// Config file and store it in the std::map +// Defined getter function getValue() to get the +// data from the std::map. +// +// To use this class, pass the config file path to +// the function getInstance() +// +// This is one of the advance config reader, because this +// class is handling the comment line as well. Comment line +// will start from hash(#). So all the string after +// semicolon will be discarded. +// +// NOTE: NO NEED TO MAKE THIS CLASS THREAD-SAFE. IT IS EXTRA OVEHEAD. +// BECAUSE MOSTLY WE ARE DOING ONLY READ OPERATION. WRITE OPERATION IS +// HAPPENING ONLY ONE TIME, WHICH IS IN THE FUNCTION parse(). SO CALL +// parse() FUNCTION AT THE TIME OF INITIALIZATION ONLY. +// +// IF YOUR CONFIGURATION FILE IS UPDATING AT THE RUN TIME AND YOU NEED +// UPDATED DATA FROM THE CONFIGURATION FILE AT RUN TIME, THEN YOU NEED +// TO MAKE THIS CLASS THREAD-SAFE. + +class ConfigReader +{ + private: + + // Define the map to store data from the config file + std::map<std::string, std::string> m_ConfigSettingMap; + + // Static pointer instance to make this class singleton. + static ConfigReader* m_pInstance; + + public: + + // Public static method getInstance(). This function is + // responsible for object creation. + static ConfigReader* getInstance(); + + // Parse the config file. + bool parseFile(std::string fileName = "/tmp/default_config"); + // bool parseFile(std::string fileName = "/tmp/sdptr.conf"); + + // Overloaded getValue() function. + // Value of the tag in cofiguration file could be + // string or integer. So the caller need to take care this. + // Caller need to call appropiate function based on the + // data type of the value of the tag. + + bool getValue(std::string group, std::string tag, int& value); + bool getValue(std::string group, std::string tag, std::string& value); + + // Function dumpFileValues is for only debug purpose + void dumpFileValues(); + + private: + + // Define constructor in the private section to make this + // class as singleton. + ConfigReader(); + + // Define destructor in private section, so no one can delete + // the instance of this class. + ~ConfigReader(); + + // Define copy constructor in the private section, so that no one can + // voilate the singleton policy of this class + ConfigReader(const ConfigReader& obj){} + + // Define assignment operator in the private section, so that no one can + // voilate the singleton policy of this class + void operator=(const ConfigReader& obj){} + + // Helper function to trim the tag and value. These helper function is + // calling to trim the un-necessary spaces. + std::string trim(const std::string& str, const std::string& whitespace = " \t"); + std::string reduce(const std::string& str, + const std::string& fill = " ", + const std::string& whitespace = " \t"); +}; + +#endif // End of _CONFIG_READER_H_ \ No newline at end of file diff --git a/src/sdptr.conf b/src/sdptr.conf new file mode 100644 index 0000000000000000000000000000000000000000..21a9b60b34f2d45c557d6dce5ee676dd23682bd9 --- /dev/null +++ b/src/sdptr.conf @@ -0,0 +1,59 @@ +# sdptr_lts.conf +# configuration file for the SDP Translator. +# +# this config file holds settings for all [type]. +# +# # settings per type +# [LB_Core] # [band_stationtype] +# n_fpgas = 4 # normal 8 or 16, lts=4, dts=? +# first_pfga_nr = 0 # normal 0, lts=8, dts=? +# ip_prefix = "10.99." # first part of ip (last part is hardware dependent) +# n_beamsets = 1 # 1 for 'LB', 'HB Remote' and 'HB International' and 2 for 'HB Core' + + +[] +fw_name = "lofar2_unb2b_sdp_station_xsub_one" # expected firmware name +fw_version = 2 # expected firmware version + + +[LB_Core] +n_fpgas = 16 +first_fpga_nr = 0 +ip_prefix = "10.99." +n_beamsets = 1 + +[LB_Remote] +n_fpgas = 16 +first_fpga_nr = 0 +ip_prefix = "10.99." +n_beamsets = 1 + +[LB_International] +n_fpgas = 16 +first_fpga_nr = 0 +ip_prefix = "10.99." +n_beamsets = 1 + +[HB_Core] +n_fpgas = 8 +first_fpga_nr = 0 +ip_prefix = "10.99." +n_beamsets = 2 + +[HB_Remote] +n_fpgas = 8 +first_fpga_nr = 0 +ip_prefix = "10.99." +n_beamsets = 1 + +[HB_International] +n_fpgas = 16 +first_fpga_nr = 0 +ip_prefix = "10.99." +n_beamsets = 1 + +[LTS] +n_fpgas = 4 +first_fpga_nr = 8 +ip_prefix = "10.99." +n_beamsets = 1