Skip to content

Commit cab17f6

Browse files
committed
turn RegexReplaceFormatter into template
1 parent 6c8d23f commit cab17f6

File tree

4 files changed

+103
-193
lines changed

4 files changed

+103
-193
lines changed

src/RegexReplaceFormatter.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,3 @@
1818
//
1919
#include "stdafx.h"
2020
#include "RegexReplaceFormatter.h"
21-
22-
std::vector<NumberReplacer> g_incVec;
23-
std::vector<NumberReplacerA> g_incVecA;

src/RegexReplaceFormatter.h

Lines changed: 100 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
#pragma warning(push)
2626
#pragma warning(disable : 4996) // warning STL4010: Various members of std::allocator are deprecated in C++17
2727
#include <boost/regex.hpp>
28-
#include <boost/iostreams/device/mapped_file.hpp>
29-
3028
#pragma warning(pop)
3129

30+
template<typename CharT>
3231
class NumberReplacer
3332
{
3433
public:
@@ -40,41 +39,22 @@ class NumberReplacer
4039
{
4140
}
4241

43-
bool leadZero;
44-
int padding;
45-
int start;
46-
int increment;
47-
std::wstring expression;
48-
};
49-
50-
class NumberReplacerA
51-
{
52-
public:
53-
NumberReplacerA()
54-
: leadZero(false)
55-
, padding(0)
56-
, start(1)
57-
, increment(1)
58-
{
59-
}
60-
61-
bool leadZero;
62-
int padding;
63-
int start;
64-
int increment;
65-
std::string expression;
42+
bool leadZero;
43+
int padding;
44+
int start;
45+
int increment;
46+
std::basic_string<CharT> expression;
6647
};
6748

