2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file script_priorityqueue.cpp Implementation of ScriptPriorityQueue. */
10 #include "../../stdafx.h"
11 #include "script_priorityqueue.hpp"
12 #include "script_error.hpp"
13 #include "../squirrel_helper.hpp"
14 #include "../script_instance.hpp"
15 #include "../../debug.h"
17 #include "../../safeguards.h"
20 static bool operator==(const ScriptPriorityQueue::PriorityItem
&lhs
, const HSQOBJECT
&rhs
)
22 return lhs
.second
._type
== rhs
._type
&& lhs
.second
._unVal
.raw
== rhs
._unVal
.raw
;
26 ScriptPriorityQueue::~ScriptPriorityQueue()
28 /* Release reference to stored objects. */
29 auto inst
= ScriptObject::GetActiveInstance();
30 if (!inst
->InShutdown()) {
31 for (auto &i
: this->queue
) inst
->ReleaseSQObject(const_cast<HSQOBJECT
*>(&i
.second
));
35 SQInteger
ScriptPriorityQueue::Insert(HSQUIRRELVM vm
)
39 sq_resetobject(&item
);
40 sq_getstackobj(vm
, 2, &item
);
41 sq_getinteger(vm
, 3, &priority
);
43 sq_addref(vm
, &item
); // Keep object alive.
45 this->queue
.emplace_back(priority
, item
);
46 std::push_heap(this->queue
.begin(), this->queue
.end(), this->comp
);
48 return SQConvert::Return
<bool>::Set(vm
, true);
51 SQInteger
ScriptPriorityQueue::Pop(HSQUIRRELVM vm
)
53 if (this->IsEmpty()) {
54 ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED
);
59 HSQOBJECT item
= this->queue
.front().second
;
60 std::pop_heap(this->queue
.begin(), this->queue
.end(), this->comp
);
61 this->queue
.pop_back();
63 /* Store the object on the Squirrel stack before releasing it to make sure the ref count can't drop to zero. */
64 auto ret
= SQConvert::Return
<HSQOBJECT
>::Set(vm
, item
);
65 sq_release(vm
, &item
);
69 SQInteger
ScriptPriorityQueue::Peek(HSQUIRRELVM vm
)
71 if (this->IsEmpty()) {
72 ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED
);
77 return SQConvert::Return
<HSQOBJECT
>::Set(vm
, this->queue
.front().second
);
80 SQInteger
ScriptPriorityQueue::Exists(HSQUIRRELVM vm
)
83 sq_resetobject(&item
);
84 sq_getstackobj(vm
, 2, &item
);
86 return SQConvert::Return
<bool>::Set(vm
, std::find(this->queue
.cbegin(), this->queue
.cend(), item
) != this->queue
.cend());
89 SQInteger
ScriptPriorityQueue::Clear(HSQUIRRELVM vm
)
91 /* Release reference to stored objects. */
92 for (auto &i
: this->queue
) sq_release(vm
, const_cast<HSQOBJECT
*>(&i
.second
));
98 bool ScriptPriorityQueue::IsEmpty()
100 return this->queue
.empty();
103 SQInteger
ScriptPriorityQueue::Count()
105 return (SQInteger
)this->queue
.size();