This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new c30413540c5 libs/libc/stdio: Add <stdio_ext.h>.
c30413540c5 is described below

commit c30413540c58fd5f8db26115dce3e7ceecdeb6b2
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Oct 8 22:01:13 2026 +0200

    libs/libc/stdio: Add <stdio_ext.h>.
    
    glibc and musl provide <stdio_ext.h>, with functions that report or
    change the state of a stream: pending output, read-ahead, line
    buffering, the error flag, purge.  Portable code uses them instead of
    looking inside FILE, and fails to build on a C library without them.
    
    Add __fbufsize(), __fpending(), __freading(), __fwriting(),
    __freadable(), __fwritable(), __flbf(), __fpurge(), __freadahead(),
    __freadptr(), __freadptrinc(), __fseterr(), __fsetlocking() and
    _flushlbf(), built on the buffer pointers of struct file_struct.  They
    are built with CONFIG_FILE_STREAM, like the rest of the stream
    functions.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 include/stdio_ext.h             |  79 ++++++++++
 libs/libc/stdio/CMakeLists.txt  |   3 +-
 libs/libc/stdio/Make.defs       |   2 +-
 libs/libc/stdio/lib_stdio_ext.c | 317 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 399 insertions(+), 2 deletions(-)

diff --git a/include/stdio_ext.h b/include/stdio_ext.h
new file mode 100644
index 00000000000..e3c56096f45
--- /dev/null
+++ b/include/stdio_ext.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * include/stdio_ext.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_STDIO_EXT_H
+#define __INCLUDE_STDIO_EXT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Values for __fsetlocking() */
+
+#define FSETLOCKING_QUERY    0  /* Only return the current mode */
+#define FSETLOCKING_INTERNAL 1  /* The library locks the stream */
+#define FSETLOCKING_BYCALLER 2  /* The caller locks the stream */
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* These functions give access to the state of a stream.  glibc and musl
+ * provide them, and portable code (gnulib, for example) uses them instead
+ * of looking inside FILE.
+ */
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+size_t __fbufsize(FAR FILE *stream);
+size_t __fpending(FAR FILE *stream);
+int    __freading(FAR FILE *stream);
+int    __fwriting(FAR FILE *stream);
+int    __freadable(FAR FILE *stream);
+int    __fwritable(FAR FILE *stream);
+int    __flbf(FAR FILE *stream);
+void   __fpurge(FAR FILE *stream);
+size_t __freadahead(FAR FILE *stream);
+FAR const char *__freadptr(FAR FILE *stream, FAR size_t *sizep);
+void   __freadptrinc(FAR FILE *stream, size_t inc);
+void   __fseterr(FAR FILE *stream);
+int    __fsetlocking(FAR FILE *stream, int type);
+void   _flushlbf(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_STDIO_EXT_H */
diff --git a/libs/libc/stdio/CMakeLists.txt b/libs/libc/stdio/CMakeLists.txt
index a41cff00efb..8d2982192aa 100644
--- a/libs/libc/stdio/CMakeLists.txt
+++ b/libs/libc/stdio/CMakeLists.txt
@@ -106,7 +106,8 @@ if(CONFIG_FILE_STREAM)
     lib_open_memstream.c
     lib_fgetwc.c
     lib_getwc.c
-    lib_ungetwc.c)
+    lib_ungetwc.c
+    lib_stdio_ext.c)
 endif()
 
 target_sources(c PRIVATE ${SRCS})
diff --git a/libs/libc/stdio/Make.defs b/libs/libc/stdio/Make.defs
index 218d494879d..af412a2c915 100644
--- a/libs/libc/stdio/Make.defs
+++ b/libs/libc/stdio/Make.defs
@@ -46,7 +46,7 @@ CSRCS += lib_scanf.c lib_vscanf.c lib_fscanf.c lib_vfscanf.c 
lib_tmpfile.c
 CSRCS += lib_setbuf.c lib_setvbuf.c lib_libfilelock.c lib_libgetstreams.c
 CSRCS += lib_setbuffer.c lib_fputwc.c lib_putwc.c lib_fputws.c
 CSRCS += lib_fopencookie.c lib_fmemopen.c lib_open_memstream.c lib_fgetwc.c
-CSRCS += lib_getwc.c lib_ungetwc.c
+CSRCS += lib_getwc.c lib_ungetwc.c lib_stdio_ext.c
 endif
 
 # Add the stdio directory to the build
