|  | /* | 
|  | * Copyright (C) 2022 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 "src/trace_processor/util/streaming_line_reader.h" | 
|  |  | 
|  | #include "perfetto/base/logging.h" | 
|  | #include "perfetto/ext/base/utils.h" | 
|  |  | 
|  | namespace perfetto { | 
|  | namespace trace_processor { | 
|  | namespace util { | 
|  |  | 
|  | StreamingLineReader::StreamingLineReader(LinesCallback cb) | 
|  | : lines_callback_(std::move(cb)) {} | 
|  | StreamingLineReader::~StreamingLineReader() = default; | 
|  |  | 
|  | char* StreamingLineReader::BeginWrite(size_t write_buf_size) { | 
|  | PERFETTO_DCHECK(size_before_write_ == 0); | 
|  | size_before_write_ = buf_.size(); | 
|  | buf_.resize(size_before_write_ + write_buf_size); | 
|  | return &buf_[size_before_write_]; | 
|  | } | 
|  |  | 
|  | void StreamingLineReader::EndWrite(size_t size_written) { | 
|  | PERFETTO_DCHECK(size_before_write_ + size_written <= buf_.size()); | 
|  | buf_.resize(size_before_write_ + size_written); | 
|  | size_before_write_ = 0; | 
|  |  | 
|  | size_t consumed = Tokenize(base::StringView(buf_.data(), buf_.size())); | 
|  | PERFETTO_DCHECK(consumed <= buf_.size()); | 
|  |  | 
|  | // Unless we got very lucky, the last line in the chunk just written will be | 
|  | // incomplete. Move it to the beginning of the buffer so it gets glued | 
|  | // together on the next {Begin,End}Write() call. | 
|  | buf_.erase(buf_.begin(), buf_.begin() + static_cast<ssize_t>(consumed)); | 
|  | } | 
|  |  | 
|  | size_t StreamingLineReader::Tokenize(base::StringView input) { | 
|  | size_t chars_consumed = 0; | 
|  | const char* line_start = input.data(); | 
|  | std::vector<base::StringView> lines; | 
|  | lines.reserve(1000);  // An educated guess to avoid silly expansions. | 
|  | for (const char* c = input.data(); c < input.end(); ++c) { | 
|  | if (*c != '\n') | 
|  | continue; | 
|  | lines.emplace_back(line_start, static_cast<size_t>(c - line_start)); | 
|  | line_start = c + 1; | 
|  | chars_consumed = static_cast<size_t>(c + 1 - input.data()); | 
|  | }  // for(c : input) | 
|  |  | 
|  | PERFETTO_DCHECK(lines.empty() ^ (chars_consumed != 0)); | 
|  | if (!lines.empty()) | 
|  | lines_callback_(lines); | 
|  | return chars_consumed; | 
|  | } | 
|  |  | 
|  | }  // namespace util | 
|  | }  // namespace trace_processor | 
|  | }  // namespace perfetto |