File: uc_list.h

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (178 lines) | stat: -rw-r--r-- 5,161 bytes parent folder | download | duplicates (3)
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