//
// Copyright 2011,2016 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
#include
#include
#include
#include
#include
#include
#include
using namespace uhd;
static const char* arg_delim = ",";
static const char* pair_delim = "=";
static std::string trim(const std::string &in){
return boost::algorithm::trim_copy(in);
}
#define tokenizer(inp, sep) \
boost::tokenizer > \
(inp, boost::char_separator(sep))
device_addr_t::device_addr_t(const std::string &args){
for(const std::string &pair: tokenizer(args, arg_delim)){
if (trim(pair) == "") continue;
std::vector toks;
for(const std::string &tok: tokenizer(pair, pair_delim)){
toks.push_back(tok);
}
if (toks.size() == 1) toks.push_back(""); //pad empty value
if (toks.size() == 2 and not trim(toks[0]).empty()){ //only valid combination
this->set(trim(toks[0]), trim(toks[1]));
}
else throw uhd::value_error("invalid args string: "+args); //otherwise error
}
}
std::string device_addr_t::to_pp_string(void) const{
if (this->size() == 0) return "Empty Device Address";
std::stringstream ss;
ss << "Device Address:" << std::endl;
for(std::string key: this->keys()){
ss << boost::format(" %s: %s") % key % this->get(key) << std::endl;
}
return ss.str();
}
std::string device_addr_t::to_string(void) const{
std::string args_str;
size_t count = 0;
for(const std::string &key: this->keys()){
args_str += ((count++)? arg_delim : "") + key + pair_delim + this->get(key);
}
return args_str;
}
#include
device_addrs_t uhd::separate_device_addr(const device_addr_t &dev_addr){
//------------ support old deprecated way and print warning --------
if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){
std::vector addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" "));
if (addrs.size() > 1){
device_addr_t fixed_dev_addr = dev_addr;
fixed_dev_addr.pop("addr");
for (size_t i = 0; i < addrs.size(); i++){
fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i];
}
UHD_LOGGER_WARNING("UHD") <<
"addr = is deprecated.\n"
"To address a multi-device, use multiple = .\n"
"See the USRP-NXXX application notes. Two device example:\n"
" addr0 = 192.168.10.2\n"
" addr1 = 192.168.10.3\n"
;
return separate_device_addr(fixed_dev_addr);
}
}
//------------------------------------------------------------------
device_addrs_t dev_addrs(1); //must be at least one (obviously)
std::vector global_keys; //keys that apply to all (no numerical suffix)
for(const std::string &key: dev_addr.keys()){
boost::cmatch matches;
if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){
throw std::runtime_error("unknown key format: " + key);
}
std::string key_part(matches[1].first, matches[1].second);
std::string num_part(matches[2].first, matches[2].second);
if (num_part.empty()){ //no number? save it for later
global_keys.push_back(key);
continue;
}
const size_t num = boost::lexical_cast(num_part);
dev_addrs.resize(std::max(num+1, dev_addrs.size()));
dev_addrs[num][key_part] = dev_addr[key];
}
//copy the global settings across all device addresses
for(device_addr_t &my_dev_addr: dev_addrs){
for(const std::string &global_key: global_keys){
my_dev_addr[global_key] = dev_addr[global_key];
}
}
return dev_addrs;
}
device_addr_t uhd::combine_device_addrs(const device_addrs_t &dev_addrs){
device_addr_t dev_addr;
for (size_t i = 0; i < dev_addrs.size(); i++){
for(const std::string &key: dev_addrs[i].keys()){
dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key];
}
}
return dev_addr;
}