This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 64e3a1fa0b960f841c248e54d96ba2b369c6e8a5 Author: Xu Xingliang <[email protected]> AuthorDate: Tue Apr 9 20:52:51 2024 +0800 libc/stream: add base64 encoded stream output Signed-off-by: Xu Xingliang <[email protected]> --- include/nuttx/streams.h | 29 ++++++ libs/libc/stream/CMakeLists.txt | 3 +- libs/libc/stream/Kconfig | 4 + libs/libc/stream/Make.defs | 2 +- libs/libc/stream/lib_base64outstream.c | 182 +++++++++++++++++++++++++++++++++ libs/libc/stream/lib_hexdumpstream.c | 8 +- 6 files changed, 222 insertions(+), 6 deletions(-) diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h index 38ce0a26be..b0a7e58535 100644 --- a/include/nuttx/streams.h +++ b/include/nuttx/streams.h @@ -243,6 +243,16 @@ struct lib_hexdumpstream_s char buffer[CONFIG_STREAM_HEXDUMP_BUFFER_SIZE + 1]; }; +struct lib_base64outstream_s +{ + struct lib_outstream_s common; + FAR struct lib_outstream_s *backend; + int pending; + unsigned char bytes[3]; + int nbytes; + char buffer[CONFIG_STREAM_BASE64_BUFFER_SIZE + 1]; +}; + /* This is a special stream that does buffered character I/O. NOTE that is * CONFIG_SYSLOG_BUFFER is not defined, it is the same as struct * lib_outstream_s @@ -446,6 +456,25 @@ void lib_bufferedoutstream(FAR struct lib_bufferedoutstream_s *stream, void lib_hexdumpstream(FAR struct lib_hexdumpstream_s *stream, FAR struct lib_outstream_s *backend); +/**************************************************************************** + * Name: lib_base64stream + * + * Description: + * Convert binary stream to base64 and redirect to syslog + * + * Input Parameters: + * stream - User allocated, uninitialized instance of struct + * lib_base64stream_s to be initialized. + * backend - Stream backend port. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_base64outstream(FAR struct lib_base64outstream_s *stream, + FAR struct lib_outstream_s *backend); + /**************************************************************************** * Name: lib_lowoutstream * diff --git a/libs/libc/stream/CMakeLists.txt b/libs/libc/stream/CMakeLists.txt index 8c6fb41b26..5a3f9ee7e3 100644 --- a/libs/libc/stream/CMakeLists.txt +++ b/libs/libc/stream/CMakeLists.txt @@ -40,7 +40,8 @@ list( lib_syslogstream.c lib_syslograwstream.c lib_bufferedoutstream.c - lib_hexdumpstream.c) + lib_hexdumpstream.c + lib_base64outstream.c) if(CONFIG_FILE_STREAM) list(APPEND SRCS lib_stdinstream.c lib_stdoutstream.c lib_stdsistream.c diff --git a/libs/libc/stream/Kconfig b/libs/libc/stream/Kconfig index ebf32b5a1c..a0792475f6 100644 --- a/libs/libc/stream/Kconfig +++ b/libs/libc/stream/Kconfig @@ -29,4 +29,8 @@ config STREAM_HEXDUMP_BUFFER_SIZE int "Output hexdump stream buffer size" default 128 +config STREAM_BASE64_BUFFER_SIZE + int "Output base64 stream buffer size" + default 128 + endmenu # Locale Support diff --git a/libs/libc/stream/Make.defs b/libs/libc/stream/Make.defs index 729411f2ad..d605efbb63 100644 --- a/libs/libc/stream/Make.defs +++ b/libs/libc/stream/Make.defs @@ -29,7 +29,7 @@ CSRCS += lib_rawoutstream.c lib_rawsistream.c lib_rawsostream.c CSRCS += lib_zeroinstream.c lib_nullinstream.c lib_nulloutstream.c CSRCS += lib_mtdoutstream.c lib_libnoflush.c lib_libsnoflush.c CSRCS += lib_syslogstream.c lib_syslograwstream.c lib_bufferedoutstream.c -CSRCS += lib_hexdumpstream.c lib_fileoutstream.c +CSRCS += lib_hexdumpstream.c lib_base64outstream.c lib_fileoutstream.c # The remaining sources files depend upon C streams diff --git a/libs/libc/stream/lib_base64outstream.c b/libs/libc/stream/lib_base64outstream.c new file mode 100644 index 0000000000..a273195024 --- /dev/null +++ b/libs/libc/stream/lib_base64outstream.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * libs/libc/stream/lib_base64outstream.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/compiler.h> +#include <nuttx/streams.h> + +#include <resolv.h> + +/* Limit the output stream buffer size to multiple of 4 bytes. */ + +#define STREAM_BASE64_BUFFER_SIZE (CONFIG_STREAM_BASE64_BUFFER_SIZE / 4 * 4) + +/**************************************************************************** + * Name: base64stream_flush + ****************************************************************************/ + +static int base64stream_flush(FAR struct lib_outstream_s *self) +{ + FAR struct lib_base64outstream_s *stream = (FAR void *)self; + + if (stream->nbytes > 0) + { + b64_ntop(stream->bytes, stream->nbytes, + stream->buffer + stream->pending, 4 + 1); + + stream->pending += 4; + stream->nbytes = 0; + } + + lib_stream_puts(stream->backend, stream->buffer, stream->pending); + stream->pending = 0; + return OK; +} + +/**************************************************************************** + * Name: base64stream_putc + ****************************************************************************/ + +static void base64stream_putc(FAR struct lib_outstream_s *self, int ch) +{ + FAR struct lib_base64outstream_s *stream = (FAR void *)self; + + stream->bytes[stream->nbytes++] = (char)ch; + if (stream->nbytes == 3) + { + b64_ntop(stream->bytes, 3, + stream->buffer + stream->pending, 4 + 1); + stream->pending += 4; + stream->nbytes = 0; + if (stream->pending == STREAM_BASE64_BUFFER_SIZE) + { + base64stream_flush(self); + } + } + + self->nput++; +} + +/**************************************************************************** + * Name: base64stream_puts + ****************************************************************************/ + +static int base64stream_puts(FAR struct lib_outstream_s *self, + FAR const void *buf, int len) +{ + FAR struct lib_base64outstream_s *stream = (FAR void *)self; + FAR const unsigned char *input = (FAR const unsigned char *)buf; + int remaining = len; + + if (stream->nbytes) + { + /* Flush the first three bytes */ + + int n = 3 - stream->nbytes; + if (n > remaining) + { + n = remaining; + } + + memcpy(stream->bytes + stream->nbytes, input, n); + stream->nbytes += n; + remaining -= n; + input += n; + if (stream->nbytes == 3) + { + b64_ntop(stream->bytes, 3, + stream->buffer + stream->pending, 4 + 1); + stream->pending += 4; + stream->nbytes = 0; + if (stream->pending == STREAM_BASE64_BUFFER_SIZE) + { + base64stream_flush(self); + } + } + } + + while (remaining >= 3) + { + int outlen; + int n = (STREAM_BASE64_BUFFER_SIZE - stream->pending) / 4 * 3; + if (n > remaining) + { + n = remaining / 3 * 3; + } + + outlen = n / 3 * 4; + b64_ntop(input, n, stream->buffer + stream->pending, + outlen + 1); + stream->pending += outlen; + input += n; + remaining -= n; + if (stream->pending == STREAM_BASE64_BUFFER_SIZE) + { + base64stream_flush(self); + } + } + + if (remaining > 0) + { + memcpy(stream->bytes, input, remaining); + stream->nbytes = remaining; + } + + self->nput += len; + return len; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_base64stream + * + * Description: + * Convert binary stream to base64 and redirect to output stream + * + * Input Parameters: + * stream - User allocated, uninitialized instance of struct + * lib_base64outstream_s to be initialized. + * backend - Stream backend port. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_base64outstream(FAR struct lib_base64outstream_s *stream, + FAR struct lib_outstream_s *backend) +{ + struct lib_outstream_s *public = &stream->common; + + public->putc = base64stream_putc; + public->puts = base64stream_puts; + public->flush = base64stream_flush; + public->nput = 0; + + stream->pending = 0; + stream->backend = backend; +} diff --git a/libs/libc/stream/lib_hexdumpstream.c b/libs/libc/stream/lib_hexdumpstream.c index 3207580720..3e42c91f88 100644 --- a/libs/libc/stream/lib_hexdumpstream.c +++ b/libs/libc/stream/lib_hexdumpstream.c @@ -136,8 +136,8 @@ static int hexdumpstream_puts(FAR struct lib_outstream_s *self, ret = bin2hex(p, ret, stream->buffer + stream->pending, (outlen - stream->pending) / 2); - p += ret; - remain -= ret; + p += ret; + remain -= ret; stream->pending += ret * 2; if (stream->pending == outlen) @@ -181,6 +181,6 @@ void lib_hexdumpstream(FAR struct lib_hexdumpstream_s *stream, public->flush = hexdumpstream_flush; public->nput = 0; - stream->pending = 0; - stream->backend = backend; + stream->pending = 0; + stream->backend = backend; }
