489 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			489 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * $Id$
 | |
|  *
 | |
|     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
 | |
| 
 | |
|     Redistribution and use in source and binary forms, with or without
 | |
|     modification, are permitted provided that the following conditions
 | |
|     are met:
 | |
|     1. Redistributions of source code must retain the above copyright
 | |
|        notice, this list of conditions and the following disclaimer.
 | |
|     2. Redistributions in binary form must reproduce the above copyright
 | |
|        notice, this list of conditions and the following disclaimer in the
 | |
|        documentation and/or other materials provided with the distribution.
 | |
| 
 | |
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 | |
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
|  
 | |
| #ifndef _QSE_SI_SIO_H_
 | |
| #define _QSE_SI_SIO_H_
 | |
| 
 | |
| /** @file
 | |
|  * This file defines a simple stream I/O interface.
 | |
|  */
 | |
| 
 | |
| #include <qse/types.h>
 | |
| #include <qse/macros.h>
 | |
| #include <qse/si/fio.h>
 | |
| #include <qse/si/tio.h>
 | |
| #include <qse/si/mtx.h>
 | |
| #include <stdarg.h>
 | |
| 
 | |
| enum qse_sio_flag_t
 | |
| {
 | |
| 	/* ensure that these enumerators never overlap with
 | |
| 	 * qse_fio_flag_t enumerators. you can use values between
 | |
| 	 * (1<<0) and (1<<7) inclusive reserved in qse_fio_flag_t.
 | |
| 	 * the range is represented by QSE_FIO_RESERVED. */
 | |
| 	QSE_SIO_LINEBREAK     = (1 << 0), /* expand \n to a system line-break convention if necessary */
 | |
| 	QSE_SIO_IGNOREMBWCERR = (1 << 1),
 | |
| 	QSE_SIO_NOAUTOFLUSH   = (1 << 2),
 | |
| 	QSE_SIO_KEEPPATH      = (1 << 3),
 | |
| 	QSE_SIO_REENTRANT     = (1 << 4),
 | |
| 
 | |
| 	/* ensure that the following enumerators are one of
 | |
| 	 * qse_fio_flags_t enumerators */
 | |
| 	QSE_SIO_HANDLE        = QSE_FIO_HANDLE,
 | |
| 	QSE_SIO_TEMPORARY     = QSE_FIO_TEMPORARY,
 | |
| 	QSE_SIO_NOCLOSE       = QSE_FIO_NOCLOSE,
 | |
| 	QSE_SIO_READ          = QSE_FIO_READ,
 | |
| 	QSE_SIO_WRITE         = QSE_FIO_WRITE,
 | |
| 	QSE_SIO_APPEND        = QSE_FIO_APPEND,
 | |
| 	QSE_SIO_CREATE        = QSE_FIO_CREATE,
 | |
| 	QSE_SIO_TRUNCATE      = QSE_FIO_TRUNCATE,
 | |
| 	QSE_SIO_EXCLUSIVE     = QSE_FIO_EXCLUSIVE,
 | |
| 	QSE_SIO_SYNC          = QSE_FIO_SYNC,
 | |
| 	QSE_SIO_NOFOLLOW      = QSE_FIO_NOFOLLOW,
 | |
| 	QSE_SIO_NOSHREAD      = QSE_FIO_NOSHREAD,
 | |
| 	QSE_SIO_NOSHWRITE     = QSE_FIO_NOSHWRITE,
 | |
| 	QSE_SIO_NOSHDELETE    = QSE_FIO_NOSHDELETE,
 | |
| 	QSE_SIO_RANDOM        = QSE_FIO_RANDOM,
 | |
| 	QSE_SIO_SEQUENTIAL    = QSE_FIO_SEQUENTIAL
 | |
| };
 | |
| 
 | |
| enum qse_sio_errnum_t
 | |
| {
 | |
| 	QSE_SIO_ENOERR = 0, /**< no error */
 | |
| 	QSE_SIO_EOTHER,     /**< other error */
 | |
| 	QSE_SIO_ENOIMPL,    /**< not implemented */
 | |
| 	QSE_SIO_ESYSERR,    /**< subsystem(system call) error */
 | |
| 	QSE_SIO_EINTERN,    /**< internal error */
 | |
| 
 | |
| 	QSE_SIO_ENOMEM,     /**< out of memory */
 | |
| 	QSE_SIO_EINVAL,     /**< invalid parameter */
 | |
| 	QSE_SIO_EACCES,     /**< access denied */
 | |
| 	QSE_SIO_EPERM,      /**< operation not permitted */
 | |
| 	QSE_SIO_ENOENT,     /**< no such file */
 | |
| 	QSE_SIO_EEXIST,     /**< already exist */
 | |
| 	QSE_SIO_ENOTDIR,    /**< not a directory */
 | |
| 	QSE_SIO_EINTR,      /**< interrupted */
 | |
| 	QSE_SIO_EPIPE,      /**< broken pipe */
 | |
| 	QSE_SIO_EAGAIN,     /**< resource not available temporarily */
 | |
| 
 | |
| 	QSE_SIO_EILSEQ,     /**< illegal sequence */
 | |
| 	QSE_SIO_EICSEQ,     /**< incomplete sequence */
 | |
| 	QSE_SIO_EILCHR      /**< illegal character */
 | |
| };
 | |
