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