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.

324 lines
11 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: pantheios/inserters/w2m.hpp
  3. *
  4. * Purpose: Class for inserting wide strings.
  5. *
  6. * Created: 2nd September 2008
  7. * Updated: 23rd July 2010
  8. *
  9. * Home: http://www.pantheios.org/
  10. *
  11. * Copyright (c) 2008-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 pantheios/inserters/w2m.hpp
  41. *
  42. * [C++ only] Class for inserting wide strings.
  43. */
  44. #ifndef PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_W2M
  45. #define PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_W2M
  46. /* /////////////////////////////////////////////////////////////////////////
  47. * Version information
  48. */
  49. #ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
  50. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_W2M_MAJOR 1
  51. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_W2M_MINOR 2
  52. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_W2M_REVISION 2
  53. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_W2M_EDIT 13
  54. #endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */
  55. /* /////////////////////////////////////////////////////////////////////////
  56. * Includes
  57. */
  58. #ifndef PANTHEIOS_INCL_PANTHEIOS_H_PANTHEIOS
  59. # include <pantheios/pantheios.h>
  60. #endif /* !PANTHEIOS_INCL_PANTHEIOS_H_PANTHEIOS */
  61. #ifndef PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_FMT
  62. # include <pantheios/inserters/fmt.hpp>
  63. #endif /* !PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_FMT */
  64. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  65. # include <stlsoft/shims/access/string.hpp>
  66. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  67. #ifdef PANTHEIOS_USE_WIDE_STRINGS
  68. # include <stlsoft/string/string_view.hpp>
  69. #endif /* PANTHEIOS_USE_WIDE_STRINGS */
  70. /* /////////////////////////////////////////////////////////////////////////
  71. * Namespace
  72. */
  73. #if !defined(PANTHEIOS_NO_NAMESPACE)
  74. namespace pantheios
  75. {
  76. #endif /* !PANTHEIOS_NO_NAMESPACE */
  77. /* /////////////////////////////////////////////////////////////////////////
  78. * Inserter classes
  79. */
  80. /** Class for inserting wide strings into Pantheios diagnostic logging
  81. * statements.
  82. *
  83. * \ingroup group__application_layer_interface__inserters
  84. *
  85. * This class converts a w2m variable into a string, thereby enabling
  86. * it to be inserted into a logging statement. Consider the following
  87. * statement:
  88. *
  89. * \code
  90. wchar_t ws = L"abc";
  91. char s[] = "abc";
  92. std::string str("def");
  93. pantheios::log(pantheios::notice, "s=", s, ", c=", pantheios::w2m(ws), ", str=", str);
  94. * \endcode
  95. *
  96. * This will produce the output:
  97. *
  98. * &nbsp;&nbsp;&nbsp;&nbsp;<b>s=abc, c=abc, str=def</b>
  99. */
  100. #ifdef PANTHEIOS_USE_WIDE_STRINGS
  101. typedef stlsoft_ns_qual(wstring_view) w2m;
  102. #else /* ? PANTHEIOS_USE_WIDE_STRINGS */
  103. class w2m
  104. {
  105. public: // Member Types
  106. /// This type
  107. typedef w2m class_type;
  108. public: // Construction
  109. /// Construct from a c-style string
  110. explicit w2m(wchar_t const* s);
  111. /// Construct from a pointer to a string and a given length
  112. w2m(wchar_t const* s, size_t len);
  113. /// Construct from a widestring of unknown type
  114. ///
  115. /// \warning This method must only be used "inline", i.e. in a log
  116. /// statement. If you create a separate instance of w2m using this
  117. /// constructor and attempt to access its converted value - either
  118. /// directly, via c_str()/data(), or indirectly via inserting into a
  119. /// log statement - the program will have undefined behaviour.
  120. template <typename WS>
  121. explicit w2m(WS const& ws)
  122. {
  123. // If the init_() call fails to compile with an error message that
  124. // mentions
  125. // 'containing your_wide_type_relies_on_intermediate_shim_conversions_which_are_prohibited_unless_PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES_is_defined'
  126. // then the (wide) shims for the type WS use intermediate instances
  127. // of conversion classes, and would cause undefined behaviour if
  128. // you were to use it any a non-"inline" log statement. If you are
  129. // sure you are using the inserter correctly, then #define the
  130. // preprocessor symbol PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES to
  131. // allow it to compile.
  132. #ifndef PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES
  133. int unused =
  134. #endif /* !PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES */
  135. init_(::stlsoft::c_str_data_w(ws), ::stlsoft::c_str_len_w(ws));
  136. #ifndef PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES
  137. STLSOFT_SUPPRESS_UNUSED(unused);
  138. #endif /* !PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES */
  139. }
  140. /// Releases any resources allocated for the conversion
  141. ~w2m() stlsoft_throw_0();
  142. private:
  143. #if !defined(STLSOFT_COMPILER_IS_GCC)
  144. w2m(class_type const&);
  145. #endif /* compiler */
  146. class_type& operator =(class_type const&);
  147. public: // Accessors
  148. /// A possibly non-nul-terminated non-null pointer to the c-style string representation of the w2m
  149. char const* data() const;
  150. /// A nul-terminated non-null pointer to the c-style string representation of the w2m
  151. char const* c_str() const;
  152. /// The length of the c-style string representation of the w2m
  153. size_t length() const;
  154. private: // Implementation
  155. int init_(wchar_t const* s, size_t n);
  156. #ifndef PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES
  157. struct your_wide_type_relies_on_intermediate_shim_conversions_which_are_prohibited_unless_PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES_is_defined;
  158. template <typename T0, typename T1>
  159. your_wide_type_relies_on_intermediate_shim_conversions_which_are_prohibited_unless_PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES_is_defined init_(T0 const&, T1 const&);
  160. #endif /* !PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES */
  161. void construct_() const;
  162. void construct_();
  163. static size_t sentinelLength_()
  164. {
  165. return ~size_t(0);
  166. }
  167. private: // Member Variables
  168. // We can't use auto_buffer because GCC is a total dullard, "helpfully"
  169. // informing us that it can't generate a copy-constructor when we're
  170. // telling *it* that we're proscribing that very thing.
  171. //
  172. // So, we're just going to have to manage our own memory, and use up
  173. // two more hours that could be more profitably spent on something else
  174. wchar_t const* m_source;
  175. size_t m_sourceLen;
  176. char* m_result;
  177. size_t m_length;
  178. };
  179. #endif /* PANTHEIOS_USE_WIDE_STRINGS */
  180. /* /////////////////////////////////////////////////////////////////////////
  181. * String Access Shims
  182. */
  183. #ifndef PANTHEIOS_USE_WIDE_STRINGS
  184. #ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
  185. # if !defined(PANTHEIOS_NO_NAMESPACE)
  186. namespace shims
  187. {
  188. # endif /* !PANTHEIOS_NO_NAMESPACE */
  189. /** \overload c_str_data_a(w2m const&) */
  190. inline char const* c_str_data_a(w2m const& r)
  191. {
  192. return r.data();
  193. }
  194. /** \overload c_str_data(w2m const&) */
  195. inline pan_char_t const* c_str_data(w2m const& r)
  196. {
  197. return r.data();
  198. }
  199. /** \overload c_str_len_a(w2m const&) */
  200. inline size_t c_str_len_a(w2m const& r)
  201. {
  202. return r.length();
  203. }
  204. /** \overload c_str_len(w2m const&) */
  205. inline size_t c_str_len(w2m const& r)
  206. {
  207. return r.length();
  208. }
  209. /** \overload c_str_ptr_a(w2m const&) */
  210. inline char const* c_str_ptr_a(w2m const& r)
  211. {
  212. return r.c_str();
  213. }
  214. /** \overload c_str_ptr(w2m const&) */
  215. inline pan_char_t const* c_str_ptr(w2m const& r)
  216. {
  217. return r.c_str();
  218. }
  219. # if !defined(PANTHEIOS_NO_NAMESPACE)
  220. } /* namespace shims */
  221. # if defined(STLSOFT_COMPILER_IS_GCC)
  222. /* GCC does not seem to correctly handle the phases of
  223. * processing of C++ templates, so we need to 'use' the
  224. * shims into the same namespace as the inserter class
  225. * in order that ADL can suffice instead.
  226. */
  227. using ::pantheios::shims::c_str_data_a;
  228. using ::pantheios::shims::c_str_data;
  229. using ::pantheios::shims::c_str_len_a;
  230. using ::pantheios::shims::c_str_len;
  231. using ::pantheios::shims::c_str_ptr_a;
  232. using ::pantheios::shims::c_str_ptr;
  233. # endif /* compiler */
  234. # endif /* !PANTHEIOS_NO_NAMESPACE */
  235. #endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */
  236. #endif /* PANTHEIOS_USE_WIDE_STRINGS */
  237. /* /////////////////////////////////////////////////////////////////////////
  238. * Namespace
  239. */
  240. #if !defined(PANTHEIOS_NO_NAMESPACE)
  241. } /* namespace pantheios */
  242. #ifndef PANTHEIOS_USE_WIDE_STRINGS
  243. namespace stlsoft
  244. {
  245. // 'Export' the string access shims into the STLSoft namespace
  246. //
  247. // c_str_ptr(_a) is not necessary for version 1.0 of Pantheios, but it's
  248. // defined and exported in order to allow for the case where someone
  249. // may find a legitimate use for the conversion classes additional to
  250. // the type-tunneling of the Pantheios API.
  251. using ::pantheios::shims::c_str_data_a;
  252. using ::pantheios::shims::c_str_data;
  253. using ::pantheios::shims::c_str_len_a;
  254. using ::pantheios::shims::c_str_len;
  255. using ::pantheios::shims::c_str_ptr_a;
  256. using ::pantheios::shims::c_str_ptr;
  257. }
  258. #endif /* PANTHEIOS_USE_WIDE_STRINGS */
  259. #endif /* !PANTHEIOS_NO_NAMESPACE */
  260. /* /////////////////////////////////////////////////////////////////////////
  261. * Inclusion
  262. */
  263. #ifdef STLSOFT_PPF_pragma_once_SUPPORT
  264. # pragma once
  265. #endif /* STLSOFT_PPF_pragma_once_SUPPORT */
  266. /* ////////////////////////////////////////////////////////////////////// */
  267. #endif /* !PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_W2M */
  268. /* ///////////////////////////// end of file //////////////////////////// */