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.

345 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/containers/environment_block.hpp (stlsoft_environment_block.h)
  3. *
  4. * Purpose: Contains the basic_environment_block class.
  5. *
  6. * Created: 25th June 2004
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2004-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/containers/environment_block.hpp
  40. *
  41. * \brief [C++ only] Definition of the stlsoft::basic_environment_block
  42. * container class template
  43. * (\ref group__library__containers "Containers" Library).
  44. */
  45. #ifndef STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK
  46. #define STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK_MAJOR 4
  49. # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK_MINOR 2
  50. # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK_REVISION 3
  51. # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK_EDIT 43
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Compatibility
  55. */
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Includes
  58. */
  59. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  60. # include <stlsoft/stlsoft.h>
  61. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  62. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  63. # include <stlsoft/memory/auto_buffer.hpp>
  64. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  65. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_BASE
  66. # include <stlsoft/memory/allocator_base.hpp> // for STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  67. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_BASE */
  68. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
  69. # include <stlsoft/memory/allocator_selector.hpp>
  70. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR */
  71. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  72. # include <stlsoft/string/char_traits.hpp>
  73. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS */
  74. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  75. # include <stlsoft/shims/access/string.hpp>
  76. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  77. /* /////////////////////////////////////////////////////////////////////////
  78. * Namespace
  79. */
  80. #ifndef _STLSOFT_NO_NAMESPACE
  81. namespace stlsoft
  82. {
  83. #endif /* _STLSOFT_NO_NAMESPACE */
  84. /* /////////////////////////////////////////////////////////////////////////
  85. * Classes
  86. */
  87. /** \brief Stores nul-terminated environment variable name-value strings
  88. * continguously in a format compatible with system environment settings.
  89. *
  90. * \ingroup group__library__containers
  91. *
  92. * \param C The character type
  93. * \param T The traits type. Defaults to char_traits<C>. On translators that do not support default template parameters, this must be explicitly specified.
  94. * \param A The allocator type. Defaults to stlsoft::allocator_selector<C>::allocator_type. On translators that do not support default template parameters, this must be explicitly specified.
  95. */
  96. template< ss_typename_param_k C
  97. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  98. , ss_typename_param_k T = char_traits<C>
  99. , ss_typename_param_k A = ss_typename_type_def_k allocator_selector<C>::allocator_type
  100. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  101. , ss_typename_param_k T /* = char_traits<C> */
  102. , ss_typename_param_k A /* = ss_typename_type_def_k allocator_selector<C>::allocator_type */
  103. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  104. >
  105. class basic_environment_block
  106. {
  107. /// \name Types
  108. /// @{
  109. public:
  110. /// The value type
  111. typedef C value_type;
  112. /// The char type
  113. typedef C char_type;
  114. /// The traits type
  115. typedef T traits_type;
  116. /// The allocator type
  117. typedef A allocator_type;
  118. /// The current parameterisation of the type
  119. typedef basic_environment_block<C, T, A> class_type;
  120. /// The mutating (non-const) pointer type
  121. typedef char_type* pointer;
  122. /// The non-mutating (const) pointer type
  123. typedef char_type const* const_pointer;
  124. /// The size type
  125. typedef ss_size_t size_type;
  126. /// @}
  127. /// \name Construction
  128. /// @{
  129. public:
  130. basic_environment_block()
  131. : m_chars(1)
  132. , m_offsets(1)
  133. , m_pointers(0)
  134. {
  135. m_chars[0] = '\0';
  136. m_offsets[0] = 0;
  137. }
  138. /// @}
  139. /// \name Operations
  140. /// @{
  141. public:
  142. /// \brief Append a full NAME=VALUE environment pair
  143. void push_back(char_type const* s, ss_size_t cch)
  144. {
  145. STLSOFT_ASSERT(NULL != s);
  146. STLSOFT_ASSERT(cch >= 3);
  147. STLSOFT_ASSERT(NULL != traits_type::find(s, cch, '='));
  148. STLSOFT_ASSERT(m_chars.size() > 0);
  149. STLSOFT_ASSERT('\0' == m_chars[m_chars.size() - 1]);
  150. const size_type numChars_ = m_chars.size();
  151. const size_type numOffsets_ = m_offsets.size();
  152. const size_type numPointers_ = m_pointers.size();
  153. m_chars.resize(numChars_ + cch + 1);
  154. // The next item
  155. traits_type::copy(&m_chars[numChars_ - 1], s, cch);
  156. m_chars[numChars_ + cch - 1] = '\0';
  157. // The terminating item
  158. m_chars[numChars_ + cch] = '\0';
  159. m_offsets.resize(numOffsets_ + 1);
  160. m_offsets[numOffsets_] = numChars_ + cch;
  161. m_pointers.resize(0);
  162. STLSOFT_ASSERT('\0' == m_chars[m_chars.size() - 1]);
  163. }
  164. template <ss_typename_param_k S>
  165. void push_back(S const& s)
  166. {
  167. push_back(stlsoft_ns_qual(c_str_data)(s), stlsoft_ns_qual(c_str_len)(s));
  168. }
  169. void push_back(char_type const* name, ss_size_t cchName, char_type const* value, ss_size_t cchValue)
  170. {
  171. STLSOFT_ASSERT(NULL != name);
  172. STLSOFT_ASSERT(NULL != value);
  173. STLSOFT_ASSERT(cchName > 0);
  174. STLSOFT_ASSERT(cchValue > 0);
  175. STLSOFT_ASSERT(NULL == traits_type::find(name, cchName, '='));
  176. STLSOFT_ASSERT(m_chars.size() > 0);
  177. STLSOFT_ASSERT('\0' == m_chars[m_chars.size() - 1]);
  178. const size_type numChars_ = m_chars.size();
  179. const size_type numOffsets_ = m_offsets.size();
  180. const size_type numPointers_ = m_pointers.size();
  181. m_chars.resize(numChars_ + cchName + 1 + cchValue + 1);
  182. // The next item
  183. traits_type::copy(&m_chars[numChars_ - 1], name, cchName);
  184. m_chars[numChars_ - 1 + cchName] = '=';
  185. traits_type::copy(&m_chars[numChars_ - 1 + cchName + 1], value, cchValue);
  186. m_chars[numChars_ - 1 + cchName + 1 + cchValue] = '\0';
  187. // The terminating item
  188. m_chars[numChars_ + cchName + 1 + cchValue] = '\0';
  189. m_offsets.resize(numOffsets_ + 1);
  190. m_offsets[numOffsets_] = numChars_ + cchName + 1 + cchValue;
  191. m_pointers.resize(0);
  192. STLSOFT_ASSERT('\0' == m_chars[m_chars.size() - 1]);
  193. }
  194. template< ss_typename_param_k S1
  195. , ss_typename_param_k S2
  196. >
  197. void push_back(S1 const& name, S2 const& value)
  198. {
  199. push_back(stlsoft_ns_qual(c_str_data)(name), stlsoft_ns_qual(c_str_len)(name), stlsoft_ns_qual(c_str_data)(value), stlsoft_ns_qual(c_str_len)(value));
  200. }
  201. void clear()
  202. {
  203. m_chars.resize(1);
  204. m_offsets.resize(1);
  205. m_pointers.resize(0);
  206. m_chars[0] = '\0';
  207. m_offsets[0] = 0;
  208. }
  209. /// @}
  210. /// \name Accessors
  211. /// @{
  212. public:
  213. char_type const* const* base() const
  214. {
  215. if(m_pointers.size() != m_offsets.size())
  216. {
  217. set_pointers();
  218. }
  219. return m_pointers.data();
  220. }
  221. size_type size() const
  222. {
  223. STLSOFT_ASSERT(m_offsets.size() >= 1);
  224. return m_offsets.size() - 1;
  225. }
  226. /// @}
  227. // Implementation
  228. private:
  229. void set_pointers()
  230. {
  231. if(m_pointers.resize(m_offsets.size()))
  232. {
  233. for(size_type i = 0; i < m_offsets.size(); ++i)
  234. {
  235. m_pointers[i] = &m_chars[m_offsets[i]];
  236. }
  237. }
  238. }
  239. void set_pointers() const
  240. {
  241. const_cast<class_type*>(this)->set_pointers();
  242. }
  243. // Members
  244. private:
  245. typedef stlsoft_ns_qual(auto_buffer_old)< char_type
  246. , allocator_type
  247. , 1024
  248. > char_buffer_type;
  249. typedef stlsoft_ns_qual(auto_buffer_old)< size_type
  250. #if defined(STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT)
  251. , ss_typename_type_k allocator_type::ss_template_qual_k rebind<size_type>::other
  252. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  253. , ss_typename_type_k allocator_selector<size_type>::allocator_type
  254. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  255. , 32
  256. > offset_buffer_type;
  257. typedef stlsoft_ns_qual(auto_buffer_old)< const_pointer
  258. #if defined(STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT)
  259. , ss_typename_type_k allocator_type::ss_template_qual_k rebind<pointer>::other
  260. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  261. , ss_typename_type_k allocator_selector<pointer>::allocator_type
  262. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  263. , 32
  264. > pointer_buffer_type;
  265. char_buffer_type m_chars;
  266. offset_buffer_type m_offsets;
  267. pointer_buffer_type m_pointers;
  268. };
  269. /* /////////////////////////////////////////////////////////////////////////
  270. * Typedefs for commonly encountered types
  271. */
  272. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  273. /// Specialisation of the basic_path template for the ANSI character type \c char
  274. typedef basic_environment_block<ss_char_a_t> environment_block_a;
  275. /** \brief Specialisation of the basic_environment_block template for the Unicode character type \c wchar_t
  276. *
  277. * \ingroup group__library__containers
  278. */
  279. typedef basic_environment_block<ss_char_w_t> environment_block_w;
  280. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  281. /* /////////////////////////////////////////////////////////////////////////
  282. * Unit-testing
  283. */
  284. #ifdef STLSOFT_UNITTEST
  285. # include "./unittest/environment_block_unittest_.h"
  286. #endif /* STLSOFT_UNITTEST */
  287. /* /////////////////////////////////////////////////////////////////////////
  288. * Implementation
  289. */
  290. /* ////////////////////////////////////////////////////////////////////// */
  291. #ifndef _STLSOFT_NO_NAMESPACE
  292. } // namespace stlsoft
  293. #endif /* _STLSOFT_NO_NAMESPACE */
  294. /* ////////////////////////////////////////////////////////////////////// */
  295. #endif /* !STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_ENVIRONMENT_BLOCK */
  296. /* ///////////////////////////// end of file //////////////////////////// */