OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4ValueMap.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 #include "C4Include.h"
18 #include "script/C4ValueMap.h"
19 
20 #include "script/C4Value.h"
21 
22 // *** C4ValueMapData ***
23 
25  : pData(0), pNames(0), bTempNameList(false), pNext(0)
26 {
27 
28 }
29 
31  : pData(0), pNames(0), bTempNameList(false), pNext(0)
32 {
33  SetNameList(DataToCopy.pNames);
34  if (pNames) for (int32_t i = 0; i < pNames->iSize; i++)
35  pData[i].Set(DataToCopy.pData[i]);
36 }
37 
39 {
40  SetNameList(DataToCopy.pNames);
41  if (pNames) for (int32_t i = 0; i < pNames->iSize; i++)
42  pData[i].Set(DataToCopy.pData[i]);
43  return *this;
44 }
45 
47 {
48  if (pNames != Data.pNames) return false;
49  if (pNames)
50  for (int i = 0; i < pNames->iSize; i++)
51  if (pData[i] != Data.pData[i])
52  return false;
53  return true;
54 }
55 
57 {
58  Reset();
59 }
60 
62 {
63  // unreg from name list (if using one)
64  if (pNames) UnRegister();
65  pNames = 0;
66  // free data
67  delete[] pData;
68  pData = 0;
69 }
70 
72 {
73  if (pNames)
74  // Realloc list (will destroy all data)
75  ReAllocList();
76  else
77  {
78  delete[] pData;
79  pData = 0;
80  }
81 }
82 
84 {
85  if (pNames == pnNames) return;
86  if (pNames)
87  {
88  // save name array from old name list
89  char **pOldNames = pNames->pNames;
90  int32_t iOldSize = pNames->iSize;
91 
92  // unreg from old name list
93  // (manually, because Data::UnRegister() would destroy content)
94  C4ValueMapNames *pNames = this->pNames;
95 
96  pNames->UnRegister(this);
97 
98  // register at new name list
99  pnNames->Register(this);
100 
101  // call OnNameListChanged to copy data and realloc data array
102  OnNameListChanged(const_cast<const char **>(pOldNames), iOldSize);
103 
104  // delete old names list, if it is temporary
105  if (bTempNameList)
106  delete pNames;
107  bTempNameList = false;
108 
109  // ok
110  }
111  else
112  {
113  // simply register...
114  Register(pnNames);
115  }
116 }
117 
118 void C4ValueMapData::Register(C4ValueMapNames *pnNames)
119 {
120  // UnReg from old?
121  if (pNames) UnRegister();
122 
123  if (pnNames) pnNames->Register(this);
124  pNames = pnNames;
125 
126  // alloc data array
127  ReAllocList();
128 }
129 
130 
131 void C4ValueMapData::UnRegister()
132 {
133  if (!pNames) return;
134 
135  // safe pointer
136  C4ValueMapNames *pNames = this->pNames;
137 
138  // unreg
139  pNames->UnRegister(this);
140 
141  // delete name list (if it is temporary)
142  if (bTempNameList)
143  delete pNames;
144  bTempNameList = false;
145 
146  // delete data array
147  delete[] pData;
148  pData = 0;
149 }
150 
152 {
153  // create new list
154  C4ValueMapNames *pTempNames = new C4ValueMapNames();
155 
156  // register (this func will unreg if necessary, too)
157  Register(pTempNames);
158 
159  // error?
160  if (pNames != pTempNames)
161  {
162  delete pTempNames;
163  return 0;
164  }
165 
166  // set flag
167  bTempNameList = true;
168 
169  return pTempNames;
170 }
171 
172 void C4ValueMapData::ReAllocList()
173 {
174  if (!pNames)
175  {
176  Reset();
177  return;
178  }
179 
180  // delete old array
181  delete[] pData;
182 
183  // create new one
184  pData = new C4Value [pNames->iSize] ();
185 
186  // ok...
187 }
188 
189 void C4ValueMapData::OnNameListChanged(const char **pOldNames, int32_t iOldSize)
190 {
191  if (!pNames)
192  {
193  Reset();
194  return;
195  }
196 
197  // this function does not use ReAllocList because the old values
198  // have to be hold.
199 
200  // save pointer on old data
201  C4Value *pOldData = pData;
202 
203  // create new data list
204  pData = new C4Value [pNames->iSize] ();
205 
206  // (try to) copy data
207  int32_t i, j;
208  for (i = 0; i < iOldSize; i++)
209  {
210  if (i < pNames->iSize && SEqual(pNames->pNames[i], pOldNames[i]))
211  {
212  pData[i] = pOldData[i];
213  }
214  else for (j = 0; j < pNames->iSize; j++)
215  {
216  if (SEqual(pNames->pNames[j], pOldNames[i]))
217  {
218  pData[j] = pOldData[i];
219  break;
220  }
221  }
222  }
223  // delete old data array
224  delete[] pOldData;
225 }
226 
228 {
229  assert(pNames);
230  assert(iNr < pNames->iSize);
231  assert(iNr >= 0);
232  // the list is nothing without name list...
233  if (!pNames) return 0;
234 
235  if (iNr >= pNames->iSize) return 0;
236 
237  return &pData[iNr];
238 }
239 
240 C4Value *C4ValueMapData::GetItem(const char *strName)
241 {
242  assert(pNames);
243  if (!pNames) return 0;
244 
245  int32_t iNr = pNames->GetItemNr(strName);
246  assert(iNr != -1);
247 
248  if (iNr == -1) return 0;
249 
250  return &pData[iNr];
251 }
252 
254 {
255  if (!pNames) return 0;
256  return pNames->iSize;
257 }
258 
260 {
261  if (!pNames) return;
262  for (int32_t i = 0; i < pNames->iSize; i++)
263  pData[i].Denumerate(numbers);
264 }
265 
267 {
268  bool deserializing = pComp->isDeserializer();
269  C4ValueMapNames *pOldNames = pNames;
270  if (deserializing) Reset();
271  // Compile item count
272  int32_t iValueCnt;
273  if (!deserializing) iValueCnt = pNames ? pNames->iSize : 0;
274  pComp->Value(mkDefaultAdapt(iValueCnt, 0));
275  // nuthing 2do for no items
276  if (!iValueCnt) return;
277  // Separator (';')
279  // Data
280  char **ppNames = !deserializing ? pNames->pNames : new char * [iValueCnt];
281  if (deserializing) for (int32_t i = 0; i < iValueCnt; i++) ppNames[i] = 0;
282  C4Value *pValues = !deserializing ? pData : new C4Value [iValueCnt];
283  // Compile
284  try
285  {
286  for (int32_t i = 0; i < iValueCnt; i++)
287  {
288  // Separate
289  if (i) pComp->Separator();
290  // Name
291  StdStrBuf Name;
292  if (!deserializing) Name.Ref(ppNames[i]);
293  pComp->Value(mkParAdapt(Name, StdCompiler::RCT_Idtf));
294  if (deserializing) ppNames[i] = Name.GrabPointer();
295  // Separator ('=')
297  // Value
298  pComp->Value(mkParAdapt(pValues[i], numbers));
299  }
300  }
301  catch (...)
302  {
303  // make sure no mem is leaked on compiler error in name list
304  if (deserializing)
305  {
306  for (int32_t i = 0; i < iValueCnt; i++) if (ppNames[i]) free(ppNames[i]);
307  delete [] ppNames;
308  delete [] pValues;
309  }
310  throw;
311  }
312  // Set
313  if (deserializing)
314  {
315  // Set
317  pNames->SetNameArray(const_cast<const char **>(ppNames), iValueCnt);
318  for (int32_t i = 0; i < iValueCnt; i++) free(ppNames[i]);
319  delete [] ppNames; delete [] pData;
320  pData = pValues;
321  // Assign old name list
322  if (pOldNames) SetNameList(pOldNames);
323  }
324 }
325 
326 // *** C4ValueMapNames ***
327 
329  : pNames(0), iSize(0), pFirst(0)
330 {
331 
332 }
333 
335  : pNames(0), iSize(0), pFirst(0)
336 {
337  ChangeNameList(const_cast<const char **>(NamesToCopy.pNames), NamesToCopy.iSize);
338 }
339 
341 {
342  ChangeNameList(const_cast<const char **>(NamesToCopy.pNames), NamesToCopy.iSize);
343  return *this;
344 }
345 
347 {
348  Reset();
349 }
350 
352 {
353  // unreg all data lists
354  while (pFirst) UnRegister(pFirst);
355  // free name list
356  for (int32_t i = 0; i < iSize; i++)
357  delete[] pNames[i];
358  delete[] pNames;
359  pNames = nullptr;
360  iSize = 0;
361 }
362 
363 void C4ValueMapNames::Register(C4ValueMapData *pData)
364 {
365  // add to begin of list
366  pData->pNext = pFirst;
367  pFirst = pData;
368  // set name list
369  pData->pNames = this;
370 }
371 
372 void C4ValueMapNames::UnRegister(C4ValueMapData *pData)
373 {
374  // find in list
375  C4ValueMapData *pAktData = pFirst, *pLastData = 0;
376  while (pAktData && pAktData != pData)
377  {
378  pLastData = pAktData;
379  pAktData = pAktData->pNext;
380  }
381 
382  if (!pAktData)
383  // isn't registred here...
384  return;
385 
386  // unreg
387  if (pLastData)
388  pLastData->pNext = pData->pNext;
389  else
390  pFirst = pData->pNext;
391  pData->pNext = 0;
392 
393  pData->pNames = 0;
394 }
395 
396 void C4ValueMapNames::ChangeNameList(const char **pnNames, int32_t nSize)
397 {
398  // safe old name list
399  char **pOldNames = pNames;
400  int32_t iOldSize = iSize;
401 
402 
403  // create new lists
404  pNames = new char *[nSize];
405 
406  // copy names
407  int32_t i;
408  for (i = 0; i < nSize; i++)
409  {
410  pNames[i] = new char [SLen(pnNames[i]) + 1];
411  SCopy(pnNames[i], pNames[i], SLen(pnNames[i]) + 1);
412  }
413 
414  // set new size
415  iSize = nSize;
416 
417  // call OnNameListChanged list for all "child" lists
418  C4ValueMapData *pAktData = pFirst;
419  while (pAktData)
420  {
421  pAktData->OnNameListChanged(const_cast<const char **>(pOldNames), iOldSize);
422  pAktData = pAktData->pNext;
423  }
424 
425  // delete old list
426  for (i = 0; i < iOldSize; i++)
427  delete[] pOldNames[i];
428  delete[] pOldNames;
429 
430  // ok.
431 }
432 
433 void C4ValueMapNames::SetNameArray(const char **pnNames, int32_t nSize)
434 {
435  // simply pass it through...
436  ChangeNameList(pnNames, nSize);
437 }
438 
439 int32_t C4ValueMapNames::AddName(const char *pnName)
440 {
441  // name already existing?
442  int32_t iNr;
443  if ((iNr=GetItemNr(pnName)) != -1)
444  return iNr;
445 
446  // create new dummy lists
447  const char **pDummyNames = new const char *[iSize + 1];
448 
449  // copy all data from old list
450  // (danger! if ChangeNameList would now delete them before
451  // creating the new list, this would cause cruel errors...)
452  int32_t i;
453  for (i = 0; i < iSize; i++)
454  {
455  pDummyNames[i] = pNames[i];
456  }
457  pDummyNames[i] = pnName;
458 
459  // change list
460  ChangeNameList(pDummyNames, iSize + 1);
461 
462  // delete dummy arrays
463  delete[] pDummyNames;
464 
465  // return index to new element (simply last element)
466  return iSize-1;
467 }
468 
469 int32_t C4ValueMapNames::GetItemNr(const char *strName) const
470 {
471  for (int32_t i = 0; i < iSize; i++)
472  if (SEqual(pNames[i], strName))
473  return i;
474  return -1;
475 }
C4Value * GetItem(const char *strName)
Definition: C4ValueMap.cpp:240
virtual bool Separator(Sep eSep=SEP_SEP)
Definition: StdCompiler.h:129
bool bTempNameList
Definition: C4ValueMap.h:48
char * GrabPointer()
Definition: StdBuf.h:467
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
Definition: Standard.cpp:122
friend class C4ValueMapNames
Definition: C4ValueMap.h:29
virtual ~C4ValueMapNames()
Definition: C4ValueMap.cpp:346
void Denumerate(C4ValueNumbers *)
Definition: C4ValueMap.cpp:259
size_t SLen(const char *sptr)
Definition: Standard.h:78
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
int32_t AddName(const char *pnName)
Definition: C4ValueMap.cpp:439
void SetNameList(C4ValueMapNames *pnNames)
Definition: C4ValueMap.cpp:83
void ResetContent()
Definition: C4ValueMap.cpp:71
bool operator==(const C4ValueMapData &Data) const
Definition: C4ValueMap.cpp:46
void SetNameArray(const char **pnNames, int32_t nSize)
Definition: C4ValueMap.cpp:433
virtual ~C4ValueMapData()
Definition: C4ValueMap.cpp:56
C4ValueMapNames * pNames
Definition: C4ValueMap.h:44
void Value(const T &rStruct)
Definition: StdCompiler.h:171
C4ValueMapData & operator=(const C4ValueMapData &DataToCopy)
Definition: C4ValueMap.cpp:38
virtual bool isDeserializer()
Definition: StdCompiler.h:63
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:469
void Ref(const char *pnData)
Definition: StdBuf.h:463
C4ValueMapNames * CreateTempNameList()
Definition: C4ValueMap.cpp:151
int32_t GetAnzItems()
Definition: C4ValueMap.cpp:253
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:456
C4ValueMapNames & operator=(const C4ValueMapNames &NamesToCopy)
Definition: C4ValueMap.cpp:340
StdDefaultAdapt< T, D > mkDefaultAdapt(T &&rValue, const D &rDefault)
Definition: StdAdaptors.h:65
char ** pNames
Definition: C4ValueMap.h:106
int iSize
Definition: TstC4NetIO.cpp:35
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *)
Definition: C4ValueMap.cpp:266
C4Value * pData
Definition: C4ValueMap.h:41