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