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

📄 _v_scanf.c

📁 newos is new operation system
💻 C
字号:
/*** Copyright 2003, Justin Smith. All rights reserved.** Distributed under the terms of the NewOS License.** 2003/09/01*/#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <limits.h>#include <ctype.h>#include <unistd.h>/* gross hack to get this to link inside the kernel */#if _KERNEL#include <kernel/vfs.h>#define read(fd, buf, size) sys_read(fd, buf, -1, size)#endifint _v_scanf( int (*_read)(void*), void (*_push)(void*, unsigned char),	 void* arg, const unsigned char *, va_list);/**********************************************************//* sscanf functions					  *//**********************************************************/struct _sscanf_struct{	int unget;	int count;	unsigned char const *str;    int pos;};static void _sscanf_push(void *p, unsigned char c){	struct _sscanf_struct *val = (struct _sscanf_struct*)p;		if(val->unget >= 0)	{		//problems		return;	}	val->unget = c;}static int _sscanf_read(void* p){    int ch;	struct _sscanf_struct *val = (struct _sscanf_struct*)p;	if(val->unget >= 0)	{		int c = val->unget;		val->unget = -1;		return c;	}    if((ch = val->str[val->pos++]) == 0)    {	val->pos--;	return 0;    }    val->count++;	return ch;}int vsscanf(char const *str, char const *format, va_list arg_ptr){    int ret_val;    struct _sscanf_struct *val = (struct _sscanf_struct*)malloc(sizeof(struct _sscanf_struct));    val->unget = -1;    val->count = 0;    val->pos = 0;    val->str = str;    ret_val = _v_scanf(_sscanf_read, _sscanf_push, val, format, arg_ptr);	free(val);	return ret_val;}/**********************************************************//* fscanf functions					  *//**********************************************************/struct _fscanf_struct{	int count;	FILE* stream;};static void _fscanf_push(void *p, unsigned char c){	struct _fscanf_struct *val = (struct _fscanf_struct*)p;	FILE* stream = val->stream;	if(stream->flags & _STDIO_UNGET)	{		//a problem		return;	}	val->count--;	stream->flags &= !_STDIO_EOF;	stream->flags |= _STDIO_UNGET;	stream->unget = c;}static int _fscanf_read(void *p){	struct _fscanf_struct *val = (struct _fscanf_struct*)p;	unsigned char c;	FILE* stream;	stream = val->stream;    if(stream->flags & _STDIO_UNGET)	{		stream->flags &= stream->flags ^ _STDIO_UNGET;		return stream->unget;	}    	if (stream->rpos >= stream->buf_pos)    {	int len = read(stream->fd, stream->buf, stream->buf_size);	if (len==0)	{	    stream->flags |= _STDIO_EOF;	    return EOF;	}	else if (len < 0)	{	    stream->flags |= _STDIO_ERROR;	    return EOF;	}	stream->rpos=0;	stream->buf_pos=len;    }	c = stream->buf[stream->rpos++];	val->count++;    return (int)c;}int vfscanf( FILE *stream, char const *format, va_list arg_ptr){	int ret_val;	struct _fscanf_struct *val = (struct _fscanf_struct*)malloc(sizeof(struct _fscanf_struct));	val->count = 0;	val->stream = stream;    ret_val = _v_scanf(_fscanf_read, _fscanf_push, val, format, arg_ptr);	free(val);	return ret_val;}/**********************************************************//* value size determination functions			  *//**********************************************************/typedef enum{	SHORT,	INT,	LONG,	LONGLONG} valSize;/*static valSize _getValSize(char c, int (*_read)(void*), void* arg){	if(c == 'h')	{		return SHORT;	}	if(c == 'l')	{		return LONG;	}	if( c == 'L')	{		return LONGLONG;	}	return INT;}*//**********************************************************//* utility functions					  *//**********************************************************//*static bool _isIntegralType(char c){	return c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x'		|| c == 'X' || c == 'p';}static bool _isFloatingType(char c){	return c == 'E' || c == 'G'		|| c == 'e' || c == 'f' || c == 'g';}static bool _isType(char c){	return _isIntegralType(c) || _isFloatingType(c) || c == 'n' || c == 'c' || c == '%' || c == '[';}*/static int _read_next_non_space( int (*_read)(void*), void* arg){	int c = _read(arg);	while(isspace(c))	{		c = _read(arg);	}	return c;}/*  The code for this function is mostly taken from strtoull */static long long convertIntegralValue(int (*_read)(void*), void (*_push)(void*, unsigned char), void *arg, int base, short width){	unsigned long long acc;	int c;	unsigned long long qbase, cutoff;	int neg, any, cutlim;	int length = 0;	do {		c = _read(arg);	} while (isspace(c));	if(c <= 0)	{		// what to do?		return 0;	}	if(width == 0)	{		return 0;	}	if (c == (int)'-') {		neg = 1;		length++;		c = _read(arg);	} else {		neg = 0;		if (c == (int)'+')		{			length++;			c = _read(arg);		}	}	if(c <= 0)	{		// what to do?		return 0;	}	if(width > 0 && length >= width)	{		return 0;	}	if (base == 0 || base == 16)	{		unsigned char c_next = _read(arg);	    if(c == '0' && (c_next == 'x' || c_next == 'X'))		{			c = _read(arg);			base = 16;		}		else		{			if(c <= 0 || c_next <= 0)			{				// what to do?				return 0;			}			_push(arg, c_next);		}	}	if(c <= 0)	{		// what to do?		return 0;	}	if(width > 0 && length >= width)	{		return 0;	}	if (base == 0)	{		base = c == '0' ? 8 : 10;	}	qbase = (unsigned)base;	cutoff = (unsigned long long)ULLONG_MAX / qbase;	cutlim = (unsigned long long)ULLONG_MAX % qbase;	for (acc = 0, any = 0;; c = _read(arg), length++)	{		if(c <= 0)		{			goto finish;		}		if(width > 0 && length > width)		{			_push(arg, c);			goto finish;		}		if (!isascii(c))		break;		if (isdigit(c))			c -= '0';		else if (isalpha(c))			c -= isupper(c) ? 'A' - 10 : 'a' - 10;		else			break;		if (c >= base)			break;		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))			any = -1;		else		{			any = 1;			acc *= qbase;			acc += c;		}	}finish:	if (any < 0)	{		acc = ULLONG_MAX;	}	else if (neg)		acc = -acc;	return (long long)acc;}/**********************************************************//* the function						  *//**********************************************************/int _v_scanf( int (*_read)(void*), void (*_push)(void*, unsigned char),	 void* arg, const unsigned char *format, va_list arg_ptr){	unsigned int fieldsRead = 0;	unsigned char fch;	while (*format)	{		long long temp = 0;		fch = *format++;	if(isspace(fch))	{			if(isspace(_read(arg)))			{				break;			}			return EOF;		}		else if(fch != '%')		{			if(fch == _read_next_non_space(_read, arg))			{				break;			}			return EOF;		}		else		{			bool suppressAssignment = false;			short width = -1;			valSize size = INT;keeplooking:			fch = *format++;			switch(fch)			{				case '%':					if(_read_next_non_space(_read, arg) != '%')					{						return EOF;					}					break;				case '*':					suppressAssignment = true;					goto keeplooking;				case '0':				case '1':				case '2':				case '3':				case '4':				case '5':				case '6':				case '7':				case '8':				case '9':					if(width == -1)					{						width = 0;					}					do					{						width = 10 * width + (unsigned int)(fch - (unsigned char)'0');						fch = *format++;					}					while(isdigit(fch));					format--;					goto keeplooking;				case 'h':					size = SHORT;					goto keeplooking;				case 'l':					size = LONG;					goto keeplooking;				case 'L':					size = LONGLONG;					goto keeplooking;				case 'u':				{					temp = convertIntegralValue(_read, _push, arg, 10, width);					fieldsRead++;					switch(size)					{						case SHORT:						{							unsigned short* us = (unsigned short*)va_arg(arg_ptr, unsigned short*);							if(temp > USHRT_MAX)							{								*us = USHRT_MAX;								break;							}							*us = (unsigned short)temp;						}						break;						case INT:						{							unsigned int *ui = (unsigned int*)va_arg(arg_ptr, unsigned int*);							if(temp > UINT_MAX)							{								*ui = UINT_MAX;								break;							}							*ui = (unsigned int)temp;						}						break;						case LONG:						{							unsigned long *ul = (unsigned long*)va_arg(arg_ptr, unsigned long*);							if(temp > ULONG_MAX)							{								*ul = ULONG_MAX;								break;							}							*ul = (unsigned long)temp;						}						break;						default:						{							unsigned long long *ull = (unsigned long long*)va_arg(arg_ptr, unsigned long long*);							*ull = (unsigned long long)temp;						}						break;					}				}				break;				case 'i':					temp = (long long)convertIntegralValue(_read, _push, arg, 0, width);					goto read_signed_int;				case 'd':					temp = (long long)convertIntegralValue(_read, _push, arg, 10, width);					goto read_signed_int;				case 'o':					temp = (long long)convertIntegralValue(_read, _push, arg, 8, width);					goto read_signed_int;				case 'x':				case 'X':				case 'p':				{					temp = (long long)convertIntegralValue(_read, _push, arg, 16, width);read_signed_int:					fieldsRead++;					switch(size)					{						case SHORT:						{							short* s = (short*)va_arg(arg_ptr, short*);							if(temp > SHRT_MAX)							{								*s = SHRT_MAX;								break;							}							else if(temp < SHRT_MIN)							{								*s = SHRT_MIN;								break;							}							*s = (unsigned short)temp;						}						break;						case INT:						{							int *i = (int*)va_arg(arg_ptr, int*);							if(temp > INT_MAX)							{								*i = INT_MAX;								break;							}							else if(temp < INT_MIN)							{								*i = INT_MIN;							}							*i = (unsigned int)temp;						}						break;						case LONG:						{							long *l = (long*)va_arg(arg_ptr, long*);							if(temp > LONG_MAX)							{								*l = LONG_MAX;								break;							}							else if(temp < LONG_MIN)							{								*l = LONG_MIN;							}							*l = (unsigned long)temp;						}						break;						default:						{							long long *ll = (long long*)va_arg(arg_ptr, unsigned long long*);							*ll = (long long)temp;						}					}				}				break;				case 'c':				{					unsigned char* c = (unsigned char*)va_arg(arg_ptr, unsigned char*);					int i = 0;					if(width == -1)						width = 1;					for(; i < width; i++)					{						int temp = _read(arg);						if(temp < 0)						{							break;						}						*(c+i) = temp;						if(!temp)							break;					}				}				break;				// Dangerous to use without specifying width.				case 's':				{					width = 10;					unsigned char* c = (unsigned char*)va_arg(arg_ptr, unsigned char*);					int i = 0;					do					{						int temp = _read(arg);						if(temp <= 0 || isspace(temp))							break;						*(c+i++) = temp;					}while(!(width >= 0 && i >= width));					*(c+i) = '\0';					break;				}				default:					// not yet implemented					return EOF;			}		}	}	return fieldsRead;}

⌨️ 快捷键说明

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