ObjectStreamOut.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. ObjectQueue::size_type cur = 0;
  36. for (; cur < mObjectQueue.size() && !mStream.fail(); ++cur)
  37. WriteObject(mObjectQueue[cur]);
  38. mObjectQueue.erase(mObjectQueue.begin(), mObjectQueue.begin() + cur);
  39. return !mStream.fail();
  40. }
  41. void ObjectStreamOut::WriteObject(const void *inObject)
  42. {
  43. // Find object identifier
  44. IdentifierMap::iterator i = mIdentifierMap.find(inObject);
  45. JPH_ASSERT(i != mIdentifierMap.end());
  46. // Write class description and associated descriptions
  47. QueueRTTI(i->second.mRTTI);
  48. ClassQueue::size_type cur = 0;
  49. for (; cur < mClassQueue.size() && !mStream.fail(); ++cur)
  50. WriteRTTI(mClassQueue[cur]);
  51. mClassQueue.erase(mClassQueue.begin(), mClassQueue.begin() + cur);
  52. HintNextItem();
  53. HintNextItem();
  54. // Write object header.
  55. WriteDataType(EOSDataType::Object);
  56. WriteName(i->second.mRTTI->GetName());
  57. WriteIdentifier(i->second.mIdentifier);
  58. // Write attribute data
  59. WriteClassData(i->second.mRTTI, inObject);
  60. }
  61. void ObjectStreamOut::QueueRTTI(const RTTI *inRTTI)
  62. {
  63. ClassSet::const_iterator i = mClassSet.find(inRTTI);
  64. if (i == mClassSet.end())
  65. {
  66. mClassSet.insert(inRTTI);
  67. mClassQueue.push_back(inRTTI);
  68. }
  69. }
  70. void ObjectStreamOut::WriteRTTI(const RTTI *inRTTI)
  71. {
  72. HintNextItem();
  73. HintNextItem();
  74. // Write class header. E.g. in text mode: "class <name> <attr-count>"
  75. WriteDataType(EOSDataType::Declare);
  76. WriteName(inRTTI->GetName());
  77. WriteCount(inRTTI->GetAttributeCount());
  78. // Write class attribute info
  79. HintIndentUp();
  80. for (int attr_index = 0; attr_index < inRTTI->GetAttributeCount(); ++attr_index)
  81. {
  82. // Get attribute
  83. const SerializableAttribute &attr = inRTTI->GetAttribute(attr_index);
  84. // Write definition of attribute class if undefined
  85. const RTTI *rtti = attr.GetMemberPrimitiveType();
  86. if (rtti != nullptr)
  87. QueueRTTI(rtti);
  88. HintNextItem();
  89. // Write attribute information.
  90. WriteName(attr.GetName());
  91. attr.WriteDataType(*this);
  92. }
  93. HintIndentDown();
  94. }
  95. void ObjectStreamOut::WriteClassData(const RTTI *inRTTI, const void *inInstance)
  96. {
  97. JPH_ASSERT(inInstance);
  98. // Write attributes
  99. HintIndentUp();
  100. for (int attr_index = 0; attr_index < inRTTI->GetAttributeCount(); ++attr_index)
  101. {
  102. // Get attribute
  103. const SerializableAttribute &attr = inRTTI->GetAttribute(attr_index);
  104. attr.WriteData(*this, inInstance);
  105. }
  106. HintIndentDown();
  107. }
  108. void ObjectStreamOut::WritePointerData(const RTTI *inRTTI, const void *inPointer)
  109. {
  110. Identifier identifier;
  111. if (inPointer)
  112. {
  113. // Check if this object has an identifier
  114. IdentifierMap::iterator i = mIdentifierMap.find(inPointer);
  115. if (i != mIdentifierMap.end())
  116. {
  117. // Object already has an identifier
  118. identifier = i->second.mIdentifier;
  119. }
  120. else
  121. {
  122. // Assign a new identifier to this object and queue it for serialization
  123. identifier = mNextIdentifier++;
  124. mIdentifierMap.try_emplace(inPointer, identifier, inRTTI);
  125. mObjectQueue.push_back(inPointer);
  126. }
  127. }
  128. else
  129. {
  130. // Write nullptr pointer
  131. identifier = sNullIdentifier;
  132. }
  133. // Write the identifier
  134. HintNextItem();
  135. WriteIdentifier(identifier);
  136. }
  137. JPH_NAMESPACE_END
  138. #endif // JPH_OBJECT_STREAM