Deduplicate code
[TortoiseGit.git] / src / Utils / StringUtils.h
blob614aa74412fbeec12c956ea5eb12f90fd3600ffb
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2010, 2020-2023 - TortoiseSVN
4 // Copyright (C) 2015-2016, 2020, 2024 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program 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.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
21 #include <string>
22 #include <vector>
24 #ifdef UNICODE
25 #define wcswildcmp wcswildcmp
26 #else
27 #define wcswildcmp strwildcmp
28 #endif
30 /**
31 * \ingroup Utils
32 * Performs a wild card compare of two strings.
33 * \param wild the wild card string
34 * \param string the string to compare the wild card to
35 * \return TRUE if the wild card matches the string, 0 otherwise
36 * \par example
37 * \code
38 * if (strwildcmp("bl?hblah.*", "bliblah.jpeg"))
39 * printf("success\n");
40 * else
41 * printf("not found\n");
42 * if (strwildcmp("bl?hblah.*", "blabblah.jpeg"))
43 * printf("success\n");
44 * else
45 * printf("not found\n");
46 * \endcode
47 * The output of the above code would be:
48 * \code
49 * success
50 * not found
51 * \endcode
53 int strwildcmp(const char * wild, const char * string);
54 int wcswildcmp(const wchar_t * wild, const wchar_t * string);
56 // append = true as the default: a default value should never lose data!
57 template <typename Container, typename CHARTYPE, typename TRAIT>
58 void stringtok(Container& container, const std::basic_string<CHARTYPE, TRAIT>& in, bool trim, const CHARTYPE* const delimiters, bool append = true)
60 const auto len = in.length();
61 decltype(in.length()) i = 0;
62 if (!append)
63 container.clear();
65 while (i < len)
67 if (trim)
69 // eat leading whitespace
70 i = in.find_first_not_of(delimiters, i);
71 if (i == std::basic_string<CHARTYPE, TRAIT>::npos)
72 return; // nothing left but white space
75 // find the end of the token
76 const auto j = in.find_first_of(delimiters, i);
78 // push token
79 if (j == std::basic_string<CHARTYPE, TRAIT>::npos)
81 if constexpr (std::is_same_v<typename Container::value_type, std::basic_string<CHARTYPE, TRAIT>>)
82 container.push_back(in.substr(i));
83 else if constexpr (std::is_same_v<CHARTYPE, wchar_t>)
84 container.push_back(static_cast<typename Container::value_type>(_wtoi64(in.substr(i).c_str())));
85 else if constexpr (std::is_same_v<CHARTYPE, char>)
86 container.push_back(static_cast<typename Container::value_type>(_atoi64(in.substr(i).c_str())));
87 else
88 static_assert(false);
89 return;
91 else
93 if constexpr (std::is_same_v<typename Container::value_type, std::basic_string<CHARTYPE, TRAIT>>)
94 container.push_back(in.substr(i, j - i));
95 else if constexpr (std::is_same_v<CHARTYPE, wchar_t>)
96 container.push_back(static_cast<typename Container::value_type>(_wtoi64(in.substr(i, j - i).c_str())));
97 else if constexpr (std::is_same_v<CHARTYPE, char>)
98 container.push_back(static_cast<typename Container::value_type>(_atoi64(in.substr(i, j - i).c_str())));
99 else
100 static_assert(false);
103 // set up for next loop
104 i = j + 1;
109 * \ingroup Utils
110 * string helper functions
112 class CStringUtils
114 public:
115 CStringUtils() = delete;
116 #if defined(CSTRING_AVAILABLE) || defined(_MFC_VER)
119 * Removes all '&' chars from a string.
121 static void RemoveAccelerators(CString& text);
124 * Returns the accellerator used in the string or \0
126 static wchar_t GetAccellerator(const CString& text);
129 * Escapes all '&' chars from a string with another '&'.
131 static CString EscapeAccellerators(CString& text);
133 static CString EnsureCRLF(const CString& text);
134 #endif
136 #ifdef _MFC_VER
138 * Writes an ASCII CString to the clipboard in CF_TEXT format
140 static bool WriteAsciiStringToClipboard(const CStringA& sClipdata, LCID lcid, HWND hOwningWnd = nullptr);
142 * Writes a String to the clipboard in both CF_UNICODETEXT and CF_TEXT format
144 static bool WriteAsciiStringToClipboard(const CStringW& sClipdata, HWND hOwningWnd = nullptr);
147 * Writes an ASCII CString to the clipboard in TGIT_UNIFIEDDIFF format, which is basically the patch file
148 * as a ASCII string.
150 static bool WriteDiffToClipboard(const CStringA& sClipdata, HWND hOwningWnd = nullptr);
153 * Reads the string \text from the file \path in utf8 encoding.
155 static bool ReadStringFromTextFile(const CString& path, CString& text);
157 #endif
158 #if defined(CSTRING_AVAILABLE) || defined(_MFC_VER)
159 static BOOL WildCardMatch(const CString& wildcard, const CString& string);
160 static CString LinesWrap(const CString& longstring, int limit = 80, bool bCompactPaths = false);
161 static CString WordWrap(const CString& longstring, int limit, bool bCompactPaths, bool bForceWrap, int tabSize);
162 static std::vector<CString> WordWrap(const CString& longstring, int limit, int tabSize);
164 * Unescapes Git quoted filenames
165 * This is not a full implementation of the unescaper as we skip some conversions that will result in invalid filenames.
167 static CString UnescapeGitQuotePath(const CString& s);
169 * Find and return the number n of starting characters equal between
170 * \ref lhs and \ref rhs. (max n: lhs.Left(n) == rhs.Left(n))
172 static int GetMatchingLength (const CString& lhs, const CString& rhs);
175 * Optimizing wrapper around CompareNoCase.
177 static int FastCompareNoCase (const CStringW& lhs, const CStringW& rhs);
179 static void ParseEmailAddress(CString mailaddress, CString& parsedAddress, CString* parsedName = nullptr);
181 static bool IsPlainReadableASCII(const CString& text);
183 static bool StartsWith(const wchar_t* heystack, const CString& needle);
184 static bool StartsWithI(const wchar_t* heystack, const CString& needle);
185 static bool WriteStringToTextFile(LPCWSTR path, LPCWSTR text, bool bUTF8 = true);
186 static bool EndsWith(const CString& heystack, const wchar_t* needle);
187 static bool EndsWith(const CString& heystack, const wchar_t needle);
188 static bool EndsWithI(const CString& heystack, const wchar_t* needle);
189 #endif
190 static bool StartsWith(const wchar_t* heystack, const wchar_t* needle);
191 static bool StartsWith(const char* heystack, const char* needle);
194 * Writes the string \text to the file \path, either in utf16 or utf8 encoding,
195 * depending on the \c bUTF8 param.
197 static bool WriteStringToTextFile(const std::wstring& path, const std::wstring& text, bool bUTF8 = true);
200 * Replace all pipe (|) character in the string with a nullptr character. Used
201 * for passing into Win32 functions that require such representation
203 static void PipesToNulls(wchar_t* buffer, size_t length);
204 static void PipesToNulls(wchar_t* buffer);