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.

1008 lines
32 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/string/special_string_instance.hpp
  3. *
  4. * Purpose: Special string instance class template.
  5. *
  6. * Created: 3rd June 2006
  7. * Updated: 19th May 2012
  8. *
  9. * Thanks to: Pablo Aguilar for spotting my omission of string access shims
  10. * for special_string_instance_1.
  11. *
  12. * Home: http://stlsoft.org/
  13. *
  14. * Copyright (c) 2006-2012, Matthew Wilson and Synesis Software
  15. * All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms, with or without
  18. * modification, are permitted provided that the following conditions are
  19. * met:
  20. *
  21. * - Redistributions of source code must retain the above copyright notice,
  22. * this list of conditions and the following disclaimer.
  23. * - Redistributions in binary form must reproduce the above copyright
  24. * notice, this list of conditions and the following disclaimer in the
  25. * documentation and/or other materials provided with the distribution.
  26. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the
  27. * names of any contributors may be used to endorse or promote products
  28. * derived from this software without specific prior written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  31. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  32. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  33. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  35. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  36. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  37. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  38. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  39. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  40. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * ////////////////////////////////////////////////////////////////////// */
  43. /** \file stlsoft/string/special_string_instance.hpp
  44. *
  45. * \brief [C++ only] Definition of the stlsoft::special_string_instance
  46. * class template
  47. * (\ref group__library__string "String" Library).
  48. */
  49. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE
  50. #define STLSOFT_INCL_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE
  51. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  52. # define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_MAJOR 1
  53. # define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_MINOR 3
  54. # define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_REVISION 2
  55. # define STLSOFT_VER_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE_EDIT 23
  56. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  57. /* /////////////////////////////////////////////////////////////////////////
  58. * Compatibility
  59. */
  60. /*
  61. [Incompatibilies-start]
  62. STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1200
  63. [Incompatibilies-end]
  64. */
  65. /* Compatibility
  66. [<[STLSOFT-AUTO:NO-DOCFILELABEL]>]
  67. [<[STLSOFT-AUTO:NO-UNITTEST]>]
  68. */
  69. /* /////////////////////////////////////////////////////////////////////////
  70. * Includes
  71. */
  72. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  73. # include <stlsoft/stlsoft.h>
  74. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  75. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  76. # include <stlsoft/memory/auto_buffer.hpp>
  77. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  78. #ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_SAME_TYPE
  79. # include <stlsoft/meta/is_same_type.hpp>
  80. #endif /* !STLSOFT_INCL_STLSOFT_META_HPP_IS_SAME_TYPE */
  81. #ifndef STLSOFT_INCL_STLSOFT_META_HPP_SELECT_FIRST_TYPE_IF
  82. # include <stlsoft/meta/select_first_type_if.hpp>
  83. #endif /* !STLSOFT_INCL_STLSOFT_META_HPP_SELECT_FIRST_TYPE_IF */
  84. #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE
  85. # include <stlsoft/synch/lock_scope.hpp>
  86. #endif /* !STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE */
  87. /* /////////////////////////////////////////////////////////////////////////
  88. * Namespace
  89. */
  90. #ifndef _STLSOFT_NO_NAMESPACE
  91. namespace stlsoft
  92. {
  93. #endif /* _STLSOFT_NO_NAMESPACE */
  94. /* /////////////////////////////////////////////////////////////////////////
  95. * Classes
  96. */
  97. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  98. template< ss_typename_param_k C
  99. , ss_size_t N
  100. , ss_typename_param_k A
  101. , ss_typename_param_k A0
  102. >
  103. struct ssi_buffer
  104. {
  105. /// \name Member Types
  106. /// @{
  107. public:
  108. /// The character type
  109. typedef C char_type;
  110. /// The allocator type
  111. typedef A allocator_type;
  112. /// The size type
  113. typedef ss_size_t size_type;
  114. /// The argument type
  115. typedef A0 argument_0_type;
  116. /// The class type
  117. typedef ssi_buffer<C, N, A, A0> class_type;
  118. private:
  119. /// The buffer type
  120. typedef stlsoft::auto_buffer<
  121. char_type
  122. #if defined(STLSOFT_COMPILER_IS_BORLAND)
  123. , 128
  124. #else /* ? compiler */
  125. , N
  126. #endif /* compiler */
  127. , allocator_type
  128. > buffer_type_;
  129. /// @}
  130. /// \name Construction
  131. /// @{
  132. public:
  133. ssi_buffer()
  134. : m_len(0)
  135. , m_buffer(0)
  136. {}
  137. #ifdef STLSOFT_COMPILER_IS_GCC
  138. ssi_buffer(class_type const& rhs)
  139. : m_len(rhs.m_len)
  140. , m_buffer(rhs.m_len + 1)
  141. {
  142. ::memcpy(&m_buffer[0], &rhs.m_buffer[0], sizeof(char_type) * (1u + m_len));
  143. }
  144. #endif /* compiler */
  145. void init(size_type (*pfn)(char_type*, size_type))
  146. {
  147. // We don't pass NULL here, just in case
  148. char_type empty = '\0';
  149. size_type cch = pfn(&empty, 0);
  150. if(m_buffer.resize(1 + cch))
  151. {
  152. for(;;)
  153. {
  154. cch = pfn(&m_buffer[0], m_buffer.size());
  155. if(cch < m_buffer.size())
  156. {
  157. m_len = cch;
  158. break;
  159. }
  160. else
  161. {
  162. if(!m_buffer.resize(2 * m_buffer.size()))
  163. {
  164. m_buffer.resize(0);
  165. break;
  166. }
  167. }
  168. }
  169. }
  170. m_buffer[m_len] = '\0';
  171. }
  172. void init(argument_0_type arg0, size_type (*pfn)(argument_0_type, char_type*, size_type))
  173. {
  174. size_type cch = pfn(arg0, NULL, 0); // We don't pass NULL here, just in case
  175. if(m_buffer.resize(1 + cch))
  176. {
  177. for(;;)
  178. {
  179. cch = pfn(arg0, &m_buffer[0], m_buffer.size());
  180. if(cch < m_buffer.size())
  181. {
  182. m_len = cch;
  183. break;
  184. }
  185. else
  186. {
  187. if(!m_buffer.resize(2 * m_buffer.size()))
  188. {
  189. m_buffer.resize(0);
  190. break;
  191. }
  192. }
  193. }
  194. }
  195. m_buffer[m_len] = '\0';
  196. }
  197. /// @}
  198. /// \name Accessors
  199. /// @{
  200. public:
  201. char_type const* data() const
  202. {
  203. return m_buffer.data();
  204. }
  205. size_type length() const
  206. {
  207. return m_len;
  208. }
  209. /// @}
  210. /// \name Members
  211. /// @{
  212. private:
  213. size_type m_len;
  214. buffer_type_ m_buffer;
  215. /// @}
  216. };
  217. template< ss_typename_param_k C
  218. , ss_size_t N
  219. , ss_typename_param_k A
  220. , ss_typename_param_k A0
  221. >
  222. struct ssi_buffer_non_static
  223. : public ssi_buffer<C, N, A, A0>
  224. {
  225. /// \name Member Types
  226. /// @{
  227. public:
  228. typedef ssi_buffer<C, N, A, A0> ssi_buffer_type;
  229. typedef ssi_buffer<C, N, A, A0> parent_class_type;
  230. typedef ssi_buffer_non_static<C, N, A, A0> class_type;
  231. typedef ss_typename_type_k ssi_buffer_type::char_type char_type;
  232. typedef ss_typename_type_k ssi_buffer_type::size_type size_type;
  233. /// @}
  234. /// \name Construction
  235. /// @{
  236. public:
  237. ssi_buffer_non_static(size_type (*pfn)(char_type*, size_type))
  238. {
  239. parent_class_type::init(pfn);
  240. }
  241. ssi_buffer_non_static(A0 a0, size_type (*pfn)(A0, char_type*, size_type))
  242. {
  243. parent_class_type::init(a0, pfn);
  244. }
  245. #ifdef STLSOFT_COMPILER_IS_GCC
  246. ssi_buffer_non_static(class_type const& rhs)
  247. : parent_class_type(rhs)
  248. {}
  249. #endif /* compiler */
  250. /// @}
  251. /// \name Accessors
  252. /// @{
  253. public:
  254. char_type const* data() const
  255. {
  256. return parent_class_type::data();
  257. }
  258. size_type length() const
  259. {
  260. return parent_class_type::length();
  261. }
  262. /// @}
  263. /// \name Not to be implemented
  264. /// @{
  265. private:
  266. #ifndef STLSOFT_COMPILER_IS_GCC
  267. ssi_buffer_non_static(class_type const&);
  268. #endif /* compiler */
  269. class_type& operator =(class_type const&);
  270. /// @}
  271. };
  272. template< ss_typename_param_k C
  273. , ss_size_t N
  274. , ss_typename_param_k A
  275. , ss_typename_param_k A0
  276. , ss_typename_param_k P // Passes policy type, from which spin_mutex_type is elicited, so non-statics do not need to specify it
  277. >
  278. struct ssi_buffer_static
  279. {
  280. /// \name Member Types
  281. /// @{
  282. public:
  283. typedef ssi_buffer<C, N, A, A0> ssi_buffer_type;
  284. typedef ssi_buffer_static<C, N, A, A0, P> class_type;
  285. typedef ss_typename_type_k ssi_buffer_type::char_type char_type;
  286. typedef ss_typename_type_k ssi_buffer_type::size_type size_type;
  287. private:
  288. typedef P policy_type;
  289. typedef ss_typename_type_k policy_type::spin_mutex_type spin_mutex_type;
  290. typedef ss_typename_type_k policy_type::atomic_int_type atomic_int_type;
  291. /// @}
  292. /// \name Construction
  293. /// @{
  294. public:
  295. ssi_buffer_static(size_type (*pfn)(char_type*, size_type))
  296. : m_buffer(get_buffer(pfn))
  297. {}
  298. ssi_buffer_static(A0 a0, size_type (*pfn)(A0, char_type*, size_type))
  299. : m_buffer(a0, get_buffer(a0, pfn))
  300. {}
  301. #ifdef STLSOFT_COMPILER_IS_GCC
  302. ssi_buffer_static(class_type const& rhs)
  303. : m_buffer(rhs.m_buffer)
  304. {}
  305. #endif /* compiler */
  306. /// @}
  307. /// \name Accessors
  308. /// @{
  309. public:
  310. char_type const* data() const
  311. {
  312. return m_buffer.data();
  313. }
  314. size_type length() const
  315. {
  316. return m_buffer.length();
  317. }
  318. /// @}
  319. /// \name Implementation
  320. /// @{
  321. private:
  322. static ssi_buffer_type& get_buffer(size_type (*pfn)(char_type*, size_type))
  323. {
  324. static atomic_int_type s_count = 0;
  325. static bool s_bInit = false;
  326. spin_mutex_type mx(&s_count);
  327. stlsoft::lock_scope<spin_mutex_type> lock(mx);
  328. static ssi_buffer_type s_buffer;
  329. if(!s_bInit)
  330. {
  331. s_buffer.init(pfn);
  332. s_bInit = true;
  333. }
  334. return s_buffer;
  335. }
  336. static ssi_buffer_type& get_buffer(A0 a0, size_type (*pfn)(A0, char_type*, size_type))
  337. {
  338. static atomic_int_type s_count = 0;
  339. static bool s_bInit = false;
  340. spin_mutex_type mx(&s_count);
  341. stlsoft::lock_scope<spin_mutex_type> lock(mx);
  342. static ssi_buffer_type s_buffer;
  343. if(!s_bInit)
  344. {
  345. s_buffer.init(a0, pfn);
  346. s_bInit = true;
  347. }
  348. return s_buffer;
  349. }
  350. /// @}
  351. /// \name Members
  352. /// @{
  353. private:
  354. ssi_buffer_type& m_buffer;
  355. /// @}
  356. /// \name Not to be implemented
  357. /// @{
  358. private:
  359. #ifndef STLSOFT_COMPILER_IS_GCC
  360. ssi_buffer_static(class_type const&);
  361. #endif /* compiler */
  362. class_type& operator =(class_type const&);
  363. /// @}
  364. };
  365. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  366. /** \brief Special string instance class template.
  367. *
  368. * \ingroup group__library__string
  369. *
  370. * \param P The SSI policy type.
  371. *
  372. * The policy type provides the following:
  373. *
  374. * - A member constant <code>internalBufferSize</code> that determines the
  375. * size of the SSI's internal
  376. * \link stlsoft::auto_buffer auto_buffer\endlink's internal buffer size.
  377. * - A static method <code>get_value(char_type* buffer, size_type cchBuffer)</code>
  378. * that has the
  379. * - A member constant <code>allowImplicitConversion</code> that determines
  380. * whether an implicit conversion operator (to
  381. * <code>char_type const*</code>) is to be provided.
  382. */
  383. template <ss_typename_param_k P>
  384. class special_string_instance_0
  385. {
  386. /// \name Member Types
  387. /// @{
  388. public:
  389. /// \brief The policy type
  390. typedef P policy_type;
  391. /// \brief The current instantiation of the template.
  392. typedef special_string_instance_0<P> class_type;
  393. /// \brief The character type
  394. typedef ss_typename_type_k policy_type::char_type char_type;
  395. /// \brief The size type
  396. typedef ss_typename_type_k policy_type::size_type size_type;
  397. /// \brief The character type for ANSI specialisations
  398. ///
  399. /// \note This is used in the specification of the string access shim
  400. /// functions.
  401. private:
  402. enum { charTypeIsAnsi = is_same_type<ss_char_a_t, char_type>::value };
  403. public:
  404. typedef ss_typename_type_k select_first_type_if<
  405. ss_char_a_t const*
  406. , void
  407. , charTypeIsAnsi
  408. >::type cstring_a_type;
  409. /// \brief The character type for Unicode specialisations
  410. ///
  411. /// \note This is used in the specification of the string access shim
  412. /// functions.
  413. private:
  414. enum { charTypeIsWide = is_same_type<ss_char_w_t, char_type>::value };
  415. public:
  416. typedef ss_typename_type_k select_first_type_if<
  417. ss_char_w_t const*
  418. , void
  419. , charTypeIsWide
  420. >::type cstring_w_type;
  421. private:
  422. typedef ss_typename_type_k policy_type::pfn_type pfn_type;
  423. private:
  424. // This section allows for the case where the policy does not define an
  425. // allocator, which it indicates by defining its member type
  426. // allocator_type to be void.
  427. typedef ss_typename_type_k policy_type::allocator_type putative_allocator_type;
  428. enum
  429. {
  430. policy_has_allocator_type = (0 != size_of<putative_allocator_type>::value)
  431. };
  432. typedef ss_typename_type_k allocator_selector<char_type>::allocator_type backup_allocator_type;
  433. public:
  434. /// \brief The allocator type
  435. typedef ss_typename_type_k select_first_type_if<
  436. putative_allocator_type
  437. , backup_allocator_type
  438. , policy_has_allocator_type
  439. >::type allocator_type;
  440. private:
  441. enum { allowImplicitConversion = policy_type::allowImplicitConversion };
  442. public:
  443. /// \brief The implicit conversion operator type
  444. typedef ss_typename_type_k select_first_type_if<
  445. char_type const*
  446. , void
  447. , allowImplicitConversion
  448. >::type implicit_conversion_type;
  449. private:
  450. // This section accounts for whether the policy indicates shared state.
  451. // If so, then the buffer type resolves to the appropriate
  452. // specialisation of ssi_buffer_static, which stores a threadsafe buffer
  453. // shared by all instances. If not, then the buffer type resolves to
  454. // ssi_buffer_non_static, which stores a buffer per instance.
  455. enum
  456. {
  457. policy_indicates_shared_state = (0 != policy_type::sharedState)
  458. };
  459. struct null_argument
  460. {};
  461. enum { internalBufferSize = policy_type::internalBufferSize };
  462. typedef ssi_buffer_static<
  463. char_type
  464. , internalBufferSize
  465. , allocator_type
  466. , null_argument
  467. , policy_type // Passes policy type, from which spin_mutex_type is elicited, so non-statics do not need to specify it
  468. > ssi_buffer_static_type;
  469. typedef ssi_buffer_non_static<
  470. char_type
  471. , internalBufferSize
  472. , allocator_type
  473. , null_argument
  474. > ssi_buffer_non_static_type;
  475. typedef ss_typename_type_k select_first_type_if<
  476. ssi_buffer_static_type
  477. , ssi_buffer_non_static_type
  478. , policy_indicates_shared_state
  479. >::type buffer_type_;
  480. /// @}
  481. /// \name Construction
  482. /// @{
  483. public:
  484. special_string_instance_0()
  485. : m_buffer(policy_type::get_fn())
  486. {}
  487. /// @}
  488. /// \name Accessors
  489. /// @{
  490. public:
  491. size_type length() const
  492. {
  493. return m_buffer.length();
  494. }
  495. size_type size() const
  496. {
  497. return length();
  498. }
  499. char_type const* data() const
  500. {
  501. return m_buffer.data();
  502. }
  503. char_type const* c_str() const
  504. {
  505. return data();
  506. }
  507. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  508. cstring_a_type c_str_a() const
  509. {
  510. return c_str();
  511. }
  512. cstring_w_type c_str_w() const
  513. {
  514. return c_str();
  515. }
  516. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  517. /// @}
  518. /// \name Operators
  519. /// @{
  520. public:
  521. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  522. operator implicit_conversion_type () const
  523. {
  524. return this->c_str();
  525. }
  526. #endif /* compiler */
  527. /// @}
  528. /// \name Operations
  529. /// @{
  530. public:
  531. static size_type get(char_type* buffer, size_type cchBuffer)
  532. {
  533. return (policy_type::get_fn())(buffer, cchBuffer);
  534. }
  535. /// @}
  536. /// \name Members
  537. /// @{
  538. private:
  539. buffer_type_ m_buffer;
  540. /// @}
  541. };
  542. /** \brief Special string instance class template.
  543. *
  544. * \ingroup group__library__string
  545. *
  546. * \param P The SSI policy type.
  547. *
  548. * The policy type provides the following:
  549. *
  550. * - A member constant <code>internalBufferSize</code> that determines the
  551. * size of the SSI's internal
  552. * \link stlsoft::auto_buffer auto_buffer\endlink's internal buffer size.
  553. * - A static method <code>get_value(char_type* buffer, size_type cchBuffer)</code>
  554. * that has the
  555. * - A member constant <code>allowImplicitConversion</code> that determines
  556. * whether an implicit conversion operator (to
  557. * <code>char_type const*</code>) is to be provided.
  558. */
  559. template <ss_typename_param_k P>
  560. class special_string_instance_1
  561. {
  562. /// \name Member Types
  563. /// @{
  564. public:
  565. /// \brief The policy type.
  566. typedef P policy_type;
  567. /// \brief The current instantiation of the template.
  568. typedef special_string_instance_1<P> class_type;
  569. /// \brief The character type
  570. typedef ss_typename_type_k policy_type::char_type char_type;
  571. /// \brief The size type
  572. typedef ss_typename_type_k policy_type::size_type size_type;
  573. /// \brief The argument type
  574. typedef ss_typename_type_k policy_type::argument_0_type argument_0_type;
  575. /// \brief The character type for ANSI specialisations
  576. ///
  577. /// \note This is used in the specification of the string access shim
  578. /// functions.
  579. private:
  580. enum { charTypeIsAnsi = is_same_type<ss_char_a_t, char_type>::value };
  581. public:
  582. typedef ss_typename_type_k select_first_type_if<
  583. ss_char_a_t const*
  584. , void
  585. , charTypeIsAnsi
  586. >::type cstring_a_type;
  587. /// \brief The character type for Unicode specialisations
  588. ///
  589. /// \note This is used in the specification of the string access shim
  590. /// functions.
  591. private:
  592. enum { charTypeIsWide = is_same_type<ss_char_w_t, char_type>::value };
  593. public:
  594. typedef ss_typename_type_k select_first_type_if<
  595. ss_char_w_t const*
  596. , void
  597. , charTypeIsWide
  598. >::type cstring_w_type;
  599. private:
  600. typedef ss_typename_type_k policy_type::pfn_type pfn_type;
  601. private:
  602. // This section allows for the case where the policy does not define an
  603. // allocator, which it indicates by defining its member type
  604. // allocator_type to be void.
  605. typedef ss_typename_type_k policy_type::allocator_type putative_allocator_type;
  606. enum
  607. {
  608. policy_has_allocator_type = (0 != size_of<putative_allocator_type>::value)
  609. };
  610. typedef ss_typename_type_k allocator_selector<char_type>::allocator_type backup_allocator_type;
  611. public:
  612. /// \brief The allocator type
  613. typedef ss_typename_type_k select_first_type_if<
  614. putative_allocator_type
  615. , backup_allocator_type
  616. , policy_has_allocator_type
  617. >::type allocator_type;
  618. /// \brief The implicit conversion operator type
  619. private:
  620. enum { allowImplicitConversion = policy_type::allowImplicitConversion };
  621. public:
  622. typedef ss_typename_type_k select_first_type_if<
  623. char_type const*
  624. , void
  625. , allowImplicitConversion
  626. >::type implicit_conversion_type;
  627. private:
  628. // This section accounts for whether the policy indicates shared state.
  629. // If so, then the buffer type resolves to the appropriate
  630. // specialisation of ssi_buffer_static, which stores a threadsafe buffer
  631. // shared by all instances. If not, then the buffer type resolves to
  632. // ssi_buffer_non_static, which stores a buffer per instance.
  633. enum
  634. {
  635. policy_indicates_shared_state = (0 != policy_type::sharedState)
  636. };
  637. enum { internalBufferSize = policy_type::internalBufferSize };
  638. typedef ssi_buffer_static<
  639. char_type
  640. , internalBufferSize
  641. , allocator_type
  642. , argument_0_type
  643. , policy_type // Passes policy type, from which spin_mutex_type is elicited, so non-statics do not need to specify it
  644. > ssi_buffer_static_type;
  645. typedef ssi_buffer_non_static<
  646. char_type
  647. , internalBufferSize
  648. , allocator_type
  649. , argument_0_type
  650. > ssi_buffer_non_static_type;
  651. typedef ss_typename_type_k select_first_type_if<
  652. ssi_buffer_static_type
  653. , ssi_buffer_non_static_type
  654. , policy_indicates_shared_state
  655. >::type buffer_type_;
  656. /// @}
  657. /// \name Construction
  658. /// @{
  659. public:
  660. special_string_instance_1(argument_0_type argument)
  661. : m_buffer(argument, policy_type::get_fn())
  662. {}
  663. /// @}
  664. /// \name Operations
  665. /// @{
  666. public:
  667. static size_type get(argument_0_type argument, char_type* buffer, size_type cchBuffer)
  668. {
  669. return (policy_type::get_fn())(argument, buffer, cchBuffer);
  670. }
  671. /// @}
  672. /// \name Attributes
  673. /// @{
  674. public:
  675. char_type const* c_str() const
  676. {
  677. return m_buffer.data();
  678. }
  679. char_type const* data() const
  680. {
  681. return m_buffer.data();
  682. }
  683. size_type length() const
  684. {
  685. return m_buffer.length();
  686. }
  687. size_type size() const
  688. {
  689. return length();
  690. }
  691. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  692. cstring_a_type c_str_a() const
  693. {
  694. return c_str();
  695. }
  696. cstring_w_type c_str_w() const
  697. {
  698. return c_str();
  699. }
  700. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  701. /// @}
  702. /// \name Operators
  703. /// @{
  704. public:
  705. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  706. operator implicit_conversion_type () const
  707. {
  708. return this->c_str();
  709. }
  710. #endif /* compiler */
  711. /// @}
  712. /// \name Member Types
  713. /// @{
  714. private:
  715. buffer_type_ m_buffer;
  716. /// @}
  717. };
  718. /* /////////////////////////////////////////////////////////////////////////
  719. * Shims
  720. */
  721. /** \brief \ref group__concept__shim__string_access__c_str_ptr_null for stlsoft::special_string_instance_0
  722. *
  723. * \ingroup group__concept__shim__string_access
  724. */
  725. template <ss_typename_param_k P>
  726. inline ss_typename_type_ret_k special_string_instance_0<P>::char_type const* c_str_ptr_null(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  727. {
  728. return (0 != ssi.length()) ? ssi.c_str() : NULL;
  729. }
  730. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  731. template <ss_typename_param_k P>
  732. inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_a_type c_str_ptr_null_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  733. {
  734. return (0 != ssi.length()) ? ssi.c_str_a() : NULL;
  735. }
  736. template <ss_typename_param_k P>
  737. inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_w_type c_str_ptr_null_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  738. {
  739. return (0 != ssi.length()) ? ssi.c_str_w() : NULL;
  740. }
  741. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  742. /** \brief \ref group__concept__shim__string_access__c_str_ptr for stlsoft::special_string_instance_0
  743. *
  744. * \ingroup group__concept__shim__string_access
  745. */
  746. template <ss_typename_param_k P>
  747. inline ss_typename_type_ret_k special_string_instance_0<P>::char_type const* c_str_ptr(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  748. {
  749. return ssi.c_str();
  750. }
  751. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  752. template <ss_typename_param_k P>
  753. inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_a_type c_str_ptr_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  754. {
  755. return ssi.c_str_a();
  756. }
  757. template <ss_typename_param_k P>
  758. inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_w_type c_str_ptr_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  759. {
  760. return ssi.c_str_w();
  761. }
  762. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  763. /** \brief \ref group__concept__shim__string_access__c_str_data for stlsoft::special_string_instance_0
  764. *
  765. * \ingroup group__concept__shim__string_access
  766. */
  767. template <ss_typename_param_k P>
  768. inline ss_typename_type_ret_k special_string_instance_0<P>::char_type const* c_str_data(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  769. {
  770. return ssi.c_str();
  771. }
  772. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  773. template <ss_typename_param_k P>
  774. inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_a_type c_str_data_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  775. {
  776. return ssi.c_str_a();
  777. }
  778. template <ss_typename_param_k P>
  779. inline ss_typename_type_ret_k special_string_instance_0<P>::cstring_w_type c_str_data_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  780. {
  781. return ssi.c_str_w();
  782. }
  783. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  784. /** \brief \ref group__concept__shim__string_access__c_str_len for stlsoft::special_string_instance_0
  785. *
  786. * \ingroup group__concept__shim__string_access
  787. */
  788. template <ss_typename_param_k P>
  789. inline ss_size_t c_str_len(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  790. {
  791. return ssi.length();
  792. }
  793. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  794. template <ss_typename_param_k P>
  795. inline ss_size_t c_str_len_a(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  796. {
  797. // If this fires, you're trying to invoke c_str_len_w() on an SSI
  798. // whose policy defines the character type to be something other
  799. // than char.
  800. ss_char_a_t const* const special_string_instance_must_use_narrow_character = ssi.c_str_a();
  801. STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_narrow_character);
  802. return ssi.length();
  803. }
  804. template <ss_typename_param_k P>
  805. inline ss_size_t c_str_len_w(stlsoft_ns_qual(special_string_instance_0)<P> const& ssi)
  806. {
  807. // If this fires, you're trying to invoke c_str_len_w() on an SSI
  808. // whose policy defines the character type to be something other
  809. // than wchar_t.
  810. ss_char_w_t const* const special_string_instance_must_use_wide_character = ssi.c_str_w();
  811. STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_wide_character);
  812. return ssi.length();
  813. }
  814. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  815. /** \brief \ref group__concept__shim__string_access__c_str_ptr_null for stlsoft::special_string_instance_1
  816. *
  817. * \ingroup group__concept__shim__string_access
  818. */
  819. template <ss_typename_param_k P>
  820. inline ss_typename_type_ret_k special_string_instance_1<P>::char_type const* c_str_ptr_null(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  821. {
  822. return (0 != ssi.length()) ? ssi.c_str() : NULL;
  823. }
  824. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  825. template <ss_typename_param_k P>
  826. inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_a_type c_str_ptr_null_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  827. {
  828. return (0 != ssi.length()) ? ssi.c_str_a() : NULL;
  829. }
  830. template <ss_typename_param_k P>
  831. inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_w_type c_str_ptr_null_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  832. {
  833. return (0 != ssi.length()) ? ssi.c_str_w() : NULL;
  834. }
  835. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  836. /** \brief \ref group__concept__shim__string_access__c_str_ptr for stlsoft::special_string_instance_1
  837. *
  838. * \ingroup group__concept__shim__string_access
  839. */
  840. template <ss_typename_param_k P>
  841. inline ss_typename_type_ret_k special_string_instance_1<P>::char_type const* c_str_ptr(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  842. {
  843. return ssi.c_str();
  844. }
  845. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  846. template <ss_typename_param_k P>
  847. inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_a_type c_str_ptr_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  848. {
  849. return ssi.c_str_a();
  850. }
  851. template <ss_typename_param_k P>
  852. inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_w_type c_str_ptr_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  853. {
  854. return ssi.c_str_w();
  855. }
  856. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  857. /** \brief \ref group__concept__shim__string_access__c_str_data for stlsoft::special_string_instance_1
  858. *
  859. * \ingroup group__concept__shim__string_access
  860. */
  861. template <ss_typename_param_k P>
  862. inline ss_typename_type_ret_k special_string_instance_1<P>::char_type const* c_str_data(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  863. {
  864. return ssi.c_str();
  865. }
  866. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  867. template <ss_typename_param_k P>
  868. inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_a_type c_str_data_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  869. {
  870. return ssi.c_str_a();
  871. }
  872. template <ss_typename_param_k P>
  873. inline ss_typename_type_ret_k special_string_instance_1<P>::cstring_w_type c_str_data_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  874. {
  875. return ssi.c_str_w();
  876. }
  877. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  878. /** \brief \ref group__concept__shim__string_access__c_str_len for stlsoft::special_string_instance_1
  879. *
  880. * \ingroup group__concept__shim__string_access
  881. */
  882. template <ss_typename_param_k P>
  883. inline ss_size_t c_str_len(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  884. {
  885. return ssi.length();
  886. }
  887. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  888. template <ss_typename_param_k P>
  889. inline ss_size_t c_str_len_a(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  890. {
  891. // If this fires, you're trying to invoke c_str_len_w() on an SSI
  892. // whose policy defines the character type to be something other
  893. // than char.
  894. ss_char_a_t const* const special_string_instance_must_use_narrow_character = ssi.c_str_a();
  895. STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_narrow_character);
  896. return ssi.length();
  897. }
  898. template <ss_typename_param_k P>
  899. inline ss_size_t c_str_len_w(stlsoft_ns_qual(special_string_instance_1)<P> const& ssi)
  900. {
  901. // If this fires, you're trying to invoke c_str_len_w() on an SSI
  902. // whose policy defines the character type to be something other
  903. // than wchar_t.
  904. ss_char_w_t const* const special_string_instance_must_use_wide_character = ssi.c_str_w();
  905. STLSOFT_SUPPRESS_UNUSED(special_string_instance_must_use_wide_character);
  906. return ssi.length();
  907. }
  908. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  909. /* ////////////////////////////////////////////////////////////////////// */
  910. #ifndef _STLSOFT_NO_NAMESPACE
  911. } // namespace stlsoft
  912. #endif /* _STLSOFT_NO_NAMESPACE */
  913. /* ////////////////////////////////////////////////////////////////////// */
  914. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SPECIAL_STRING_INSTANCE */
  915. /* ///////////////////////////// end of file //////////////////////////// */