Skip to content

Commit 06f2017

Browse files
committed
fix #560: Return a list in IEngine::findBroadcasts()
1 parent 2e966ed commit 06f2017

File tree

7 files changed

+90
-49
lines changed

7 files changed

+90
-49
lines changed

include/scratchcpp/iengine.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ class LIBSCRATCHCPP_EXPORT IEngine
291291
/*! Returns the broadcast at index. */
292292
virtual std::shared_ptr<Broadcast> broadcastAt(int index) const = 0;
293293

294-
/*! Returns the index of the broadcast with the given name. */
295-
virtual int findBroadcast(const std::string &broadcastName) const = 0;
294+
/*! Returns the list of indexes of the broadcasts with the given name (case insensitive). */
295+
virtual std::vector<int> findBroadcasts(const std::string &broadcastName) const = 0;
296296

297297
/*! Returns the index of the broadcast with the given ID. */
298298
virtual int findBroadcastById(const std::string &broadcastId) const = 0;

src/blocks/eventblocks.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,12 @@ void EventBlocks::compileBroadcast(Compiler *compiler)
9999
auto input = compiler->input(BROADCAST_INPUT);
100100

101101
if (input->type() != Input::Type::ObscuredShadow) {
102-
compiler->addConstValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
103-
compiler->addFunctionCall(&broadcastByIndex);
102+
std::vector<int> broadcasts = compiler->engine()->findBroadcasts(input->primaryValue()->value().toString());
103+
104+
for (int index : broadcasts) {
105+
compiler->addConstValue(index);
106+
compiler->addFunctionCall(&broadcastByIndex);
107+
}
104108
} else {
105109
compiler->addInput(input);
106110
compiler->addFunctionCall(&broadcast);
@@ -112,11 +116,14 @@ void EventBlocks::compileBroadcastAndWait(Compiler *compiler)
112116
auto input = compiler->input(BROADCAST_INPUT);
113117

114118
if (input->type() != Input::Type::ObscuredShadow) {
115-
int index = compiler->engine()->findBroadcast(input->primaryValue()->value().toString());
116-
compiler->addConstValue(index);
117-
compiler->addFunctionCall(&broadcastByIndexAndWait);
118-
compiler->addConstValue(index);
119-
compiler->addFunctionCall(&checkBroadcastByIndex);
119+
std::vector<int> broadcasts = compiler->engine()->findBroadcasts(input->primaryValue()->value().toString());
120+
121+
for (int index : broadcasts) {
122+
compiler->addConstValue(index);
123+
compiler->addFunctionCall(&broadcastByIndexAndWait);
124+
compiler->addConstValue(index);
125+
compiler->addFunctionCall(&checkBroadcastByIndex);
126+
}
120127
} else {
121128
compiler->addInput(input);
122129
compiler->addFunctionCall(&broadcastAndWait);
@@ -197,7 +204,11 @@ unsigned int EventBlocks::whenTouchingObjectPredicate(VirtualMachine *vm)
197204

198205
unsigned int EventBlocks::broadcast(VirtualMachine *vm)
199206
{
200-
vm->engine()->broadcast(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()));
207+
std::vector<int> broadcasts = vm->engine()->findBroadcasts(vm->getInput(0, 1)->toString());
208+
209+
for (int index : broadcasts)
210+
vm->engine()->broadcast(index);
211+
201212
return 1;
202213
}
203214

@@ -209,7 +220,11 @@ unsigned int EventBlocks::broadcastByIndex(VirtualMachine *vm)
209220

210221
unsigned int EventBlocks::broadcastAndWait(VirtualMachine *vm)
211222
{
212-
vm->engine()->broadcast(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString()));
223+
std::vector<int> broadcasts = vm->engine()->findBroadcasts(vm->getInput(0, 1)->toString());
224+
225+
for (int index : broadcasts)
226+
vm->engine()->broadcast(index);
227+
213228
return 1;
214229
}
215230

@@ -221,8 +236,20 @@ unsigned int EventBlocks::broadcastByIndexAndWait(VirtualMachine *vm)
221236

