| 3696 | /*************** CODE SNIPPET ***************/ |
| 3697 | |
| 3698 | class SourceFile { |
| 3699 | public: |
| 3700 | typedef std::vector<std::pair<unsigned, std::string> > lines_t; |
| 3701 | |
| 3702 | SourceFile() {} |
| 3703 | SourceFile(const std::string &path) { |
| 3704 | // 1. If BACKWARD_CXX_SOURCE_PREFIXES is set then assume it contains |
| 3705 | // a colon-separated list of path prefixes. Try prepending each |
| 3706 | // to the given path until a valid file is found. |
| 3707 | const std::vector<std::string> &prefixes = get_paths_from_env_variable(); |
| 3708 | for (size_t i = 0; i < prefixes.size(); ++i) { |
| 3709 | // Double slashes (//) should not be a problem. |
| 3710 | std::string new_path = prefixes[i] + '/' + path; |
| 3711 | _file.reset(new std::ifstream(new_path.c_str())); |
| 3712 | if (is_open()) |
| 3713 | break; |
| 3714 | } |
| 3715 | // 2. If no valid file found then fallback to opening the path as-is. |
| 3716 | if (!_file || !is_open()) { |
| 3717 | _file.reset(new std::ifstream(path.c_str())); |
| 3718 | } |
| 3719 | } |
| 3720 | bool is_open() const { return _file->is_open(); } |
| 3721 | |
| 3722 | lines_t &get_lines(unsigned line_start, unsigned line_count, lines_t &lines) { |
| 3723 | using namespace std; |
| 3724 | // This function make uses of the dumbest algo ever: |
| 3725 | // 1) seek(0) |
| 3726 | // 2) read lines one by one and discard until line_start |
| 3727 | // 3) read line one by one until line_start + line_count |
| 3728 | // |
| 3729 | // If you are getting snippets many time from the same file, it is |
| 3730 | // somewhat a waste of CPU, feel free to benchmark and propose a |
| 3731 | // better solution ;) |
| 3732 | |
| 3733 | _file->clear(); |
| 3734 | _file->seekg(0); |
| 3735 | string line; |
| 3736 | unsigned line_idx; |
| 3737 | |
| 3738 | for (line_idx = 1; line_idx < line_start; ++line_idx) { |
| 3739 | std::getline(*_file, line); |
| 3740 | if (!*_file) { |
| 3741 | return lines; |
| 3742 | } |
| 3743 | } |
| 3744 | |
| 3745 | // think of it like a lambda in C++98 ;) |
| 3746 | // but look, I will reuse it two times! |
| 3747 | // What a good boy am I. |
| 3748 | struct isspace { |
| 3749 | bool operator()(char c) { return std::isspace(c); } |
| 3750 | }; |
| 3751 | |
| 3752 | bool started = false; |
| 3753 | for (; line_idx < line_start + line_count; ++line_idx) { |
| 3754 | getline(*_file, line); |
| 3755 | if (!*_file) { |
no test coverage detected