選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

155 行
3.0 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #include <lol/engine-internal.h>
  11. #include <cstring>
  12. #include <cstdlib>
  13. #if defined _WIN32 || defined _XBOX
  14. # define strcasecmp _stricmp
  15. #endif
  16. namespace lol
  17. {
  18. /*
  19. * Dict implementation class
  20. */
  21. class DictData
  22. {
  23. friend class Dict;
  24. public:
  25. DictData() :
  26. nentities(0)
  27. {
  28. /* Nothing to do */
  29. }
  30. ~DictData()
  31. {
  32. #if !LOL_BUILD_RELEASE
  33. if (nentities)
  34. Log::Error("still %i entities in dict\n", nentities);
  35. #endif
  36. }
  37. private:
  38. array<Entity *> m_entities;
  39. int nentities;
  40. };
  41. /*
  42. * Public Dict class
  43. */
  44. Dict::Dict()
  45. : data(new DictData())
  46. {
  47. }
  48. Dict::~Dict()
  49. {
  50. delete data;
  51. }
  52. int Dict::MakeSlot(char const *name)
  53. {
  54. int slotid, empty = -1;
  55. /* If the entry is already registered, remember its ID. Look for an
  56. * empty slot at the same time. */
  57. for (slotid = 0; slotid < data->m_entities.Count(); slotid++)
  58. {
  59. Entity *e = data->m_entities[slotid];
  60. if (!e)
  61. {
  62. empty = slotid;
  63. break;
  64. }
  65. else
  66. {
  67. char const *oldname = e->GetName();
  68. if (*oldname == '<')
  69. {
  70. while (*oldname && *oldname != '>')
  71. oldname++;
  72. while (*oldname == '>')
  73. oldname++;
  74. while (*oldname == ' ')
  75. oldname++;
  76. }
  77. if (!strcasecmp(name, oldname))
  78. break;
  79. }
  80. }
  81. /* If this is a new entry, create a new slot for it. */
  82. if (slotid == data->m_entities.Count() || !data->m_entities[slotid])
  83. {
  84. if (slotid == data->m_entities.Count())
  85. {
  86. empty = (int)data->m_entities.Count();
  87. data->m_entities.Push(nullptr);
  88. }
  89. data->m_entities[empty] = nullptr;
  90. slotid = empty;
  91. data->nentities++;
  92. }
  93. else
  94. {
  95. Ticker::Ref(data->m_entities[slotid]);
  96. }
  97. return slotid;
  98. }
  99. void Dict::RemoveSlot(int slotid)
  100. {
  101. if (Ticker::Unref(data->m_entities[slotid]) == 0)
  102. {
  103. data->m_entities[slotid] = nullptr;
  104. data->nentities--;
  105. }
  106. }
  107. void Dict::RemoveSlot(Entity *entity)
  108. {
  109. for (int slotid = 0; slotid < data->m_entities.Count(); slotid++)
  110. if (data->m_entities[slotid] == entity)
  111. {
  112. RemoveSlot(slotid);
  113. return;
  114. }
  115. #if !LOL_BUILD_RELEASE
  116. Log::Error("removing unregistered entity %p (%s)\n",
  117. entity, entity->GetName());
  118. #endif
  119. }
  120. void Dict::SetEntity(int slotid, Entity *entity)
  121. {
  122. Ticker::Ref(entity);
  123. data->m_entities[slotid] = entity;
  124. }
  125. Entity *Dict::GetEntity(int slotid)
  126. {
  127. return data->m_entities[slotid];
  128. }
  129. } /* namespace lol */