From 205ca265565f4e8dae912df38c150c04664799ce Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 1 Mar 2023 21:03:07 +0800 Subject: [PATCH] libc/streams: Implement gets/puts for all streams Signed-off-by: yinshengkai --- libs/libc/stream/lib_meminstream.c | 31 ++++++++++++++++++++++ libs/libc/stream/lib_memsistream.c | 30 +++++++++++++++++++++ libs/libc/stream/lib_memsostream.c | 26 +++++++++++++++++++ libs/libc/stream/lib_nullinstream.c | 9 +++++++ libs/libc/stream/lib_nulloutstream.c | 11 ++++++++ libs/libc/stream/lib_rawinstream.c | 28 ++++++++++++++++++++ libs/libc/stream/lib_rawsistream.c | 28 ++++++++++++++++++++ libs/libc/stream/lib_rawsostream.c | 39 ++++++++++++++++++++++++++++ libs/libc/stream/lib_stdinstream.c | 29 +++++++++++++++++++++ libs/libc/stream/lib_stdoutstream.c | 39 ++++++++++++++++++++++++++++ libs/libc/stream/lib_stdsistream.c | 24 +++++++++++++++++ libs/libc/stream/lib_stdsostream.c | 37 ++++++++++++++++++++++++++ libs/libc/stream/lib_zeroinstream.c | 9 +++++++ 13 files changed, 340 insertions(+) diff --git a/libs/libc/stream/lib_meminstream.c b/libs/libc/stream/lib_meminstream.c index 460910cb79..36c9261149 100644 --- a/libs/libc/stream/lib_meminstream.c +++ b/libs/libc/stream/lib_meminstream.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include "libc.h" @@ -56,6 +57,35 @@ static int meminstream_getc(FAR struct lib_instream_s *this) return ret; } +/**************************************************************************** + * Name: meminstream_gets + ****************************************************************************/ + +static int meminstream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + FAR struct lib_meminstream_s *mthis = (FAR struct lib_meminstream_s *)this; + int ret; + + DEBUGASSERT(this); + + /* Get the buffer (if any) from the stream */ + + if (this->nget < mthis->buflen) + { + ret = mthis->buflen - this->nget < len ? + mthis->buflen - this->nget : len; + this->nget += ret; + memcpy(buffer, mthis->buffer, ret); + } + else + { + ret = EOF; + } + + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -81,6 +111,7 @@ void lib_meminstream(FAR struct lib_meminstream_s *instream, FAR const char *bufstart, int buflen) { instream->public.getc = meminstream_getc; + instream->public.gets = meminstream_gets; instream->public.nget = 0; /* Will be buffer index */ instream->buffer = bufstart; /* Start of buffer */ instream->buflen = buflen; /* Length of the buffer */ diff --git a/libs/libc/stream/lib_memsistream.c b/libs/libc/stream/lib_memsistream.c index 15b1f16626..66fd546bbe 100644 --- a/libs/libc/stream/lib_memsistream.c +++ b/libs/libc/stream/lib_memsistream.c @@ -57,6 +57,35 @@ static int memsistream_getc(FAR struct lib_sistream_s *this) return ret; } +/**************************************************************************** + * Name: meminstream_gets + ****************************************************************************/ + +static int memsistream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + FAR struct lib_memsistream_s *mthis = (FAR struct lib_memsistream_s *)this; + int ret; + + DEBUGASSERT(this); + + /* Get the buffer (if any) from the stream */ + + if (this->nget < mthis->buflen) + { + ret = mthis->buflen - this->nget; + ret = ret < len ? ret : len; + this->nget += ret; + memcpy(buffer, mthis->buffer, ret); + } + else + { + ret = EOF; + } + + return ret; +} + /**************************************************************************** * Name: memsistream_seek ****************************************************************************/ @@ -125,6 +154,7 @@ void lib_memsistream(FAR struct lib_memsistream_s *instream, FAR const char *bufstart, int buflen) { instream->public.getc = memsistream_getc; + instream->public.gets = memsistream_gets; instream->public.seek = memsistream_seek; instream->public.nget = 0; /* Total number of characters read */ instream->buffer = bufstart; /* Start of buffer */ diff --git a/libs/libc/stream/lib_memsostream.c b/libs/libc/stream/lib_memsostream.c index 55b73df825..b99cac57f1 100644 --- a/libs/libc/stream/lib_memsostream.c +++ b/libs/libc/stream/lib_memsostream.c @@ -54,6 +54,31 @@ static void memsostream_putc(FAR struct lib_sostream_s *this, int ch) } } +/**************************************************************************** + * Name: memoutstream_puts + ****************************************************************************/ + +static int memsostream_puts(FAR struct lib_sostream_s *this, + FAR const void *buf, int len) +{ + int ncopy; + FAR struct lib_memsostream_s *mthis = (FAR struct lib_memsostream_s *)this; + + DEBUGASSERT(this); + + ncopy = mthis->offset + len + 1 < mthis->buflen ? len : + mthis->buflen - mthis->offset - 1; + if (ncopy > 0) + { + memcpy(mthis->buffer + mthis->offset, buf, ncopy); + mthis->public.nput += ncopy; + mthis->offset += ncopy; + mthis->buffer[mthis->offset] = '\0'; + } + + return ncopy; +} + /**************************************************************************** * Name: memsostream_seek ****************************************************************************/ @@ -122,6 +147,7 @@ void lib_memsostream(FAR struct lib_memsostream_s *outstream, FAR char *bufstart, int buflen) { outstream->public.putc = memsostream_putc; + outstream->public.puts = memsostream_puts; outstream->public.flush = lib_snoflush; outstream->public.seek = memsostream_seek; outstream->public.nput = 0; /* Total number of characters written */ diff --git a/libs/libc/stream/lib_nullinstream.c b/libs/libc/stream/lib_nullinstream.c index 3fa0c4f944..8cd94d256e 100644 --- a/libs/libc/stream/lib_nullinstream.c +++ b/libs/libc/stream/lib_nullinstream.c @@ -37,6 +37,14 @@ static int nullinstream_getc(FAR struct lib_instream_s *this) return EOF; } +static int nullinstream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + UNUSED(buffer); + UNUSED(len); + return EOF; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -60,5 +68,6 @@ static int nullinstream_getc(FAR struct lib_instream_s *this) void lib_nullinstream(FAR struct lib_instream_s *nullinstream) { nullinstream->getc = nullinstream_getc; + nullinstream->gets = nullinstream_gets; nullinstream->nget = 0; } diff --git a/libs/libc/stream/lib_nulloutstream.c b/libs/libc/stream/lib_nulloutstream.c index 20b305a85b..fcbdf7b57f 100644 --- a/libs/libc/stream/lib_nulloutstream.c +++ b/libs/libc/stream/lib_nulloutstream.c @@ -39,6 +39,16 @@ static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch) this->nput++; } +static int nulloutstream_puts(FAR struct lib_outstream_s *this, + FAR const void *buffer, int len) +{ + UNUSED(buffer); + UNUSED(len); + DEBUGASSERT(this); + this->nput += len; + return len; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -62,6 +72,7 @@ static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch) void lib_nulloutstream(FAR struct lib_outstream_s *nulloutstream) { nulloutstream->putc = nulloutstream_putc; + nulloutstream->puts = nulloutstream_puts; nulloutstream->flush = lib_noflush; nulloutstream->nput = 0; } diff --git a/libs/libc/stream/lib_rawinstream.c b/libs/libc/stream/lib_rawinstream.c index 88e180d2b5..b98e4c2781 100644 --- a/libs/libc/stream/lib_rawinstream.c +++ b/libs/libc/stream/lib_rawinstream.c @@ -66,6 +66,33 @@ static int rawinstream_getc(FAR struct lib_instream_s *this) return EOF; } +/**************************************************************************** + * Name: rawinstream_getc + ****************************************************************************/ + +static int rawinstream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + FAR struct lib_rawinstream_s *rthis = (FAR struct lib_rawinstream_s *)this; + int nread; + + DEBUGASSERT(this && rthis->fd >= 0); + + /* Attempt to read one character */ + + nread = _NX_READ(rthis->fd, buffer, len); + if (nread >= 0) + { + this->nget += nread; + } + else + { + nread = _NX_GETERRVAL(nread); + } + + return nread; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -90,6 +117,7 @@ static int rawinstream_getc(FAR struct lib_instream_s *this) void lib_rawinstream(FAR struct lib_rawinstream_s *instream, int fd) { instream->public.getc = rawinstream_getc; + instream->public.gets = rawinstream_gets; instream->public.nget = 0; instream->fd = fd; } diff --git a/libs/libc/stream/lib_rawsistream.c b/libs/libc/stream/lib_rawsistream.c index 8b2268b4f8..2313dca683 100644 --- a/libs/libc/stream/lib_rawsistream.c +++ b/libs/libc/stream/lib_rawsistream.c @@ -66,6 +66,33 @@ static int rawsistream_getc(FAR struct lib_sistream_s *this) return EOF; } +/**************************************************************************** + * Name: rawsistream_gets + ****************************************************************************/ + +static int rawsistream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + FAR struct lib_rawsistream_s *rthis = (FAR struct lib_rawsistream_s *)this; + int nread; + + DEBUGASSERT(this && rthis->fd >= 0); + + /* Attempt to read a buffer */ + + nread = _NX_READ(rthis->fd, buffer, len); + if (nread >= 0) + { + this->nget += nread; + } + else + { + nread = _NX_GETERRVAL(nread); + } + + return nread; +} + /**************************************************************************** * Name: rawsistream_seek ****************************************************************************/ @@ -103,6 +130,7 @@ static off_t rawsistream_seek(FAR struct lib_sistream_s *this, off_t offset, void lib_rawsistream(FAR struct lib_rawsistream_s *instream, int fd) { instream->public.getc = rawsistream_getc; + instream->public.gets = rawsistream_gets; instream->public.seek = rawsistream_seek; instream->public.nget = 0; instream->fd = fd; diff --git a/libs/libc/stream/lib_rawsostream.c b/libs/libc/stream/lib_rawsostream.c index 468fbcd7e3..2f286c386d 100644 --- a/libs/libc/stream/lib_rawsostream.c +++ b/libs/libc/stream/lib_rawsostream.c @@ -73,6 +73,44 @@ static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch) while (errcode == EINTR); } +/**************************************************************************** + * Name: rawsostream_puts + ****************************************************************************/ + +static int rawsostream_puts(FAR struct lib_sostream_s *this, + FAR const void *buffer, int len) +{ + FAR struct lib_rawsostream_s *rthis = (FAR struct lib_rawsostream_s *)this; + int nwritten; + + DEBUGASSERT(this && rthis->fd >= 0); + + /* Loop until the buffer is successfully transferred or until an + * irrecoverable error occurs. + */ + + do + { + nwritten = _NX_WRITE(rthis->fd, buffer, len); + if (nwritten >= 0) + { + this->nput += nwritten; + return nwritten; + } + + /* The only expected error is EINTR, meaning that the write operation + * was awakened by a signal. Zero would not be a valid return value + * from _NX_WRITE(). + */ + + nwritten = _NX_GETERRVAL(nwritten); + DEBUGASSERT(nwritten < 0); + } + while (nwritten == -EINTR); + + return nwritten; +} + /**************************************************************************** * Name: rawsostream_seek ****************************************************************************/ @@ -110,6 +148,7 @@ static off_t rawsostream_seek(FAR struct lib_sostream_s *this, off_t offset, void lib_rawsostream(FAR struct lib_rawsostream_s *outstream, int fd) { outstream->public.putc = rawsostream_putc; + outstream->public.puts = rawsostream_puts; outstream->public.flush = lib_snoflush; outstream->public.seek = rawsostream_seek; outstream->public.nput = 0; diff --git a/libs/libc/stream/lib_stdinstream.c b/libs/libc/stream/lib_stdinstream.c index e218d20ecd..06be80712f 100644 --- a/libs/libc/stream/lib_stdinstream.c +++ b/libs/libc/stream/lib_stdinstream.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include "libc.h" @@ -52,6 +53,33 @@ static int stdinstream_getc(FAR struct lib_instream_s *this) return ret; } +/**************************************************************************** + * Name: stdinstream_gets + ****************************************************************************/ + +static int stdinstream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + FAR struct lib_stdinstream_s *sthis = (FAR struct lib_stdinstream_s *)this; + int nread = 0; + + DEBUGASSERT(this); + + /* Get the buffer from the incoming stream */ + + nread = fread(buffer, len, 1, sthis->stream); + if (nread >= 0) + { + this->nget += nread; + } + else + { + nread = _NX_GETERRVAL(nread); + } + + return nread; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -77,6 +105,7 @@ void lib_stdinstream(FAR struct lib_stdinstream_s *instream, FAR FILE *stream) { instream->public.getc = stdinstream_getc; + instream->public.gets = stdinstream_gets; instream->public.nget = 0; instream->stream = stream; } diff --git a/libs/libc/stream/lib_stdoutstream.c b/libs/libc/stream/lib_stdoutstream.c index 3b77d074ff..f85aa8134c 100644 --- a/libs/libc/stream/lib_stdoutstream.c +++ b/libs/libc/stream/lib_stdoutstream.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "libc.h" @@ -64,6 +65,43 @@ static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch) while (get_errno() == EINTR); } +/**************************************************************************** + * Name: stdoutstream_puts + ****************************************************************************/ + +static int stdoutstream_puts(FAR struct lib_outstream_s *this, + FAR const void *buffer, int len) +{ + FAR struct lib_stdoutstream_s *sthis = + (FAR struct lib_stdoutstream_s *)this; + int result; + + DEBUGASSERT(this && sthis->stream); + + /* Loop until the buffer is successfully transferred or an irrecoverable + * error occurs. + */ + + do + { + result = fwrite(buffer, len, 1, sthis->stream); + if (result >= 0) + { + this->nput += result; + return result; + } + + result = _NX_GETERRVAL(result); + + /* EINTR (meaning that fputc was interrupted by a signal) is the only + * recoverable error. + */ + } + while (result == -EINTR); + + return result; +} + /**************************************************************************** * Name: stdoutstream_flush ****************************************************************************/ @@ -106,6 +144,7 @@ void lib_stdoutstream(FAR struct lib_stdoutstream_s *outstream, /* Select the putc operation */ outstream->public.putc = stdoutstream_putc; + outstream->public.puts = stdoutstream_puts; /* Select the correct flush operation. This flush is only called when * a newline is encountered in the output stream. However, we do not diff --git a/libs/libc/stream/lib_stdsistream.c b/libs/libc/stream/lib_stdsistream.c index 41ca3434e3..9feb39ab8c 100644 --- a/libs/libc/stream/lib_stdsistream.c +++ b/libs/libc/stream/lib_stdsistream.c @@ -52,6 +52,29 @@ static int stdsistream_getc(FAR struct lib_sistream_s *this) return ret; } +/**************************************************************************** + * Name: stdsistream_gets + ****************************************************************************/ + +static int stdsistream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + FAR struct lib_stdsistream_s *sthis = (FAR struct lib_stdsistream_s *)this; + int nread = 0; + + DEBUGASSERT(this); + + /* Get the buffer from the incoming stream */ + + nread = fread(buffer, len, 1, sthis->stream); + if (nread >= 0) + { + this->nget += nread; + } + + return nread; +} + /**************************************************************************** * Name: stdsistream_seek ****************************************************************************/ @@ -90,6 +113,7 @@ void lib_stdsistream(FAR struct lib_stdsistream_s *instream, FAR FILE *stream) { instream->public.getc = stdsistream_getc; + instream->public.gets = stdsistream_gets; instream->public.seek = stdsistream_seek; instream->public.nget = 0; instream->stream = stream; diff --git a/libs/libc/stream/lib_stdsostream.c b/libs/libc/stream/lib_stdsostream.c index c73dac066b..bdb594cad1 100644 --- a/libs/libc/stream/lib_stdsostream.c +++ b/libs/libc/stream/lib_stdsostream.c @@ -63,6 +63,42 @@ static void stdsostream_putc(FAR struct lib_sostream_s *this, int ch) while (get_errno() == EINTR); } +/**************************************************************************** + * Name: stdsostream_puts + ****************************************************************************/ + +static int stdsostream_puts(FAR struct lib_sostream_s *this, + FAR const void *buffer, int len) +{ + FAR struct lib_stdsostream_s *sthis = (FAR struct lib_stdsostream_s *)this; + int result; + + DEBUGASSERT(this && sthis->stream); + + /* Loop until the character is successfully transferred or an irrecoverable + * error occurs. + */ + + do + { + result = lib_fwrite(buffer, len, sthis->stream); + if (result >= 0) + { + this->nput += result; + return result; + } + + result = _NX_GETERRVAL(result); + + /* EINTR (meaning that fputc was interrupted by a signal) is the only + * recoverable error. + */ + } + while (result == -EINTR); + + return result; +} + /**************************************************************************** * Name: stdsostream_flush ****************************************************************************/ @@ -117,6 +153,7 @@ void lib_stdsostream(FAR struct lib_stdsostream_s *outstream, /* Select the putc operation */ outstream->public.putc = stdsostream_putc; + outstream->public.puts = stdsostream_puts; /* Select the correct flush operation. This flush is only called when * a newline is encountered in the output stream. However, we do not diff --git a/libs/libc/stream/lib_zeroinstream.c b/libs/libc/stream/lib_zeroinstream.c index 1cd42177f7..d2e52edacf 100644 --- a/libs/libc/stream/lib_zeroinstream.c +++ b/libs/libc/stream/lib_zeroinstream.c @@ -36,6 +36,14 @@ static int zeroinstream_getc(FAR struct lib_instream_s *this) return 0; } +static int zeroinstream_gets(FAR struct lib_instream_s *this, + FAR void *buffer, int len) +{ + this->nget += len; + memset(buffer, 0, len); + return len; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -59,5 +67,6 @@ static int zeroinstream_getc(FAR struct lib_instream_s *this) void lib_zeroinstream(FAR struct lib_instream_s *zeroinstream) { zeroinstream->getc = zeroinstream_getc; + zeroinstream->gets = zeroinstream_gets; zeroinstream->nget = 0; }