68-
extern std::vector<NumberReplacer> g_incVec;
69-
extern std::vector<NumberReplacerA> g_incVecA;
70-
49+
// Iter is the same as the BidirectionalIterator in which `regex_replace` it is used
50+
template<typename CharT, typename Iter = std::basic_string<CharT>::const_iterator>
7151
class RegexReplaceFormatter
7252
{
7353
public:
74-
RegexReplaceFormatter(const std::wstring& sReplace)
75-
: m_sReplace(sReplace)
54+
RegexReplaceFormatter(const std::basic_string<CharT>& str)
55+
: m_sReplace(str)
7656
{
77-
g_incVec.clear();
57+
m_incVec.clear();
7858
// parse for ${count0L}, ${count0L(n)}, ${count0L(n,m)}, where
7959
// ${count}
8060
// is replaced later with numbers starting from 1, incremented by 1
@@ -84,53 +64,71 @@ class RegexReplaceFormatter
8464
// is replaced with numbers starting from n, incremented by m
8565
// 0 and L are optional and specify the size of the right-aligned
8666
// number string. If 0 is specified, zeros are used for padding, otherwise spaces.
87-
// boost::wregex expression = boost::wregex(L"(?<!\\\\)\\$\\{count(?<leadzero>0)?(?<length>\\d+)?(\\((?<startval>[-0-9]+)\\)||\\((?<startval>[-0-9]+),(?<increment>[-0-9]+)\\))?\\}", boost::regex::normal);
88-
boost::wregex expression = boost::wregex(L"\\$\\{count(?<leadzero>0)?(?<length>\\d+)?(\\((?<startval>[-0-9]+)\\)||\\((?<startval>[-0-9]+),(?<increment>[-0-9]+)\\))?\\}", boost::regex::normal);
89-
boost::match_results<std::wstring::const_iterator> whatc;
90-
std::wstring::const_iterator start = m_sReplace.begin();
91-
std::wstring::const_iterator end = m_sReplace.end();
92-
boost::match_flag_type flags = boost::match_default | boost::format_all;
93-
while (boost::regex_search(start, end, whatc, expression, flags))
67+
// expr: "\\$\\{count(?<leadzero>0)?(?<length>\\d+)?(\\((?<startval>[-0-9]+)\\)||\\((?<startval>[-0-9]+),(?<increment>[-0-9]+)\\))?\\}"
68+
CharT expr[] = {
69+
'\\', '$', '\\', '{',
70+
'c', 'o', 'u', 'n', 't',
71+
'(', '?', '<', 'l', 'e', 'a', 'd', 'z', 'e', 'r', 'o', '>', '0', ')', '?',
72+
'(', '?', '<', 'l', 'e', 'n', 'g', 't', 'h', '>', '\\', 'd', '+', ')', '?',
73+
'(',
74+
'\\', '(', '(', '?', '<', 's', 't', 'a', 'r', 't', 'v', 'a', 'l', '>', '[', '-', '0', '-', '9', ']', '+', ')', '\\', ')', '|', '|',
75+
'\\', '(', '(', '?', '<', 's', 't', 'a', 'r', 't', 'v', 'a', 'l', '>', '[', '-', '0', '-', '9', ']', '+', ')', ',',
76+
'(', '?', '<', 'i', 'n', 'c', 'r', 'e', 'm', 'e', 'n', 't', '>', '[', '-', '0', '-', '9', ']', '+', ')',
77+
'\\', ')',
78+
')', '?',
79+
'\\', '}', 0
80+
};
81+
boost::basic_regex<CharT> regEx = boost::basic_regex<CharT>(expr, boost::regex::normal);
82+
boost::match_results<std::basic_string<CharT>::const_iterator> whatC;
83+
typename std::basic_string<CharT>::const_iterator start = m_sReplace.begin();
84+
typename std::basic_string<CharT>::const_iterator end = m_sReplace.end();
85+
boost::match_flag_type flags = boost::match_default | boost::format_all;
86+
while (boost::regex_search(start, end, whatC, regEx, flags))
9487
{
95-
if (whatc[0].matched)
88+
if (whatC[0].matched)
9689
{
97-
NumberReplacer nr;
98-
nr.leadZero = (static_cast<std::wstring>(whatc[L"leadzero"]) == L"0");
99-
nr.padding = _wtoi(static_cast<std::wstring>(whatc[L"length"]).c_str());
100-
std::wstring s = static_cast<std::wstring>(whatc[L"startval"]);
90+
NumberReplacer<CharT> nr;
91+
CharT leadzero[] = {'l', 'e', 'a', 'd', 'z', 'e', 'r', 'o', 0};
92+
CharT zero[] = {'0', 0};
93+
nr.leadZero = (static_cast<std::basic_string<CharT>>(whatC[leadzero]) == zero);
94+
CharT length[] = {'l', 'e', 'n', 'g', 't', 'h', 0};
95+
nr.padding = t_ttoi(static_cast<std::basic_string<CharT>>(whatC[length]).c_str());
96+
CharT startval[] = {'s', 't', 'a', 'r', 't', 'v', 'a', 'l', 0};
97+
std::basic_string<CharT> s = static_cast<std::basic_string<CharT>>(whatC[startval]);
10198
if (!s.empty())
102-
nr.start = _wtoi(s.c_str());
103-
s = static_cast<std::wstring>(whatc[L"increment"]);
99+
nr.start = t_ttoi(s.c_str());
100+
CharT increment[] = {'i', 'n', 'c', 'r', 'e', 'm', 'e', 'n', 't', 0};
101+
s = static_cast<std::basic_string<CharT>>(whatC[increment]);
104102
if (!s.empty())
105-
nr.increment = _wtoi(s.c_str());
103+
nr.increment = t_ttoi(s.c_str());
106104
if (nr.increment == 0)
107105
nr.increment = 1;
108-
nr.expression = static_cast<std::wstring>(whatc[0]);
109-
g_incVec.push_back(nr);
106+
nr.expression = static_cast<std::basic_string<CharT>>(whatC[0]);
107+
m_incVec.push_back(nr);
110108
}
111109
// update search position:
112-
if (start == whatc[0].second)
110+
if (start == whatC[0].second)
113111
{
114112
if (start == end)
115113
break;
116114
++start;
117115
}
118116
else
119-
start = whatc[0].second;
117+
start = whatC[0].second;
120118
// update flags:
121119
flags |= boost::match_prev_avail;
122120
flags |= boost::match_not_bob;
123121
}
124122
}
125123

126-
void SetReplacePair(const std::wstring& s1, const std::wstring& s2)
124+
void SetReplacePair(const std::basic_string<CharT>& s1, const std::basic_string<CharT>& s2)
127125
{
128126
m_replaceMap[s1] = s2;
129127
}
130128

131-
std::wstring operator()(boost::match_results<std::wstring::const_iterator> what) const
129+
std::basic_string<CharT> operator()(boost::match_results<Iter> what)
132130
{
133-
std::wstring sReplace = what.format(m_sReplace);
131+
std::basic_string<CharT> sReplace = what.format(m_sReplace);
134132
if (!m_replaceMap.empty())
135133
{
136134
for (auto it = m_replaceMap.cbegin(); it != m_replaceMap.cend(); ++it)
@@ -151,31 +149,38 @@ class RegexReplaceFormatter
151149
}
152150
}
153151
}
154-
if (!g_incVec.empty())
152+
if (!m_incVec.empty())
155153
{
156-
for (auto it = g_incVec.begin(); it != g_incVec.end(); ++it)
154+
for (auto it = m_incVec.begin(); it != m_incVec.end(); ++it)
157155
{
158156
auto itBegin = std::search(sReplace.begin(), sReplace.end(), it->expression.begin(), it->expression.end());
159157
if (itBegin != sReplace.end())
160158
{
161159
if ((itBegin == sReplace.begin()) || ((*(itBegin - 1)) != '\\'))
162160
{
163161
auto itEnd = itBegin + it->expression.size();
164-
wchar_t format[20] = {0};
162+
CharT format[20] = {0};
165163
if (it->padding)
166164
{
165+
CharT *fmt;
166+
CharT fmt1[] = {'%', '%', '0', '%', 'd', 'd', 0};
167+
CharT fmt2[] = {'%', '%', '%', 'd', 'd', 0};
167168
if (it->leadZero)
168-
swprintf_s(format, _countof(format), L"%%0%dd", it->padding);
169+
fmt = fmt1;
169170
else
170-
swprintf_s(format, _countof(format), L"%%%dd", it->padding);
171+
fmt = fmt2;
172+
t_stprintf_s(format, _countof(format), fmt, it->padding);
171173
}
172174
else
173-
wcscpy_s(format, L"%d");
175+
{
176+
CharT fmt[] = {'%', 'd', 0};
177+
t_tcscpy_s(format, fmt);
178+
}
174179
if (it->padding < 50)
175180
{
176181
// for small strings, reserve space on the stack
177-
wchar_t buf[128] = {0};
178-
swprintf_s(buf, _countof(buf), format, it->start);
182+
CharT buf[128] = {0};
183+
t_stprintf_s(buf, _countof(buf), format, it->start);
179184
sReplace.replace(itBegin, itEnd, buf);
180185
}
181186
else
@@ -193,146 +198,54 @@ class RegexReplaceFormatter
193198
}
194199
}
195200

196-
// sReplace = boost::regex_replace(what[0].str(), sReplace, boost::match_default);
197-
198201
return sReplace;
199202
}
200203

201204
private:
202-
std::wstring m_sReplace;
203-
std::map<std::wstring, std::wstring> m_replaceMap;
204-
};
205+
int t_ttoi(const wchar_t *str)
206+
{
207+
return _wtoi(str);
208+
}
205209

