⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 funopen.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
字号:
/* Copyright (C) 2007 Eric Blake * Permission to use, copy, modify, and distribute this software * is freely granted, provided that this notice is preserved. *//*FUNCTION<<funopen>>, <<fropen>>, <<fwopen>>---open a stream with custom callbacksINDEX	funopenINDEX	fropenINDEX	fwopenANSI_SYNOPSIS	#include <stdio.h>	FILE *funopen(const void *<[cookie]>,	              int (*<[readfn]>) (void *cookie, char *buf, int n),	              int (*<[writefn]>) (void *cookie, const char *buf, int n),	              fpos_t (*<[seekfn]>) (void *cookie, fpos_t off, int whence),	              int (*<[closefn]>) (void *cookie));	FILE *fropen(const void *<[cookie]>,	             int (*<[readfn]>) (void *cookie, char *buf, int n));	FILE *fwopen(const void *<[cookie]>,	             int (*<[writefn]>) (void *cookie, const char *buf, int n));DESCRIPTION<<funopen>> creates a <<FILE>> stream where I/O is performed usingcustom callbacks.  At least one of <[readfn]> and <[writefn]> must beprovided, which determines whether the stream behaves with mode <"r">,<"w">, or <"r+">.<[readfn]> should return -1 on failure, or else the number of bytesread (0 on EOF).  It is similar to <<read>>, except that <int> ratherthan <size_t> bounds a transaction size, and <[cookie]> will be passedas the first argument.  A NULL <[readfn]> makes attempts to read thestream fail.<[writefn]> should return -1 on failure, or else the number of byteswritten.  It is similar to <<write>>, except that <int> rather than<size_t> bounds a transaction size, and <[cookie]> will be passed asthe first argument.  A NULL <[writefn]> makes attempts to write thestream fail.<[seekfn]> should return (fpos_t)-1 on failure, or else the currentfile position.  It is similar to <<lseek>>, except that <[cookie]>will be passed as the first argument.  A NULL <[seekfn]> makes thestream behave similarly to a pipe in relation to stdio functions thatrequire positioning.  This implementation assumes fpos_t and off_t arethe same type.<[closefn]> should return -1 on failure, or 0 on success.  It issimilar to <<close>>, except that <[cookie]> will be passed as thefirst argument.  A NULL <[closefn]> merely flushes all data then lets<<fclose>> succeed.  A failed close will still invalidate the stream.Read and write I/O functions are allowed to change the underlyingbuffer on fully buffered or line buffered streams by calling<<setvbuf>>.  They are also not required to completely fill or emptythe buffer.  They are not, however, allowed to change streams fromunbuffered to buffered or to change the state of the line bufferingflag.  They must also be prepared to have read or write calls occur onbuffers other than the one most recently specified.The functions <<fropen>> and <<fwopen>> are convenience macros around<<funopen>> that only use the specified callback.RETURNSThe return value is an open FILE pointer on success.  On error,<<NULL>> is returned, and <<errno>> will be set to EINVAL if afunction pointer is missing, ENOMEM if the stream cannot be created,or EMFILE if too many streams are already open.PORTABILITYThis function is a newlib extension, copying the prototype from BSD.It is not portable.  See also the <<fopencookie>> interface from Linux.Supporting OS subroutines required: <<sbrk>>.*/#include <stdio.h>#include <errno.h>#include <sys/lock.h>#include "local.h"typedef int (*funread)(void *_cookie, char *_buf, int _n);typedef int (*funwrite)(void *_cookie, const char *_buf, int _n);#ifdef __LARGE64_FILEStypedef _fpos64_t (*funseek)(void *_cookie, _fpos64_t _off, int _whence);#elsetypedef fpos_t (*funseek)(void *_cookie, fpos_t _off, int _whence);#endiftypedef int (*funclose)(void *_cookie);typedef struct funcookie {  void *cookie;  funread readfn;  funwrite writefn;  funseek seekfn;  funclose closefn;} funcookie;static _READ_WRITE_RETURN_TYPE_DEFUN(funreader, (ptr, cookie, buf, n),       struct _reent *ptr _AND       void *cookie _AND       char *buf _AND       int n){  int result;  funcookie *c = (funcookie *) cookie;  errno = 0;  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)    ptr->_errno = errno;  return result;}static _READ_WRITE_RETURN_TYPE_DEFUN(funwriter, (ptr, cookie, buf, n),       struct _reent *ptr _AND       void *cookie _AND       const char *buf _AND       int n){  int result;  funcookie *c = (funcookie *) cookie;  errno = 0;  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)    ptr->_errno = errno;  return result;}static _fpos_t_DEFUN(funseeker, (ptr, cookie, off, whence),       struct _reent *ptr _AND       void *cookie _AND       _fpos_t off _AND       int whence){  funcookie *c = (funcookie *) cookie;#ifndef __LARGE64_FILES  fpos_t result;  errno = 0;  if ((result = c->seekfn (c->cookie, (fpos_t) off, whence)) < 0 && errno)    ptr->_errno = errno;#else /* __LARGE64_FILES */  _fpos64_t result;  errno = 0;  if ((result = c->seekfn (c->cookie, (_fpos64_t) off, whence)) < 0 && errno)    ptr->_errno = errno;  else if ((_fpos_t)result != result)    {      ptr->_errno = EOVERFLOW;      result = -1;    }#endif /* __LARGE64_FILES */  return result;}#ifdef __LARGE64_FILESstatic _fpos64_t_DEFUN(funseeker64, (ptr, cookie, off, whence),       struct _reent *ptr _AND       void *cookie _AND       _fpos64_t off _AND       int whence){  _fpos64_t result;  funcookie *c = (funcookie *) cookie;  errno = 0;  if ((result = c->seekfn (c->cookie, off, whence)) < 0 && errno)    ptr->_errno = errno;  return result;}#endif /* __LARGE64_FILES */static int_DEFUN(funcloser, (ptr, cookie),       struct _reent *ptr _AND       void *cookie){  int result = 0;  funcookie *c = (funcookie *) cookie;  if (c->closefn)    {      errno = 0;      if ((result = c->closefn (c->cookie)) < 0 && errno)	ptr->_errno = errno;    }  _free_r (ptr, c);  return result;}FILE *_DEFUN(_funopen_r, (ptr, cookie, readfn, writefn, seekfn, closefn),       struct _reent *ptr _AND       const void *cookie _AND       funread readfn _AND       funwrite writefn _AND       funseek seekfn _AND       funclose closefn){  FILE *fp;  funcookie *c;  if (!readfn && !writefn)    {      ptr->_errno = EINVAL;      return NULL;    }  if ((fp = __sfp (ptr)) == NULL)    return NULL;  if ((c = (funcookie *) _malloc_r (ptr, sizeof *c)) == NULL)    {      __sfp_lock_acquire ();      fp->_flags = 0;		/* release */#ifndef __SINGLE_THREAD__      __lock_close_recursive (fp->_lock);#endif      __sfp_lock_release ();      return NULL;    }  _flockfile (fp);  fp->_file = -1;  c->cookie = (void *) cookie; /* cast away const */  fp->_cookie = c;  if (readfn)    {      c->readfn = readfn;      fp->_read = funreader;      if (writefn)	{	  fp->_flags = __SRW;	  c->writefn = writefn;	  fp->_write = funwriter;	}      else	{	  fp->_flags = __SRD;	  c->writefn = NULL;	  fp->_write = NULL;	}    }  else    {      fp->_flags = __SWR;      c->writefn = writefn;      fp->_write = funwriter;      c->readfn = NULL;      fp->_read = NULL;    }  c->seekfn = seekfn;  fp->_seek = seekfn ? funseeker : NULL;#ifdef __LARGE64_FILES  fp->_seek64 = seekfn ? funseeker64 : NULL;  fp->_flags |= __SL64;#endif  c->closefn = closefn;  fp->_close = funcloser;  _funlockfile (fp);  return fp;}#ifndef _REENT_ONLYFILE *_DEFUN(funopen, (cookie, readfn, writefn, seekfn, closefn),       const void *cookie _AND       funread readfn _AND       funwrite writefn _AND       funseek seekfn _AND       funclose closefn){  return _funopen_r (_REENT, cookie, readfn, writefn, seekfn, closefn);}#endif /* !_REENT_ONLY */

⌨️ 快捷键说明

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