222237
unsigned int EventBlocks::checkBroadcast(VirtualMachine *vm)
223238
{
224-
if (vm->engine()->broadcastRunning(vm->engine()->findBroadcast(vm->getInput(0, 1)->toString())))
239+
bool running = false;
240+
241+
std::vector<int> broadcasts = vm->engine()->findBroadcasts(vm->getInput(0, 1)->toString());
242+
243+
for (int index : broadcasts) {
244+
if (vm->engine()->broadcastRunning(index)) {
245+
running = true;
246+
break;
247+
}
248+
}
249+
250+
if (running)
225251
vm->stop(true, true, true);
252+
226253
return 1;
227254
}
228255

src/engine/internal/engine.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,21 +1081,21 @@ std::shared_ptr<Broadcast> Engine::broadcastAt(int index) const
10811081
return m_broadcasts[index];
10821082
}
10831083

1084-
int Engine::findBroadcast(const std::string &broadcastName) const
1084+
std::vector<int> Engine::findBroadcasts(const std::string &broadcastName) const
10851085
{
1086+
std::vector<int> ret;
10861087
std::string lowercaseName = broadcastName;
10871088
std::transform(lowercaseName.begin(), lowercaseName.end(), lowercaseName.begin(), ::tolower);
10881089

1089-
auto it = std::find_if(m_broadcasts.begin(), m_broadcasts.end(), [lowercaseName](std::shared_ptr<Broadcast> broadcast) {
1090-
std::string name = broadcast->name();
1090+
for (unsigned int i = 0; i < m_broadcasts.size(); i++) {
1091+
std::string name = m_broadcasts[i]->name();
10911092
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
1092-
return name == lowercaseName;
1093-
});
10941093

1095-
if (it == m_broadcasts.end())
1096-
return -1;
1097-
else
1098-
return it - m_broadcasts.begin();
1094+
if (name == lowercaseName)
1095+
ret.push_back(i);
1096+
}
1097+
1098+
return ret;
10991099
}
11001100

11011101
int Engine::findBroadcastById(const std::string &broadcastId) const

src/engine/internal/engine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class Engine : public IEngine
123123
const std::vector<std::shared_ptr<Broadcast>> &broadcasts() const override;
124124
void setBroadcasts(const std::vector<std::shared_ptr<Broadcast>> &broadcasts) override;
125125
std::shared_ptr<Broadcast> broadcastAt(int index) const override;
126-
int findBroadcast(const std::string &broadcastName) const override;
126+
std::vector<int> findBroadcasts(const std::string &broadcastName) const override;
127127
int findBroadcastById(const std::string &broadcastId) const override;
128128

129129
void addWhenTouchingObjectScript(std::shared_ptr<Block> hatBlock) override;

test/blocks/event_blocks_test.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,8 @@ TEST_F(EventBlocksTest, Broadcast)
373373
notBlock->setCompileFunction(&OperatorBlocks::compileNot);
374374
addObscuredInput(block2, "BROADCAST_INPUT", EventBlocks::BROADCAST_INPUT, notBlock);
375375

376-
EXPECT_CALL(m_engineMock, findBroadcast("test")).WillOnce(Return(0));
377-
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::broadcastByIndex)).WillOnce(Return(0));
376+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 0, 3 })));
377+
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::broadcastByIndex)).Times(2).WillRepeatedly(Return(0));
378378
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::broadcast)).WillOnce(Return(1));
379379

380380
compiler.init();
@@ -384,9 +384,8 @@ TEST_F(EventBlocksTest, Broadcast)
384384
EventBlocks::compileBroadcast(&compiler);
385385
compiler.end();
386386

387-
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 1, vm::OP_HALT }));
388-
ASSERT_EQ(compiler.constValues().size(), 1);
389-
ASSERT_EQ(compiler.constValues()[0].toDouble(), 0);
387+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 1, vm::OP_EXEC, 0, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 1, vm::OP_HALT }));
388+
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 0, 3 }));
390389
ASSERT_TRUE(compiler.variables().empty());
391390
ASSERT_TRUE(compiler.lists().empty());
392391
}
@@ -402,8 +401,9 @@ TEST_F(EventBlocksTest, BroadcastImpl)
402401
vm.setFunctions(functions);
403402
vm.setConstValues(constValues);
404403

