tchar.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // Generic algorithms for manipulating null-terminated character sequences
  2. //
  3. // Platform: ISO C++ 98/11
  4. // $Id$
  5. //
  6. // (c) __vic 2008
  7. #ifndef __VIC_TCHAR_H
  8. #define __VIC_TCHAR_H
  9. #include<__vic/defs.h>
  10. #include<string> // for char_traits
  11. #include<cstring>
  12. #include<cwchar>
  13. #if !__cpp_lambdas
  14. #include<functional>
  15. #endif
  16. namespace __vic { namespace tchar {
  17. //----------------------------------------------------------------------------
  18. // String length (generic strlen)
  19. //----------------------------------------------------------------------------
  20. template<class charT>
  21. inline size_t length(const charT *st)
  22. {
  23. return std::char_traits<charT>::length(st);
  24. }
  25. //----------------------------------------------------------------------------
  26. //----------------------------------------------------------------------------
  27. // Find end of sequence (pointer to null-terminator)
  28. //----------------------------------------------------------------------------
  29. template<class charT>
  30. const charT *end(const charT *st)
  31. {
  32. while(*st != charT()) st++;
  33. return st;
  34. }
  35. //----------------------------------------------------------------------------
  36. template<>
  37. inline const char *end(const char *st)
  38. {
  39. return std::strchr(st, '\x0');
  40. }
  41. //----------------------------------------------------------------------------
  42. template<>
  43. inline const wchar_t *end(const wchar_t *st)
  44. {
  45. return std::wcschr(st, L'\x0');
  46. }
  47. //----------------------------------------------------------------------------
  48. template<class charT>
  49. inline charT *end(charT *st)
  50. {
  51. return const_cast<charT*>(end(const_cast<const charT *>(st)));
  52. }
  53. //----------------------------------------------------------------------------
  54. //----------------------------------------------------------------------------
  55. // Compare strings (generic strcmp, wcscmp)
  56. //----------------------------------------------------------------------------
  57. template<class charT>
  58. inline int compare(const charT *s1, const charT *s2)
  59. {
  60. for(; *s1 && *s2; ++s1, ++s2)
  61. if(*s1 != *s2) return *s1 < *s2 ? -1 : 1;
  62. if(!*s1 && *s2) return -1; // s1 < s2
  63. if( *s1 && !*s2) return 1; // s1 > s2
  64. return 0; // s1 == s2
  65. }
  66. //----------------------------------------------------------------------------
  67. template<>
  68. inline int compare(const char *s1, const char *s2)
  69. {
  70. return std::strcmp(s1, s2);
  71. }
  72. //----------------------------------------------------------------------------
  73. template<>
  74. inline int compare(const wchar_t *s1, const wchar_t *s2)
  75. {
  76. return std::wcscmp(s1, s2);
  77. }
  78. //----------------------------------------------------------------------------
  79. //----------------------------------------------------------------------------
  80. // Copy string (generic strcpy, wcscpy)
  81. //----------------------------------------------------------------------------
  82. template<class charT>
  83. inline charT *copy(charT *dest, const charT *src, size_t n)
  84. {
  85. std::memcpy(dest, src, n*sizeof(charT));
  86. return dest;
  87. }
  88. //----------------------------------------------------------------------------
  89. template<class charT>
  90. inline charT *copy(charT *dest, const charT *src)
  91. {
  92. return copy(dest, src, length(src) + 1);
  93. }
  94. //----------------------------------------------------------------------------
  95. template<>
  96. inline char *copy(char *dest, const char *src)
  97. {
  98. return std::strcpy(dest, src);
  99. }
  100. //----------------------------------------------------------------------------
  101. template<>
  102. inline wchar_t *copy(wchar_t *dest, const wchar_t *src)
  103. {
  104. return std::wcscpy(dest, src);
  105. }
  106. //----------------------------------------------------------------------------
  107. //----------------------------------------------------------------------------
  108. // Move the string in memory (generic memmove)
  109. //----------------------------------------------------------------------------
  110. template<class charT>
  111. inline charT *move(charT *dest, const charT *src)
  112. {
  113. std::memmove(dest, src, (length(src) + 1) * sizeof(charT));
  114. return dest;
  115. }
  116. //----------------------------------------------------------------------------
  117. //----------------------------------------------------------------------------
  118. // Add a one string to another (generic strcat)
  119. //----------------------------------------------------------------------------
  120. template<class charT>
  121. charT *concat(charT *dest, const charT *src)
  122. {
  123. return copy(end(dest), src);
  124. }
  125. //----------------------------------------------------------------------------
  126. template<>
  127. inline char *concat(char *dest, const char *src)
  128. {
  129. return std::strcat(dest, src);
  130. }
  131. //----------------------------------------------------------------------------
  132. template<>
  133. inline wchar_t *concat(wchar_t *dest, const wchar_t *src)
  134. {
  135. return std::wcscat(dest, src);
  136. }
  137. //----------------------------------------------------------------------------
  138. //----------------------------------------------------------------------------
  139. // Find first character in a string that satisfies a specified condition
  140. //----------------------------------------------------------------------------
  141. template<class charT, class Pred>
  142. const charT *find_if(const charT *st, Pred pred)
  143. {
  144. for(; *st; st++)
  145. if(pred(*st)) return st;
  146. return nullptr;
  147. }
  148. //----------------------------------------------------------------------------
  149. template<class charT, class Pred>
  150. inline charT *find_if(charT *st, Pred pred)
  151. {
  152. return const_cast<charT*>(find_if(const_cast<const charT *>(st), pred));
  153. }
  154. //----------------------------------------------------------------------------
  155. //----------------------------------------------------------------------------
  156. // Find first character in a string that not satisfies a specified condition
  157. //----------------------------------------------------------------------------
  158. template<class charT, class Pred>
  159. const charT *find_if_not(const charT *st, Pred pred)
  160. {
  161. for(; *st; st++)
  162. if(!pred(*st)) return st;
  163. return nullptr;
  164. }
  165. //----------------------------------------------------------------------------
  166. template<class charT, class Pred>
  167. inline charT *find_if_not(charT *st, Pred pred)
  168. {
  169. return const_cast<charT*>(find_if_not(const_cast<const charT *>(st), pred));
  170. }
  171. //----------------------------------------------------------------------------
  172. //----------------------------------------------------------------------------
  173. // Find last character in a string that satisfies a specified condition
  174. //----------------------------------------------------------------------------
  175. template<class charT, class Pred>
  176. const charT *rfind_if(const charT *st, Pred pred)
  177. {
  178. for(const charT *p = end(st) - 1; p >= st; p--)
  179. if(pred(*p)) return p;
  180. return nullptr;
  181. }
  182. //----------------------------------------------------------------------------
  183. template<class charT, class Pred>
  184. inline charT *rfind_if(charT *st, Pred pred)
  185. {
  186. return const_cast<charT*>(rfind_if(const_cast<const charT *>(st), pred));
  187. }
  188. //----------------------------------------------------------------------------
  189. //----------------------------------------------------------------------------
  190. // Find last character in a string that not satisfies a specified condition
  191. //----------------------------------------------------------------------------
  192. template<class charT, class Pred>
  193. const charT *rfind_if_not(const charT *st, Pred pred)
  194. {
  195. for(const charT *p = end(st) - 1; p >= st; p--)
  196. if(!pred(*p)) return p;
  197. return nullptr;
  198. }
  199. //----------------------------------------------------------------------------
  200. template<class charT, class Pred>
  201. inline charT *rfind_if_not(charT *st, Pred pred)
  202. {
  203. return const_cast<charT*>(rfind_if_not(const_cast<const charT *>(st), pred));
  204. }
  205. //----------------------------------------------------------------------------
  206. //----------------------------------------------------------------------------
  207. // Find a first occurrence of char in string (generic strchr)
  208. //----------------------------------------------------------------------------
  209. template<class charT>
  210. inline const charT *find(const charT *st, charT ch)
  211. {
  212. return find_if(st,
  213. #if __cpp_lambdas
  214. [ch](charT c) { return c == ch; }
  215. #else
  216. std::bind2nd(std::equal_to<charT>(), ch)
  217. #endif
  218. );
  219. }
  220. //----------------------------------------------------------------------------
  221. template<>
  222. inline const char *find(const char *st, char ch)
  223. {
  224. return std::strchr(st,ch);
  225. }
  226. //----------------------------------------------------------------------------
  227. template<>
  228. inline const wchar_t *find(const wchar_t *st, wchar_t ch)
  229. {
  230. return std::wcschr(st,ch);
  231. }
  232. //----------------------------------------------------------------------------
  233. template<class charT>
  234. inline charT *find(charT *st, charT ch)
  235. {
  236. return const_cast<charT*>(find(const_cast<const charT *>(st), ch));
  237. }
  238. //----------------------------------------------------------------------------
  239. //----------------------------------------------------------------------------
  240. // Find a first occurrence of substring in string (generic strstr)
  241. //----------------------------------------------------------------------------
  242. template<class charT>
  243. const charT *find(const charT *st, const charT *sub)
  244. {
  245. for(; *st; st++)
  246. {
  247. if(*st == *sub)
  248. {
  249. const charT *p = st, *q = sub;
  250. while(*p && *q && *p != *q) p++, q++;
  251. if(*q == charT()) return st;
  252. }
  253. }
  254. return nullptr;
  255. }
  256. //----------------------------------------------------------------------------
  257. template<>
  258. inline const char *find(const char *st, const char *sub)
  259. {
  260. return std::strstr(st,sub);
  261. }
  262. //----------------------------------------------------------------------------
  263. template<>
  264. inline const wchar_t *find(const wchar_t *st, const wchar_t *sub)
  265. {
  266. return std::wcsstr(st,sub);
  267. }
  268. //----------------------------------------------------------------------------
  269. template<class charT>
  270. inline charT *find(charT *st, const charT *sub)
  271. {
  272. return const_cast<charT*>(find(const_cast<const charT *>(st), sub));
  273. }
  274. //----------------------------------------------------------------------------
  275. //----------------------------------------------------------------------------
  276. // Find a last occurrence of ch in string or NULL (generic strrchr)
  277. //----------------------------------------------------------------------------
  278. template<class charT>
  279. inline const charT *rfind(const charT *st, charT ch)
  280. {
  281. return rfind_if(st,
  282. #if __cpp_lambdas
  283. [ch](charT c) { return c == ch; }
  284. #else
  285. std::bind2nd(std::equal_to<charT>(), ch)
  286. #endif
  287. );
  288. }
  289. //----------------------------------------------------------------------------
  290. template<>
  291. inline const char *rfind(const char *st, char ch)
  292. {
  293. return std::strrchr(st,ch);
  294. }
  295. //----------------------------------------------------------------------------
  296. template<>
  297. inline const wchar_t *rfind(const wchar_t *st, wchar_t ch)
  298. {
  299. return std::wcsrchr(st,ch);
  300. }
  301. //----------------------------------------------------------------------------
  302. template<class charT>
  303. inline charT *rfind(charT *st, charT ch)
  304. {
  305. return const_cast<charT*>(rfind(const_cast<const charT *>(st), ch));
  306. }
  307. //----------------------------------------------------------------------------
  308. //----------------------------------------------------------------------------
  309. // Find a first occurrence of any character from
  310. // specified set in string (generic strpbrk)
  311. //----------------------------------------------------------------------------
  312. template<class charT>
  313. const charT *find_first_of(const charT *st, const charT *set)
  314. {
  315. for(; *st; st++)
  316. for(const charT *p = set; *p; p++) if(*st == *p) return st;
  317. return nullptr;
  318. }
  319. //----------------------------------------------------------------------------
  320. template<>
  321. inline const char *find_first_of(const char *st, const char *set)
  322. {
  323. return std::strpbrk(st, set);
  324. }
  325. //----------------------------------------------------------------------------
  326. template<>
  327. inline const wchar_t *find_first_of(const wchar_t *st, const wchar_t *set)
  328. {
  329. return std::wcspbrk(st, set);
  330. }
  331. //----------------------------------------------------------------------------
  332. template<class charT>
  333. inline charT *find_first_of(charT *st, const charT *set)
  334. {
  335. return const_cast<charT*>(find_first_of(const_cast<const charT *>(st), set));
  336. }
  337. //----------------------------------------------------------------------------
  338. //----------------------------------------------------------------------------
  339. // Find a first character in a string that does NOT belong
  340. // to a set (generic strspn, that returns pointer instead of index)
  341. //----------------------------------------------------------------------------
  342. template<class charT>
  343. const charT *find_first_not_of(const charT *st, const charT *set)
  344. {
  345. for(; *st; st++)
  346. for(const charT *p = set; *p; p++) if(*st != *p) return st;
  347. return nullptr;
  348. }
  349. //----------------------------------------------------------------------------
  350. template<>
  351. inline const char *find_first_not_of(const char *st, const char *set)
  352. {
  353. return st + std::strspn(st, set);
  354. }
  355. //----------------------------------------------------------------------------
  356. template<>
  357. inline const wchar_t *find_first_not_of(const wchar_t *st, const wchar_t *set)
  358. {
  359. return st + std::wcsspn(st, set);
  360. }
  361. //----------------------------------------------------------------------------
  362. template<class charT>
  363. inline charT *find_first_not_of(charT *st, const charT *set)
  364. {
  365. return const_cast<charT*>(find_first_not_of(const_cast<const charT *>(st), set));
  366. }
  367. //----------------------------------------------------------------------------
  368. //----------------------------------------------------------------------------
  369. // Find a last occurrence of any character from specified set in string
  370. //----------------------------------------------------------------------------
  371. template<class charT>
  372. const charT *find_last_of(const charT *st, const charT *set)
  373. {
  374. const charT *p = end(st) - 1;
  375. while(p >= st && !find(set, *p)) p--;
  376. return p >= st ? p : nullptr;
  377. }
  378. //----------------------------------------------------------------------------
  379. template<class charT>
  380. inline charT *find_last_of(charT *st, const charT *set)
  381. {
  382. return const_cast<charT*>(find_last_of(const_cast<const charT *>(st), set));
  383. }
  384. //----------------------------------------------------------------------------
  385. //----------------------------------------------------------------------------
  386. // Find a last character in a string that does NOT belong to a set
  387. //----------------------------------------------------------------------------
  388. template<class charT>
  389. const charT *find_last_not_of(const charT *st, const charT *set)
  390. {
  391. const charT *p = end(st) - 1;
  392. while(p >= st && find(set, *p)) p--;
  393. return p >= st ? p : nullptr;
  394. }
  395. //----------------------------------------------------------------------------
  396. template<class charT>
  397. inline charT *find_last_not_of(charT *st, const charT *set)
  398. {
  399. return const_cast<charT*>(find_last_not_of(const_cast<const charT *>(st), set));
  400. }
  401. //----------------------------------------------------------------------------
  402. //----------------------------------------------------------------------------
  403. // Skip all occurrences of the specified character at the begin of the string
  404. //----------------------------------------------------------------------------
  405. template<class charT>
  406. const charT *skip(const charT *p, charT ch)
  407. {
  408. while(*p && *p == ch) p++;
  409. return p;
  410. }
  411. //----------------------------------------------------------------------------
  412. template<class charT>
  413. charT *skip(charT *p, charT ch)
  414. {
  415. return const_cast<charT*>(skip(const_cast<const charT *>(p), ch));
  416. }
  417. //----------------------------------------------------------------------------
  418. }} // namespace
  419. #endif // header guard