GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GUrlFile.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GUrlFile.cpp - File URL class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2013-2021 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GUrlFile.cpp
23  * @brief File URL class interface implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cstdarg> // std::va_list
32 #include <cstdio> // std::fopen, std::fgets, std::fclose, etc...
33 #include "GUrlFile.hpp"
34 #include "GTools.hpp"
35 #include "GException.hpp"
36 
37 /* __ Method name definitions ____________________________________________ */
38 #define G_OPEN "GUrlFile::open(std::string&, std::string&)"
39 
40 /* __ Macros _____________________________________________________________ */
41 
42 /* __ Coding definitions _________________________________________________ */
43 
44 /* __ Debug definitions __________________________________________________ */
45 
46 
47 /*==========================================================================
48  = =
49  = Constructors/destructors =
50  = =
51  ==========================================================================*/
52 
53 /***********************************************************************//**
54  * @brief Void constructor
55  ***************************************************************************/
57 {
58  // Initialise members
59  init_members();
60 
61  // Return
62  return;
63 }
64 
65 
66 /***********************************************************************//**
67  * @brief Opening constructor
68  *
69  * @param[in] url File name.
70  * @param[in] mode File mode.
71  *
72  * Constructs GUrlFile object by opening a file @p url in the specified
73  * @p mode. Any environment variable present in the file name will be
74  * automatically expanded.
75  ***************************************************************************/
76 GUrlFile::GUrlFile(const std::string& url, const std::string& mode) : GUrl()
77 {
78  // Initialise members
79  init_members();
80 
81  // Open file
82  open(url, mode);
83 
84  // Return
85  return;
86 }
87 
88 
89 /***********************************************************************//**
90  * @brief Copy constructor
91  *
92  * @param[in] url URL.
93  ***************************************************************************/
94 GUrlFile::GUrlFile(const GUrlFile& url) : GUrl(url)
95 {
96  // Initialise members
97  init_members();
98 
99  // Copy members
100  copy_members(url);
101 
102  // Return
103  return;
104 }
105 
106 
107 /***********************************************************************//**
108  * @brief Destructor
109  ***************************************************************************/
111 {
112  // Free members
113  free_members();
114 
115  // Return
116  return;
117 }
118 
119 
120 /*==========================================================================
121  = =
122  = Operators =
123  = =
124  ==========================================================================*/
125 
126 /***********************************************************************//**
127  * @brief Assignment operator
128  *
129  * @param[in] url URL.
130  * @return URL.
131  ***************************************************************************/
133 {
134  // Execute only if object is not identical
135  if (this != &url) {
136 
137  // Copy base class members
138  this->GUrl::operator=(url);
139 
140  // Free members
141  free_members();
142 
143  // Initialise members
144  init_members();
145 
146  // Copy members
147  copy_members(url);
148 
149  } // endif: object was not identical
150 
151  // Return
152  return *this;
153 }
154 
155 
156 /*==========================================================================
157  = =
158  = Public methods =
159  = =
160  ==========================================================================*/
161 
162 /***********************************************************************//**
163  * @brief Clear instance
164  ***************************************************************************/
165 void GUrlFile::clear(void)
166 {
167  // Free class members
168  free_members();
169  this->GUrl::free_members();
170 
171  // Initialise members
172  this->GUrl::init_members();
173  init_members();
174 
175  // Return
176  return;
177 }
178 
179 
180 /***********************************************************************//**
181  * @brief Clone instance
182  *
183  * @return Pointer to deep copy of file URL.
184  ***************************************************************************/
186 {
187  // Clone object
188  return new GUrlFile(*this);
189 }
190 
191 
192 /***********************************************************************//**
193  * @brief Open file
194  *
195  * @param[in] url File name.
196  * @param[in] mode File mode.
197  *
198  * @exception GException::file_error
199  * Unable to open file.
200  *
201  * Opens a file @p url in the specified @p mode. Any environment variable
202  * present in the filename will be automatically expanded.
203  *
204  * @todo Strip any file:// prefix
205  ***************************************************************************/
206 void GUrlFile::open(const std::string& url, const std::string& mode)
207 {
208  // First close any existing file
209  close();
210 
211  // Expand environment variables
212  std::string filename = gammalib::expand_env(url);
213 
214  // Try opening file. Throw an exception if opening failed.
215  m_fptr = std::fopen(filename.c_str(), mode.c_str());
216  if (m_fptr == NULL) {
217  std::string msg = "Unable to open file \""+filename+"\" in mode \""+
218  mode+"\". Please specify an accessible file.";
219  throw GException::file_error(G_OPEN, msg);
220  }
221 
222  // Store URL and mode
223  m_url = url;
224  m_mode = mode;
225 
226  // Return
227  return;
228 }
229 
230 
231 /***********************************************************************//**
232  * @brief Close file
233  ***************************************************************************/
234 void GUrlFile::close(void)
235 {
236  // Close file
237  if (m_fptr != NULL) {
238  std::fclose(m_fptr);
239  }
240 
241  // Reset members
242  m_url.clear();
243  m_mode.clear();
244  m_fptr = NULL;
245 
246  // Return
247  return;
248 }
249 
250 
251 /***********************************************************************//**
252  * @brief Read block of data from file in buffer
253  *
254  * @param[in] buffer Data buffer.
255  * @param[in] nbyte Number of Bytes to be read.
256  * @return Number of Bytes that were effectively read.
257  *
258  * Reads @p nbyte Bytes from the file into a @p buffer. The position
259  * indicator of the file is advanced by the total amount of bytes read.
260  *
261  * The total number of Bytes successfully read is returned. If this number
262  * differs from the @p nbyte parameter, either a reading error occurred or
263  * the end-of-file was reached while reading. In both cases, the proper
264  * indicator is set.
265  *
266  * If either @p buffer is NULL or @p nbyte is zero, the method returns zero
267  * and both the file state and the content pointed by @p buffer remain
268  * unchanged.
269  *
270  * If no file has been opened, the method returns zero and both the file
271  * state and the content pointed by @p buffer remain unchanged.
272  ***************************************************************************/
273 int GUrlFile::read(void* buffer, const int& nbyte)
274 {
275  // Initialise number of Bytes read
276  int nread = 0;
277 
278  // Continue only if file is opened
279  if (m_fptr != NULL) {
280 
281  // Continue only if buffer is valid and nbyte is positive
282  if (buffer != NULL && nbyte > 0) {
283  nread = std::fread(buffer, 1, nbyte, m_fptr);
284  }
285 
286  } // endif: File was opened
287 
288  // Return number of Bytes read
289  return nread;
290 }
291 
292 
293 /***********************************************************************//**
294  * @brief Write block of data buffer into file
295  *
296  * @param[in] buffer Data buffer.
297  * @param[in] nbyte Number of Bytes to be written.
298  * @return Number of Bytes that were effectively written.
299  *
300  * Writes @p nbyte Bytes from a @p buffer into the file. The position
301  * indicator of the file is advanced by the total amount of bytes written.
302  *
303  * The total number of Bytes successfully written is returned. If this number
304  * differs from the @p nbyte parameter, a writing error prevented the
305  * function from completing.
306  *
307  * If either @p buffer is NULL or @p nbyte is zero, the method returns zero
308  * and both the file state and the content pointed by @p buffer remain
309  * unchanged.
310  *
311  * If no file has been opened, the method returns zero and both the file
312  * state and the content pointed by @p buffer remain unchanged.
313  ***************************************************************************/
314 int GUrlFile::write(const void* buffer, const int& nbyte)
315 {
316  // Initialise number of Bytes written
317  int nwritten = 0;
318 
319  // Continue only if file is opened
320  if (m_fptr != NULL) {
321 
322  // Continue only if buffer is valid and nbyte is positive
323  if (buffer != NULL && nbyte > 0) {
324  nwritten = std::fwrite(buffer, 1, nbyte, m_fptr);
325  }
326 
327  } // endif: File was opened
328 
329  // Return number of Bytes written
330  return nwritten;
331 }
332 
333 
334 /***********************************************************************//**
335  * @brief Return next character from file
336  *
337  * @return Next character in file.
338  *
339  * Returns the character currently pointed by the internal file position
340  * indicator of the file. The internal file position indicator is then
341  * advanced to the next character.
342  *
343  * If the stream is at the end-of-file when called, the function returns EOF
344  * and sets the end-of-file indicator for the file.
345  *
346  * If a read error occurs, the method returns EOF.
347  *
348  * If no file has been opened, the method returns EOF.
349  ***************************************************************************/
350 int GUrlFile::get_char(void) const
351 {
352  // Initialise character to EOF
353  int character = EOF;
354 
355  // Continue only if file is opened
356  if (m_fptr != NULL) {
357 
358  // Get next character
359  character = std::fgetc(m_fptr);
360 
361  } // endif: File was opened
362 
363  // Return character
364  return character;
365 }
366 
367 
368 /***********************************************************************//**
369  * @brief Write character into file
370  *
371  * @param[in] character Character.
372  *
373  * Writes a character to the file and advances the position indicator.
374  *
375  * If no file has been opened, the method does nothing.
376  ***************************************************************************/
377 void GUrlFile::put_char(const int& character)
378 {
379  // Continue only if file is opened
380  if (m_fptr != NULL) {
381 
382  // Write character
383  std::fputc(character, m_fptr);
384 
385  } // endif: File was opened
386 
387  // Return
388  return;
389 }
390 
391 
392 /***********************************************************************//**
393  * @brief Read formatted data from file
394  *
395  * @param[in] format Format.
396  * @param[in] ... Optional parameters.
397  *
398  * Reads data from a file and stores them according to the parameter format
399  * into the locations pointed by the additional arguments. The additional
400  * arguments should point to already allocated objects of the type specified
401  * by their corresponding format specifier within the format string.
402  *
403  * If no file has been opened, the method does nothing.
404  ***************************************************************************/
405 void GUrlFile::scanf(const char* format, ...)
406 {
407  // Continue only if file is opened
408  if (m_fptr != NULL) {
409 
410  // Declare argument pointer
411  std::va_list arg_ptr;
412 
413  // Set start argument
414  va_start(arg_ptr, format);
415 
416  // Read data from file
417  vfscanf(m_fptr, format, arg_ptr);
418 
419  // Stop argument reading
420  va_end(arg_ptr);
421 
422  } // endif: File was opened
423 
424  // Return
425  return;
426 }
427 
428 
429 /***********************************************************************//**
430  * @brief Write formatted data into file
431  *
432  * @param[in] format Format.
433  * @param[in] ... Optional parameters.
434  *
435  * Writes the C string pointed by format to the file. If format includes
436  * format specifiers (subsequences beginning with %), the additional
437  * arguments following format are formatted and inserted in the resulting
438  * string replacing their respective specifiers.
439  *
440  * After the format parameter, the function expects at least as many
441  * additional arguments as specified by format.
442  *
443  * If no file has been opened, the method does nothing.
444  ***************************************************************************/
445 void GUrlFile::printf(const char* format, ...)
446 {
447  // Continue only if file is opened
448  if (m_fptr != NULL) {
449 
450  // Declare argument pointer
451  std::va_list arg_ptr;
452 
453  // Set start argument
454  va_start(arg_ptr, format);
455 
456  // Write data into file
457  std::vfprintf(m_fptr, format, arg_ptr);
458 
459  // Stop argument reading
460  va_end(arg_ptr);
461 
462  } // endif: File was opened
463 
464  // Return
465  return;
466 }
467 
468 
469 /***********************************************************************//**
470  * @brief Print URL information
471  *
472  * @param[in] chatter Chattiness (defaults to NORMAL).
473  * @return String containing URL information.
474  ***************************************************************************/
475 std::string GUrlFile::print(const GChatter& chatter) const
476 {
477  // Initialise result string
478  std::string result;
479 
480  // Continue only if chatter is not silent
481  if (chatter != SILENT) {
482 
483  // Append header
484  result.append("=== GUrlFile ===");
485 
486  // Append information
487  if (m_fptr != NULL) {
488 
489  // Get information
490  int pos = std::ftell(m_fptr);
491  int err = std::ferror(m_fptr);
492 
493  // Append it
494  result.append("\n"+gammalib::parformat("File URL")+m_url);
495  result.append("\n"+gammalib::parformat("File mode")+m_mode);
496  result.append("\n"+gammalib::parformat("File position indicator"));
497  result.append(gammalib::str(pos));
498  result.append("\n"+gammalib::parformat("File error"));
499  if (err == 0) {
500  result.append("none");
501  }
502  else {
503  result.append(gammalib::str(err));
504  }
505  }
506  else {
507  result.append("\n"+gammalib::parformat("URL")+"none");
508  }
509 
510  } // endif: chatter was not silent
511 
512  // Return result
513  return result;
514 }
515 
516 
517 
518 
519 /*==========================================================================
520  = =
521  = Private methods =
522  = =
523  ==========================================================================*/
524 
525 /***********************************************************************//**
526  * @brief Initialise class members
527  ***************************************************************************/
529 {
530  // Initialise members
531  m_url.clear();
532  m_mode.clear();
533  m_fptr = NULL;
534 
535  // Return
536  return;
537 }
538 
539 
540 /***********************************************************************//**
541  * @brief Copy class members
542  *
543  * @param[in] url URL.
544  *
545  * @todo The simple copying of the file pointer is not clean as we have no
546  * control anymore over the object. The file pointer should be cloned
547  * somehow.
548  ***************************************************************************/
550 {
551  // Copy members
552  m_url = url.m_url;
553  m_mode = url.m_mode;
554  m_fptr = url.m_fptr;
555 
556  // Return
557  return;
558 }
559 
560 
561 /***********************************************************************//**
562  * @brief Delete class members
563  ***************************************************************************/
565 {
566  // Close file
567  close();
568 
569  // Return
570  return;
571 }
std::string m_mode
File mode.
Definition: GUrlFile.hpp:75
virtual void clear(void)
Clear instance.
Definition: GUrlFile.cpp:165
GUrlFile(void)
Void constructor.
Definition: GUrlFile.cpp:56
void free_members(void)
Delete class members.
Definition: GUrlFile.cpp:564
GUrlFile & operator=(const GUrlFile &url)
Assignment operator.
Definition: GUrlFile.cpp:132
GUrl & operator=(const GUrl &url)
Assignment operator.
Definition: GUrl.cpp:104
virtual int write(const void *buffer, const int &nbyte)
Write block of data buffer into file.
Definition: GUrlFile.cpp:314
Gammalib tools definition.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print URL information.
Definition: GUrlFile.cpp:475
File URL class interface definition.
virtual ~GUrlFile(void)
Destructor.
Definition: GUrlFile.cpp:110
Abstract URL base class.
Definition: GUrl.hpp:44
File URL class.
Definition: GUrlFile.hpp:41
std::string m_url
File URL.
Definition: GUrlFile.hpp:74
virtual void close(void)
Close file.
Definition: GUrlFile.cpp:234
virtual void open(const std::string &url, const std::string &mode)
Open file.
Definition: GUrlFile.cpp:206
GChatter
Definition: GTypemaps.hpp:33
void free_members(void)
Delete class members.
Definition: GUrl.cpp:163
virtual void printf(const char *format,...)
Write formatted data into file.
Definition: GUrlFile.cpp:445
void copy_members(const GUrlFile &url)
Copy class members.
Definition: GUrlFile.cpp:549
#define G_OPEN
Definition: GUrlFile.cpp:38
virtual void scanf(const char *format,...)
Read formatted data from file.
Definition: GUrlFile.cpp:405
virtual int get_char(void) const
Return next character from file.
Definition: GUrlFile.cpp:350
virtual GUrlFile * clone(void) const
Clone instance.
Definition: GUrlFile.cpp:185
virtual int read(void *buffer, const int &nbyte)
Read block of data from file in buffer.
Definition: GUrlFile.cpp:273
virtual void put_char(const int &character)
Write character into file.
Definition: GUrlFile.cpp:377
Exception handler interface definition.
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition: GTools.cpp:214
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
void init_members(void)
Initialise class members.
Definition: GUrlFile.cpp:528
void init_members(void)
Initialise class members.
Definition: GUrl.cpp:141
FILE * m_fptr
File pointer.
Definition: GUrlFile.hpp:76
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489