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