ProteoWizard
cpp_cli_utilities.hpp
Go to the documentation of this file.
1 //
2 // $Id: cpp_cli_utilities.hpp 10827 2017-05-11 21:01:58Z chambm $
3 //
4 //
5 // Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
6 //
7 // Copyright 2010 Vanderbilt University - Nashville, TN 37232
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 //
13 // http://www.apache.org/licenses/LICENSE-2.0
14 //
15 // Unless required by applicable law or agreed to in writing, software
16 // distributed under the License is distributed on an "AS IS" BASIS,
17 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 // See the License for the specific language governing permissions and
19 // limitations under the License.
20 //
21 
22 
23 #ifndef _CPP_CLI_UTILITIES_HPP_
24 #define _CPP_CLI_UTILITIES_HPP_
25 
26 #include <gcroot.h>
27 #include <vcclr.h>
28 #include <comdef.h> // _com_error
29 #include <vector>
30 #include <string>
31 #include <stdexcept>
32 #include <boost/algorithm/string/split.hpp>
33 #include <boost/range/algorithm/copy.hpp>
34 #include "automation_vector.h"
35 
36 namespace pwiz {
37 namespace util {
38 
39 
40 inline std::string ToStdString(System::String^ source)
41 {
42  if (System::String::IsNullOrEmpty(source))
43  return std::string();
44 
45  System::Text::Encoding^ encoding = System::Text::Encoding::UTF8;
46  array<System::Byte>^ encodedBytes = encoding->GetBytes(source);
47 
48  std::string target("", encodedBytes->Length);
49  char* buffer = &target[0];
50  unsigned char* unsignedBuffer = reinterpret_cast<unsigned char*>(buffer);
51  System::Runtime::InteropServices::Marshal::Copy(encodedBytes, 0, (System::IntPtr) unsignedBuffer, encodedBytes->Length);
52  return target;
53 }
54 
55 
56 inline System::String^ ToSystemString(const std::string& source, bool utf8=true)
57 {
58  if (utf8)
59  {
60  System::Text::Encoding^ encoding = System::Text::Encoding::UTF8;
61  int length = source.length();
62  array<System::Byte>^ buffer = gcnew array<System::Byte>(length);
63  System::Runtime::InteropServices::Marshal::Copy((System::IntPtr) const_cast<char*>(source.c_str()), buffer, 0, length);
64  return encoding->GetString(buffer);
65  }
66  else
67  return gcnew System::String(source.c_str());
68 }
69 
70 
71 template<typename managed_value_type, typename native_value_type>
72 void ToStdVector(cli::array<managed_value_type>^ managedArray, std::vector<native_value_type>& stdVector)
73 {
74  stdVector.clear();
75  if (managedArray->Length > 0)
76  {
77  cli::pin_ptr<managed_value_type> pin = &managedArray[0];
78  native_value_type* begin = (native_value_type*) pin;
79  stdVector.assign(begin, begin + managedArray->Length);
80  }
81 }
82 
83 
84 template<typename managed_value_type, typename native_value_type>
85 void ToStdVector(System::Collections::Generic::IList<managed_value_type>^ managedList, std::vector<native_value_type>& stdVector)
86 {
87  stdVector.clear();
88  if (managedList->Count > 0)
89  {
90  stdVector.reserve(managedList->Count);
91  for (size_t i = 0, end = managedList->Count; i < end; ++i)
92  stdVector.push_back((native_value_type) managedList[i]);
93  }
94 }
95 
96 
97 /// wraps a managed array in an automation_vector to enable direct access from unmanaged code
98 template<typename managed_value_type, typename native_value_type>
99 void ToAutomationVector(cli::array<managed_value_type>^ managedArray, automation_vector<native_value_type>& automationArray)
100 {
101  VARIANT v;
102  ::VariantInit(&v);
103  System::IntPtr vPtr = (System::IntPtr) &v;
104  System::Runtime::InteropServices::Marshal::GetNativeVariantForObject((System::Object^) managedArray, vPtr);
105  automationArray.attach(v);
106 }
107 
108 
109 } // namespace util
110 } // namespace pwiz
111 
112 
113 namespace {
114 
115 /// prepends function with a single level of scope,
116 /// e.g. "Reader::read()" instead of "pwiz::data::msdata::Reader::read()"
117 template <typename T>
118 std::string trimFunctionMacro(const char* function, const T& param)
119 {
120  std::vector<boost::iterator_range<std::string::const_iterator> > tokens;
121  std::string functionStr(function);
122  boost::algorithm::split(tokens, functionStr, boost::is_any_of(":"), boost::algorithm::token_compress_on);
123  std::string what("[");
124  if (tokens.size() > 1)
125  {
126  boost::range::copy(*(tokens.rbegin() + 1), std::back_inserter(what));
127  what += "::";
128  if (boost::range::equal(*(tokens.rbegin() + 1), *tokens.rbegin()))
129  what += "ctor";
130  else if (tokens.rbegin()->front() == '~')
131  what += "dtor";
132  else
133  boost::range::copy(*tokens.rbegin(), std::back_inserter(what));
134  }
135  else if (tokens.size() > 0)
136  boost::range::copy(*tokens.rbegin(), std::back_inserter(what));
137  what += "(" + lexical_cast<std::string>(param) + ")] ";
138  return what;
139 }
140 
141 } // namespace
142 
143 
144 /// forwards managed exception to unmanaged code;
145 /// prepends function with a single level of scope,
146 /// e.g. "Reader::read()" instead of "pwiz::data::msdata::Reader::read()"
147 #define CATCH_AND_FORWARD_EX(param) \
148  catch (std::exception&) {throw;} \
149  catch (_com_error& e) {throw std::runtime_error(string("COM error: ") + e.ErrorMessage());} \
150  /*catch (CException* e) {std::auto_ptr<CException> exceptionDeleter(e); char message[1024]; e->GetErrorMessage(message, 1024); throw std::runtime_error(string("MFC error: ") + message);}*/ \
151  catch (System::AggregateException^ e) { throw std::runtime_error(trimFunctionMacro(__FUNCTION__, (param)) + pwiz::util::ToStdString(e->ToString())); } \
152  catch (System::Exception^ e) { throw std::runtime_error(trimFunctionMacro(__FUNCTION__, (param)) + pwiz::util::ToStdString(e->Message)); }
153 
154 #define CATCH_AND_FORWARD CATCH_AND_FORWARD_EX("")
155 
156 #endif // _CPP_CLI_UTILITIES_HPP_
std::string ToStdString(System::String^ source)
void ToAutomationVector(cli::array< managed_value_type >^ managedArray, automation_vector< native_value_type > &automationArray)
wraps a managed array in an automation_vector to enable direct access from unmanaged code ...
float lexical_cast(const std::string &str)
void ToStdVector(cli::array< managed_value_type >^ managedArray, std::vector< native_value_type > &stdVector)
System::String ToSystemString(const std::string &source, bool utf8=true)