diff --git a/libs/libc/stdio/lib_stdio_ext.c b/libs/libc/stdio/lib_stdio_ext.c
new file mode 100644
index 00000000000..120bd7d0824
--- /dev/null
+++ b/libs/libc/stdio/lib_stdio_ext.c
@@ -0,0 +1,317 @@
+/****************************************************************************
+ * libs/libc/stdio/lib_stdio_ext.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 <fcntl.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Does the buffer hold read data?  The buffer holds read data between
+ * fs_bufstart and fs_bufread, or write data between fs_bufstart and
+ * fs_bufpos (then fs_bufread == fs_bufstart).
+ */
+
+static bool stdio_ext_reading(FAR FILE *stream)
+{
+#if CONFIG_NUNGET_CHARS > 0
+  if (stream->fs_nungotten > 0)
+    {
+      return true;
+    }
+#endif
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  return stream->fs_bufstart != NULL &&
+         stream->fs_bufread != stream->fs_bufstart;
+#else
+  return false;
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: __fbufsize
+ *
+ * Description:
+ *   Return the size of the buffer of the stream.
+ *
+ ****************************************************************************/
+
+size_t __fbufsize(FAR FILE *stream)
+{
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  if (stream->fs_bufstart != NULL)
+    {
+      return stream->fs_bufend - stream->fs_bufstart;
+    }
+#endif
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: __fpending
+ *
+ * Description:
+ *   Return the number of bytes in the output buffer of the stream.
+ *
+ ****************************************************************************/
+
+size_t __fpending(FAR FILE *stream)
+{
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  if (stream->fs_bufstart != NULL &&
+      stream->fs_bufread == stream->fs_bufstart)
+    {
+      return stream->fs_bufpos - stream->fs_bufstart;
+    }
+#endif
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: __freading
+ *
+ * Description:
+ *   Return non-zero if the stream is read-only, or if the last operation on
+ *   it was a read.
+ *
+ ****************************************************************************/
+
+int __freading(FAR FILE *stream)
+{
+  return (stream->fs_oflags & O_ACCMODE) == O_RDONLY ||
+         stdio_ext_reading(stream);
+}
+
+/****************************************************************************
+ * Name: __fwriting
+ *
+ * Description:
+ *   Return non-zero if the stream is write-only, or if the last operation
+ *   on it was a write.
+ *
+ ****************************************************************************/
+
+int __fwriting(FAR FILE *stream)
+{
+  return (stream->fs_oflags & O_ACCMODE) == O_WRONLY ||
+         __fpending(stream) > 0;
+}
+
+/****************************************************************************
+ * Name: __freadable
+ *
+ * Description:
+ *   Return non-zero if the stream may be read.
+ *
+ ****************************************************************************/
+
+int __freadable(FAR FILE *stream)
+{
+  return (stream->fs_oflags & O_ACCMODE) != O_WRONLY;
+}
+
+/****************************************************************************
+ * Name: __fwritable
+ *
+ * Description:
+ *   Return non-zero if the stream may be written.
+ *
+ ****************************************************************************/
+
+int __fwritable(FAR FILE *stream)
+{
+  return (stream->fs_oflags & O_ACCMODE) != O_RDONLY;
+}
+
+/****************************************************************************
+ * Name: __flbf
+ *
+ * Description:
+ *   Return non-zero if the stream is line buffered.
+ *
+ ****************************************************************************/
+
+int __flbf(FAR FILE *stream)
+{
+  return (stream->fs_flags & __FS_FLAG_LBF) != 0;
+}
+
+/****************************************************************************
+ * Name: __fpurge
+ *
+ * Description:
+ *   Discard the contents of the buffer of the stream: unread input,
+ *   pushed-back characters and unwritten output.
+ *
+ ****************************************************************************/
+
+void __fpurge(FAR FILE *stream)
+{
+  flockfile(stream);
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  stream->fs_bufpos  = stream->fs_bufstart;
+  stream->fs_bufread = stream->fs_bufstart;
+#endif
+
+#if CONFIG_NUNGET_CHARS > 0
+  stream->fs_nungotten = 0;
+#endif
+
+  funlockfile(stream);
+}
+
+/****************************************************************************
+ * Name: __freadahead
+ *
+ * Description:
+ *   Return the number of bytes that have been read into the buffer, or
+ *   pushed back, and not yet consumed.
+ *
+ ****************************************************************************/
+
+size_t __freadahead(FAR FILE *stream)
+{
+  size_t n = 0;
+
+  if (!stdio_ext_reading(stream))
+    {
+      return 0;
+    }
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  if (stream->fs_bufstart != NULL)
+    {
+      n = stream->fs_bufread - stream->fs_bufpos;
+    }
+#endif
+
+#if CONFIG_NUNGET_CHARS > 0
+  n += stream->fs_nungotten;
+#endif
+
+  return n;
+}
+
+/****************************************************************************
+ * Name: __freadptr
+ *
+ * Description:
+ *   Return a pointer to the bytes in the read buffer that have not been
+ *   consumed, and their number in *sizep.  Return NULL if there are none,
+ *   or if characters have been pushed back.
+ *
+ ****************************************************************************/
+
+FAR const char *__freadptr(FAR FILE *stream, FAR size_t *sizep)
+{
+#if CONFIG_NUNGET_CHARS > 0
+  if (stream->fs_nungotten > 0)
+    {
+      return NULL;
+    }
+#endif
+
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  if (stdio_ext_reading(stream) && stream->fs_bufread > stream->fs_bufpos)
+    {
+      *sizep = stream->fs_bufread - stream->fs_bufpos;
+      return stream->fs_bufpos;
+    }
+#endif
+
+  return NULL;
+}
+
+/****************************************************************************
+ * Name: __freadptrinc
+ *
+ * Description:
+ *   Consume inc bytes of the read buffer (see __freadptr()).
+ *
+ ****************************************************************************/
+
+void __freadptrinc(FAR FILE *stream, size_t inc)
+{
+#ifndef CONFIG_STDIO_DISABLE_BUFFERING
+  stream->fs_bufpos += inc;
+#endif
+}
+
+/****************************************************************************
+ * Name: __fseterr
+ *
+ * Description:
+ *   Set the error indicator of the stream.
+ *
+ ****************************************************************************/
+
+void __fseterr(FAR FILE *stream)
+{
+  stream->fs_flags |= __FS_FLAG_ERROR;
+}
+
+/****************************************************************************
+ * Name: __fsetlocking
+ *
+ * Description:
+ *   The library always locks the stream; the type is ignored.
+ *
+ ****************************************************************************/
+
+int __fsetlocking(FAR FILE *stream, int type)
+{
+  UNUSED(stream);
+  UNUSED(type);
+
+  return FSETLOCKING_INTERNAL;
+}
+
+/****************************************************************************
+ * Name: _flushlbf
+ *
+ * Description:
+ *   Flush all line-buffered streams.  NuttX flushes all streams.
+ *
+ ****************************************************************************/
+
+void _flushlbf(void)
+{
+  fflush(NULL);
+}

Reply via email to