📄 stream.cxx
字号:
//========================================================================
//
// stream.cxx
//
// Implementations of internal C library stdio stream functions
//
//========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jlarmour
// Contributors:
// Date: 2000-04-20
// Purpose:
// Description:
// Usage:
//
//####DESCRIPTIONEND####
//
//========================================================================
// CONFIGURATION
#include <pkgconf/libc_stdio.h> // Configuration header
// INCLUDES
#include <cyg/infra/cyg_type.h> // Common project-wide type definitions
#include <cyg/infra/cyg_ass.h> // Assertion infrastructure
#include <stddef.h> // NULL and size_t from compiler
#include <errno.h> // Error codes
#include <string.h> // memcpy() and memset()
#include <cyg/libc/stdio/stream.hxx> // Header for this file
#include <cyg/libc/stdio/stdiosupp.hxx> // Stdio support functions
#include <cyg/libc/stdio/io.inl> // I/O system inlines
// FUNCTIONS
Cyg_StdioStream::Cyg_StdioStream(cyg_stdio_handle_t dev,
OpenMode open_mode,
cyg_bool append, cyg_bool binary,
int buffer_mode, cyg_ucount32 buffer_size,
cyg_uint8 *buffer_addr )
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
: io_buf( buffer_size, buffer_addr )
#endif
{
initialize( dev, open_mode, append, binary, buffer_mode,
buffer_size, buffer_addr);
}
void Cyg_StdioStream::initialize(cyg_stdio_handle_t dev,
OpenMode open_mode,
cyg_bool append, cyg_bool binary,
int buffer_mode, cyg_ucount32 buffer_size,
cyg_uint8 *buffer_addr )
{
#ifdef CYGDBG_USE_ASSERTS
magic_validity_word = 0xbadbad;
#endif
my_device = dev;
// Clear all flags
memset( &flags, 0, sizeof(flags) );
switch (open_mode) {
case CYG_STREAM_READ:
flags.opened_for_read = true;
break;
case CYG_STREAM_WRITE:
flags.opened_for_write = true;
break;
case CYG_STREAM_READWRITE_NOCREATE:
case CYG_STREAM_READWRITE_CREATE:
flags.opened_for_read = true;
flags.opened_for_write = true;
break;
default:
error=EINVAL;
return;
} // switch
if (flags.opened_for_write) {
#if 0
// FIXME: need some replacement for this
if (!my_device->write_blocking) {
error = EDEVNOSUPP;
return;
} // if
#endif
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
flags.last_buffer_op_was_read = false;
#endif
} // if
if (flags.opened_for_read) {
#if 0
// FIXME: need some replacement for this
if (!my_device->read_blocking) {
error = EDEVNOSUPP;
return;
} // if
#endif
// NB also if opened for read AND write, then say last op was read
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
flags.last_buffer_op_was_read = true;
#endif
} // if
flags.binary = binary ? 1 : 0;
error = ENOERR;
// in due course we would do an equivalent to fseek(...,0, SEEK_END);
// when appending. for now, there's nothing, except set eof
flags.at_eof = append ? 1 : 0;
position = 0;
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
switch (buffer_mode) {
case _IONBF:
CYG_ASSERT( (buffer_size == 0) && (buffer_addr == NULL),
"No buffering wanted but size/address specified!" );
flags.buffering = flags.line_buffering = false;
break;
case _IOLBF:
flags.buffering = true;
flags.line_buffering = true;
break;
case _IOFBF:
flags.buffering = true;
flags.line_buffering = false;
break;
default:
error = EINVAL;
return;
} // switch
// one way of checking the buffer was set up correctly
if (flags.buffering && io_buf.get_buffer_size()==-1) {
error = ENOMEM;
return;
}
#endif
#if 0 // FIXME - Need to set binary mode.
if (my_device->open) {
error = (*my_device->open)( my_device->cookie,
binary ? CYG_DEVICE_OPEN_MODE_RAW
: CYG_DEVICE_OPEN_MODE_TEXT );
if (error != ENOERR)
return; // keep error code the same
} // if
#endif
#ifdef CYGDBG_USE_ASSERTS
magic_validity_word = 0x7b4321ce;
#endif
} // Cyg_StdioStream constructor
Cyg_StdioStream::Cyg_StdioStream( OpenMode open_mode,
cyg_ucount32 buffer_size,
cyg_uint8 *buffer_addr )
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
: io_buf( buffer_size, buffer_addr )
#endif
{
initialize( CYG_STDIO_HANDLE_NULL, open_mode, false, false, _IOFBF,
buffer_size, buffer_addr );
if( error != ENOERR )
return;
switch( open_mode )
{
case CYG_STREAM_READ:
// Fix up the stream so it looks like the buffer contents has just
// been read in.
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
io_buf.set_bytes_written( buffer_size );
#endif
break;
case CYG_STREAM_WRITE:
// Fix up the stream so it looks like the buffer is ready to accept
// new data.
break;
default:
error = EINVAL;
return;
}
}
Cyg_ErrNo
Cyg_StdioStream::refill_read_buffer( void )
{
Cyg_ErrNo read_err;
cyg_uint8 *buffer;
cyg_uint32 len;
CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
if (!lock_me())
return EBADF; // assume file is now invalid
// first just check that we _can_ read this device!
if (!flags.opened_for_read) {
unlock_me();
return EINVAL;
}
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
// If there is pending output to write, then this will check and
// write it
if (flags.buffering) {
read_err = flush_output_unlocked();
// we're now reading
flags.last_buffer_op_was_read = true;
// flush ALL streams
if (read_err == ENOERR)
read_err = cyg_libc_stdio_flush_all_but(this);
if (read_err != ENOERR) {
unlock_me();
return read_err;
} // if
len = io_buf.get_buffer_addr_to_write( (cyg_uint8**)&buffer );
if (!len) { // no buffer space available
unlock_me();
return ENOERR; // isn't an error, just needs user to read out data
} // if
}
else
#endif
if (!flags.readbuf_char_in_use) {
len = 1;
buffer = &readbuf_char;
}
else {
// no buffer space available
unlock_me();
return ENOERR; // isn't an error, just needs user to read out data
} // else
read_err = cyg_stdio_read(my_device, buffer, &len);
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
if (flags.buffering)
io_buf.set_bytes_written( len );
else
#endif
flags.readbuf_char_in_use = len ? 1 : 0;
unlock_me();
if (read_err == ENOERR) {
if (len == 0) {
read_err = EAGAIN;
flags.at_eof = true;
}
else
flags.at_eof = false;
} // if
return read_err;
} // refill_read_buffer()
Cyg_ErrNo
Cyg_StdioStream::read( cyg_uint8 *user_buffer, cyg_ucount32 buffer_length,
cyg_ucount32 *bytes_read )
{
CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
*bytes_read = 0;
if (!lock_me())
return EBADF; // assume file is now invalid
if (!flags.opened_for_read) {
unlock_me();
return EINVAL;
}
#ifdef CYGFUN_LIBC_STDIO_ungetc
if (flags.unread_char_buf_in_use && buffer_length) {
*user_buffer++ = unread_char_buf;
++*bytes_read;
flags.unread_char_buf_in_use = false;
--buffer_length;
} // if
#endif // ifdef CYGFUN_LIBC_STDIO_ungetc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -