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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 //=============================================================================
24 //
25 // Containers script API.
26 //
27 //=============================================================================
28 
29 #include "ags/shared/ac/common.h" // quit
30 #include "ags/engine/ac/string.h"
31 #include "ags/engine/ac/dynobj/cc_dynamic_array.h"
32 #include "ags/engine/ac/dynobj/cc_dynamic_object.h"
33 #include "ags/engine/ac/dynobj/script_dict.h"
34 #include "ags/engine/ac/dynobj/script_set.h"
35 #include "ags/engine/ac/dynobj/script_string.h"
36 #include "ags/engine/script/script_api.h"
37 #include "ags/engine/script/script_runtime.h"
38 #include "ags/shared/util/bbop.h"
39 #include "ags/globals.h"
40 
41 namespace AGS3 {
42 
43 //=============================================================================
44 //
45 // Dictionary of strings script API.
46 //
47 //=============================================================================
48 
Dict_CreateImpl(bool sorted,bool case_sensitive)49 ScriptDictBase *Dict_CreateImpl(bool sorted, bool case_sensitive) {
50 	ScriptDictBase *dic;
51 	if (sorted) {
52 		if (case_sensitive)
53 			dic = new ScriptDict();
54 		else
55 			dic = new ScriptDictCI();
56 	} else {
57 		if (case_sensitive)
58 			dic = new ScriptHashDict();
59 		else
60 			dic = new ScriptHashDictCI();
61 	}
62 	return dic;
63 }
64 
Dict_Create(bool sorted,bool case_sensitive)65 ScriptDictBase *Dict_Create(bool sorted, bool case_sensitive) {
66 	ScriptDictBase *dic = Dict_CreateImpl(sorted, case_sensitive);
67 	ccRegisterManagedObject(dic, dic);
68 	return dic;
69 }
70 
71 // TODO: we need memory streams
Dict_Unserialize(int index,const char * serializedData,int dataSize)72 ScriptDictBase *Dict_Unserialize(int index, const char *serializedData, int dataSize) {
73 	if (dataSize < (int)sizeof(int32_t) * 2)
74 		quit("Dict_Unserialize: not enough data.");
75 	const char *ptr = serializedData;
76 	const int sorted = BBOp::Int32FromLE(*((const int *)ptr));
77 	ptr += sizeof(int32_t);
78 	const int cs = BBOp::Int32FromLE(*((const int *)ptr));
79 	ptr += sizeof(int32_t);
80 	ScriptDictBase *dic = Dict_CreateImpl(sorted != 0, cs != 0);
81 	dic->Unserialize(index, ptr, dataSize -= sizeof(int32_t) * 2);
82 	return dic;
83 }
84 
Dict_Clear(ScriptDictBase * dic)85 void Dict_Clear(ScriptDictBase *dic) {
86 	dic->Clear();
87 }
88 
Dict_Contains(ScriptDictBase * dic,const char * key)89 bool Dict_Contains(ScriptDictBase *dic, const char *key) {
90 	return dic->Contains(key);
91 }
92 
Dict_Get(ScriptDictBase * dic,const char * key)93 const char *Dict_Get(ScriptDictBase *dic, const char *key) {
94 	auto *str = dic->Get(key);
95 	return str ? CreateNewScriptString(str) : nullptr;
96 }
97 
Dict_Remove(ScriptDictBase * dic,const char * key)98 bool Dict_Remove(ScriptDictBase *dic, const char *key) {
99 	return dic->Remove(key);
100 }
101 
Dict_Set(ScriptDictBase * dic,const char * key,const char * value)102 bool Dict_Set(ScriptDictBase *dic, const char *key, const char *value) {
103 	return dic->Set(key, value);
104 }
105 
Dict_GetCompareStyle(ScriptDictBase * dic)106 int Dict_GetCompareStyle(ScriptDictBase *dic) {
107 	return dic->IsCaseSensitive() ? 1 : 0;
108 }
109 
Dict_GetSortStyle(ScriptDictBase * dic)110 int Dict_GetSortStyle(ScriptDictBase *dic) {
111 	return dic->IsSorted() ? 1 : 0;
112 }
113 
Dict_GetItemCount(ScriptDictBase * dic)114 int Dict_GetItemCount(ScriptDictBase *dic) {
115 	return dic->GetItemCount();
116 }
117 
Dict_GetKeysAsArray(ScriptDictBase * dic)118 void *Dict_GetKeysAsArray(ScriptDictBase *dic) {
119 	std::vector<const char *> items;
120 	dic->GetKeys(items);
121 	if (items.size() == 0)
122 		return nullptr;
123 	DynObjectRef arr = DynamicArrayHelpers::CreateStringArray(items);
124 	return arr.second;
125 }
126 
Dict_GetValuesAsArray(ScriptDictBase * dic)127 void *Dict_GetValuesAsArray(ScriptDictBase *dic) {
128 	std::vector<const char *> items;
129 	dic->GetValues(items);
130 	if (items.size() == 0)
131 		return nullptr;
132 	DynObjectRef arr = DynamicArrayHelpers::CreateStringArray(items);
133 	return arr.second;
134 }
135 
Sc_Dict_Create(const RuntimeScriptValue * params,int32_t param_count)136 RuntimeScriptValue Sc_Dict_Create(const RuntimeScriptValue *params, int32_t param_count) {
137 	API_SCALL_OBJAUTO_PBOOL2(ScriptDictBase, Dict_Create);
138 }
139 
Sc_Dict_Clear(void * self,const RuntimeScriptValue * params,int32_t param_count)140 RuntimeScriptValue Sc_Dict_Clear(void *self, const RuntimeScriptValue *params, int32_t param_count) {
141 	API_OBJCALL_VOID(ScriptDictBase, Dict_Clear);
142 }
143 
Sc_Dict_Contains(void * self,const RuntimeScriptValue * params,int32_t param_count)144 RuntimeScriptValue Sc_Dict_Contains(void *self, const RuntimeScriptValue *params, int32_t param_count) {
145 	API_OBJCALL_BOOL_POBJ(ScriptDictBase, Dict_Contains, const char);
146 }
147 
Sc_Dict_Get(void * self,const RuntimeScriptValue * params,int32_t param_count)148 RuntimeScriptValue Sc_Dict_Get(void *self, const RuntimeScriptValue *params, int32_t param_count) {
149 	API_CONST_OBJCALL_OBJ_POBJ(ScriptDictBase, const char, _GP(myScriptStringImpl), Dict_Get, const char);
150 }
151 
Sc_Dict_Remove(void * self,const RuntimeScriptValue * params,int32_t param_count)152 RuntimeScriptValue Sc_Dict_Remove(void *self, const RuntimeScriptValue *params, int32_t param_count) {
153 	API_OBJCALL_BOOL_POBJ(ScriptDictBase, Dict_Remove, const char);
154 }
155 
Sc_Dict_Set(void * self,const RuntimeScriptValue * params,int32_t param_count)156 RuntimeScriptValue Sc_Dict_Set(void *self, const RuntimeScriptValue *params, int32_t param_count) {
157 	API_OBJCALL_BOOL_POBJ2(ScriptDictBase, Dict_Set, const char, const char);
158 }
159 
Sc_Dict_GetCompareStyle(void * self,const RuntimeScriptValue * params,int32_t param_count)160 RuntimeScriptValue Sc_Dict_GetCompareStyle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
161 	API_OBJCALL_INT(ScriptDictBase, Dict_GetCompareStyle);
162 }
163 
Sc_Dict_GetSortStyle(void * self,const RuntimeScriptValue * params,int32_t param_count)164 RuntimeScriptValue Sc_Dict_GetSortStyle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
165 	API_OBJCALL_INT(ScriptDictBase, Dict_GetSortStyle);
166 }
167 
Sc_Dict_GetItemCount(void * self,const RuntimeScriptValue * params,int32_t param_count)168 RuntimeScriptValue Sc_Dict_GetItemCount(void *self, const RuntimeScriptValue *params, int32_t param_count) {
169 	API_OBJCALL_INT(ScriptDictBase, Dict_GetItemCount);
170 }
171 
Sc_Dict_GetKeysAsArray(void * self,const RuntimeScriptValue * params,int32_t param_count)172 RuntimeScriptValue Sc_Dict_GetKeysAsArray(void *self, const RuntimeScriptValue *params, int32_t param_count) {
173 	API_OBJCALL_OBJ(ScriptDictBase, void, _GP(globalDynamicArray), Dict_GetKeysAsArray);
174 }
175 
Sc_Dict_GetValuesAsArray(void * self,const RuntimeScriptValue * params,int32_t param_count)176 RuntimeScriptValue Sc_Dict_GetValuesAsArray(void *self, const RuntimeScriptValue *params, int32_t param_count) {
177 	API_OBJCALL_OBJ(ScriptDictBase, void, _GP(globalDynamicArray), Dict_GetValuesAsArray);
178 }
179 
180 //=============================================================================
181 //
182 // Set of strings script API.
183 //
184 //=============================================================================
185 
Set_CreateImpl(bool sorted,bool case_sensitive)186 ScriptSetBase *Set_CreateImpl(bool sorted, bool case_sensitive) {
187 	ScriptSetBase *set;
188 	if (sorted) {
189 		if (case_sensitive)
190 			set = new ScriptSet();
191 		else
192 			set = new ScriptSetCI();
193 	} else {
194 		if (case_sensitive)
195 			set = new ScriptHashSet();
196 		else
197 			set = new ScriptHashSetCI();
198 	}
199 	return set;
200 }
201 
Set_Create(bool sorted,bool case_sensitive)202 ScriptSetBase *Set_Create(bool sorted, bool case_sensitive) {
203 	ScriptSetBase *set = Set_CreateImpl(sorted, case_sensitive);
204 	ccRegisterManagedObject(set, set);
205 	return set;
206 }
207 
208 // TODO: we need memory streams
Set_Unserialize(int index,const char * serializedData,int dataSize)209 ScriptSetBase *Set_Unserialize(int index, const char *serializedData, int dataSize) {
210 	if (dataSize < (int)sizeof(int32_t) * 2)
211 		quit("Set_Unserialize: not enough data.");
212 	const char *ptr = serializedData;
213 	const int sorted = BBOp::Int32FromLE(*((const int *)ptr));
214 	ptr += sizeof(int32_t);
215 	const int cs = BBOp::Int32FromLE(*((const int *)ptr));
216 	ptr += sizeof(int32_t);
217 	ScriptSetBase *set = Set_CreateImpl(sorted != 0, cs != 0);
218 	set->Unserialize(index, ptr, dataSize -= sizeof(int32_t) * 2);
219 	return set;
220 }
221 
Set_Add(ScriptSetBase * set,const char * item)222 bool Set_Add(ScriptSetBase *set, const char *item) {
223 	return set->Add(item);
224 }
225 
Set_Clear(ScriptSetBase * set)226 void Set_Clear(ScriptSetBase *set) {
227 	set->Clear();
228 }
229 
Set_Contains(ScriptSetBase * set,const char * item)230 bool Set_Contains(ScriptSetBase *set, const char *item) {
231 	return set->Contains(item);
232 }
233 
Set_Remove(ScriptSetBase * set,const char * item)234 bool Set_Remove(ScriptSetBase *set, const char *item) {
235 	return set->Remove(item);
236 }
237 
Set_GetCompareStyle(ScriptSetBase * set)238 int Set_GetCompareStyle(ScriptSetBase *set) {
239 	return set->IsCaseSensitive() ? 1 : 0;
240 }
241 
Set_GetSortStyle(ScriptSetBase * set)242 int Set_GetSortStyle(ScriptSetBase *set) {
243 	return set->IsSorted() ? 1 : 0;
244 }
245 
Set_GetItemCount(ScriptSetBase * set)246 int Set_GetItemCount(ScriptSetBase *set) {
247 	return set->GetItemCount();
248 }
249 
Set_GetItemsAsArray(ScriptSetBase * set)250 void *Set_GetItemsAsArray(ScriptSetBase *set) {
251 	std::vector<const char *> items;
252 	set->GetItems(items);
253 	if (items.size() == 0)
254 		return nullptr;
255 	DynObjectRef arr = DynamicArrayHelpers::CreateStringArray(items);
256 	return arr.second;
257 }
258 
Sc_Set_Create(const RuntimeScriptValue * params,int32_t param_count)259 RuntimeScriptValue Sc_Set_Create(const RuntimeScriptValue *params, int32_t param_count) {
260 	API_SCALL_OBJAUTO_PBOOL2(ScriptSetBase, Set_Create);
261 }
262 
Sc_Set_Add(void * self,const RuntimeScriptValue * params,int32_t param_count)263 RuntimeScriptValue Sc_Set_Add(void *self, const RuntimeScriptValue *params, int32_t param_count) {
264 	API_OBJCALL_BOOL_POBJ(ScriptSetBase, Set_Add, const char);
265 }
266 
Sc_Set_Clear(void * self,const RuntimeScriptValue * params,int32_t param_count)267 RuntimeScriptValue Sc_Set_Clear(void *self, const RuntimeScriptValue *params, int32_t param_count) {
268 	API_OBJCALL_VOID(ScriptSetBase, Set_Clear);
269 }
270 
Sc_Set_Contains(void * self,const RuntimeScriptValue * params,int32_t param_count)271 RuntimeScriptValue Sc_Set_Contains(void *self, const RuntimeScriptValue *params, int32_t param_count) {
272 	API_OBJCALL_BOOL_POBJ(ScriptSetBase, Set_Contains, const char);
273 }
274 
Sc_Set_Remove(void * self,const RuntimeScriptValue * params,int32_t param_count)275 RuntimeScriptValue Sc_Set_Remove(void *self, const RuntimeScriptValue *params, int32_t param_count) {
276 	API_OBJCALL_BOOL_POBJ(ScriptSetBase, Set_Remove, const char);
277 }
278 
Sc_Set_GetCompareStyle(void * self,const RuntimeScriptValue * params,int32_t param_count)279 RuntimeScriptValue Sc_Set_GetCompareStyle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
280 	API_OBJCALL_INT(ScriptSetBase, Set_GetCompareStyle);
281 }
282 
Sc_Set_GetSortStyle(void * self,const RuntimeScriptValue * params,int32_t param_count)283 RuntimeScriptValue Sc_Set_GetSortStyle(void *self, const RuntimeScriptValue *params, int32_t param_count) {
284 	API_OBJCALL_INT(ScriptSetBase, Set_GetSortStyle);
285 }
286 
Sc_Set_GetItemCount(void * self,const RuntimeScriptValue * params,int32_t param_count)287 RuntimeScriptValue Sc_Set_GetItemCount(void *self, const RuntimeScriptValue *params, int32_t param_count) {
288 	API_OBJCALL_INT(ScriptSetBase, Set_GetItemCount);
289 }
290 
Sc_Set_GetItemAsArray(void * self,const RuntimeScriptValue * params,int32_t param_count)291 RuntimeScriptValue Sc_Set_GetItemAsArray(void *self, const RuntimeScriptValue *params, int32_t param_count) {
292 	API_OBJCALL_OBJ(ScriptSetBase, void, _GP(globalDynamicArray), Set_GetItemsAsArray);
293 }
294 
295 
296 
RegisterContainerAPI()297 void RegisterContainerAPI() {
298 	ccAddExternalStaticFunction("Dictionary::Create", Sc_Dict_Create);
299 	ccAddExternalObjectFunction("Dictionary::Clear", Sc_Dict_Clear);
300 	ccAddExternalObjectFunction("Dictionary::Contains", Sc_Dict_Contains);
301 	ccAddExternalObjectFunction("Dictionary::Get", Sc_Dict_Get);
302 	ccAddExternalObjectFunction("Dictionary::Remove", Sc_Dict_Remove);
303 	ccAddExternalObjectFunction("Dictionary::Set", Sc_Dict_Set);
304 	ccAddExternalObjectFunction("Dictionary::get_CompareStyle", Sc_Dict_GetCompareStyle);
305 	ccAddExternalObjectFunction("Dictionary::get_SortStyle", Sc_Dict_GetSortStyle);
306 	ccAddExternalObjectFunction("Dictionary::get_ItemCount", Sc_Dict_GetItemCount);
307 	ccAddExternalObjectFunction("Dictionary::GetKeysAsArray", Sc_Dict_GetKeysAsArray);
308 	ccAddExternalObjectFunction("Dictionary::GetValuesAsArray", Sc_Dict_GetValuesAsArray);
309 
310 	ccAddExternalStaticFunction("Set::Create", Sc_Set_Create);
311 	ccAddExternalObjectFunction("Set::Add", Sc_Set_Add);
312 	ccAddExternalObjectFunction("Set::Clear", Sc_Set_Clear);
313 	ccAddExternalObjectFunction("Set::Contains", Sc_Set_Contains);
314 	ccAddExternalObjectFunction("Set::Remove", Sc_Set_Remove);
315 	ccAddExternalObjectFunction("Set::get_CompareStyle", Sc_Set_GetCompareStyle);
316 	ccAddExternalObjectFunction("Set::get_SortStyle", Sc_Set_GetSortStyle);
317 	ccAddExternalObjectFunction("Set::get_ItemCount", Sc_Set_GetItemCount);
318 	ccAddExternalObjectFunction("Set::GetItemsAsArray", Sc_Set_GetItemAsArray);
319 }
320 
321 } // namespace AGS3
322