dservice

Форк
1
/
Component.cpp 
466 строк · 13.5 Кб
1
/*
2
 *  Modern Native AddIn
3
 *  Copyright (C) 2018  Infactum
4
 *
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.
9
 *
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.
14
 *
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/>.
17
 *
18
 */
19

20
#include <algorithm>
21
#include <codecvt>
22
#include <cwctype>
23
#include <locale>
24

25
#include "Component.h"
26

27
#ifdef _WINDOWS
28
#pragma warning (disable : 4267)
29
#endif
30

31
bool Component::Init(void *connection_) {
32
    connection = static_cast<IAddInDefBase *>(connection_);
33
    return connection != nullptr;
34
}
35

36
bool Component::setMemManager(void *memory_manager_) {
37
    memory_manager = static_cast<IMemoryManager *>(memory_manager_);
38
    return memory_manager != nullptr;
39
}
40

41
void Component::SetLocale(const WCHAR_T *locale) {
42
#ifdef CASE_INSENSITIVE
43
    try {
44
        std::locale::global(std::locale{toUTF8String(locale)});
45
    } catch (std::runtime_error &) {
46
        std::locale::global(std::locale{""});
47
    }
48
#endif
49
}
50

51
bool Component::RegisterExtensionAs(WCHAR_T **ext_name) {
52
    auto name = extensionName();
53

54
    try {
55
        storeVariable(name, ext_name);
56
    } catch (const std::bad_alloc &) {
57
        return false;
58
    }
59

60
    return true;
61
}
62

63
long Component::GetNProps() {
64
    return properties_meta.size();
65
}
66

67
long Component::FindProp(const WCHAR_T *prop_name) {
68

69
    std::wstring lookup_name = toWstring(prop_name);
70

71
#ifdef CASE_INSENSITIVE
72
    lookup_name = toUpper(lookup_name);
73

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);
78
        }
79
    }
80
#else
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);
85
        }
86
    }
87
#endif
88
    return -1;
89

90
}
91

92
const WCHAR_T *Component::GetPropName(long num, long lang_alias) {
93

94
    std::wstring *name;
95
    if (lang_alias == 0) {
96
        name = &(properties_meta[num].alias);
97
    } else {
98
        name = &(properties_meta[num].alias_ru);
99
    }
100

101
    WCHAR_T *result = nullptr;
102
    storeVariable(std::u16string(reinterpret_cast<const char16_t *>(name->c_str())), &result);
103

104
    return result;
105
}
106

107
bool Component::GetPropVal(const long num, tVariant *value) {
108

109
    try {
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);
114
        return false;
115
    } catch (...) {
116
        AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
117
        return false;
118
    }
119

120
    return true;
121
}
122

123
bool Component::SetPropVal(const long num, tVariant *value) {
124

125
    try {
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);
130
        return false;
131
    } catch (...) {
132
        AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
133
        return false;
134
    }
135

136
    return true;
137
}
138

139
bool Component::IsPropReadable(const long lPropNum) {
140
    return static_cast<bool>(properties_meta[lPropNum].getter);
141
}
142

143
bool Component::IsPropWritable(const long lPropNum) {
144
    return static_cast<bool>(properties_meta[lPropNum].setter);
145
}
146

147
long Component::GetNMethods() {
148
    return methods_meta.size();
149
}
150

151
long Component::FindMethod(const WCHAR_T *method_name) {
152

153
    std::wstring lookup_name = toWstring(method_name);
154

155
#ifdef CASE_INSENSITIVE
156
    lookup_name = toUpper(lookup_name);
157

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);
162
        }
163
    }
164
#else
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);
169
        }
170
    }
171
#endif
172

173
    return -1;
174
}
175

176
const WCHAR_T *Component::GetMethodName(const long num, const long lang_alias) {
177

178
    std::wstring *name;
179
    if (lang_alias == 0) {
180
        name = &(methods_meta[num].alias);
181
    } else {
182
        name = &(methods_meta[num].alias_ru);
183
    }
184

185
    WCHAR_T *result = nullptr;
186
    storeVariable(std::u16string(reinterpret_cast<const char16_t *>(name->c_str())), &result);
187

188
    return result;
189

190
}
191

