ProteoWizard
cpp_cli_utilities.hpp
Go to the documentation of this file.
1//
2// $Id$
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#define WIN32_LEAN_AND_MEAN
27#define NOGDI
28
29#ifndef NOMINMAX
30# define NOMINMAX
31#endif
32
33#include <gcroot.h>
34#include <vcclr.h>
35#pragma unmanaged
36#include <comdef.h> // _com_error
37#include <vector>
38#include <string>
39#include <stdexcept>
40#include <boost/algorithm/string/split.hpp>
41#include <boost/range/algorithm/copy.hpp>
42#include "automation_vector.h"
43#pragma managed
44#include "BinaryData.hpp"
45
46namespace pwiz {
47namespace util {
48
49
50inline std::string ToStdString(System::String^ source)
51{
52 if (System::String::IsNullOrEmpty(source))
53 return std::string();
54
55 System::Text::Encoding^ encoding = System::Text::Encoding::UTF8;
56 array<System::Byte>^ encodedBytes = encoding->GetBytes(source);
57
58 std::string target("", encodedBytes->Length);
59 char* buffer = &target[0];
60 unsigned char* unsignedBuffer = reinterpret_cast<unsigned char*>(buffer);
61 System::Runtime::InteropServices::Marshal::Copy(encodedBytes, 0, (System::IntPtr) unsignedBuffer, encodedBytes->Length);
62 return target;
63}
64
65
66inline System::String^ ToSystemString(const std::string& source, bool utf8=true)
67{
68 if (utf8)
69 {
70 System::Text::Encoding^ encoding = System::Text::Encoding::UTF8;
71 int length = source.length();
72 array<System::Byte>^ buffer = gcnew array<System::Byte>(length);
73 System::Runtime::InteropServices::Marshal::Copy((System::IntPtr) const_cast<char*>(source.c_str()), buffer, 0, length);
74 return encoding->GetString(buffer);
75 }
76 else
77 return gcnew System::String(source.c_str());
78}
79
80
81template<typename managed_value_type, typename native_value_type>
82void ToStdVector(cli::array<managed_value_type>^ managedArray, std::vector<native_value_type>& stdVector)
83{
84 stdVector.clear();
85 if (managedArray->Length > 0)
86 {
87 cli::pin_ptr<managed_value_type> pin = &managedArray[0];
88 native_value_type* begin = (native_value_type*) pin;
89 stdVector.assign(begin, begin + managedArray->Length);
90 }
91}
92
93
94template<typename managed_value_type>
95void ToStdVector(cli::array<managed_value_type>^ managedArray, std::vector<std::string>& stdVector)
96{
97 stdVector.clear();
98 if (managedArray->Length > 0)
99 {
100 stdVector.reserve(managedArray->Length);
101 for (size_t i = 0, end = managedArray->Length; i < end; ++i)
102 stdVector.push_back(ToStdString(managedArray[i]->ToString()));
103 }
104}
105
106
107template<typename native_value_type, typename managed_value_type>
108std::vector<native_value_type> ToStdVector(cli::array<managed_value_type>^ managedArray)
109{
110 std::vector<native_value_type> result;
111 ToStdVector(managedArray, result);
112 return result;
113}
114
115
116template<typename managed_value_type, typename native_value_type>
117void ToStdVector(cli::array<managed_value_type>^ managedArray, int sourceIndex, std::vector<native_value_type>& stdVector, int destinationIndex, int count)
118{
119 stdVector.clear();
120 if (managedArray->Length > 0)
121 {
122 cli::pin_ptr<managed_value_type> pin = &managedArray[sourceIndex];
123 native_value_type* begin = (native_value_type*)pin;
124 stdVector.assign(begin + destinationIndex, begin + destinationIndex + count);
125 }
126}
127
128
129template<typename managed_value_type, typename native_value_type>
130void ToStdVector(System::Collections::Generic::IList<managed_value_type>^ managedList, std::vector<native_value_type>& stdVector)
131{
132 stdVector.clear();
133 if (managedList->Count > 0)
134 {
135 stdVector.reserve(managedList->Count);
136 for (size_t i = 0, end = managedList->Count; i < end; ++i)
137 stdVector.push_back((native_value_type) managedList[i]);
138 }
139}
140
141
142/// wraps a managed array in an automation_vector to enable direct access from unmanaged code
143template<typename managed_value_type, typename native_value_type>
144void ToAutomationVector(cli::array<managed_value_type>^ managedArray, automation_vector<native_value_type>& automationArray)
145{
146 VARIANT v;
147 ::VariantInit(&v);
148 System::IntPtr vPtr = (System::IntPtr) &v;
149 System::Runtime::InteropServices::Marshal::GetNativeVariantForObject((System::Object^) managedArray, vPtr);
150 automationArray.attach(v);
151}
152
153
154template<typename managed_value_type, typename native_value_type>
155void ToBinaryData(cli::array<managed_value_type>^ managedArray, BinaryData<native_value_type>& binaryData)
156{
157 typedef System::Runtime::InteropServices::GCHandle GCHandle;
158
159#ifdef PWIZ_MANAGED_PASSTHROUGH
160 GCHandle handle = GCHandle::Alloc(managedArray);
161 binaryData = ((System::IntPtr)handle).ToPointer();
162 handle.Free();
163#else
164 ToBinaryData(managedArray, 0, binaryData, 0, managedArray->Length);
165#endif
166}
167
168
169template<typename managed_value_type, typename native_value_type>
170void ToBinaryData(cli::array<managed_value_type>^ managedArray, int sourceIndex, BinaryData<native_value_type>& binaryData, int destinationIndex, int count)
171{
172 binaryData.clear();
173 if (managedArray->Length > 0)
174 {
175 cli::pin_ptr<managed_value_type> pin = &managedArray[sourceIndex];
176 native_value_type* begin = (native_value_type*)pin;
177 binaryData.assign(begin + destinationIndex, begin + destinationIndex + count);
178 }
179}
180
181
182template<typename managed_value_type, typename native_value_type>
183void ToBinaryData(System::Collections::Generic::IList<managed_value_type>^ managedList, BinaryData<native_value_type>& binaryData)
184{
185 binaryData.clear();
186 if (managedList->Count > 0)
187 {
188 binaryData.reserve(managedList->Count);
189 for (size_t i = 0, end = managedList->Count; i < end; ++i)
190 binaryData.push_back((native_value_type)managedList[i]);
191 }
192}
193
194
195
196ref class Lock
197{
198 System::Object^ m_pObject;
199
200 public:
201 Lock(System::Object^ pObject) : m_pObject(pObject) { System::Threading::Monitor::Enter(m_pObject); }
202 ~Lock() { System::Threading::Monitor::Exit(m_pObject); }
203};
204
205
206} // namespace util
207} // namespace pwiz
208
209
210namespace {
211
212/// prepends function with a single level of scope,
213/// e.g. "Reader::read()" instead of "pwiz::data::msdata::Reader::read()"
214template <typename T>
215std::string trimFunctionMacro(const char* function, const T& param)
216{
217 std::vector<boost::iterator_range<std::string::const_iterator> > tokens;
218 std::string functionStr(function);
219 boost::algorithm::split(tokens, functionStr, boost::is_any_of(":"), boost::algorithm::token_compress_on);
220 std::string what("[");
221 if (tokens.size() > 1)
222 {
223 boost::range::copy(*(tokens.rbegin() + 1), std::back_inserter(what));
224 what += "::";
225 if (boost::range::equal(*(tokens.rbegin() + 1), *tokens.rbegin()))
226 what += "ctor";
227 else if (tokens.rbegin()->front() == '~')
228 what += "dtor";
229 else
230 boost::range::copy(*tokens.rbegin(), std::back_inserter(what));
231 }
232 else if (tokens.size() > 0)
233 boost::range::copy(*tokens.rbegin(), std::back_inserter(what));
234 what += "(" + lexical_cast<std::string>(param) + ")] ";
235 return what;
236}
237
238} // namespace
239
240
241/// forwards managed exception to unmanaged code;
242/// prepends function with a single level of scope,
243/// e.g. "Reader::read()" instead of "pwiz::data::msdata::Reader::read()"
244#define CATCH_AND_FORWARD_EX(param) \
245 catch (std::exception&) {throw;} \
246 catch (_com_error& e) {throw std::runtime_error(std::string("COM error: ") + e.ErrorMessage());} \
247 /*catch (CException* e) {std::auto_ptr<CException> exceptionDeleter(e); char message[1024]; e->GetErrorMessage(message, 1024); throw std::runtime_error(string("MFC error: ") + message);}*/ \
248 catch (System::AggregateException^ e) { throw std::runtime_error(trimFunctionMacro(__FUNCTION__, (param)) + pwiz::util::ToStdString(e->ToString())); } \
249 catch (System::Exception^ e) { throw std::runtime_error(trimFunctionMacro(__FUNCTION__, (param)) + pwiz::util::ToStdString(e->Message)); }
250
251#define CATCH_AND_FORWARD CATCH_AND_FORWARD_EX("")
252
253#endif // _CPP_CLI_UTILITIES_HPP_
A custom vector class that can store its contents in either a std::vector or a cli::array (when compi...
void reserve(size_type n)
void assign(const Iter &first, const Iter &last)
void push_back(const T &value)
System::Object m_pObject
Lock(System::Object^ pObject)
std::string ToStdString(System::String^ source)
void ToBinaryData(cli::array< managed_value_type >^ managedArray, BinaryData< native_value_type > &binaryData)
System::String ToSystemString(const std::string &source, bool utf8=true)
void ToStdVector(cli::array< managed_value_type >^ managedArray, std::vector< native_value_type > &stdVector)
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