ByteArrayStream.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "native/utilities/ByteArrayStream.h"
  9. namespace AssetProcessor
  10. {
  11. using namespace AZ::IO;
  12. ByteArrayStream::ByteArrayStream()
  13. {
  14. m_usingOwnArray = true;
  15. m_activeArray = &m_ownArray;
  16. m_currentPos = 0;
  17. m_readOnly = false;
  18. }
  19. ByteArrayStream::ByteArrayStream(QByteArray* other)
  20. {
  21. m_activeArray = other;
  22. m_usingOwnArray = false;
  23. m_currentPos = m_activeArray->size();
  24. m_readOnly = false;
  25. }
  26. ByteArrayStream::ByteArrayStream(const char* data, unsigned int length)
  27. {
  28. m_activeArray = &m_ownArray;
  29. m_ownArray.setRawData(data, length);
  30. m_usingOwnArray = true;
  31. m_currentPos = 0;
  32. m_readOnly = true;
  33. }
  34. void ByteArrayStream::Reserve(int amount)
  35. {
  36. if (m_readOnly)
  37. {
  38. return;
  39. }
  40. m_activeArray->reserve(amount);
  41. }
  42. void ByteArrayStream::Seek(OffsetType bytes, SeekMode mode)
  43. {
  44. SizeType finalPosition = GenericStream::ComputeSeekPosition(bytes, mode);
  45. AZ_Assert(finalPosition < INT_MAX, "Overflow of SizeType to int in ByteArrayStream.");
  46. AZ_Assert(finalPosition <= m_activeArray->size(), "You cant seek beyond end of file");
  47. // safety clamp!
  48. finalPosition = AZ::GetClamp<SizeType>(finalPosition, 0, static_cast<SizeType>(m_activeArray->size()));
  49. m_currentPos = static_cast<int>(finalPosition);
  50. }
  51. SizeType ByteArrayStream::Read(SizeType bytes, void* oBuffer)
  52. {
  53. // eg
  54. // xxxxx <-- data, size() 5
  55. // ^ <-- pos, currently 2
  56. // we have 3 bytes available .. 5 - 2.
  57. int actualAvailableBytes = m_activeArray->size() - m_currentPos;
  58. if (actualAvailableBytes <= 0)
  59. {
  60. return static_cast<SizeType>(0);
  61. }
  62. const char* data = m_activeArray->constData();
  63. data += m_currentPos;
  64. AZ_Assert(bytes < std::numeric_limits<int>::max(), "Overflow in ByteArrayStream::Read.");
  65. // safety cast.
  66. bytes = AZ::GetMin(static_cast<SizeType>(std::numeric_limits<int>::max()), bytes);
  67. int bytesToRead = AZ::GetMin<int>(static_cast<int>(bytes), actualAvailableBytes);
  68. memcpy(oBuffer, data, bytesToRead);
  69. m_currentPos += bytesToRead;
  70. return bytesToRead;
  71. }
  72. SizeType ByteArrayStream::PrepareForWrite(SizeType bytes)
  73. {
  74. // how much bigger does our array have to grow?
  75. // example
  76. // oooooooo <---- capacity = 8
  77. // xxxxx <--- size = 5
  78. // ^ <--- currentpos = 2 (3rd byte)
  79. // if we're asking for a 10 byte write the final picture will be
  80. // xxyyyyyyyyyy <--- size() = 12.
  81. if (m_readOnly)
  82. {
  83. return 0;
  84. }
  85. SizeType intMaxSize = std::numeric_limits<int>::max();
  86. SizeType finalSize = bytes + static_cast<SizeType>(m_currentPos);
  87. AZ_Assert(finalSize < intMaxSize, "Overflow in ByteArrayStream::Write");
  88. if (finalSize > intMaxSize)
  89. {
  90. SizeType delta = finalSize - intMaxSize;
  91. finalSize -= delta;
  92. bytes -= delta;
  93. }
  94. int intSize = static_cast<int>(finalSize);
  95. if (intSize > m_activeArray->capacity())
  96. {
  97. // grow the array, but let's be smart about it.
  98. // assume there'll be another write the same size pretty soon.
  99. // we'd like to grow it by about a quarter of its current size
  100. // thus if we're making one LARGE write, it grows 0
  101. int growthAmount = intSize / 4;
  102. // don't allow overflow here either.
  103. if (static_cast<SizeType>(growthAmount) + static_cast<SizeType>(intSize) >= intMaxSize)
  104. {
  105. growthAmount = 0;
  106. }
  107. m_activeArray->reserve(intSize + growthAmount);
  108. }
  109. if (intSize > m_activeArray->size())
  110. {
  111. m_activeArray->resize(intSize);
  112. }
  113. return bytes;
  114. }
  115. SizeType ByteArrayStream::Write(SizeType bytes, const void* iBuffer)
  116. {
  117. bytes = PrepareForWrite(bytes);
  118. if (bytes > 0)
  119. {
  120. char* data = m_activeArray->data();
  121. data += m_currentPos;
  122. memcpy(data, iBuffer, bytes);
  123. m_currentPos += static_cast<int>(bytes);
  124. }
  125. return bytes;
  126. }
  127. SizeType ByteArrayStream::WriteFromStream(SizeType bytes, AZ::IO::GenericStream* inputStream)
  128. {
  129. AZ_Assert(inputStream, "Cannot copy from a null input stream.");
  130. AZ_Assert(inputStream != this, "Can't write and read from the same stream.");
  131. bytes = PrepareForWrite(bytes);
  132. if (bytes > 0)
  133. {
  134. char* data = m_activeArray->data();
  135. data += m_currentPos;
  136. bytes = inputStream->Read(bytes, data);
  137. m_currentPos += static_cast<int>(bytes);
  138. }
  139. return bytes;
  140. }
  141. SizeType ByteArrayStream::GetCurPos() const
  142. {
  143. return static_cast<SizeType>(m_currentPos);
  144. }
  145. SizeType ByteArrayStream::GetLength() const
  146. {
  147. return static_cast<SizeType>(m_activeArray->size());
  148. }
  149. QByteArray ByteArrayStream::GetArray() const
  150. {
  151. if (m_usingOwnArray)
  152. {
  153. return m_ownArray;
  154. }
  155. return *m_activeArray;
  156. }
  157. }