| typedef enum qse_sio_errnum_t qse_sio_errnum_t;
 | |
| 
 | |
| typedef qse_fio_off_t qse_sio_pos_t;
 | |
| typedef qse_fio_hnd_t qse_sio_hnd_t;
 | |
| typedef qse_fio_std_t qse_sio_std_t;
 | |
| typedef qse_fio_ori_t qse_sio_ori_t;
 | |
| 
 | |
| #define QSE_SIO_STDIN  QSE_FIO_STDIN
 | |
| #define QSE_SIO_STDOUT QSE_FIO_STDOUT
 | |
| #define QSE_SIO_STDERR QSE_FIO_STDERR
 | |
| 
 | |
| #define QSE_SIO_BEGIN   QSE_FIO_BEGIN
 | |
| #define QSE_SIO_CURRENT QSE_FIO_CURRENT
 | |
| #define QSE_SIO_END     QSE_FIO_END
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_t type defines a simple text stream over a file. It also
 | |
|  * provides predefined streams for standard input, output, and error.
 | |
|  */
 | |
| typedef struct qse_sio_t qse_sio_t;
 | |
| 
 | |
| struct qse_sio_t
 | |
| {
 | |
| 	qse_mmgr_t*      mmgr;
 | |
| 	qse_sio_errnum_t errnum;
 | |
| 
 | |
| 	qse_fio_t file;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		qse_tio_t  io;
 | |
| 		qse_sio_t* xtn; /* static extension for tio */
 | |
| 	} tio;
 | |
| 
 | |
| 	qse_mchar_t inbuf[2048];
 | |
| 	qse_mchar_t outbuf[2048];
 | |
| 
 | |
| 	qse_char_t* path;
 | |
| 	qse_mtx_t* mtx;
 | |
| 
 | |
| #if defined(_WIN32) || defined(__OS2__)
 | |
| 	int status;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| /** access the @a errnum field of the #qse_sio_t structure */
 | |
| #define QSE_SIO_ERRNUM(sio)    ((sio)->errnum)
 | |
| 
 | |
| #if defined(__cplusplus)
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_open() fucntion creates a stream object.
 | |
|  */
 | |
