BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
string.cpp
Go to the documentation of this file.
1 #include <fc/fwd_impl.hpp>
3 #include <fc/io/json.hpp>
4 #include <fc/io/sstream.hpp>
5 #include <boost/lexical_cast.hpp>
6 #include <boost/algorithm/string.hpp>
7 
8 #include <string>
9 #include <sstream>
10 #include <iomanip>
11 #include <locale>
12 #include <limits>
13 
18 namespace fc {
19  class comma_numpunct : public std::numpunct<char>
20  {
21  protected:
22  virtual char do_thousands_sep() const { return ','; }
23  virtual std::string do_grouping() const { return "\03"; }
24  };
25 
26  std::string to_pretty_string( int64_t value )
27  {
28  std::stringstream ss;
29  ss.imbue( {std::locale(), new comma_numpunct} );
30  ss << std::fixed << value;
31  return ss.str();
32  }
33 
34  int64_t to_int64( const std::string& i )
35  {
36  try
37  {
38  return boost::lexical_cast<int64_t>(i.c_str());
39  }
40  catch( const boost::bad_lexical_cast& e )
41  {
42  FC_THROW_EXCEPTION( parse_error_exception, "Couldn't parse int64_t" );
43  }
44  FC_RETHROW_EXCEPTIONS( warn, "${i} => int64_t", ("i",i) )
45  }
46 
47  uint64_t to_uint64( const std::string& i )
48  { try {
49  try
50  {
51  return boost::lexical_cast<uint64_t>(i.c_str());
52  }
53  catch( const boost::bad_lexical_cast& e )
54  {
55  FC_THROW_EXCEPTION( parse_error_exception, "Couldn't parse uint64_t" );
56  }
57  FC_RETHROW_EXCEPTIONS( warn, "${i} => uint64_t", ("i",i) )
58  } FC_CAPTURE_AND_RETHROW( (i) ) }
59 
60  double to_double( const std::string& i)
61  {
62  try
63  {
64  return boost::lexical_cast<double>(i.c_str());
65  }
66  catch( const boost::bad_lexical_cast& e )
67  {
68  FC_THROW_EXCEPTION( parse_error_exception, "Couldn't parse double" );
69  }
70  FC_RETHROW_EXCEPTIONS( warn, "${i} => double", ("i",i) )
71  }
72 
73  std::string to_string(double d)
74  {
75  // +2 is required to ensure that the double is rounded correctly when read back in. http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
76  std::stringstream ss;
77  ss << std::setprecision(std::numeric_limits<double>::digits10 + 2) << std::fixed << d;
78  return ss.str();
79  }
80 
81  std::string to_string( uint64_t d)
82  {
83  return boost::lexical_cast<std::string>(d);
84  }
85 
86  std::string to_string( int64_t d)
87  {
88  return boost::lexical_cast<std::string>(d);
89  }
90  std::string to_string( uint16_t d)
91  {
92  return boost::lexical_cast<std::string>(d);
93  }
94  std::string trim( const std::string& s )
95  {
96  return boost::algorithm::trim_copy(s);
97  }
98  std::string to_lower( const std::string& s )
99  {
100  auto tmp = s;
102  return tmp;
103  }
104  string trim_and_normalize_spaces( const string& s )
105  {
106  string result = boost::algorithm::trim_copy( s );
107  while( result.find( " " ) != result.npos )
108  boost::algorithm::replace_all( result, " ", " " );
109  return result;
110  }
111 
121  uint64_t parse_size( const string& s )
122  {
123  try
124  {
125  size_t i = 0, n = s.size(), suffix_start = n;
126  for( i=0; i<n; i++ )
127  {
128  if( !((s[i] >= '0') && (s[i] <= '9')) )
129  {
130  suffix_start = i;
131  break;
132  }
133  }
134  uint64_t u = to_uint64( s.substr( 0, suffix_start ) );
135 
136  FC_ASSERT( n - suffix_start <= 3 );
137 
138  uint64_t m = 1;
139  uint64_t thousand = 1024;
140 
141  if( suffix_start == n )
142  {
143  return u;
144  }
145  else if( suffix_start == n-1 )
146  {
147  }
148  else if( suffix_start == n-2 )
149  {
150  FC_ASSERT( (s[suffix_start+1] == 'b') || (s[suffix_start+1] == 'B') );
151  thousand = 1000;
152  }
153  else if( suffix_start == n-3 )
154  {
155  FC_ASSERT( (s[suffix_start+1] == 'i') || (s[suffix_start+1] == 'I') );
156  FC_ASSERT( (s[suffix_start+2] == 'b') || (s[suffix_start+2] == 'B') );
157  }
158  switch( s[suffix_start] )
159  {
160  case 'y':
161  case 'Y':
162  m *= thousand;
163  case 'z':
164  case 'Z':
165  m *= thousand;
166  case 'e':
167  case 'E':
168  m *= thousand;
169  case 'p':
170  case 'P':
171  m *= thousand;
172  case 't':
173  case 'T':
174  m *= thousand;
175  case 'g':
176  case 'G':
177  m *= thousand;
178  case 'm':
179  case 'M':
180  m *= thousand;
181  case 'k':
182  case 'K':
183  m *= thousand;
184  break;
185  default:
186  FC_ASSERT( false );
187  }
188  return u*m;
189  }
190  catch( const fc::exception& e )
191  {
192  FC_THROW_EXCEPTION( parse_error_exception, "Couldn't parse size" );
193  }
194  }
195 
196  string format_string( const string& format, const variant_object& args, uint32_t max_object_depth )
197  {
198  stringstream ss;
199  size_t prev = 0;
200  auto next = format.find( '$' );
201  while( prev < format.size() )
202  {
203  ss << format.substr( prev, next == string::npos ? string::npos : next - prev );
204 
205  // if we got to the end, return it.
206  if( next == size_t(string::npos) || next == format.size() )
207  return ss.str();
208 
209  // if we are not at the end, then update the start
210  prev = next + 1;
211 
212  if( format[prev] == '{' )
213  {
214  // if the next char is a open, then find close
215  next = format.find( '}', prev );
216  // if we found close...
217  if( next != string::npos )
218  {
219  // the key is between prev and next
220  string key = format.substr( prev+1, (next-prev-1) );
221 
222  auto val = args.find( key );
223  if( val != args.end() )
224  {
225  if( val->value().is_object() || val->value().is_array() )
226  {
227  try
228  {
229  ss << json::to_string( val->value(), json::stringify_large_ints_and_doubles, max_object_depth );
230  }
231  catch( const fc::assert_exception& e )
232  {
233  ss << "[\"ERROR_WHILE_CONVERTING_VALUE_TO_STRING\"]";
234  }
235  }
236  else
237  ss << val->value().as_string();
238  }
239  else
240  ss << "${"<<key<<"}";
241  prev = next + 1;
242  }
243  }
244  else
245  ss << format[next];
246  next = format.find( '$', prev );
247  }
248  return ss.str();
249  }
250 
251 } // namespace fc
static string to_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:638
std::string format_string(const std::string &, const variant_object &, uint32_t max_object_depth=200)
iterator find(const string &key) const
std::string to_lower(const std::string &)
Definition: string.cpp:98
string trim_and_normalize_spaces(const string &s)
Definition: string.cpp:104
An order-perserving dictionary of variant&#39;s.
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
int64_t to_int64(const std::string &)
Definition: string.cpp:34
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception&#39;s, std::exceptions, and ... and rethrows them after appending the provided log m...
Definition: exception.hpp:463
virtual std::string do_grouping() const
Definition: string.cpp:23
virtual char do_thousands_sep() const
Definition: string.cpp:22
std::string to_pretty_string(int64_t)
Definition: string.cpp:26
std::string str()
Definition: sstream.cpp:33
double to_double(const std::string &)
Definition: string.cpp:60
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
uint64_t parse_size(const string &s)
Definition: string.cpp:121
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
Definition: exception.hpp:378
uint64_t to_uint64(const std::string &)
Definition: string.cpp:47
Defines exception&#39;s used by fc.
iterator end() const
std::string to_string(double)
Definition: string.cpp:73
Definition: api.hpp:15
std::string trim(const std::string &)
Definition: string.cpp:94