-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmessage_parser_library.cpp
More file actions
119 lines (102 loc) · 3.83 KB
/
Copy pathmessage_parser_library.cpp
File metadata and controls
119 lines (102 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2026 Davide Faconti
// SPDX-License-Identifier: Apache-2.0
#include "pj_plugins/host/message_parser_library.hpp"
#include <utility>
#include "detail/library_loader.hpp"
#include "detail/vtable_validation.hpp"
namespace PJ {
MessageParserLibrary::MessageParserLibrary(
std::shared_ptr<void> handle, const PJ_message_parser_vtable_t* vtable, std::string path)
: handle_(std::move(handle)), vtable_(vtable), path_(std::move(path)) {}
MessageParserLibrary::~MessageParserLibrary() {
reset();
}
MessageParserLibrary::MessageParserLibrary(MessageParserLibrary&& other) noexcept
: handle_(std::move(other.handle_)), vtable_(other.vtable_), path_(std::move(other.path_)) {
other.vtable_ = nullptr;
}
MessageParserLibrary& MessageParserLibrary::operator=(MessageParserLibrary&& other) noexcept {
if (this != &other) {
reset();
handle_ = std::move(other.handle_);
vtable_ = other.vtable_;
path_ = std::move(other.path_);
other.vtable_ = nullptr;
}
return *this;
}
Expected<MessageParserLibrary> MessageParserLibrary::load(std::string_view path) {
auto raw_handle = detail::loadLibraryHandle(path);
if (!raw_handle) {
return unexpected(raw_handle.error());
}
auto handle = detail::adoptLibraryHandle(*raw_handle);
if (auto abi = detail::checkPluginAbiVersion(handle.get()); !abi) {
return unexpected(abi.error());
}
auto sym = detail::resolveSymbol(handle.get(), "PJ_get_message_parser_vtable");
if (!sym) {
return unexpected(sym.error());
}
auto entry = reinterpret_cast<PJ_get_message_parser_vtable_fn>(*sym);
const PJ_message_parser_vtable_t* vtable = entry();
if (vtable == nullptr) {
return unexpected("PJ_get_message_parser_vtable returned null");
}
if (vtable->protocol_version != PJ_MESSAGE_PARSER_PROTOCOL_VERSION) {
return unexpected("MessageParser protocol version mismatch");
}
if (vtable->struct_size < PJ_MESSAGE_PARSER_MIN_VTABLE_SIZE) {
return unexpected("MessageParser vtable smaller than v4.0 baseline");
}
if (auto status = detail::validateRequiredSlots(vtable); !status) {
return unexpected(status.error());
}
return MessageParserLibrary(std::move(handle), vtable, std::string(path));
}
Expected<MessageParserLibrary> MessageParserLibrary::loadStatic(const PJ_message_parser_vtable_t* vtable) {
if (vtable == nullptr) {
return unexpected("static MessageParser vtable is null");
}
if (vtable->protocol_version != PJ_MESSAGE_PARSER_PROTOCOL_VERSION) {
return unexpected("MessageParser protocol version mismatch");
}
if (vtable->struct_size < PJ_MESSAGE_PARSER_MIN_VTABLE_SIZE) {
return unexpected("MessageParser vtable smaller than v4.0 baseline");
}
if (auto status = detail::validateRequiredSlots(vtable); !status) {
return unexpected(status.error());
}
static char anchor = 0;
std::shared_ptr<void> handle(&anchor, [](void*) {});
return MessageParserLibrary(std::move(handle), vtable, "static://");
}
Expected<const PJ_dialog_vtable_t*> MessageParserLibrary::resolveDialogVtable() const {
auto sym = detail::resolveSymbol(handle_.get(), "PJ_get_dialog_vtable");
if (!sym) {
return unexpected(sym.error());
}
auto fn = reinterpret_cast<PJ_get_dialog_vtable_fn>(*sym);
const PJ_dialog_vtable_t* vt = fn();
if (vt == nullptr) {
return unexpected("PJ_get_dialog_vtable returned null");
}
if (vt->protocol_version != PJ_DIALOG_PROTOCOL_VERSION) {
return unexpected("Dialog protocol version mismatch");
}
if (vt->struct_size < PJ_DIALOG_MIN_VTABLE_SIZE) {
return unexpected("Dialog vtable smaller than v4.0 baseline");
}
if (auto status = detail::validateRequiredSlots(vt); !status) {
return unexpected(status.error());
}
return vt;
}
void MessageParserLibrary::reset() {
if (handle_ != nullptr) {
handle_.reset();
vtable_ = nullptr;
path_.clear();
}
}
} // namespace PJ