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 /* string table: holds all strings used by script engine */ 17 18 #ifndef C4STRINGTABLE_H 19 #define C4STRINGTABLE_H 20 21 class C4RefCnt 22 { 23 public: 24 C4RefCnt() = default; 25 virtual ~C4RefCnt() = default; 26 // Add/Remove Reference IncRef()27 void IncRef() { RefCnt++; } DecRef()28 void DecRef() { if (!--RefCnt) delete this; } 29 protected: 30 // Reference counter 31 unsigned int RefCnt{0}; 32 }; 33 34 class C4String: public C4RefCnt 35 { 36 public: 37 unsigned int Hash; 38 private: 39 StdCopyStrBuf Data; // string data 40 41 explicit C4String(StdStrBuf strString); 42 C4String(); 43 void operator=(const char * s); 44 45 friend class C4StringTable; 46 public: 47 ~C4String() override; 48 GetCStr()49 const char * GetCStr() const { return Data.getData(); } GetData()50 StdStrBuf GetData() const { return Data.getRef(); } 51 52 }; 53 54 template <class T> 55 class C4RefCntPointer 56 { 57 public: C4RefCntPointer(T * p)58 C4RefCntPointer(T* p): p(p) { IncRef(); } C4RefCntPointer()59 C4RefCntPointer(): p(nullptr) { } C4RefCntPointer(const C4RefCntPointer<T> & r)60 C4RefCntPointer(const C4RefCntPointer<T> & r) : p(r.p) { IncRef(); } C4RefCntPointer(const C4RefCntPointer<U> & r)61 template <class U> C4RefCntPointer(const C4RefCntPointer<U> & r): p(r.p) { IncRef(); } 62 // Move constructor C4RefCntPointer(C4RefCntPointer<T> && r)63 C4RefCntPointer(C4RefCntPointer<T> &&r) : p(r.p) { r.p = nullptr; } C4RefCntPointer(C4RefCntPointer<U> && r)64 template <class U> C4RefCntPointer(C4RefCntPointer<U> &&r): p(r.p) { r.p = 0; } 65 // Move assignment 66 C4RefCntPointer& operator = (C4RefCntPointer<T> &&r) 67 { 68 if (p != r.p) 69 { 70 DecRef(); 71 p = r.p; 72 r.p = nullptr; 73 } 74 return *this; 75 } 76 template <class U> C4RefCntPointer& operator = (C4RefCntPointer<U> &&r) 77 { 78 if (p != r.p) 79 { 80 DecRef(); 81 p = r.p; 82 r.p = 0; 83 } 84 return *this; 85 } ~C4RefCntPointer()86 ~C4RefCntPointer() { DecRef(); } 87 template <class U> C4RefCntPointer& operator = (U* new_p) 88 { 89 if (p != new_p) 90 { 91 DecRef(); 92 p = new_p; 93 IncRef(); 94 } 95 return *this; 96 } 97 C4RefCntPointer& operator = (const C4RefCntPointer<T>& r) 98 { 99 return *this = r.p; 100 } 101 template <class U> C4RefCntPointer& operator = (const C4RefCntPointer<U>& r) 102 { 103 return *this = r.p; 104 } 105 T& operator * () { return *p; } 106 const T& operator * () const { return *p; } 107 T* operator -> () { return p; } 108 const T* operator -> () const { return p; } 109 operator T * () { return p; } 110 operator const T * () const { return p; } Get()111 T *Get() const { return p; } 112 private: IncRef()113 void IncRef() { if (p) p->IncRef(); } DecRef()114 void DecRef() { if (p) p->DecRef(); } 115 T * p; 116 }; 117 118 template<typename T> class C4Set 119 { 120 unsigned int Capacity{2}; 121 unsigned int Size{0}; 122 T * Table; GetPlaceFor(T const & e)123 T * GetPlaceFor(T const & e) 124 { 125 unsigned int h = Hash(e); 126 T * p = &Table[h % Capacity]; 127 while (*p && !Equals(*p, e)) 128 { 129 p = &Table[++h % Capacity]; 130 } 131 return p; 132 } AddInternal(T const & e)133 T * AddInternal(T const & e) 134 { 135 T * p = GetPlaceFor(e); 136 *p = e; 137 return p; 138 } AddInternal(T && e)139 T * AddInternal(T && e) 140 { 141 T * p = GetPlaceFor(e); 142 *p = std::move(e); 143 return p; 144 } ClearTable()145 void ClearTable() 146 { 147 for (unsigned int i = 0; i < Capacity; ++i) 148 Table[i] = nullptr; 149 } MaintainCapacity()150 void MaintainCapacity() 151 { 152 if (Capacity - Size < std::max(2u, Capacity / 4)) 153 { 154 unsigned int OCapacity = Capacity; 155 Capacity *= 2; 156 T * OTable = Table; 157 Table = new T[Capacity]; 158 ClearTable(); 159 for (unsigned int i = 0; i < OCapacity; ++i) 160 { 161 if (OTable[i]) 162 AddInternal(std::move(OTable[i])); 163 } 164 delete [] OTable; 165 } 166 } 167 public: 168 template<typename H> static unsigned int Hash(const H &); 169 template<typename H> static bool Equals(const T &, const H &); Equals(const T & a,const T & b)170 static bool Equals(const T & a, const T & b) { return a == b; } C4Set()171 C4Set(): Table(new T[Capacity]) 172 { 173 ClearTable(); 174 } ~C4Set()175 ~C4Set() 176 { 177 delete[] Table; 178 } C4Set(const C4Set & b)179 C4Set(const C4Set & b): Capacity(0), Size(0), Table(0) 180 { 181 *this = b; 182 } 183 C4Set & operator = (const C4Set & b) 184 { 185 Capacity = b.Capacity; 186 Size = b.Size; 187 delete[] Table; 188 Table = new T[Capacity]; 189 for (unsigned int i = 0; i < Capacity; ++i) 190 Table[i] = b.Table[i]; 191 return *this; 192 } 193 void CompileFunc(class StdCompiler *pComp, class C4ValueNumbers *); Clear()194 void Clear() 195 { 196 ClearTable(); 197 Size = 0; 198 } Get(H e)199 template<typename H> T & Get(H e) const 200 { 201 unsigned int h = Hash(e); 202 T * r = &Table[h % Capacity]; 203 while (*r && !Equals(*r, e)) 204 { 205 r = &Table[++h % Capacity]; 206 } 207 return *r; 208 } Has(H e)209 template<typename H> bool Has(H e) const 210 { 211 unsigned int h = Hash(e); 212 T * r = &Table[h % Capacity]; 213 while (*r && !Equals(*r, e)) 214 { 215 r = &Table[++h % Capacity]; 216 } 217 return !!*r; 218 } GetSize()219 unsigned int GetSize() const { return Size; } Add(T const & e)220 T * Add(T const & e) 221 { 222 MaintainCapacity(); 223 T * r = AddInternal(e); 224 ++Size; 225 return r; 226 } Add(T && e)227 T * Add(T && e) 228 { 229 MaintainCapacity(); 230 T * r = AddInternal(std::move(e)); 231 ++Size; 232 return r; 233 } Remove(H e)234 template<typename H> void Remove(H e) 235 { 236 unsigned int h = Hash(e); 237 T * r = &Table[h % Capacity]; 238 while (*r && !Equals(*r, e)) 239 { 240 r = &Table[++h % Capacity]; 241 } 242 assert(*r); 243 *r = nullptr; 244 --Size; 245 // Move entries which might have collided with e 246 while (*(r = &Table[++h % Capacity])) 247 { 248 T m = *r; 249 *r = nullptr; 250 AddInternal(std::move(m)); 251 } 252 } First()253 T const * First() const { return Next(Table - 1); } Next(T const * p)254 T const * Next(T const * p) const 255 { 256 while (++p != &Table[Capacity]) 257 { 258 if (*p) return p; 259 } 260 return nullptr; 261 } Swap(C4Set<T> * S2)262 void Swap(C4Set<T> * S2) 263 { 264 unsigned int Capacity2 = S2->Capacity; 265 unsigned int Size2 = S2->Size; 266 T * Table2 = S2->Table; 267 S2->Capacity = Capacity; 268 S2->Size = Size; 269 S2->Table = Table; 270 Capacity = Capacity2; 271 Size = Size2; 272 Table = Table2; 273 } SortFunc(const T * p1,const T * p2)274 static bool SortFunc(const T *p1, const T*p2) 275 { 276 // elements are guarantueed to be non-nullptr 277 return *p1<*p2; 278 } GetSortedListOfElementPointers()279 std::list<const T *> GetSortedListOfElementPointers() const 280 { 281 // return a list of pointers to all elements in this set sorted by the standard less-than operation 282 // of the elements 283 // elements of resulting lists are guarantueed to be non-nullptr 284 // list remains valid as long as this set is not changed 285 std::list<const T *> result; 286 for (const T *p = First(); p; p = Next(p)) result.push_back(p); 287 result.sort(C4Set<T>::SortFunc); 288 return result; 289 } 290 }; 291 292 template<> template<> 293 inline unsigned int C4Set<C4String *>::Hash<const C4String *>(const C4String * const & e) 294 { 295 return e->Hash; 296 } 297 template<> template<> 298 inline unsigned int C4Set<C4String *>::Hash<C4String *>(C4String * const & e) 299 { 300 return e->Hash; 301 } 302 303 enum C4PropertyName 304 { 305 // TODO: documentation comments can be removed 306 // as soon as all properties are documented 307 308 P_Prototype, 309 P_Name, 310 P_Priority, 311 P_Interval, 312 P_CommandTarget, 313 P_Time, 314 P_Construction, 315 P_Destruction, 316 P_Start, 317 P_Stop, 318 P_Timer, 319 P_Effect, 320 P_Damage, 321 P_Collectible, 322 P_Touchable, 323 P_ActMap, 324 P_Attach, 325 P_Visibility, 326 P_Parallaxity, 327 P_LineColors, 328 P_LineAttach, 329 P_PictureTransformation, 330 P_MeshTransformation, 331 P_Procedure, 332 P_Speed, 333 P_Accel, 334 P_Decel, 335 P_Directions, 336 P_FlipDir, 337 P_Length, 338 P_Delay, 339 P_X, 340 P_Y, 341 P_x, 342 P_y, 343 P_Wdt, 344 P_Hgt, 345 P_wdt, 346 P_hgt, 347 P_Vertices, 348 P_Edges, 349 P_LineWidth, 350 P_OffX, 351 P_OffY, 352 P_proplist, 353 P_Proplist, 354 P_FacetBase, 355 P_FacetTopFace, 356 P_FacetTargetStretch, 357 P_NextAction, 358 P_Hold, 359 P_Idle, 360 P_NoOtherAction, 361 P_StartCall, 362 P_EndCall, 363 P_AbortCall, 364 P_PhaseCall, 365 P_Sound, 366 P_ObjectDisabled, 367 P_DigFree, 368 P_InLiquidAction, 369 P_TurnAction, 370 P_Reverse, 371 P_Step, 372 P_MouseDrag, 373 P_MouseDragImage, 374 P_Animation, 375 P_Action, 376 P_BreatheWater, 377 P_CorrosionResist, 378 P_MaxEnergy, 379 P_MaxBreath, 380 P_ThrowSpeed, 381 P_Mode, // unused? 382 P_CausedBy, // unused? 383 P_Blasted, // unused? 384 P_IncineratingObj, // unused? 385 P_Plane, 386 P_BorderBound, 387 P_ContactCalls, 388 P_SolidMaskPlane, 389 P_Tooltip, 390 P_Placement, 391 P_ContainBlast, 392 P_BlastIncinerate, 393 P_ContactIncinerate, 394 P_MaterialIncinerate, 395 P_Global, 396 P_Scenario, 397 P_JumpSpeed, 398 P_BackgroundColor, 399 P_Decoration, 400 P_Symbol, 401 P_Target, 402 P_Std, 403 P_Text, 404 P_GraphicsName, 405 P_ID, 406 P_OnClick, 407 P_OnMouseIn, 408 P_OnMouseOut, 409 P_OnClose, 410 P_Style, 411 P_Player, 412 P_Margin, 413 P_Algo, 414 P_Layer, 415 P_Seed, 416 P_Ratio, 417 P_FixedOffset, 418 P_Op, 419 P_R, 420 P_Scale, 421 P_Amplitude, 422 P_Iterations, 423 P_Empty, 424 P_Open, 425 P_Left, 426 P_Top, 427 P_Right, 428 P_Bottom, 429 P_Filter, 430 P_ForceX, 431 P_ForceY, 432 P_G, 433 P_B, 434 P_Alpha, 435 P_DampingX, 436 P_DampingY, 437 P_Size, 438 P_Rotation, 439 P_BlitMode, 440 P_Phase, 441 P_Stretch, 442 P_CollisionVertex, 443 P_CollisionDensity, 444 P_OnCollision, 445 P_Distance, 446 P_Smoke, 447 P_Source, 448 P_Color, 449 P_EditCursorCommands, 450 P_IsPointContained, 451 P_GetRandomPoint, 452 P_Type, 453 P_Reverb_Density, 454 P_Reverb_Diffusion, 455 P_Reverb_Gain, 456 P_Reverb_GainHF, 457 P_Reverb_Decay_Time, 458 P_Reverb_Decay_HFRatio, 459 P_Reverb_Reflections_Gain, 460 P_Reverb_Reflections_Delay, 461 P_Reverb_Late_Reverb_Gain, 462 P_Reverb_Late_Reverb_Delay, 463 P_Reverb_Air_Absorption_GainHF, 464 P_Reverb_Room_Rolloff_Factor, 465 P_Reverb_Decay_HFLimit, 466 P_Echo_Delay, 467 P_Echo_LRDelay, 468 P_Echo_Damping, 469 P_Echo_Feedback, 470 P_Echo_Spread, 471 P_Equalizer_Low_Gain, 472 P_Equalizer_Low_Cutoff, 473 P_Equalizer_Mid1_Gain, 474 P_Equalizer_Mid1_Center, 475 P_Equalizer_Mid1_Width, 476 P_Equalizer_Mid2_Gain, 477 P_Equalizer_Mid2_Center, 478 P_Equalizer_Mid2_Width, 479 P_Equalizer_High_Gain, 480 P_Equalizer_High_Cutoff, 481 P_LightOffset, 482 P_PlayList, 483 P_MusicBreakMin, 484 P_MusicBreakMax, 485 P_MusicBreakChance, 486 P_MusicMaxPositionMemory, 487 P_InflameLandscape, 488 P_OptionKey, 489 P_ValueKey, 490 P_Value, 491 P_DefaultValueFunction, 492 P_Delegate, 493 P_VertexDelegate, 494 P_EdgeDelegate, 495 P_HorizontalFix, 496 P_VerticalFix, 497 P_StructureFix, 498 P_OnUpdate, 499 P_EditorPropertyChanged, 500 P_Min, 501 P_Max, 502 P_Set, 503 P_SetGlobal, 504 P_SetRoot, 505 P_Options, 506 P_Key, 507 P_AsyncGet, 508 P_Get, 509 P_Relative, 510 P_CanMoveCenter, 511 P_StartFromObject, 512 P_Storage, 513 P_Elements, 514 P_EditOnSelection, 515 P_EditorProps, 516 P_DefaultEditorProp, 517 P_EditorActions, 518 P_CopyDefault, 519 P_Display, 520 P_DefaultValue, 521 P_DefinitionPriority, 522 P_Group, 523 P_Command, 524 P_Select, 525 P_DescendPath, 526 P_EmptyName, 527 P_ShortName, 528 P_EditorHelp, 529 P_Description, 530 P_AllowEditing, 531 P_EditorInitialize, 532 P_EditorPlacementLimit, 533 P_EditorCollection, 534 P_Sorted, 535 P_Uniforms, 536 P_ForceSerialization, 537 P_DrawArrows, 538 P_SCENPAR, 539 P_Translatable, 540 P_Function, 541 P_Translate, 542 // Default Action Procedures 543 DFA_WALK, 544 DFA_FLIGHT, 545 DFA_KNEEL, 546 DFA_SCALE, 547 DFA_HANGLE, 548 DFA_DIG, 549 DFA_SWIM, 550 DFA_THROW, 551 DFA_BRIDGE, 552 DFA_PUSH, 553 DFA_LIFT, 554 DFA_FLOAT, 555 DFA_ATTACH, 556 DFA_CONNECT, 557 DFA_PULL, 558 P_LAST 559 }; 560 561 // There is only one Stringtable 562 class C4StringTable 563 { 564 public: 565 C4StringTable(); 566 virtual ~C4StringTable(); 567 568 C4String *RegString(StdStrBuf String); RegString(const char * s)569 C4String *RegString(const char * s) { return RegString(StdStrBuf(s)); } 570 // Find existing C4String 571 C4String *FindString(const char *strString) const; 572 573 private: 574 C4Set<C4String *> Set; 575 friend class C4String; 576 577 public: 578 // After the set, so these are destroyed with the set still alive 579 C4String P[P_LAST]; 580 }; 581 582 extern C4StringTable Strings; 583 584 #endif 585