405-
EXPECT_CALL(m_engineMock, findBroadcast("test")).WillOnce(Return(1));
406-
EXPECT_CALL(m_engineMock, broadcast(1)).Times(1);
404+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 1, 4 })));
405+
EXPECT_CALL(m_engineMock, broadcast(1));
406+
EXPECT_CALL(m_engineMock, broadcast(4));
407407

408408
vm.setBytecode(bytecode1);
409409
vm.run();
@@ -432,9 +432,9 @@ TEST_F(EventBlocksTest, BroadcastAndWait)
432432
notBlock->setCompileFunction(&OperatorBlocks::compileNot);
433433
addObscuredInput(block2, "BROADCAST_INPUT", EventBlocks::BROADCAST_INPUT, notBlock);
434434

435-
EXPECT_CALL(m_engineMock, findBroadcast("test")).WillOnce(Return(0));
436-
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::broadcastByIndexAndWait)).WillOnce(Return(0));
437-
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::checkBroadcastByIndex)).WillOnce(Return(1));
435+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 0, 3 })));
436+
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::broadcastByIndexAndWait)).Times(2).WillRepeatedly(Return(0));
437+
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::checkBroadcastByIndex)).Times(2).WillRepeatedly(Return(1));
438438
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::broadcastAndWait)).WillOnce(Return(2));
439439
EXPECT_CALL(m_engineMock, functionIndex(&EventBlocks::checkBroadcast)).WillOnce(Return(3));
440440

@@ -448,8 +448,9 @@ TEST_F(EventBlocksTest, BroadcastAndWait)
448448
ASSERT_EQ(
449449
compiler.bytecode(),
450450
std::vector<unsigned int>(
451-
{ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 1, vm::OP_EXEC, 1, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 2, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 3, vm::OP_HALT }));
452-
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 0, 0 }));
451+
{ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 1, vm::OP_EXEC, 1, vm::OP_CONST, 2, vm::OP_EXEC, 0, vm::OP_CONST, 3, vm::OP_EXEC, 1,
452+
vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 2, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 3, vm::OP_HALT }));
453+
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 0, 0, 3, 3 }));
453454
ASSERT_TRUE(compiler.variables().empty());
454455
ASSERT_TRUE(compiler.lists().empty());
455456
}
@@ -467,15 +468,16 @@ TEST_F(EventBlocksTest, BroadcastAndWaitImpl)
467468
vm.setFunctions(functions);
468469
vm.setConstValues(constValues);
469470

470-
EXPECT_CALL(m_engineMock, findBroadcast("test")).WillOnce(Return(1));
471-
EXPECT_CALL(m_engineMock, broadcast(1)).Times(1);
471+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 1, 4 })));
472+
EXPECT_CALL(m_engineMock, broadcast(1));
473+
EXPECT_CALL(m_engineMock, broadcast(4));
472474

473475
vm.setBytecode(bytecode1);
474476
vm.run();
475477

476478
ASSERT_EQ(vm.registerCount(), 0);
477479

478-
EXPECT_CALL(m_engineMock, findBroadcast("test")).WillOnce(Return(2));
480+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 2, 3 })));
479481
EXPECT_CALL(m_engineMock, broadcastRunning(2)).WillOnce(Return(true));
480482

481483
vm.setBytecode(bytecode2);
@@ -484,8 +486,18 @@ TEST_F(EventBlocksTest, BroadcastAndWaitImpl)
484486
ASSERT_EQ(vm.registerCount(), 1);
485487
ASSERT_EQ(vm.atEnd(), false);
486488

487-
EXPECT_CALL(m_engineMock, findBroadcast("test")).WillOnce(Return(2));
489+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 2, 3 })));
490+
EXPECT_CALL(m_engineMock, broadcastRunning(2)).WillOnce(Return(true));
491+
492+
vm.reset();
493+
vm.run();
494+
495+
ASSERT_EQ(vm.registerCount(), 1);
496+
ASSERT_EQ(vm.atEnd(), false);
497+
498+
EXPECT_CALL(m_engineMock, findBroadcasts("test")).WillOnce(Return(std::vector<int>({ 2, 3 })));
488499
EXPECT_CALL(m_engineMock, broadcastRunning(2)).WillOnce(Return(false));
500+
EXPECT_CALL(m_engineMock, broadcastRunning(3)).WillOnce(Return(false));
489501