206-
class RegexReplaceFormatterA
207-
{
208-
public:
209-
RegexReplaceFormatterA(const std::string& sReplace)
210-
: m_sReplace(sReplace)
210+
int t_ttoi(const char *str)
211211
{
212-
g_incVec.clear();
213-
// parse for ${count0L}, ${count0L(n)}, ${count0L(n,m)}, where
214-
// ${count}
215-
// is replaced later with numbers starting from 1, incremented by 1
216-
// ${count(n)}
217-
// is replaced with numbers starting from n, incremented by 1
218-
// ${count(n,m)}
219-
// is replaced with numbers starting from n, incremented by m
220-
// 0 and L are optional and specify the size of the right-aligned
221-
// number string. If 0 is specified, zeros are used for padding, otherwise spaces.
222-
// boost::wregex expression = boost::wregex(L"(?<!\\\\)\\$\\{count(?<leadzero>0)?(?<length>\\d+)?(\\((?<startval>[-0-9]+)\\)||\\((?<startval>[-0-9]+),(?<increment>[-0-9]+)\\))?\\}", boost::regex::normal);
223-
boost::regex expression = boost::regex("\\$\\{count(?<leadzero>0)?(?<length>\\d+)?(\\((?<startval>[-0-9]+)\\)||\\((?<startval>[-0-9]+),(?<increment>[-0-9]+)\\))?\\}", boost::regex::normal);
224-
boost::match_results<std::string::const_iterator> whatc;
225-
std::string::const_iterator start = m_sReplace.begin();
226-
std::string::const_iterator end = m_sReplace.end();
227-
boost::match_flag_type flags = boost::match_default | boost::format_all;
228-
while (boost::regex_search(start, end, whatc, expression, flags))
229-
{
230-
if (whatc[0].matched)
231-
{
232-
NumberReplacerA nr;
233-
nr.leadZero = (static_cast<std::string>(whatc["leadzero"]) == "0");
234-
nr.padding = atoi(static_cast<std::string>(whatc["length"]).c_str());
235-
std::string s = static_cast<std::string>(whatc["startval"]);
236-
if (!s.empty())
237-
nr.start = atoi(s.c_str());
238-
s = static_cast<std::string>(whatc["increment"]);
239-
if (!s.empty())
240-
nr.increment = atoi(s.c_str());
241-
if (nr.increment == 0)
242-
nr.increment = 1;
243-
nr.expression = static_cast<std::string>(whatc[0]);
244-
g_incVecA.push_back(nr);
245-
}
246-
// update search position:
247-
if (start == whatc[0].second)
248-
{
249-
if (start == end)
250-
break;
251-
++start;
252-
}
253-
else
254-
start = whatc[0].second;
255-
// update flags:
256-
flags |= boost::match_prev_avail;
257-
flags |= boost::match_not_bob;
258-
}
212+
return atoi(str);
259213
}
260214

261-
void SetReplacePair(const std::string& s1, const std::string& s2)
215+
int t_stprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, ...)
262216
{
263-
m_replaceMap[s1] = s2;
217+
int _Result;
218+
va_list _ArgList;
219+
__crt_va_start(_ArgList, format);
220+
_Result = _vswprintf_s_l(buffer, sizeOfBuffer, format, NULL, _ArgList);
221+
__crt_va_end(_ArgList);
222+
return _Result;
264223
}
265224

