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.

414 lines
16 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/string/string_traits.hpp
  3. *
  4. * Purpose: string_traits traits class.
  5. *
  6. * Created: 16th January 2002
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2002-2009, 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/string_traits.hpp
  40. *
  41. * \brief [C++ only] Definition of the stlsoft::string_traits traits class
  42. * (\ref group__library__string "String" Library).
  43. */
  44. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS
  45. #define STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS
  46. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  47. # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TRAITS_MAJOR 4
  48. # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TRAITS_MINOR 0
  49. # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TRAITS_REVISION 4
  50. # define STLSOFT_VER_STLSOFT_STRING_HPP_STRING_TRAITS_EDIT 78
  51. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  52. /* /////////////////////////////////////////////////////////////////////////
  53. * Compatibility
  54. */
  55. /*
  56. [Incompatibilies-start]
  57. [Incompatibilies-end]
  58. */
  59. /* /////////////////////////////////////////////////////////////////////////
  60. * Includes
  61. */
  62. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  63. # include <stlsoft/stlsoft.h>
  64. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  65. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  66. # include <stlsoft/string/char_traits.hpp>
  67. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS */
  68. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS_FWD
  69. # include <stlsoft/string/string_traits_fwd.hpp>
  70. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS_FWD */
  71. #ifndef _STLSOFT_STRING_TRAITS_NO_STD_STRING
  72. # include <string>
  73. #endif /* _STLSOFT_STRING_TRAITS_NO_STD_STRING */
  74. #ifdef STLSOFT_UNITTEST
  75. # include <string>
  76. # include <stlsoft/meta/base_type_traits.hpp>
  77. #endif /* STLSOFT_UNITTEST */
  78. /* /////////////////////////////////////////////////////////////////////////
  79. * Namespace
  80. */
  81. #ifndef _STLSOFT_NO_NAMESPACE
  82. namespace stlsoft
  83. {
  84. #endif /* _STLSOFT_NO_NAMESPACE */
  85. /* /////////////////////////////////////////////////////////////////////////
  86. * Classes
  87. */
  88. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  89. /* C-style ANSI string */
  90. STLSOFT_TEMPLATE_SPECIALISATION
  91. struct string_traits<ss_char_a_t *>
  92. {
  93. typedef ss_char_a_t value_type;
  94. typedef ss_char_a_t char_type;
  95. typedef ss_size_t size_type;
  96. typedef char_type const const_char_type;
  97. typedef value_type const* string_type;
  98. typedef value_type* pointer;
  99. typedef value_type const* const_pointer;
  100. enum { is_pointer = true };
  101. enum { is_pointer_to_const = false };
  102. enum { char_type_size = int(sizeof(char_type)) };
  103. static string_type empty_string()
  104. {
  105. // This character array is initialised to 0, which conveniently happens to
  106. // be the empty string, by the module/application load, so it is
  107. // guaranteed to be valid, and there are no threading/race conditions
  108. static char_type s_empty[1];
  109. STLSOFT_ASSERT(s_empty[0] == '\0'); // Paranoid check
  110. return s_empty;
  111. }
  112. };
  113. STLSOFT_TEMPLATE_SPECIALISATION
  114. struct string_traits<ss_char_a_t const*>
  115. {
  116. typedef ss_char_a_t value_type;
  117. typedef ss_char_a_t char_type;
  118. typedef ss_size_t size_type;
  119. typedef char_type const const_char_type;
  120. typedef value_type const* string_type;
  121. typedef value_type* pointer;
  122. typedef value_type const* const_pointer;
  123. enum { is_pointer = true };
  124. enum { is_pointer_to_const = false };
  125. enum { char_type_size = int(sizeof(char_type)) };
  126. static string_type empty_string()
  127. {
  128. // This character array is initialised to 0, which conveniently happens to
  129. // be the empty string, by the module/application load, so it is
  130. // guaranteed to be valid, and there are no threading/race conditions
  131. static char_type s_empty[1];
  132. STLSOFT_ASSERT(s_empty[0] == '\0'); // Paranoid check
  133. return s_empty;
  134. }
  135. };
  136. # if 0
  137. # ifdef STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
  138. # if 1
  139. template <ss_size_t N>
  140. struct string_traits<ss_char_a_t const (&)[N]>
  141. : public string_traits<ss_char_a_t const*>
  142. {};
  143. template <ss_size_t N>
  144. struct string_traits<ss_char_a_t (&)[N]>
  145. : public string_traits<ss_char_a_t *>
  146. {};
  147. STLSOFT_TEMPLATE_SPECIALISATION
  148. struct string_traits<ss_char_a_t const []>
  149. : public string_traits<ss_char_a_t const*>
  150. {};
  151. STLSOFT_TEMPLATE_SPECIALISATION
  152. struct string_traits<ss_char_a_t []>
  153. : public string_traits<ss_char_a_t *>
  154. {};
  155. # else /* ? 0 */
  156. template <ss_typename_param_k C, ss_size_t N>
  157. struct string_traits<C (&)[N]>
  158. : public string_traits<C *>
  159. {
  160. typedef ss_char_a_t value_type;
  161. typedef ss_char_a_t char_type;
  162. typedef ss_size_t size_type;
  163. typedef char_type const const_char_type;
  164. typedef value_type const* string_type;
  165. typedef value_type* pointer;
  166. typedef value_type const* const_pointer;
  167. };
  168. template <ss_typename_param_k C, ss_size_t N>
  169. struct string_traits<C const (&)[N]>
  170. : public string_traits<C const*>
  171. {
  172. typedef ss_char_a_t value_type;
  173. typedef ss_char_a_t char_type;
  174. typedef ss_size_t size_type;
  175. typedef char_type const const_char_type;
  176. typedef value_type const* string_type;
  177. typedef value_type* pointer;
  178. typedef value_type const* const_pointer;
  179. };
  180. # endif /* 0 */
  181. # endif /* STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
  182. # endif /* 0 */
  183. /* C-style Unicode string */
  184. STLSOFT_TEMPLATE_SPECIALISATION
  185. struct string_traits<ss_char_w_t *>
  186. {
  187. typedef ss_char_w_t value_type;
  188. typedef ss_char_w_t char_type;
  189. typedef ss_size_t size_type;
  190. typedef char_type const const_char_type;
  191. typedef value_type const* string_type;
  192. typedef value_type* pointer;
  193. typedef value_type const* const_pointer;
  194. enum { is_pointer = true };
  195. enum { is_pointer_to_const = false };
  196. enum { char_type_size = int(sizeof(char_type)) };
  197. static string_type empty_string()
  198. {
  199. // This character array is initialised to 0, which conveniently happens to
  200. // be the empty string, by the module/application load, so it is
  201. // guaranteed to be valid, and there are no threading/race conditions
  202. static char_type s_empty[1];
  203. STLSOFT_ASSERT(s_empty[0] == '\0'); // Paranoid check
  204. return s_empty;
  205. }
  206. };
  207. STLSOFT_TEMPLATE_SPECIALISATION
  208. struct string_traits<ss_char_w_t const*>
  209. {
  210. typedef ss_char_w_t value_type;
  211. typedef ss_char_w_t char_type;
  212. typedef ss_size_t size_type;
  213. typedef char_type const const_char_type;
  214. typedef value_type const* string_type;
  215. typedef value_type* pointer;
  216. typedef value_type const* const_pointer;
  217. enum { is_pointer = true };
  218. enum { is_pointer_to_const = false };
  219. enum { char_type_size = int(sizeof(char_type)) };
  220. static string_type empty_string()
  221. {
  222. // This character array is initialised to 0, which conveniently happens to
  223. // be the empty string, by the module/application load, so it is
  224. // guaranteed to be valid, and there are no threading/race conditions
  225. static char_type s_empty[1];
  226. STLSOFT_ASSERT(s_empty[0] == '\0'); // Paranoid check
  227. return s_empty;
  228. }
  229. };
  230. /* std::basic_string */
  231. # ifndef _STLSOFT_STRING_TRAITS_NO_STD_STRING
  232. # ifdef STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
  233. template <ss_typename_param_k C>
  234. struct string_traits<stlsoft_ns_qual_std(basic_string)<C> >
  235. {
  236. // NOTE: Originally, what is string_type_ was defined as value_type, but
  237. // Borland objects to value_type::value_type.
  238. typedef stlsoft_ns_qual_std(basic_string)<C> string_type_;
  239. typedef ss_typename_type_k string_type_::value_type char_type;
  240. typedef ss_typename_type_k string_type_::size_type size_type;
  241. typedef char_type const const_char_type;
  242. typedef string_type_ string_type;
  243. typedef string_type_ value_type;
  244. typedef ss_typename_type_k string_type::pointer pointer;
  245. typedef ss_typename_type_k string_type::const_pointer const_pointer;
  246. typedef ss_typename_type_k string_type::iterator iterator;
  247. typedef ss_typename_type_k string_type::const_iterator const_iterator;
  248. typedef ss_typename_type_k string_type::reverse_iterator reverse_iterator;
  249. typedef ss_typename_type_k string_type::const_reverse_iterator const_reverse_iterator;
  250. enum { is_pointer = false };
  251. enum { is_pointer_to_const = false };
  252. enum { char_type_size = sizeof(char_type) };
  253. static string_type empty_string()
  254. {
  255. return string_type();
  256. }
  257. static string_type construct(string_type const& src, size_type pos, size_type len)
  258. {
  259. return string_type(src, pos, len);
  260. }
  261. # ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  262. template <ss_typename_param_k I>
  263. static string_type &assign_inplace(string_type& str, I first, I last)
  264. # else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  265. static string_type &assign_inplace(string_type& str, const_iterator first, const_iterator last)
  266. # endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  267. {
  268. // std::basic_string cannot assign in-place (or rather not all implementations do so)
  269. return (str = string_type(first, last), str);
  270. }
  271. };
  272. # else /* ? STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
  273. # if defined(STLSOFT_CF_std_NAMESPACE)
  274. STLSOFT_TEMPLATE_SPECIALISATION
  275. struct string_traits<stlsoft_ns_qual_std(basic_string)<ss_char_a_t> >
  276. {
  277. typedef stlsoft_ns_qual_std(basic_string)<ss_char_a_t> value_type;
  278. typedef value_type::value_type char_type;
  279. typedef value_type::size_type size_type;
  280. typedef char_type const const_char_type;
  281. typedef value_type string_type;
  282. typedef string_type::pointer pointer;
  283. typedef string_type::const_pointer const_pointer;
  284. typedef string_type::iterator iterator;
  285. typedef string_type::const_iterator const_iterator;
  286. typedef string_type::reverse_iterator reverse_iterator;
  287. typedef string_type::const_reverse_iterator const_reverse_iterator;
  288. enum { is_pointer = false };
  289. enum { is_pointer_to_const = false };
  290. enum { char_type_size = sizeof(char_type) };
  291. static string_type empty_string()
  292. {
  293. return string_type();
  294. }
  295. static string_type construct(string_type const& src, size_type pos, size_type len)
  296. {
  297. return string_type(src, pos, len);
  298. }
  299. # ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  300. template <ss_typename_param_k I>
  301. static string_type &assign_inplace(string_type& str, I first, I last)
  302. # else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  303. static string_type &assign_inplace(string_type& str, const_iterator first, const_iterator last)
  304. # endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  305. {
  306. // std::basic_string cannot assign in-place (or rather not all implementations do so)
  307. return (str = string_type(first, last), str);
  308. }
  309. };
  310. STLSOFT_TEMPLATE_SPECIALISATION
  311. struct string_traits<stlsoft_ns_qual_std(basic_string)<ss_char_w_t> >
  312. {
  313. typedef stlsoft_ns_qual_std(basic_string)<ss_char_w_t> value_type;
  314. typedef value_type::value_type char_type;
  315. typedef value_type::size_type size_type;
  316. typedef char_type const const_char_type;
  317. typedef value_type string_type;
  318. typedef string_type::pointer pointer;
  319. typedef string_type::const_pointer const_pointer;
  320. typedef string_type::iterator iterator;
  321. typedef string_type::const_iterator const_iterator;
  322. typedef string_type::reverse_iterator reverse_iterator;
  323. typedef string_type::const_reverse_iterator const_reverse_iterator;
  324. enum { is_pointer = false };
  325. enum { is_pointer_to_const = false };
  326. enum { char_type_size = sizeof(char_type) };
  327. static string_type empty_string()
  328. {
  329. return string_type();
  330. }
  331. static string_type construct(string_type const& src, size_type pos, size_type len)
  332. {
  333. return string_type(src, pos, len);
  334. }
  335. # ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  336. template <ss_typename_param_k I>
  337. static string_type &assign_inplace(string_type& str, I first, I last)
  338. # else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  339. static string_type &assign_inplace(string_type& str, const_iterator first, const_iterator last)
  340. # endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  341. {
  342. // std::basic_string cannot assign in-place (or rather not all implementations do so)
  343. return (str = string_type(first, last), str);
  344. }
  345. };
  346. # endif /* STLSOFT_CF_std_NAMESPACE */
  347. # endif /* STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT */
  348. # endif /* _STLSOFT_STRING_TRAITS_NO_STD_STRING */
  349. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  350. ////////////////////////////////////////////////////////////////////////////
  351. // Unit-testing
  352. #ifdef STLSOFT_UNITTEST
  353. # include "./unittest/string_traits_unittest_.h"
  354. #endif /* STLSOFT_UNITTEST */
  355. /* ////////////////////////////////////////////////////////////////////// */
  356. #ifndef _STLSOFT_NO_NAMESPACE
  357. } // namespace stlsoft
  358. #endif /* _STLSOFT_NO_NAMESPACE */
  359. /* ////////////////////////////////////////////////////////////////////// */
  360. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STRING_TRAITS */
  361. /* ///////////////////////////// end of file //////////////////////////// */