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
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program 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, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ULTIMA8_USECODE_UCLIST_H
#define ULTIMA8_USECODE_UCLIST_H
#include "ultima/shared/std/containers.h"
#include "ultima/shared/std/string.h"
namespace Ultima {
namespace Ultima8 {
// stringlists: _elementSize = 2, each element is actually a stringref
// see for example the 0x0E opcode: there is no way to see if the
// created list is a stringlist or not
// the opcodes which do need a distinction have a operand for this.
// Question: how are unionList/subtractList supposed to know what to do?
// their behaviour differs if this is a stringlist
// Question: does subtractList remove _all_ occurrences of elements or only 1?
class UCList {
Std::vector<uint8> _elements;
unsigned int _elementSize;
unsigned int _size;
public:
UCList(unsigned int elementSize, unsigned int capacity = 0) :
_elementSize(elementSize), _size(0) {
if (capacity > 0)
_elements.reserve(_elementSize * capacity);
}
~UCList() {
// Slight problem: we don't know if we're a stringlist.
// So we need to hope something else has ensured any strings
// are already freed.
free();
}
const uint8 *operator[](uint32 index) const {
// check that index isn't out of bounds...
return &(_elements[index * _elementSize]);
}
uint16 getuint16(uint32 index) const {
assert(_elementSize == 2);
uint16 t = _elements[index * _elementSize];
t += _elements[index * _elementSize + 1] << 8;
return t;
}
void append(const uint8 *e) {
_elements.resize((_size + 1) * _elementSize);
for (unsigned int i = 0; i < _elementSize; i++)
_elements[_size * _elementSize + i] = e[i];
_size++;
}
void appenduint16(uint16 val) {
assert(_elementSize == 2);
uint8 buf[2];
buf[0] = static_cast<uint8>(val);
buf[1] = static_cast<uint8>(val >> 8);
append(buf);
}
void remove(const uint8 *e) {
// do we need to erase all occurrences of e or just the first one?
// (deleting all, currently)
for (unsigned int i = 0; i < _size; i++) {
bool equal = true;
for (unsigned int j = 0; j < _elementSize && equal; j++)
equal = equal && (_elements[i * _elementSize + j] == e[j]);
if (equal) {
_elements.erase(_elements.begin() + i * _elementSize,
_elements.begin() + (i + 1)*_elementSize);
_size--;
i--; // back up a bit
}
}
}
bool inList(const uint8 *e) const {
for (unsigned int i = 0; i < _size; i++) {
bool equal = true;
for (unsigned int j = 0; j < _elementSize && equal; j++)
equal = (_elements[i * _elementSize + j] == e[j]);
if (equal)
return true;
}
return false;
}
void appendList(const UCList &l) {
// elementsizes should match...
assert(_elementSize == l.getElementSize());
_elements.reserve(_elementSize * (_size + l._size));
for (unsigned int i = 0; i < l._size; i++)
append(l[i]);
}
void unionList(const UCList &l) { // like append, but remove duplicates
// elementsizes should match...
assert(_elementSize == l.getElementSize());
_elements.reserve(_elementSize * (_size + l._size));
for (unsigned int i = 0; i < l._size; i++)
if (!inList(l[i]))
append(l[i]);
}
void subtractList(const UCList &l) {
// elementsizes should match...
assert(_elementSize == l.getElementSize());
for (unsigned int i = 0; i < l._size; i++)
remove(l[i]);
}
void free() {
_elements.clear();
_size = 0;
}
uint32 getSize() const {
return _size;
}
unsigned int getElementSize() const {
return _elementSize;
}
void assign(uint32 index, const uint8 *e) {
// need to check that index isn't out-of-bounds? (or grow list?)
for (unsigned int i = 0; i < _elementSize; i++)
_elements[index * _elementSize + i] = e[i];
}
void copyList(const UCList &l) { // deep copy for list
free();
appendList(l);
}
void freeStrings();
void copyStringList(const UCList &l) ;
void unionStringList(UCList &l);
void subtractStringList(const UCList &l);
bool stringInList(uint16 str) const;
void assignString(uint32 index, uint16 str);
void removeString(uint16 str, bool nodel = false);
uint16 getStringIndex(uint32 index) const;
void save(Common::WriteStream *ws) const;
bool load(Common::ReadStream *rs, uint32 version);
private:
const Std::string &getString(uint32 index) const;
};
} // End of namespace Ultima8
} // End of namespace Ultima
#endif
|