266-
template <typename It>
267-
std::string operator()(boost::match_results<It> what) const
225+
int t_stprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
268226
{
269-
std::string sReplace = what.format(m_sReplace);
270-
if (!m_replaceMap.empty())
271-
{
272-
for (auto it = m_replaceMap.cbegin(); it != m_replaceMap.cend(); ++it)
273-
{
274-
auto itBegin = std::search(sReplace.begin(), sReplace.end(), it->first.begin(), it->first.end());
275-
while (itBegin != sReplace.end())
276-
{
277-
if ((itBegin == sReplace.begin()) || ((*(itBegin - 1)) != '\\'))
278-
{
279-
auto itEnd = itBegin + it->first.size();
280-
sReplace.replace(itBegin, itEnd, it->second);
281-
}
282-
else if ((*(itBegin - 1)) == '\\')
283-
{
284-
sReplace.erase(itBegin - 1);
285-
};
286-
itBegin = std::search(sReplace.begin(), sReplace.end(), it->first.begin(), it->first.end());
287-
}
288-
}
289-
}
290-
if (!g_incVec.empty())
291-
{
292-
for (auto it = g_incVec.begin(); it != g_incVec.end(); ++it)
293-
{
294-
auto itBegin = std::search(sReplace.begin(), sReplace.end(), it->expression.begin(), it->expression.end());
295-
if (itBegin != sReplace.end())
296-
{
297-
if ((itBegin == sReplace.begin()) || ((*(itBegin - 1)) != '\\'))
298-
{
299-
auto itEnd = itBegin + it->expression.size();
300-
char format[20] = {0};
301-
if (it->padding)
302-
{
303-
if (it->leadZero)
304-
sprintf_s(format, _countof(format), "%%0%dd", it->padding);
305-
else
306-
sprintf_s(format, _countof(format), "%%%dd", it->padding);
307-
}
308-
else
309-
strcpy_s(format, "%d");
310-
if (it->padding < 50)
311-
{
312-
// for small strings, reserve space on the stack
313-
char buf[128] = {0};
314-
sprintf_s(buf, _countof(buf), format, it->start);
315-
sReplace.replace(itBegin, itEnd, buf);
316-
}
317-
else
318-
{
319-
auto s = CStringUtils::Format(format, it->start);
320-
sReplace.replace(itBegin, itEnd, s);
321-
}
322-
it->start += it->increment;
323-
}
324-
else if ((*(itBegin - 1)) == '\\')
325-
{
326-
sReplace.erase(itBegin - 1);
327-
};
328-
}
329-
}
330-
}
227+
int _Result;
228+
va_list _ArgList;
229+
__crt_va_start(_ArgList, format);
230+
_Result = _vsprintf_s_l(buffer, sizeOfBuffer, format, NULL, _ArgList);
231+
__crt_va_end(_ArgList);
232+
return _Result;
233+
}
331234

332-
return sReplace;
235+
template <size_t size>
236+
errno_t t_tcscpy_s(wchar_t (&dest)[size], const wchar_t *src)
237+
{
238+
return wcscpy_s(dest, size, src);
239+
}
240+
241+
template <size_t size>
242+
errno_t t_tcscpy_s(char (&dest)[size], const char *src)
243+
{
244+
return strcpy_s(dest, size, src);
333245
}
334246

335247
private:
336-
std::string m_sReplace;
337-
std::map<std::string, std::string> m_replaceMap;
248+
std::vector<NumberReplacer<CharT>> m_incVec;
249+
std::basic_string<CharT> m_sReplace;
250+
std::map<std::basic_string<CharT>, std::basic_string<CharT>> m_replaceMap;
338251
};

0 commit comments

Comments
 (0)