📄 ilibparsers.c
字号:
// c = (char*)node->Reserved - 1; while(*c!='<') { // // The Reserved field of the StartElement points to the first character after // the '>' of the StartElement. Just work our way backwards to find the start of // the StartElement // c = c -1; } c = c +1; // // Now that we isolated the string in between the '<' and the '>' we can parse the // string as delimited by ' ', because thats what delineates attributes. We need // to use ILibParseStringAdv because these attributes can be within quotation marks // // // But before we start, replace linefeeds and carriage-return-linefeeds to spaces // for(i=0;i<(int)((char*)node->Reserved - c -EndReserved);++i) { if(c[i]==10 || c[i]==13 || c[i]==9 || c[i]==0) { c[i]=' '; } } xml = ILibParseStringAdv(c,0,(int)((char*)node->Reserved - c -EndReserved)," ",1); field = xml->FirstResult; // // We skip the first token, because the first token, is the Element name // if(field!=NULL) {field = field->NextResult;} // // Iterate through all the other tokens, as these are all attributes // while(field!=NULL) { if(field->datalength>0 && field->data[0]!=10 && field->data[0]!=13) { if(RetVal==NULL) { // // If we haven't already created an Attribute node, create it now // RetVal = (struct ILibXMLAttribute*)malloc(sizeof(struct ILibXMLAttribute)); RetVal->Next = NULL; } else { // // We already created an Attribute node, so simply create a new one, and // attach it on the beginning of the old one. // current = (struct ILibXMLAttribute*)malloc(sizeof(struct ILibXMLAttribute)); current->Next = RetVal; RetVal = current; } // // Parse each token by the ':' // If this results in more than one token, we can figure that the first token // is the namespace prefix // temp2 = ILibParseStringAdv(field->data,0,field->datalength,":",1); if(temp2->NumResults==1) { // // This attribute has no prefix, so just parse on the '=' // The first token is the attribute name, the other is the value // RetVal->Prefix = NULL; RetVal->PrefixLength = 0; temp3 = ILibParseStringAdv(field->data,0,field->datalength,"=",1); } else { // // Since there is a namespace prefix, seperate that out, and parse the remainder // on the '=' to figure out what the attribute name and value are // RetVal->Prefix = temp2->FirstResult->data; RetVal->PrefixLength = temp2->FirstResult->datalength; temp3 = ILibParseStringAdv(field->data,RetVal->PrefixLength+1,field->datalength-RetVal->PrefixLength-1,"=",1); } // // After attaching the pointers, we can free the results, as all the data // is a pointer into the original string. We can think of the nodes we created // as templates. Once done, we don't need them anymore. // ILibDestructParserResults(temp2); RetVal->Parent = node; RetVal->Name = temp3->FirstResult->data; RetVal->NameLength = temp3->FirstResult->datalength; RetVal->Value = temp3->LastResult->data; RetVal->ValueLength = temp3->LastResult->datalength; // // Remove the Quote or Apostraphe if it exists // if(RetVal->ValueLength>=2 && (RetVal->Value[0]=='"' || RetVal->Value[0]=='\'')) { RetVal->Value += 1; RetVal->ValueLength -= 2; } ILibDestructParserResults(temp3); } field = field->NextResult; } ILibDestructParserResults(xml); if(CheckName) { node->Name[node->NameLength]=0; } return(RetVal);}/// <summary>/// Parse an XML string/// </summary>/// <para>/// The strings are never copied. Everything is referenced via pointers into the original buffer/// </para>/// <param name="buffer">The buffer to parse</param>/// <param name="offset">The offset in the buffer to start parsing</param>/// <param name="length">The length to parse</param>/// <returns>A tree of ILibXMLNodes, representing the XML document</returns>struct ILibXMLNode *ILibParseXML(char *buffer, int offset, int length){ struct parser_result *xml; struct parser_result_field *field; struct parser_result *temp; struct parser_result *temp2; struct parser_result *temp3; char* TagName; int TagNameLength; int StartTag; int EmptyTag; int i; struct ILibXMLNode *RetVal = NULL; struct ILibXMLNode *current = NULL; struct ILibXMLNode *x = NULL; char *NSTag; int NSTagLength; // // Even though "technically" the first character of an XML document must be < // we're going to be nice, and not enforce that // while(buffer[offset]!='<' && length>0) { ++offset; --length; } if(length==0) { // Garbage in Garbage out :) RetVal = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode)); memset(RetVal,0,sizeof(struct ILibXMLNode)); return(RetVal); } // // All XML Elements start with a '<' character. If we delineate the string with // this character, we can go from there. // xml = ILibParseString(buffer,offset,length,"<",1); field = xml->FirstResult; while(field!=NULL) { // // Ignore the XML declarator // if(field->datalength !=0 && memcmp(field->data,"?",1)!=0) { EmptyTag = 0; if(memcmp(field->data,"/",1)==0) { // // The first character after the '<' was a '/', so we know this is the // EndElement // StartTag = 0; field->data = field->data+1; field->datalength -= 1; // // If we look for the '>' we can find the end of this element // temp2 = ILibParseString(field->data,0,field->datalength,">",1); } else { // // The first character after the '<' was not a '/' so we know this is a // StartElement // StartTag = -1; // // If we look for the '>' we can find the end of this element // temp2 = ILibParseString(field->data,0,field->datalength,">",1); if(temp2->FirstResult->datalength>0 && temp2->FirstResult->data[temp2->FirstResult->datalength-1]=='/') { // // If this element ended with a '/' this is an EmptyElement // EmptyTag = -1; } } // // Parsing on the ' ', we can isolate the Element name from the attributes. // The first token, being the element name // temp = ILibParseString(temp2->FirstResult->data,0,temp2->FirstResult->datalength," ",1); // // Now that we have the token that contains the element name, we need to parse on the ":" // because we need to figure out what the namespace qualifiers are // temp3 = ILibParseString(temp->FirstResult->data,0,temp->FirstResult->datalength,":",1); if(temp3->NumResults==1) { // // If there is only one token, there was no namespace prefix. // The whole token is the attribute name // NSTag = NULL; NSTagLength = 0; TagName = temp3->FirstResult->data; TagNameLength = temp3->FirstResult->datalength; } else { // // The first token is the namespace prefix, the second is the attribute name // NSTag = temp3->FirstResult->data; NSTagLength = temp3->FirstResult->datalength; TagName = temp3->FirstResult->NextResult->data; TagNameLength = temp3->FirstResult->NextResult->datalength; } ILibDestructParserResults(temp3); // // Iterate through the tag name, to figure out what the exact length is, as // well as check to see if its an empty element // for(i=0;i<TagNameLength;++i) { if( (TagName[i]==' ')||(TagName[i]=='/')||(TagName[i]=='>')||(TagName[i]=='\t')||(TagName[i]=='\r')||(TagName[i]=='\n') ) { if(i!=0) { if(TagName[i]=='/') { EmptyTag = -1; } TagNameLength = i; break; } } } if(TagNameLength!=0) { // // Instantiate a new ILibXMLNode for this element // x = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode)); memset(x,0,sizeof(struct ILibXMLNode)); x->Name = TagName; x->NameLength = TagNameLength; x->StartTag = StartTag; x->NSTag = NSTag; x->NSLength = NSTagLength; if(StartTag==0) { // // The Reserved field of StartElements point to te first character before // the '<'. // x->Reserved = field->data; do { x->Reserved -= 1; }while(*((char*)x->Reserved)=='<'); } else { // // The Reserved field of EndElements point to the end of the element // x->Reserved = temp2->LastResult->data; } if(RetVal==NULL) { RetVal = x; } else { current->Next = x; } current = x; if(EmptyTag!=0) { // // If this was an empty element, we need to create a bogus EndElement, // just so the tree is consistent. No point in introducing unnecessary complexity // x = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode)); memset(x,0,sizeof(struct ILibXMLNode)); x->Name = TagName; x->NameLength = TagNameLength; x->NSTag = NSTag; x->NSLength = NSTagLength; x->Reserved = current->Reserved; current->EmptyTag = -1; current->Next = x; current = x; } } ILibDestructParserResults(temp2); ILibDestructParserResults(temp); } field = field->NextResult; } ILibDestructParserResults(xml); return(RetVal);}/// <summary>/// Create an empty Queue/// </summary>/// <returns>An empty queue</returns>void *ILibQueue_Create(void){ struct ILibQueueNode *RetVal = (struct ILibQueueNode*)malloc(sizeof(struct ILibQueueNode)); memset(RetVal,0,sizeof(struct ILibQueueNode)); return(RetVal);}/// <summary>/// Locks a queue/// </summary>/// <param name="q">The queue to lock</param>void ILibQueue_Lock(void *q){}/// <summary>/// Unlocks a queue/// </summary>/// <param name="q">The queue to unlock</param>void ILibQueue_UnLock(void *q){}/// <summary>/// Frees the resources associated with a queue/// </summary>/// <param name="q">The queue to free</param>void ILibQueue_Destroy(void *q){ struct ILibQueueNode *qn = (struct ILibQueueNode*)q; struct ILibStackNode *temp; temp = qn->Head; while(temp!=NULL) { qn->Head = qn->Head->Next; free(temp); temp = qn->Head; } free(qn);}/// <summary>/// Checks to see if a queue is empty/// </summary>/// <param name="q">The queue to check</param>/// <returns>zero value if not empty, non-zero if empty</returns>int ILibQueue_IsEmpty(void *q){ struct ILibQueueNode *qn = (struct ILibQueueNode*)q; return(qn->Head==NULL?1:0);}/// <summary>/// Add an item to the queue/// </summary>/// <param name="q">The queue to add </param>/// <param name="data">The data to add to the queue</param>void ILibQueue_EnQueue(void *q, void *data){ struct ILibQueueNode *qn = (struct ILibQueueNode*)q; struct ILibStackNode *sn = (struct ILibStackNode*)malloc(sizeof(struct ILibStackNode)); sn->Data = data; sn->Next = NULL; if(qn->Head==NULL) { // // If there is no head, this new entry is the head // qn->Head = sn; qn->Tail = sn; } else { // // Since there is already a head, just attach this entry to the tail, and // call this the new tail // qn->Tail->Next = sn; qn->Tail = sn; }}/// <summary>/// Removes an item from the queue/// </summary>/// <param name="q">The queue to remove an item from</param>/// <returns>The item removed from the queue. NULL if empty</returns>void *ILibQueue_DeQueue(void *q){ struct ILibQueueNode *qn = (struct ILibQueueNode*)q; struct ILibStackNode *temp; void *RetVal = NULL; if(qn->Head==NULL) {return(NULL);} temp = qn->Head; RetVal = qn->Head->Data; qn->Head = qn->Head->Next; if(qn->Head==NULL) {qn->Tail = NULL;} free(temp); return(RetVal);}/// <summary>/// Peeks at an item from the queue/// </summary>/// <param name="q">The queue to peek an item from</param>/// <returns>The item from the queue. NULL if empty</returns>void *ILibQueue_PeekQueue(void *q){ struct ILibQueueNode *qn = (struct ILibQueueNode*)q; if(qn->Head==NULL) { return(NULL); } else { return(qn->Head->Data); }}/// <summary>/// Creates an empty Stack/// </summary>/// <para>/// This module uses a void* that is preinitialized to NULL, eg:/// void *stack = NULL;/// ILibCreateStack(&stack);/// </para>/// <param name="TheStack">A void* to use for the stack. Simply pass in a void* by reference</param>void ILibCreateStack(void **TheStack){ *TheStack = NULL;}/// <summary>/// Push an item onto the stack/// </summary>/// <param name="TheStack">The stack to push to</param>/// <param name="data">The data to push onto the stack</param>void ILibPushStack(void **TheStack, void *data){ struct ILibStackNode *RetVal = (struct ILibStackNode*)malloc(sizeof(struct ILibStackNode)); RetVal->Data = data; RetVal->Next = *TheStack; *TheStack = RetVal;}/// <summary>/// Pop an item from the stack/// </summary>/// <param name="TheStack">The stack to pop from</param>/// <returns>The item that was popped from the stack</returns>void *ILibPopStack(void **TheStack){ void *RetVal = NULL; void *Temp; if(*TheStack!=NULL) { RetVal = ((struct ILibStackNode*)*TheStack)->Data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -