1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef ULTIMA8_USECODE_UCLIST_H 24 #define ULTIMA8_USECODE_UCLIST_H 25 26 #include "ultima/shared/std/containers.h" 27 #include "ultima/shared/std/string.h" 28 29 namespace Ultima { 30 namespace Ultima8 { 31 32 // stringlists: _elementSize = 2, each element is actually a stringref 33 // see for example the 0x0E opcode: there is no way to see if the 34 // created list is a stringlist or not 35 // the opcodes which do need a distinction have a operand for this. 36 37 // Question: how are unionList/subtractList supposed to know what to do? 38 // their behaviour differs if this is a stringlist 39 40 // Question: does subtractList remove _all_ occurences of elements or only 1? 41 42 class UCList { 43 Std::vector<uint8> _elements; 44 unsigned int _elementSize; 45 unsigned int _size; 46 47 public: 48 UCList(unsigned int elementSize, unsigned int capacity = 0) : _elementSize(elementSize)49 _elementSize(elementSize), _size(0) { 50 if (capacity > 0) 51 _elements.reserve(_elementSize * capacity); 52 } 53 ~UCList()54 ~UCList() { 55 // Slight problem: we don't know if we're a stringlist. 56 // So we need to hope something else has ensured any strings 57 // are already freed. 58 free(); 59 } 60 61 const uint8 *operator[](uint32 index) const { 62 // check that index isn't out of bounds... 63 return &(_elements[index * _elementSize]); 64 } 65 getuint16(uint32 index)66 uint16 getuint16(uint32 index) const { 67 assert(_elementSize == 2); 68 uint16 t = _elements[index * _elementSize]; 69 t += _elements[index * _elementSize + 1] << 8; 70 return t; 71 } 72 append(const uint8 * e)73 void append(const uint8 *e) { 74 _elements.resize((_size + 1) * _elementSize); 75 for (unsigned int i = 0; i < _elementSize; i++) 76 _elements[_size * _elementSize + i] = e[i]; 77 _size++; 78 } 79 appenduint16(uint16 val)80 void appenduint16(uint16 val) { 81 assert(_elementSize == 2); 82 uint8 buf[2]; 83 buf[0] = static_cast<uint8>(val); 84 buf[1] = static_cast<uint8>(val >> 8); 85 append(buf); 86 } 87 remove(const uint8 * e)88 void remove(const uint8 *e) { 89 // do we need to erase all occurences of e or just the first one? 90 // (deleting all, currently) 91 for (unsigned int i = 0; i < _size; i++) { 92 bool equal = true; 93 for (unsigned int j = 0; j < _elementSize && equal; j++) 94 equal = equal && (_elements[i * _elementSize + j] == e[j]); 95 if (equal) { 96 _elements.erase(_elements.begin() + i * _elementSize, 97 _elements.begin() + (i + 1)*_elementSize); 98 _size--; 99 i--; // back up a bit 100 } 101 } 102 } 103 inList(const uint8 * e)104 bool inList(const uint8 *e) const { 105 for (unsigned int i = 0; i < _size; i++) { 106 bool equal = true; 107 for (unsigned int j = 0; j < _elementSize && equal; j++) 108 equal = (_elements[i * _elementSize + j] == e[j]); 109 if (equal) 110 return true; 111 } 112 return false; 113 } 114 appendList(const UCList & l)115 void appendList(const UCList &l) { 116 // elementsizes should match... 117 assert(_elementSize == l.getElementSize()); 118 _elements.reserve(_elementSize * (_size + l._size)); 119 for (unsigned int i = 0; i < l._size; i++) 120 append(l[i]); 121 } unionList(const UCList & l)122 void unionList(const UCList &l) { // like append, but remove duplicates 123 // elementsizes should match... 124 assert(_elementSize == l.getElementSize()); 125 _elements.reserve(_elementSize * (_size + l._size)); 126 for (unsigned int i = 0; i < l._size; i++) 127 if (!inList(l[i])) 128 append(l[i]); 129 } subtractList(const UCList & l)130 void subtractList(const UCList &l) { 131 // elementsizes should match... 132 assert(_elementSize == l.getElementSize()); 133 for (unsigned int i = 0; i < l._size; i++) 134 remove(l[i]); 135 } 136 free()137 void free() { 138 _elements.clear(); 139 _size = 0; 140 } getSize()141 uint32 getSize() const { 142 return _size; 143 } getElementSize()144 unsigned int getElementSize() const { 145 return _elementSize; 146 } 147 assign(uint32 index,const uint8 * e)148 void assign(uint32 index, const uint8 *e) { 149 // need to check that index isn't out-of-bounds? (or grow list?) 150 for (unsigned int i = 0; i < _elementSize; i++) 151 _elements[index * _elementSize + i] = e[i]; 152 } 153 copyList(const UCList & l)154 void copyList(const UCList &l) { // deep copy for list 155 free(); 156 appendList(l); 157 } 158 159 void freeStrings(); 160 void copyStringList(const UCList &l) ; 161 void unionStringList(UCList &l); 162 void subtractStringList(const UCList &l); 163 bool stringInList(uint16 str) const; 164 void assignString(uint32 index, uint16 str); 165 void removeString(uint16 str, bool nodel = false); 166 167 uint16 getStringIndex(uint32 index) const; 168 169 void save(Common::WriteStream *ws) const; 170 bool load(Common::ReadStream *rs, uint32 version); 171 172 private: 173 const Std::string &getString(uint32 index) const; 174 }; 175 176 } // End of namespace Ultima8 177 } // End of namespace Ultima 178 179 #endif 180