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.

294 lines
10 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: platformstl/filesystem/cwd_stack.hpp
  3. *
  4. * Purpose: Platform header for the filesystem_traits components.
  5. *
  6. * Created: 16th July 2006
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2006-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 platformstl/filesystem/cwd_stack.hpp
  40. *
  41. * \brief [C++ only] Definition of the platformstl::cwd_stack
  42. * class template
  43. * (\ref group__library__filesystem "File System" Library).
  44. */
  45. #ifndef PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK
  46. #define PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK
  47. /* File version */
  48. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  49. # define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK_MAJOR 2
  50. # define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK_MINOR 1
  51. # define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK_REVISION 5
  52. # define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK_EDIT 25
  53. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  54. /* /////////////////////////////////////////////////////////////////////////
  55. * Includes
  56. */
  57. #ifndef PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_PLATFORMSTL
  58. # include <platformstl/platformstl.hpp>
  59. #endif /* !PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_PLATFORMSTL */
  60. #ifndef PLATFORMSTL_INCL_PLATFORMSTL_ERROR_HPP_EXCEPTIONS
  61. # include <platformstl/error/exceptions.hpp>
  62. #endif /* !PLATFORMSTL_INCL_PLATFORMSTL_ERROR_HPP_EXCEPTIONS */
  63. #ifndef PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_CURRENT_DIRECTORY
  64. # include <platformstl/filesystem/current_directory.hpp>
  65. #endif /* !PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_CURRENT_DIRECTORY */
  66. #ifndef PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
  67. # include <platformstl/filesystem/filesystem_traits.hpp>
  68. #endif /* !PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS */
  69. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
  70. # include <stlsoft/string/simple_string.hpp>
  71. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */
  72. #ifndef STLSOFT_INCL_STACK
  73. # define STLSOFT_INCL_STACK
  74. # include <stack>
  75. #endif /* !STLSOFT_INCL_STACK */
  76. /* /////////////////////////////////////////////////////////////////////////
  77. * Namespace
  78. */
  79. #if defined(_STLSOFT_NO_NAMESPACE) || \
  80. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  81. /* There is no stlsoft namespace, so must define ::platformstl */
  82. namespace platformstl
  83. {
  84. #else
  85. /* Define stlsoft::platformstl_project */
  86. namespace stlsoft
  87. {
  88. namespace platformstl_project
  89. {
  90. #endif /* _STLSOFT_NO_NAMESPACE */
  91. /* /////////////////////////////////////////////////////////////////////////
  92. * Classes
  93. */
  94. /** \brief Acts as a stack for current working directory changes, setting
  95. * the current working directory with <code>push()</code>, and resetting
  96. * to its previous value with <code>pop()</code>.
  97. *
  98. * \ingroup group__library__filesystem
  99. */
  100. template< typename C
  101. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  102. , typename XP = platformstl::platform_exception_policy
  103. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  104. , typename XP = stlsoft::nothrow_exception_policy
  105. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  106. >
  107. class basic_cwd_stack
  108. {
  109. public:
  110. typedef C char_type;
  111. typedef XP exception_policy_type;
  112. typedef stlsoft::basic_simple_string<C> string_type;
  113. typedef bool bool_type;
  114. typedef stlsoft_ns_qual(ss_size_t) size_type;
  115. private:
  116. typedef filesystem_traits<C> traits_type;
  117. typedef std::stack<string_type> stack_type;
  118. public:
  119. string_type const &top() const;
  120. void push(string_type const& directory);
  121. ///
  122. /// \exception platformstl::platform_exception Thrown if the directory
  123. void pop();
  124. ///
  125. ///
  126. /// \remarks If fails, then platformstl::system_traits<C>::get_last_error() gives the error
  127. bool_type try_pop();
  128. public:
  129. /// Indicates whether the stack is empty
  130. bool_type empty() const;
  131. /// [DEPRECATED] Indicates whether the stack is empty
  132. ///
  133. /// \deprecated Use empty() instead
  134. bool_type is_empty() const;
  135. /// Indicates the number of directories in the stack
  136. size_type size() const;
  137. private:
  138. string_type const &translate_environment_(string_type const& directory, string_type &trueDirectory);
  139. private:
  140. stack_type m_stack;
  141. // TODO: if throws, then implies that the class keeps a lock on the directory, if poss.
  142. #if 0
  143. struct directory
  144. {
  145. string_type path;
  146. file_handle handle; // This keeps the directory from being removed
  147. };
  148. #endif /* 0 */
  149. };
  150. /* /////////////////////////////////////////////////////////////////////////
  151. * Typedefs
  152. */
  153. typedef basic_cwd_stack<ss_char_a_t> cwd_stack_a;
  154. typedef basic_cwd_stack<ss_char_w_t> cwd_stack_w;
  155. typedef basic_cwd_stack<ss_char_a_t> cwd_stack;
  156. /* /////////////////////////////////////////////////////////////////////////
  157. * Implementation
  158. */
  159. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  160. template <typename C, typename XP>
  161. inline ss_typename_type_ret_k basic_cwd_stack<C, XP>::string_type const& basic_cwd_stack<C, XP>::translate_environment_(ss_typename_type_k basic_cwd_stack<C, XP>::string_type const& directory, ss_typename_type_k basic_cwd_stack<C, XP>::string_type &trueDirectory)
  162. {
  163. if(directory.end() != std::find(directory.begin(), directory.end(), '%'))
  164. {
  165. stlsoft::auto_buffer<char_type> buffer(1 + traits_type::expand_environment_strings(directory.c_str(), NULL, 0));
  166. const stlsoft_ns_qual(ss_size_t) cch = traits_type::expand_environment_strings(directory.c_str(), &buffer[0], buffer.size());
  167. trueDirectory.assign(buffer.data(), cch);
  168. return trueDirectory;
  169. }
  170. return directory;
  171. }
  172. template <typename C, typename XP>
  173. inline ss_typename_type_ret_k basic_cwd_stack<C, XP>::size_type basic_cwd_stack<C, XP>::size() const
  174. {
  175. return m_stack.size();
  176. }
  177. template <typename C, typename XP>
  178. inline ss_typename_type_ret_k basic_cwd_stack<C, XP>::bool_type basic_cwd_stack<C, XP>::empty() const
  179. {
  180. return 0 == size();
  181. }
  182. template <typename C, typename XP>
  183. inline ss_typename_type_ret_k basic_cwd_stack<C, XP>::bool_type basic_cwd_stack<C, XP>::is_empty() const
  184. {
  185. return empty();
  186. }
  187. template <typename C, typename XP>
  188. inline void basic_cwd_stack<C, XP>::push(ss_typename_type_k basic_cwd_stack<C, XP>::string_type const& directory)
  189. {
  190. stlsoft::auto_buffer<char_type> buffer(1 + traits_type::get_current_directory(static_cast<char_type*>(NULL), 0));
  191. const stlsoft_ns_qual(ss_size_t) cch = traits_type::get_current_directory(&buffer[0], buffer.size());
  192. string_type cwd(buffer.data(), cch);
  193. string_type trueDirectory;
  194. m_stack.push(cwd);
  195. if(!traits_type::set_current_directory(translate_environment_(directory, trueDirectory).c_str()))
  196. {
  197. m_stack.pop();
  198. exception_policy_type xp;
  199. xp("Failed to change directory", traits_type::get_last_error());
  200. }
  201. }
  202. template <typename C, typename XP>
  203. inline void basic_cwd_stack<C, XP>::pop()
  204. {
  205. STLSOFT_ASSERT(!empty());
  206. const string_type directory = m_stack.top();
  207. m_stack.pop();
  208. if(!traits_type::set_current_directory(directory.c_str()))
  209. {
  210. exception_policy_type xp;
  211. xp("Failed to restore directory", traits_type::get_last_error());
  212. }
  213. }
  214. template <typename C, typename XP>
  215. inline ss_typename_type_ret_k basic_cwd_stack<C, XP>::bool_type basic_cwd_stack<C, XP>::try_pop()
  216. {
  217. STLSOFT_ASSERT(!empty());
  218. string_type const &directory = m_stack.top();
  219. if(!traits_type::set_current_directory(directory.c_str()))
  220. {
  221. return false;
  222. }
  223. else
  224. {
  225. m_stack.pop();
  226. return true;
  227. }
  228. }
  229. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  230. /* ////////////////////////////////////////////////////////////////////// */
  231. #if defined(_STLSOFT_NO_NAMESPACE) || \
  232. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  233. } // namespace platformstl
  234. #else
  235. } // namespace platformstl_project
  236. } // namespace stlsoft
  237. #endif /* _STLSOFT_NO_NAMESPACE */
  238. /* ////////////////////////////////////////////////////////////////////// */
  239. #endif /* !PLATFORMSTL_INCL_PLATFORMSTL_FILESYSTEM_HPP_CWD_STACK */
  240. /* ///////////////////////////// end of file //////////////////////////// */