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.

426 lines
15 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/system/environment_block.hpp
  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 winstl/system/environment_block.hpp
  40. *
  41. * \brief [C++ only] Definition of the winstl::basic_environment_block class
  42. * template
  43. * (\ref group__library__system "System" Library).
  44. */
  45. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK
  46. #define WINSTL_INCL_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define WINSTL_VER_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK_MAJOR 4
  49. # define WINSTL_VER_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK_MINOR 0
  50. # define WINSTL_VER_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK_REVISION 2
  51. # define WINSTL_VER_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK_EDIT 54
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Compatibility
  55. */
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Includes
  58. */
  59. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  60. # include <winstl/winstl.h>
  61. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  62. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
  63. # include <winstl/memory/processheap_allocator.hpp>
  64. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
  65. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  66. # include <stlsoft/memory/auto_buffer.hpp>
  67. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  68. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
  69. # include <stlsoft/string/char_traits.hpp>
  70. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS */
  71. #ifndef WINSTL_INCL_WINSTL_SHIMS_ACCESS_HPP_STRING
  72. # include <winstl/shims/access/string.hpp>
  73. #endif /* !WINSTL_INCL_WINSTL_SHIMS_ACCESS_HPP_STRING */
  74. /* /////////////////////////////////////////////////////////////////////////
  75. * Namespace
  76. */
  77. #ifndef _WINSTL_NO_NAMESPACE
  78. # if defined(_STLSOFT_NO_NAMESPACE) || \
  79. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  80. /* There is no stlsoft namespace, so must define ::winstl */
  81. namespace winstl
  82. {
  83. # else
  84. /* Define stlsoft::winstl_project */
  85. namespace stlsoft
  86. {
  87. namespace winstl_project
  88. {
  89. # endif /* _STLSOFT_NO_NAMESPACE */
  90. #endif /* !_WINSTL_NO_NAMESPACE */
  91. /* /////////////////////////////////////////////////////////////////////////
  92. * Classes
  93. */
  94. /** \brief Class used for preparing environment blocks compatible with the Windows
  95. * CreateProcess() function.
  96. *
  97. * \ingroup group__library__system
  98. *
  99. * It is used as follows:
  100. \code
  101. winstl::environment_block env;
  102. env.push_back("Name1", "Value1"); // Insert separate name and value
  103. env.push_back("Name2=Value2"); // Insert composite name and value
  104. ::CreateProcess( . . . // application name
  105. , . . . // command line
  106. , . . . // process attributes
  107. , . . . // thread attributes
  108. , . . . // handle inherit boolean
  109. , . . . // creation flags
  110. , const_cast<void*>(env.base()) // The environment
  111. , . . . // current directory
  112. , . . . // statup info
  113. , . . . // process info);
  114. \endcode
  115. *
  116. */
  117. template< ss_typename_param_k C
  118. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  119. , ss_typename_param_k T = char_traits<C>
  120. , ss_typename_param_k A = processheap_allocator<C>
  121. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  122. , ss_typename_param_k T /* = char_traits<C> */
  123. , ss_typename_param_k A /* = processheap_allocator<C> */
  124. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  125. >
  126. class basic_environment_block
  127. {
  128. /// \name Types
  129. /// @{
  130. public:
  131. /// The value type
  132. typedef C value_type;
  133. /// The char type
  134. typedef C char_type;
  135. /// The traits type
  136. typedef T traits_type;
  137. /// The allocator type
  138. typedef A allocator_type;
  139. /// The current parameterisation of the type
  140. typedef basic_environment_block<C, T, A> class_type;
  141. /// The size type
  142. typedef ws_size_t size_type;
  143. /// @}
  144. /// \name Construction
  145. /// @{
  146. public:
  147. /// Constructs an empty block
  148. basic_environment_block()
  149. : m_buffer(2)
  150. {
  151. m_buffer[0] = '\0';
  152. m_buffer[1] = '\0';
  153. }
  154. /// Constructs the block with a copy of the given instance
  155. basic_environment_block(class_type const& rhs)
  156. : m_buffer(rhs.m_buffer.size())
  157. {
  158. pod_copy_n(&m_buffer.data()[0], &rhs.m_buffer.data()[0], m_buffer.size());
  159. }
  160. /// Copies the contents of the given instance
  161. ///
  162. /// \exception std::bad_alloc When compiling with exception support, this will throw
  163. /// std::bad_alloc if memory cannot be acquired. When compiling absent
  164. /// exception support, failure to acquire memory will leave the
  165. /// instance unchanged.
  166. class_type& operator =(class_type const& rhs)
  167. {
  168. if(m_buffer.resize(rhs.m_buffer.size()))
  169. {
  170. pod_copy_n(&m_buffer.data()[0], &rhs.m_buffer.data()[0], m_buffer.size());
  171. }
  172. return *this;
  173. }
  174. /// @}
  175. /// \name Operations
  176. /// @{
  177. public:
  178. /// \brief Append a full NAME=VALUE environment variable
  179. ///
  180. /// \param variable The variable
  181. /// \param cch The length of the variable
  182. ///
  183. /// \return An indication of success. This will always return true when
  184. /// compiling with exception support.
  185. ///
  186. /// \note The variable must contain an equal sign ('=')
  187. ///
  188. /// \exception std::bad_alloc When compiling with exception support, this will throw
  189. /// std::bad_alloc if memory cannot be acquired. When compiling absent
  190. /// exception support, failure to acquire memory will cause the method
  191. /// to return false.
  192. ws_bool_t push_back(char_type const* variable, ws_size_t cch)
  193. {
  194. WINSTL_ASSERT(NULL != variable);
  195. WINSTL_ASSERT(cch >= 3);
  196. WINSTL_ASSERT(NULL != traits_type::find(variable, cch, '='));
  197. size_type oldSize = m_buffer.size();
  198. WINSTL_ASSERT(m_buffer.size() > 1);
  199. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 1]);
  200. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 2]);
  201. if(!m_buffer.resize(oldSize + cch + 1))
  202. {
  203. return false;
  204. }
  205. else
  206. {
  207. traits_type::copy(&m_buffer[oldSize - 1], variable, cch);
  208. m_buffer[m_buffer.size() - 2] = '\0';
  209. m_buffer[m_buffer.size() - 1] = '\0';
  210. WINSTL_ASSERT(m_buffer.size() > 1);
  211. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 1]);
  212. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 2]);
  213. return true;
  214. }
  215. }
  216. /// \brief Append a NAME= environment variable
  217. ///
  218. /// \param variable The variable
  219. ///
  220. /// \return An indication of success. This will always return true when
  221. /// compiling with exception support.
  222. ///
  223. /// \note The variable must contain an equal sign ('=')
  224. ///
  225. /// \exception std::bad_alloc When compiling with exception support, this will throw
  226. /// std::bad_alloc if memory cannot be acquired. When compiling absent
  227. /// exception support, failure to acquire memory will cause the method
  228. /// to return false.
  229. template <ss_typename_param_k S>
  230. ws_bool_t push_back(S const& variable)
  231. {
  232. return push_back(stlsoft_ns_qual(c_str_data)(variable), stlsoft_ns_qual(c_str_len)(variable));
  233. }
  234. /// \brief Append a full NAME=VALUE environment pair
  235. ///
  236. /// \param name The variable name
  237. /// \param cchName The length of the variable name
  238. /// \param value The variable value
  239. /// \param cchValue The length of the variable value
  240. ///
  241. /// \return An indication of success. This will always return true when
  242. /// compiling with exception support.
  243. ///
  244. /// \exception std::bad_alloc When compiling with exception support, this will throw
  245. /// std::bad_alloc if memory cannot be acquired. When compiling absent
  246. /// exception support, failure to acquire memory will cause the method
  247. /// to return false.
  248. ws_bool_t push_back(char_type const* name, ws_size_t cchName, char_type const* value, ws_size_t cchValue)
  249. {
  250. WINSTL_ASSERT(NULL != name);
  251. WINSTL_ASSERT(NULL != value);
  252. WINSTL_ASSERT(cchName > 1);
  253. // WINSTL_ASSERT(cchValue > 1);
  254. size_type oldSize = m_buffer.size();
  255. WINSTL_ASSERT(m_buffer.size() > 1);
  256. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 1]);
  257. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 2]);
  258. if(!m_buffer.resize(oldSize + cchName + 1 + cchValue + 1))
  259. {
  260. return false;
  261. }
  262. else
  263. {
  264. traits_type::copy(&m_buffer[oldSize - 2], name, cchName);
  265. m_buffer[oldSize - 2 + cchName] = '=';
  266. traits_type::copy(&m_buffer[oldSize - 2 + cchName + 1], value, cchValue);
  267. m_buffer[oldSize - 2 + cchName + 1 + cchValue] = '\0';
  268. m_buffer[m_buffer.size() - 2] = '\0';
  269. m_buffer[m_buffer.size() - 1] = '\0';
  270. WINSTL_ASSERT(m_buffer.size() > 1);
  271. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 1]);
  272. WINSTL_ASSERT('\0' == m_buffer[m_buffer.size() - 2]);
  273. return true;
  274. }
  275. }
  276. /// \brief Append a full NAME=VALUE environment pair
  277. ///
  278. /// \param name The variable name
  279. /// \param value The variable value
  280. ///
  281. /// \return An indication of success. This will always return true when
  282. /// compiling with exception support.
  283. ///
  284. /// \exception std::bad_alloc When compiling with exception support, this will throw
  285. /// std::bad_alloc if memory cannot be acquired. When compiling absent
  286. /// exception support, failure to acquire memory will cause the method
  287. /// to return false.
  288. template< ss_typename_param_k S1
  289. , ss_typename_param_k S2
  290. >
  291. ws_bool_t push_back(S1 const& name, S2 const& value)
  292. {
  293. return 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));
  294. }
  295. /// Empties the block of all variables
  296. void clear()
  297. {
  298. m_buffer.resize(2);
  299. m_buffer[0] = '\0';
  300. m_buffer[1] = '\0';
  301. }
  302. /// Swaps the contents of the two instances
  303. void swap(class_type& rhs) stlsoft_throw_0()
  304. {
  305. m_buffer.swap(rhs.m_buffer);
  306. }
  307. /// @}
  308. /// \name Accessors
  309. /// @{
  310. public:
  311. /// Returns a pointer to the block contents
  312. void const *base() const
  313. {
  314. return m_buffer.data();
  315. }
  316. /// The number of characters in the block
  317. size_type size() const
  318. {
  319. return m_buffer.size();
  320. }
  321. /// The number of characters in the block
  322. ///
  323. /// \note This method is a synonym for size()
  324. size_type length() const
  325. {
  326. return size();
  327. }
  328. /// @}
  329. /** \brief Members
  330. *
  331. * \ingroup group__library__system
  332. */
  333. private:
  334. typedef stlsoft_ns_qual(auto_buffer_old)< char_type
  335. , allocator_type
  336. , 1024
  337. > buffer_type_;
  338. buffer_type_ m_buffer;
  339. };
  340. /* /////////////////////////////////////////////////////////////////////////
  341. * Typedefs for commonly encountered types
  342. */
  343. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  344. /// Specialisation of the basic_path template for the ANSI character type \c char
  345. typedef basic_environment_block<ws_char_a_t> environment_block_a;
  346. /** \brief Specialisation of the basic_environment_block template for the Unicode character type \c wchar_t
  347. *
  348. * \ingroup group__library__system
  349. */
  350. typedef basic_environment_block<ws_char_w_t> environment_block_w;
  351. /** \brief Specialisation of the basic_environment_block template for the Win32 character type \c TCHAR
  352. *
  353. * \ingroup group__library__system
  354. */
  355. typedef basic_environment_block<TCHAR> environment_block;
  356. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  357. /* /////////////////////////////////////////////////////////////////////////
  358. * Unit-testing
  359. */
  360. #ifdef STLSOFT_UNITTEST
  361. # include "./unittest/environment_block_unittest_.h"
  362. #endif /* STLSOFT_UNITTEST */
  363. /* /////////////////////////////////////////////////////////////////////////
  364. * Implementation
  365. */
  366. /* ////////////////////////////////////////////////////////////////////// */
  367. #ifndef _WINSTL_NO_NAMESPACE
  368. # if defined(_STLSOFT_NO_NAMESPACE) || \
  369. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  370. } // namespace winstl
  371. # else
  372. } // namespace winstl_project
  373. } // namespace stlsoft
  374. # endif /* _STLSOFT_NO_NAMESPACE */
  375. #endif /* !_WINSTL_NO_NAMESPACE */
  376. /* ////////////////////////////////////////////////////////////////////// */
  377. #endif /* WINSTL_INCL_WINSTL_SYSTEM_HPP_ENVIRONMENT_BLOCK */
  378. /* ///////////////////////////// end of file //////////////////////////// */