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