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

📄 uri.l

📁 this is very good for teacher
💻 L
📖 第 1 页 / 共 2 页
字号:
}<FRAGMENT>.|\n		|<FRAGMENT><<EOF>>	{	yyless(0);	BEGIN ACCEPT;}<ACCEPT>.|\n		|<ACCEPT><<EOF>>		{	yyless(0);	return __length;}<INITIAL>{URI-reference}	return yyleng;<INITIAL>.|\n		|<INITIAL><<EOF>>	{	yyless(0);	return 0;}%%int yywrap(void){	return 1;}#define URI_INIT(uri) \do {							\	(uri)->scheme = NULL;		\	(uri)->authority = NULL;	\	(uri)->path = NULL;			\	(uri)->query = NULL;		\	(uri)->fragment = NULL;		\} while (0)static int __uri_parse(struct uri *uri){	URI_INIT(uri);	__uri = uri;	__length = 0;	BEGIN SCHEME;	return yylex();}/* Scan a file and return the length of the uri. Return negative number * when and only when failed to allocate memory. */int uri_parse_file(struct uri *uri, FILE *file){	YY_BUFFER_STATE buf;	int n = -1;	yyin = file;	if (buf = yy_create_buffer(yyin, YY_BUF_SIZE))	{		yy_switch_to_buffer(buf);		n = __uri_parse(uri);		yy_delete_buffer(buf);	}	return n;}/* Scan a string ('\0' terminated). */int uri_parse_string(struct uri *uri, const char *string){	YY_BUFFER_STATE buf;	int n = -1;	if (buf = yy_scan_string(string))	{		yy_switch_to_buffer(buf);		n = __uri_parse(uri);		yy_delete_buffer(buf);	}	return n;}/* Scan some memory bytes. */int uri_parse_bytes(struct uri *uri, const char *bytes, int len){	YY_BUFFER_STATE buf;	int n = -1;	if (buf = yy_scan_bytes(bytes, len))	{		yy_switch_to_buffer(buf);		n = __uri_parse(uri);		yy_delete_buffer(buf);	}	return n;}/* Scan some memory bytes. The last two bytes of the memory MUST be '\0', or * the function will return -1 indicating a failure. This function has better * performance than "uri_parse_bytes", but note there is NO "const" key * word before the "base" argument, which means the content of memory may * be changed. */int uri_parse_buffer(struct uri *uri, char *base, unsigned int size){	YY_BUFFER_STATE buf;	int n = -1;	if (buf = yy_scan_buffer(base, size))	{		yy_switch_to_buffer(buf);		n = __uri_parse(uri);		yy_delete_buffer(buf);	}	return n;}void uri_destroy(struct uri *uri){	URI_FREE(uri->scheme);	if (uri->authority)	{		URI_AUTH_DESTROY(uri->authority);		free(uri->authority);	}	URI_FREE(uri->path);	URI_FREE(uri->query);	URI_FREE(uri->fragment);}int __uri_length(void){	BEGIN INITIAL;	return yylex();}int uri_length_string(const char *string){	YY_BUFFER_STATE buf;	int n = -1;	if (buf = yy_scan_string(string))	{		yy_switch_to_buffer(buf);		n = __uri_length();		yy_delete_buffer(buf);	}	return n;}int uri_length_bytes(const char *bytes, int len){	YY_BUFFER_STATE buf;	int n = -1;	if (buf = yy_scan_bytes(bytes, len))	{		yy_switch_to_buffer(buf);		n = __uri_length();		yy_delete_buffer(buf);	}	return n;}/* Validate a string ('\0' terminated). */int uri_validate_string(const char *string){	int n = uri_length_string(string);	return n >= 0 ? n == strlen(string) : n;}/* Validate some memory bytes. */int uri_validate_bytes(const char *bytes, int len){	int n = uri_length_bytes(bytes, len);	return n >= 0 ? n == len : n;}/* Merge two path. It sounds easy but indeed quite troublesome if you take * everything into consideration. Core of merging two URIs. The function will * allocate memory for you, which is NOT a very good programming style you * should not follow. */int __uri_path_merge(char **abs_path,					 const char *rel_path, const char *base_path){	int len;	STACK *stack;	const char *curpos;	int seglen;	const char *next_slash;	int i;	/* This merging algorithm is different from RFC 2396, which uses string,	 * while this algorithm uses stack. */	if (!(stack = stack_create(STACK_INITIAL_SIZE)))		return -1;	/* The "base_path" and the "rel_path" are divided into segments and push	 * all these segments and their length into the stack. If a segment	 * is ".", ignore it; if a segment is "..", pop one segment out. */	len = 0;	for (i = 0; i < 2; i++)	{		/* Both "rel_path" and "base_path" can be NULL. */		if (curpos = base_path)		{			while (next_slash = strchr(curpos, '/'))			{				if (strncmp(curpos, "../", next_slash - curpos + 1) == 0)				{					if (stack_height(stack) > sizeof (char *) + sizeof (int) ||						!stack_empty(stack) && stack_top(stack, int) != 1)					{						len -= stack_pop(stack, int);						stack_pop(stack, const char *);					}				}				else if (strncmp(curpos, "./", next_slash - curpos + 1) != 0)				{					len += next_slash - curpos + 1;					if (stack_push(stack, curpos, const char *) < 0 ||						stack_push(stack, next_slash - curpos + 1, int) < 0)					{						stack_destroy(stack);						return -1;					}				}				curpos = next_slash + 1;			}				base_path = rel_path;		}	}	/* This part deals with the "filename", which may be empty, may be "..",	 * may be ".", and may be something else like "index.html". */	if (curpos)	{		if (strcmp(curpos, "..") == 0)		{			if (stack_height(stack) > sizeof (char *) + sizeof (int) ||				!stack_empty(stack) && stack_top(stack, int) != 1)			{				len -= stack_pop(stack, int);				stack_pop(stack, const char *);			}		}		else if (strcmp(curpos, ".") != 0)		{			len += strlen(curpos);			if (stack_push(stack, curpos, const char *) < 0 ||				stack_push(stack, strlen(curpos), int) < 0)			{				stack_destroy(stack);				return -1;			}		}	}	/* The result path is an "empty path". We should turn it into "no path".	 * "no path" is allowed while "empty path" is illegal. */	if (len == 0)	{		*abs_path = NULL;		return 0;	}	/* Example:	 * rel_path: "../././../game/../document/rfc/rfc2616.pdf"	 * base_path: "/pub/incoming/./software/linux/nasm.tar.gz",	 * Now the stack is:	 *	 *	+---------------+		<-- stack top	 *	|	11			|	 *	+---------------|	 *	|	rfc2616.pdf	|	 *	+---------------|	 *	|	4			|	 *	|---------------|	 *	|	rfc/		|	 *	|---------------|	 *	|	9			|	 *	|---------------|	 *	|	document/	|	 *	|---------------|	 *	|	9			|	 *	|---------------|	 *	|	incoming/	|	 *	|---------------|	 *	|	4			|	 *	|---------------|	 *	|	pub/		|	 *	|---------------|	 *	|	1			|	 *	|---------------|	 *	|	/			|	 *	+---------------+		<-- stack base	 *	 * len = 1 + 4 + 9 + 9 + 4 + 11 = ??	 *	 * Note that we do NOT copy the segments into the stack, we just push the	 * pointers into the stack.	 *	 * All the information we need to compose the result path has been here.	 */	if (*abs_path = (char *)malloc((len + 1) * sizeof (char)))	{		*abs_path = *abs_path + len;		**abs_path = '\0';		while (!stack_empty(stack))		{			seglen = stack_pop(stack, int);			*abs_path -= seglen;			memcpy(*abs_path, stack_pop(stack, const char *), seglen);		}	}	else		len = -1;	stack_destroy(stack);	return len;}int uri_merge(struct uri *abs_uri,			  const struct uri *rel_uri, const struct uri *base_uri){	int len, n;	/* I am lazy. */	#define __URI_STRDUP(str) \	({																	\		char *__res;													\		if (str)														\		{																\			if (__res = strdup(str))									\				len += strlen(__res);									\			else														\				break;													\		}																\		else															\			__res = NULL;												\		__res;															\	})	#define __URI_AUTH_DUP(auth) \	({																	\		struct authority *__res;										\		if (auth)														\		{																\			if (__res = (struct authority *)							\						malloc(sizeof (struct authority)))				\				URI_AUTH_INIT(__res, (auth)->type);						\			else														\				break;													\			if ((auth)->type == AT_SERVER)								\			{															\				if (__res->userinfo = __URI_STRDUP((auth)->userinfo))	\					len++;												\				__res->host = __URI_STRDUP((auth)->host);				\				if (__res->port = __URI_STRDUP((auth)->port))			\					len++;												\			}															\			else														\				__res->reg_name = __URI_STRDUP((auth)->reg_name);		\			len += 2;													\		}																\		else															\			__res = NULL;												\		__res;															\	})	URI_INIT(abs_uri);	len = 0;	do {		/* If the relative URI has a scheme, take it; else take the scheme		 * of the base URI. */		if (rel_uri->scheme)		{			abs_uri->scheme = __URI_STRDUP(rel_uri->scheme);			len++;		}		else if (abs_uri->scheme = __URI_STRDUP(base_uri->scheme))			len++;		/* If the relative URI has a scheme or an authority, take it's		 * authority; else take the authority of the base URI. */		if (rel_uri->scheme || rel_uri->authority)			abs_uri->authority = __URI_AUTH_DUP(rel_uri->authority);		else			abs_uri->authority = __URI_AUTH_DUP(base_uri->authority);		/* If the relative URI has a scheme or an authority or an absolute		 * path, take it's path; else if the relative URI does not have a		 * path, take the base URI's path; else if base URI has a path,		 * merge the relative URI's path with the base URI's path, and take		 * the result; else if the base URI has no path, merge the relative		 * URI's path with path "/" and take the result; no else. */		if (rel_uri->scheme || rel_uri->authority ||									rel_uri->path && *rel_uri->path == '/')			abs_uri->path = __URI_STRDUP(rel_uri->path);		else if (!rel_uri->path)			abs_uri->path = __URI_STRDUP(base_uri->path);		else if ((n = __uri_path_merge(&abs_uri->path, rel_uri->path,								base_uri->path ? base_uri->path : "/")) >= 0)			len += n;		else			break;		/* Query is taken from relative URI. */		if (abs_uri->query = __URI_STRDUP(rel_uri->query))			len++;		/* Fragment is taken from relative URI. */		if (abs_uri->fragment = __URI_STRDUP(rel_uri->fragment))			len++;		return len;	} while (0);	#undef __URI_AUTH_DUP	#undef __URI_STRDUP	uri_destroy(abs_uri);	return -1;}/* Recombine a URI structure into a URI string. Quite boring. */int uri_recombine(const struct uri *uri, char *uristr, unsigned int len){	char *curpos = uristr;	char *end = curpos + len;	unsigned int n;	do {		if (uri->scheme)		{			n = strlen(uri->scheme);			if (curpos + n + 1 < end)			{				MEMCPY_PLUS(curpos, uri->scheme, n);				*curpos++ = ':';			}			else				break;		}		if (uri->authority)		{			if (curpos + 2 < end)			{				*curpos++ = '/';				*curpos++ = '/';			}			else				break;			if (uri->authority->type == AT_SERVER)			{				if (uri->authority->userinfo)				{					n = strlen(uri->authority->userinfo);					if (curpos + n + 1 < end)					{						MEMCPY_PLUS(curpos, uri->authority->userinfo, n);						*curpos++ = '@';					}					else						break;				}				if (uri->authority->host)				{					n = strlen(uri->authority->host);					if (curpos + n < end)						MEMCPY_PLUS(curpos, uri->authority->host, n);					else						break;				}				if (uri->authority->port)				{					n = strlen(uri->authority->port);					if (curpos + n + 1 < end)					{						*curpos++ = ':';						MEMCPY_PLUS(curpos, uri->authority->port, n);					}					else						break;				}			}			else if (uri->authority->type == AT_REG_NAME)			{				if (uri->authority->reg_name)				{					n = strlen(uri->authority->reg_name);					if (curpos + n < end)						MEMCPY_PLUS(curpos, uri->authority->reg_name, n);					else						break;				}			}		}		if (uri->path)		{			n = strlen(uri->path);			if (curpos + n < end)				MEMCPY_PLUS(curpos, uri->path, n);			else				break;		}		if (uri->query)		{			n = strlen(uri->query);			if (curpos + n + 1 < end)			{				*curpos++ = '?';				MEMCPY_PLUS(curpos, uri->query, n);			}			else				break;		}		if (uri->fragment)		{			n = strlen(uri->fragment);			if (curpos + n + 1 < end)			{				*curpos++ = '#';				MEMCPY_PLUS(curpos, uri->fragment, n);			}			else				break;		}		if (curpos < end)			*curpos = '\0';		else			break;		return curpos - uristr;	} while (0);	errno = ENOSPC;	return -1;}

⌨️ 快捷键说明

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