• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/tracing/core/sliced_protobuf_input_stream.h"
18 
19 #include <algorithm>
20 
21 #include "perfetto/base/logging.h"
22 
23 namespace perfetto {
24 
SlicedProtobufInputStream(const Slices * slices)25 SlicedProtobufInputStream::SlicedProtobufInputStream(const Slices* slices)
26     : slices_(slices), cur_slice_(slices_->begin()) {}
27 
28 SlicedProtobufInputStream::~SlicedProtobufInputStream() = default;
29 
Next(const void ** data,int * size)30 bool SlicedProtobufInputStream::Next(const void** data, int* size) {
31   if (cur_slice_ == slices_->end())
32     return false;
33 
34   PERFETTO_DCHECK(Validate());
35   *data = reinterpret_cast<const void*>(
36       reinterpret_cast<uintptr_t>(cur_slice_->start) + pos_in_cur_slice_);
37   *size = static_cast<int>(cur_slice_->size - pos_in_cur_slice_);
38   cur_slice_++;
39   pos_in_cur_slice_ = 0;
40   PERFETTO_DCHECK(Validate());
41 
42   return true;
43 }
44 
BackUp(int count)45 void SlicedProtobufInputStream::BackUp(int count) {
46   size_t n = static_cast<size_t>(count);
47   PERFETTO_DCHECK(Validate());
48   while (n) {
49     if (cur_slice_ == slices_->end() || pos_in_cur_slice_ == 0) {
50       if (cur_slice_ == slices_->begin()) {
51         // The protobuf library is violating its contract and backing up more
52         // bytes than available.
53         PERFETTO_DFATAL("Protobuf library backed up too many bytes.");
54         return;
55       }
56       cur_slice_--;
57       pos_in_cur_slice_ = cur_slice_->size;
58       continue;
59     }
60 
61     const size_t decrement = std::min(n, pos_in_cur_slice_);
62     pos_in_cur_slice_ -= decrement;
63     n -= decrement;
64   }
65   PERFETTO_DCHECK(Validate());
66 }
67 
Skip(int count)68 bool SlicedProtobufInputStream::Skip(int count) {
69   PERFETTO_DCHECK(Validate());
70   size_t n = static_cast<size_t>(count);
71   while (n) {
72     PERFETTO_DCHECK(Validate());
73     if (cur_slice_ == slices_->end())
74       return false;
75 
76     const size_t increment = std::min(n, cur_slice_->size - pos_in_cur_slice_);
77     pos_in_cur_slice_ += increment;
78     n -= increment;
79 
80     if (pos_in_cur_slice_ >= cur_slice_->size) {
81       cur_slice_++;
82       pos_in_cur_slice_ = 0;
83     }
84   }
85   PERFETTO_DCHECK(Validate());
86   return true;
87 }
88 
ByteCount() const89 google::protobuf::int64 SlicedProtobufInputStream::ByteCount() const {
90   PERFETTO_DCHECK(Validate());
91   google::protobuf::int64 count = 0;
92   for (auto it = slices_->begin(); it != slices_->end(); it++) {
93     if (it == cur_slice_) {
94       count += static_cast<google::protobuf::int64>(pos_in_cur_slice_);
95       break;
96     }
97     count += static_cast<google::protobuf::int64>(it->size);
98   }
99   return count;
100 }
101 
Validate() const102 bool SlicedProtobufInputStream::Validate() const {
103   return ((cur_slice_ == slices_->end() && pos_in_cur_slice_ == 0) ||
104           pos_in_cur_slice_ < cur_slice_->size ||
105           (pos_in_cur_slice_ == 0 && cur_slice_->size == 0));
106 }
107 
108 }  // namespace perfetto
109