xiaoxiang781216 commented on code in PR #11011: URL: https://github.com/apache/nuttx/pull/11011#discussion_r1371620147
########## libs/libc/stdio/lib_fmemopen.c: ########## @@ -0,0 +1,291 @@ +/**************************************************************************** + * libs/libc/stdio/lib_fmemopen.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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <assert.h> +#include <errno.h> + +#include "libc.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct fmemopen_cookie_s +{ + FAR char *buf; /* Memory buffer */ + off_t pos; /* Current position in the buffer */ + off_t end; /* End buffer position */ + size_t size; /* Buffer size */ + bool custom; /* True if custom buffer is used */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fmemopen_read + ****************************************************************************/ + +static ssize_t fmemopen_read(FAR void *c, FAR char *buf, size_t size) +{ + FAR struct fmemopen_cookie_s *fmemopen_cookie = + (FAR struct fmemopen_cookie_s *)c; + if (fmemopen_cookie->pos + size > fmemopen_cookie->end) + { + size = fmemopen_cookie->end - fmemopen_cookie->pos; + } + + if (size < 0) + { + size = 0; + } + + memcpy(buf, fmemopen_cookie->buf + fmemopen_cookie->pos, size); + + fmemopen_cookie->pos += size; + return size; +} + +/**************************************************************************** + * Name: fmemopen_write + ****************************************************************************/ + +static ssize_t fmemopen_write(FAR void *c, FAR const char *buf, size_t size) +{ + FAR struct fmemopen_cookie_s *fmemopen_cookie = + (FAR struct fmemopen_cookie_s *)c; + if (size + fmemopen_cookie->pos > fmemopen_cookie->size) + { + return -ENOSPC; + } + + memcpy(fmemopen_cookie->buf + fmemopen_cookie->pos, buf, size); + + fmemopen_cookie->pos += size; + if (fmemopen_cookie->pos > fmemopen_cookie->end) + { + fmemopen_cookie->end = fmemopen_cookie->pos; + } + + /* POSIX states that NULL byte shall be written at the current position + * or end of the buffer. + */ + + if (fmemopen_cookie->pos < fmemopen_cookie->size && + fmemopen_cookie->buf[fmemopen_cookie->pos - 1] != '\0') + { + fmemopen_cookie->buf[fmemopen_cookie->pos] = '\0'; + } + + return size; +} + +/**************************************************************************** + * Name: fmemopen_seek + ****************************************************************************/ + +static off_t fmemopen_seek(FAR void *c, FAR off_t *offset, int whence) +{ + FAR struct fmemopen_cookie_s *fmemopen_cookie = + (FAR struct fmemopen_cookie_s *)c; + off_t new_offset; + + switch (whence) + { + case SEEK_SET: + new_offset = *offset; + break; + case SEEK_END: + new_offset = fmemopen_cookie->end + *offset; + break; + case SEEK_CUR: + new_offset = fmemopen_cookie->pos + *offset; + break; + default: + return ENOTSUP; + } + + /* Seek to negative value or value larger than maximum size shall fail. */ + + if (new_offset < 0 || (new_offset > fmemopen_cookie->end)) + { + return EINVAL; + } + + fmemopen_cookie->pos = new_offset; + *offset = new_offset; + return new_offset; +} + +/**************************************************************************** + * Name: fmemopen_close + ****************************************************************************/ + +static int fmemopen_close(FAR void *c) +{ + FAR struct fmemopen_cookie_s *fmemopen_cookie = + (FAR struct fmemopen_cookie_s *)c; + if (fmemopen_cookie->custom) + { + lib_free(fmemopen_cookie->buf); + } + + lib_free(fmemopen_cookie); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fmemopen + ****************************************************************************/ + +FAR FILE *fmemopen(FAR void *buf, size_t size, FAR const char *mode) +{ + cookie_io_functions_t fmemopen_io; + FAR struct fmemopen_cookie_s *fmemopen_cookie; + FAR FILE *filep; + + fmemopen_cookie = lib_zalloc(sizeof(struct fmemopen_cookie_s)); + if (fmemopen_cookie == NULL) + { + set_errno(ENOMEM); + return NULL; + } + + if (buf == NULL) + { + /* POSIX standard states: + * Because this feature is only useful when the stream is opened for + * updating (because there is no way to get a pointer to the buffer) + * the fmemopen() call may fail if the mode argument does not + * include a '+'. + */ + + if (mode[1] != '+') Review Comment: Yes, but since fdopen/lib_mode2oflags doesn't do any real action, we can reuse the parser result, but do the action a little bit differently. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
