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;
 }

Reply via email to