2
0

ObjectStreamOut.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #include <Jolt/ObjectStream/ObjectStreamOut.h>
  6. #include <Jolt/ObjectStream/ObjectStreamTextOut.h>
  7. #include <Jolt/ObjectStream/ObjectStreamBinaryOut.h>
  8. #include <Jolt/ObjectStream/TypeDeclarations.h>
  9. JPH_NAMESPACE_BEGIN
  10. ObjectStreamOut::ObjectStreamOut(ostream &inStream) :
  11. mStream(inStream)
  12. {
  13. // Add all primitives to the class set
  14. #define JPH_DECLARE_PRIMITIVE(name) mClassSet.insert(JPH_RTTI(name));
  15. #include <Jolt/ObjectStream/ObjectStreamTypes.h>
  16. }
  17. ObjectStreamOut *ObjectStreamOut::Open(EStreamType inType, ostream &inStream)
  18. {
  19. switch (inType)
  20. {
  21. case EStreamType::Text: return new ObjectStreamTextOut(inStream);
  22. case EStreamType::Binary: return new ObjectStreamBinaryOut(inStream);
  23. default: JPH_ASSERT(false);
  24. }
  25. return nullptr;
  26. }
  27. bool ObjectStreamOut::Write(const void *inObject, const RTTI *inRTTI)
  28. {
  29. // Assign a new identifier to the object and write it
  30. mIdentifierMap.try_emplace(inObject, mNextIdentifier, inRTTI);
  31. mNextIdentifier++;
  32. WriteObject(inObject);
  33. // Write all linked objects
  34. while (!mObjectQueue.empty() && !mStream.fail())
  35. {
  36. const void *linked_object = mObjectQueue.front();
  37. WriteObject(linked_object);
  38. mObjectQueue.pop();
  39. }
  40. return !mStream.fail();
  41. }
  42. void ObjectStreamOut::WriteObject(const void *inObject)
  43. {
  44. // Find object identifier
  45. IdentifierMap::iterator i = mIdentifierMap.find(inObject);
  46. JPH_ASSERT(i != mIdentifierMap.end());
  47. // Write class description and associated descriptions
  48. QueueRTTI(i->second.mRTTI);
  49. while (!mClassQueue.empty() && !mStream.fail())
  50. {
  51. WriteRTTI(mClassQueue.front());
  52. mClassQueue.pop();
  53. }
  54. HintNextItem();
  55. HintNextItem();
  56. // Write object header.
  57. WriteDataType(EOSDataType::Object);
  58. WriteName(i->second.mRTTI->GetName());
  59. WriteIdentifier(i->second.mIdentifier);
  60. // Write attribute data
  61. WriteClassData(i->second.mRTTI, inObject);
  62. }
  63. void ObjectStreamOut::QueueRTTI(const RTTI *inRTTI)
  64. {
  65. ClassSet::const_iterator i = mClassSet.find(inRTTI);
  66. if (i == mClassSet.end())
  67. {
  68. mClassSet.insert(inRTTI);
  69. mClassQueue.push(inRTTI);
  70. }
  71. }
  72. void ObjectStreamOut::WriteRTTI(const RTTI *inRTTI)
  73. {
  74. HintNextItem();
  75. HintNextItem();
  76. // Write class header. E.g. in text mode: "class <name> <attr-count>"
  77. WriteDataType(EOSDataType::Declare);
  78. WriteName(inRTTI->GetName());
  79. WriteCount(inRTTI->GetAttributeCount());
  80. // Write class attribute info
  81. HintIndentUp();
  82. for (int attr_index = 0; attr_index < inRTTI->GetAttributeCount(); ++attr_index)
  83. {
  84. // Get attribute
  85. const SerializableAttribute &attr = inRTTI->GetAttribute(attr_index);
  86. // Write definition of attribute class if undefined
  87. const RTTI *rtti = attr.GetMemberPrimitiveType();
  88. if (rtti != nullptr)
  89. QueueRTTI(rtti);
  90. HintNextItem();
  91. // Write attribute information.
  92. WriteName(attr.GetName());
  93. attr.WriteDataType(*this);
  94. }
  95. HintIndentDown();
  96. }
  97. void ObjectStreamOut::WriteClassData(const RTTI *inRTTI, const void *inInstance)
  98. {
  99. JPH_ASSERT(inInstance);
  100. // Write attributes
  101. HintIndentUp();
  102. for (int attr_index = 0; attr_index < inRTTI->GetAttributeCount(); ++attr_index)
  103. {
  104. // Get attribute
  105. const SerializableAttribute &attr = inRTTI->GetAttribute(attr_index);
  106. attr.WriteData(*this, inInstance);
  107. }
  108. HintIndentDown();
  109. }
  110. void ObjectStreamOut::WritePointerData(const RTTI *inRTTI, const void *inPointer)
  111. {
  112. Identifier identifier;
  113. if (inPointer)
  114. {
  115. // Check if this object has an identifier
  116. IdentifierMap::iterator i = mIdentifierMap.find(inPointer);
  117. if (i != mIdentifierMap.end())
  118. {
  119. // Object already has an identifier
  120. identifier = i->second.mIdentifier;
  121. }
  122. else
  123. {
  124. // Assign a new identifier to this object and queue it for serialization
  125. identifier = mNextIdentifier++;
  126. mIdentifierMap.try_emplace(inPointer, identifier, inRTTI);
  127. mObjectQueue.push(inPointer);
  128. }
  129. }
  130. else
  131. {
  132. // Write nullptr pointer
  133. identifier = sNullIdentifier;
  134. }
  135. // Write the identifier
  136. HintNextItem();
  137. WriteIdentifier(identifier);
  138. }
  139. JPH_NAMESPACE_END