| /* | 
 |  * Copyright (C) 2017 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #include "perfetto/protozero/scattered_stream_writer.h" | 
 |  | 
 | #include <algorithm> | 
 |  | 
 | #include "perfetto/base/logging.h" | 
 |  | 
 | namespace protozero { | 
 |  | 
 | ScatteredStreamWriter::Delegate::~Delegate() {} | 
 |  | 
 | ScatteredStreamWriter::ScatteredStreamWriter(Delegate* delegate) | 
 |     : delegate_(delegate), | 
 |       cur_range_({nullptr, nullptr}), | 
 |       write_ptr_(nullptr) {} | 
 |  | 
 | ScatteredStreamWriter::~ScatteredStreamWriter() {} | 
 |  | 
 | void ScatteredStreamWriter::Reset(ContiguousMemoryRange range) { | 
 |   written_previously_ += static_cast<uint64_t>(write_ptr_ - cur_range_.begin); | 
 |   cur_range_ = range; | 
 |   write_ptr_ = range.begin; | 
 |   PERFETTO_DCHECK(!write_ptr_ || write_ptr_ < cur_range_.end); | 
 | } | 
 |  | 
 | void ScatteredStreamWriter::Extend() { | 
 |   Reset(delegate_->GetNewBuffer()); | 
 | } | 
 |  | 
 | void ScatteredStreamWriter::WriteBytesSlowPath(const uint8_t* src, | 
 |                                                size_t size) { | 
 |   size_t bytes_left = size; | 
 |   while (bytes_left > 0) { | 
 |     if (write_ptr_ >= cur_range_.end) | 
 |       Extend(); | 
 |     const size_t burst_size = std::min(bytes_available(), bytes_left); | 
 |     WriteBytesUnsafe(src, burst_size); | 
 |     bytes_left -= burst_size; | 
 |     src += burst_size; | 
 |   } | 
 | } | 
 |  | 
 | // TODO(primiano): perf optimization: I suspect that at the end this will always | 
 | // be called with |size| == 4, in which case we might just hardcode it. | 
 | uint8_t* ScatteredStreamWriter::ReserveBytes(size_t size) { | 
 |   if (write_ptr_ + size > cur_range_.end) { | 
 |     // Assume the reservations are always < Delegate::GetNewBuffer().size(), | 
 |     // so that one single call to Extend() will definitely give enough headroom. | 
 |     Extend(); | 
 |     PERFETTO_DCHECK(write_ptr_ + size <= cur_range_.end); | 
 |   } | 
 |   uint8_t* begin = write_ptr_; | 
 |   write_ptr_ += size; | 
 | #if PERFETTO_DCHECK_IS_ON() | 
 |   memset(begin, 0, size); | 
 | #endif | 
 |   return begin; | 
 | } | 
 |  | 
 | }  // namespace protozero |