ScummVM API documentation
uc_list.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef ULTIMA8_USECODE_UCLIST_H
23 #define ULTIMA8_USECODE_UCLIST_H
24 
25 #include "common/array.h"
26 
27 namespace Common {
28 class ReadStream;
29 class WriteStream;
30 }
31 
32 namespace Ultima {
33 namespace Ultima8 {
34 
35 // stringlists: _elementSize = 2, each element is actually a stringref
36 // see for example the 0x0E opcode: there is no way to see if the
37 // created list is a stringlist or not
38 // the opcodes which do need a distinction have a operand for this.
39 
40 // Question: how are unionList/subtractList supposed to know what to do?
41 // their behaviour differs if this is a stringlist
42 
43 // Question: does subtractList remove _all_ occurrences of elements or only 1?
44 
45 class UCList {
46  Common::Array<uint8> _elements;
47  unsigned int _elementSize;
48  unsigned int _size;
49 
50 public:
51  UCList(unsigned int elementSize, unsigned int capacity = 0) :
52  _elementSize(elementSize), _size(0) {
53  if (capacity > 0)
54  _elements.reserve(_elementSize * capacity);
55  }
56 
57  ~UCList() {
58  // Slight problem: we don't know if we're a stringlist.
59  // So we need to hope something else has ensured any strings
60  // are already freed.
61  free();
62  }
63 
64  const uint8 *operator[](uint32 index) const {
65  // check that index isn't out of bounds...
66  return &(_elements[index * _elementSize]);
67  }
68 
69  uint16 getuint16(uint32 index) const {
70  assert(_elementSize == 2);
71  uint16 t = _elements[index * _elementSize];
72  t += _elements[index * _elementSize + 1] << 8;
73  return t;
74  }
75 
76  void append(const uint8 *e) {
77  _elements.resize((_size + 1) * _elementSize);
78  for (unsigned int i = 0; i < _elementSize; i++)
79  _elements[_size * _elementSize + i] = e[i];
80  _size++;
81  }
82 
83  void appenduint16(uint16 val) {
84  assert(_elementSize == 2);
85  uint8 buf[2];
86  buf[0] = static_cast<uint8>(val);
87  buf[1] = static_cast<uint8>(val >> 8);
88  append(buf);
89  }
90 
91  void remove(const uint8 *e) {
92  // do we need to erase all occurrences of e or just the first one?
93  // (deleting all, currently)
94  for (unsigned int i = 0; i < _size; i++) {
95  bool equal = true;
96  for (unsigned int j = 0; j < _elementSize && equal; j++)
97  equal = equal && (_elements[i * _elementSize + j] == e[j]);
98  if (equal) {
99  _elements.erase(_elements.begin() + i * _elementSize,
100  _elements.begin() + (i + 1)*_elementSize);
101  _size--;
102  i--; // back up a bit
103  }
104  }
105  }
106 
107  bool inList(const uint8 *e) const {
108  for (unsigned int i = 0; i < _size; i++) {
109  bool equal = true;
110  for (unsigned int j = 0; j < _elementSize && equal; j++)
111  equal = (_elements[i * _elementSize + j] == e[j]);
112  if (equal)
113  return true;
114  }
115  return false;
116  }
117 
118  void appendList(const UCList &l) {
119  // elementsizes should match...
120  assert(_elementSize == l.getElementSize());
121  _elements.reserve(_elementSize * (_size + l._size));
122  for (unsigned int i = 0; i < l._size; i++)
123  append(l[i]);
124  }
125  void unionList(const UCList &l) { // like append, but remove duplicates
126  // elementsizes should match...
127  assert(_elementSize == l.getElementSize());
128  _elements.reserve(_elementSize * (_size + l._size));
129  for (unsigned int i = 0; i < l._size; i++)
130  if (!inList(l[i]))
131  append(l[i]);
132  }
133  void subtractList(const UCList &l) {
134  // elementsizes should match...
135  assert(_elementSize == l.getElementSize());
136  for (unsigned int i = 0; i < l._size; i++)
137  remove(l[i]);
138  }
139 
140  void free() {
141  _elements.clear();
142  _size = 0;
143  }
144  uint32 getSize() const {
145  return _size;
146  }
147  unsigned int getElementSize() const {
148  return _elementSize;
149  }
150 
151  void assign(uint32 index, const uint8 *e) {
152  // need to check that index isn't out-of-bounds? (or grow list?)
153  for (unsigned int i = 0; i < _elementSize; i++)
154  _elements[index * _elementSize + i] = e[i];
155  }
156 
157  void copyList(const UCList &l) { // deep copy for list
158  free();
159  appendList(l);
160  }
161 
162  void freeStrings();
163  void copyStringList(const UCList &l) ;
164  void unionStringList(UCList &l);
165  void subtractStringList(const UCList &l);
166  bool stringInList(uint16 str) const;
167  void assignString(uint32 index, uint16 str);
168  void removeString(uint16 str, bool nodel = false);
169 
170  uint16 getStringIndex(uint32 index) const;
171 
172  void save(Common::WriteStream *ws) const;
173  bool load(Common::ReadStream *rs, uint32 version);
174 
175 private:
176  const Common::String &getString(uint32 index) const;
177 };
178 
179 } // End of namespace Ultima8
180 } // End of namespace Ultima
181 
182 #endif
Definition: str.h:59
Definition: stream.h:77
void clear()
Definition: array.h:321
iterator begin()
Definition: array.h:375
Definition: detection.h:27
void reserve(size_type newCapacity)
Definition: array.h:397
Definition: algorithm.h:29
Definition: uc_list.h:45
void resize(size_type newSize)
Definition: array.h:412
Definition: stream.h:385
iterator erase(iterator pos)
Definition: array.h:329