192
long Component::GetNParams(const long method_num) {
193
    return methods_meta[method_num].params_count;
194
}
195

196
bool Component::GetParamDefValue(const long method_num, const long param_num, tVariant *def_value) {
197

198
    auto &def_args = methods_meta[method_num].default_args;
199

200
    auto it = def_args.find(param_num);
201
    if (it == def_args.end()) {
202
        return false;
203
    }
204

205
    storeVariable(it->second, *def_value);
206
    return true;
207
}
208

209
bool Component::HasRetVal(const long method_num) {
210
    return methods_meta[method_num].returns_value;
211
}
212

213
bool Component::CallAsProc(const long method_num, tVariant *params, const long array_size) {
214

215
    try {
216
        auto args = parseParams(params, array_size);
217
        methods_meta[method_num].call(args);
218
#ifdef OUT_PARAMS
219
        storeParams(args, params);
220
#endif
221
    } catch (const std::exception &e) {
222
        AddError(ADDIN_E_FAIL, extensionName(), e.what(), true);
223
        return false;
224
    } catch (...) {
225
        AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
226
        return false;
227
    }
228

229
    return true;
230
}
231

232
bool Component::CallAsFunc(const long method_num, tVariant *ret_value, tVariant *params, const long array_size) {
233

234
    try {
235
        auto args = parseParams(params, array_size);
236
        variant_t result = methods_meta[method_num].call(args);
237
        storeVariable(result, *ret_value);
238
#ifdef OUT_PARAMS
239
        storeParams(args, params);
240
#endif
241
    } catch (const std::exception &e) {
242
        AddError(ADDIN_E_FAIL, extensionName(), e.what(), true);
243
        return false;
244
    } catch (...) {
245
        AddError(ADDIN_E_FAIL, extensionName(), UNKNOWN_EXCP, true);
246
        return false;
247
    }
248

249
    return true;
250

251
}
252

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;
256

257
    storeVariable(src, &source);
258
    storeVariable(msg, &descr);
259

260
    connection->AddError(code, source, descr, throw_excp);
261

262
    memory_manager->FreeMemory(reinterpret_cast<void **>(&source));
263
    memory_manager->FreeMemory(reinterpret_cast<void **>(&descr));
264
}
265

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;
270

271
    storeVariable(src, &wszSource);
272
    storeVariable(msg, &wszMessage);
273
    storeVariable(data, &wszData);
274

275
    auto success = connection->ExternalEvent(wszSource, wszMessage, wszData);
276

277
    memory_manager->FreeMemory(reinterpret_cast<void **>(&wszSource));
278
    memory_manager->FreeMemory(reinterpret_cast<void **>(&wszMessage));
279
    memory_manager->FreeMemory(reinterpret_cast<void **>(&wszData));
280

281
    return success;
282
}
283

284
bool Component::SetEventBufferDepth(long depth) {
285
    return connection->SetEventBufferDepth(depth);
286
}
287

288
long Component::GetEventBufferDepth() {
289
    return connection->GetEventBufferDepth();
290
}
291

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) {
295

296
    PropertyMeta meta{alias, alias_ru, std::move(getter), std::move(setter)};
297
    properties_meta.push_back(std::move(meta));
298

299
}
300

301
void Component::AddProperty(const std::wstring &alias, const std::wstring &alias_ru,
302
                            std::shared_ptr<variant_t> storage) {
303

304
    if (!storage) {
305
        return;
306
    }
307

308
    AddProperty(alias, alias_ru,
309
                [storage]() { // getter
310
                    return storage;
311
                },
312
                [storage](variant_t &&v) -> void { //setter
313
                    *storage = std::move(v);
314
                });
315

316
}
317

