Flow123d  jenkins-Flow123d-linux-release-multijob-282
xio.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  *
26  * @file xio.cc
27  * @ingroup system
28  * @brief I/O functions with filename storing, able to track current line in opened file. All standard
29  * stdio functions working with files (not stdin, stdout, stderr) should be replaced
30  * by their equivalents from XIO library.
31  *
32  * @date 6.4.2010
33  * @author Jiri Jenicek
34  * @todo Better error handling ( perror()? strerror()? )
35  *
36  */
37 
38 
39 
40 #include <string.h>
41 #include <strings.h>
42 #include <stdarg.h>
43 #include <errno.h>
44 #include <limits.h>
45 
46 #include <iostream>
47 #include <algorithm>
48 #include <iterator>
49 
50 #include "xio.h"
51 
52 using namespace std;
53 
54 
55 //! @brief basic definitions
56 /// @{
57 static XFILE xstdin = {&std::string("stdin")[0], &std::string("r")[0], 0};
58 static XFILE xstdout = {&std::string("stdout")[0], &std::string("w")[0], 0};
59 static XFILE xstderr = {&std::string("stderr")[0], &std::string("w")[0], 0};
60 //! @}
61 
62 static XFILE * xio_getfptr( FILE * f );
63 
64 #define XIO_WARN(f) xprintf(Warn, "File pointer '%p' not in xfiles_map. Opened with regular fopen() or already closed?\n", (f) )
65 #define XIO_PRINT_INFO(f) printf( "XIO: In function '%s', %s\n", __func__, xio_getfulldescription( f ) )
66 #define XIO_DEBUG(f) do { if ( Xio::get_instance()->get_verbosity() > 0 ) XIO_PRINT_INFO(f); } while (0)
67 
68 
69 /*******************************************************************
70  * implementation of Xio
71  */
72 
73 Xio * Xio::instance = NULL;
74 
76 : verbosity_(0)
77 {
78  xfiles_map_[stdin] = &xstdin;
79  xfiles_map_[stdout] = &xstdout;
80  xfiles_map_[stderr] = &xstderr;
81 }
82 
84 {
85  ASSERT( instance , "XIO library not initialized yet.\n");
86  return instance;
87 }
88 
89 void Xio::init()
90 {
91  if (instance == NULL) {
92  instance = new Xio();
93  } else {
94  xprintf(Warn, "The XIO library already initialized.\n");
95  }
96 }
97 
98 void Xio::set_verbosity( int verb )
99 {
100  verbosity_ = verb;
101 }
102 
104 {
105  return verbosity_;
106 }
107 
109 {
110  return xfiles_map_;
111 }
112 
113 
114 
115 /*!
116  * @brief Get file name from pointer to FILE structure.
117  * @param[in] f pointer to FILE structure
118  * @return pointer to file name if OK, NULL if file stream is not known
119  */
120 char * xio_getfname( FILE * f )
121 {
122  XFILE * xf;
123  char * rs = NULL;
124 
125  xf = xio_getfptr(f);
126  if ( xf )
127  {
128  rs = xf->filename;
129  }
130  else
131  {
132  XIO_WARN(f);
133  }
134 
135  return rs;
136 }
137 
138 /*!
139  * @brief Get file mode from file stream
140  * @param[in] f pointer to FILE structure
141  * @return pointer to file opening mode if OK, NULL if file stream is not known
142  */
143 char * xio_getfmode( FILE * f )
144 {
145  XFILE * xf;
146  char * rs = NULL;
147 
148  xf = xio_getfptr(f);
149  if ( xf )
150  {
151  rs = xf->mode;
152  }
153  else
154  {
155  XIO_WARN(f);
156  }
157 
158  return rs;
159 }
160 
161 /*!
162  * @brief Get number of lines that were completely read from file since fopen() or rewind()
163  * @param[in] f pointer to FILE structure
164  * @return number of lines read if OK, -1 if file stream is not known
165  */
166 int xio_getlinesread( FILE * f )
167 {
168  XFILE * xf;
169  int lines = -1;
170 
171  xf = xio_getfptr(f);
172  if ( xf )
173  {
174  lines = xf->lineno;
175  }
176  else
177  {
178  XIO_WARN(f);
179  }
180 
181  return lines;
182 }
183 
184 /*!
185  * @brief Get pointer to string with full file description
186  * @param[in] f pointer to FILE structure
187  * @return pointer to string with description, null terminated, no LF
188  */
189 char * xio_getfulldescription( FILE * f )
190 {
191  const char prn_format_long[] = "FILE ptr %p: x->name '%s', x->mode '%s', x->line '%d'";
192  const char prn_format_short[] = "FILE ptr %p: unknown FILE pointer";
193  static char * rs = NULL;
194  static int maxlen = 0;
195  int len;
196  XFILE * xf;
197 
198  if (!rs)
199  {
200  maxlen = LINE_SIZE;
201  rs = (char *)xmalloc( maxlen );
202  }
203 
204  xf = xio_getfptr(f);
205  if ( xf )
206  {
207  len = snprintf( rs, maxlen, prn_format_long, f, xf->filename, xf->mode, xf->lineno );
208  if ( len >= maxlen ) //string overflow?
209  {
210  maxlen = len + 1;
211  rs = (char *)xrealloc( rs, maxlen );
212  snprintf( rs, maxlen, prn_format_long, f, xf->filename, xf->mode, xf->lineno );
213  }
214  }
215  else
216  {
217  len = snprintf( rs, maxlen, prn_format_short, f );
218  if ( len >= maxlen ) //string overflow?
219  {
220  maxlen = len + 1;
221  rs = (char *)xrealloc( rs, maxlen );
222  snprintf( rs, maxlen, prn_format_short, f );
223  }
224  }
225 
226  return rs;
227 }
228 
229 /*!
230  * @brief Internal XIO locator
231  * @param[in] f pointer to FILE structure
232  * @return pointer to XFILE structure if OK, NULL if file stream is not known
233  */
234 static XFILE * xio_getfptr( FILE * f )
235 {
236  XFILE * xf = NULL;
237 
238  if ( Xio::get_instance()->get_xfile_map().find(f) != Xio::get_instance()->get_xfile_map().end() )
239  {
240  xf = Xio::get_instance()->get_xfile_map()[f];
241  }
242 
243  return xf;
244 }
245 
246 FILE *xfopen( const std::string& fname, const char *mode )
247 {
248  const char *fnamec = fname.c_str();
249  return xfopen(fnamec,mode);
250 }
251 
252 /*!
253  * @brief fopen() with error handling and filename store
254  * @param[in] fname filename to open
255  * @param[in] mode opening mode
256  * @return same as ISO C fopen()
257  */
258 FILE *xfopen( const char *fname, const char *mode )
259 {
260  XFILE * xf;
261  FILE *rc;
262 
263  ASSERT(!( (fname == NULL) || (mode == NULL) ),"NULL pointer as argument of function xfopen()\n");
264  xprintf(MsgLog,"Opening file: '%s'\n", fname);
265  rc = fopen( fname, mode );
266  INPUT_CHECK( rc != NULL ,"Cannot open file '%s' with permissions %s\n", fname, mode );
267 
268  //store file name and file opening mode
269  xf = (XFILE *)xmalloc(sizeof(XFILE));
270  xf->filename = (char *)xmalloc(strlen(fname)+1);
271  strcpy( xf->filename, fname );
272  xf->mode = (char *)xmalloc(strlen(mode)+1);
273  strcpy(xf->mode, mode);
274  xf->lineno = 0;
275  Xio::get_instance()->get_xfile_map()[rc] = xf;
276 
277  XIO_DEBUG( rc );
278 
279  return(rc);
280 }
281 
282 /*!
283  * @brief Flush file stream
284  * @param[in,out] f pointer to FILE structure
285  * @return same as ISO C fflush()
286  */
287 int xfflush( FILE * f )
288 {
289  XFILE * xf;
290 
291  ASSERT(!(f == NULL),"NULL as input argument\n");
292 
293  XIO_DEBUG( f );
294 
295  xf = xio_getfptr(f);
296  if ( !xf )
297  {
298  XIO_WARN(f);
299  }
300 
301  return fflush ( f );
302 }
303 
304 /*!
305  * @brief FCLOSE WITH ERROR HANDLING
306  * @param[in,out] stream pointer to FILE structure
307  * @return same as ISO C fclose()
308  */
309 int xfclose( FILE *stream )
310 {
311  XFILE * xf;
312  int rc;
313 
314  ASSERT(!( stream == NULL ),"NULL pointer as argument of function xfclose()\n");
315 
316  XIO_DEBUG( stream );
317 
318  rc = fclose( stream );
319 
320  INPUT_CHECK(!( rc == EOF ),"Cannot close file %s\n", xio_getfname(stream) );
321 
322  if ( rc != EOF )
323  {
324  xf = xio_getfptr(stream);
325  if ( xf )
326  {
327  Xio::get_instance()->get_xfile_map().erase(stream);
328  xfree( xf->filename );
329  xfree( xf->mode );
330  xfree( xf );
331  }
332  else
333  {
334  XIO_WARN(stream);
335  }
336  }
337 
338  return(rc);
339 }
340 
341 /*!
342  * @brief Reopen stream with different file or mode
343  * @param[in] filename Name of the file to be opened
344  * @param[in] mode File access mode
345  * @param[in,out] stream Pointer to a FILE object that identifies the stream to be reopened
346  * @return Same as ISO C freopen()
347  */
348 FILE * xfreopen( const char * filename, const char * mode, FILE * stream )
349 {
350  XFILE * xf;
351  FILE *rc;
352 
353  ASSERT(!( (mode == NULL) || (stream == NULL)),"Wrong arguments\n");
354 
355  rc = freopen( filename, mode, stream );
356 
357  INPUT_CHECK( rc != NULL ,"Cannot reopen file %s with permissions %s\n", filename, mode );
358 
359  //store file name and file opening mode
360  xf = xio_getfptr(rc);
361  if (xf)
362  {
363  //replace filename, if enough space
364  if ( strlen(filename) > strlen(xf->filename) )
365  xf->filename = (char *)xrealloc(xf->filename, strlen(filename)+1 );
366  strcpy(xf->filename, filename);
367 
368  //replace filemode, if enough space
369  if ( strlen(mode) > strlen(xf->mode) )
370  xf->mode = (char *)xrealloc( xf->mode, strlen(mode)+1 );
371  strcpy(xf->mode, mode);
372 
373  xf->lineno = 0;
374  }
375  else
376  {
377  //new file
378  xf = (XFILE *)xmalloc(sizeof(XFILE));
379  xf->filename = (char *)xmalloc(strlen(filename));
380  strcpy(xf->filename, filename);
381  xf->mode = (char *)xmalloc(strlen(mode));
382  strcpy(xf->mode, mode);
383  xf->lineno = 0;
384  Xio::get_instance()->get_xfile_map()[rc] = xf;
385  }
386 
387  XIO_DEBUG( rc );
388 
389  return(rc);
390 }
391 
392 /*!
393  * @brief FPRINTF WITH ERROR HANDLING
394  */
395 int xfprintf( FILE *out, const char *fmt, ... )
396 {
397  va_list argptr;
398  int rc;
399 
400  ASSERT(!( (out == NULL) || (fmt == NULL) ),"NULL pointer as argument of function xfprintf()\n");
401  va_start( argptr, fmt );
402  rc = vfprintf( out, fmt, argptr );
403  va_end( argptr );
404  INPUT_CHECK(!( rc == EOF ),"Cannot write to file %s\n", xio_getfname(out) );
405 
406  return rc;
407 }
408 
409 /*!
410  * @brief FSCANF WITH ERROR HANDLING
411  */
412 int xfscanf( FILE *in, const char *fmt, ... )
413 {
414  va_list argptr;
415  int rc;
416 
417  ASSERT(!( (in == NULL) || (fmt == NULL) ),"NULL pointer as argument of function xfscanf()\n");
418  va_start( argptr , fmt );
419  rc = vfscanf( in, fmt, argptr );
420  va_end( argptr );
421  INPUT_CHECK(!( (rc == EOF) || (rc == 0) ),"Cannot read from file %s\n", xio_getfname(in) );
422 
423  return(rc);
424 }
425 
426 /*!
427  * @brief getc() with error handling and line count
428  * @param[in,out] f pointer to FILE structure
429  * @return same as ISO C getc()
430  */
431 int xgetc( FILE * f )
432 {
433  int rc;
434 
435  ASSERT(!(f == NULL), "NULL file\n");
436 
437  rc = xfgetc( f );
438  XIO_DEBUG( f );
439 
440  return( rc );
441 }
442 
443 /*!
444  * @brief fgetc() with error handling and line count
445  * @param[in,out] f pointer to FILE structure
446  * @return same as ISO C fgetc()
447  */
448 int xfgetc( FILE * f )
449 {
450  int rc;
451  XFILE * xf;
452 
453  ASSERT(!(f == NULL), "NULL file\n");
454 
455  rc = fgetc( f );
456 
457  //update line count
458  xf = xio_getfptr( f );
459  if ( xf )
460  {
461  if ( rc == '\n' )
462  xf->lineno++;
463  }
464  else
465  {
466  XIO_WARN( f );
467  }
468 
469  XIO_DEBUG( f );
470 
471  INPUT_CHECK(!( (rc == EOF) && (!feof(f))),"Cannot read from file '%s'\n", xio_getfname( f ) );
472 
473  return(rc);
474 }
475 
476 /*!
477  * @brief ungetc() with error handling and line count
478  * @param[in] c character to push back
479  * @param[in,out] f pointer to FILE structure with INPUT stream
480  * @return same as ISO C ungetc()
481  */
482 int xungetc( int c, FILE * f )
483 {
484  int rc;
485  XFILE * xf;
486 
487  ASSERT(!(f == NULL), "NULL file\n");
488 
489  rc = ungetc( c, f );
490 
491  //update line count
492  xf = xio_getfptr( f );
493  if ( xf )
494  {
495  if ( ( rc == '\n' ) && ( xf->lineno > 0 ) )
496  xf->lineno--;
497  }
498  else
499  {
500  XIO_WARN( f );
501  }
502 
503  XIO_DEBUG( f );
504 
505  INPUT_CHECK(!(rc == EOF), "Unable to push back character '%c' to file '%s'.\n", c, xio_getfname(f) );
506  return( rc );
507 }
508 
509 /*!
510  * @brief Changes the name of the file or directory specified by oldname to newname
511  * @param[in] oldname name of the file to be renamed and/or moved
512  * @param[in] newname new name
513  * @return same as ISO C rename()
514  */
515 int xrename ( const char * oldname, const char * newname )
516 {
517  int rc;
518 
519  ASSERT(!(( oldname == NULL) || (newname == NULL)), "NULL file name\n");
520 
521  rc = rename( oldname, newname );
522 
523  INPUT_CHECK( rc != 0,"Failed when renaming '%s' to '%s'\n", oldname, newname );
524  return( rc );
525 }
526 
527 /*!
528  * @brief Read block of data from stream, handle errors
529  * @param[out] ptr Pointer to a block of memory with a minimum size of (size*count) bytes.
530  * @param[in] size Size in bytes of each element to be read.
531  * @param[in] count Number of elements, each one with a size of size bytes.
532  * @param[in,out] stream Pointer to a FILE object that specifies an input stream.
533  * @return same as ISO C fread()
534  */
535 size_t xfread( void * ptr, size_t size, size_t count, FILE * stream )
536 {
537  size_t rc;
538 
539  ASSERT(!( (ptr == NULL) || ( stream == NULL) ),"Incorrect arguments\n");
540 
541  rc = fread( ptr, size, count, stream );
542 
543  XIO_DEBUG( stream );
544 
545  INPUT_CHECK(!( (rc != count) && (!feof(stream))),"Cannot read from file '%s'\n", xio_getfname(stream) );
546 
547  return(rc);
548 }
549 
550 /*!
551  * @brief Write block of data to stream, handle errors
552  * @param[in] ptr Pointer to a block of memory with a minimum size of (size*count) bytes.
553  * @param[in] size Size in bytes of each element to be written.
554  * @param[in] count Number of elements, each one with a size of size bytes.
555  * @param[in,out] stream Pointer to a FILE object that specifies an output stream.
556  * @return same as ISO C fwrite()
557  */
558 size_t xfwrite( const void * ptr, size_t size, size_t count, FILE * stream )
559 {
560  size_t rc;
561 
562  ASSERT(!( (ptr == NULL) || (stream == NULL) ),"Incorrect arguments\n");
563 
564  rc = fwrite( ptr, size, count, stream );
565 
566  XIO_DEBUG( stream );
567 
568  INPUT_CHECK(!( (rc != count) ),"Cannot write to file '%s'\n", xio_getfname(stream) );
569 
570  return(rc);
571 }
572 
573 /*!
574  * @brief FGETS WITH ERROR HANDLING and line count
575  * @param[out] s Pointer to an array of chars where the string read is stored
576  * @param[in] n Maximum number of characters to be read (including the final null-character)
577  * @param[in,out] in Pointer to a FILE
578  * @return same as ISO C fgets()
579  */
580 char *xfgets( char *s, int n, FILE *in )
581 {
582  XFILE * xf;
583  char *rc = NULL;
584 
585  ASSERT(!( (s == NULL) || (in == NULL) ),"Incorrect arguments of function xfgets()\n");
586  rc = fgets( s, n, in );
587 
588  //update line count
589  xf = xio_getfptr(in);
590  if ( xf )
591  {
592  //check if complete line is read
593  if ( rc )
594  {
595  char c;
596  c = s[strlen(s)-1];
597  if ( c == '\n' )
598  {
599  xf->lineno++;
600  }
601  }
602  }
603  else
604  {
605  XIO_WARN(in);
606  }
607 
608  XIO_DEBUG( in );
609 
610  INPUT_CHECK(!( (rc == NULL) && (!feof(in))),"Cannot read from file '%s'\n", xio_getfname(in) );
611 
612  return(rc);
613 }
614 
615 /*!
616  * @brief Rewind file, handle line count
617  * @param[in,out] f pointer to FILE structure
618  */
619 void xrewind( FILE * f )
620 {
621  XFILE * xf;
622 
623  ASSERT(!(f == NULL),"NULL file argument in xrewind()\n");
624 
625  xf = xio_getfptr(f);
626  if ( xf )
627  {
628  xf->lineno = 0;
629  }
630  else
631  {
632  XIO_WARN(f);
633  }
634 
635  rewind( f );
636 
637  XIO_DEBUG( f );
638 }
639 
640 /*!
641  * @brief Check END OF FILE
642  * @param[in] f pointer to FILE structure
643  * @return same as ISO C feof()
644  */
645 int xfeof ( FILE * f )
646 {
647  XFILE * xf;
648  int rc;
649 
650  xf = xio_getfptr(f);
651  if ( !xf )
652  {
653  XIO_WARN(f);
654  }
655 
656  rc = feof ( f );
657 
658  XIO_DEBUG( f );
659 
660  return rc;
661 }
int verbosity_
internal XIO debug: print info at each XIO function
Definition: xio.h:100
static Xio * instance
Definition: xio.h:88
char * mode
opening mode
Definition: xio.h:57
Definition: xio.h:69
void set_verbosity(int verb)
Enable/Disable XIO debug output for EACH XIO function call.
Definition: xio.cc:98
int xfflush(FILE *f)
Flush file stream.
Definition: xio.cc:287
void xrewind(FILE *f)
Rewind file, handle line count.
Definition: xio.cc:619
static Xio * get_instance()
return instance
Definition: xio.cc:83
int xrename(const char *oldname, const char *newname)
Changes the name of the file or directory specified by oldname to newname.
Definition: xio.cc:515
int xfclose(FILE *stream)
FCLOSE WITH ERROR HANDLING.
Definition: xio.cc:309
size_t xfwrite(const void *ptr, size_t size, size_t count, FILE *stream)
Write block of data to stream, handle errors.
Definition: xio.cc:558
char * xio_getfname(FILE *f)
Get file name from pointer to FILE structure.
Definition: xio.cc:120
int xgetc(FILE *f)
getc() with error handling and line count
Definition: xio.cc:431
int xfprintf(FILE *out, const char *fmt,...)
FPRINTF WITH ERROR HANDLING.
Definition: xio.cc:395
char * xfgets(char *s, int n, FILE *in)
FGETS WITH ERROR HANDLING and line count.
Definition: xio.cc:580
size_t xfread(void *ptr, size_t size, size_t count, FILE *stream)
Read block of data from stream, handle errors.
Definition: xio.cc:535
int xio_getlinesread(FILE *f)
Get number of lines that were completely read from file since fopen() or rewind() ...
Definition: xio.cc:166
XFILEMAP & get_xfile_map()
Get XIO mapping instance.
Definition: xio.cc:108
FILE * xfreopen(const char *filename, const char *mode, FILE *stream)
Reopen stream with different file or mode.
Definition: xio.cc:348
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
Definition: system.hh:72
void * xrealloc(void *ptr, size_t size)
Reallocation of memory block with checking.
Definition: system.cc:243
static XFILE xstderr
Definition: xio.cc:59
#define ASSERT(...)
Definition: global_defs.h:121
Definition: system.hh:72
char * xio_getfmode(FILE *f)
Get file mode from file stream.
Definition: xio.cc:143
#define XIO_WARN(f)
Definition: xio.cc:64
XFILE structure holds additional info to generic FILE.
Definition: xio.h:55
char * xio_getfulldescription(FILE *f)
Get pointer to string with full file description.
Definition: xio.cc:189
#define xprintf(...)
Definition: system.hh:100
#define LINE_SIZE
Definition: xio.h:51
static XFILE xstdin
basic definitions
Definition: xio.cc:57
void * xmalloc(size_t size)
Memory allocation with checking.
Definition: system.cc:209
#define INPUT_CHECK(i,...)
Debugging macros.
Definition: global_defs.h:61
int lineno
last read line (only for text files)
Definition: xio.h:58
int xfgetc(FILE *f)
fgetc() with error handling and line count
Definition: xio.cc:448
char * filename
file name in the time of opening
Definition: xio.h:56
#define xfree(p)
Definition: system.hh:108
#define XIO_DEBUG(f)
Definition: xio.cc:66
int xfeof(FILE *f)
Check END OF FILE.
Definition: xio.cc:645
int get_verbosity()
Get current XIO debug verbosity level.
Definition: xio.cc:103
static XFILE xstdout
Definition: xio.cc:58
int xungetc(int c, FILE *f)
ungetc() with error handling and line count
Definition: xio.cc:482
int xfscanf(FILE *in, const char *fmt,...)
FSCANF WITH ERROR HANDLING.
Definition: xio.cc:412
static XFILE * xio_getfptr(FILE *f)
Internal XIO locator.
Definition: xio.cc:234
static void init()
initialize XIO library
Definition: xio.cc:89
XFILEMAP xfiles_map_
mapping instance
Definition: xio.h:98
Xio()
Definition: xio.cc:75
FILE * xfopen(const std::string &fname, const char *mode)
Definition: xio.cc:246