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.

752 lines
25 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/string/char_traits.hpp
  3. *
  4. * Purpose: char_traits classes.
  5. *
  6. * Created: 19th November 1998
  7. * Updated: 11th January 2011
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 1998-2011, 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/char_traits.hpp
  40. *
  41. * \brief [C++ only] Definition of the stlsoft::stlsoft_char_traits and
  42. * stlsoft::stlsoft_char_traits_safe traits classes
  43. * (\ref group__library__string "String" Library).
  44. */
  45. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  46. #define STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define STLSOFT_VER_STLSOFT_STRING_HPP_CHAR_TRAITS_MAJOR 4
  49. # define STLSOFT_VER_STLSOFT_STRING_HPP_CHAR_TRAITS_MINOR 0
  50. # define STLSOFT_VER_STLSOFT_STRING_HPP_CHAR_TRAITS_REVISION 3
  51. # define STLSOFT_VER_STLSOFT_STRING_HPP_CHAR_TRAITS_EDIT 71
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. *
  56. * There is a degree of complexity with respect to the definition and use of
  57. * char_traits in the STLSoft libraries, depending on whether the std and/or
  58. * stlsoft namespaces are defined.
  59. *
  60. * 1. If neither std nor stlsoft namespaces are defined, then the standard
  61. * library char_traits is visible in the global namespace, and no definition is
  62. * provided in the stlsoft namespace. This is necessary to avoid a clash.
  63. *
  64. * 2. If std is defined, and the stlsoft namespace is not defined, then the
  65. * STLSoft definition of char_traits is provided, and exists in the global
  66. * namespace.
  67. *
  68. * 3. If std is not defined, and the stlsoft namespace is defined, then the
  69. * STLSoft definition of char_traits is provided, and exists in the stlsoft
  70. * namespace.
  71. *
  72. * 4. If both std and stlsoft namespaces are not defined, then the
  73. * STLSoft definition of char_traits is provided, and exists in the stlsoft
  74. * namespace.
  75. *
  76. * Also influencing this is whether the compiler/std-library actually provide
  77. * a char_traits type. GCC 2.95 does not. Presence of this is indicated by the
  78. * definition of STLSOFT_CF_std_char_traits_AVAILABLE
  79. *
  80. * Finally, DMC++ has a problem whereby, with the SGI libs, the specialisation
  81. * of char_traits in the global namespace clashes with stlsoft::char_traits<>.
  82. * This is a combination compiler/library bug, so the only thing we can do is
  83. * indicate to the STLSoft libs that ("std::")char_traits is unavailable, and
  84. * "use" the standard library one.
  85. */
  86. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  87. # include <stlsoft/stlsoft.h>
  88. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  89. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_SIGN_TRAITS
  90. # include <stlsoft/util/sign_traits.hpp>
  91. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_SIGN_TRAITS */
  92. #if defined(STLSOFT_CF_std_char_traits_AVAILABLE) && \
  93. defined(_STLSOFT_NO_NAMESPACE) && \
  94. !defined(STLSOFT_CF_std_NAMESPACE)
  95. # include <string> // for std::char_traits
  96. #elif defined(STLSOFT_COMPILER_IS_DMC) && \
  97. !defined(STLSOFT_CF_std_NAMESPACE)
  98. # include <string> // for std::char_traits
  99. #endif /* !::stlsoft && !::std */
  100. #if !defined(STLSOFT_NO_CHAR_TRAITS_LIBRARY_CALLS) || \
  101. defined(_DEBUG)
  102. # include <string.h>
  103. # include <wchar.h>
  104. # if defined(STLSOFT_COMPILER_IS_BORLAND) && \
  105. __BORLANDC__ >= 0x0560
  106. # include <mem.h>
  107. #endif /* compiler */
  108. #endif /* !STLSOFT_NO_CHAR_TRAITS_LIBRARY_CALLS || _DEBUG */
  109. /* /////////////////////////////////////////////////////////////////////////
  110. * Namespace
  111. */
  112. #ifndef _STLSOFT_NO_NAMESPACE
  113. namespace stlsoft
  114. {
  115. #endif /* _STLSOFT_NO_NAMESPACE */
  116. /* /////////////////////////////////////////////////////////////////////////
  117. * Constraints
  118. */
  119. // class stlsoft_char_traits
  120. /** \brief Character traits
  121. *
  122. * \param C The character type
  123. * \param N The integer type
  124. * \param Z The size type
  125. *
  126. * \ingroup group__library__string
  127. */
  128. template< ss_typename_param_k C
  129. >
  130. struct stlsoft_char_traits
  131. {
  132. public:
  133. /// The char type
  134. typedef C char_type;
  135. /// The current parameterisation of the type
  136. typedef stlsoft_char_traits<C> class_type;
  137. /// The integer type
  138. typedef ss_int_t int_type;
  139. /// The size type
  140. typedef ss_size_t size_type;
  141. /// The position type
  142. typedef ss_streampos_t pos_type;
  143. /// The offset type
  144. typedef ss_streamoff_t off_type;
  145. public:
  146. /// Assigns \c rhs to \c lhs
  147. static void assign(char_type &lhs, char_type const& rhs)
  148. {
  149. lhs = rhs;
  150. }
  151. /// Assigns \c cch characters of value \c c to \c dest
  152. static char_type* assign(char_type* dest, size_type cch, char_type const& c)
  153. {
  154. char_type* ret;
  155. STLSOFT_MESSAGE_ASSERT("char_traits<X>::assign called with NULL destination", (0 == cch || NULL != dest));
  156. for(ret = dest; 0 < cch; --cch, ++dest)
  157. {
  158. assign(*dest, c);
  159. }
  160. return ret;
  161. }
  162. /// Evaluates whether \c lhs is equivalent to \c rhs
  163. static ss_bool_t eq(char_type const& lhs, char_type const& rhs)
  164. {
  165. return lhs == rhs;
  166. }
  167. /// Evaluates whether \c lhs is less than \c rhs
  168. static ss_bool_t lt(char_type const& lhs, char_type const& rhs)
  169. {
  170. return lhs < rhs;
  171. }
  172. /// Compares \c cch characters of \c s1 with \c s2
  173. ///
  174. /// \param s1 The first string to compare
  175. /// \param s2 The second string to compare
  176. /// \param cch The number of characters to compare \c s1 with \c s2
  177. ///
  178. /// \retval <0 s1 is lexicographically less than s2
  179. /// \retval 0 s1 is lexicographically equal to s2
  180. /// \retval >0 s1 is lexicographically more than s2
  181. static int_type compare(char_type const* s1, char_type const* s2, size_type cch)
  182. {
  183. STLSOFT_MESSAGE_ASSERT("char_traits<X>::compare called with NULL string", (0 == cch || NULL != s1));
  184. STLSOFT_MESSAGE_ASSERT("char_traits<X>::compare called with NULL string", (0 == cch || NULL != s2));
  185. for(size_type n = 0; n < cch; ++n, ++s1, ++s2)
  186. {
  187. if(!eq(*s1, *s2))
  188. {
  189. return lt(*s1, *s2) ? -1 : +1;
  190. }
  191. }
  192. return 0;
  193. }
  194. static int_type compare_max(char_type const* s1, char_type const* s2, size_type cch)
  195. {
  196. STLSOFT_MESSAGE_ASSERT("char_traits<X>::compare_max called with NULL string", (0 == cch || NULL != s1));
  197. STLSOFT_MESSAGE_ASSERT("char_traits<X>::compare_max called with NULL string", (0 == cch || NULL != s2));
  198. for(size_type n = 0; n < cch; ++n, ++s1, ++s2)
  199. {
  200. if(!eq(*s1, *s2))
  201. {
  202. return lt(*s1, *s2) ? -1 : +1;
  203. }
  204. else if(eq(*s1, char_type(0)))
  205. {
  206. break;
  207. }
  208. }
  209. return 0;
  210. }
  211. /// Compares, using compare(), \c s1 with \c s2, either or both of which may be \c null
  212. static int_type compare_null(char_type const* s1, char_type const* s2, size_type cch)
  213. {
  214. int_type result;
  215. if(NULL == s1)
  216. {
  217. result = (NULL == s2) ? 0 : -1;
  218. }
  219. else
  220. {
  221. result = (NULL == s2) ? 1 : compare(s1, s2, cch);
  222. }
  223. return result;
  224. }
  225. /// Compares, using compare_max(), \c s1 with \c s2, either or both of which may be \c null
  226. static int_type compare_maxnull(char_type const* s1, char_type const* s2, size_type cch)
  227. {
  228. int_type result;
  229. if(NULL == s1)
  230. {
  231. result = (NULL == s2) ? 0 : -1;
  232. }
  233. else
  234. {
  235. result = (NULL == s2) ? 1 : compare_max(s1, s2, cch);
  236. }
  237. return result;
  238. }
  239. /// Evaluates the length of the string \c s
  240. static size_type length(char_type const* s)
  241. {
  242. size_type cch;
  243. STLSOFT_MESSAGE_ASSERT("char_traits<X>::length called with NULL string", NULL != s);
  244. for(cch = 0; !eq(*s, char_type(0)); ++s)
  245. {
  246. ++cch;
  247. }
  248. return cch;
  249. }
  250. /// Evaluates the length of the string \c s, which may be \c null
  251. static size_type length_null(char_type const* s)
  252. {
  253. return (NULL != s) ? length(s) : 0;
  254. }
  255. /// Evaluates the length of the string \c s up to a given number of characters
  256. ///
  257. /// \param s The string to be evaluated. It may <b>not</b> be null
  258. /// \param limit The maximum number of characters to evaluate
  259. /// \return The length of the string (in characters) not including the null-terminator
  260. static size_type length_max(char_type const* s, size_type limit)
  261. {
  262. size_type cch;
  263. STLSOFT_MESSAGE_ASSERT("char_traits<X>::length_max called with NULL string", NULL != s);
  264. for(cch = 0; cch < limit && !eq(*s, char_type(0)); ++s)
  265. {
  266. ++cch;
  267. }
  268. return cch;
  269. }
  270. /// Evaluates the length of the string \c s, which may be \c null, up to a given number of characters
  271. ///
  272. /// \param s The string to be evaluated. It may be null
  273. /// \param limit The maximum number of characters to evaluate
  274. /// \return The length of the string (in characters) not including the null-terminator
  275. static size_type length_max_null(char_type const* s, size_type limit)
  276. {
  277. return (NULL != s) ? length_max(s, limit) : 0;
  278. }
  279. /// Copies \c cch characters from \c src to \c dest
  280. static char_type* copy(char_type* dest, char_type const* src, size_type cch)
  281. {
  282. char_type* ret;
  283. STLSOFT_MESSAGE_ASSERT("char_traits<X>::copy called with NULL destination", (0 == cch || NULL != dest));
  284. STLSOFT_MESSAGE_ASSERT("char_traits<X>::copy called with NULL source", (0 == cch || NULL != src));
  285. #ifdef _DEBUG
  286. ::memset(dest, 0, cch * sizeof(char_type));
  287. #endif /* _DEBUG */
  288. for(ret = dest; 0 < cch; --cch, ++dest, ++src)
  289. {
  290. assign(*dest, *src);
  291. }
  292. return ret;
  293. }
  294. /// Copies \c cch characters from \c src to \c dest, accounting for whether the ranges overlap
  295. static char_type* move(char_type* dest, char_type const* src, size_type cch)
  296. {
  297. char_type* const ret = dest;
  298. STLSOFT_MESSAGE_ASSERT("char_traits<X>::move called with NULL destination", (0 == cch || NULL != dest));
  299. STLSOFT_MESSAGE_ASSERT("char_traits<X>::move called with NULL source", (0 == cch || NULL != src));
  300. if( src < dest &&
  301. dest < src + cch)
  302. {
  303. for(dest += cch, src += cch; 0 < cch; --cch)
  304. {
  305. assign(*--dest, *--src);
  306. }
  307. }
  308. else
  309. {
  310. for(; 0 < cch; --cch, ++dest, ++src)
  311. {
  312. assign(*dest, *src);
  313. }
  314. }
  315. return ret;
  316. }
  317. /// Finds the first \c c in \c cch elements in \c s, or \c NULL if not found
  318. static char_type const* find(char_type const* s, size_type cch, char_type const& c)
  319. {
  320. STLSOFT_MESSAGE_ASSERT("char_traits<X>::find called with NULL string", (0 == cch || NULL != s));
  321. for(; 0 < cch; --cch, ++s)
  322. {
  323. if(eq(*s, c))
  324. {
  325. break;
  326. }
  327. }
  328. return (0 < cch) ? s : NULL;
  329. }
  330. /// Represents the character \c in the character type \c char_type
  331. static char_type to_char_type(int_type const& c)
  332. {
  333. return static_cast<char_type>(c);
  334. }
  335. /// Represents the character \c in the integer type \c int_type
  336. static int_type to_int_type(char_type const& c)
  337. {
  338. #if defined(STLSOFT_COMPILER_IS_WATCOM)
  339. return (int_type)(c);
  340. #else /* ? compiler */
  341. return static_cast<int_type>(static_cast<ss_typename_type_k sign_traits<char_type>::unsigned_type>(c));
  342. #endif /* compiler */
  343. }
  344. /// Evaluates whether \c lhs and \c rhs are equivalent
  345. static ss_bool_t eq_int_type(int_type const& lhs, int_type const& rhs)
  346. {
  347. return lhs == rhs;
  348. }
  349. /// Returns the value representing the end-of-file.
  350. static int_type eof()
  351. {
  352. return static_cast<int_type>(-1);
  353. }
  354. /// Evaluates whether the given character is the end-of-file.
  355. static int_type not_eof(int_type const& c)
  356. {
  357. return (c != eof() ? c : !eof());
  358. }
  359. };
  360. // class stlsoft_char_traits_safe
  361. /** \brief Character traits, all of the operations of which can work with null pointers
  362. *
  363. * \param C The character type
  364. * \param N The integer type
  365. * \param Z The size type
  366. *
  367. * \ingroup group__library__string
  368. */
  369. template< ss_typename_param_k C
  370. >
  371. struct stlsoft_char_traits_safe
  372. : private stlsoft_char_traits<C>
  373. {
  374. private:
  375. typedef stlsoft_char_traits<C> parent_class_type;
  376. public:
  377. /// The character type
  378. typedef C char_type;
  379. /// The current parameterisation of the type
  380. typedef stlsoft_char_traits_safe<C> class_type;
  381. /// The integer type
  382. typedef ss_int_t int_type;
  383. /// The size type
  384. typedef ss_size_t size_type;
  385. /// The position type
  386. typedef ss_streampos_t pos_type;
  387. /// The offset type
  388. typedef ss_streamoff_t off_type;
  389. public:
  390. /// Assigns \c rhs to \c lhs
  391. static void assign(char_type &lhs, char_type const& rhs)
  392. {
  393. parent_class_type::assign(lhs, rhs);
  394. }
  395. /// Assigns \c cch characters of value \c c to \c dest
  396. static char_type* assign(char_type* dest, size_type cch, char_type const& c)
  397. {
  398. STLSOFT_MESSAGE_ASSERT("char_traits_safe<X>::assign called with NULL destination", NULL != dest);
  399. return parent_class_type::assign(dest, cch, c);
  400. }
  401. /// Evaluates whether \c lhs is equivalent to \c rhs
  402. static ss_bool_t eq(char_type const& lhs, char_type const& rhs)
  403. {
  404. return parent_class_type::eq(lhs, rhs);
  405. }
  406. /// Evaluates whether \c lhs is less than \c rhs
  407. static ss_bool_t lt(char_type const& lhs, char_type const& rhs)
  408. {
  409. return parent_class_type::lt(lhs, rhs);
  410. }
  411. /// Compares \c cch characters of \c s1 with \c s2
  412. ///
  413. /// \param s1 The first string to compare
  414. /// \param s2 The second string to compare
  415. /// \param cch The number of characters to compare \c s1 with \c s2
  416. ///
  417. /// \retval <0 s1 is lexicographically less than s2
  418. /// \retval 0 s1 is lexicographically equal to s2
  419. /// \retval >0 s1 is lexicographically more than s2
  420. static int_type compare(char_type const* s1, char_type const* s2, size_type cch)
  421. {
  422. return compare_null(s1, s2, cch);
  423. }
  424. static int_type compare_max(char_type const* s1, char_type const* s2, size_type cch)
  425. {
  426. return compare_maxnull(s1, s2, cch);
  427. }
  428. /// Compares, using compare(), \c s1 with \c s2, either or both of which may be \c null
  429. static int_type compare_null(char_type const* s1, char_type const* s2, size_type cch)
  430. {
  431. return parent_class_type::compare(s1, s2, cch);
  432. }
  433. /// Compares, using compare_max(), \c s1 with \c s2, either or both of which may be \c null
  434. static int_type compare_maxnull(char_type const* s1, char_type const* s2, size_type cch)
  435. {
  436. return parent_class_type::compare_maxnull(s1, s2, cch);
  437. }
  438. /// Evaluates the length of the string \c s up to a given number of characters
  439. ///
  440. /// \param s The string to be evaluated. It may be null
  441. /// \param limit The maximum number of characters to evaluate
  442. /// \return The length of the string (in characters) not including the null-terminator
  443. static size_type length_max_null(char_type const* s, size_type limit)
  444. {
  445. return (NULL == s) ? 0 : parent_class_type::length_max(s, limit);
  446. }
  447. /// Evaluates the length of the string \c s, which may be \c null, up to a given number of characters
  448. ///
  449. /// \param s The string to be evaluated. It may be null
  450. /// \param limit The maximum number of characters to evaluate
  451. /// \return The length of the string (in characters) not including the null-terminator
  452. static size_type length_max(char_type const* s, size_type limit)
  453. {
  454. return length_max_null(s, limit);
  455. }
  456. /// Evaluates the length of the string \c s, which may be \c null
  457. static size_type length_null(char_type const* s)
  458. {
  459. return (NULL == s) ? 0 : parent_class_type::length(s);
  460. }
  461. /// Evaluates the length of the string \c s
  462. static size_type length(char_type const* s)
  463. {
  464. return length_null(s);
  465. }
  466. /// Copies \c cch characters from \c src to \c dest
  467. static char_type* copy(char_type* dest, char_type const* src, size_type cch)
  468. {
  469. STLSOFT_MESSAGE_ASSERT("char_traits_safe<X>::copy called with NULL destination", NULL != dest);
  470. STLSOFT_MESSAGE_ASSERT("char_traits_safe<X>::copy called with NULL source", NULL != src);
  471. return parent_class_type::copy(dest, src, cch);
  472. }
  473. /// Copies \c cch characters from \c src to \c dest, accounting for whether the ranges overlap
  474. static char_type* move(char_type* dest, char_type const* src, size_type cch)
  475. {
  476. STLSOFT_MESSAGE_ASSERT("char_traits_safe<X>::move called with NULL destination", NULL != dest);
  477. STLSOFT_MESSAGE_ASSERT("char_traits_safe<X>::move called with NULL source", NULL != src);
  478. return parent_class_type::move(dest, src, cch);
  479. }
  480. /// Finds the first \c c in \c cch elements in \c s, or \c NULL if not found
  481. static char_type const* find(char_type const* s, size_type cch, char_type const& c)
  482. {
  483. return (NULL == s) ? NULL : parent_class_type::find(s, cch, c);
  484. }
  485. /// Represents the character \c in the character type \c char_type
  486. static char_type to_char_type(int_type const& c)
  487. {
  488. return parent_class_type::to_char_type(c);
  489. }
  490. /// Represents the character \c in the integer type \c int_type
  491. static int_type to_int_type(char_type const& c)
  492. {
  493. return parent_class_type::to_int_type(c);
  494. }
  495. /// Evaluates whether \c lhs and \c rhs are equivalent
  496. static ss_bool_t eq_int_type(int_type const& lhs, int_type const& rhs)
  497. {
  498. return parent_class_type::eq_int_type(lhs, rhs);
  499. }
  500. /// Returns the value representing the end-of-file.
  501. static int_type eof()
  502. {
  503. return parent_class_type::eof();
  504. }
  505. /// Evaluates whether the given character is the end-of-file.
  506. static int_type not_eof(int_type const& c)
  507. {
  508. return parent_class_type::not_eof();
  509. }
  510. };
  511. // class char_traits
  512. /** \brief Character traits, all of the operations of which can work with null pointers
  513. *
  514. * \param C The character type
  515. * \param N The integer type
  516. * \param Z The size type
  517. *
  518. * \ingroup group__library__string
  519. */
  520. /* DMC++ special handling */
  521. #if defined(STLSOFT_COMPILER_IS_DMC) && /* compiler is DMC++ */ \
  522. !defined(STLSOFT_CF_std_NAMESPACE) /* std namespace is not defined */
  523. # if !defined(__SGI_STL_STRING_FWD_H)
  524. # error Unexpected
  525. # endif /* !__SGI_STL_STRING_FWD_H */
  526. # if !defined(__SGI_STL_CHAR_TRAITS_H)
  527. # error Unexpected
  528. # endif /* !__SGI_STL_CHAR_TRAITS_H */
  529. using ::char_traits;
  530. #else /* ? comp/lib */
  531. /* We only define (stlsoft::)char_traits if no std::char_traits is available, or
  532. * the stlsoft namespace is defined, or the std namespace is defined.
  533. */
  534. #if !defined(STLSOFT_CF_std_char_traits_AVAILABLE) || /* std does not define char_traits */ \
  535. !defined(_STLSOFT_NO_NAMESPACE) || /* stlsoft namespace is defined */ \
  536. defined(STLSOFT_CF_std_NAMESPACE)
  537. template< ss_typename_param_k C
  538. >
  539. struct char_traits
  540. : public stlsoft_char_traits<C>
  541. {
  542. typedef stlsoft_char_traits<C> parent_class_type;
  543. public:
  544. /// The current parameterisation of the type
  545. typedef char_traits<C> class_type;
  546. /// The character type
  547. typedef ss_typename_type_k parent_class_type::char_type char_type;
  548. typedef ss_typename_type_k parent_class_type::int_type int_type;
  549. typedef ss_typename_type_k parent_class_type::size_type size_type;
  550. typedef ss_typename_type_k parent_class_type::pos_type pos_type;
  551. typedef ss_typename_type_k parent_class_type::off_type off_type;
  552. };
  553. # endif /* !::stlsoft && !::std */
  554. #endif /* comp/lib */
  555. // class char_traits_safe
  556. /** \brief Character traits, all of the operations of which can work with null pointers
  557. *
  558. * \param C The character type
  559. * \param N The integer type
  560. * \param Z The size type
  561. *
  562. * \ingroup group__library__string
  563. */
  564. template< ss_typename_param_k C
  565. >
  566. struct char_traits_safe
  567. : public stlsoft_char_traits_safe<C>
  568. {
  569. typedef stlsoft_char_traits_safe<C> parent_class_type;
  570. public:
  571. /// The current parameterisation of the type
  572. typedef char_traits_safe<C> class_type;
  573. /// The character type
  574. typedef ss_typename_type_k parent_class_type::char_type char_type;
  575. typedef ss_typename_type_k parent_class_type::int_type int_type;
  576. typedef ss_typename_type_k parent_class_type::size_type size_type;
  577. typedef ss_typename_type_k parent_class_type::pos_type pos_type;
  578. typedef ss_typename_type_k parent_class_type::off_type off_type;
  579. };
  580. /* /////////////////////////////////////////////////////////////////////////
  581. * Specialisations
  582. */
  583. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  584. #if !defined(STLSOFT_NO_CHAR_TRAITS_LIBRARY_CALLS) && \
  585. !defined(STLSOFT_COMPILER_IS_DMC) && \
  586. ( !defined(STLSOFT_COMPILER_IS_MSVC) || \
  587. _MSC_VER >= 1100) && \
  588. !defined(STLSOFT_COMPILER_IS_VECTORC) && \
  589. !defined(STLSOFT_COMPILER_IS_WATCOM)
  590. /* char */
  591. STLSOFT_TEMPLATE_SPECIALISATION
  592. inline char* stlsoft_char_traits<char>::assign(char* dest, ss_size_t cch, char const& c)
  593. {
  594. return static_cast<char*>(::memset(dest, c, cch * sizeof(char)));
  595. }
  596. STLSOFT_TEMPLATE_SPECIALISATION
  597. inline ss_int_t stlsoft_char_traits<char>::compare(char_type const* s1, char_type const* s2, ss_size_t cch)
  598. {
  599. return ::memcmp(s1, s2, cch);
  600. }
  601. STLSOFT_TEMPLATE_SPECIALISATION
  602. inline char const* stlsoft_char_traits<char>::find(char_type const* s, size_type cch, char_type const& c)
  603. {
  604. #if defined(STLSOFT_COMPILER_IS_BORLAND) && \
  605. __BORLANDC__ < 0x0560
  606. return static_cast<char const*>(memchr(s, c, cch));
  607. #else /* ? compiler */
  608. void const *p = ::memchr(s, c, cch);
  609. return static_cast<char const*>(p);
  610. #endif /* compiler */
  611. }
  612. STLSOFT_TEMPLATE_SPECIALISATION
  613. inline char* stlsoft_char_traits<char>::copy(char* dest, char const* src, ss_size_t cch)
  614. {
  615. #ifdef _DEBUG
  616. ::memset(dest, 0, cch * sizeof(char));
  617. #endif /* _DEBUG */
  618. return static_cast<char*>(memcpy(dest, src, cch * sizeof(char)));
  619. }
  620. STLSOFT_TEMPLATE_SPECIALISATION
  621. inline ss_size_t stlsoft_char_traits<char>::length(char const* s)
  622. {
  623. return ::strlen(s);
  624. }
  625. /* wchar_t */
  626. STLSOFT_TEMPLATE_SPECIALISATION
  627. inline ss_size_t stlsoft_char_traits<wchar_t>::length(wchar_t const* s)
  628. {
  629. return ::wcslen(s);
  630. }
  631. #endif /* !STLSOFT_NO_CHAR_TRAITS_LIBRARY_CALLS && !STLSOFT_COMPILER_IS_DMC */
  632. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  633. ////////////////////////////////////////////////////////////////////////////
  634. // Unit-testing
  635. #ifdef STLSOFT_UNITTEST
  636. # include "./unittest/char_traits_unittest_.h"
  637. #endif /* STLSOFT_UNITTEST */
  638. /* ////////////////////////////////////////////////////////////////////// */
  639. #ifndef _STLSOFT_NO_NAMESPACE
  640. } // namespace stlsoft
  641. #endif /* _STLSOFT_NO_NAMESPACE */
  642. /* ////////////////////////////////////////////////////////////////////// */
  643. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS */
  644. /* ///////////////////////////// end of file //////////////////////////// */