Skip to content

Commit 4f2610d

Browse files
committed
io/ipchandler: add prop get
1 parent 9417d6f commit 4f2610d

File tree

10 files changed

+260
-29
lines changed

10 files changed

+260
-29
lines changed

src/io/ipc.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "ipc.hpp"
2+
#include <cstring>
23
#include <utility>
34

45
#include <qcolor.h>
56
#include <qmetatype.h>
67
#include <qobjectdefs.h>
8+
#include <qtypes.h>
9+
#include <qvariant.h>
710

811
namespace qs::io::ipc {
912

@@ -14,6 +17,12 @@ const BoolIpcType BoolIpcType::INSTANCE {};
1417
const DoubleIpcType DoubleIpcType::INSTANCE {};
1518
const ColorIpcType ColorIpcType::INSTANCE {};
1619

20+
void* IpcType::copyStorage(const void* data) const {
21+
auto* storage = this->createStorage();
22+
memcpy(storage, data, this->size());
23+
return storage;
24+
}
25+
1726
const IpcType* IpcType::ipcType(const QMetaType& metaType) {
1827
if (metaType.id() == QMetaType::Void) return &VoidIpcType::INSTANCE;
1928
if (metaType.id() == QMetaType::QString) return &StringIpcType::INSTANCE;
@@ -70,12 +79,18 @@ void IpcTypeSlot::replace(void* value) {
7079
this->storage = value;
7180
}
7281

82+
void IpcTypeSlot::replace(const QVariant& value) {
83+
this->replace(this->mType->copyStorage(value.constData()));
84+
}
85+
7386
const char* VoidIpcType::name() const { return "void"; }
7487
const char* VoidIpcType::genericArgumentName() const { return "void"; }
88+
qsizetype VoidIpcType::size() const { return 0; }
7589

7690
// string
7791
const char* StringIpcType::name() const { return "string"; }
7892
const char* StringIpcType::genericArgumentName() const { return "QString"; }
93+
qsizetype StringIpcType::size() const { return sizeof(QString); }
7994
void* StringIpcType::fromString(const QString& string) const { return new QString(string); }
8095
QString StringIpcType::toString(void* slot) const { return *static_cast<QString*>(slot); }
8196
void* StringIpcType::createStorage() const { return new QString(); }
@@ -84,6 +99,7 @@ void StringIpcType::destroyStorage(void* slot) const { delete static_cast<QStrin
8499
// int
85100
const char* IntIpcType::name() const { return "int"; }
86101
const char* IntIpcType::genericArgumentName() const { return "int"; }
102+
qsizetype IntIpcType::size() const { return sizeof(int); }
87103

88104
void* IntIpcType::fromString(const QString& string) const {
89105
auto ok = false;
@@ -100,6 +116,7 @@ void IntIpcType::destroyStorage(void* slot) const { delete static_cast<int*>(slo
100116
// bool
101117
const char* BoolIpcType::name() const { return "bool"; }
102118
const char* BoolIpcType::genericArgumentName() const { return "bool"; }
119+
qsizetype BoolIpcType::size() const { return sizeof(bool); }
103120

104121
void* BoolIpcType::fromString(const QString& string) const {
105122
if (string == "true") return new bool(true);
@@ -121,6 +138,7 @@ void BoolIpcType::destroyStorage(void* slot) const { delete static_cast<bool*>(s
121138
// double
122139
const char* DoubleIpcType::name() const { return "real"; }
123140
const char* DoubleIpcType::genericArgumentName() const { return "double"; }
141+
qsizetype DoubleIpcType::size() const { return sizeof(double); }
124142

125143
void* DoubleIpcType::fromString(const QString& string) const {
126144
auto ok = false;
@@ -139,6 +157,7 @@ void DoubleIpcType::destroyStorage(void* slot) const { delete static_cast<double
139157
// color
140158
const char* ColorIpcType::name() const { return "color"; }
141159
const char* ColorIpcType::genericArgumentName() const { return "QColor"; }
160+
qsizetype ColorIpcType::size() const { return sizeof(QColor); }
142161

143162
void* ColorIpcType::fromString(const QString& string) const {
144163
auto color = QColor::fromString(string);
@@ -167,13 +186,21 @@ QString WireFunctionDefinition::toString() const {
167186
return "function " % this->name % '(' % paramString % "): " % this->returnType;
168187
}
169188

189+
QString WirePropertyDefinition::toString() const {
190+
return "property " % this->name % ": " % this->type;
191+
}
192+
170193
QString WireTargetDefinition::toString() const {
171194
QString accum = "target " % this->name;
172195

173196
for (const auto& func: this->functions) {
174197
accum += "\n " % func.toString();
175198
}
176199

200+
for (const auto& prop: this->properties) {
201+
accum += "\n " % prop.toString();
202+
}
203+
177204
return accum;
178205
}
179206

src/io/ipc.hpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <qcontainerfwd.h>
44
#include <qobjectdefs.h>
55
#include <qtclasshelpermacros.h>
6+
#include <qtypes.h>
67

78
#include "../ipc/ipc.hpp"
89

@@ -21,10 +22,12 @@ class IpcType {
2122

2223
[[nodiscard]] virtual const char* name() const = 0;
2324
[[nodiscard]] virtual const char* genericArgumentName() const = 0;
25+
[[nodiscard]] virtual qsizetype size() const = 0;
2426
[[nodiscard]] virtual void* fromString(const QString& /*string*/) const { return nullptr; }
2527
[[nodiscard]] virtual QString toString(void* /*slot*/) const { return ""; }
2628
[[nodiscard]] virtual void* createStorage() const { return nullptr; }
2729
virtual void destroyStorage(void* /*slot*/) const {}
30+
void* copyStorage(const void* data) const;
2831

2932
static const IpcType* ipcType(const QMetaType& metaType);
3033
};
@@ -43,6 +46,7 @@ class IpcTypeSlot {
4346
[[nodiscard]] QGenericReturnArgument asGenericReturnArgument();
4447

4548
void replace(void* value);
49+
void replace(const QVariant& value);
4650

4751
private:
4852
const IpcType* mType = nullptr;
@@ -53,6 +57,7 @@ class VoidIpcType: public IpcType {
5357
public:
5458
[[nodiscard]] const char* name() const override;
5559
[[nodiscard]] const char* genericArgumentName() const override;
60+
[[nodiscard]] qsizetype size() const override;
5661

5762
static const VoidIpcType INSTANCE;
5863
};
@@ -61,6 +66,7 @@ class StringIpcType: public IpcType {
6166
public:
6267
[[nodiscard]] const char* name() const override;
6368
[[nodiscard]] const char* genericArgumentName() const override;
69+
[[nodiscard]] qsizetype size() const override;
6470
[[nodiscard]] void* fromString(const QString& string) const override;
6571
[[nodiscard]] QString toString(void* slot) const override;
6672
[[nodiscard]] void* createStorage() const override;
@@ -73,6 +79,7 @@ class IntIpcType: public IpcType {
7379
public:
7480
[[nodiscard]] const char* name() const override;
7581
[[nodiscard]] const char* genericArgumentName() const override;
82+
[[nodiscard]] qsizetype size() const override;
7683
[[nodiscard]] void* fromString(const QString& string) const override;
7784
[[nodiscard]] QString toString(void* slot) const override;
7885
[[nodiscard]] void* createStorage() const override;
@@ -85,6 +92,7 @@ class BoolIpcType: public IpcType {
8592
public:
8693
[[nodiscard]] const char* name() const override;
8794
[[nodiscard]] const char* genericArgumentName() const override;
95+
[[nodiscard]] qsizetype size() const override;
8896
[[nodiscard]] void* fromString(const QString& string) const override;
8997
[[nodiscard]] QString toString(void* slot) const override;
9098
[[nodiscard]] void* createStorage() const override;
@@ -97,6 +105,7 @@ class DoubleIpcType: public IpcType {
97105
public:
98106
[[nodiscard]] const char* name() const override;
99107
[[nodiscard]] const char* genericArgumentName() const override;
108+
[[nodiscard]] qsizetype size() const override;
100109
[[nodiscard]] void* fromString(const QString& string) const override;
101110
[[nodiscard]] QString toString(void* slot) const override;
102111
[[nodiscard]] void* createStorage() const override;
@@ -109,6 +118,7 @@ class ColorIpcType: public IpcType {
109118
public:
110119
[[nodiscard]] const char* name() const override;
111120
[[nodiscard]] const char* genericArgumentName() const override;
121+
[[nodiscard]] qsizetype size() const override;
112122
[[nodiscard]] void* fromString(const QString& string) const override;
113123
[[nodiscard]] QString toString(void* slot) const override;
114124
[[nodiscard]] void* createStorage() const override;
@@ -127,13 +137,23 @@ struct WireFunctionDefinition {
127137

128138
DEFINE_SIMPLE_DATASTREAM_OPS(WireFunctionDefinition, data.name, data.returnType, data.arguments);
129139

140+
struct WirePropertyDefinition {
141+
QString name;
142+
QString type;
143+
144+
[[nodiscard]] QString toString() const;
145+
};
146+
147+
DEFINE_SIMPLE_DATASTREAM_OPS(WirePropertyDefinition, data.name, data.type);
148+
130149
struct WireTargetDefinition {
131150
QString name;
132151
QVector<WireFunctionDefinition> functions;
152+
QVector<WirePropertyDefinition> properties;
133153

134154
[[nodiscard]] QString toString() const;
135155
};
136156

137-
DEFINE_SIMPLE_DATASTREAM_OPS(WireTargetDefinition, data.name, data.functions);
157+
DEFINE_SIMPLE_DATASTREAM_OPS(WireTargetDefinition, data.name, data.functions, data.properties);
138158

139159
} // namespace qs::io::ipc

src/io/ipccomm.cpp

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@ namespace qs::io::ipc::comm {
2121

2222
struct NoCurrentGeneration: std::monostate {};
2323
struct TargetNotFound: std::monostate {};
24-
struct FunctionNotFound: std::monostate {};
24+
struct EntryNotFound: std::monostate {};
2525

2626
using QueryResponse = std::variant<
2727
std::monostate,
2828
NoCurrentGeneration,
2929
TargetNotFound,
30-
FunctionNotFound,
30+
EntryNotFound,
3131
QVector<WireTargetDefinition>,
3232
WireTargetDefinition,
33-
WireFunctionDefinition>;
33+
WireFunctionDefinition,
34+
WirePropertyDefinition>;
3435

3536
void QueryMetadataCommand::exec(qs::ipc::IpcServerConnection* conn) const {
3637
auto resp = conn->responseStream<QueryResponse>();
@@ -44,16 +45,24 @@ void QueryMetadataCommand::exec(qs::ipc::IpcServerConnection* conn) const {
4445
auto* handler = registry->findHandler(this->target);
4546

4647
if (handler) {
47-
if (this->function.isEmpty()) {
48+
if (this->name.isEmpty()) {
4849
resp << handler->wireDef();
4950
} else {
50-
auto* func = handler->findFunction(this->function);
51+
auto* func = handler->findFunction(this->name);
5152

5253
if (func) {
5354
resp << func->wireDef();
54-
} else {
55-
resp << FunctionNotFound();
55+
return;
5656
}
57+
58+
auto* prop = handler->findProperty(this->name);
59+
60+
if (prop) {
61+
resp << prop->wireDef();
62+
return;
63+
}
64+
65+
resp << EntryNotFound();
5766
}
5867
} else {
5968
resp << TargetNotFound();
@@ -64,8 +73,8 @@ void QueryMetadataCommand::exec(qs::ipc::IpcServerConnection* conn) const {
6473
}
6574
}
6675

67-
int queryMetadata(IpcClient* client, const QString& target, const QString& function) {
68-
client->sendMessage(IpcCommand(QueryMetadataCommand {.target = target, .function = function}));
76+
int queryMetadata(IpcClient* client, const QString& target, const QString& name) {
77+
client->sendMessage(IpcCommand(QueryMetadataCommand {.target = target, .name = name}));
6978

7079
QueryResponse slot;
7180
if (!client->waitForResponse(slot)) return -1;
@@ -82,9 +91,11 @@ int queryMetadata(IpcClient* client, const QString& target, const QString& funct
8291
qCInfo(logBare).noquote() << std::get<WireTargetDefinition>(slot).toString();
8392
} else if (std::holds_alternative<WireFunctionDefinition>(slot)) {
8493
qCInfo(logBare).noquote() << std::get<WireFunctionDefinition>(slot).toString();
94+
} else if (std::holds_alternative<WirePropertyDefinition>(slot)) {
95+
qCInfo(logBare).noquote() << std::get<WirePropertyDefinition>(slot).toString();
8596
} else if (std::holds_alternative<TargetNotFound>(slot)) {
8697
qCCritical(logBare) << "Target not found.";
87-
} else if (std::holds_alternative<FunctionNotFound>(slot)) {
98+
} else if (std::holds_alternative<EntryNotFound>(slot)) {
8899
qCCritical(logBare) << "Function not found.";
89100
} else if (std::holds_alternative<NoCurrentGeneration>(slot)) {
90101
qCCritical(logBare) << "Not ready to accept queries yet.";
@@ -119,7 +130,7 @@ using StringCallResponse = std::variant<
119130
std::monostate,
120131
NoCurrentGeneration,
121132
TargetNotFound,
122-
FunctionNotFound,
133+
EntryNotFound,
123134
ArgParseFailed,
124135
Completed>;
125136

@@ -137,7 +148,7 @@ void StringCallCommand::exec(qs::ipc::IpcServerConnection* conn) const {
137148

138149
auto* func = handler->findFunction(this->function);
139150
if (!func) {
140-
resp << FunctionNotFound();
151+
resp << EntryNotFound();
141152
return;
142153
}
143154

@@ -223,7 +234,7 @@ int callFunction(
223234
qCCritical(logBare).noquote() << "Function definition:" << error.definition.toString();
224235
} else if (std::holds_alternative<TargetNotFound>(slot)) {
225236
qCCritical(logBare) << "Target not found.";
226-
} else if (std::holds_alternative<FunctionNotFound>(slot)) {
237+
} else if (std::holds_alternative<EntryNotFound>(slot)) {
227238
qCCritical(logBare) << "Function not found.";
228239
} else if (std::holds_alternative<NoCurrentGeneration>(slot)) {
229240
qCCritical(logBare) << "Not ready to accept queries yet.";
@@ -233,4 +244,74 @@ int callFunction(
233244

234245
return -1;
235246
}
247+
248+
struct PropertyValue {
249+
QString value;
250+
};
251+
252+
DEFINE_SIMPLE_DATASTREAM_OPS(PropertyValue, data.value);
253+
254+
using StringPropReadResponse =
255+
std::variant<std::monostate, NoCurrentGeneration, TargetNotFound, EntryNotFound, PropertyValue>;
256+
257+
void StringPropReadCommand::exec(qs::ipc::IpcServerConnection* conn) const {
258+
auto resp = conn->responseStream<StringPropReadResponse>();
259+
260+
if (auto* generation = EngineGeneration::currentGeneration()) {
261+
auto* registry = IpcHandlerRegistry::forGeneration(generation);
262+
263+
auto* handler = registry->findHandler(this->target);
264+
if (!handler) {
265+
resp << TargetNotFound();
266+
return;
267+
}
268+
269+
auto* prop = handler->findProperty(this->property);
270+
if (!prop) {
271+
resp << EntryNotFound();
272+
return;
273+
}
274+
275+
auto slot = IpcTypeSlot(prop->type);
276+
prop->read(handler, slot);
277+
278+
resp << PropertyValue {
279+
.value = slot.type()->toString(slot.get()),
280+
};
281+
} else {
282+
conn->respond(StringCallResponse(NoCurrentGeneration()));
283+
}
284+
}
285+
286+
int getProperty(IpcClient* client, const QString& target, const QString& property) {
287+
if (target.isEmpty()) {
288+
qCCritical(logBare) << "Target required to send message.";
289+
return -1;
290+
} else if (property.isEmpty()) {
291+
qCCritical(logBare) << "Property required to send message.";
292+
return -1;
293+
}
294+
295+
client->sendMessage(IpcCommand(StringPropReadCommand {.target = target, .property = property}));
296+
297+
StringPropReadResponse slot;
298+
if (!client->waitForResponse(slot)) return -1;
299+
300+
if (std::holds_alternative<PropertyValue>(slot)) {
301+
auto& result = std::get<PropertyValue>(slot);
302+
QTextStream(stdout) << result.value << Qt::endl;
303+
return 0;
304+
} else if (std::holds_alternative<TargetNotFound>(slot)) {
305+
qCCritical(logBare) << "Target not found.";
306+
} else if (std::holds_alternative<EntryNotFound>(slot)) {
307+
qCCritical(logBare) << "Property not found.";
308+
} else if (std::holds_alternative<NoCurrentGeneration>(slot)) {
309+
qCCritical(logBare) << "Not ready to accept queries yet.";
310+
} else {
311+
qCCritical(logIpc) << "Received invalid IPC response from" << client;
312+
}
313+
314+
return -1;
315+
}
316+
236317
} // namespace qs::io::ipc::comm

0 commit comments

Comments
 (0)