1 // Copyright 2020 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "dawn_wire/ChunkedCommandHandler.h" 16 17 #include "common/Alloc.h" 18 19 #include <algorithm> 20 #include <cstring> 21 22 namespace dawn_wire { 23 24 ChunkedCommandHandler::~ChunkedCommandHandler() = default; 25 HandleCommands(const volatile char * commands,size_t size)26 const volatile char* ChunkedCommandHandler::HandleCommands(const volatile char* commands, 27 size_t size) { 28 if (mChunkedCommandRemainingSize > 0) { 29 // If there is a chunked command in flight, append the command data. 30 // We append at most |mChunkedCommandRemainingSize| which is enough to finish the 31 // in-flight chunked command, and then pass the rest along to a second call to 32 // |HandleCommandsImpl|. 33 size_t chunkSize = std::min(size, mChunkedCommandRemainingSize); 34 35 memcpy(mChunkedCommandData.get() + mChunkedCommandPutOffset, 36 const_cast<const char*>(commands), chunkSize); 37 mChunkedCommandPutOffset += chunkSize; 38 mChunkedCommandRemainingSize -= chunkSize; 39 40 commands += chunkSize; 41 size -= chunkSize; 42 43 if (mChunkedCommandRemainingSize == 0) { 44 // Once the chunked command is complete, pass the data to the command handler 45 // implemenation. 46 auto chunkedCommandData = std::move(mChunkedCommandData); 47 if (HandleCommandsImpl(chunkedCommandData.get(), mChunkedCommandPutOffset) == 48 nullptr) { 49 // |HandleCommandsImpl| returns nullptr on error. Forward any errors 50 // out. 51 return nullptr; 52 } 53 } 54 } 55 56 return HandleCommandsImpl(commands, size); 57 } 58 BeginChunkedCommandData(const volatile char * commands,size_t commandSize,size_t initialSize)59 ChunkedCommandHandler::ChunkedCommandsResult ChunkedCommandHandler::BeginChunkedCommandData( 60 const volatile char* commands, 61 size_t commandSize, 62 size_t initialSize) { 63 ASSERT(!mChunkedCommandData); 64 65 // Reserve space for all the command data we're expecting, and copy the initial data 66 // to the start of the memory. 67 mChunkedCommandData.reset(AllocNoThrow<char>(commandSize)); 68 if (!mChunkedCommandData) { 69 return ChunkedCommandsResult::Error; 70 } 71 72 memcpy(mChunkedCommandData.get(), const_cast<const char*>(commands), initialSize); 73 mChunkedCommandPutOffset = initialSize; 74 mChunkedCommandRemainingSize = commandSize - initialSize; 75 76 return ChunkedCommandsResult::Consumed; 77 } 78 79 } // namespace dawn_wire 80