3
* Copyright (C) 2018 Infactum
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU Affero General Public License as
7
* published by the Free Software Foundation, either version 3 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU Affero General Public License for more details.
15
* You should have received a copy of the GNU Affero General Public License
16
* along with this program. If not, see <https://www.gnu.org/licenses/>.
28
#pragma warning (disable : 4267)
31
bool Component::Init(void *connection_) {
32
connection = static_cast<IAddInDefBase *>(connection_);
33
return connection != nullptr;
36
bool Component::setMemManager(void *memory_manager_) {
37
memory_manager = static_cast<IMemoryManager *>(memory_manager_);
38
return memory_manager != nullptr;
41
void Component::SetLocale(const WCHAR_T *locale) {
42
#ifdef CASE_INSENSITIVE
44
std::locale::global(std::locale{toUTF8String(locale)});
45
} catch (std::runtime_error &) {
46
std::locale::global(std::locale{""});
51
bool Component::RegisterExtensionAs(WCHAR_T **ext_name) {
52
auto name = extensionName();
55
storeVariable(name, ext_name);
56
} catch (const std::bad_alloc &) {
63
long Component::GetNProps() {
64
return properties_meta.size();
67
long Component::FindProp(const WCHAR_T *prop_name) {
69
std::wstring lookup_name = toWstring(prop_name);
71
#ifdef CASE_INSENSITIVE
72
lookup_name = toUpper(lookup_name);
74
for (auto i = 0u; i < properties_meta.size(); ++i) {
75
if (toUpper(properties_meta[i].alias) == lookup_name
76
|| toUpper(properties_meta[i].alias_ru) == lookup_name) {
77
return static_cast<long>(i);
81
for (auto i = 0u; i < properties_meta.size(); ++i) {
82
if (properties_meta[i].alias == lookup_name
83
|| properties_meta[i].alias_ru == lookup_name) {
84
return static_cast<long>(i);
92
const WCHAR_T *Component::GetPropName(long num, long lang_alias) {
95
if (lang_alias == 0) {
96
name = &(properties_meta[num].alias);
98
name = &(properties_meta[num].alias_ru);
101
WCHAR_T *result = nullptr;
102
storeVariable(std::u16string(reinterpret_cast<const char16_t *>(name->c_str())), &result);
107
bool Component::GetPropVal(const long num, tVariant *value) {
110
auto tmp = properties_meta[num].getter();
111
storeVariable(*tmp, *value);
112
} catch (const std::exception &e) {
113
AddError(ADDIN_E_FAIL, extensionName(), e.what(), true);
116
AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
123
bool Component::SetPropVal(const long num, tVariant *value) {
126
auto tmp = toStlVariant(*value);
127
properties_meta[num].setter(std::move(tmp));
128
} catch (const std::exception &e) {
129
AddError(ADDIN_E_FAIL, extensionName(), e.what(), true);
132
AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
139
bool Component::IsPropReadable(const long lPropNum) {
140
return static_cast<bool>(properties_meta[lPropNum].getter);
143
bool Component::IsPropWritable(const long lPropNum) {
144
return static_cast<bool>(properties_meta[lPropNum].setter);
147
long Component::GetNMethods() {
148
return methods_meta.size();
151
long Component::FindMethod(const WCHAR_T *method_name) {
153
std::wstring lookup_name = toWstring(method_name);
155
#ifdef CASE_INSENSITIVE
156
lookup_name = toUpper(lookup_name);
158
for (auto i = 0u; i < methods_meta.size(); ++i) {
159
if (toUpper(methods_meta[i].alias) == lookup_name
160
|| toUpper(methods_meta[i].alias_ru) == lookup_name) {
161
return static_cast<long>(i);
165
for (auto i = 0u; i < methods_meta.size(); ++i) {
166
if (methods_meta[i].alias == lookup_name
167
|| methods_meta[i].alias_ru == lookup_name) {
168
return static_cast<long>(i);
176
const WCHAR_T *Component::GetMethodName(const long num, const long lang_alias) {
179
if (lang_alias == 0) {
180
name = &(methods_meta[num].alias);
182
name = &(methods_meta[num].alias_ru);
185
WCHAR_T *result = nullptr;
186
storeVariable(std::u16string(reinterpret_cast<const char16_t *>(name->c_str())), &result);
192
long Component::GetNParams(const long method_num) {
193
return methods_meta[method_num].params_count;
196
bool Component::GetParamDefValue(const long method_num, const long param_num, tVariant *def_value) {
198
auto &def_args = methods_meta[method_num].default_args;
200
auto it = def_args.find(param_num);
201
if (it == def_args.end()) {
205
storeVariable(it->second, *def_value);
209
bool Component::HasRetVal(const long method_num) {
210
return methods_meta[method_num].returns_value;
213
bool Component::CallAsProc(const long method_num, tVariant *params, const long array_size) {
216
auto args = parseParams(params, array_size);
217
methods_meta[method_num].call(args);
219
storeParams(args, params);
221
} catch (const std::exception &e) {
222
AddError(ADDIN_E_FAIL, extensionName(), e.what(), true);
225
AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
232
bool Component::CallAsFunc(const long method_num, tVariant *ret_value, tVariant *params, const long array_size) {
235
auto args = parseParams(params, array_size);
236
variant_t result = methods_meta[method_num].call(args);
237
storeVariable(result, *ret_value);
239
storeParams(args, params);
241
} catch (const std::exception &e) {
242
AddError(ADDIN_E_FAIL, extensionName(), e.what(), true);
245
AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
253
void Component::AddError(unsigned short code, const std::string &src, const std::string &msg, bool throw_excp) {
254
WCHAR_T *source = nullptr;
255
WCHAR_T *descr = nullptr;
257
storeVariable(src, &source);
258
storeVariable(msg, &descr);
260
connection->AddError(code, source, descr, throw_excp);
262
memory_manager->FreeMemory(reinterpret_cast<void **>(&source));
263
memory_manager->FreeMemory(reinterpret_cast<void **>(&descr));
266
bool Component::ExternalEvent(const std::string &src, const std::string &msg, const std::string &data) {
267
WCHAR_T *wszSource = nullptr;
268
WCHAR_T *wszMessage = nullptr;
269
WCHAR_T *wszData = nullptr;
271
storeVariable(src, &wszSource);
272
storeVariable(msg, &wszMessage);
273
storeVariable(data, &wszData);
275
auto success = connection->ExternalEvent(wszSource, wszMessage, wszData);
277
memory_manager->FreeMemory(reinterpret_cast<void **>(&wszSource));
278
memory_manager->FreeMemory(reinterpret_cast<void **>(&wszMessage));
279
memory_manager->FreeMemory(reinterpret_cast<void **>(&wszData));
284
bool Component::SetEventBufferDepth(long depth) {
285
return connection->SetEventBufferDepth(depth);
288
long Component::GetEventBufferDepth() {
289
return connection->GetEventBufferDepth();
292
void Component::AddProperty(const std::wstring &alias, const std::wstring &alias_ru,
293
std::function<std::shared_ptr<variant_t>(void)> getter,
294
std::function<void(variant_t &&)> setter) {
296
PropertyMeta meta{alias, alias_ru, std::move(getter), std::move(setter)};
297
properties_meta.push_back(std::move(meta));
301
void Component::AddProperty(const std::wstring &alias, const std::wstring &alias_ru,
302
std::shared_ptr<variant_t> storage) {
308
AddProperty(alias, alias_ru,
309
[storage]() { // getter
312
[storage](variant_t &&v) -> void { //setter
313
*storage = std::move(v);
318
variant_t Component::toStlVariant(tVariant src) {
322
case VTYPE_I4: //int32_t
324
case VTYPE_R8: //double
326
case VTYPE_PWSTR: { //std::string
327
return toUTF8String(std::basic_string_view(src.pwstrVal, src.wstrLen));
332
return std::vector<char>(src.pstrVal, src.pstrVal + src.strLen);
336
throw std::bad_cast();
340
void Component::storeVariable(const variant_t &src, tVariant &dst) {
342
if (dst.vt == VTYPE_PWSTR && dst.pwstrVal != nullptr) {
343
memory_manager->FreeMemory(reinterpret_cast<void **>(&dst.pwstrVal));
346
if ((dst.vt == VTYPE_PSTR || dst.vt == VTYPE_BLOB) && dst.pstrVal != nullptr) {
347
memory_manager->FreeMemory(reinterpret_cast<void **>(&dst.pstrVal));
350
std::visit(overloaded{
351
[&](std::monostate) { dst.vt = VTYPE_EMPTY; },
352
[&](const int32_t &v) {
356
[&](const double &v) {
364
[&](const std::tm &v) {
368
[&](const std::string &v) { storeVariable(v, dst); },
369
[&](const std::vector<char> &v) { storeVariable(v, dst); }
374
void Component::storeVariable(const std::string &src, tVariant &dst) {
376
std::u16string tmp = toUTF16String(src);
378
dst.vt = VTYPE_PWSTR;
379
storeVariable(tmp, &dst.pwstrVal);
380
dst.wstrLen = static_cast<uint32_t>(tmp.length());
383
void Component::storeVariable(const std::string &src, WCHAR_T **dst) {
384
std::u16string tmp = toUTF16String(src);
385
storeVariable(tmp, dst);
388
void Component::storeVariable(const std::u16string &src, WCHAR_T **dst) {
390
size_t c_size = (src.size() + 1) * sizeof(char16_t);
392
if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast<void **>(dst), c_size)) {
393
throw std::bad_alloc();
396
memcpy(*dst, src.c_str(), c_size);
399
void Component::storeVariable(const std::vector<char> &src, tVariant &dst) {
402
dst.strLen = src.size();
404
if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast<void **>(&dst.pstrVal), src.size())) {
405
throw std::bad_alloc();
408
memcpy(dst.pstrVal, src.data(), src.size());
411
std::vector<variant_t> Component::parseParams(tVariant *params, long array_size) {
412
std::vector<variant_t> result;
414
auto size = static_cast<const unsigned long>(array_size);
415
result.reserve(size);
416
for (size_t i = 0; i < size; i++) {
417
result.emplace_back(toStlVariant(params[i]));
423
void Component::storeParams(const std::vector<variant_t> &src, tVariant *dest) {
424
for (size_t i = 0; i < src.size(); i++) {
425
storeVariable(src[i], dest[i]);
429
std::wstring Component::toUpper(std::wstring str) {
430
std::transform(str.begin(), str.end(), str.begin(), std::towupper);
434
std::string Component::toUTF8String(std::basic_string_view<WCHAR_T> src) {
437
// https://social.msdn.microsoft.com/Forums/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral
438
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cvt_utf8_utf16;
439
return cvt_utf8_utf16.to_bytes(src.data(), src.data() + src.size());
441
static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> cvt_utf8_utf16;
442
return cvt_utf8_utf16.to_bytes(reinterpret_cast<const char16_t *>(src.data()),
443
reinterpret_cast<const char16_t *>(src.data() + src.size()));
447
std::wstring Component::toWstring(std::basic_string_view<WCHAR_T> src) {
449
return std::wstring(src);
451
std::wstring_convert<std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>> conv;
452
return conv.from_bytes(reinterpret_cast<const char*>(src.data()),
453
reinterpret_cast<const char*>(src.data() + src.size()));
457
std::u16string Component::toUTF16String(std::string_view src) {
459
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cvt_utf8_utf16;
460
std::wstring tmp = cvt_utf8_utf16.from_bytes(src.data(), src.data() + src.size());
461
return std::u16string(reinterpret_cast<const char16_t *>(tmp.data()), tmp.size());
463
static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> cvt_utf8_utf16;
464
return cvt_utf8_utf16.from_bytes(src.data(), src.data() + src.size());