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.

325 lines
11 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: pantheios/inserters/m2w.hpp
  3. *
  4. * Purpose: Inserter class for incorporating multibyte strings into a
  5. * wide string statement.
  6. *
  7. * Created: 22nd November 2010
  8. * Updated: 22nd November 2010
  9. *
  10. * Home: http://www.pantheios.org/
  11. *
  12. * Copyright (c) 2010, Matthew Wilson and Synesis Software
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions are
  17. * met:
  18. *
  19. * - Redistributions of source code must retain the above copyright notice,
  20. * this list of conditions and the following disclaimer.
  21. * - Redistributions in binary form must reproduce the above copyright
  22. * notice, this list of conditions and the following disclaimer in the
  23. * documentation and/or other materials provided with the distribution.
  24. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the
  25. * names of any contributors may be used to endorse or promote products
  26. * derived from this software without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  29. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  30. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  31. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  32. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  33. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  34. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  35. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  36. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  37. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * ////////////////////////////////////////////////////////////////////// */
  41. /** \file pantheios/inserters/m2w.hpp
  42. *
  43. * [C++ only] Inserter class for incorporating multibyte strings into a wide
  44. * string statement.
  45. */
  46. #ifndef PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_M2W
  47. #define PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_M2W
  48. /* /////////////////////////////////////////////////////////////////////////
  49. * Version information
  50. */
  51. #ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
  52. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_M2W_MAJOR 1
  53. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_M2W_MINOR 0
  54. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_M2W_REVISION 0
  55. # define PANTHEIOS_VER_PANTHEIOS_INSERTERS_HPP_M2W_EDIT 1
  56. #endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */
  57. /* /////////////////////////////////////////////////////////////////////////
  58. * Includes
  59. */
  60. #ifndef PANTHEIOS_INCL_PANTHEIOS_H_PANTHEIOS
  61. # include <pantheios/pantheios.h>
  62. #endif /* !PANTHEIOS_INCL_PANTHEIOS_H_PANTHEIOS */
  63. #ifndef PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_FMT
  64. # include <pantheios/inserters/fmt.hpp>
  65. #endif /* !PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_FMT */
  66. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  67. # include <stlsoft/shims/access/string.hpp>
  68. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  69. #ifndef PANTHEIOS_USE_WIDE_STRINGS
  70. # include <stlsoft/string/string_view.hpp>
  71. #endif /* !PANTHEIOS_USE_WIDE_STRINGS */
  72. /* /////////////////////////////////////////////////////////////////////////
  73. * Namespace
  74. */
  75. #if !defined(PANTHEIOS_NO_NAMESPACE)
  76. namespace pantheios
  77. {
  78. #endif /* !PANTHEIOS_NO_NAMESPACE */
  79. /* /////////////////////////////////////////////////////////////////////////
  80. * Inserter classes
  81. */
  82. /** Class for inserting wide strings into Pantheios diagnostic logging
  83. * statements.
  84. *
  85. * \ingroup group__application_layer_interface__inserters
  86. *
  87. * This class converts a m2w variable into a string, thereby enabling
  88. * it to be inserted into a logging statement. Consider the following
  89. * statement:
  90. *
  91. * \code
  92. char s[] = "abc";
  93. wchar_t ws = L"def";
  94. std::wstring wstr(L"ghi");
  95. pantheios::log(pantheios::notice, L"s=", pantheios::m2w(s), L", ws=", ws, L", wstr=", wstr);
  96. * \endcode
  97. *
  98. * This will produce the output:
  99. *
  100. * &nbsp;&nbsp;&nbsp;&nbsp;<b>s=abc, ws=def, str=ghi</b>
  101. */
  102. #ifndef PANTHEIOS_USE_WIDE_STRINGS
  103. typedef stlsoft_ns_qual(string_view) m2w;
  104. #else /* ? !PANTHEIOS_USE_WIDE_STRINGS */
  105. class m2w
  106. {
  107. public: // Member Types
  108. /// This type
  109. typedef m2w class_type;
  110. public: // Construction
  111. /// Construct from a c-style string
  112. explicit m2w(char const* s);
  113. /// Construct from a pointer to a string and a given length
  114. m2w(char const* s, size_t len);
  115. /// Construct from a widestring of unknown type
  116. ///
  117. /// \warning This method must only be used "inline", i.e. in a log
  118. /// statement. If you create a separate instance of m2w using this
  119. /// constructor and attempt to access its converted value - either
  120. /// directly, via c_str()/data(), or indirectly via inserting into a
  121. /// log statement - the program will have undefined behaviour.
  122. template <typename WS>
  123. explicit m2w(WS const& ws)
  124. {
  125. // If the init_() call fails to compile with an error message that
  126. // mentions
  127. // 'containing your_wide_type_relies_on_intermediate_shim_conversions_which_are_prohibited_unless_PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES_is_defined'
  128. // then the (wide) shims for the type WS use intermediate instances
  129. // of conversion classes, and would cause undefined behaviour if
  130. // you were to use it any a non-"inline" log statement. If you are
  131. // sure you are using the inserter correctly, then #define the
  132. // preprocessor symbol PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES to
  133. // allow it to compile.
  134. #ifndef PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES
  135. int unused =
  136. #endif /* !PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES */
  137. init_(::stlsoft::c_str_data_a(ws), ::stlsoft::c_str_len_a(ws));
  138. #ifndef PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES
  139. STLSOFT_SUPPRESS_UNUSED(unused);
  140. #endif /* !PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES */
  141. }
  142. /// Releases any resources allocated for the conversion
  143. ~m2w() stlsoft_throw_0();
  144. private:
  145. #if !defined(STLSOFT_COMPILER_IS_GCC)
  146. m2w(class_type const&);
  147. #endif /* compiler */
  148. class_type& operator =(class_type const&);
  149. public: // Accessors
  150. /// A possibly non-nul-terminated non-null pointer to the c-style string representation of the m2w
  151. wchar_t const* data() const;
  152. /// A nul-terminated non-null pointer to the c-style string representation of the m2w
  153. wchar_t const* c_str() const;
  154. /// The length of the c-style string representation of the m2w
  155. size_t length() const;
  156. private: // Implementation
  157. int init_(char const* s, size_t n);
  158. #ifndef PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES
  159. struct your_wide_type_relies_on_intermediate_shim_conversions_which_are_prohibited_unless_PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES_is_defined;
  160. template <typename T0, typename T1>
  161. your_wide_type_relies_on_intermediate_shim_conversions_which_are_prohibited_unless_PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES_is_defined init_(T0 const&, T1 const&);
  162. #endif /* !PANTHEIOS_SAFE_ALLOW_SHIM_INTERMEDIATES */
  163. void construct_() const;
  164. void construct_();
  165. static size_t sentinelLength_()
  166. {
  167. return ~size_t(0);
  168. }
  169. private: // Member Variables
  170. // We can't use auto_buffer because GCC is a total dullard, "helpfully"
  171. // informing us that it can't generate a copy-constructor when we're
  172. // telling *it* that we're proscribing that very thing.
  173. //
  174. // So, we're just going to have to manage our own memory, and use up
  175. // two more hours that could be more profitably spent on something else
  176. char const* m_source;
  177. size_t m_sourceLen;
  178. wchar_t* m_result;
  179. size_t m_length;
  180. };
  181. #endif /* !PANTHEIOS_USE_WIDE_STRINGS */
  182. /* /////////////////////////////////////////////////////////////////////////
  183. * String Access Shims
  184. */
  185. #ifdef PANTHEIOS_USE_WIDE_STRINGS
  186. # if !defined(PANTHEIOS_NO_NAMESPACE)
  187. namespace shims
  188. {
  189. # endif /* !PANTHEIOS_NO_NAMESPACE */
  190. # ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
  191. /** \overload c_str_data_w(m2w const&) */
  192. inline wchar_t const* c_str_data_w(m2w const& r)
  193. {
  194. return r.data();
  195. }
  196. /** \overload c_str_data(m2w const&) */
  197. inline pan_char_t const* c_str_data(m2w const& r)
  198. {
  199. return r.data();
  200. }
  201. /** \overload c_str_len_w(m2w const&) */
  202. inline size_t c_str_len_w(m2w const& r)
  203. {
  204. return r.length();
  205. }
  206. /** \overload c_str_len(m2w const&) */
  207. inline size_t c_str_len(m2w const& r)
  208. {
  209. return r.length();
  210. }
  211. /** \overload c_str_ptr_w(m2w const&) */
  212. inline wchar_t const* c_str_ptr_w(m2w const& r)
  213. {
  214. return r.c_str();
  215. }
  216. /** \overload c_str_ptr(m2w const&) */
  217. inline pan_char_t const* c_str_ptr(m2w const& r)
  218. {
  219. return r.c_str();
  220. }
  221. # if !defined(PANTHEIOS_NO_NAMESPACE)
  222. } /* namespace shims */
  223. # if defined(STLSOFT_COMPILER_IS_GCC)
  224. /* GCC does not seem to correctly handle the phases of
  225. * processing of C++ templates, so we need to 'use' the
  226. * shims into the same namespace as the inserter class
  227. * in order that ADL can suffice instead.
  228. */
  229. using ::pantheios::shims::c_str_data_w;
  230. using ::pantheios::shims::c_str_data;
  231. using ::pantheios::shims::c_str_len_w;
  232. using ::pantheios::shims::c_str_len;
  233. using ::pantheios::shims::c_str_ptr_w;
  234. using ::pantheios::shims::c_str_ptr;
  235. # endif /* compiler */
  236. # endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */
  237. # endif /* !PANTHEIOS_NO_NAMESPACE */
  238. #endif /* PANTHEIOS_USE_WIDE_STRINGS */
  239. /* /////////////////////////////////////////////////////////////////////////
  240. * Namespace
  241. */
  242. #if !defined(PANTHEIOS_NO_NAMESPACE)
  243. } /* namespace pantheios */
  244. # ifdef PANTHEIOS_USE_WIDE_STRINGS
  245. namespace stlsoft
  246. {
  247. // 'Export' the string access shims into the STLSoft namespace
  248. //
  249. // c_str_ptr(_w) is not necessary for version 1.0 of Pantheios, but it's
  250. // defined and exported in order to allow for the case where someone
  251. // may find a legitimate use for the conversion classes additional to
  252. // the type-tunneling of the Pantheios API.
  253. using ::pantheios::shims::c_str_data_w;
  254. using ::pantheios::shims::c_str_data;
  255. using ::pantheios::shims::c_str_len_w;
  256. using ::pantheios::shims::c_str_len;
  257. using ::pantheios::shims::c_str_ptr_w;
  258. using ::pantheios::shims::c_str_ptr;
  259. }
  260. # endif /* PANTHEIOS_USE_WIDE_STRINGS */
  261. #endif /* !PANTHEIOS_NO_NAMESPACE */
  262. /* /////////////////////////////////////////////////////////////////////////
  263. * Inclusion
  264. */
  265. #ifdef STLSOFT_PPF_pragma_once_SUPPORT
  266. # pragma once
  267. #endif /* STLSOFT_PPF_pragma_once_SUPPORT */
  268. /* ////////////////////////////////////////////////////////////////////// */
  269. #endif /* !PANTHEIOS_INCL_PANTHEIOS_INSERTERS_HPP_M2W */
  270. /* ///////////////////////////// end of file //////////////////////////// */