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(const char *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  // Write object data into the provided stream
68  void Serialize(const char *address, AGS::Shared::Stream *out) override;
69 
70 private:
71  virtual void SerializeContainer(AGS::Shared::Stream *out) = 0;
72  virtual void UnserializeContainer(AGS::Shared::Stream *in) = 0;
73 };
74 
75 template <typename TDict, bool is_sorted, bool is_casesensitive>
76 class ScriptDictImpl final : public ScriptDictBase {
77 public:
78  typedef typename TDict::const_iterator ConstIterator;
79 
80  ScriptDictImpl() {}
81 
82  bool IsCaseSensitive() const override {
83  return is_casesensitive;
84  }
85  bool IsSorted() const override {
86  return is_sorted;
87  }
88 
89  void Clear() override {
90  for (auto it = _dic.begin(); it != _dic.end(); ++it)
91  DeleteItem(it);
92  _dic.clear();
93  }
94  bool Contains(const char *key) override {
95 #ifdef AGS_PLATFORM_SCUMMVM
96  return _dic.find(String::Wrapper(key)) != _dic.end();
97 #else
98  return _dic.count(String::Wrapper(key)) != 0;
99 #endif
100  }
101  const char *Get(const char *key) override {
102  auto it = _dic.find(String::Wrapper(key));
103  if (it == _dic.end()) return nullptr;
104  return it->_value.GetCStr();
105  }
106  bool Remove(const char *key) override {
107  auto it = _dic.find(String::Wrapper(key));
108  if (it == _dic.end()) return false;
109  DeleteItem(it);
110  _dic.erase(it);
111  return true;
112  }
113  bool Set(const char *key, const char *value) override {
114  if (!key)
115  return false;
116  if (!value) {
117  // Remove keys with null value
118  Remove(key);
119  return true;
120  }
121 
122  return TryAddItem(String(key), String(value));
123  }
124  int GetItemCount() override {
125  return _dic.size();
126  }
127  void GetKeys(std::vector<const char *> &buf) const override {
128  for (auto it = _dic.begin(); it != _dic.end(); ++it)
129  buf.push_back(it->_key.GetCStr());
130  }
131  void GetValues(std::vector<const char *> &buf) const override {
132  for (auto it = _dic.begin(); it != _dic.end(); ++it)
133  buf.push_back(it->_value.GetCStr());
134  }
135 
136 private:
137  bool TryAddItem(const String &key, const String &value) {
138  _dic[key] = value;
139  return true;
140  }
141  void DeleteItem(ConstIterator /*it*/) { /* do nothing */ }
142 
143  size_t CalcSerializeSize() override {
144  // 2 class properties + item count
145  size_t total_sz = sizeof(int32_t) * 3;
146  // (int32 + string buffer) per item
147  for (auto it = _dic.begin(); it != _dic.end(); ++it) {
148  total_sz += sizeof(int32_t) + it->_key.GetLength();
149  total_sz += sizeof(int32_t) + it->_value.GetLength();
150  }
151  return total_sz;
152  }
153 
154  void SerializeContainer(AGS::Shared::Stream *out) override
155  {
156  out->WriteInt32((int)_dic.size());
157  for (auto it = _dic.begin(); it != _dic.end(); ++it)
158  {
159  out->WriteInt32((int)it->_key.GetLength());
160  out->Write(it->_key.GetCStr(), it->_key.GetLength());
161  out->WriteInt32((int)it->_value.GetLength());
162  out->Write(it->_value.GetCStr(), it->_value.GetLength());
163  }
164  }
165 
166  void UnserializeContainer(AGS::Shared::Stream *in) override {
167  size_t item_count = in->ReadInt32();
168  for (size_t i = 0; i < item_count; ++i) {
169  size_t key_len = in->ReadInt32();
170  String key = String::FromStreamCount(in, key_len);
171  size_t value_len = in->ReadInt32();
172  if (value_len != (size_t)-1) // do not restore keys with null value (old format)
173  {
174  String value = String::FromStreamCount(in, value_len);
175  TryAddItem(key, value);
176  }
177  }
178  }
179 
180  TDict _dic;
181 };
182 
187 
188 } // namespace AGS3
189 
190 #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:31
Definition: string.h:62
Definition: script_dict.h:76
Definition: stream.h:52
Definition: ags.h:40