490502
vm.run();
491503

test/engine/engine_test.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,23 +1276,25 @@ TEST(EngineTest, Broadcasts)
12761276
auto b1 = std::make_shared<Broadcast>("a", "message1");
12771277
auto b2 = std::make_shared<Broadcast>("b", "message2");
12781278
auto b3 = std::make_shared<Broadcast>("c", "Test");
1279-
engine.setBroadcasts({ b1, b2, b3 });
1279+
auto b4 = std::make_shared<Broadcast>("d", "TesT");
1280+
engine.setBroadcasts({ b1, b2, b3, b4 });
12801281

1281-
ASSERT_EQ(engine.broadcasts(), std::vector<std::shared_ptr<Broadcast>>({ b1, b2, b3 }));
1282+
ASSERT_EQ(engine.broadcasts(), std::vector<std::shared_ptr<Broadcast>>({ b1, b2, b3, b4 }));
12821283
ASSERT_EQ(engine.broadcastAt(0), b1);
12831284
ASSERT_EQ(engine.broadcastAt(1), b2);
12841285
ASSERT_EQ(engine.broadcastAt(2), b3);
1285-
ASSERT_EQ(engine.broadcastAt(3), nullptr);
1286+
ASSERT_EQ(engine.broadcastAt(3), b4);
1287+
ASSERT_EQ(engine.broadcastAt(4), nullptr);
12861288
ASSERT_EQ(engine.broadcastAt(-1), nullptr);
12871289

1288-
ASSERT_EQ(engine.findBroadcast("invalid"), -1);
1289-
ASSERT_EQ(engine.findBroadcast("message1"), 0);
1290-
ASSERT_EQ(engine.findBroadcast("message2"), 1);
1291-
ASSERT_EQ(engine.findBroadcast("Test"), 2);
1292-
ASSERT_EQ(engine.findBroadcast("MessAge2"), 1);
1293-
ASSERT_EQ(engine.findBroadcast("tEst"), 2);
1290+
ASSERT_TRUE(engine.findBroadcasts("invalid").empty());
1291+
ASSERT_EQ(engine.findBroadcasts("message1"), std::vector<int>({ 0 }));
1292+
ASSERT_EQ(engine.findBroadcasts("message2"), std::vector<int>({ 1 }));
1293+
ASSERT_EQ(engine.findBroadcasts("Test"), std::vector<int>({ 2, 3 }));
1294+
ASSERT_EQ(engine.findBroadcasts("MessAge2"), std::vector<int>({ 1 }));
1295+
ASSERT_EQ(engine.findBroadcasts("tEst"), std::vector<int>({ 2, 3 }));
12941296

1295-
ASSERT_EQ(engine.findBroadcastById("d"), -1);
1297+
ASSERT_EQ(engine.findBroadcastById("e"), -1);
12961298
ASSERT_EQ(engine.findBroadcastById("a"), 0);
12971299
ASSERT_EQ(engine.findBroadcastById("b"), 1);
12981300
ASSERT_EQ(engine.findBroadcastById("c"), 2);

test/mocks/enginemock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class EngineMock : public IEngine
103103
MOCK_METHOD(const std::vector<std::shared_ptr<Broadcast>> &, broadcasts, (), (const, override));
104104
MOCK_METHOD(void, setBroadcasts, (const std::vector<std::shared_ptr<Broadcast>> &), (override));
105105
MOCK_METHOD(std::shared_ptr<Broadcast>, broadcastAt, (int), (const, override));
106-
MOCK_METHOD(int, findBroadcast, (const std::string &), (const, override));
106+
MOCK_METHOD(std::vector<int>, findBroadcasts, (const std::string &), (const, override));
107107
MOCK_METHOD(int, findBroadcastById, (const std::string &), (const, override));
108108

109109
MOCK_METHOD(void, addWhenTouchingObjectScript, (std::shared_ptr<Block>), (override));

0 commit comments

Comments
 (0)