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 
45 namespace AGS3 {
46 
47 using namespace AGS::Shared;
48 
50 public:
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;
66 protected:
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 
72 private:
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 
78 template <typename TDict, bool is_sorted, bool is_casesensitive>
79 class ScriptDictImpl final : public ScriptDictBase {
80 public:
81  typedef typename TDict::const_iterator ConstIterator;
82 
83  ScriptDictImpl() {}
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 
139 private:
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: vector.h:39
void push_back(const T &element)
Definition: array.h:180
Definition: script_dict.h:49
Definition: cc_ags_dynamic_object.h:88
Definition: string.h:62
Definition: script_dict.h:79
Definition: stream.h:52
Definition: ags.h:40