kodi
Clix.h
1 // ------------------------------------------------------------------------------------------- //
2 // clix.h
3 //
4 // http://www.nuclex.org/articles/5-cxx/10-marshaling-strings-in-cxx-cli
5 //
6 // Marshals strings between .NET and C++ using C++/CLI (Visual C++ 2005 and later only).
7 // Faster and cleaner than the System::Interop method because it uses garbage collected memory.
8 // Use at your own leisure. No warranties whatsoever provided.
9 //
10 // Original code by Markus Ewald (http://www.nuclex.org/articles/marshaling-strings-in-cxx-cli)
11 // Updated version including several improvements suggested by Neil Hunt
12 // ------------------------------------------------------------------------------------------- //
13 #pragma once
14 
15 #include <string>
16 #include <vcclr.h>
17 
18 // CLI extensions namespace
19 namespace clix {
20 
22  enum Encoding {
23 
29  E_ANSI,
30 
38  E_UTF8,
39 
48  E_UTF16, E_UNICODE = E_UTF16
49 
50  };
51 
52  // Ignore this if you're just scanning the headers for informations :-)
53  /* All this template stuff might seem like overkill, but it is well thought out and enables
54  you to use a readable and convenient call while still keeping the highest possible code
55  efficiency due to compile-time evaluation of the required conversion path.
56  */
57  namespace detail {
58 
59  // Get C++ string type for specified encoding
60  template<Encoding encoding> struct StringTypeSelecter;
61  template<> struct StringTypeSelecter<E_ANSI> { typedef std::string Type; };
62  template<> struct StringTypeSelecter<E_UTF8> { typedef std::string Type; };
63  template<> struct StringTypeSelecter<E_UTF16> { typedef std::wstring Type; };
64 
65  // Compile-time check whether a given type is a managed System::String
66  template<typename StringType> struct IsManagedString { enum { Result = false }; };
67  template<> struct IsManagedString<System::String ^> { enum { Result = true }; };
68 
69  // Compile-time selection of two types depending on a boolean expression
70  template<bool expression> struct Select;
71  template<> struct Select<false> {
72  template<typename TrueType, typename FalseType> struct Type { typedef FalseType Result; };
73  };
74  template<> struct Select<true> {
75  template<typename TrueType, typename FalseType> struct Type { typedef TrueType Result; };
76  };
77 
78  // Direction of the marshaling process
79  enum MarshalingDirection {
80  CxxFromNet,
81  NetFromCxx
82  };
83 
84  // The actual marshaling code
85  template<MarshalingDirection direction> struct StringMarshaler;
86 
87  // Marshals to .NET from C++ strings
88  template<> struct StringMarshaler<NetFromCxx> {
89 
90  template<Encoding encoding, typename SourceType>
91  static System::String ^marshal(const SourceType &string) {
92  // Constructs a std::[w]string in case someone gave us a char * to choke on
93  return marshalCxxString<encoding, SourceType>(string);
94  }
95 
96  template<Encoding encoding, typename SourceType>
97  static System::String ^marshalCxxString(
98  const typename StringTypeSelecter<encoding>::Type &cxxString
99  ) {
100  typedef typename StringTypeSelecter<encoding>::Type SourceStringType;
101  size_t byteCount = cxxString.length() * sizeof(SourceStringType::value_type);
102 
103  // Copy the C++ string contents into a managed array of bytes
104  array<unsigned char> ^bytes = gcnew array<unsigned char>(byteCount);
105  { pin_ptr<unsigned char> pinnedBytes = &bytes[0];
106  memcpy(pinnedBytes, cxxString.c_str(), byteCount);
107  }
108 
109  // Now let one of .NET's encoding classes do the rest
110  return decode<encoding>(bytes);
111  }
112 
113  private:
114  // Converts a byte array based on the selected encoding
115  template<Encoding encoding> static System::String ^decode(array<unsigned char> ^bytes);
116  template<> static System::String ^decode<E_ANSI>(array<unsigned char> ^bytes) {
117  return System::Text::Encoding::Default->GetString(bytes);
118  }
119  template<> static System::String ^decode<E_UTF8>(array<unsigned char> ^bytes) {
120  return System::Text::Encoding::UTF8->GetString(bytes);
121  }
122  template<> static System::String ^decode<E_UTF16>(array<unsigned char> ^bytes) {
123  return System::Text::Encoding::Unicode->GetString(bytes);
124  }
125  };
126 
127  // Marshals to C++ strings from .NET
128  template<> struct StringMarshaler<CxxFromNet> {
129 
130  template<Encoding encoding, typename SourceType>
131  static typename detail::StringTypeSelecter<encoding>::Type marshal(
132  System::String ^string
133  ) {
134  typedef typename StringTypeSelecter<encoding>::Type StringType;
135 
136  // First, we use .NET's encoding classes to convert the string into a byte array
137  array<unsigned char> ^bytes = encode<encoding>(string);
138 
139  // fix crash if empty string passed
140  if (bytes->Length == 0) return StringType();
141 
142  // Then we construct our native string from that byte array
143  pin_ptr<unsigned char> pinnedBytes(&bytes[0]);
144  return StringType(
145  reinterpret_cast<StringType::value_type *>(static_cast<unsigned char *>(pinnedBytes)),
146  bytes->Length / sizeof(StringType::value_type)
147  );
148  }
149 
150  template<> static std::wstring marshal<E_UTF16, System::String ^>(
151  System::String ^string
152  ) {
153  // fix crash if empty string passed
154  if (string->Length == 0) return std::wstring();
155 
156  // We can directly access the characters in the managed string
157  pin_ptr<const wchar_t> pinnedChars(::PtrToStringChars(string));
158  return std::wstring(pinnedChars, string->Length);
159  }
160 
161  private:
162  // Converts a string based on the selected encoding
163  template<Encoding encoding> static array<unsigned char> ^encode(System::String ^string);
164  template<> static array<unsigned char> ^encode<E_ANSI>(System::String ^string) {
165  return System::Text::Encoding::Default->GetBytes(string);
166  }
167  template<> static array<unsigned char> ^encode<E_UTF8>(System::String ^string) {
168  return System::Text::Encoding::UTF8->GetBytes(string);
169  }
170  template<> static array<unsigned char> ^encode<E_UTF16>(System::String ^string) {
171  return System::Text::Encoding::Unicode->GetBytes(string);
172  }
173 
174  };
175 
176  } // namespace detail
177 
178  // ----------------------------------------------------------------------------------------- //
179  // clix::marshalString()
180  // ----------------------------------------------------------------------------------------- //
189  template<Encoding encoding, typename SourceType>
192  System::String ^
193  >::Result marshalString(SourceType string) {
194 
195  // Pass on the call to our nifty template routines
197  detail::IsManagedString<SourceType>::Result ? detail::CxxFromNet : detail::NetFromCxx
198  >::marshal<encoding, SourceType>(string);
199 
200  }
201 
202 } // namespace clix
Definition: Clix.h:70
Definition: Clix.h:85
Definition: EventStreamDetail.h:15
Definition: Clix.h:66
Definition: Clix.h:19