ZNC  trunk
ZNCString.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2024 ZNC, see the NOTICE file for details.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ZNCSTRING_H
18 #define ZNCSTRING_H
19 
20 #include <znc/zncconfig.h>
21 #include <map>
22 #include <set>
23 #include <string>
24 #include <vector>
25 #include <sstream>
26 #include <sys/types.h>
27 #include <initializer_list>
28 
29 #define _SQL(s) CString("'" + CString(s).Escape_n(CString::ESQL) + "'")
30 #define _URL(s) CString(s).Escape_n(CString::EURL)
31 #define _HTML(s) CString(s).Escape_n(CString::EHTML)
32 #define _NAMEDFMT(s) CString(s).Escape_n(CString::ENAMEDFMT)
33 
34 class CString;
35 class MCString;
36 
37 typedef std::set<CString> SCString;
38 typedef std::vector<CString> VCString;
39 typedef std::vector<std::pair<CString, CString>> VPair;
40 
41 static const unsigned char XX = 0xff;
42 static const unsigned char base64_table[256] = {
43  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
44  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
45  XX, XX, XX, XX, XX, 62, XX, XX, XX, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
46  61, XX, XX, XX, XX, XX, XX, XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
47  11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, XX, XX, XX, XX,
48  XX, XX, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
49  43, 44, 45, 46, 47, 48, 49, 50, 51, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
50  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
51  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
52  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
53  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
54  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
55  XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
56  XX, XX, XX, XX, XX, XX, XX, XX, XX,
57 };
58 
60 
68 class CString : public std::string {
69  public:
70  typedef enum {
79  } EEscape;
80 
84 
85  explicit CString(bool b) : std::string(b ? "true" : "false") {}
86  explicit CString(char c);
87  explicit CString(unsigned char c);
88  explicit CString(short i);
89  explicit CString(unsigned short i);
90  explicit CString(int i);
91  explicit CString(unsigned int i);
92  explicit CString(long i);
93  explicit CString(unsigned long i);
94  explicit CString(long long i);
95  explicit CString(unsigned long long i);
96  explicit CString(double i, int precision = 2);
97  explicit CString(float i, int precision = 2);
98 
99  CString() : std::string() {}
100  CString(const char* c) : std::string(c) {}
101  CString(const char* c, size_t l) : std::string(c, l) {}
102  CString(const std::string& s) : std::string(s) {}
103  CString(size_t n, char c) : std::string(n, c) {}
104  CString(std::initializer_list<char> list) : std::string(list) {}
105  ~CString() {}
106 
113  template <typename T>
114  bool Convert(T* target) const {
115  std::stringstream ss(*this);
116  ss >> *target;
117  return (bool)ss; // we don't care why it failed, only whether it failed
118  }
119 
127  template <typename Iterator>
128  CString Join(Iterator i_start, const Iterator& i_end) const {
129  if (i_start == i_end) return CString("");
130  std::ostringstream output;
131  output << *i_start;
132  while (true) {
133  ++i_start;
134  if (i_start == i_end) return CString(output.str());
135  output << *this;
136  output << *i_start;
137  }
138  }
139 
147  int CaseCmp(const CString& s,
148  CString::size_type uLen = CString::npos) const;
156  int StrCmp(const CString& s, CString::size_type uLen = CString::npos) const;
164  bool Equals(const CString& s, CaseSensitivity cs = CaseInsensitive) const;
168  bool Equals(const CString& s, bool bCaseSensitive,
169  CString::size_type uLen = CString::npos) const;
181  static bool WildCmp(const CString& sWild, const CString& sString,
191  bool WildCmp(const CString& sWild,
192  CaseSensitivity cs = CaseSensitive) const;
193 
209  CString AsUpper() const;
215  CString AsLower() const;
216 
217  static EEscape ToEscape(const CString& sEsc);
218  CString Escape_n(EEscape eFrom, EEscape eTo) const;
222 
243  static unsigned int Replace(CString& sStr, const CString& sReplace,
244  const CString& sWith, const CString& sLeft = "",
245  const CString& sRight = "",
246  bool bRemoveDelims = false);
247 
258  CString Replace_n(const CString& sReplace, const CString& sWith,
259  const CString& sLeft = "", const CString& sRight = "",
260  bool bRemoveDelims = false) const;
270  unsigned int Replace(const CString& sReplace, const CString& sWith,
271  const CString& sLeft = "", const CString& sRight = "",
272  bool bRemoveDelims = false);
279  CString Ellipsize(unsigned int uLen) const;
284  CString Left(size_type uCount) const;
289  CString Right(size_type uCount) const;
290 
294  CString FirstLine() const { return Token(0, false, "\n"); }
295 
311  CString Token(size_t uPos, bool bRest = false, const CString& sSep = " ",
312  bool bAllowEmpty = false) const;
313 
318  CString Token(size_t uPos, bool bRest, const CString& sSep,
319  bool bAllowEmpty, const CString& sLeft, const CString& sRight,
320  bool bTrimQuotes = true) const;
321 
322  size_type URLSplit(MCString& msRet) const;
323  size_type OptionSplit(MCString& msRet, bool bUpperKeys = false) const;
324  size_type QuoteSplit(VCString& vsRet) const;
325 
341  size_type Split(const CString& sDelim, VCString& vsRet,
342  bool bAllowEmpty = true, const CString& sLeft = "",
343  const CString& sRight = "", bool bTrimQuotes = true,
344  bool bTrimWhiteSpace = false) const;
345 
350  size_type Split(const CString& sDelim, SCString& ssRet,
351  bool bAllowEmpty = true, const CString& sLeft = "",
352  const CString& sRight = "", bool bTrimQuotes = true,
353  bool bTrimWhiteSpace = false) const;
354 
363  static CString NamedFormat(const CString& sFormat,
364  const MCString& msValues);
365 
370  static CString RandomString(unsigned int uLength);
371 
373  CString MD5() const;
375  CString SHA256() const;
376 
381  unsigned long Base64Decode(CString& sRet) const;
386  unsigned long Base64Decode();
399  bool Base64Encode(CString& sRet, unsigned int uWrap = 0) const;
404  bool Base64Encode(unsigned int uWrap = 0);
409  CString Base64Encode_n(unsigned int uWrap = 0) const;
410 
411 #ifdef HAVE_LIBSSL
412  CString Encrypt_n(const CString& sPass, const CString& sIvec = "") const;
413  CString Decrypt_n(const CString& sPass, const CString& sIvec = "") const;
414  void Encrypt(const CString& sPass, const CString& sIvec = "");
415  void Decrypt(const CString& sPass, const CString& sIvec = "");
416  void Crypt(const CString& sPass, bool bEncrypt, const CString& sIvec = "");
417 #endif
418 
423  static CString ToPercent(double d);
428  static CString ToByteStr(unsigned long long d);
433  static CString ToTimeStr(unsigned long s);
434 
436  bool ToBool() const;
438  short ToShort() const;
440  unsigned short ToUShort() const;
442  int ToInt() const;
444  long ToLong() const;
446  unsigned int ToUInt() const;
448  unsigned long ToULong() const;
450  unsigned long long ToULongLong() const;
452  long long ToLongLong() const;
454  double ToDouble() const;
455 
461  bool Trim(const CString& s = " \t\r\n");
467  bool TrimLeft(const CString& s = " \t\r\n");
473  bool TrimRight(const CString& s = " \t\r\n");
479  CString Trim_n(const CString& s = " \t\r\n") const;
485  CString TrimLeft_n(const CString& s = " \t\r\n") const;
491  CString TrimRight_n(const CString& s = " \t\r\n") const;
492 
497  bool TrimPrefix(const CString& sPrefix = ":");
502  bool TrimSuffix(const CString& sSuffix);
507  CString TrimPrefix_n(const CString& sPrefix = ":") const;
512  CString TrimSuffix_n(const CString& sSuffix) const;
513 
520  size_t Find(const CString& s, CaseSensitivity cs = CaseInsensitive) const;
527  bool StartsWith(const CString& sPrefix,
528  CaseSensitivity cs = CaseInsensitive) const;
535  bool EndsWith(const CString& sSuffix,
536  CaseSensitivity cs = CaseInsensitive) const;
543  bool Contains(const CString& s, CaseSensitivity cs = CaseInsensitive) const;
544 
549  bool LeftChomp(size_type uLen = 1);
554  bool RightChomp(size_type uLen = 1);
560  CString LeftChomp_n(size_type uLen = 1) const;
566  CString RightChomp_n(size_type uLen = 1) const;
580 
581  private:
582  protected:
583  unsigned char* strnchr(const unsigned char* src, unsigned char c,
584  unsigned int iMaxBytes,
585  unsigned char* pFill = nullptr,
586  unsigned int* piCount = nullptr) const;
587 };
588 
595 class MCString : public std::map<CString, CString> {
596  public:
598  MCString() : std::map<CString, CString>() {}
600  MCString(std::initializer_list<std::pair<const CString, CString>> list)
601  : std::map<CString, CString>(list) {}
603  virtual ~MCString() { clear(); }
604 
606  static const MCString EmptyMap;
607 
610  enum status_t {
620  MCS_EREADFIL = 4
621  };
622 
629  enum status_t WriteToDisk(const CString& sPath, mode_t iMode = 0644) const;
635  enum status_t ReadFromDisk(const CString& sPath);
636 
644  virtual bool WriteFilter(CString& sKey, CString& sValue) const {
645  return true;
646  }
654  virtual bool ReadFilter(CString& sKey, CString& sValue) const {
655  return true;
656  }
657 
661  virtual CString& Encode(CString& sValue) const;
663  virtual CString& Decode(CString& sValue) const;
664 };
665 
666 namespace std {
667 template <>
668 struct hash<CString> : hash<std::string> {};
669 }
670 
671 // Make translateable messages easy to write:
672 // t_f("Foo is {1}")(foo)
674  public:
675  explicit CInlineFormatMessage(const CString& sFormat)
676  : m_sFormat(sFormat) {}
677  explicit CInlineFormatMessage(CString&& sFormat)
678  : m_sFormat(std::move(sFormat)) {}
679 
680  template <typename... Args>
681  CString operator()(const Args&... args) const {
682  MCString values;
683  apply(values, 1, args...);
684  return CString::NamedFormat(m_sFormat, values);
685  }
686 
687  private:
688  template <typename Arg, typename... Rest>
689  void apply(MCString& values, int index, const Arg& arg,
690  const Rest&... rest) const {
691  values[CString(index)] = CString(arg);
692  apply(values, index + 1, rest...);
693  }
694 
695  void apply(MCString& values, int index) const {}
696 
697  CString m_sFormat;
698 };
699 
700 // For gtest
701 #ifdef GTEST_FAIL
702 inline void PrintTo(const CString& s, std::ostream* os) {
703  *os << '"' << s.Escape_n(CString::EDEBUG) << '"';
704 }
705 #endif
706 
707 #endif // !ZNCSTRING_H
std::vector< std::pair< CString, CString > > VPair
Definition: ZNCString.h:39
std::set< CString > SCString
Definition: ZNCString.h:35
CaseSensitivity
Definition: ZNCString.h:59
std::vector< CString > VCString
Definition: ZNCString.h:38
Definition: ZNCString.h:673
CString operator()(const Args &... args) const
Definition: ZNCString.h:681
CInlineFormatMessage(CString &&sFormat)
Definition: ZNCString.h:677
CInlineFormatMessage(const CString &sFormat)
Definition: ZNCString.h:675
String class that is used inside ZNC.
Definition: ZNCString.h:68
unsigned long long ToULongLong() const
CString(unsigned long i)
size_type Split(const CString &sDelim, VCString &vsRet, bool bAllowEmpty=true, const CString &sLeft="", const CString &sRight="", bool bTrimQuotes=true, bool bTrimWhiteSpace=false) const
Split up this string into tokens.
size_type QuoteSplit(VCString &vsRet) const
static CString NamedFormat(const CString &sFormat, const MCString &msValues)
Build a string from a format string, replacing values from a map.
CString(unsigned short i)
CString(long long i)
unsigned long Base64Decode()
Treat this string as base64-encoded data and decode it.
CString Replace_n(const CString &sReplace, const CString &sWith, const CString &sLeft="", const CString &sRight="", bool bRemoveDelims=false) const
Replace all occurrences in the current string.
CString(bool b)
Definition: ZNCString.h:85
CString & MakeLower()
Turn all characters in this string into their lower-case equivalent.
CString RightChomp_n(size_type uLen=1) const
Remove characters from the end of this string.
CString AsLower() const
Return a copy of this string with all characters turned into lower-case.
CString(char c)
int ToInt() const
CString Escape_n(EEscape eTo) const
CString(float i, int precision=2)
CString Join(Iterator i_start, const Iterator &i_end) const
Joins a collection of objects together, using 'this' as a delimiter.
Definition: ZNCString.h:128
bool EndsWith(const CString &sSuffix, CaseSensitivity cs=CaseInsensitive) const
Check whether the string ends with a given suffix.
CString TrimLeft_n(const CString &s=" \t\r\n") const
Trim this string.
CString(std::initializer_list< char > list)
Definition: ZNCString.h:104
CString(const std::string &s)
Definition: ZNCString.h:102
CString Encrypt_n(const CString &sPass, const CString &sIvec="") const
unsigned short ToUShort() const
bool Equals(const CString &s, bool bCaseSensitive, CString::size_type uLen=CString::npos) const
int StrCmp(const CString &s, CString::size_type uLen=CString::npos) const
Compare this string case sensitively to some other string.
static unsigned int Replace(CString &sStr, const CString &sReplace, const CString &sWith, const CString &sLeft="", const CString &sRight="", bool bRemoveDelims=false)
Replace all occurrences in a string.
static const CaseSensitivity CaseSensitive
Definition: ZNCString.h:81
static CString RandomString(unsigned int uLength)
Produces a random string.
CString Decrypt_n(const CString &sPass, const CString &sIvec="") const
bool ToBool() const
bool Base64Encode(unsigned int uWrap=0)
Base64-encode the current string.
long long ToLongLong() const
static const CaseSensitivity CaseInsensitive
Definition: ZNCString.h:82
CString(unsigned char c)
static EEscape ToEscape(const CString &sEsc)
unsigned int ToUInt() const
long ToLong() const
CString(unsigned int i)
int CaseCmp(const CString &s, CString::size_type uLen=CString::npos) const
Compare this string caselessly to some other string.
void Crypt(const CString &sPass, bool bEncrypt, const CString &sIvec="")
CString StripControls_n() const
Remove controls characters from this string.
CString FirstLine() const
Get the first line of this string.
Definition: ZNCString.h:294
CString TrimRight_n(const CString &s=" \t\r\n") const
Trim this string.
~CString()
Definition: ZNCString.h:105
bool LeftChomp(size_type uLen=1)
Remove characters from the beginning of this string.
CString Token(size_t uPos, bool bRest=false, const CString &sSep=" ", bool bAllowEmpty=false) const
Get a token out of this string.
CString(int i)
CString AsUpper() const
Return a copy of this string with all characters turned into upper-case.
CString Trim_n(const CString &s=" \t\r\n") const
Trim this string.
void Encrypt(const CString &sPass, const CString &sIvec="")
size_type OptionSplit(MCString &msRet, bool bUpperKeys=false) const
bool RightChomp(size_type uLen=1)
Remove characters from the end of this string.
unsigned long Base64Decode(CString &sRet) const
Treat this string as base64-encoded data and decode it.
static CString ToTimeStr(unsigned long s)
Pretty-print a time span.
CString(const char *c, size_t l)
Definition: ZNCString.h:101
bool Contains(const CString &s, CaseSensitivity cs=CaseInsensitive) const
Check whether the string contains a given string.
double ToDouble() const
CString Base64Encode_n(unsigned int uWrap=0) const
Base64-encode the current string.
EEscape
Definition: ZNCString.h:70
@ EHTML
Definition: ZNCString.h:73
@ EURL
Definition: ZNCString.h:72
@ ESQL
Definition: ZNCString.h:74
@ ENAMEDFMT
Definition: ZNCString.h:75
@ EHEXCOLON
Definition: ZNCString.h:78
@ EDEBUG
Definition: ZNCString.h:76
@ EMSGTAG
Definition: ZNCString.h:77
@ EASCII
Definition: ZNCString.h:71
bool Base64Encode(CString &sRet, unsigned int uWrap=0) const
Base64-encode the current string.
unsigned char * strnchr(const unsigned char *src, unsigned char c, unsigned int iMaxBytes, unsigned char *pFill=nullptr, unsigned int *piCount=nullptr) const
CString(size_t n, char c)
Definition: ZNCString.h:103
CString TrimSuffix_n(const CString &sSuffix) const
Trim a given suffix.
CString Left(size_type uCount) const
Return the left part of the string.
CString(long i)
CString(double i, int precision=2)
CString(short i)
size_t Find(const CString &s, CaseSensitivity cs=CaseInsensitive) const
Find the position of the given substring.
CString Token(size_t uPos, bool bRest, const CString &sSep, bool bAllowEmpty, const CString &sLeft, const CString &sRight, bool bTrimQuotes=true) const
Get a token out of this string.
size_type Split(const CString &sDelim, SCString &ssRet, bool bAllowEmpty=true, const CString &sLeft="", const CString &sRight="", bool bTrimQuotes=true, bool bTrimWhiteSpace=false) const
Split up this string into tokens.
CString Ellipsize(unsigned int uLen) const
Ellipsize the current string.
CString LeftChomp_n(size_type uLen=1) const
Remove characters from the beginning of this string.
CString Escape_n(EEscape eFrom, EEscape eTo) const
unsigned int Replace(const CString &sReplace, const CString &sWith, const CString &sLeft="", const CString &sRight="", bool bRemoveDelims=false)
Replace all occurrences in the current string.
unsigned long ToULong() const
CString & StripControls()
Remove controls characters from this string.
bool Trim(const CString &s=" \t\r\n")
Trim this string.
static CString ToPercent(double d)
Pretty-print a percent value.
bool StartsWith(const CString &sPrefix, CaseSensitivity cs=CaseInsensitive) const
Check whether the string starts with a given prefix.
CString SHA256() const
CString & Escape(EEscape eTo)
bool TrimLeft(const CString &s=" \t\r\n")
Trim this string.
CString & Escape(EEscape eFrom, EEscape eTo)
CString(const char *c)
Definition: ZNCString.h:100
CString MD5() const
static bool WildCmp(const CString &sWild, const CString &sString, CaseSensitivity cs=CaseSensitive)
Do a wildcard comparison between two strings.
bool TrimSuffix(const CString &sSuffix)
Trim a given suffix.
CString Right(size_type uCount) const
Return the right part of the string.
CString & MakeUpper()
Turn all characters in this string into their upper-case equivalent.
void Decrypt(const CString &sPass, const CString &sIvec="")
CString TrimPrefix_n(const CString &sPrefix=":") const
Trim a given prefix.
bool WildCmp(const CString &sWild, CaseSensitivity cs=CaseSensitive) const
Do a wild compare on this string.
bool Convert(T *target) const
Casts a CString to another type.
Definition: ZNCString.h:114
bool Equals(const CString &s, CaseSensitivity cs=CaseInsensitive) const
Check if this string is equal to some other string.
size_type URLSplit(MCString &msRet) const
CString()
Definition: ZNCString.h:99
CString Base64Decode_n() const
Treat this string as base64-encoded data and decode it.
bool TrimRight(const CString &s=" \t\r\n")
Trim this string.
short ToShort() const
CString(unsigned long long i)
static CString ToByteStr(unsigned long long d)
Pretty-print a number of bytes.
bool TrimPrefix(const CString &sPrefix=":")
Trim a given prefix.
A dictionary for strings.
Definition: ZNCString.h:595
enum status_t ReadFromDisk(const CString &sPath)
Read a map from a file.
enum status_t WriteToDisk(const CString &sPath, mode_t iMode=0644) const
Write this map to a file.
virtual ~MCString()
Destruct this MCString.
Definition: ZNCString.h:603
static const MCString EmptyMap
A static instance of an empty map.
Definition: ZNCString.h:606
MCString()
Construct an empty MCString.
Definition: ZNCString.h:598
virtual bool ReadFilter(CString &sKey, CString &sValue) const
Filter used while reading this map.
Definition: ZNCString.h:654
virtual CString & Encode(CString &sValue) const
Encode a value so that it can safely be parsed by ReadFromDisk().
status_t
Status codes that can be returned by WriteToDisk() and ReadFromDisk().
Definition: ZNCString.h:610
@ MCS_EWRITEFIL
WriteFilter() failed.
Definition: ZNCString.h:618
@ MCS_EOPEN
Opening the file failed.
Definition: ZNCString.h:614
@ MCS_SUCCESS
No errors.
Definition: ZNCString.h:612
@ MCS_EWRITE
Writing to the file failed.
Definition: ZNCString.h:616
@ MCS_EREADFIL
ReadFilter() failed.
Definition: ZNCString.h:620
MCString(std::initializer_list< std::pair< const CString, CString >> list)
Construct a MCString using an initializer list eg.
Definition: ZNCString.h:600
virtual bool WriteFilter(CString &sKey, CString &sValue) const
Filter used while writing this map.
Definition: ZNCString.h:644
virtual CString & Decode(CString &sValue) const
Undo the effects of Encode().