Hermes
str.h
Go to the documentation of this file.
1 
32 #ifndef HERMES_COMMON_STR_H
33 #define HERMES_COMMON_STR_H
34 
35 #include <string>
36 #include <sstream>
37 #include <vector>
38 #include <regex>
39 #include <functional>
40 #include <iomanip>
41 #include <iostream>
42 #include <cstring>
43 #include <cstdint>
44 #include <hermes/common/defs.h>
45 #include <hermes/common/str_view.h>
46 
47 namespace hermes {
48 
49 // *********************************************************************************************************************
50 // Str
51 // *********************************************************************************************************************
53 class Str {
54 public:
55  // *******************************************************************************************************************
56  // STATIC FIELDS
57  // *******************************************************************************************************************
58  struct regex {
59  static const char floating_point_number[];
60  static const char integer_number[];
61  static const char alpha_numeric_word[];
62  static const char c_identifier[];
63  // regex
69  static bool match(const std::string &s, const std::string &pattern,
70  std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
76  static bool contains(const std::string &s, const std::string &pattern,
77  std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
83  static std::smatch search(const std::string &s, const std::string &pattern,
84  std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
91  static bool search(std::string s,
92  const std::string &pattern,
93  const std::function<void(const std::smatch &)> &callback,
94  std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
101  static std::string replace(const std::string &s, const std::string &pattern, const std::string &format,
102  std::regex_constants::match_flag_type flags = std::regex_constants::match_default);
103  };
104  // *******************************************************************************************************************
105  // STATIC METHODS
106  // *******************************************************************************************************************
107  // queries
112  static bool isPrefix(const std::string& p, const std::string& s);
113  // formatting
121  static std::string abbreviate(const std::string &s, size_t width, const char fmt[4] = "s.s");
128  template<typename T>
129  static std::string rjust(const T &value, size_t width, char fill_char = ' ') {
130  Str s;
131  s = s << value;
132  if (s.str().size() >= width)
133  return s.str();
134  return std::string(width - s.str().size(), fill_char) + s.str();
135  }
142  template<typename T>
143  static std::string ljust(const T &value, size_t width, char fill_char = ' ') {
144  Str s;
145  s = s << value;
146  if (s.str().size() >= width)
147  return s.str();
148  return s.str() + std::string(width - s.str().size(), fill_char);
149  }
156  template<typename T>
157  static std::string cjust(const T &value, size_t width, char fill_char = ' ') {
158  Str s;
159  s = s << value;
160  if (s.str().size() >= width)
161  return s.str();
162  size_t pad = (width - s.str().size()) / 2;
163  return std::string(pad, fill_char) + s.str() + std::string(pad, fill_char);
164  }
169  template<typename... Ts>
170  static std::string format(const std::string &fmt, Ts &&... args) {
171  std::stringstream s;
172  std::string r;
173  if constexpr(sizeof...(args) > 0) {
174  format_r_(s, fmt, 0, std::forward<Ts>(args) ...);
175  r = s.str();
176  } else
177  r = fmt;
178  return r;
179  }
187  template<typename T>
188  static std::string toHex(T i, bool leading_zeros = false, bool zero_x = false) {
189  std::stringstream stream;
190  if (zero_x)
191  stream << "0x";
192  if (leading_zeros)
193  stream << std::setfill('0') << std::setw(sizeof(T) * 2)
194  << std::hex << i;
195  else
196  stream << std::hex << i;
197  if (!i)
198  stream << '0';
199  return stream.str();
200  }
205  static std::string strip(const std::string &s, const std::string &patterns = " \t\n");
206  // concatenation
211  template<class... Args>
212  static std::string concat(const Args &... args) {
213  std::stringstream s;
214  (s << ... << args);
215  return s.str();
216  }
221  static std::string join(const std::vector<std::string> &v, const std::string &separator = "");
228  template<typename T>
229  static std::string join(const std::vector<T> &v, const std::string &separator = "") {
230  bool first = true;
231  std::stringstream r;
232  for (const auto &s : v) {
233  if (!first)
234  r << separator;
235  first = false;
236  r << s;
237  }
238  return r.str();
239  }
240  // separation
245  static std::vector<std::string> split(const std::string &s,
246  const std::string &delimiters = " ");
247  // numeric
251  static std::string printBits(u32 n) {
252  std::string r;
253  for (int i = 31; i >= 0; i--)
254  if ((1 << i) & n)
255  r += '1';
256  else
257  r += '0';
258  return r;
259  }
266  template<typename T>
267  static std::string binaryToHex(T input_n, bool uppercase = true, bool strip_leading_zeros = false) {
268  static const char digits[] = "0123456789abcdef";
269  static const char DIGITS[] = "0123456789ABCDEF";
270  unsigned long long n = 0;
271  std::memcpy(&n, &input_n, sizeof(T));
272  std::string s;
273  for (int i = sizeof(T) - 1; i >= 0; --i) {
274  u8 a = n >> (8 * i + 4) & 0xf;
275  u8 b = (n >> (8 * i)) & 0xf;
276  if (a)
277  strip_leading_zeros = false;
278  if (!strip_leading_zeros)
279  s += (uppercase) ? DIGITS[a] : digits[a];
280  if (b)
281  strip_leading_zeros = false;
282  if (!strip_leading_zeros)
283  s += (uppercase) ? DIGITS[b] : digits[b];
284  }
285  return s;
286  }
291  static std::string addressOf(uintptr_t ptr, u32 digit_count = 8) {
292  std::string s;
293  // TODO: assuming little endianess
294  for (i8 i = 7; i >= 0; --i) {
295  auto h = binaryToHex((ptr >> (i * 8)) & 0xff, true);
296  s += h.substr(h.size() - 2);
297  }
298  return "0x" + s.substr(s.size() - digit_count, digit_count);
299  }
303  static std::string byteToBinary(byte b) {
304  std::string s;
305  for (int i = 7; i >= 0; i--)
306  s += std::to_string((b >> i) & 1);
307  return s;
308  }
313  static bool isInteger(const std::string &s);
318  static bool isNumber(const std::string &s);
319  // *******************************************************************************************************************
320  // FRIEND FUNCTIONS
321  // *******************************************************************************************************************
326  inline friend Str operator<<(const char *s, const Str &str) {
327  return {str.str() + s};
328  }
333  inline friend Str operator+(const std::string &s, const Str &str) {
334  std::stringstream ss;
335  ss << s << str.s_;
336  return {ss.str()};
337  }
338  // boolean
343  inline friend bool operator==(const char *ss, const Str &s) {
344  return s.str() == ss;
345  }
351  template<typename T>
352  inline bool friend operator==(const T &t, const Str &s) {
353  std::stringstream ss;
354  ss << t;
355  return s.str() == ss.str();
356  }
357  // *******************************************************************************************************************
358  // CONSTRUCTORS
359  // *******************************************************************************************************************
361  Str();
364  Str(std::string s);
367  Str(const char *s);
370  Str(const Str &other);
373  Str(Str &&other) noexcept;
375  ~Str();
376  // *******************************************************************************************************************
377  // ACCESS
378  // *******************************************************************************************************************
381  [[nodiscard]] inline const std::string &str() const { return s_; }
384  [[nodiscard]] inline const char *c_str() const { return s_.c_str(); }
387  [[nodiscard]] inline size_t size() const { return s_.size(); }
390  [[nodiscard]] inline bool empty() const { return s_.empty(); }
395  Result<ConstStrView> substr(size_t pos = 0, i64 len = -1);
396  // *******************************************************************************************************************
397  // METHODS
398  // *******************************************************************************************************************
403  template<class... Args>
404  void append(const Args &... args) {
405  std::ostringstream s;
406  (s << ... << args);
407  s_ += s.str();
408  }
413  template<class... Args>
414  void appendLine(const Args &... args) {
415  std::ostringstream s;
416  (s << ... << args);
417  s_ += s.str() + '\n';
418  }
419  // *******************************************************************************************************************
420  // OPERATORS
421  // *******************************************************************************************************************
422  // assignment
426  Str &operator=(const Str &s) = default;
432  template<typename T>
433  Str &operator=(const T &t) {
434  std::stringstream ss;
435  ss << t;
436  s_ = ss.str();
437  return *this;
438  }
439  // arithmetic
443  Str &operator+=(const Str &other) {
444  s_ += other.s_;
445  return *this;
446  }
452  template<typename T>
453  Str &operator+=(const T &t) {
454  std::stringstream ss;
455  ss << t;
456  s_ += ss.str();
457  return *this;
458  }
464  template<typename T>
465  inline Str operator+(const T &t) const {
466  std::stringstream ss;
467  ss << s_ << t;
468  return ss.str();
469  }
473  inline Str operator<<(const char *s) const {
474  return {s_ + s};
475  }
476  // boolean
480  inline bool operator==(const char *ss) const {
481  return s_ == ss;
482  }
485  template<typename T>
486  inline bool operator==(const T &t) const {
487  std::stringstream ss;
488  ss << t;
489  return s_ == ss.str();
490  }
491 private:
492  // *******************************************************************************************************************
493  // PRIVATE METHODS
494  // *******************************************************************************************************************
495  template<typename T>
496  static void format_r_(std::stringstream &s, const std::string &fmt, u32 i, const T &first) {
497  auto first_i = i;
498  while (i + 1 < fmt.size() && !(fmt[i] == '{' && fmt[i + 1] == '}'))
499  ++i;
500  if (i + 1 < fmt.size()) {
501  s << fmt.substr(first_i, i - first_i);
502  s << first;
503  s << fmt.substr(i + 2, fmt.size() - i - 2);
504  } else
505  s << fmt.substr(first_i, fmt.size() - first_i);
506  }
507  template<typename T, typename...Ts>
508  static void format_r_(std::stringstream &s, const std::string &fmt, u32 i, const T &first, Ts &&... rest) {
509  // iterate until first occurrence of pair {}
510  auto first_i = i;
511  while (i + 1 < fmt.size() && !(fmt[i] == '{' && fmt[i + 1] == '}'))
512  ++i;
513  if (i + 1 < fmt.size()) {
514  s << fmt.substr(first_i, i - first_i);
515  s << first;
516  if constexpr(sizeof ...(rest) > 0)
517  format_r_(s, fmt, i + 2, std::forward<Ts>(rest)...);
518  else
519  s << fmt.substr(i + 2, fmt.size() - i - 2);
520  } else
521  s << fmt.substr(first_i, fmt.size() - first_i);
522  }
523  // *******************************************************************************************************************
524  // PRIVATE FIELDS
525  // *******************************************************************************************************************
526  std::string s_;
527 };
528 
529 // *********************************************************************************************************************
530 // IO
531 // *********************************************************************************************************************
536 inline std::ostream &operator<<(std::ostream &os, const Str &s) {
537  os << s.str();
538  return os;
539 }
545 template<typename T>
546 inline Str operator<<(const Str &s, T t) {
547  std::stringstream ss;
548  ss << t;
549  return {s + ss.str()};
550 }
556 template<typename T, std::enable_if_t<std::is_same_v<T, std::string> == false>>
557 inline Str operator<<(T t, const Str &s) {
558  std::stringstream ss;
559  ss << t;
560  return {s + ss.str()};
561 }
562 
563 }
564 
565 #endif //HERMES_COMMON_STR_H
566 
Holds a valid object or an error.
Definition: result.h:56
String class and set of string functions.
Definition: str.h:53
static std::string concat(const Args &... args)
Concatenates multiple elements_ into a single string.
Definition: str.h:212
const char * c_str() const
Get const char* pointer.
Definition: str.h:384
static std::string rjust(const T &value, size_t width, char fill_char=' ')
Right justifies string value.
Definition: str.h:129
static std::string strip(const std::string &s, const std::string &patterns=" \t\n")
Definition: str.cpp:149
Str()
Default constructor.
static std::string join(const std::vector< T > &v, const std::string &separator="")
Concatenate elements together separates by a separator.
Definition: str.h:229
static std::string binaryToHex(T input_n, bool uppercase=true, bool strip_leading_zeros=false)
Get ascii representation of raw bit data of input_n
Definition: str.h:267
size_t size() const
Get the number of characters on the string.
Definition: str.h:387
static std::string join(const std::vector< std::string > &v, const std::string &separator="")
Concatenate strings together separated by a separator.
Definition: str.cpp:137
Result< ConstStrView > substr(size_t pos=0, i64 len=-1)
Get a sub-string view from this object.
Definition: str.cpp:256
static std::string printBits(u32 n)
Print bits in big-endian order.
Definition: str.h:251
static bool isNumber(const std::string &s)
Checks if string represents a number.
Definition: str.cpp:205
void append(const Args &... args)
Append arguments to this Str.
Definition: str.h:404
bool friend operator==(const T &t, const Str &s)
Character-wise comparison.
Definition: str.h:352
Str operator<<(const char *s) const
Generates a copy appended by s
Definition: str.h:473
static std::string abbreviate(const std::string &s, size_t width, const char fmt[4]="s.s")
Abbreviates a string to fit in a string of width characters.
Definition: str.cpp:93
bool operator==(const T &t) const
Performs character comparison with string value of t
Definition: str.h:486
Str & operator+=(const Str &other)
Simple concatenation with other
Definition: str.h:443
static std::vector< std::string > split(const std::string &s, const std::string &delimiters=" ")
Splits a string into tokens separated by delimiters.
Definition: str.cpp:170
Str & operator=(const Str &s)=default
Str & operator+=(const T &t)
Simple concatenation with string of value.
Definition: str.h:453
Str operator+(const T &t) const
Generates a copy appended by t
Definition: str.h:465
static std::string cjust(const T &value, size_t width, char fill_char=' ')
Center justifies string value.
Definition: str.h:157
static std::string addressOf(uintptr_t ptr, u32 digit_count=8)
Generates hexadecimal representation of memory address.
Definition: str.h:291
static std::string format(const std::string &fmt, Ts &&... args)
Definition: str.h:170
static bool isInteger(const std::string &s)
Checks if string represents an integer.
Definition: str.cpp:187
friend bool operator==(const char *ss, const Str &s)
const char* pointer comparison
Definition: str.h:343
const std::string & str() const
Get std::string object.
Definition: str.h:381
void appendLine(const Args &... args)
Append arguments to this Str followed by a breakline.
Definition: str.h:414
static bool isPrefix(const std::string &p, const std::string &s)
Checks if s has prefix p.
Definition: str.cpp:82
static std::string toHex(T i, bool leading_zeros=false, bool zero_x=false)
Generates hexadecimal representation from number.
Definition: str.h:188
Str & operator=(const T &t)
String of value assignment.
Definition: str.h:433
friend Str operator+(const std::string &s, const Str &str)
Concatenate.
Definition: str.h:333
bool empty() const
Checks if string is empty.
Definition: str.h:390
static std::string ljust(const T &value, size_t width, char fill_char=' ')
Left justifies string value.
Definition: str.h:143
static std::string byteToBinary(byte b)
Binary representation of byte.
Definition: str.h:303
Str(const Str &other)
Copy constructor.
bool operator==(const char *ss) const
Performs const char* comparison.
Definition: str.h:480
friend Str operator<<(const char *s, const Str &str)
Concatenate.
Definition: str.h:326
Data type definitions.
int8_t i8
8 bit size integer type
Definition: defs.h:81
uint32_t u32
32 bit size unsigned integer type
Definition: defs.h:88
int64_t i64
64 bit size integer type
Definition: defs.h:84
uint8_t u8
8 bit size unsigned integer type
Definition: defs.h:86
Definition: str.h:58
static bool match(const std::string &s, const std::string &pattern, std::regex_constants::match_flag_type flags=std::regex_constants::match_default)
Checks if a string s matches exactly a regular expression.
Definition: str.cpp:40
static bool contains(const std::string &s, const std::string &pattern, std::regex_constants::match_flag_type flags=std::regex_constants::match_default)
Checks if any substring of s matches a regular expression.
Definition: str.cpp:45
static std::smatch search(const std::string &s, const std::string &pattern, std::regex_constants::match_flag_type flags=std::regex_constants::match_default)
Search the first substrings of s that matches the pattern.
Definition: str.cpp:52
static std::string replace(const std::string &s, const std::string &pattern, const std::string &format, std::regex_constants::match_flag_type flags=std::regex_constants::match_default)
Replaces all matches of pattern in s by format.
Definition: str.cpp:75