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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
#include "stdafx.h"
#include "Queue.h"
namespace storm {
QueueBase::QueueBase(const Handle &type) : handle(type), data(null), head(0) {}
QueueBase::QueueBase(const QueueBase &other) : handle(other.handle), data(null), head(0) {
if (other.empty())
return;
Nat count = other.count();
ensure(count);
Nat at = other.head;
for (Nat i = 0; i < count; i++, step(at)) {
handle.safeCopy(ptr(i), other.ptr(at));
}
data->filled = count;
}
void QueueBase::deepCopy(CloneEnv *env) {
if (handle.deepCopyFn && data) {
Nat at = head;
for (Nat i = 0; i < data->filled; i++, step(at)) {
(*handle.deepCopyFn)(ptr(at), env);
}
}
}
void QueueBase::ensure(Nat n) {
if (n == 0)
return;
Nat oldCap = data ? Nat(data->count) : 0;
if (oldCap >= n)
return;
Nat oldCount = count();
Nat newCap = max(Nat(16), oldCap * 2);
if (newCap < n)
newCap = n;
GcArray<byte> *newData = runtime::allocArray<byte>(engine(), handle.gcArrayType, newCap);
if (data) {
// Copy from head to the end.
Nat firstBatch = min(oldCount, Nat(data->count) - head);
memcpy(ptr(newData, 0), ptr(head), handle.size*firstBatch);
// If needed, copy remaining elements.
if (firstBatch < oldCount)
memcpy(ptr(newData, firstBatch), ptr(0), handle.size*(oldCount - firstBatch));
// Update metadata.
data->filled = 0;
newData->filled = oldCount;
}
// Swap contents.
data = newData;
head = 0;
}
void QueueBase::reserve(Nat n) {
ensure(n);
}
void QueueBase::clear() {
data = null;
head = 0;
}
void *QueueBase::topRaw() {
if (empty())
throw new (this) QueueError(S("Cannot get the top element of an empty queue."));
return ptr(head);
}
void QueueBase::pop() {
if (empty())
throw new (this) QueueError(S("Cannot pop an empty queue."));
head++;
if (head >= data->count)
head -= Nat(data->count);
data->filled--;
}
void QueueBase::pushRaw(const void *elem) {
ensure(count() + 1);
Nat to = head + Nat(data->filled);
if (to >= data->count)
to -= Nat(data->count);
handle.safeCopy(ptr(to), elem);
data->filled++;
}
void QueueBase::toS(StrBuf *to) const {
*to << S("Queue:[");
for (Nat at = head, i = 0; i < count(); i++, step(at)) {
if (i > 0)
*to << S(", ");
(*handle.toSFn)(ptr(at), to);
}
*to << S("]");
}
QueueBase::Iter QueueBase::beginRaw() {
return Iter(this, 0);
}
QueueBase::Iter QueueBase::endRaw() {
return Iter(this, count());
}
QueueBase::Iter::Iter() : owner(null), index(0) {}
QueueBase::Iter::Iter(QueueBase *owner, Nat index) : owner(owner), index(index) {}
Bool QueueBase::Iter::operator ==(const Iter &o) const {
if (atEnd() || o.atEnd())
return atEnd() == o.atEnd();
else
return index == o.index && owner == o.owner;
}
Bool QueueBase::Iter::atEnd() const {
return owner == null
|| owner->count() <= index;
}
Bool QueueBase::Iter::operator !=(const Iter &o) const {
return !(*this == o);
}
QueueBase::Iter &QueueBase::Iter::operator ++() {
if (!atEnd())
index++;
return *this;
}
QueueBase::Iter QueueBase::Iter::operator ++(int) {
Iter c = *this;
++(*this);
return c;
}
void *QueueBase::Iter::getRaw() const {
if (atEnd()) {
Engine &e = runtime::someEngine();
throw new (e) QueueError(S("Trying to dereference an invalid iterator."));
}
Nat i = owner->head + index;
if (i >= owner->data->count)
i -= Nat(owner->data->count);
return owner->ptr(i);
}
QueueBase::Iter &QueueBase::Iter::preIncRaw() {
return operator ++();
}
QueueBase::Iter QueueBase::Iter::postIncRaw() {
return operator ++(0);
}
QueueError::QueueError(const wchar *msg) : msg(new (engine()) Str(msg)) {
saveTrace();
}
QueueError::QueueError(Str *msg) : msg(msg) {
saveTrace();
}
void QueueError::message(StrBuf *to) const {
*to << S("Queue error: ") << msg;
}
}
|