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

📄 ilibparsers.c

📁 解析xml格式的文件的好源码。解析xml格式的文件的好源码。解析xml格式的文件的好源码。解析xml格式的文件的好源码。解析xml格式的文件的好源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct timeval tv;
	int slct;
	int v;
#if !defined(WIN32) && !defined(_WIN32_WCE)
	int TerminatePipe[2];
	int flags;
#endif
	
	//
	// Use this thread as if it's our own. Keep looping until we are signaled to stop
	//
	FD_ZERO(&readset);
	FD_ZERO(&errorset);
	FD_ZERO(&writeset);
	
#if !defined(WIN32) && !defined(_WIN32_WCE)
	// 
	// For posix, we need to use a pipe to force unblock the select loop
	//
	pipe(TerminatePipe);
	flags = fcntl(TerminatePipe[0],F_GETFL,0);
	//
	// We need to set the pipe to nonblock, so we can blindly empty the pipe
	//
	fcntl(TerminatePipe[0],F_SETFL,O_NONBLOCK|flags);
	((struct ILibBaseChain*)Chain)->TerminateReadPipe = fdopen(TerminatePipe[0],"r");
	((struct ILibBaseChain*)Chain)->TerminateWritePipe = fdopen(TerminatePipe[1],"w");
#endif

	while(((struct ILibBaseChain*)Chain)->TerminateFlag==0)
	{
		slct = 0;
		FD_ZERO(&readset);
		FD_ZERO(&errorset);
		FD_ZERO(&writeset);
		tv.tv_sec = UPNP_MAX_WAIT;
		tv.tv_usec = 0;
		
		sem_wait(&ILibChainLock);
#if defined(WIN32) || defined(_WIN32_WCE)
		//
		// Check the fake socket, for ILibForceUnBlockChain
		//
		if(((struct ILibBaseChain*)Chain)->Terminate==~0)
		{
			slct = -1;
		}
		else
		{
			FD_SET(((struct ILibBaseChain*)Chain)->Terminate,&errorset);
		}
#else
		//
		// Put the Read end of the Pipe in the FDSET, for ILibForceUnBlockChain
		//
		FD_SET(TerminatePipe[0],&readset);
#endif
		sem_post(&ILibChainLock);
		
		//
		// Iterate through all the PreSelect function pointers in the chain
		//
		c = (struct ILibBaseChain*)Chain;
		while(c!=NULL && c->Object!=NULL)
		{
			if(((struct ILibChain*)c->Object)->PreSelect!=NULL)
			{
#ifdef MEMORY_CHECK
#ifdef WIN32
				_CrtCheckMemory();
#endif
#endif
				v = (tv.tv_sec*1000) + (tv.tv_usec/1000);
				((struct ILibChain*)c->Object)->PreSelect(c->Object,&readset,&writeset,&errorset,&v);
				tv.tv_sec = v/1000;
				tv.tv_usec = 1000*(v%1000);

#ifdef MEMORY_CHECK
#ifdef WIN32
				_CrtCheckMemory();
#endif
#endif
			}
			c = c->Next;
		}
		//
		// If this flag is set, force the max block time to be zero
		//
		if(slct!=0)
		{
			tv.tv_sec = 0;
			tv.tv_usec = 0;
		}

		//
		// The actual Select Statement
		//
		slct = select(FD_SETSIZE,&readset,&writeset,&errorset,&tv);
		if(slct==-1)
		{
			//
			// If the select simply timed out, we need to clear these sets
			//
			FD_ZERO(&readset);
			FD_ZERO(&writeset);
			FD_ZERO(&errorset);
		}
		
#if defined(WIN32) || defined(_WIN32_WCE)
		//
		// Reinitialise our fake socket if necessary
		//
		if(((struct ILibBaseChain*)Chain)->Terminate==~0)
		{
			((struct ILibBaseChain*)Chain)->Terminate = socket(AF_INET,SOCK_DGRAM,0);
		}
#else
		if(FD_ISSET(TerminatePipe[0],&readset))
		{
			//
			// Empty the pipe
			//
			while(fgetc(((struct ILibBaseChain*)Chain)->TerminateReadPipe)!=EOF)
			{
			}
		}
#endif
		//
		// Iterate through all of the PostSelect in the chain
		//
		c = (struct ILibBaseChain*)Chain;
		while(c!=NULL && c->Object!=NULL)
		{
			if(((struct ILibChain*)c->Object)->PostSelect!=NULL)
			{
#ifdef MEMORY_CHECK
#ifdef WIN32
				_CrtCheckMemory();
#endif
#endif
				((struct ILibChain*)c->Object)->PostSelect(c->Object,slct,&readset,&writeset,&errorset);
#ifdef MEMORY_CHECK
#ifdef WIN32
				_CrtCheckMemory();
#endif
#endif
			}
			c = c->Next;
		}
	}

	//
	// This loop will start, when the Chain was signaled to quit. Clean up the chain
	// by iterating through all the Destroy.
	//
	c = (struct ILibBaseChain*)Chain;
	while(c!=NULL && c->Object!=NULL)
	{
		if(((struct ILibChain*)c->Object)->Destroy!=NULL)
		{
			((struct ILibChain*)c->Object)->Destroy(c->Object);
		}
		//
		// After calling the Destroy, we free the link
		//
		free(c->Object);
		c = c->Next;
	}
	
	//
	// Now we actually free the chain
	//
	c = (struct ILibBaseChain*)Chain;
