You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

543 lines
16 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/string/split_functions.hpp
  3. *
  4. * Purpose: String split functions.
  5. *
  6. * Created: 28th January 2005
  7. * Updated: 26th June 2012
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2005-2012, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file stlsoft/string/split_functions.hpp
  40. *
  41. * \brief [C++ only] String split functions
  42. * (\ref group__library__string "String" Library).
  43. */
  44. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS
  45. #define STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS
  46. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  47. # define STLSOFT_VER_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS_MAJOR 2
  48. # define STLSOFT_VER_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS_MINOR 3
  49. # define STLSOFT_VER_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS_REVISION 2
  50. # define STLSOFT_VER_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS_EDIT 42
  51. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  52. /* /////////////////////////////////////////////////////////////////////////
  53. * Compatibility
  54. */
  55. /*
  56. [Incompatibilies-start]
  57. STLSOFT_COMPILER_IS_BORLAND: __BORLANDC__<0x0564
  58. STLSOFT_COMPILER_IS_DMC: __DMC__<0x0844
  59. STLSOFT_COMPILER_IS_GCC: __GNUC__<3
  60. STLSOFT_COMPILER_IS_WATCOM:
  61. [Incompatibilies-end]
  62. */
  63. /* /////////////////////////////////////////////////////////////////////////
  64. * Includes
  65. */
  66. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  67. # include <stlsoft/stlsoft.h>
  68. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  69. #if ( defined(STLSOFT_COMPILER_IS_BORLAND) && \
  70. __BORLANDC__ < 0x0560) || \
  71. ( defined(STLSOFT_COMPILER_IS_DMC) && \
  72. __DMC__ < 0x0844) || \
  73. ( defined(STLSOFT_COMPILER_IS_GCC) && \
  74. __GNUC__ < 3) || \
  75. ( defined(STLSOFT_COMPILER_IS_MSVC) && \
  76. _MSC_VER < 1200) || \
  77. defined(STLSOFT_COMPILER_IS_SUNPRO)
  78. # define STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY
  79. #endif /* compiler */
  80. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  81. # include <stlsoft/shims/access/string.hpp>
  82. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  83. #ifndef STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY
  84. # ifndef STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_STATIC_ARRAY
  85. # include <stlsoft/containers/static_array.hpp>
  86. # endif /* !STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_STATIC_ARRAY */
  87. #else /* ? STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY */
  88. # include <vector>
  89. #endif /* STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY */
  90. #ifndef STLSOFT_INCL_ALGORITHM
  91. # define STLSOFT_INCL_ALGORITHM
  92. # include <algorithm>
  93. #endif /* !STLSOFT_INCL_ALGORITHM */
  94. #ifdef STLSOFT_UNITTEST
  95. # include <stlsoft/string/simple_string.hpp>
  96. #endif /* STLSOFT_UNITTEST */
  97. /* /////////////////////////////////////////////////////////////////////////
  98. * Namespace
  99. */
  100. #ifndef _STLSOFT_NO_NAMESPACE
  101. namespace stlsoft
  102. {
  103. #endif /* _STLSOFT_NO_NAMESPACE */
  104. /* /////////////////////////////////////////////////////////////////////////
  105. * Helper functions
  106. */
  107. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  108. STLSOFT_OPEN_WORKER_NS_(ximpl_split_functions)
  109. template< ss_typename_param_k S
  110. , ss_typename_param_k C /* = ss_typename_type_def_k S::value_type */
  111. >
  112. inline ss_bool_t split_impl(C const* s, ss_size_t n, C delim, S& s0, S& s1)
  113. {
  114. C const* const b = s;
  115. C const* const e = s + n;
  116. C const* it = stlsoft_ns_qual_std(find)(b, e, delim);
  117. s0 = S(b, it);
  118. return (e == it) ? false : (++it, s1 = S(it, e), true);
  119. }
  120. template< ss_typename_param_k S
  121. , ss_typename_param_k C /* = ss_typename_type_def_k S::value_type */
  122. >
  123. inline ss_uint_t split_impl(C const* s, ss_size_t cch, C delim, S& s0, S& s1, S& s2)
  124. {
  125. C const* const b = s;
  126. C const* const e = s + cch;
  127. C const* it0 = b;
  128. C const* it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  129. ss_uint_t n = it1 != it0;
  130. s0 = S(it0, it1);
  131. if(e != it1)
  132. {
  133. ++n;
  134. it0 = ++it1;
  135. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  136. }
  137. else
  138. {
  139. it0 = it1;
  140. }
  141. s1 = S(it0, it1);
  142. if(e != it1)
  143. {
  144. ++n;
  145. it0 = ++it1;
  146. it1 = e;
  147. }
  148. else
  149. {
  150. it0 = it1;
  151. }
  152. s2 = S(it0, it1);
  153. return n;
  154. }
  155. template< ss_typename_param_k S
  156. , ss_typename_param_k C /* = ss_typename_type_def_k S::value_type */
  157. >
  158. inline ss_uint_t split_impl(C const* s, ss_size_t cch, C delim, S& s0, S& s1, S& s2, S& s3)
  159. {
  160. C const* const b = s;
  161. C const* const e = s + cch;
  162. C const* it0 = b;
  163. C const* it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  164. ss_uint_t n = it1 != it0;
  165. s0 = S(it0, it1);
  166. if(e != it1)
  167. {
  168. ++n;
  169. it0 = ++it1;
  170. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  171. }
  172. else
  173. {
  174. it0 = it1;
  175. }
  176. s1 = S(it0, it1);
  177. if(e != it1)
  178. {
  179. ++n;
  180. it0 = ++it1;
  181. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  182. }
  183. else
  184. {
  185. it0 = it1;
  186. }
  187. s2 = S(it0, it1);
  188. if(e != it1)
  189. {
  190. ++n;
  191. it0 = ++it1;
  192. it1 = e;
  193. }
  194. else
  195. {
  196. it0 = it1;
  197. }
  198. s3 = S(it0, it1);
  199. return n;
  200. }
  201. template< ss_typename_param_k S
  202. , ss_typename_param_k C /* = ss_typename_type_def_k S::value_type */
  203. >
  204. inline ss_uint_t split_impl(C const* s, ss_size_t cch, C delim, S& s0, S& s1, S& s2, S& s3, S& s4)
  205. {
  206. C const* const b = s;
  207. C const* const e = s + cch;
  208. C const* it0 = b;
  209. C const* it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  210. ss_uint_t n = it1 != it0;
  211. s0 = S(it0, it1);
  212. if(e != it1)
  213. {
  214. ++n;
  215. it0 = ++it1;
  216. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  217. }
  218. else
  219. {
  220. it0 = it1;
  221. }
  222. s1 = S(it0, it1);
  223. if(e != it1)
  224. {
  225. ++n;
  226. it0 = ++it1;
  227. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  228. }
  229. else
  230. {
  231. it0 = it1;
  232. }
  233. s2 = S(it0, it1);
  234. if(e != it1)
  235. {
  236. ++n;
  237. it0 = ++it1;
  238. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  239. }
  240. else
  241. {
  242. it0 = it1;
  243. }
  244. s3 = S(it0, it1);
  245. if(e != it1)
  246. {
  247. ++n;
  248. it0 = ++it1;
  249. it1 = e;
  250. }
  251. else
  252. {
  253. it0 = it1;
  254. }
  255. s4 = S(it0, it1);
  256. return n;
  257. }
  258. template< ss_typename_param_k S
  259. , ss_typename_param_k C /* = ss_typename_type_def_k S::value_type */
  260. >
  261. inline ss_uint_t split_impl(C const* s, ss_size_t cch, C delim, S& s0, S& s1, S& s2, S& s3, S& s4, S& s5)
  262. {
  263. C const* const b = s;
  264. C const* const e = s + cch;
  265. C const* it0 = b;
  266. C const* it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  267. ss_uint_t n = it1 != it0;
  268. s0 = S(it0, it1);
  269. if(e != it1)
  270. {
  271. ++n;
  272. it0 = ++it1;
  273. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  274. }
  275. else
  276. {
  277. it0 = it1;
  278. }
  279. s1 = S(it0, it1);
  280. if(e != it1)
  281. {
  282. ++n;
  283. it0 = ++it1;
  284. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  285. }
  286. else
  287. {
  288. it0 = it1;
  289. }
  290. s2 = S(it0, it1);
  291. if(e != it1)
  292. {
  293. ++n;
  294. it0 = ++it1;
  295. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  296. }
  297. else
  298. {
  299. it0 = it1;
  300. }
  301. s3 = S(it0, it1);
  302. if(e != it1)
  303. {
  304. ++n;
  305. it0 = ++it1;
  306. it1 = stlsoft_ns_qual_std(find)(it0, e, delim);
  307. }
  308. else
  309. {
  310. it0 = it1;
  311. }
  312. s4 = S(it0, it1);
  313. if(e != it1)
  314. {
  315. ++n;
  316. it0 = ++it1;
  317. it1 = e;
  318. }
  319. else
  320. {
  321. it0 = it1;
  322. }
  323. s5 = S(it0, it1);
  324. return n;
  325. }
  326. STLSOFT_CLOSE_WORKER_NS_(ximpl_split_functions)
  327. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  328. /* /////////////////////////////////////////////////////////////////////////
  329. * Functions
  330. */
  331. /** Splits a string into two, at the first incidence of a delimiter
  332. *
  333. * \ingroup group__library__string
  334. *
  335. * \warn The behaviour is undefined if the string instance being split is
  336. * passed as one or both recipients
  337. */
  338. template< ss_typename_param_k S1
  339. , ss_typename_param_k S2
  340. , ss_typename_param_k C /* = ss_typename_type_def_k S2::value_type */
  341. >
  342. inline ss_bool_t split(S1 const& s, C delim, S2& s0, S2& s1)
  343. {
  344. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s0));
  345. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s1));
  346. return STLSOFT_WORKER_NS_QUAL_(ximpl_split_functions, split_impl)(c_str_data(s), c_str_len(s), delim, s0, s1);
  347. }
  348. /** Splits a string into three, at first two incidences of a delimiter
  349. *
  350. * \ingroup group__library__string
  351. *
  352. * \warn The behaviour is undefined if the string instance being split is
  353. * passed as one or both recipients
  354. */
  355. template< ss_typename_param_k S1
  356. , ss_typename_param_k S2
  357. , ss_typename_param_k C /* = ss_typename_type_def_k S2::value_type */
  358. >
  359. inline ss_uint_t split(S1 const& s, C delim, S2& s0, S2& s1, S2& s2)
  360. {
  361. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s0));
  362. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s1));
  363. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s2));
  364. return STLSOFT_WORKER_NS_QUAL_(ximpl_split_functions, split_impl)(c_str_data(s), c_str_len(s), delim, s0, s1, s2);
  365. }
  366. /** Splits a string into four, at first three incidences of a delimiter
  367. *
  368. * \ingroup group__library__string
  369. *
  370. * \warn The behaviour is undefined if the string instance being split is
  371. * passed as one or both recipients
  372. */
  373. template< ss_typename_param_k S1
  374. , ss_typename_param_k S2
  375. , ss_typename_param_k C /* = ss_typename_type_def_k S2::value_type */
  376. >
  377. inline ss_uint_t split(S1 const& s, C delim, S2& s0, S2& s1, S2& s2, S2& s3)
  378. {
  379. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s0));
  380. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s1));
  381. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s2));
  382. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s3));
  383. return STLSOFT_WORKER_NS_QUAL_(ximpl_split_functions, split_impl)(c_str_data(s), c_str_len(s), delim, s0, s1, s2, s3);
  384. }
  385. /** Splits a string into five, at first four incidences of a delimiter
  386. *
  387. * \ingroup group__library__string
  388. *
  389. * \warn The behaviour is undefined if the string instance being split is
  390. * passed as one or both recipients
  391. */
  392. template< ss_typename_param_k S1
  393. , ss_typename_param_k S2
  394. , ss_typename_param_k C /* = ss_typename_type_def_k S2::value_type */
  395. >
  396. inline ss_uint_t split(S1 const& s, C delim, S2& s0, S2& s1, S2& s2, S2& s3, S2& s4)
  397. {
  398. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s0));
  399. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s1));
  400. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s2));
  401. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s3));
  402. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s4));
  403. return STLSOFT_WORKER_NS_QUAL_(ximpl_split_functions, split_impl)(c_str_data(s), c_str_len(s), delim, s0, s1, s2, s3, s4);
  404. }
  405. /** Splits a string into six, at first five incidences of a delimiter
  406. *
  407. * \ingroup group__library__string
  408. *
  409. * \warn The behaviour is undefined if the string instance being split is
  410. * passed as one or both recipients
  411. */
  412. template< ss_typename_param_k S1
  413. , ss_typename_param_k S2
  414. , ss_typename_param_k C /* = ss_typename_type_def_k S2::value_type */
  415. >
  416. inline ss_uint_t split(S1 const& s, C delim, S2& s0, S2& s1, S2& s2, S2& s3, S2& s4, S2& s5)
  417. {
  418. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s0));
  419. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s1));
  420. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s2));
  421. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s3));
  422. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s4));
  423. STLSOFT_MESSAGE_ASSERT("Source string specified as recipient!", static_cast<void const*>(&s) != static_cast<void const*>(&s5));
  424. return STLSOFT_WORKER_NS_QUAL_(ximpl_split_functions, split_impl)(c_str_data(s), c_str_len(s), delim, s0, s1, s2, s3, s4, s5);
  425. }
  426. /** Splits a string into two, at the first incidence of a delimiter
  427. *
  428. * \ingroup group__library__string
  429. *
  430. */
  431. template< ss_typename_param_k S
  432. , ss_typename_param_k C /* = ss_typename_type_def_k S::value_type */
  433. >
  434. #ifndef STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY
  435. inline static_array_1d<S, 2>
  436. #else /* ? STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY */
  437. inline stlsoft_ns_qual_std_(vector)<S>
  438. #endif /* STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY */
  439. split(S const& s, C delim)
  440. {
  441. #ifndef STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY
  442. static_array_1d<S, 2> r;
  443. #else /* ? STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY */
  444. stlsoft_ns_qual_std_(vector)<S> r(2);
  445. #endif /* STLSOFT_STRING_SPLIT_FUNCTIONS_CANNOT_USE_STATIC_ARRAY */
  446. STLSOFT_WORKER_NS_QUAL_(ximpl_split_functions, split_impl)(c_str_data(s), c_str_len(s), delim, r[0], r[1]);
  447. return r;
  448. }
  449. ////////////////////////////////////////////////////////////////////////////
  450. // Unit-testing
  451. #ifdef STLSOFT_UNITTEST
  452. # include "./unittest/split_functions_unittest_.h"
  453. #endif /* STLSOFT_UNITTEST */
  454. /* ////////////////////////////////////////////////////////////////////// */
  455. #ifndef _STLSOFT_NO_NAMESPACE
  456. } // namespace stlsoft
  457. #endif /* _STLSOFT_NO_NAMESPACE */
  458. /* ////////////////////////////////////////////////////////////////////// */
  459. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SPLIT_FUNCTIONS */
  460. /* ///////////////////////////// end of file //////////////////////////// */