179 lines
5.0 KiB
C++
179 lines
5.0 KiB
C++
/* 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
|