1// Copyright 2018 The Fuchsia 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#include "fidl/source_file.h" 6 7#include <assert.h> 8 9#include <algorithm> 10#include <functional> 11 12namespace fidl { 13 14SourceFile::SourceFile(std::string filename, std::string data) 15 : filename_(std::move(filename)), data_(std::move(data)) { 16 size_t size = 0u; 17 auto start_of_line = data_.cbegin(); 18 19 for (auto it = data_.cbegin(); it != data_.cend(); ++it) { 20 ++size; 21 if (*it == '\n' || *it == '\0') { 22 auto& position = *start_of_line; 23 lines_.push_back(StringView(&position, size)); 24 25 size = 0u; 26 start_of_line = it + 1; 27 } 28 } 29} 30 31SourceFile::~SourceFile() = default; 32 33StringView SourceFile::LineContaining(StringView view, Position* position_out) const { 34 auto ptr_less_equal = std::less_equal<const char*>(); 35 36 assert(ptr_less_equal(data().data(), view.data()) && "The view is not part of this SourceFile"); 37 assert(ptr_less_equal(view.data() + view.size(), data().data() + data().size()) && 38 "The view is not part of this SourceFile"); 39 40 // We are looking from the end of the file backwards (hence 41 // crbegin and crend), looking for the the first line (hence 42 // upper_bound) to start at or before before the token in 43 // question. 44 auto is_in_line = [&ptr_less_equal](const StringView& left, const StringView& right) { 45 return ptr_less_equal(right.data(), left.data()); 46 }; 47 auto line = std::upper_bound(lines_.crbegin(), lines_.crend(), view, is_in_line); 48 assert(line != lines_.crend()); 49 50 if (position_out != nullptr) { 51 // Humans number lines from 1. Calculating this from the end 52 // accounts for this. 53 int line_number = lines_.crend() - line; 54 // But columns from 0! 55 int column_number = view.data() - line->data(); 56 *position_out = {line_number, column_number}; 57 } 58 return *line; 59} 60 61} // namespace fidl 62