1 /*
2  * Copyright (C) 2020 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/trace_processor/importers/proto/proto_trace_tokenizer.h"
18 
19 #include "perfetto/ext/base/utils.h"
20 
21 namespace perfetto {
22 namespace trace_processor {
23 
24 ProtoTraceTokenizer::ProtoTraceTokenizer() = default;
25 
Decompress(TraceBlobView input,TraceBlobView * output)26 util::Status ProtoTraceTokenizer::Decompress(TraceBlobView input,
27                                              TraceBlobView* output) {
28   PERFETTO_DCHECK(gzip::IsGzipSupported());
29 
30   uint8_t out[4096];
31 
32   std::vector<uint8_t> data;
33   data.reserve(input.length());
34 
35   // Ensure that the decompressor is able to cope with a new stream of data.
36   decompressor_.Reset();
37   decompressor_.SetInput(input.data(), input.length());
38 
39   using ResultCode = GzipDecompressor::ResultCode;
40   for (auto ret = ResultCode::kOk; ret != ResultCode::kEof;) {
41     auto res = decompressor_.Decompress(out, base::ArraySize(out));
42     ret = res.ret;
43     if (ret == ResultCode::kError || ret == ResultCode::kNoProgress ||
44         ret == ResultCode::kNeedsMoreInput) {
45       return util::ErrStatus("Failed to decompress (error code: %d)",
46                              static_cast<int>(ret));
47     }
48 
49     data.insert(data.end(), out, out + res.bytes_written);
50   }
51 
52   std::unique_ptr<uint8_t[]> out_data(new uint8_t[data.size()]);
53   memcpy(out_data.get(), data.data(), data.size());
54   *output = TraceBlobView(std::move(out_data), 0, data.size());
55   return util::OkStatus();
56 }
57 
58 }  // namespace trace_processor
59 }  // namespace perfetto
60