1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2001-2021 The Octave Project Developers 4 // 5 // See the file COPYRIGHT.md in the top-level directory of this 6 // distribution or <https://octave.org/copyright/>. 7 // 8 // This file is part of Octave. 9 // 10 // Octave is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 3 of the License, or 13 // (at your option) any later version. 14 // 15 // Octave is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Octave; see the file COPYING. If not, see 22 // <https://www.gnu.org/licenses/>. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 26 #if defined (HAVE_CONFIG_H) 27 # include "config.h" 28 #endif 29 30 #include <deque> 31 #include <fstream> 32 33 #include "file-info.h" 34 #include "file-stat.h" 35 #include "lo-error.h" 36 #include "lo-sysdep.h" 37 38 namespace octave 39 { get_line(std::size_t line) const40 std::string file_info::get_line (std::size_t line) const 41 { 42 std::string retval; 43 44 if (line == 0) 45 return retval; 46 47 if (line < m_offsets.size ()) 48 { 49 std::size_t bol = m_offsets[line-1]; 50 std::size_t eol = m_offsets[line]; 51 52 while (eol > 0 && eol > bol 53 && (m_file_buf[eol-1] == '\n' || m_file_buf[eol-1] == '\r')) 54 eol--; 55 56 retval = m_file_buf.substr (bol, eol - bol); 57 } 58 59 return retval; 60 } 61 62 std::deque<std::string> get_lines(std::size_t line,std::size_t num_lines) const63 file_info::get_lines (std::size_t line, std::size_t num_lines) const 64 { 65 std::deque<std::string> retval; 66 67 for (std::size_t i = line; i < line+num_lines; i++) 68 retval.push_back (get_line (i)); 69 70 return retval; 71 } 72 73 // Read entire file called fname and return the contents as a string 74 snarf_file(const std::string & fname)75 std::string file_info::snarf_file (const std::string& fname) 76 { 77 std::string retval; 78 79 sys::file_stat fs (fname); 80 81 if (! fs) 82 (*current_liboctave_error_handler) ("no such file, '%s'", fname.c_str ()); 83 84 std::size_t sz = fs.size (); 85 86 std::ifstream file = sys::ifstream (fname.c_str (), 87 std::ios::in | std::ios::binary); 88 89 if (file) 90 { 91 std::string buf (sz+1, 0); 92 93 file.read (&buf[0], sz+1); 94 95 if (! file.eof ()) 96 (*current_liboctave_error_handler) 97 ("error reading file %s", fname.c_str ()); 98 99 // Expected to read the entire file. 100 retval = buf; 101 } 102 103 return retval; 104 } 105 get_line_offsets(const std::string & buf)106 std::vector<std::size_t> file_info::get_line_offsets (const std::string& buf) 107 { 108 std::deque<std::size_t> tmp_offsets; 109 110 tmp_offsets.push_back (0); 111 112 std::size_t len = buf.length (); 113 114 for (std::size_t i = 0; i < len; i++) 115 { 116 char c = buf[i]; 117 118 if (c == '\r' && ++i < len) 119 { 120 c = buf[i]; 121 122 if (c == '\n') 123 tmp_offsets.push_back (i+1); 124 else 125 tmp_offsets.push_back (i); 126 } 127 else if (c == '\n') 128 tmp_offsets.push_back (i+1); 129 } 130 131 tmp_offsets.push_back (len-1); 132 133 std::size_t n = tmp_offsets.size (); 134 135 std::vector<std::size_t> retval (n); 136 std::size_t i = 0; 137 for (auto& elt : tmp_offsets) 138 retval[i++] = elt; 139 140 return retval; 141 } 142 } 143