9
0
Fork 0

Implemented line-oriented buffering for std output

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3606 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2011-05-14 15:21:04 +00:00
parent e1b9c993a6
commit 4abb53793d
15 changed files with 214 additions and 24 deletions

View File

@ -1752,3 +1752,10 @@
information about RGMP.
* lib/stdio/lib_fclose.c: Must flush all buffered data when the file is closed.
Instead, it was discarding the buffered data.
* lib/stdio: All output stream logic was modified to support CONFIG_STDIO_LINEBUFFER.
If standard C buffered I/O is enabled (CONFIG_STDIO_BUFFER_SIZE > 0), then this
option may be added to force automatic, line-oriented flushing the output buffer
for printf() fprintf(), and vfprintf(). When a newline is encountered in the
format string, the output buffer will be flushed. This (slightly) increases
the NuttX footprint but supports the kind of behavior that people expect for
printf.

View File

@ -3413,6 +3413,13 @@ build
<code>CONFIG_STDIO_BUFFER_SIZE</code>: Size of the buffer to allocate
on fopen. (Only if CONFIG_NFILE_STREAMS > 0)
</li>
<li>
<code>CONFIG_STDIO_LINEBUFFER</code>:
If standard C buffered I/O is enabled (<code>CONFIG_STDIO_BUFFER_SIZE</code> > 0),
then this option may be added to force automatic, line-oriented flushing the output buffer
for <code>printf()</code> >, <code>fprintf()</code> >, and <code>vfprintf()</code> >.
When a newline character is encountered in the format string, the output buffer will be flushed.
This (slightly) increases the NuttX footprint but supports the kind of behavior that people expect for printf.
<li>
<code>CONFIG_NUNGET_CHARS</code>: Number of characters that can be
buffered by ungetc() (Only if CONFIG_NFILE_STREAMS > 0)

View File

@ -503,6 +503,13 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_NAME_MAX - The maximum size of a file name.
CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate
on fopen. (Only if CONFIG_NFILE_STREAMS > 0)
CONFIG_STDIO_LINEBUFFER - If standard C buffered I/O is enabled
(CONFIG_STDIO_BUFFER_SIZE > 0), then this option may be added
to force automatic, line-oriented flushing the output buffer
for printf() fprintf(), and vfprintf(). When a newline is
encountered in the format string, the output buffer will be
flushed. This (slightly) increases the NuttX footprint but
supports the kind of behavior that people expect for printf.
CONFIG_NUNGET_CHARS - Number of characters that can be
buffered by ungetc() (Only if CONFIG_NFILE_STREAMS > 0)
CONFIG_PREALLOC_MQ_MSGS - The number of pre-allocated message

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/streams.h
*
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@ -56,20 +56,24 @@
struct lib_instream_s;
struct lib_outstream_s;
typedef int (*lib_getc_t)(FAR struct lib_instream_s *this);
typedef int (*lib_getc_t)(FAR struct lib_instream_s *this);
typedef void (*lib_putc_t)(FAR struct lib_outstream_s *this, int ch);
typedef int (*lib_flush_t)(FAR struct lib_outstream_s *this);
struct lib_instream_s
{
lib_getc_t get; /* Pointer to function to get one character */
int nget; /* Total number of characters gotten. Written
lib_getc_t get; /* Pointer to function to get one character */
int nget; /* Total number of characters gotten. Written
* by get method, readable by user */
};
struct lib_outstream_s
{
lib_putc_t put; /* Pointer to function to put one character */
int nput; /* Total number of characters put. Written
lib_putc_t put; /* Pointer to function to put one character */
#ifdef CONFIG_STDIO_LINEBUFFER
lib_flush_t flush; /* Pointer to function flush buffered characters */
#endif
int nput; /* Total number of characters put. Written
* by put method, readable by user */
};

View File

@ -110,10 +110,16 @@ extern void stream_semtake(FAR struct streamlist *list);
extern void stream_semgive(FAR struct streamlist *list);
#endif
/* Defined in lib_libnoflush.c */
#ifdef CONFIG_STDIO_LINEBUFFER
extern int lib_noflush(FAR struct lib_outstream_s *this);
#endif
/* Defined in lib_libsprintf.c */
extern int lib_sprintf (FAR struct lib_outstream_s *obj,
const char *fmt, ...);
extern int lib_sprintf(FAR struct lib_outstream_s *obj,
const char *fmt, ...);
/* Defined lib_libvsprintf.c */

View File

@ -51,6 +51,11 @@ STDIO_SRCS += lib_fopen.c lib_fclose.c lib_fread.c lib_libfread.c lib_fseek.c \
lib_fprintf.c lib_vfprintf.c lib_stdinstream.c lib_stdoutstream.c
endif
endif
ifeq ($(CONFIG_LIBC_FLOATINGPOINT),y)
STDIO_SRCS += lib_dtoa.c
endif
ifeq ($(CONFIG_STDIO_LINEBUFFER),y)
STDIO_SRCS += lib_libnoflush.c
endif

View File

