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