#if !defined(WIN32) && !defined(_WIN32_WCE)
	//
	// Free the pipe resources
	//
	fclose(c->TerminateReadPipe);
	fclose(c->TerminateWritePipe);
#endif
	while(c!=NULL)
	{
		temp = c->Next;
		free(c);
		c = temp;
	}
#ifdef WIN32
	WSACleanup();
#endif
	if(ILibChainLock_RefCounter==1)
	{
		sem_destroy(&ILibChainLock);
	}
	--ILibChainLock_RefCounter;
}

/*! \fn ILibStopChain(void *Chain)
	\brief Stops a chain
	\para
	This will signal the microstack thread to shutdown. When the chain cleans itself up, 
	the thread that is blocked on ILibStartChain will return.
	\param Chain The Chain to stop
*/
void ILibStopChain(void *Chain)
{
	((struct ILibBaseChain*)Chain)->TerminateFlag = 1;
	ILibForceUnBlockChain(Chain);
}


/*! \fn ILibDestructXMLNodeList(struct ILibXMLNode *node)
	\brief Frees resources from an XMLNodeList tree that was returned from ILibParseXML
	\param node The XML Tree to clean up
*/
void ILibDestructXMLNodeList(struct ILibXMLNode *node)
{
	struct ILibXMLNode *temp;
	while(node!=NULL)
	{
		temp = node->Next;
		if(node->Reserved2!=NULL)
		{
			// If there was a namespace table, delete it
			ILibDestroyHashTree(node->Reserved2);
		}
		free(node);
		node = temp;
	}
}

/*! \fn ILibDestructXMLAttributeList(struct ILibXMLAttribute *attribute)
	\brief Frees resources from an AttributeList that was returned from ILibGetXMLAttributes
	\param attribute The Attribute Tree to clean up
*/
void ILibDestructXMLAttributeList(struct ILibXMLAttribute *attribute)
{
	struct ILibXMLAttribute *temp;
	while(attribute!=NULL)
	{
		temp = attribute->Next;
		free(attribute);
		attribute = temp;
	}
}

/*! \fn ILibProcessXMLNodeList(struct ILibXMLNode *nodeList)
	\brief Pro-process an XML node list
	\para
	Checks XML for validity, while at the same time populate helper properties on each node,
	such as Parent, Peer, etc, to aid in XML parsing.
	\param nodeList The XML Tree to process
	\returns 0 if the XML is valid, nonzero otherwise
*/
int ILibProcessXMLNodeList(struct ILibXMLNode *nodeList)
{
	int RetVal = 0;
	struct ILibXMLNode *current = nodeList;
	struct ILibXMLNode *temp;
	void *TagStack;
	
	ILibCreateStack(&TagStack);
	
	//
	// Iterate through the node list, and setup all the pointers
	// such that all StartElements have pointers to EndElements,
	// And all StartElements have pointers to siblings and parents.
	//
	while(current!=NULL)
	{
		if(memcmp(current->Name,"!",1)==0)
		{
			// Comment
			temp = current;
			current = (struct ILibXMLNode*)ILibPeekStack(&TagStack);
			if(current!=NULL)
			{
				current->Next = temp->Next;
			}
			else
			{
				current = temp;
			}
		}
		else if(current->StartTag!=0)
		{
			// Start Tag
			current->Parent = ILibPeekStack(&TagStack);
			ILibPushStack(&TagStack,current);
		}
		else
		{
			// Close Tag

			//
			// Check to see if there is supposed to be an EndElement
			//
			temp = (struct ILibXMLNode*)ILibPopStack(&TagStack);
			if(temp!=NULL)
			{
				//
				// Checking to see if this EndElement is correct in scope
				//
				if(temp->NameLength==current->NameLength && memcmp(temp->Name,current->Name,current->NameLength)==0)
				{
					//
					// Now that we know this EndElement is correct, set the Peer
					// pointers of the previous sibling
					//
					if(current->Next!=NULL)
					{
						if(current->Next->StartTag!=0)
						{
							temp->Peer = current->Next;
						}
					}
					temp->ClosingTag = current;
					current->StartingTag = temp;
				}
				else
				{
					// Illegal Close Tag Order
					RetVal = -2;
					break;
				}
			}
			else
			{
				// Illegal Close Tag
				RetVal = -1;
				break;
			}
		}
		current = current->Next;
	}
	
	//
	// If there are still elements in the stack, that means not all the StartElements
	// have associated EndElements, which means this XML is not valid XML.
	//
	if(TagStack!=NULL)
	{
		// Incomplete XML
		RetVal = -3;
		ILibClearStack(&TagStack);
	}
	
	return(RetVal);
}

