summaryrefslogtreecommitdiff
path: root/strings/xml.c
diff options
context:
space:
mode:
authorunknown <bar@bar.mysql.r18.ru>2003-01-10 16:34:53 +0400
committerunknown <bar@bar.mysql.r18.ru>2003-01-10 16:34:53 +0400
commitf00289c43105a539c5db456f097803100c2b68ba (patch)
treed07938522be5fe422e0f5db14459d2651185f587 /strings/xml.c
parent408c41e9749e6af677cceb901e9ebd3449b80a52 (diff)
downloadmariadb-git-f00289c43105a539c5db456f097803100c2b68ba.tar.gz
xml.c:
new file
Diffstat (limited to 'strings/xml.c')
-rw-r--r--strings/xml.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/strings/xml.c b/strings/xml.c
new file mode 100644
index 00000000000..4f6301249ae
--- /dev/null
+++ b/strings/xml.c
@@ -0,0 +1,374 @@
+/* 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(" \t\r\n",a->beg[0]) ; a->beg++ );
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",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(" \t\r\n",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 (!memcmp(p->cur,"<!--",4))
+ {
+ for( ; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++);
+ if(!memcmp(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("?'\"=/<> \t\r\n", 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]='\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]='\0';
+}
+
+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 ? p->leave(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
+
+ *e='\0';
+ 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=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;
+}