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.

369 lines
11 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/util/exception_string.hpp
  3. *
  4. * Purpose: Contains the exception_string limited functionality string class.
  5. *
  6. * Created: 26th December 2005
  7. * Updated: 28th May 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2005-2010, 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
  16. * met:
  17. *
  18. * - Redistributions of source code must retain the above copyright notice,
  19. * this list of conditions and the following disclaimer.
  20. * - Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in the
  22. * documentation and/or other materials provided with the distribution.
  23. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the
  24. * names of any contributors may be used to endorse or promote products
  25. * derived from this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  28. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  29. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  31. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  32. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  33. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  34. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * ////////////////////////////////////////////////////////////////////// */
  40. /** \file stlsoft/util/exception_string.hpp
  41. *
  42. * \brief [C++ only] Definition of the stlsoft::exception_string class
  43. * (\ref group__library__utility "Utility" Library).
  44. */
  45. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING
  46. #define STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define STLSOFT_VER_STLSOFT_UTIL_HPP_EXCEPTION_STRING_MAJOR 1
  49. # define STLSOFT_VER_STLSOFT_UTIL_HPP_EXCEPTION_STRING_MINOR 4
  50. # define STLSOFT_VER_STLSOFT_UTIL_HPP_EXCEPTION_STRING_REVISION 1
  51. # define STLSOFT_VER_STLSOFT_UTIL_HPP_EXCEPTION_STRING_EDIT 21
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. */
  56. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  57. # include <stlsoft/stlsoft.h>
  58. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  59. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
  60. # include <stlsoft/memory/allocator_selector.hpp>
  61. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR */
  62. #ifndef STLSOFT_INCL_STLSOFT_HPP_MEMORY_AUTO_BUFFER
  63. # include <stlsoft/memory/auto_buffer.hpp>
  64. #endif /* !STLSOFT_INCL_STLSOFT_HPP_MEMORY_AUTO_BUFFER */
  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. #ifdef STLSOFT_UNITTEST
  69. # include <string.h>
  70. #endif /* STLSOFT_UNITTEST */
  71. /* /////////////////////////////////////////////////////////////////////////
  72. * Namespace
  73. */
  74. #ifndef _STLSOFT_NO_NAMESPACE
  75. namespace stlsoft
  76. {
  77. #endif /* _STLSOFT_NO_NAMESPACE */
  78. /* /////////////////////////////////////////////////////////////////////////
  79. * Classes
  80. */
  81. /** Minimalist string class for use within exception classes.
  82. *
  83. * \ingroup group__library__string
  84. */
  85. class exception_string
  86. {
  87. /// \name Member Types
  88. /// @{
  89. public:
  90. /// The character type
  91. typedef char char_type;
  92. /// The traits type
  93. typedef stlsoft_char_traits<char_type> traits_type;
  94. /// The allocator type
  95. typedef allocator_selector<char_type>::allocator_type allocator_type;
  96. /// This type
  97. typedef exception_string class_type;
  98. /// The size type
  99. typedef ss_size_t size_type;
  100. private:
  101. typedef auto_buffer_old<char_type, allocator_type, 96> buffer_type_;
  102. /// @}
  103. /// \name Construction
  104. /// @{
  105. public:
  106. /// Constructs an empty exception
  107. exception_string()
  108. : m_message(1)
  109. {
  110. m_message[0] = '\0';
  111. }
  112. /// Constructs an exception from the given message
  113. ss_explicit_k exception_string(char_type const* message)
  114. : m_message(1 + ((NULL == message) ? 0 : traits_type::length(message)))
  115. {
  116. traits_type::copy(&m_message[0], message, m_message.size() - 1);
  117. m_message[m_message.size() - 1] = '\0';
  118. }
  119. /// Constructs an exception from the given message, to the given length
  120. exception_string(char_type const* message, size_type len)
  121. : m_message(1 + len)
  122. {
  123. traits_type::copy(&m_message[0], message, m_message.size() - 1);
  124. m_message[m_message.size() - 1] = '\0';
  125. }
  126. /// Copies the message from the given instance
  127. exception_string(class_type const& rhs)
  128. : m_message(rhs.m_message.size())
  129. {
  130. traits_type::copy(&m_message[0], &rhs.m_message[0], m_message.size());
  131. m_message[m_message.size() - 1] = '\0';
  132. }
  133. /// Appends the given string to the message
  134. void operator +=(char_type const* s)
  135. {
  136. const ss_size_t n = traits_type::length(s);
  137. const ss_size_t currLen = this->length();
  138. if(m_message.resize(m_message.size() + n))
  139. {
  140. traits_type::copy(&m_message[currLen], s, n);
  141. m_message[m_message.size() - 1] = '\0';
  142. }
  143. }
  144. /// Appends the given string to the message
  145. void operator +=(class_type const& rhs)
  146. {
  147. const ss_size_t n = rhs.length();
  148. const ss_size_t currLen = this->length();
  149. if(m_message.resize(m_message.size() + n))
  150. {
  151. traits_type::copy(&m_message[currLen], rhs.c_str(), n);
  152. m_message[m_message.size() - 1] = '\0';
  153. }
  154. }
  155. /// Appends the given character to the message
  156. void operator +=(char_type ch)
  157. {
  158. const ss_size_t n = 1;
  159. const ss_size_t currLen = this->length();
  160. if(m_message.resize(m_message.size() + n))
  161. {
  162. traits_type::copy(&m_message[currLen], &ch, n);
  163. m_message[m_message.size() - 1] = '\0';
  164. }
  165. }
  166. /// Truncates the string to the given length
  167. ///
  168. /// \param n The length to which the string's contents will be truncated
  169. ///
  170. /// \remarks This method is a no-op if the length specified is greater
  171. /// than the current length
  172. void truncate(size_type n)
  173. {
  174. if(n < m_message.size() - 1)
  175. {
  176. if(m_message.resize(n + 1))
  177. {
  178. m_message[m_message.size() - 1] = '\0';
  179. }
  180. }
  181. }
  182. /// @}
  183. /// \name Attributes
  184. /// @{
  185. public:
  186. /// Returns a null-terminated c-style string string representing
  187. /// the message
  188. char_type const* c_str() const
  189. {
  190. return data();
  191. }
  192. /// Returns a null-terminated c-style string string representing
  193. /// the message
  194. char_type const* data() const
  195. {
  196. return m_message.data();
  197. }
  198. /// Returns the number of characters in the message
  199. size_type length() const
  200. {
  201. return size();
  202. }
  203. /// Returns the number of characters in the message
  204. size_type size() const
  205. {
  206. STLSOFT_ASSERT(m_message.size() > 0);
  207. return m_message.size() - 1;
  208. }
  209. /// Indicates whether or not the message is blank
  210. ss_bool_t empty() const
  211. {
  212. return 0 == this->length();
  213. }
  214. /// @}
  215. /// \name Members
  216. /// @{
  217. private:
  218. buffer_type_ m_message;
  219. /// @}
  220. /// \name Not to be implemented
  221. /// @{
  222. private:
  223. class_type& operator =(class_type const&);
  224. /// @}
  225. };
  226. /* /////////////////////////////////////////////////////////////////////////
  227. * Shims
  228. */
  229. inline exception_string::char_type const* c_str_data(exception_string const& xs)
  230. {
  231. return xs.data();
  232. }
  233. inline exception_string::size_type c_str_len(exception_string const& xs)
  234. {
  235. return xs.size();
  236. }
  237. inline exception_string::char_type const* c_str_ptr(exception_string const& xs)
  238. {
  239. return xs.c_str();
  240. }
  241. inline exception_string::char_type const* c_str_data_a(exception_string const& xs)
  242. {
  243. return c_str_data(xs);
  244. }
  245. inline exception_string::size_type c_str_len_a(exception_string const& xs)
  246. {
  247. return c_str_len(xs);
  248. }
  249. inline exception_string::char_type const* c_str_ptr_a(exception_string const& xs)
  250. {
  251. return c_str_ptr(xs);
  252. }
  253. /* /////////////////////////////////////////////////////////////////////////
  254. * Operators
  255. */
  256. /** Adds a C-style string to an exception_string
  257. *
  258. * \ingroup group__library__string
  259. */
  260. inline exception_string operator +(exception_string const& lhs, exception_string::char_type const* rhs)
  261. {
  262. exception_string s(lhs);
  263. s += rhs;
  264. return s;
  265. }
  266. /** Adds an exception_string to a character
  267. *
  268. * \ingroup group__library__string
  269. */
  270. inline exception_string operator +(exception_string::char_type lhs, exception_string const& rhs)
  271. {
  272. exception_string::char_type lhs_[2] = { lhs, '\0' };
  273. exception_string s(lhs_);
  274. s += rhs;
  275. return s;
  276. }
  277. /** Adds a character to an exception_string
  278. *
  279. * \ingroup group__library__string
  280. */
  281. inline exception_string operator +(exception_string const& lhs, exception_string::char_type rhs)
  282. {
  283. exception_string s(lhs);
  284. s += rhs;
  285. return s;
  286. }
  287. /** Adds an exception_string to a C-style string
  288. *
  289. * \ingroup group__library__string
  290. */
  291. inline exception_string operator +(exception_string::char_type const* lhs, exception_string const& rhs)
  292. {
  293. exception_string s(lhs);
  294. s += rhs;
  295. return s;
  296. }
  297. /** Adds an exception_string to an exception_string
  298. *
  299. * \ingroup group__library__string
  300. */
  301. inline exception_string operator +(exception_string const& lhs, exception_string const& rhs)
  302. {
  303. exception_string s(lhs);
  304. s += rhs;
  305. return s;
  306. }
  307. ////////////////////////////////////////////////////////////////////////////
  308. // Unit-testing
  309. #ifdef STLSOFT_UNITTEST
  310. # include "./unittest/exception_string_unittest_.h"
  311. #endif /* STLSOFT_UNITTEST */
  312. /* ////////////////////////////////////////////////////////////////////// */
  313. #ifndef _STLSOFT_NO_NAMESPACE
  314. } // namespace stlsoft
  315. #endif /* _STLSOFT_NO_NAMESPACE */
  316. /* ////////////////////////////////////////////////////////////////////// */
  317. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING */
  318. /* ///////////////////////////// end of file //////////////////////////// */