OSDN Git Service

invoke yamy{64,32} and yamyd32 from same directory of yamy.exe instead of current...
[yamy/yamy.git] / stringtool.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // stringtool.cpp\r
3 \r
4 \r
5 #include "stringtool.h"\r
6 #include "array.h"\r
7 #include <locale>\r
8 #include <malloc.h>\r
9 #include <mbstring.h>\r
10 \r
11 \r
12 /* ************************************************************************** *\r
13 \r
14 STRLCPY(3)                OpenBSD Programmer's Manual               STRLCPY(3)\r
15 \r
16 NAME\r
17      strlcpy, strlcat - size-bounded string copying and concatenation\r
18 \r
19 \r
20 \r
21 SYNOPSIS\r
22      #include <string.h>\r
23 \r
24      size_t\r
25      strlcpy(char *dst, const char *src, size_t size);\r
26 \r
27      size_t\r
28      strlcat(char *dst, const char *src, size_t size);\r
29 \r
30 DESCRIPTION\r
31      The strlcpy() and strlcat() functions copy and concatenate strings re-\r
32      spectively.  They are designed to be safer, more consistent, and less er-\r
33      ror prone replacements for strncpy(3) and strncat(3).  Unlike those func-\r
34      tions, strlcpy() and strlcat() take the full size of the buffer (not just\r
35      the length) and guarantee to NUL-terminate the result (as long as size is\r
36      larger than 0).  Note that you should include a byte for the NUL in size.\r
37 \r
38      The strlcpy() function copies up to size - 1 characters from the NUL-ter-\r
39      minated string src to dst, NUL-terminating the result.\r
40 \r
41      The strlcat() function appends the NUL-terminated string src to the end\r
42      of dst. It will append at most size - strlen(dst) - 1 bytes, NUL-termi-\r
43      nating the result.\r
44 \r
45 RETURN VALUES\r
46      The strlcpy() and strlcat() functions return the total length of the\r
47      string they tried to create.  For strlcpy() that means the length of src.\r
48      For strlcat() that means the initial length of dst plus the length of\r
49      src. While this may seem somewhat confusing it was done to make trunca-\r
50      tion detection simple.\r
51 \r
52 EXAMPLES\r
53      The following code fragment illustrates the simple case:\r
54 \r
55            char *s, *p, buf[BUFSIZ];\r
56 \r
57            ...\r
58 \r
59            (void)strlcpy(buf, s, sizeof(buf));\r
60            (void)strlcat(buf, p, sizeof(buf));\r
61 \r
62      To detect truncation, perhaps while building a pathname, something like\r
63      the following might be used:\r
64 \r
65            char *dir, *file, pname[MAXPATHNAMELEN];\r
66 \r
67            ...\r
68 \r
69            if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))\r
70                    goto toolong;\r
71            if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))\r
72                    goto toolong;\r
73 \r
74      Since we know how many characters we copied the first time, we can speed\r
75      things up a bit by using a copy instead on an append:\r
76 \r
77            char *dir, *file, pname[MAXPATHNAMELEN];\r
78            size_t n;\r
79 \r
80            ...\r
81 \r
82            n = strlcpy(pname, dir, sizeof(pname));\r
83            if (n >= sizeof(pname))\r
84                    goto toolong;\r
85            if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname)-n)\r
86                    goto toolong;\r
87 \r
88      However, one may question the validity of such optimizations, as they de-\r
89      feat the whole purpose of strlcpy() and strlcat().  As a matter of fact,\r
90      the first version of this manual page got it wrong.\r
91 \r
92 SEE ALSO\r
93      snprintf(3),  strncat(3),  strncpy(3)\r
94 \r
95 OpenBSD 2.6                      June 22, 1998                               2\r
96 \r
97 \r
98 -------------------------------------------------------------------------------\r
99 \r
100 Source: OpenBSD 2.6 man pages. Copyright: Portions are copyrighted by BERKELEY\r
101 SOFTWARE DESIGN, INC., The Regents of the University of California,\r
102 Massachusetts Institute of Technology, Free Software Foundation, FreeBSD Inc.,\r
103 and others.\r
104 \r
105 * ************************************************************************** */\r
106 \r
107 \r
108 // copy\r
109 template <class T>\r
110 static inline size_t xstrlcpy(T *o_dest, const T *i_src, size_t i_destSize)\r
111 {\r
112         T *d = o_dest;\r
113         const T *s = i_src;\r
114         size_t n = i_destSize;\r
115 \r
116         ASSERT( o_dest != NULL );\r
117         ASSERT( i_src != NULL );\r
118 \r
119         // Copy as many bytes as will fit\r
120         if (n != 0 && --n != 0) {\r
121                 do {\r
122                         if ((*d++ = *s++) == 0)\r
123                                 break;\r
124                 } while (--n != 0);\r
125         }\r
126 \r
127         // Not enough room in o_dest, add NUL and traverse rest of i_src\r
128         if (n == 0) {\r
129                 if (i_destSize != 0)\r
130                         *d = T();                                       // NUL-terminate o_dest\r
131                 while (*s++)\r
132                         ;\r
133         }\r
134 \r
135         return (s - i_src - 1);                 // count does not include NUL\r
136 }\r
137 \r
138 \r
139 // copy\r
140 size_t strlcpy(char *o_dest, const char *i_src, size_t i_destSize)\r
141 {\r
142         return xstrlcpy(o_dest, i_src, i_destSize);\r
143 }\r
144 \r
145 \r
146 // copy\r
147 size_t wcslcpy(wchar_t *o_dest, const wchar_t *i_src, size_t i_destSize)\r
148 {\r
149         return xstrlcpy(o_dest, i_src, i_destSize);\r
150 }\r
151 \r
152 \r
153 // copy\r
154 size_t mbslcpy(unsigned char *o_dest, const unsigned char *i_src,\r
155                            size_t i_destSize)\r
156 {\r
157         unsigned char *d = o_dest;\r
158         const unsigned char *s = i_src;\r
159         size_t n = i_destSize;\r
160 \r
161         ASSERT( o_dest != NULL );\r
162         ASSERT( i_src != NULL );\r
163 \r
164         if (n == 0)\r
165                 return strlen(reinterpret_cast<const char *>(i_src));\r
166 \r
167         // Copy as many bytes as will fit\r
168         for (-- n; *s && 0 < n; -- n) {\r
169                 if (_ismbblead(*s)) {\r
170                         if (!(s[1] && 2 <= n))\r
171                                 break;\r
172                         *d++ = *s++;\r
173                         -- n;\r
174                 }\r
175                 *d++ = *s++;\r
176         }\r
177         *d = '\0';\r
178 \r
179         for (; *s; ++ s)\r
180                 ;\r
181 \r
182         return s - i_src;\r
183 }\r
184 \r
185 \r
186 /// stream output\r
187 tostream &operator<<(tostream &i_ost, const tstringq &i_data)\r
188 {\r
189         i_ost << _T("\"");\r
190         for (const _TCHAR *s = i_data.c_str(); *s; ++ s) {\r
191                 switch (*s) {\r
192                 case _T('\a'):\r
193                         i_ost << _T("\\a");\r
194                         break;\r
195                 case _T('\f'):\r
196                         i_ost << _T("\\f");\r
197                         break;\r
198                 case _T('\n'):\r
199                         i_ost << _T("\\n");\r
200                         break;\r
201                 case _T('\r'):\r
202                         i_ost << _T("\\r");\r
203                         break;\r
204                 case _T('\t'):\r
205                         i_ost << _T("\\t");\r
206                         break;\r
207                 case _T('\v'):\r
208                         i_ost << _T("\\v");\r
209                         break;\r
210                 case _T('"'):\r
211                         i_ost << _T("\\\"");\r
212                         break;\r
213                 default:\r
214                         if (_istlead(*s)) {\r
215                                 _TCHAR buf[3] = { s[0], s[1], 0 };\r
216                                 i_ost << buf;\r
217                                 ++ s;\r
218                         } else if (_istprint(*s)) {\r
219                                 _TCHAR buf[2] = { *s, 0 };\r
220                                 i_ost << buf;\r
221                         } else {\r
222                                 i_ost << _T("\\x");\r
223                                 _TCHAR buf[5];\r
224 #ifdef _UNICODE\r
225                                 _sntprintf(buf, NUMBER_OF(buf), _T("%04x"), *s);\r
226 #else\r
227                                 _sntprintf(buf, NUMBER_OF(buf), _T("%02x"), *s);\r
228 #endif\r
229                                 i_ost << buf;\r
230                         }\r
231                         break;\r
232                 }\r
233         }\r
234         i_ost << _T("\"");\r
235         return i_ost;\r
236 }\r
237 \r
238 \r
239 // interpret meta characters such as \n\r
240 tstring interpretMetaCharacters(const _TCHAR *i_str, size_t i_len,\r
241                                                                 const _TCHAR *i_quote,\r
242                                                                 bool i_doesUseRegexpBackReference)\r
243 {\r
244         // interpreted string is always less than i_len\r
245         Array<_TCHAR> result(i_len + 1);\r
246         // destination\r
247         _TCHAR *d = result.get();\r
248         // end pointer\r
249         const _TCHAR *end = i_str + i_len;\r
250 \r
251         while (i_str < end && *i_str) {\r
252                 if (*i_str != _T('\\')) {\r
253                         if (_istlead(*i_str) && *(i_str + 1) && i_str + 1 < end)\r
254                                 *d++ = *i_str++;\r
255                         *d++ = *i_str++;\r
256                 } else if (*(i_str + 1) != _T('\0')) {\r
257                         i_str ++;\r
258                         if (i_quote && _tcschr(i_quote, *i_str))\r
259                                 *d++ = *i_str++;\r
260                         else\r
261                                 switch (*i_str) {\r
262                                 case _T('a'):\r
263                                         *d++ = _T('\x07');\r
264                                         i_str ++;\r
265                                         break;\r
266                                         //case _T('b'): *d++ = _T('\b'); i_str ++; break;\r
267                                 case _T('e'):\r
268                                         *d++ = _T('\x1b');\r
269                                         i_str ++;\r
270                                         break;\r
271                                 case _T('f'):\r
272                                         *d++ = _T('\f');\r
273                                         i_str ++;\r
274                                         break;\r
275                                 case _T('n'):\r
276                                         *d++ = _T('\n');\r
277                                         i_str ++;\r
278                                         break;\r
279                                 case _T('r'):\r
280                                         *d++ = _T('\r');\r
281                                         i_str ++;\r
282                                         break;\r
283                                 case _T('t'):\r
284                                         *d++ = _T('\t');\r
285                                         i_str ++;\r
286                                         break;\r
287                                 case _T('v'):\r
288                                         *d++ = _T('\v');\r
289                                         i_str ++;\r
290                                         break;\r
291                                         //case _T('?'): *d++ = _T('\x7f'); i_str ++; break;\r
292                                         //case _T('_'): *d++ = _T(' '); i_str ++; break;\r
293                                         //case _T('\\'): *d++ = _T('\\'); i_str ++; break;\r
294                                 case _T('\''):\r
295                                         *d++ = _T('\'');\r
296                                         i_str ++;\r
297                                         break;\r
298                                 case _T('"'):\r
299                                         *d++ = _T('"');\r
300                                         i_str ++;\r
301                                         break;\r
302                                 case _T('\\'):\r
303                                         *d++ = _T('\\');\r
304                                         i_str ++;\r
305                                         break;\r
306                                 case _T('c'): // control code, for example '\c[' is escape: '\x1b'\r
307                                         i_str ++;\r
308                                         if (i_str < end && *i_str) {\r
309                                                 static const _TCHAR *ctrlchar =\r
310                                                         _T("@ABCDEFGHIJKLMNO")\r
311                                                         _T("PQRSTUVWXYZ[\\]^_")\r
312                                                         _T("@abcdefghijklmno")\r
313                                                         _T("pqrstuvwxyz@@@@?");\r
314                                                 static const _TCHAR *ctrlcode =\r
315                                                         _T("\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17")\r
316                                                         _T("\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37")\r
317                                                         _T("\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17")\r
318                                                         _T("\20\21\22\23\24\25\26\27\30\31\32\00\00\00\00\177");\r
319                                                 if (const _TCHAR *c = _tcschr(ctrlchar, *i_str))\r
320                                                         *d++ = ctrlcode[c - ctrlchar], i_str ++;\r
321                                         }\r
322                                         break;\r
323                                 case _T('x'):\r
324                                 case _T('X'): {\r
325                                         i_str ++;\r
326                                         static const _TCHAR *hexchar = _T("0123456789ABCDEFabcdef");\r
327                                         static int hexvalue[] = { 0, 1, 2, 3, 4, 5 ,6, 7, 8, 9,\r
328                                                                                           10, 11, 12, 13, 14, 15,\r
329                                                                                           10, 11, 12, 13, 14, 15,\r
330                                                                                         };\r
331                                         bool brace = false;\r
332                                         if (i_str < end && *i_str == _T('{')) {\r
333                                                 i_str ++;\r
334                                                 brace = true;\r
335                                         }\r
336                                         int n = 0;\r
337                                         for (; i_str < end && *i_str; i_str ++)\r
338                                                 if (const _TCHAR *c = _tcschr(hexchar, *i_str))\r
339                                                         n = n * 16 + hexvalue[c - hexchar];\r
340                                                 else\r
341                                                         break;\r
342                                         if (i_str < end && *i_str == _T('}') && brace)\r
343                                                 i_str ++;\r
344                                         if (0 < n)\r
345                                                 *d++ = static_cast<_TCHAR>(n);\r
346                                         break;\r
347                                 }\r
348                                 case _T('1'):\r
349                                 case _T('2'):\r
350                                 case _T('3'):\r
351                                 case _T('4'):\r
352                                 case _T('5'):\r
353                                 case _T('6'):\r
354                                 case _T('7'):\r
355                                         if (i_doesUseRegexpBackReference)\r
356                                                 goto case_default;\r
357                                         // fall through\r
358                                 case _T('0'): {\r
359                                         static const _TCHAR *octalchar = _T("01234567");\r
360                                         static int octalvalue[] = { 0, 1, 2, 3, 4, 5 ,6, 7, };\r
361                                         int n = 0;\r
362                                         for (; i_str < end && *i_str; i_str ++)\r
363                                                 if (const _TCHAR *c = _tcschr(octalchar, *i_str))\r
364                                                         n = n * 8 + octalvalue[c - octalchar];\r
365                                                 else\r
366                                                         break;\r
367                                         if (0 < n)\r
368                                                 *d++ = static_cast<_TCHAR>(n);\r
369                                         break;\r
370                                 }\r
371                                 default:\r
372 case_default:\r
373                                         *d++ = _T('\\');\r
374                                         if (_istlead(*i_str) && *(i_str + 1) && i_str + 1 < end)\r
375                                                 *d++ = *i_str++;\r
376                                         *d++ = *i_str++;\r
377                                         break;\r
378                                 }\r
379                 }\r
380         }\r
381         *d =_T('\0');\r
382         return result.get();\r
383 }\r
384 \r
385 \r
386 // add session id to i_str\r
387 tstring addSessionId(const _TCHAR *i_str)\r
388 {\r
389         DWORD sessionId;\r
390         tstring s(i_str);\r
391         if (ProcessIdToSessionId(GetCurrentProcessId(), &sessionId)) {\r
392                 _TCHAR buf[20];\r
393                 _sntprintf(buf, NUMBER_OF(buf), _T("%u"), sessionId);\r
394                 s += buf;\r
395         }\r
396         return s;\r
397 }\r
398 \r
399 \r
400 #ifdef _MBCS\r
401 // escape regexp special characters in MBCS trail bytes\r
402 std::string guardRegexpFromMbcs(const char *i_str)\r
403 {\r
404         size_t len = strlen(i_str);\r
405         Array<char> buf(len * 2 + 1);\r
406         char *p = buf.get();\r
407         while (*i_str) {\r
408                 if (_ismbblead(static_cast<u_char>(*i_str)) && i_str[1]) {\r
409                         *p ++ = *i_str ++;\r
410                         if (strchr(".*?+(){}[]^$", *i_str))\r
411                                 *p ++ = '\\';\r
412                 }\r
413                 *p ++ = *i_str ++;\r
414         }\r
415         return std::string(buf.get(), p);\r
416 }\r
417 #endif // !_MBCS\r
418 \r
419 \r
420 // converter\r
421 std::wstring to_wstring(const std::string &i_str)\r
422 {\r
423         size_t size = mbstowcs(NULL, i_str.c_str(), i_str.size() + 1);\r
424         if (size == (size_t)-1)\r
425                 return std::wstring();\r
426         Array<wchar_t> result(size + 1);\r
427         mbstowcs(result.get(), i_str.c_str(), i_str.size() + 1);\r
428         return std::wstring(result.get());\r
429 }\r
430 \r
431 \r
432 // converter\r
433 std::string to_string(const std::wstring &i_str)\r
434 {\r
435         size_t size = wcstombs(NULL, i_str.c_str(), i_str.size() + 1);\r
436         if (size == (size_t)-1)\r
437                 return std::string();\r
438         Array<char> result(size + 1);\r
439         wcstombs(result.get(), i_str.c_str(), i_str.size() + 1);\r
440         return std::string(result.get());\r
441 }\r
442 \r
443 \r
444 /// stream output\r
445 tostream &operator<<(tostream &i_ost, const tregex &i_data)\r
446 {\r
447         return i_ost << i_data.str();\r
448 }\r
449 \r
450 \r
451 /// get lower string\r
452 tstring toLower(const tstring &i_str)\r
453 {\r
454         tstring str(i_str);\r
455         for (size_t i = 0; i < str.size(); ++ i) {\r
456                 if (_ismbblead(str[i]))\r
457                         ++ i;\r
458                 else\r
459                         str[i] = tolower(str[i]);\r
460         }\r
461         return str;\r
462 }\r
463 \r
464 \r
465 // convert wstring to UTF-8\r
466 std::string to_UTF_8(const std::wstring &i_str)\r
467 {\r
468         // 0xxxxxxx: 00-7F\r
469         // 110xxxxx 10xxxxxx: 0080-07FF\r
470         // 1110xxxx 10xxxxxx 10xxxxxx: 0800 - FFFF\r
471 \r
472         int size = 0;\r
473 \r
474         // count needed buffer size\r
475         for (std::wstring::const_iterator i = i_str.begin(); i != i_str.end(); ++ i) {\r
476                 if (0x0000 <= *i && *i <= 0x007f)\r
477                         size += 1;\r
478                 else if (0x0080 <= *i && *i <= 0x07ff)\r
479                         size += 2;\r
480                 else if (0x0800 <= *i && *i <= 0xffff)\r
481                         size += 3;\r
482         }\r
483 \r
484         Array<char> result(size);\r
485         int ri = 0;\r
486 \r
487         // make UTF-8\r
488         for (std::wstring::const_iterator i = i_str.begin(); i != i_str.end(); ++ i) {\r
489                 if (0x0000 <= *i && *i <= 0x007f)\r
490                         result[ri ++] = static_cast<char>(*i);\r
491                 else if (0x0080 <= *i && *i <= 0x07ff) {\r
492                         result[ri ++] = static_cast<char>(((*i & 0x0fc0) >>  6) | 0xc0);\r
493                         result[ri ++] = static_cast<char>(( *i & 0x003f       ) | 0x80);\r
494                 } else if (0x0800 <= *i && *i <= 0xffff) {\r
495                         result[ri ++] = static_cast<char>(((*i & 0xf000) >> 12) | 0xe0);\r
496                         result[ri ++] = static_cast<char>(((*i & 0x0fc0) >>  6) | 0x80);\r
497                         result[ri ++] = static_cast<char>(( *i & 0x003f       ) | 0x80);\r
498                 }\r
499         }\r
500 \r
501         return std::string(result.begin(), result.end());\r
502 }\r