1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_ZUCCHINI_BUFFER_SINK_H_ 6 #define COMPONENTS_ZUCCHINI_BUFFER_SINK_H_ 7 8 #include <stdint.h> 9 10 #include <algorithm> 11 #include <iterator> 12 13 #include "base/check_op.h" 14 #include "components/zucchini/buffer_view.h" 15 16 namespace zucchini { 17 18 // BufferSink acts like an output stream with convenience methods to serialize 19 // data into a contiguous sequence of raw data. The underlying MutableBufferView 20 // emulates a cursor to track current write position, and guards against buffer 21 // overrun. Where applicable, BufferSink should be passed by pointer to maintain 22 // cursor progress across writes. 23 class BufferSink : public MutableBufferView { 24 public: 25 using iterator = MutableBufferView::iterator; 26 27 using MutableBufferView::MutableBufferView; 28 BufferSink() = default; 29 explicit BufferSink(MutableBufferView buffer); 30 BufferSink(const BufferSink&) = default; 31 BufferSink& operator=(BufferSink&&) = default; 32 33 // If sufficient space is available, writes the binary representation of 34 // |value| starting at the cursor, while advancing the cursor beyond the 35 // written region, and returns true. Otherwise returns false. 36 template <class T> PutValue(const T & value)37 bool PutValue(const T& value) { 38 DCHECK_NE(begin(), nullptr); 39 if (Remaining() < sizeof(T)) 40 return false; 41 *reinterpret_cast<T*>(begin()) = value; 42 remove_prefix(sizeof(T)); 43 return true; 44 } 45 46 // If sufficient space is available, writes the raw bytes [|first|, |last|) 47 // starting at the cursor, while advancing the cursor beyond the written 48 // region, and returns true. Otherwise returns false. 49 template <class It> PutRange(It first,It last)50 bool PutRange(It first, It last) { 51 static_assert(sizeof(typename std::iterator_traits<It>::value_type) == 52 sizeof(uint8_t), 53 "value_type should fit in uint8_t"); 54 DCHECK_NE(begin(), nullptr); 55 DCHECK(last >= first); 56 if (Remaining() < size_type(last - first)) 57 return false; 58 std::copy(first, last, begin()); 59 remove_prefix(last - first); 60 return true; 61 } 62 Remaining()63 size_type Remaining() const { return size(); } 64 }; 65 66 } // namespace zucchini 67 68 #endif // COMPONENTS_ZUCCHINI_BUFFER_SINK_H_ 69