| QSE_EXPORT qse_sio_t* qse_sio_open (
 | |
| 	qse_mmgr_t*       mmgr,    /**< memory manager */
 | |
| 	qse_size_t        xtnsize, /**< extension size in bytes */
 | |
| 	const qse_char_t* file,    /**< file name */
 | |
| 	int               flags    /**< number OR'ed of #qse_sio_flag_t */
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_sio_t* qse_sio_openstd (
 | |
| 	qse_mmgr_t*       mmgr,    /**< memory manager */
 | |
| 	qse_size_t        xtnsize, /**< extension size in bytes */
 | |
| 	qse_sio_std_t     std,     /**< standard I/O identifier */
 | |
| 	int               flags    /**< number OR'ed of #qse_sio_flag_t */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_close() function destroys a stream object.
 | |
|  */
 | |
| QSE_EXPORT void qse_sio_close (
 | |
| 	qse_sio_t* sio  /**< stream */
 | |
| );
 | |
| 
 | |
| QSE_EXPORT int qse_sio_init (
 | |
| 	qse_sio_t*        sio,
 | |
| 	qse_mmgr_t*       mmgr,
 | |
| 	const qse_char_t* file,
 | |
| 	int               flags
 | |
| );
 | |
| 
 | |
| QSE_EXPORT int qse_sio_initstd (
 | |
| 	qse_sio_t*        sio,
 | |
| 	qse_mmgr_t*       mmgr,
 | |
| 	qse_sio_std_t     std,
 | |
| 	int               flags
 | |
| );
 | |
| 
 | |
| QSE_EXPORT void qse_sio_fini (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_mmgr_t* qse_sio_getmmgr (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT void* qse_sio_getxtn (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_sio_errnum_t qse_sio_geterrnum (
 | |
| 	const qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_cmgr_t* qse_sio_getcmgr (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT void qse_sio_setcmgr (
 | |
| 	qse_sio_t*  sio,
 | |
| 	qse_cmgr_t* cmgr
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_sio_hnd_t qse_sio_gethandle (
 | |
| 	const qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| /** 
 | |
|  * The qse_sio_getpath() returns the file path used to open the stream.
 | |
|  * It returns #QSE_NULL if #QSE_SIO_HANDLE was on or #QSE_SIO_KEEPPATH 
 | |
|  * was off at the time of opening.
 | |
|  */
 | |
| QSE_EXPORT const qse_char_t* qse_sio_getpath (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_flush (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_drain() funtion purges all buffered data without writing.
 | |
|  */
 | |
| QSE_EXPORT void qse_sio_drain (
 | |
| 	qse_sio_t* sio
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_getmb (
 | |
| 	qse_sio_t*   sio,
 | |
| 	qse_mchar_t* c
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_getwc (
 | |
| 	qse_sio_t*   sio,
 | |
| 	qse_wchar_t* c
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_getmbs (
 | |
| 	qse_sio_t*   sio,
 | |
| 	qse_mchar_t* buf,
 | |
| 	qse_size_t   size
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_getmbsn (
 | |
| 	qse_sio_t*   sio,
 | |
| 	qse_mchar_t* buf,
 | |
| 	qse_size_t   size
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_getwcs() function reads at most @a size - 1 characters 
 | |
|  * from the stream @a sio into the buffer @a buf. If a new line or EOF
 | |
|  * is encountered, it stops reading from the stream. It null-terminates
 | |
|  * the buffer if @a size is greater than 0. 
 | |
|  */
 | |
| QSE_EXPORT qse_ssize_t qse_sio_getwcs (
 | |
| 	qse_sio_t*   sio,
 | |
| 	qse_wchar_t* buf,
 | |
| 	qse_size_t   size
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_getwcsn() function reads at most @a size characters 
 | |
|  * from the stream @a sio into the buffer @a buf. If a new line or EOF
 | |
|  * is encountered, it stops reading from the stream. 
 | |
|  */
 | |
| QSE_EXPORT qse_ssize_t qse_sio_getwcsn (
 | |
| 	qse_sio_t*   sio,
 | |
| 	qse_wchar_t* buf,
 | |
| 	qse_size_t   size
 | |
| );
 | |
| 
 | |
| #if defined(QSE_CHAR_IS_MCHAR)
 | |
| #	define qse_sio_getc(sio,c) qse_sio_getmb(sio,c)
 | |
| #	define qse_sio_getstr(sio,buf,size) qse_sio_getmbs(sio,buf,size)
 | |
| #	define qse_sio_getstrn(sio,buf,size) qse_sio_getmbsn(sio,buf,size)
 | |
| #else
 | |
| #	define qse_sio_getc(sio,c) qse_sio_getwc(sio,c)
 | |
| #	define qse_sio_getstr(sio,buf,size) qse_sio_getwcs(sio,buf,size)
 | |
| #	define qse_sio_getstrn(sio,buf,size) qse_sio_getwcsn(sio,buf,size)
 | |
| #endif
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putmb (
 | |
| 	qse_sio_t*  sio, 
 | |
| 	qse_mchar_t c
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putwc (
 | |
| 	qse_sio_t*  sio, 
 | |
| 	qse_wchar_t c
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putmbs (
 | |
| 	qse_sio_t*         sio,
 | |
| 	const qse_mchar_t* str
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putwcs (
 | |
| 	qse_sio_t*         sio,
 | |
| 	const qse_wchar_t* str
 | |
| );
 | |
| 
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putmbsn (
 | |
| 	qse_sio_t*         sio, 
 | |
| 	const qse_mchar_t* str,
 | |
| 	qse_size_t         size
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putwcsn (
 | |
| 	qse_sio_t*         sio, 
 | |
| 	const qse_wchar_t* str,
 | |
| 	qse_size_t         size
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putmbsf (
 | |
| 	qse_sio_t*         sio,
 | |
| 	const qse_mchar_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putwcsf (
 | |
| 	qse_sio_t*         sio,
 | |
| 	const qse_wchar_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putmbsvf (
 | |
| 	qse_sio_t*         sio,
 | |
| 	const qse_mchar_t* fmt,
 | |
| 	va_list            ap
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_sio_putwcsvf (
 | |
| 	qse_sio_t*         sio,
 | |
| 	const qse_wchar_t* fmt,
 | |
| 	va_list            ap
 | |
| );
 | |
| 
 | |
| #if defined(QSE_CHAR_IS_MCHAR)
 | |
| #	define qse_sio_putc(sio,c) qse_sio_putmb(sio,c)
 | |
| #	define qse_sio_putstr(sio,str) qse_sio_putmbs(sio,str)
 | |
| #	define qse_sio_putstrn(sio,str,size) qse_sio_putmbsn(sio,str,size)
 | |
| #	define qse_sio_putstrf qse_sio_putmbsf
 | |
| #	define qse_sio_putstrvf(sio,fmt,ap) qse_sio_putmbsvf(sio,fmt,ap)
 | |
| #else
 | |
| #	define qse_sio_putc(sio,c) qse_sio_putwc(sio,c)
 | |
| #	define qse_sio_putstr(sio,str) qse_sio_putwcs(sio,str)
 | |
| #	define qse_sio_putstrn(sio,str,size) qse_sio_putwcsn(sio,str,size)
 | |
| #	define qse_sio_putstrf qse_sio_putwcsf
 | |
| #	define qse_sio_putstrvf(sio,fmt,ap) qse_sio_putwcsvf(sio,fmt,ap)
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_getpos() function gets the current position in a stream.
 | |
|  * Note that it may not return the desired postion due to buffering.
 | |
|  * @return 0 on success, -1 on failure
 | |
|  */
 | |
| QSE_EXPORT int qse_sio_getpos (
 | |
| 	qse_sio_t*     sio,  /**< stream */
 | |
| 	qse_sio_pos_t* pos   /**< position */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_setpos() function changes the current position in a stream.
 | |
|  * @return 0 on success, -1 on failure
 | |
|  */
 | |
| QSE_EXPORT int qse_sio_setpos (
 | |
| 	qse_sio_t*    sio,   /**< stream */
 | |
| 	qse_sio_pos_t pos    /**< position */
 | |
| );
 | |
| 
 | |
| QSE_EXPORT int qse_sio_truncate (
 | |
| 	qse_sio_t*    sio,
 | |
| 	qse_sio_pos_t pos
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The qse_sio_seek() function repositions the current file offset.
 | |
|  * Upon success, \a pos is adjusted to the new offset from the beginning
 | |
|  * of the file.
 | |
|  */
 | |
| QSE_EXPORT int qse_sio_seek (
 | |
| 	qse_sio_t*     sio, 
 | |
| 	qse_sio_pos_t* pos,
 | |
| 	qse_sio_ori_t  origin
 | |
| );
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| QSE_EXPORT int qse_open_stdsios (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| QSE_EXPORT int qse_open_stdsios_with_flags (
 | |
| 	int flags
 | |
| );
 | |
| 
 | |
| QSE_EXPORT void qse_close_stdsios (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_sio_t* qse_get_stdout (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_sio_t* qse_get_stderr (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_putmbsf (
 | |
| 	const qse_mchar_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_putwcsf (
 | |
| 	const qse_wchar_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_putmbsvf (
 | |
| 	const qse_mchar_t* fmt,
 | |
| 	va_list            ap
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_putwcsvf (
 | |
| 	const qse_wchar_t* fmt,
 | |
| 	va_list            ap
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_errputmbsf (
 | |
| 	const qse_mchar_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_errputwcsf (
 | |
| 	const qse_wchar_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_errputmbsvf (
 | |
| 	const qse_mchar_t* fmt,
 | |
| 	va_list            ap
 | |
| );
 | |
| 
 | |
| QSE_EXPORT qse_ssize_t qse_errputwcsvf (
 | |
| 	const qse_wchar_t* fmt,
 | |
| 	va_list            ap
 | |
| );
 | |
| 
 | |
| #if defined(QSE_CHAR_IS_MCHAR)
 | |
| #	define qse_putstrf qse_putmbsf
 | |
| #	define qse_putstrvf(fmt,ap) qse_putmbsvf(fmt,ap)
 | |
| #	define qse_errputstrf qse_errputmbsf
 | |
| #	define qse_errputstrvf(fmt,ap) qse_errputmbsvf(fmt,ap)
 | |
| #else
 | |
| #	define qse_putstrf qse_putwcsf
 | |
| #	define qse_putstrvf(fmt,ap) qse_putwcsvf(fmt,ap)
 | |
| #	define qse_errputstrf qse_errputwcsf
 | |
| #	define qse_errputstrvf(fmt,ap) qse_errputwcsvf(fmt,ap)
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* Some convenience macros */
 | |
| #define QSE_STDOUT (qse_get_stdout())
 | |
| #define QSE_STDERR (qse_get_stderr())
 | |
| #define qse_printf qse_putstrf
 | |
| #define qse_vprintf qse_putstrvf
 | |
| #define qse_fprintf qse_sio_putstrf 
 | |
| #define qse_vfprintf qse_sio_putstrvf 
 | |
| #define qse_fflush qse_sio_flush
 | |
| 
 | |
| 
 | |
| #if defined(__cplusplus)
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #endif
 |