Fix for UBSan build
[platform/upstream/doxygen.git] / qtools / qfile.cpp
1 /****************************************************************************
2 ** 
3 **
4 ** Implementation of QFile class
5 **
6 ** Created : 930812
7 **
8 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
9 **
10 ** This file is part of the tools module of the Qt GUI Toolkit.
11 **
12 ** This file may be distributed under the terms of the Q Public License
13 ** as defined by Trolltech AS of Norway and appearing in the file
14 ** LICENSE.QPL included in the packaging of this file.
15 **
16 ** This file may be distributed and/or modified under the terms of the
17 ** GNU General Public License version 2 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.GPL included in the
19 ** packaging of this file.
20 **
21 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22 ** licenses may use this file in accordance with the Qt Commercial License
23 ** Agreement provided with the Software.
24 **
25 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 **
28 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29 **   information about Qt Commercial License Agreements.
30 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
31 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
32 **
33 ** Contact info@trolltech.com if any conditions of this licensing are
34 ** not clear to you.
35 **
36 **********************************************************************/
37
38 #include "qglobal.h"
39 #if defined(_OS_WIN32_)
40 #ifdef UNICODE
41 #ifndef _UNICODE
42 #define _UNICODE
43 #endif
44 #endif
45 #endif
46
47 #include "qfile.h"
48 #include "qfiledefs_p.h"
49
50 extern bool qt_file_access( const QString& fn, int t );
51
52 // NOT REVISED
53 /*!
54   \class QFile qfile.h
55   \brief The QFile class is an I/O device that operates on files.
56
57   \ingroup io
58
59   QFile is an I/O device for reading and writing binary and text files. A
60   QFile may be used by itself (readBlock and writeBlock) or by more
61   conveniently using QDataStream or QTextStream.
62
63   Here is a code fragment that uses QTextStream to read a text
64   file line by line. It prints each line with a line number.
65   \code
66     QFile f("file.txt");
67     if ( f.open(IO_ReadOnly) ) {    // file opened successfully
68         QTextStream t( &f );        // use a text stream
69         QString s;
70         int n = 1;
71         while ( !t.eof() ) {        // until end of file...
72             s = t.readLine();       // line of text excluding '\n'
73             printf( "%3d: %s\n", n++, (const char *)s );
74         }
75         f.close();
76     }
77   \endcode
78
79   The QFileInfo class holds detailed information about a file, such as
80   access permissions, file dates and file types.
81
82   The QDir class manages directories and lists of file names.
83
84   \sa QDataStream, QTextStream
85 */
86
87
88 /*!
89   Constructs a QFile with no name.
90 */
91
92 QFile::QFile()
93 {
94     init();
95 }
96
97 /*!
98   Constructs a QFile with a file name \e name.
99   \sa setName()
100 */
101
102 QFile::QFile( const QString &name )
103     : fn(name)
104 {
105     init();
106 }
107
108
109 /*!
110   Destructs a QFile.  Calls close().
111 */
112
113 QFile::~QFile()
114 {
115     close();
116 }
117
118
119 /*!
120   \internal
121   Initialize internal data.
122 */
123
124 void QFile::init()
125 {
126     setFlags( IO_Direct );
127     setStatus( IO_Ok );
128     fh     = 0;
129     fd     = 0;
130     length = 0;
131     ioIndex = 0;
132     ext_f  = FALSE;                             // not an external file handle
133 }
134
135
136 /*!
137   \fn QString QFile::name() const
138   Returns the name set by setName().
139   \sa setName(), QFileInfo::fileName()
140 */
141
142 /*!
143   Sets the name of the file. The name can include an absolute directory
144   path or it can be a name or a path relative to the current directory.
145
146   Do not call this function if the file has already been opened.
147
148   Note that if the name is relative QFile does not associate it with the
149   current directory.  If you change directory before calling open(), open
150   uses the new current directory.
151
152   Example:
153   \code
154      QFile f;
155      QDir::setCurrent( "/tmp" );
156      f.setName( "readme.txt" );
157      QDir::setCurrent( "/home" );
158      f.open( IO_ReadOnly );        // opens "/home/readme.txt" under UNIX
159   \endcode
160
161   Also note that the directory separator '/' works for all operating
162   systems supported by Qt.
163
164   \sa name(), QFileInfo, QDir
165 */
166
167 void QFile::setName( const QString &name )
168 {
169     if ( isOpen() ) {
170 #if defined(CHECK_STATE)
171         qWarning( "QFile::setName: File is open" );
172 #endif
173         close();
174     }
175     fn = name;
176 }
177
178 /*!
179   Returns TRUE if this file exists, otherwise FALSE.
180   \sa name()
181 */
182
183 bool QFile::exists() const
184 {
185     return qt_file_access( fn, F_OK );
186 }
187
188 /*!
189   Returns TRUE if the file given by \e fileName exists, otherwise FALSE.
190 */
191
192 bool QFile::exists( const QString &fileName )
193 {
194     return qt_file_access( fileName, F_OK );
195 }
196
197
198 /*!
199   Removes the file specified by the file name currently set.
200   Returns TRUE if successful, otherwise FALSE.
201
202   The file is closed before it is removed.
203 */
204
205 bool QFile::remove()
206 {
207     close();
208     return remove( fn );
209 }
210
211 #if defined(_OS_MAC_) || defined(_OS_MSDOS_) || defined(_OS_WIN32_) || defined(_OS_OS2_) || defined(_OS_CYGWIN_)
212 # define HAS_TEXT_FILEMODE                      // has translate/text filemode
213 #endif
214 #if defined(O_NONBLOCK)
215 # define HAS_ASYNC_FILEMODE
216 # define OPEN_ASYNC O_NONBLOCK
217 #elif defined(O_NDELAY)
218 # define HAS_ASYNC_FILEMODE
219 # define OPEN_ASYNC O_NDELAY
220 #endif
221
222 /*!
223   Flushes the file buffer to the disk.
224
225   close() also flushes the file buffer.
226 */
227
228 void QFile::flush()
229 {
230     if ( isOpen() && fh )                       // can only flush open/buffered
231         fflush( fh );                           //   file
232 }
233
234 /*!
235   Returns TRUE if the end of file has been reached, otherwise FALSE.
236   \sa size()
237 */
238
239 bool QFile::atEnd() const
240 {
241     if ( !isOpen() ) {
242 #if defined(CHECK_STATE)
243         qWarning( "QFile::atEnd: File is not open" );
244 #endif
245         return FALSE;
246     }
247     if ( isDirectAccess() && !isTranslated() ) {
248         if ( at() < length )
249             return FALSE;
250     }
251     return QIODevice::atEnd();
252 }
253
254 /*!
255   Reads a line of text.
256
257   Reads bytes from the file until end-of-line is reached, or up to \a
258   maxlen bytes, and returns the number of bytes read, or -1 in case of
259   error.  The terminating newline is not stripped.
260
261   This function is efficient only for buffered files.  Avoid
262   readLine() for files that have been opened with the \c IO_Raw
263   flag.
264
265   \sa readBlock(), QTextStream::readLine()
266 */
267
268 int QFile::readLine( char *p, uint maxlen )
269 {
270     if ( maxlen == 0 )                          // application bug?
271         return 0;
272 #if defined(CHECK_STATE)
273     CHECK_PTR( p );
274     if ( !isOpen() ) {                          // file not open
275         qWarning( "QFile::readLine: File not open" );
276         return -1;
277     }
278     if ( !isReadable() ) {                      // reading not permitted
279         qWarning( "QFile::readLine: Read operation not permitted" );
280         return -1;
281     }
282 #endif
283     int nread;                                  // number of bytes read
284     if ( isRaw() ) {                            // raw file
285         nread = QIODevice::readLine( p, maxlen );
286     } else {                                    // buffered file
287         p = fgets( p, maxlen, fh );
288         if ( p ) {
289             nread = qstrlen( p );
290             ioIndex += nread;
291         } else {
292             nread = -1;
293             setStatus(IO_ReadError);
294         }
295     }
296     return nread;
297 }
298
299
300 /*!
301   Reads a line of text.
302
303   Reads bytes from the file until end-of-line is reached, or up to \a
304   maxlen bytes, and returns the number of bytes read, or -1 in case of
305   error.  The terminating newline is not stripped.
306
307   This function is efficient only for buffered files.  Avoid
308   readLine() for files that have been opened with the \c IO_Raw
309   flag.
310
311   Note that the string is read as plain Latin1 bytes, not Unicode.
312
313   \sa readBlock(), QTextStream::readLine()
314 */
315
316 int QFile::readLine( QString& s, uint maxlen )
317 {
318     QByteArray ba(maxlen);
319     int l = readLine(ba.data(),maxlen);
320     if ( l >= 0 ) {
321         ba.truncate(l);
322         s = QString(ba);
323     }
324     return l;
325 }
326
327
328 /*!
329   Reads a single byte/character from the file.
330
331   Returns the byte/character read, or -1 if the end of the file has been
332   reached.
333
334   \sa putch(), ungetch()
335 */
336
337 int QFile::getch()
338 {
339 #if defined(CHECK_STATE)
340     if ( !isOpen() ) {                          // file not open
341         qWarning( "QFile::getch: File not open" );
342         return EOF;
343     }
344     if ( !isReadable() ) {                      // reading not permitted
345         qWarning( "QFile::getch: Read operation not permitted" );
346         return EOF;
347     }
348 #endif
349
350     int ch;
351
352     if ( !ungetchBuffer.isEmpty() ) {
353         int len = ungetchBuffer.length();
354         ch = ungetchBuffer[ len-1 ];
355         ungetchBuffer.truncate( len - 1 );
356         return ch;
357     }
358
359     if ( isRaw() ) {                            // raw file (inefficient)
360         char buf[1];
361         ch = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
362     } else {                                    // buffered file
363         if ( (ch = getc( fh )) != EOF )
364             ioIndex++;
365         else
366             setStatus(IO_ReadError);
367     }
368     return ch;
369 }
370
371 /*!
372   \fn int QFile::writeBlock( const QByteArray& data )
373   \reimp
374   \internal
375   Should be removed in 3.0
376 */
377
378 /*!
379   Writes the character \e ch to the file.
380
381   Returns \e ch, or -1 if some error occurred.
382
383   \sa getch(), ungetch()
384 */
385
386 int QFile::putch( int ch )
387 {
388 #if defined(CHECK_STATE)
389     if ( !isOpen() ) {                          // file not open
390         qWarning( "QFile::putch: File not open" );
391         return EOF;
392     }
393     if ( !isWritable() ) {                      // writing not permitted
394         qWarning( "QFile::putch: Write operation not permitted" );
395         return EOF;
396     }
397 #endif
398     if ( isRaw() ) {                            // raw file (inefficient)
399         char buf[1];
400         buf[0] = ch;
401         ch = writeBlock( buf, 1 ) == 1 ? ch : EOF;
402     } else {                                    // buffered file
403         if ( (ch = putc( ch, fh )) != EOF ) {
404             ioIndex++;
405             if ( ioIndex > length )             // update file length
406                 length = ioIndex;
407         } else {
408             setStatus(IO_WriteError);
409         }
410     }
411     return ch;
412 }
413
414 /*!
415   Puts the character \e ch back into the file and decrements the index if it
416   is not zero.
417
418   This function is normally called to "undo" a getch() operation.
419
420   Returns \e ch, or -1 if some error occurred.
421
422   \sa getch(), putch()
423 */
424
425 int QFile::ungetch( int ch )
426 {
427 #if defined(CHECK_STATE)
428     if ( !isOpen() ) {                          // file not open
429         qWarning( "QFile::ungetch: File not open" );
430         return EOF;
431     }
432     if ( !isReadable() ) {                      // reading not permitted
433         qWarning( "QFile::ungetch: Read operation not permitted" );
434         return EOF;
435     }
436 #endif
437     if ( ch == EOF )                            // cannot unget EOF
438         return ch;
439
440     if ( isSequentialAccess() && !fh) {
441         // pipe or similar => we cannot ungetch, so do it manually
442         ungetchBuffer +=ch;
443         return ch;
444     }
445
446     if ( isRaw() ) {                            // raw file (very inefficient)
447         char buf[1];
448         at( ioIndex-1 );
449         buf[0] = ch;
450         if ( writeBlock(buf, 1) == 1 )
451             at ( ioIndex-1 );
452         else
453             ch = EOF;
454     } else {                                    // buffered file
455         if ( (ch = ungetc(ch, fh)) != EOF )
456             ioIndex--;
457         else
458             setStatus( IO_ReadError );
459     }
460     return ch;
461 }
462
463
464 static QCString locale_encoder( const QString &fileName )
465 {
466     return fileName.local8Bit();
467 }
468
469
470 static QFile::EncoderFn encoder = locale_encoder;
471
472 /*!
473   When you use QFile, QFileInfo, and QDir to access the filesystem
474   with Qt, you can use Unicode filenames.  On Unix, these filenames
475   are converted to an 8-bit encoding.  If you want to do your own
476   file I/O on Unix, you should convert the filename using this
477   function.  On Windows NT, Unicode filenames are supported directly
478   in the filesystem and this function should be avoided. On Windows 95,
479   non-Latin1 locales are not supported at this time.
480
481   By default, this function converts to the local 8-bit encoding
482   determined by the user's locale.  This is sufficient for
483   filenames that the user chooses.  Filenames hard-coded into the
484   application should only use 7-bit ASCII filename characters.
485
486   The conversion scheme can be changed using setEncodingFunction().
487   This might be useful if you wish to give the user an option to
488   store in filenames in UTF-8, etc., but beware that such filenames
489   would probably then be unrecognizable when seen by other programs.
490
491   \sa decodeName()
492 */
493
494 QCString QFile::encodeName( const QString &fileName )
495 {
496     return (*encoder)(fileName);
497 }
498
499 /*!
500   \enum QFile::EncoderFn
501
502   This is used by QFile::setEncodingFunction().
503 */
504
505 /*!
506   Sets the function for encoding Unicode filenames.
507   The default encodes in the locale-specific 8-bit encoding.
508
509   \sa encodeName()
510 */
511 void QFile::setEncodingFunction( EncoderFn f )
512 {
513     encoder = f;
514 }
515
516 static
517 QString locale_decoder( const QCString &localFileName )
518 {
519     return QString::fromLocal8Bit(localFileName);
520 }
521
522 static QFile::DecoderFn decoder = locale_decoder;
523
524 /*!
525   This does the reverse of QFile::encodeName().
526
527   \sa setDecodingFunction()
528 */
529 QString QFile::decodeName( const QCString &localFileName )
530 {
531     return (*decoder)(localFileName);
532 }
533
534 /*!
535   \enum QFile::DecoderFn
536
537   This is used by QFile::setDecodingFunction().
538 */
539
540 /*!
541   Sets the function for decoding 8-bit filenames.
542   The default uses the locale-specific 8-bit encoding.
543
544   \sa encodeName(), decodeName()
545 */
546
547 void QFile::setDecodingFunction( DecoderFn f )
548 {
549     decoder = f;
550 }