Skip to content

Commit f43ea47

Browse files
committed
ModuleMixin: moving code into C++
To reduce need for recompilation on code modifications. To increase compilation speed.
1 parent 4243549 commit f43ea47

2 files changed

Lines changed: 99 additions & 62 deletions

File tree

src/inet/common/ModuleMixin.cc

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//
2+
// Copyright (C) 2025 OpenSim Ltd.
3+
//
4+
// SPDX-License-Identifier: LGPL-3.0-or-later
5+
//
6+
7+
8+
#include "inet/common/StringFormat.h"
9+
10+
#include <algorithm>
11+
#include <type_traits>
12+
#include <vector>
13+
14+
namespace inet {
15+
16+
namespace {
17+
18+
class cCollectObjectsVisitor : public cVisitor
19+
{
20+
public:
21+
const char *name;
22+
std::vector<cObject*> objects;
23+
24+
public:
25+
cCollectObjectsVisitor(const char *name): name(name) { }
26+
27+
protected:
28+
virtual bool visit(cObject *object) override {
29+
if (object->isName(name))
30+
objects.push_back(object);
31+
return true;
32+
}
33+
};
34+
35+
} // unnamed namespace
36+
37+
namespace internal {
38+
39+
void refreshDisplayString(cModule *thisModule, const StringFormat::IResolver *thisModuleAsResolver)
40+
{
41+
if (thisModule->hasPar("displayStringTextFormat")) {
42+
auto displayStringTextFormat = thisModule->par("displayStringTextFormat").stringValue();
43+
if (!opp_isempty(displayStringTextFormat)) {
44+
auto text = StringFormat::formatString(displayStringTextFormat, thisModuleAsResolver);
45+
thisModule->getDisplayString().setTagArg("t", 0, text.c_str());
46+
}
47+
}
48+
}
49+
50+
std::string doResolveExpression(cModule *thisModule, const char *expression)
51+
{
52+
const char *lastDot = strrchr(expression, '.');
53+
54+
cModule *targetModule = thisModule;
55+
const char *fieldName = expression;
56+
57+
if (lastDot != nullptr) {
58+
// Extract submodule path (everything before the last dot)
59+
std::string submodulePath(expression, lastDot - expression);
60+
targetModule = thisModule->getModuleByPath(submodulePath.c_str());
61+
fieldName = lastDot + 1;
62+
}
63+
64+
cCollectObjectsVisitor visitor(fieldName);
65+
visitor.processChildrenOf(targetModule);
66+
67+
if (visitor.objects.empty())
68+
throw cRuntimeError("Unknown expression: %s", expression);
69+
70+
if (visitor.objects.size() > 1) {
71+
std::stable_sort(visitor.objects.begin(), visitor.objects.end(), [] (const cObject *o1, const cObject *o2) {
72+
return dynamic_cast<const cWatchBase *>(o1) != nullptr && dynamic_cast<const cWatchBase *>(o2) == nullptr;
73+
});
74+
}
75+
76+
// special case so that strings are displayed without quotes
77+
if (auto *par = dynamic_cast<cPar *>(visitor.objects[0])) {
78+
if (par->getType() == cPar::STRING)
79+
return par->stdstringValue();
80+
}
81+
if (auto *watchBase = dynamic_cast<cWatchBase *>(visitor.objects[0])) {
82+
any_ptr ptr = watchBase->getValuePointer();
83+
if (ptr.contains<std::string>())
84+
return *ptr.get<std::string>();
85+
}
86+
87+
return visitor.objects[0]->str();
88+
}
89+
90+
} // namespace internal
91+
92+
} // namespace inet

src/inet/common/ModuleMixin.h

Lines changed: 7 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616

1717
namespace inet {
1818

19+
namespace internal {
20+
void refreshDisplayString(cModule *thisModule, const StringFormat::IResolver *thisModuleAsResolver);
21+
std::string doResolveExpression(cModule *targetModule, const char *expression);
22+
}
23+
1924
/**
2025
* A base functionality for all INET modules that implements behavior common to all modules.
2126
*
@@ -30,36 +35,14 @@ class INET_API ModuleMixin : public T, public StringFormat::IResolver
3035
static_assert(std::is_base_of<cModule, T>::value, "Type parameter of ModuleMixin must be a subclass of cModule");
3136

3237
protected:
33-
class cCollectObjectsVisitor : public cVisitor
34-
{
35-
public:
36-
const char *name;
37-
std::vector<cObject*> objects;
38-
39-
public:
40-
cCollectObjectsVisitor(const char *name): name(name) { }
41-
42-
protected:
43-
virtual bool visit(cObject *object) override {
44-
if (object->isName(name))
45-
objects.push_back(object);
46-
return true;
47-
}
48-
};
4938

5039
protected:
5140
virtual void initialize() override { T::initialize(); }
5241
virtual void initialize(int stage) override { T::initialize(stage); }
5342

5443
virtual void refreshDisplay() const override
5544
{
56-
if (T::hasPar("displayStringTextFormat")) {
57-
auto displayStringTextFormat = T::par("displayStringTextFormat").stringValue();
58-
if (!opp_isempty(displayStringTextFormat)) {
59-
auto text = StringFormat::formatString(displayStringTextFormat, this);
60-
T::getDisplayString().setTagArg("t", 0, text.c_str());
61-
}
62-
}
45+
internal::refreshDisplayString(const_cast<ModuleMixin<T>*>(this), this);
6346
T::refreshDisplay();
6447
}
6548

@@ -72,45 +55,7 @@ class INET_API ModuleMixin : public T, public StringFormat::IResolver
7255

7356
virtual std::string resolveExpression(const char *expression) const override
7457
{
75-
const char *lastDot = strrchr(expression, '.');
76-
77-
cModule *targetModule = const_cast<ModuleMixin<T>*>(this);
78-
const char *fieldName = expression;
79-
80-
if (lastDot != nullptr) {
81-
// Extract submodule path (everything before the last dot)
82-
std::string submodulePath(expression, lastDot - expression);
83-
84-
targetModule = const_cast<ModuleMixin<T>*>(this)->getModuleByPath(submodulePath.c_str());
85-
86-
87-
fieldName = lastDot + 1;
88-
}
89-
90-
cCollectObjectsVisitor visitor(fieldName);
91-
visitor.processChildrenOf(targetModule);
92-
93-
if (visitor.objects.empty())
94-
throw cRuntimeError("Unknown expression: %s", expression);
95-
96-
if (visitor.objects.size() > 1) {
97-
std::stable_sort(visitor.objects.begin(), visitor.objects.end(), [] (const cObject *o1, const cObject *o2) {
98-
return dynamic_cast<const cWatchBase *>(o1) != nullptr && dynamic_cast<const cWatchBase *>(o2) == nullptr;
99-
});
100-
}
101-
102-
// special case so that strings are displayed without quotes
103-
if (auto *par = dynamic_cast<cPar *>(visitor.objects[0])) {
104-
if (par->getType() == cPar::STRING)
105-
return par->stdstringValue();
106-
}
107-
if (auto *watchBase = dynamic_cast<cWatchBase *>(visitor.objects[0])) {
108-
any_ptr ptr = watchBase->getValuePointer();
109-
if (ptr.contains<std::string>())
110-
return *ptr.get<std::string>();
111-
}
112-
113-
return visitor.objects[0]->str();
58+
return internal::doResolveExpression(const_cast<ModuleMixin<T>*>(this), expression);
11459
}
11560
};
11661

0 commit comments

Comments
 (0)