ScummVM API documentation
script_dict.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//=============================================================================
23//
24// Managed script object wrapping std::map<String, String> and
25// unordered_map<String, String>.
26//
27// TODO: support wrapping non-owned Dictionary, passed by the reference, -
28// that would let expose internal engine's dicts using same interface.
29// TODO: maybe optimize key lookup operations further by not creating a String
30// object from const char*. It seems, C++14 standard allows to use convertible
31// types as keys; need to research what performance impact that would make.
32//
33//=============================================================================
34
35#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
36#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
37
38#include "common/std/map.h"
39#include "common/std/map.h"
40#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
41#include "ags/shared/util/stream.h"
42#include "ags/shared/util/string.h"
43#include "ags/shared/util/string_types.h"
44
45namespace AGS3 {
46
47using namespace AGS::Shared;
48
50public:
51 int Dispose(void *address, bool force) override;
52 const char *GetType() override;
53 void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
54
55 virtual bool IsCaseSensitive() const = 0;
56 virtual bool IsSorted() const = 0;
57
58 virtual void Clear() = 0;
59 virtual bool Contains(const char *key) = 0;
60 virtual const char *Get(const char *key) = 0;
61 virtual bool Remove(const char *key) = 0;
62 virtual bool Set(const char *key, const char *value) = 0;
63 virtual int GetItemCount() = 0;
64 virtual void GetKeys(std::vector<const char *> &buf) const = 0;
65 virtual void GetValues(std::vector<const char *> &buf) const = 0;
66protected:
67 // Calculate and return required space for serialization, in bytes
68 size_t CalcSerializeSize(const void *address) override;
69 // Write object data into the provided stream
70 void Serialize(const void *address, AGS::Shared::Stream *out) override;
71
72private:
73 virtual size_t CalcContainerSize() = 0;
74 virtual void SerializeContainer(AGS::Shared::Stream *out) = 0;
75 virtual void UnserializeContainer(AGS::Shared::Stream *in) = 0;
76};
77
78template <typename TDict, bool is_sorted, bool is_casesensitive>
79class ScriptDictImpl final : public ScriptDictBase {
80public:
81 typedef typename TDict::const_iterator ConstIterator;
82
84
85 bool IsCaseSensitive() const override {
86 return is_casesensitive;
87 }
88 bool IsSorted() const override {
89 return is_sorted;
90 }
91
92 void Clear() override {
93 for (auto it = _dic.begin(); it != _dic.end(); ++it)
94 DeleteItem(it);
95 _dic.clear();
96 }
97 bool Contains(const char *key) override {
98#ifdef AGS_PLATFORM_SCUMMVM
99 return _dic.find(String::Wrapper(key)) != _dic.end();
100#else
101 return _dic.count(String::Wrapper(key)) != 0;
102#endif
103 }
104 const char *Get(const char *key) override {
105 auto it = _dic.find(String::Wrapper(key));
106 if (it == _dic.end()) return nullptr;
107 return it->_value.GetCStr();
108 }
109 bool Remove(const char *key) override {
110 auto it = _dic.find(String::Wrapper(key));
111 if (it == _dic.end()) return false;
112 DeleteItem(it);
113 _dic.erase(it);
114 return true;
115 }
116 bool Set(const char *key, const char *value) override {
117 if (!key)
118 return false;
119 if (!value) {
120 // Remove keys with null value
121 Remove(key);
122 return true;
123 }
124
125 return TryAddItem(String(key), String(value));
126 }
127 int GetItemCount() override {
128 return _dic.size();
129 }
130 void GetKeys(std::vector<const char *> &buf) const override {
131 for (auto it = _dic.begin(); it != _dic.end(); ++it)
132 buf.push_back(it->_key.GetCStr());
133 }
134 void GetValues(std::vector<const char *> &buf) const override {
135 for (auto it = _dic.begin(); it != _dic.end(); ++it)
136 buf.push_back(it->_value.GetCStr());
137 }
138
139private:
140 bool TryAddItem(const String &key, const String &value) {
141 _dic[key] = value;
142 return true;
143 }
144 void DeleteItem(ConstIterator /*it*/) { /* do nothing */ }
145
146 size_t CalcContainerSize() override {
147 // 2 class properties + item count
148 size_t total_sz = sizeof(int32_t) * 3;
149 // (int32 + string buffer) per item
150 for (auto it = _dic.begin(); it != _dic.end(); ++it) {
151 total_sz += sizeof(int32_t) + it->_key.GetLength();
152 total_sz += sizeof(int32_t) + it->_value.GetLength();
153 }
154 return total_sz;
155 }
156
157 void SerializeContainer(AGS::Shared::Stream *out) override
158 {
159 out->WriteInt32((int)_dic.size());
160 for (auto it = _dic.begin(); it != _dic.end(); ++it)
161 {
162 out->WriteInt32((int)it->_key.GetLength());
163 out->Write(it->_key.GetCStr(), it->_key.GetLength());
164 out->WriteInt32((int)it->_value.GetLength());
165 out->Write(it->_value.GetCStr(), it->_value.GetLength());
166 }
167 }
168
169 void UnserializeContainer(AGS::Shared::Stream *in) override {
170 size_t item_count = in->ReadInt32();
171 for (size_t i = 0; i < item_count; ++i) {
172 size_t key_len = in->ReadInt32();
173 String key = String::FromStreamCount(in, key_len);
174 size_t value_len = in->ReadInt32();
175 if (value_len != (size_t)-1) // do not restore keys with null value (old format)
176 {
177 String value = String::FromStreamCount(in, value_len);
178 TryAddItem(key, value);
179 }
180 }
181 }
182
183 TDict _dic;
184};
185
190
191} // namespace AGS3
192
193#endif
Definition: stream.h:52
Definition: string.h:60
Definition: script_dict.h:49
Definition: script_dict.h:79
void push_back(const T &element)
Definition: array.h:181
Definition: vector.h:39
Definition: cc_ags_dynamic_object.h:88