xml.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:9k
- /* Copyright (C) 2000 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- #include "my_global.h"
- #include "m_string.h"
- #include "my_xml.h"
- #define MY_XML_EOF 'E'
- #define MY_XML_STRING 'S'
- #define MY_XML_IDENT 'I'
- #define MY_XML_EQ '='
- #define MY_XML_LT '<'
- #define MY_XML_GT '>'
- #define MY_XML_SLASH '/'
- #define MY_XML_COMMENT 'C'
- #define MY_XML_TEXT 'T'
- #define MY_XML_QUESTION '?'
- #define MY_XML_EXCLAM '!'
- typedef struct xml_attr_st
- {
- const char *beg;
- const char *end;
- } MY_XML_ATTR;
- static const char *lex2str(int lex)
- {
- switch(lex)
- {
- case MY_XML_EOF: return "EOF";
- case MY_XML_STRING: return "STRING";
- case MY_XML_IDENT: return "IDENT";
- case MY_XML_EQ: return "'='";
- case MY_XML_LT: return "'<'";
- case MY_XML_GT: return "'>'";
- case MY_XML_SLASH: return "'/'";
- case MY_XML_COMMENT: return "COMMENT";
- case MY_XML_TEXT: return "TEXT";
- case MY_XML_QUESTION: return "'?'";
- case MY_XML_EXCLAM: return "'!'";
- }
- return "UNKNOWN";
- }
- static void my_xml_norm_text(MY_XML_ATTR *a)
- {
- for ( ; (a->beg < a->end) && strchr(" trn",a->beg[0]) ; a->beg++ );
- for ( ; (a->beg < a->end) && strchr(" trn",a->end[-1]) ; a->end-- );
- }
- static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
- {
- int lex;
-
- for( ; ( p->cur < p->end) && strchr(" trn",p->cur[0]) ; p->cur++);
-
- if (p->cur >= p->end)
- {
- a->beg=p->end;
- a->end=p->end;
- lex=MY_XML_EOF;
- goto ret;
- }
-
- a->beg=p->cur;
- a->end=p->cur;
-
- if ((p->end - p->cur > 3) && !bcmp(p->cur,"<!--",4))
- {
- for( ; (p->cur < p->end) && bcmp(p->cur, "-->", 3); p->cur++)
- {}
- if (!bcmp(p->cur, "-->", 3))
- p->cur+=3;
- a->end=p->cur;
- lex=MY_XML_COMMENT;
- }
- else if (strchr("?=/<>!",p->cur[0]))
- {
- p->cur++;
- a->end=p->cur;
- lex=a->beg[0];
- }
- else if ( (p->cur[0]=='"') || (p->cur[0]==''') )
- {
- p->cur++;
- for( ; ( p->cur < p->end ) && (p->cur[0] != a->beg[0]); p->cur++)
- {}
- a->end=p->cur;
- if (a->beg[0]==p->cur[0])p->cur++;
- a->beg++;
- my_xml_norm_text(a);
- lex=MY_XML_STRING;
- }
- else
- {
- for(;
- (p->cur < p->end) && !strchr("?'"=/<> trn", p->cur[0]);
- p->cur++)
- {}
- a->end=p->cur;
- my_xml_norm_text(a);
- lex=MY_XML_IDENT;
- }
- #if 0
- printf("LEX=%s[%d]n",lex2str(lex),a->end-a->beg);
- #endif
- ret:
- return lex;
- }
- static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
- {
- return (st->value) ? (st->value)(st,str,len) : MY_XML_OK;
- }
- static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
- {
- if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
- {
- sprintf(st->errstr,"To deep XML");
- return MY_XML_ERROR;
- }
- if (st->attrend > st->attr)
- {
- st->attrend[0]='.';
- st->attrend++;
- }
- memcpy(st->attrend,str,len);
- st->attrend+=len;
- st->attrend[0]=' ';
- return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
- }
- static void mstr(char *s,const char *src,uint l1, uint l2)
- {
- l1 = l1<l2 ? l1 : l2;
- memcpy(s,src,l1);
- s[l1]=' ';
- }
- static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
- {
- char *e;
- uint glen;
- char s[32];
- char g[32];
- int rc;
-
- /* Find previous '.' or beginning */
- for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
- glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
-
- if (str && (slen != glen))
- {
- mstr(s,str,sizeof(s)-1,slen);
- mstr(g,e+1,sizeof(g)-1,glen),
- sprintf(p->errstr,"'</%s>' unexpected ('</%s>' wanted)",s,g);
- return MY_XML_ERROR;
- }
-
- rc = p->leave_xml ? p->leave_xml(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
-
- *e=' ';
- p->attrend=e;
-
- return rc;
- }
- int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
- {
- p->attrend=p->attr;
- p->beg=str;
- p->cur=str;
- p->end=str+len;
-
- while ( p->cur < p->end )
- {
- MY_XML_ATTR a;
- if(p->cur[0]=='<')
- {
- int lex;
- int question=0;
- int exclam=0;
-
- lex=my_xml_scan(p,&a);
-
- if (MY_XML_COMMENT==lex)
- {
- continue;
- }
-
- lex=my_xml_scan(p,&a);
-
- if (MY_XML_SLASH==lex)
- {
- if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
- {
- sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
- return MY_XML_ERROR;
- }
- if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
- return MY_XML_ERROR;
- lex=my_xml_scan(p,&a);
- goto gt;
- }
-
- if (MY_XML_EXCLAM==lex)
- {
- lex=my_xml_scan(p,&a);
- exclam=1;
- }
- else if (MY_XML_QUESTION==lex)
- {
- lex=my_xml_scan(p,&a);
- question=1;
- }
-
- if (MY_XML_IDENT==lex)
- {
- if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
- return MY_XML_ERROR;
- }
- else
- {
- sprintf(p->errstr,"3: %s unexpected (ident or '/' wanted)",
- lex2str(lex));
- return MY_XML_ERROR;
- }
-
- while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
- {
- MY_XML_ATTR b;
- if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
- {
- lex=my_xml_scan(p,&b);
- if ( (lex==MY_XML_IDENT) || (lex==MY_XML_STRING) )
- {
- if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
- (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
- (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
- return MY_XML_ERROR;
- }
- else
- {
- sprintf(p->errstr,"4: %s unexpected (ident or string wanted)",
- lex2str(lex));
- return MY_XML_ERROR;
- }
- }
- else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
- {
- if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
- (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
- return MY_XML_ERROR;
- }
- else
- break;
- }
-
- if (lex==MY_XML_SLASH)
- {
- if(MY_XML_OK!=my_xml_leave(p,NULL,0))
- return MY_XML_ERROR;
- lex=my_xml_scan(p,&a);
- }
-
- gt:
- if (question)
- {
- if (lex!=MY_XML_QUESTION)
- {
- sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
- return MY_XML_ERROR;
- }
- if(MY_XML_OK!=my_xml_leave(p,NULL,0))
- return MY_XML_ERROR;
- lex=my_xml_scan(p,&a);
- }
-
- if (exclam)
- {
- if(MY_XML_OK!=my_xml_leave(p,NULL,0))
- return MY_XML_ERROR;
- }
-
- if (lex!=MY_XML_GT)
- {
- sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
- return MY_XML_ERROR;
- }
- }
- else
- {
- a.beg=p->cur;
- for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++);
- a.end=p->cur;
-
- my_xml_norm_text(&a);
- if (a.beg!=a.end)
- {
- my_xml_value(p,a.beg,a.end-a.beg);
- }
- }
- }
- return MY_XML_OK;
- }
- void my_xml_parser_create(MY_XML_PARSER *p)
- {
- bzero((void*)p,sizeof(p[0]));
- }
- void my_xml_parser_free(MY_XML_PARSER *p __attribute__((unused)))
- {
- }
- void my_xml_set_value_handler(MY_XML_PARSER *p,
- int (*action)(MY_XML_PARSER *p, const char *s,
- uint l))
- {
- p->value=action;
- }
- void my_xml_set_enter_handler(MY_XML_PARSER *p,
- int (*action)(MY_XML_PARSER *p, const char *s,
- uint l))
- {
- p->enter=action;
- }
- void my_xml_set_leave_handler(MY_XML_PARSER *p,
- int (*action)(MY_XML_PARSER *p, const char *s,
- uint l))
- {
- p->leave_xml=action;
- }
- void my_xml_set_user_data(MY_XML_PARSER *p, void *user_data)
- {
- p->user_data=user_data;
- }
- const char *my_xml_error_string(MY_XML_PARSER *p)
- {
- return p->errstr;
- }
- uint my_xml_error_pos(MY_XML_PARSER *p)
- {
- const char *beg=p->beg;
- const char *s;
- for ( s=p->beg ; s<p->cur; s++)
- {
- if (s[0]=='n')
- beg=s;
- }
- return p->cur-beg;
- }
- uint my_xml_error_lineno(MY_XML_PARSER *p)
- {
- uint res=0;
- const char *s;
- for ( s=p->beg ; s<p->cur; s++)
- {
- if (s[0]=='n')
- res++;
- }
- return res;
- }