@ -0,0 +1,103 @@
/****************************************************************************
* lib/stdio/lib_libnoflush.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <nuttx/fs.h>
#include "lib_internal.h"
#ifdef CONFIG_STDIO_LINEBUFFER
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Global Constant Data
****************************************************************************/
/****************************************************************************
* Global Variables
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: lib_noflush
*
* Description:
* lib_noflush() provides a common, dummy flush method for output streams
* that are not flushable. Only used if CONFIG_STDIO_LINEBUFFER is selected.
*
* Return:
* Always returns OK
*
****************************************************************************/
int lib_noflush(FAR struct lib_outstream_s *this)
{
return OK;
}
#endif /* CONFIG_STDIO_LINEBUFFER */

View File

@ -1127,7 +1127,20 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
if (*src != '%')
{
/* Output the character */
obj->put(obj, *src);
/* Flush the buffer if a newline is encountered */
#ifdef CONFIG_STDIO_LINEBUFFER
if (*src == '\n')
{
(void)obj->flush(obj);
}
#endif
/* Process the next character in the format */
continue;
}

View File

@ -55,7 +55,7 @@
* Name: lowinstream_getc
****************************************************************************/
static int lowinstream_getc(FAR struct lib_outstream_s *this)
static int lowinstream_getc(FAR struct lib_instream_s *this)
{
if (this && up_getc(ch) != EOF)
{
@ -82,7 +82,7 @@ static int lowinstream_getc(FAR struct lib_outstream_s *this)
*
****************************************************************************/
void lib_lowinstream(FAR struct lib_outstream_s *stream)
void lib_lowinstream(FAR struct lib_instream_s *stream)
{
stream->get = lowinstream_getc;
stream->nget = 0;

View File

@ -84,8 +84,11 @@ static void lowoutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_lowoutstream(FAR struct lib_outstream_s *stream)
{
stream->put = lowoutstream_putc;
stream->nput = 0;
stream->put = lowoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
stream->flush = lib_noflush;
#endif
stream->nput = 0;
}
#endif /* CONFIG_ARCH_LOWPUTC */

View File

@ -82,10 +82,13 @@ static void memoutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_memoutstream(FAR struct lib_memoutstream_s *memoutstream,
FAR char *bufstart, int buflen)
{
memoutstream->public.put = memoutstream_putc;
memoutstream->public.nput = 0; /* Will be buffer index */
memoutstream->buffer = bufstart; /* Start of buffer */
memoutstream->buflen = buflen - 1; /* Save space for null terminator */
memoutstream->public.put = memoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
memoutstream->public.flush = lib_noflush;
#endif
memoutstream->public.nput = 0; /* Will be buffer index */
memoutstream->buffer = bufstart; /* Start of buffer */
memoutstream->buflen = buflen - 1; /* Save space for null terminator */
}

View File

@ -72,7 +72,10 @@ static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_nulloutstream(FAR struct lib_outstream_s *nulloutstream)
{
nulloutstream->put = nulloutstream_putc;
nulloutstream->nput = 0;
nulloutstream->put = nulloutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
nulloutstream->flush = lib_noflush;
#endif
nulloutstream->nput = 0;
}

View File

@ -91,8 +91,11 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_rawoutstream(FAR struct lib_rawoutstream_s *rawoutstream, int fd)
{
rawoutstream->public.put = rawoutstream_putc;
rawoutstream->public.nput = 0;
rawoutstream->fd = fd;
rawoutstream->public.put = rawoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
rawoutstream->public.flush = lib_noflush;
#endif
rawoutstream->public.nput = 0;
rawoutstream->fd = fd;
}

View File

@ -59,6 +59,18 @@ static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch)
}
}
/****************************************************************************
* Name: stdoutstream_flush
****************************************************************************/
#if defined(CONFIG_STDIO_LINEBUFFER) && CONFIG_STDIO_BUFFER_SIZE > 0
int stdoutstream_flush(FAR struct lib_outstream_s *this)
{
FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this;
return lib_fflush(sthis->stream, true);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -83,9 +95,16 @@ static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch)
void lib_stdoutstream(FAR struct lib_stdoutstream_s *stdoutstream,
FAR FILE *stream)
{
stdoutstream->public.put = stdoutstream_putc;
stdoutstream->public.nput = 0;
stdoutstream->stream = stream;
stdoutstream->public.put = stdoutstream_putc;
#ifdef CONFIG_STDIO_LINEBUFFER
#if CONFIG_STDIO_BUFFER_SIZE > 0
stdoutstream->public.flush = stdoutstream_flush;
#else
stdoutstream->public.flush = lib_noflush;
#endif
#endif
stdoutstream->public.nput = 0;
stdoutstream->stream = stream;
}

View File

@ -184,6 +184,13 @@ int main(int argc, char **argv, char **envp)
printf("# undef CONFIG_NUNGET_CHARS\n");
printf("# define CONFIG_NUNGET_CHARS 0\n");
printf("#endif\n\n");
printf("/* If no standard C buffered I/O is not supported, then line-oriented buffering\n");
printf(" * cannot be supported.\n");
printf(" */\n\n");
printf("#if CONFIG_STDIO_BUFFER_SIZE == 0\n");
printf("# undef CONFIG_STDIO_LINEBUFFER\n");
printf("# define CONFIG_STDIO_LINEBUFFER 0\n");
printf("#endif\n\n");
printf("/* If the maximum message size is zero, then we assume that message queues\n");
printf(" * support should be disabled\n");
printf(" */\n\n");