/* * Copyright 2013-2019 Software Radio Systems Limited * * This file is part of srsLTE. * * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #ifndef SRSENB_PARSER_H #define SRSENB_PARSER_H #include "srslte/asn1/asn1_utils.h" #include #include #include #include #include #include #include #include #include #include #include namespace srsenb { using namespace libconfig; class parser { public: class field_itf { public: virtual ~field_itf() = default; virtual int parse(Setting& root) = 0; virtual const char* get_name() = 0; }; template class field_enum_str : public field_itf { public: field_enum_str(const char* name_, T *store_ptr_, const char (*value_str_)[20], uint32_t nof_items_, bool *enabled_value_ = NULL) { name = name_; store_ptr = store_ptr_; value_str = value_str_; nof_items = nof_items_; enabled_value = enabled_value_; } const char* get_name() { return name; } int parse(Setting &root) { std::string val; if (root.exists(name)) { if (enabled_value) { *enabled_value = true; } if (root.lookupValue(name, val)) { bool found = false; // find value for (uint32_t i=0;i class field_enum_num : public field_itf { public: field_enum_num(const char* name_, T *store_ptr_, const S *value_str_, uint32_t nof_items_, bool *enabled_value_ = NULL) { name = name_; store_ptr = store_ptr_; value_str = value_str_; nof_items = nof_items_; enabled_value = enabled_value_; } const char* get_name() { return name; } int parse(Setting &root) { S val; if (root.exists(name)) { if (enabled_value) { *enabled_value = true; } if (parser::lookupValue(root, name, &val)) { bool found = false; // find value for (uint32_t i=0;i class field : public field_itf { public: field(const char* name_, T *store_ptr_, bool *enabled_value_ = NULL) { name = name_; store_ptr = store_ptr_; enabled_value = enabled_value_; } const char* get_name() { return name; } int parse(Setting &root) { if (root.exists(name)) { if (enabled_value) { *enabled_value = true; } if (!parser::lookupValue(root, name, store_ptr)) { return -1; } else { return 0; } } else { if (enabled_value) { *enabled_value = false; return 0; } else { return -1; } } } private: const char* name; T *store_ptr; bool *enabled_value; }; class section { public: section(std::string name); ~section(); void set_optional(bool *enabled_value); void add_subsection(section *s); void add_field(field_itf *f); int parse(Setting &root); private: std::string name; bool *enabled_value; std::list sub_sections; std::list fields; }; parser(std::string filename); int parse(); void add_section(section *s); static int parse_section(std::string filename, section *s); static bool lookupValue(Setting &root, const char *name, std::string *val) { return root.lookupValue(name, *val); } static bool lookupValue(Setting &root, const char *name, uint8_t *val) { uint32_t t; bool r = root.lookupValue(name, t); *val = (uint8_t) t; return r; } static bool lookupValue(Setting &root, const char *name, uint16_t *val) { uint32_t t; bool r = root.lookupValue(name, t); *val = (uint16_t) t; return r; } static bool lookupValue(Setting &root, const char *name, uint32_t *val) { uint32_t t; bool r = root.lookupValue(name, t); *val = t; return r; } static bool lookupValue(Setting &root, const char *name, int8_t *val) { int32_t t; bool r = root.lookupValue(name, t); *val = (int8_t) t; return r; } static bool lookupValue(Setting &root, const char *name, int16_t *val) { int32_t t; bool r = root.lookupValue(name, t); *val = (int16_t) t; return r; } static bool lookupValue(Setting &root, const char *name, int32_t *val) { int32_t t; bool r = root.lookupValue(name, t); *val = t; return r; } static bool lookupValue(Setting &root, const char *name, double *val) { double t; bool r = root.lookupValue(name, t); *val = t; return r; } static bool lookupValue(Setting& root, const char* name, float* val) { double t; bool r = root.lookupValue(name, t); *val = t; return r; } static bool lookupValue(Setting &root, const char *name, bool *val) { bool t; bool r = root.lookupValue(name, t); *val = t; return r; } private: std::list sections; std::string filename; }; template int parse_opt_field(T& obj, bool& flag, const char* field_name, Setting& root) { flag = root.lookupValue(field_name, obj); return 0; } template int parse_opt_field(T& obj, bool& flag, const char* field_name, Setting& root, Parser field_parser) { flag = false; if (root.exists(field_name)) { flag = true; return field_parser(obj, root[field_name]); } return 0; } namespace asn1_parsers { template bool nowhitespace_string_to_enum(EnumType& e, const std::string& s) { std::string s_nows = s; std::transform(s_nows.begin(), s_nows.end(), s_nows.begin(), ::tolower); s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), ' '), s_nows.end()); s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), '-'), s_nows.end()); for (uint32_t i = 0; i < EnumType::nof_types; ++i) { e = (typename EnumType::options)i; std::string s_nows2 = e.to_string(); std::transform(s_nows2.begin(), s_nows2.end(), s_nows2.begin(), ::tolower); s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), ' '), s_nows2.end()); s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), '-'), s_nows2.end()); if (s_nows2 == s_nows) { return true; } } return false; } template int str_to_enum(EnumType& enum_val, Setting& root) { std::string val = root; bool found = nowhitespace_string_to_enum(enum_val, val); if (not found) { fprintf(stderr, "PARSER ERROR: Invalid option: \"%s\" for asn1 enum type\n", val.c_str()); fprintf(stderr, "Valid options: \"%s\"", EnumType((typename EnumType::options)0).to_string().c_str()); for (uint32_t i = 1; i < EnumType::nof_types; i++) { fprintf(stderr, ", \"%s\"", EnumType((typename EnumType::options)i).to_string().c_str()); } fprintf(stderr, "\n"); } return found ? 0 : -1; } template int opt_str_to_enum(EnumType& enum_val, bool& presence_flag, Setting& root, const char* name) { return parse_opt_field(enum_val, presence_flag, name, root, str_to_enum); } template int number_to_enum(EnumType& enum_val, Setting& root) { if (root.isNumber()) { typename EnumType::number_type val; if (root.getType() == Setting::TypeInt64) { val = (long int)root; } else if (root.getType() == Setting::TypeInt) { val = (int)root; } bool found = asn1::number_to_enum(enum_val, val); if (not found) { std::ostringstream ss; ss << val; fprintf(stderr, "Invalid option: %s for enum field \"%s\"\n", ss.str().c_str(), root.getName()); ss.str(""); ss << EnumType((typename EnumType::options)0).to_number(); fprintf(stderr, "Valid options: %s", ss.str().c_str()); for (uint32_t i = 1; i < EnumType::nof_types; i++) { ss.str(""); ss << EnumType((typename EnumType::options)i).to_number(); fprintf(stderr, ", %s", ss.str().c_str()); } fprintf(stderr, "\n"); } return found ? 0 : -1; } else { std::string str_val = root; fprintf(stderr, "Expected a number for enum field %s but received a string %s\n", root.getName(), str_val.c_str()); } return -1; } template int opt_number_to_enum(EnumType& enum_val, bool& presence_flag, Setting& root, const char* name) { return parse_opt_field(enum_val, presence_flag, name, root, number_to_enum); } } // namespace asn1_parsers } // namespace srsenb #endif // PARSER_H