| 65 | } |
| 66 | |
| 67 | size_t MemoryStream::Chunk::Append(StreamChunk& dataView) |
| 68 | { |
| 69 | const size_t dataSize = dataView.second; |
| 70 | |
| 71 | const size_t bytesToWrite = std::min(ChunkSize - BytesUsed, dataSize); |
| 72 | const size_t bytesLeft = dataSize - bytesToWrite; |
| 73 | |
| 74 | const uint8_t* beginData = static_cast<const uint8_t*>(dataView.first); |
| 75 | const uint8_t* endData = beginData + bytesToWrite; |
| 76 | |
| 77 | // Some extreme micro optimization for MSVC (at least) |
| 78 | // std::copy will generate a call to memmove in any case |
| 79 | // which will be slower than just writing the byte |
| 80 | if (bytesToWrite == 1) |
| 81 | { |
| 82 | Data[BytesUsed] = *beginData; |
| 83 | } |
| 84 | else |
| 85 | { |
| 86 | // There is a chance for unaligned access, so we do no handle |
| 87 | // types as int32_t separately. Unaligned access is slow on x86 |
| 88 | // and fails horribly on ARM |
| 89 | std::copy(beginData, endData, Data.begin() + BytesUsed); |
| 90 | } |
| 91 | |
| 92 | dataView.first = endData; |
| 93 | dataView.second = bytesLeft; |
| 94 | |
| 95 | BytesUsed += bytesToWrite; |
| 96 | |
| 97 | return bytesLeft; |
| 98 | } |
| 99 | |
| 100 | bool MemoryStream::IsEmpty() const noexcept |
| 101 | { |
no test coverage detected