1 #ifndef CYGONCE_LIBC_STDIO_STREAM_INL
2 #define CYGONCE_LIBC_STDIO_STREAM_INL
3 //========================================================================
7 // Inline functions for internal C library stdio stream interface
9 //========================================================================
10 //####ECOSGPLCOPYRIGHTBEGIN####
11 // -------------------------------------------
12 // This file is part of eCos, the Embedded Configurable Operating System.
13 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //========================================================================
43 //#####DESCRIPTIONBEGIN####
45 // Author(s): jlarmour
50 // Usage: Do not include this file -
51 // #include <cyg/libc/stdio/stream.hxx> instead.
53 //####DESCRIPTIONEND####
55 //========================================================================
59 #include <pkgconf/libc_stdio.h> // Configuration header
63 #include <cyg/infra/cyg_type.h> // Common project-wide type definitions
64 #include <stddef.h> // NULL and size_t from compiler
65 #include <errno.h> // Error codes
66 #include <cyg/libc/stdio/stream.hxx> // Just be sure that this really is
69 #include <cyg/libc/stdio/io.inl> // I/O system inlines
73 #ifdef CYGDBG_USE_ASSERTS
75 Cyg_StdioStream::check_this( cyg_assert_class_zeal zeal ) const
77 // check that it has the magic word set meaning it is valid.
78 if ( magic_validity_word != 0x7b4321ce )
83 #endif // ifdef CYGDBG_USE_ASSERTS
89 // returns true on success
91 Cyg_StdioStream::lock_me( void )
93 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
95 #ifdef CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
96 return stream_lock.lock();
98 // otherwise it "worked"
105 // returns true on success
107 Cyg_StdioStream::trylock_me( void )
109 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
111 #ifdef CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
112 return stream_lock.trylock();
114 // otherwise it "worked"
122 Cyg_StdioStream::unlock_me( void )
124 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
126 #ifdef CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
127 stream_lock.unlock();
135 Cyg_StdioStream::close()
137 Cyg_ErrNo err = ENOERR;
142 if( my_device != CYG_STDIO_HANDLE_NULL )
144 flush_output_unlocked();
146 err = cyg_stdio_close( my_device );
149 my_device = CYG_STDIO_HANDLE_NULL;
158 Cyg_StdioStream::~Cyg_StdioStream()
160 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
162 // Close the device if it has not already been closed.
163 if( my_device != CYG_STDIO_HANDLE_NULL )
166 #ifdef CYGDBG_USE_ASSERTS
167 magic_validity_word = 0xbadbad;
169 } // Cyg_StdioStream destructor
175 // this is currently just a wrapper around write, but having this interface
176 // leaves scope for optimisations in future
178 Cyg_StdioStream::write_byte( cyg_uint8 c )
180 cyg_ucount32 dummy_bytes_written;
183 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
185 err = write( &c, 1, &dummy_bytes_written );
187 CYG_ASSERT( (err!=ENOERR) || (dummy_bytes_written==1),
188 "Single byte not written, but no error returned!" );
195 Cyg_StdioStream::unread_byte( cyg_uint8 c )
197 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
199 #ifdef CYGFUN_LIBC_STDIO_ungetc
201 return EBADF; // assume file is now invalid
203 if (flags.unread_char_buf_in_use) {
208 flags.unread_char_buf_in_use = true;
211 // can't be at EOF any more
212 flags.at_eof = false;
214 if (position) // position is always 0 for certain devices
221 #else // ifdef CYGFUN_LIBC_STDIO_ungetc
224 #endif // ifdef CYGFUN_LIBC_STDIO_ungetc
229 Cyg_StdioStream::bytes_available_to_read( void )
231 cyg_ucount32 bytes=0;
233 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
235 #ifdef CYGFUN_LIBC_STDIO_ungetc
236 if (flags.unread_char_buf_in_use)
240 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
242 // either the last operation was a read, which attempted to read bytes
243 // into the buffer, or there are no bytes in the buffer
245 if (flags.buffering) {
246 if (flags.last_buffer_op_was_read == true)
247 bytes += io_buf.get_buffer_space_used();
253 if (flags.readbuf_char_in_use)
257 } // bytes_available_to_read()
262 Cyg_StdioStream::flush_output( void )
266 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
269 return EBADF; // assume file is now invalid
271 err = flush_output_unlocked();
279 // get error status for this file
281 Cyg_StdioStream::get_error( void )
285 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
288 return EBADF; // well, we've certainly got an error now!
298 // set error status for this file
300 Cyg_StdioStream::set_error( Cyg_ErrNo errno_to_set )
302 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
306 errno = EBADF; // best we can do - we can't trust error to be there
310 errno = error = errno_to_set;
319 // are we at EOF? true means we are, false means no
321 Cyg_StdioStream::get_eof_state( void )
325 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
328 return false; // not much we can do here
330 eof_temp = flags.at_eof;
338 // Set whether we are at EOF.
340 Cyg_StdioStream::set_eof_state( cyg_bool eof_to_set )
342 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
345 return; // not much we can do here
347 flags.at_eof = eof_to_set;
355 Cyg_StdioStream::get_position( fpos_t *pos )
357 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
360 return EBADF; // assume file is now invalid
371 // set absolute position
373 Cyg_StdioStream::set_position( fpos_t pos, int whence )
375 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
377 #ifndef CYGPKG_LIBC_STDIO_FILEIO
378 // this is currently a workaround until we have real files
379 // this will be corrected when we decide the true filesystem interface
384 if ((whence != SEEK_CUR) || pos < 0)
388 return EBADF; // assume file is now invalid
392 for ( ; pos > 0 ; pos-- ) {
393 err = read_byte( &c );
395 err=refill_read_buffer();
397 // if read_byte retured error, or refill_read_buffer returned error
411 return EBADF; // assume file is now invalid
413 if ( whence != SEEK_END ) {
414 off_t bytesavail = (off_t)bytes_available_to_read();
415 off_t abspos = (whence == SEEK_CUR) ? position + pos : pos;
416 off_t posdiff = abspos - position;
418 if ( posdiff >= 0 && bytesavail > posdiff ) {
419 // can just "seek" within the existing buffer
420 #ifdef CYGFUN_LIBC_STDIO_ungetc
421 if (posdiff>0 && flags.unread_char_buf_in_use) {
422 flags.unread_char_buf_in_use = false;
426 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
427 if (posdiff>0 && flags.buffering) {
428 io_buf.set_bytes_read(posdiff);
432 if (posdiff>0 && flags.readbuf_char_in_use) {
433 flags.readbuf_char_in_use = false;
436 CYG_ASSERT(posdiff==0, "Failed to seek within buffer correctly");
441 } // endif (bytesavail > posdiff)
443 if (whence == SEEK_CUR) {
444 position += bytesavail;
446 } //endif (whence != SEEK_END)
450 // Flush output if any present.
451 err = flush_output_unlocked();
457 // Clear any input out of input buffer and any ungot chars
458 // from unread buffer.
459 io_buf.drain_buffer();
461 #ifdef CYGFUN_LIBC_STDIO_ungetc
462 flags.unread_char_buf_in_use = false;
465 // Clear EOF indicator.
466 flags.at_eof = false;
468 // Seek the file to the correct place
469 err = cyg_stdio_lseek( my_device, &newpos, whence );
471 if ( err == ENOERR) {
485 #endif // CYGONCE_LIBC_STDIO_STREAM_INL multiple inclusion protection