memstream.c

来自「一个C源代码分析器」· C语言 代码 · 共 178 行

C
178
字号
/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.This file is part of the GNU C Library.The GNU C Library is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General Public License aspublished by the Free Software Foundation; either version 2 of theLicense, or (at your option) any later version.The GNU C Library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with the GNU C Library; see the file COPYING.LIB.  Ifnot, write to the Free Software Foundation, Inc., 675 Mass Ave,Cambridge, MA 02139, USA.  */#include <ansidecl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>struct memstream_info  {    char **buffer;    size_t *bufsize;  };/* Enlarge STREAM's buffer.  */static voidDEFUN(enlarge_buffer, (stream, c),      register FILE *stream AND int c){  struct memstream_info *info = (struct memstream_info *) stream->__cookie;  size_t need;  if (stream->__put_limit != stream->__buffer)    /* Record how much has actually been written into the buffer.  */    *info->bufsize = stream->__bufp - stream->__buffer;  if (stream->__target != -1      && stream->__target > *info->bufsize)    /* Our target (where the buffer maps to) is always zero except when       the user just did a SEEK_END fseek.  If he sought within the       buffer, we need do nothing and will zero the target below.  If he       sought past the end of the object, grow and zero-fill the buffer       up to the target address.  */    need = stream->__target;  else    need = *info->bufsize + (c == EOF ? 0 : 1);  if (stream->__bufsize < need)    {      /* Enlarge the buffer.  */      char *newbuf;      if (stream->__bufsize * 2 < need)	stream->__bufsize = need;      else	stream->__bufsize *= 2;      newbuf = (char *) realloc ((PTR) stream->__buffer, stream->__bufsize);      *info->buffer = newbuf;      if (newbuf == NULL)	{	  free ((PTR) stream->__buffer);	  stream->__buffer = stream->__bufp	    = stream->__put_limit = stream->__get_limit = NULL;	  stream->__error = 1;	  return;	}      stream->__buffer = newbuf;    }  stream->__target = stream->__offset = 0;  stream->__get_limit = stream->__bufp = stream->__buffer + *info->bufsize;  stream->__put_limit = stream->__buffer + stream->__bufsize;  need -= stream->__bufp - stream->__buffer;  if (c != EOF)    --need;  if (need > 0)    {      /* We are extending the buffer after an fseek; zero-fill new space.  */      bzero (stream->__bufp, need);      stream->__bufp += need;    }  if (c != EOF)    *stream->__bufp++ = (unsigned char) c;  else    *stream->__bufp = '\0';}/* Seek function for memstreams.   There is no external state to munge.  */static intDEFUN(seek, (cookie, pos, whence),      PTR cookie AND fpos_t *pos AND int whence){  switch (whence)    {    case SEEK_SET:    case SEEK_CUR:      return 0;    case SEEK_END:      /* Return the position relative to the end of the object.	 fseek has just flushed us, so the info is consistent.  */      *pos += *((struct memstream_info *) cookie)->bufsize;      return 0;    default:      __libc_fatal ("memstream::seek called with bogus WHENCE\n");      return -1;    }}static intDEFUN(free_info, (cookie), PTR cookie){#if 0  struct memstream_info *info = (struct memstream_info *) cookie;  char *buf;  buf = (char *) realloc ((PTR) *info->buffer, *info->bufsize);  if (buf != NULL)    *info->buffer = buf;#endif  free (cookie);  return 0;}/* Open a stream that writes into a malloc'd buffer that is expanded as   necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location   and the number of characters written on fflush or fclose.  */FILE *DEFUN(open_memstream, (bufloc, sizeloc),      char **bufloc AND size_t *sizeloc){  FILE *stream;  struct memstream_info *info;  if (bufloc == NULL || sizeloc == NULL)    {      errno = EINVAL;      return NULL;    }  stream = fmemopen ((char *) NULL, BUFSIZ, "w+");  if (stream == NULL)    return NULL;  info = (struct memstream_info *) malloc (sizeof (struct memstream_info));  if (info == NULL)    {      int save = errno;      (void) fclose (stream);      errno = save;      return NULL;    }  stream->__room_funcs.__output = enlarge_buffer;  stream->__io_funcs.__seek = seek;  stream->__io_funcs.__close = free_info;  stream->__cookie = (PTR) info;  stream->__userbuf = 1;  info->buffer = bufloc;  info->bufsize = sizeloc;  *bufloc = stream->__buffer;  return stream;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?