/*! \fn ILibXML_LookupNamespace(struct ILibXMLNode *currentLocation, char *prefix, int prefixLength)
	\brief Resolves a namespace prefix from the scope of the given node
	\param currentLocation The node used to start the resolve
	\param prefix The namespace prefix to resolve
	\param prefixLength The lenght of the prefix
	\returns The resolved namespace. NULL if unable to resolve
*/
char* ILibXML_LookupNamespace(struct ILibXMLNode *currentLocation, char *prefix, int prefixLength)
{
	struct ILibXMLNode *temp = currentLocation;
	int done=0;
	char* RetVal = "";

	//
	// If the specified Prefix is zero length, we interpret that to mean
	// they want to lookup the default namespace
	//
	if(prefixLength==0)
	{
		//
		// This is the default namespace prefix
		//
		prefix = "xmlns";
		prefixLength = 5;
	}


	//
	// From the current node, keep traversing up the parents, until we find a match.
	// Each step we go up, is a step wider in scope.
	//
	do
	{
		if(temp->Reserved2!=NULL)
		{
			if(ILibHasEntry(temp->Reserved2,prefix,prefixLength)!=0)
			{
				//
				// As soon as we find the namespace declaration, stop
				// iterating the tree, as it would be a waste of time
				//
				RetVal = (char*)ILibGetEntry(temp->Reserved2,prefix,prefixLength);
				done=1;
			}
		}
		temp = temp->Parent;
	}while(temp!=NULL && done==0);
	return(RetVal);
}

/*! \fn ILibXML_BuildNamespaceLookupTable(struct ILibXMLNode *node)
	\brief Builds the lookup table used by ILibXML_LookupNamespace
	\param node This node will be the highest scoped
*/
void ILibXML_BuildNamespaceLookupTable(struct ILibXMLNode *node)
{
	struct ILibXMLAttribute *attr,*currentAttr;
	struct ILibXMLNode *current = node;

	//
	// Iterate through all the StartElements, and build a table of the declared namespaces
	//
	while(current!=NULL)
	{
		if(current->StartTag!=0)
		{
			//
			// Reserved2 is the HashTable containing the fully qualified namespace
			// keyed by the namespace prefix
			//
			current->Reserved2 = ILibInitHashTree();
			currentAttr = attr = ILibGetXMLAttributes(current);
			if(attr!=NULL)
			{
				//
				// Iterate through all the attributes to find namespace declarations
				//
				while(currentAttr!=NULL)
				{
					if(currentAttr->NameLength==5 && memcmp(currentAttr->Name,"xmlns",5)==0)
					{
						// Default Namespace Declaration
						//currentAttr->Value[currentAttr->ValueLength]=0;
						ILibAddEntry(current->Reserved2,"xmlns",5,currentAttr->Value,currentAttr->ValueLength);
					}
					else if(currentAttr->PrefixLength==5 && memcmp(currentAttr->Prefix,"xmlns",5)==0)
					{
						// Other Namespace Declaration
						//currentAttr->Value[currentAttr->ValueLength]=0;
						ILibAddEntry(current->Reserved2,currentAttr->Name,currentAttr->NameLength,currentAttr->Value,currentAttr->ValueLength);
					}
					currentAttr=currentAttr->Next;
				}
				ILibDestructXMLAttributeList(attr);
			}
		}
		current = current->Next;
	}
}


/*! \fn ILibReadInnerXML(struct ILibXMLNode *node, char **RetVal)
	\brief Reads the data segment from an ILibXMLNode
	\para
	The data is a pointer into the original string that the XML was read from.
	\param node The node to read the data from
	\param RetVal The data
	\returns The length of the data read
*/
int ILibReadInnerXML(struct ILibXMLNode *node, char **RetVal)
{
	struct ILibXMLNode *x = node;
	int length = 0;
	void *TagStack;
	*RetVal = NULL;
	
	//
	// Starting with the current StartElement, we use this stack to find the matching
	// EndElement, so we can figure out what we need to return
	//
	ILibCreateStack(&TagStack);
	do
	{
		if(x->StartTag!=0) {ILibPushStack(&TagStack,x);}
		if(x!=NULL)
		{
			x = x->Next;
		}
		else
		{
			return(0);
		}
	}while(!(x->StartTag==0 && ILibPopStack(&TagStack)==node && x->NameLength==node->NameLength && memcmp(x->Name,node->Name,node->NameLength)==0));
	
	//
	// The Reserved fields of the StartElement and EndElement are used as pointers representing
	// the data segment of the XML
	//
	length = (int)((char*)x->Reserved - (char*)node->Reserved - 1);
	if(length<0) {length=0;}
	*RetVal = (char*)node->Reserved;
	return(length);
}

⌨️ 快捷键说明

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