Monero C++ Library
gen_utils.h
1 
52 #pragma once
53 
54 #ifndef gen_utils_h
55 #define gen_utils_h
56 
57 #include <boost/lexical_cast.hpp>
58 #include "include_base_utils.h"
59 #include "common/util.h"
60 
64 namespace gen_utils
65 {
66  // ------------------------- VALUE RECONCILATION ----------------------------
67 
68  // TODO: refactor common template code
69  template <class T, typename std::enable_if<std::is_same<T, std::string>::value, T>::type* = nullptr>
70  boost::optional<T> reconcile(const boost::optional<T>& val1, const boost::optional<T>& val2, boost::optional<bool> resolve_defined, boost::optional<bool> resolve_true, boost::optional<bool> resolve_max, const std::string& err_msg = "") {
71 
72  // check for equality
73  if (val1 == val2) return val1;
74 
75  // resolve one value none
76  if (val1 == boost::none || val2 == boost::none) {
77  if (resolve_defined != boost::none && *resolve_defined == false) return boost::none;
78  else return val1 == boost::none ? val2 : val1;
79  }
80 
81  throw std::runtime_error(std::string("Cannot reconcile strings: ") + boost::lexical_cast<std::string>(val1) + std::string(" vs ") + boost::lexical_cast<std::string>(val2) + (!err_msg.empty() ? std::string(". ") + err_msg : std::string("")));
82  }
83  template <class T, typename std::enable_if<std::is_same<T, std::string>::value, T>::type* = nullptr>
84  boost::optional<T> reconcile(const boost::optional<T>& val1, const boost::optional<T>& val2, const std::string& err_msg = "") {
85  return reconcile(val1, val2, boost::none, boost::none, boost::none, err_msg);
86  }
87 
88  template <class T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
89  boost::optional<T> reconcile(const boost::optional<T>& val1, const boost::optional<T>& val2, boost::optional<bool> resolve_defined, boost::optional<bool> resolve_true, boost::optional<bool> resolve_max, const std::string& err_msg = "") {
90 
91  // check for equality
92  if (val1 == val2) return val1;
93 
94  // resolve one value none
95  if (val1 == boost::none || val2 == boost::none) {
96  if (resolve_defined != boost::none && *resolve_defined == false) return boost::none;
97  else return val1 == boost::none ? val2 : val1;
98  }
99 
100  // resolve different booleans
101  if (resolve_true != boost::none) return (bool) val1 == *resolve_true ? val1 : val2; // if resolve true, return true, else return false
102 
103  // resolve different numbers
104  if (resolve_max != boost::none) return *resolve_max ? std::max(*val1, *val2) : std::min(*val1, *val2);
105 
106  // cannot reconcile
107  throw std::runtime_error(std::string("Cannot reconcile integrals: ") + boost::lexical_cast<std::string>(val1) + std::string(" vs ") + boost::lexical_cast<std::string>(val2) + (!err_msg.empty() ? std::string(". ") + err_msg : std::string("")));
108  }
109  template <class T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
110  boost::optional<T> reconcile(const boost::optional<T>& val1, const boost::optional<T>& val2, const std::string& err_msg = "") {
111  return reconcile(val1, val2, boost::none, boost::none, boost::none, err_msg);
112  }
113 
114  template <class T>
115  std::vector<T> reconcile(const std::vector<T>& v1, const std::vector<T>& v2, const std::string& err_msg = "") {
116 
117  // check for equality
118  if (v1 == v2) return v1;
119 
120  // resolve one vector empty
121  if (v1.empty()) return v2;
122  if (v2.empty()) return v1;
123 
124  // otherwise cannot reconcile
125  throw std::runtime_error("Cannot reconcile vectors" + (!err_msg.empty() ? std::string(". ") + err_msg : std::string("")));
126  }
127 }
128 #endif /* gen_utils_h */
gen_utils
Definition: gen_utils.h:65