stator
A math, geometry, and utility library
repr.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 Marcus N Campbell Bannerman <[email protected]>
3 
4  This file is part of stator.
5 
6  stator is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  stator is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with stator. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 
23 #include <limits>
24 #include <memory>
25 #include <cstdio>
26 
27 namespace stator {
33  inline std::string strip(const std::string& str,
34  const std::string& whitespace = " \t")
35  {
36  const auto strBegin = str.find_first_not_of(whitespace);
37  if (strBegin == std::string::npos)
38  return ""; // no content
39  const auto strEnd = str.find_last_not_of(whitespace);
40  const auto strRange = strEnd - strBegin + 1;
41  return str.substr(strBegin, strRange);
42  }
43 
44 
50  template<typename ... Args>
51  std::string string_format( const std::string& format, Args ... args )
52  {
53  size_t size = std::snprintf(nullptr, 0, format.c_str(), args ... ) + 1; // +1 Extra space for '\0'
54  std::unique_ptr<char[]> buf(new char[ size ]);
55  std::snprintf(buf.get(), size, format.c_str(), args ...);
56  return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
57  }
58 
65  inline std::pair<std::string, size_t> search_replace(std::string in, const std::string& from, const std::string& to)
66  {
67  size_t replacements = 0;
68  if (!in.empty())
69  {
70  std::string::size_type toLen = to.length();
71  std::string::size_type frLen = from.length();
72  std::string::size_type loc = 0;
73 
74  while (std::string::npos != (loc = in.find(from, loc)))
75  {
76  in.replace(loc, frLen, to);
77  loc += toLen;
78  ++replacements;
79 
80  if (loc >= in.length())
81  break;
82  }
83  }
84 
85  return std::make_pair(in, replacements);
86  }
87 
88  namespace detail {
89  struct Latex_output_ID;
90  struct Debug_output_ID;
91  struct Rounding_digits_ID {};
92  };
93 
94  struct Latex_output : stator::orphan::basic_conf_t<detail::Latex_output_ID> {};
95  struct Debug_output : stator::orphan::basic_conf_t<detail::Debug_output_ID> {};
96 
97  template<int digits>
98  struct Rounding_digits : stator::orphan::value_conf_t<detail::Rounding_digits_ID, int, digits> {};
99 
100  template <typename ...Args>
101  struct ReprConfig {
102  static constexpr const auto Latex_output = stator::orphan::is_present<stator::Latex_output, Args...>::value;
103  static constexpr const auto Rounding_digits = stator::orphan::get_value<stator::Rounding_digits<0>, Args...>::value;
104  static constexpr const auto Debug_output = stator::orphan::is_present<stator::Debug_output, Args...>::value;
105  };
106 
108 
109  template<class Config = DefaultReprConfig, typename T>
110  typename std::enable_if<std::is_integral<T>::value, std::string>::type
111  repr(T a) { return std::to_string(a); }
112 
113  template<class Config, class Float>
114  inline
115  typename std::enable_if<std::is_floating_point<Float>::value, std::string>::type
116  repr(Float a) {
117  std::string basic_output = stator::string_format("%.*g", std::numeric_limits<Float>::max_digits10 - Config::Rounding_digits, a);
118  if (Config::Latex_output) {
119  //Strip the unneeded exponent leading plus sign if present
120  auto fin = search_replace(basic_output, "e+", "\\times10^{");
121  //If the number is in exponential notation, the replacement
122  //should have succeeded, so close the brackets around the
123  //exponent
124  if (fin.second) return fin.first + "}";
125 
126  //Repeat, but for the case where the exponent is negative
127  fin = search_replace(basic_output, "e", "\\times10^{");
128  if (fin.second) return fin.first + "}";
129 
130  }
131  return basic_output;
132  }
133 }
std::pair< std::string, size_t > search_replace(std::string in, const std::string &from, const std::string &to)
Search and replace elements in a std::string.
Definition: repr.hpp:65
std::enable_if< std::is_integral< T >::value, std::string >::type repr(T a)
Definition: repr.hpp:111
std::string string_format(const std::string &format, Args ... args)
A C++ version of snprintf allowing simple formatting of output. format A printf-style formatting str...
Definition: repr.hpp:51
std::string strip(const std::string &str, const std::string &whitespace=" \)
A C++ version of python&#39;s string trim function str The string to be trimmed. whitespace A string of...
Definition: repr.hpp:33
The stator library namespace.
Definition: frontpage.dox:243