TECA
The Toolkit for Extreme Climate Analysis
teca_file_util.h
Go to the documentation of this file.
1 #ifndef teca_file_util_h
2 #define teca_file_util_h
3 
4 /// @file
5 
6 #include "teca_config.h"
7 
8 #include <vector>
9 #include <deque>
10 #include <string>
11 #include <iostream>
12 #include <fstream>
13 #include <sstream>
14 #include <sys/stat.h>
15 
16 class teca_binary_stream;
17 
18 #ifndef WIN32
19  #define PATH_SEP "/"
20 #else
21  #define PATH_SEP "\\"
22 #endif
23 
24 /// Codes dealing with low level file system API's
25 namespace teca_file_util
26 {
27 /** read the file into a stream. if header is not null the call will fail if the
28  * given string is not found. return zero upon success. The verbose flag
29  * indicates whether or not an error is reported if opening the file fails. All
30  * other errors are always reported.
31  */
33 int read_stream(const char *file_name, const char *header,
34  teca_binary_stream &stream, bool verbose=true);
35 
36 /** write the stream to the file. the passed in flags control file access, a
37  * reasonable value is S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH. if header is not null
38  * the given string is prepended to the file. return zero upon success. The
39  * verbose flag indicates whether or not an error is reported if creating the
40  * file fails. All other errors are reported.
41  */
43 int write_stream(const char *file_name, int flags, const char *header,
44  const teca_binary_stream &stream, bool verbose=true);
45 
46 /// replace %t% with the given value
48 void replace_timestep(std::string &file_name, unsigned long time_step, int width = 6);
49 
50 /// replace %t% with the time t in calendar with units in the strftime format
52 int replace_time(std::string &file_name, double t,
53  const std::string &calendar, const std::string &units,
54  const std::string &format);
55 
56 /// replace %e% with the given string
58 void replace_extension(std::string &file_name, const std::string &ext);
59 
60 /// replace %s% with the given string
62 void replace_identifier(std::string &file_name, const std::string &id);
63 
64 /// return string converted to lower case
66 void to_lower(std::string &in);
67 
68 /// return 0 if the file does not exist
70 int file_exists(const char *path);
71 
72 /// return 0 if the file/directory is not writeable
74 int file_writable(const char *path);
75 
76 /** Returns the path not including the file name and not including the final
77  * PATH_SEP. If PATH_SEP isn't found then ".PATH_SEP" is returned.
78  */
80 std::string path(const std::string &filename);
81 
82 /** Returns the file name not including the extension (ie what ever is after
83  * the last ".". If there is no "." then the filename is returned unmodified.
84  */
86 std::string base_filename(const std::string &filename);
87 
88 /** Returns the file name from the given path. If PATH_SEP isn't found
89  * then the filename is returned unmodified.
90  */
92 std::string filename(const std::string &filename);
93 
94 /// Returns the extension from the given filename.
96 std::string extension(const std::string &filename);
97 
98 /// read the lines of the ascii file into a vector
100 size_t load_lines(const char *filename, std::vector<std::string> &lines);
101 
102 /// read the file into a string
104 size_t load_text(const std::string &filename, std::string &text);
105 
106 /// write the string to the named file
108 int write_text(std::string &filename, std::string &text);
109 
110 /// Search and replace with in a string of text.
113  const std::string &search_for,
114  const std::string &replace_with,
115  std::string &in_text);
116 
117 /// Locate files in path that match a regular expression.
120  const std::string &path,
121  const std::string &re,
122  std::vector<std::string> &file_list);
123 
124 /// Load a binary file into memory
125 template<typename T>
127 size_t load_bin(const char *filename, size_t dlen, T *buffer)
128 {
129  std::ifstream file(filename,std::ios::binary);
130  if (!file.is_open())
131  {
132  std::cerr << "ERROR: File " << filename << " could not be opened." << std::endl;
133  return 0;
134  }
135 
136  // determine file size
137  file.seekg(0,std::ios::end);
138  size_t flen=file.tellg();
139  file.seekg(0,std::ios::beg);
140 
141  // check if file size matches expected read size.
142  if (dlen*sizeof(T)!=flen)
143  {
144  std::cerr
145  << "ERROR: Expected " << dlen << " bytes but found "
146  << flen << " bytes in \"" << filename << "\".";
147  return 0;
148  }
149 
150  // read
151  file.read((char*)buffer,flen);
152  file.close();
153 
154  // return the data, it's up to the caller to free.
155  return dlen;
156 }
157 
158 /// extract a name-value pair from the given set of lines.
159 template<typename T>
161 int name_value(std::vector<std::string> &lines, std::string name, T &value)
162 {
163  size_t n_lines=lines.size();
164  for (size_t i=0; i<n_lines; ++i)
165  {
166  std::string tok;
167  std::istringstream is(lines[i]);
168  is >> tok;
169  if (tok==name)
170  {
171  is >> value;
172  return 1;
173  }
174  }
175  return 0;
176 }
177 
178 /** Parse a string for a "key", starting at offset "at" then advance past the
179  * key and attempt to convert what follows in to a value of type "T". If the
180  * key isn't found, then npos is returned otherwise the position imediately
181  * following the key is returned.
182 */
183 template <typename T>
185 size_t parse_value(std::string &in,size_t at, std::string key, T &value)
186 {
187  size_t p=in.find(key,at);
188  if (p!=std::string::npos)
189  {
190  size_t n=key.size();
191 
192  // check to make sure match is the whole word
193  if ((p!=0) && isalpha(in[p-1]) && isalpha(in[p+n]))
194  {
195  return std::string::npos;
196  }
197  // convert value
198  const int max_value_len=64;
199  p+=n;
200  std::istringstream valss(in.substr(p,max_value_len));
201 
202  valss >> value;
203  }
204  return p;
205 }
206 
207 /** a stack of lines. lines can be popped as they are processed and the current
208  * line number is recorded.
209  */
211 {
212  line_buffer() : m_buffer(nullptr), m_line_number(0) {}
213  ~line_buffer() { free(m_buffer); }
214 
215  // read the contents of the file and intitalize the
216  // stack of lines.
217  int initialize(const char *file_name);
218 
219  // check if the stack is not empty
220  operator bool ()
221  {
222  return !m_lines.empty();
223  }
224 
225  // get the line at the top of the stack
226  char *current()
227  {
228  return m_lines.front();
229  }
230 
231  // remove the line at the top of the stack
232  void pop()
233  {
234  m_lines.pop_front();
235  ++m_line_number;
236  }
237 
238  // get the current line number
239  size_t line_number()
240  {
241  return m_line_number;
242  }
243 
244  char *m_buffer;
245  std::deque<char*> m_lines;
246  size_t m_line_number;
247 };
248 
249 };
250 
251 #endif
Serialize objects into a binary stream.
Definition: teca_binary_stream.h:17
p_teca_error_handler error_handler TECA_EXPORT
The global error handler instance.
Codes dealing with low level file system API's.
Definition: teca_file_util.h:26
TECA_EXPORT size_t load_text(const std::string &filename, std::string &text)
read the file into a string
TECA_EXPORT std::string base_filename(const std::string &filename)
TECA_EXPORT size_t load_lines(const char *filename, std::vector< std::string > &lines)
read the lines of the ascii file into a vector
TECA_EXPORT std::string extension(const std::string &filename)
Returns the extension from the given filename.
TECA_EXPORT size_t load_bin(const char *filename, size_t dlen, T *buffer)
Load a binary file into memory.
Definition: teca_file_util.h:127
TECA_EXPORT int search_and_replace(const std::string &search_for, const std::string &replace_with, std::string &in_text)
Search and replace with in a string of text.
TECA_EXPORT int file_exists(const char *path)
return 0 if the file does not exist
TECA_EXPORT void replace_timestep(std::string &file_name, unsigned long time_step, int width=6)
replace t% with the given value
TECA_EXPORT int locate_files(const std::string &path, const std::string &re, std::vector< std::string > &file_list)
Locate files in path that match a regular expression.
TECA_EXPORT int write_stream(const char *file_name, int flags, const char *header, const teca_binary_stream &stream, bool verbose=true)
TECA_EXPORT size_t parse_value(std::string &in, size_t at, std::string key, T &value)
Definition: teca_file_util.h:185
TECA_EXPORT int name_value(std::vector< std::string > &lines, std::string name, T &value)
extract a name-value pair from the given set of lines.
Definition: teca_file_util.h:161
TECA_EXPORT int read_stream(const char *file_name, const char *header, teca_binary_stream &stream, bool verbose=true)
TECA_EXPORT int write_text(std::string &filename, std::string &text)
write the string to the named file
TECA_EXPORT void to_lower(std::string &in)
return string converted to lower case
TECA_EXPORT std::string filename(const std::string &filename)
TECA_EXPORT int replace_time(std::string &file_name, double t, const std::string &calendar, const std::string &units, const std::string &format)
replace t% with the time t in calendar with units in the strftime format
TECA_EXPORT void replace_extension(std::string &file_name, const std::string &ext)
replace e% with the given string
TECA_EXPORT void replace_identifier(std::string &file_name, const std::string &id)
replace s% with the given string
TECA_EXPORT int file_writable(const char *path)
return 0 if the file/directory is not writeable
TECA_EXPORT std::string path(const std::string &filename)
Definition: teca_file_util.h:211