ObjectStreamOut.cpp 4.1 KB

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