318
variant_t Component::toStlVariant(tVariant src) {
319
    switch (src.vt) {
320
        case VTYPE_EMPTY:
321
            return UNDEFINED;
322
        case VTYPE_I4: //int32_t
323
            return src.lVal;
324
        case VTYPE_R8: //double
325
            return src.dblVal;
326
        case VTYPE_PWSTR: { //std::string
327
            return toUTF8String(std::basic_string_view(src.pwstrVal, src.wstrLen));
328
        }
329
        case VTYPE_BOOL:
330
            return src.bVal;
331
        case VTYPE_BLOB:
332
            return std::vector<char>(src.pstrVal, src.pstrVal + src.strLen);
333
        case VTYPE_TM:
334
            return src.tmVal;
335
        default:
336
            throw std::bad_cast();
337
    }
338
}
339

340
void Component::storeVariable(const variant_t &src, tVariant &dst) {
341

342
    if (dst.vt == VTYPE_PWSTR && dst.pwstrVal != nullptr) {
343
        memory_manager->FreeMemory(reinterpret_cast<void **>(&dst.pwstrVal));
344
    }
345

346
    if ((dst.vt == VTYPE_PSTR || dst.vt == VTYPE_BLOB) && dst.pstrVal != nullptr) {
347
        memory_manager->FreeMemory(reinterpret_cast<void **>(&dst.pstrVal));
348
    }
349

350
    std::visit(overloaded{
351
            [&](std::monostate) { dst.vt = VTYPE_EMPTY; },
352
            [&](const int32_t &v) {
353
                dst.vt = VTYPE_I4;
354
                dst.lVal = v;
355
            },
356
            [&](const double &v) {
357
                dst.vt = VTYPE_R8;
358
                dst.dblVal = v;
359
            },
360
            [&](const bool v) {
361
                dst.vt = VTYPE_BOOL;
362
                dst.bVal = v;
363
            },
364
            [&](const std::tm &v) {
365
                dst.vt = VTYPE_TM;
366
                dst.tmVal = v;
367
            },
368
            [&](const std::string &v) { storeVariable(v, dst); },
369
            [&](const std::vector<char> &v) { storeVariable(v, dst); }
370
    }, src);
371

372
}
373

374
void Component::storeVariable(const std::string &src, tVariant &dst) {
375

376
    std::u16string tmp = toUTF16String(src);
377

378
    dst.vt = VTYPE_PWSTR;
379
    storeVariable(tmp, &dst.pwstrVal);
380
    dst.wstrLen = static_cast<uint32_t>(tmp.length());
381
}
382

383
void Component::storeVariable(const std::string &src, WCHAR_T **dst) {
384
    std::u16string tmp = toUTF16String(src);
385
    storeVariable(tmp, dst);
386
}
387

388
void Component::storeVariable(const std::u16string &src, WCHAR_T **dst) {
389

390
    size_t c_size = (src.size() + 1) * sizeof(char16_t);
391

392
    if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast<void **>(dst), c_size)) {
393
        throw std::bad_alloc();
394
    };
395

396
    memcpy(*dst, src.c_str(), c_size);
397
}
398

399
void Component::storeVariable(const std::vector<char> &src, tVariant &dst) {
400

401
    dst.vt = VTYPE_BLOB;
402
    dst.strLen = src.size();
403

404
    if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast<void **>(&dst.pstrVal), src.size())) {
405
        throw std::bad_alloc();
406
    };
407

408
    memcpy(dst.pstrVal, src.data(), src.size());
409
}
410

411
std::vector<variant_t> Component::parseParams(tVariant *params, long array_size) {
412
    std::vector<variant_t> result;
413

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]));
418
    }
419

420
    return result;
421
}
422

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]);
426
    }
427
}
428

429
std::wstring Component::toUpper(std::wstring str) {
430
    std::transform(str.begin(), str.end(), str.begin(), std::towupper);
431
    return str;
432
}
433

434
std::string Component::toUTF8String(std::basic_string_view<WCHAR_T> src) {
435
#ifdef _WINDOWS
436
    // VS bug
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());
440
#else
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()));
444
#endif
445
}
446

447
std::wstring Component::toWstring(std::basic_string_view<WCHAR_T> src) {
448
#ifdef _WINDOWS
449
    return std::wstring(src);
450
#else
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()));
454
#endif
455
}
456

457
std::u16string Component::toUTF16String(std::string_view src) {
458
#ifdef _WINDOWS
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());
462
#else
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());
465
#endif
466
}
467

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.