xml.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include "my_global.h"
  14. #include "m_string.h"
  15. #include "my_xml.h"
  16. #define MY_XML_EOF 'E'
  17. #define MY_XML_STRING 'S'
  18. #define MY_XML_IDENT 'I'
  19. #define MY_XML_EQ '='
  20. #define MY_XML_LT '<'
  21. #define MY_XML_GT '>'
  22. #define MY_XML_SLASH '/'
  23. #define MY_XML_COMMENT 'C'
  24. #define MY_XML_TEXT 'T'
  25. #define MY_XML_QUESTION '?'
  26. #define MY_XML_EXCLAM   '!'
  27. typedef struct xml_attr_st
  28. {
  29.   const char *beg;
  30.   const char *end;
  31. } MY_XML_ATTR;
  32. static const char *lex2str(int lex)
  33. {
  34.   switch(lex)
  35.   {
  36.     case MY_XML_EOF:      return "EOF";
  37.     case MY_XML_STRING:   return "STRING";
  38.     case MY_XML_IDENT:    return "IDENT";
  39.     case MY_XML_EQ:       return "'='";
  40.     case MY_XML_LT:       return "'<'";
  41.     case MY_XML_GT:       return "'>'";
  42.     case MY_XML_SLASH:    return "'/'";
  43.     case MY_XML_COMMENT:  return "COMMENT";
  44.     case MY_XML_TEXT:     return "TEXT";
  45.     case MY_XML_QUESTION: return "'?'";
  46.     case MY_XML_EXCLAM:   return "'!'";
  47.   }
  48.   return "UNKNOWN";
  49. }
  50. static void my_xml_norm_text(MY_XML_ATTR *a)
  51. {
  52.   for ( ; (a->beg < a->end) && strchr(" trn",a->beg[0]) ; a->beg++ );
  53.   for ( ; (a->beg < a->end) && strchr(" trn",a->end[-1]) ; a->end-- );
  54. }
  55. static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
  56. {
  57.   int lex;
  58.   
  59.   for(  ; ( p->cur < p->end) && strchr(" trn",p->cur[0]) ;  p->cur++);
  60.   
  61.   if (p->cur >= p->end)
  62.   {
  63.     a->beg=p->end;
  64.     a->end=p->end;
  65.     lex=MY_XML_EOF;
  66.     goto ret;
  67.   }
  68.   
  69.   a->beg=p->cur;
  70.   a->end=p->cur;
  71.   
  72.   if ((p->end - p->cur > 3) && !bcmp(p->cur,"<!--",4))
  73.   {
  74.     for( ; (p->cur < p->end) && bcmp(p->cur, "-->", 3); p->cur++)
  75.     {}
  76.     if (!bcmp(p->cur, "-->", 3))
  77.       p->cur+=3;
  78.     a->end=p->cur;
  79.     lex=MY_XML_COMMENT;
  80.   }
  81.   else if (strchr("?=/<>!",p->cur[0]))
  82.   {
  83.     p->cur++;
  84.     a->end=p->cur;
  85.     lex=a->beg[0];
  86.   }
  87.   else if ( (p->cur[0]=='"') || (p->cur[0]==''') )
  88.   {
  89.     p->cur++;
  90.     for(  ; ( p->cur < p->end ) && (p->cur[0] != a->beg[0]); p->cur++)
  91.     {}
  92.     a->end=p->cur;
  93.     if (a->beg[0]==p->cur[0])p->cur++;
  94.     a->beg++;
  95.     my_xml_norm_text(a);
  96.     lex=MY_XML_STRING;
  97.   }
  98.   else
  99.   {
  100.     for(;
  101. (p->cur < p->end) && !strchr("?'"=/<> trn", p->cur[0]);
  102. p->cur++)
  103.     {}
  104.     a->end=p->cur;
  105.     my_xml_norm_text(a);
  106.     lex=MY_XML_IDENT;
  107.   }
  108. #if 0
  109.   printf("LEX=%s[%d]n",lex2str(lex),a->end-a->beg);
  110. #endif
  111. ret:
  112.   return lex;
  113. }
  114. static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
  115. {
  116.   return (st->value) ? (st->value)(st,str,len) : MY_XML_OK;
  117. }
  118. static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
  119. {
  120.   if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
  121.   {
  122.     sprintf(st->errstr,"To deep XML");
  123.     return MY_XML_ERROR;
  124.   }
  125.   if (st->attrend > st->attr)
  126.   {
  127.     st->attrend[0]='.';
  128.     st->attrend++;
  129.   }
  130.   memcpy(st->attrend,str,len);
  131.   st->attrend+=len;
  132.   st->attrend[0]='';
  133.   return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
  134. }
  135. static void mstr(char *s,const char *src,uint l1, uint l2)
  136. {
  137.   l1 = l1<l2 ? l1 : l2;
  138.   memcpy(s,src,l1);
  139.   s[l1]='';
  140. }
  141. static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
  142. {
  143.   char *e;
  144.   uint glen;
  145.   char s[32];
  146.   char g[32];
  147.   int  rc;
  148.   
  149.   /* Find previous '.' or beginning */
  150.   for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
  151.   glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
  152.   
  153.   if (str && (slen != glen))
  154.   {
  155.     mstr(s,str,sizeof(s)-1,slen);
  156.     mstr(g,e+1,sizeof(g)-1,glen),
  157.     sprintf(p->errstr,"'</%s>' unexpected ('</%s>' wanted)",s,g);
  158.     return MY_XML_ERROR;
  159.   }
  160.   
  161.   rc = p->leave_xml ? p->leave_xml(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
  162.   
  163.   *e='';
  164.   p->attrend=e;
  165.   
  166.   return rc;
  167. }
  168. int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
  169. {
  170.   p->attrend=p->attr;
  171.   p->beg=str;
  172.   p->cur=str;
  173.   p->end=str+len;
  174.   
  175.   while ( p->cur < p->end )
  176.   {
  177.     MY_XML_ATTR a;
  178.     if(p->cur[0]=='<')
  179.     {
  180.       int lex;
  181.       int question=0;
  182.       int exclam=0;
  183.       
  184.       lex=my_xml_scan(p,&a);
  185.       
  186.       if (MY_XML_COMMENT==lex)
  187.       {
  188.         continue;
  189.       }
  190.       
  191.       lex=my_xml_scan(p,&a);
  192.       
  193.       if (MY_XML_SLASH==lex)
  194.       {
  195.         if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
  196.         {
  197.           sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
  198.           return MY_XML_ERROR;
  199.         }
  200.         if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
  201.           return MY_XML_ERROR;
  202.         lex=my_xml_scan(p,&a);
  203.         goto gt;
  204.       }
  205.       
  206.       if (MY_XML_EXCLAM==lex)
  207.       {
  208.         lex=my_xml_scan(p,&a);
  209.         exclam=1;
  210.       }
  211.       else if (MY_XML_QUESTION==lex)
  212.       {
  213.         lex=my_xml_scan(p,&a);
  214.         question=1;
  215.       }
  216.       
  217.       if (MY_XML_IDENT==lex)
  218.       {
  219.         if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
  220.           return MY_XML_ERROR;
  221.       }
  222.       else
  223.       {
  224.         sprintf(p->errstr,"3: %s unexpected (ident or '/' wanted)",
  225. lex2str(lex));
  226.         return MY_XML_ERROR;
  227.       }
  228.       
  229.       while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
  230.       {
  231.         MY_XML_ATTR b;
  232.         if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
  233.         {
  234.           lex=my_xml_scan(p,&b);
  235.           if ( (lex==MY_XML_IDENT) || (lex==MY_XML_STRING) )
  236.           {
  237.             if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))  ||
  238.                (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg))  ||
  239.                (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
  240.               return MY_XML_ERROR;
  241.           }
  242.           else
  243.           {
  244.             sprintf(p->errstr,"4: %s unexpected (ident or string wanted)",
  245.     lex2str(lex));
  246.             return MY_XML_ERROR;
  247.           }
  248.         }
  249.         else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
  250.         {
  251.           if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
  252.              (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
  253.            return MY_XML_ERROR;
  254.         }
  255.         else
  256.           break;
  257.       }
  258.       
  259.       if (lex==MY_XML_SLASH)
  260.       {
  261.         if(MY_XML_OK!=my_xml_leave(p,NULL,0))
  262.           return MY_XML_ERROR;
  263.         lex=my_xml_scan(p,&a);
  264.       }
  265.       
  266. gt:
  267.       if (question)
  268.       {
  269.         if (lex!=MY_XML_QUESTION)
  270.         {
  271.           sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
  272.           return MY_XML_ERROR;
  273.         }
  274.         if(MY_XML_OK!=my_xml_leave(p,NULL,0))
  275.           return MY_XML_ERROR;
  276.         lex=my_xml_scan(p,&a);
  277.       }
  278.       
  279.       if (exclam)
  280.       {
  281.         if(MY_XML_OK!=my_xml_leave(p,NULL,0))
  282.           return MY_XML_ERROR;
  283.       }
  284.       
  285.       if (lex!=MY_XML_GT)
  286.       {
  287.         sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
  288.         return MY_XML_ERROR;
  289.       }
  290.     }
  291.     else
  292.     {
  293.       a.beg=p->cur;
  294.       for ( ; (p->cur < p->end) && (p->cur[0]!='<')  ; p->cur++);
  295.       a.end=p->cur;
  296.       
  297.       my_xml_norm_text(&a);
  298.       if (a.beg!=a.end)
  299.       {
  300.         my_xml_value(p,a.beg,a.end-a.beg);
  301.       }
  302.     }
  303.   }
  304.   return MY_XML_OK;
  305. }
  306. void my_xml_parser_create(MY_XML_PARSER *p)
  307. {
  308.   bzero((void*)p,sizeof(p[0]));
  309. }
  310. void my_xml_parser_free(MY_XML_PARSER *p  __attribute__((unused)))
  311. {
  312. }
  313. void my_xml_set_value_handler(MY_XML_PARSER *p,
  314.       int (*action)(MY_XML_PARSER *p, const char *s,
  315.     uint l))
  316. {
  317.   p->value=action;
  318. }
  319. void my_xml_set_enter_handler(MY_XML_PARSER *p,
  320.       int (*action)(MY_XML_PARSER *p, const char *s,
  321.     uint l))
  322. {
  323.   p->enter=action;
  324. }
  325. void my_xml_set_leave_handler(MY_XML_PARSER *p,
  326.       int (*action)(MY_XML_PARSER *p, const char *s,
  327.     uint l))
  328. {
  329.   p->leave_xml=action;
  330. }
  331. void my_xml_set_user_data(MY_XML_PARSER *p, void *user_data)
  332. {
  333.   p->user_data=user_data;
  334. }
  335. const char *my_xml_error_string(MY_XML_PARSER *p)
  336. {
  337.   return p->errstr;
  338. }
  339. uint my_xml_error_pos(MY_XML_PARSER *p)
  340. {
  341.   const char *beg=p->beg;
  342.   const char *s;
  343.   for ( s=p->beg ; s<p->cur; s++)
  344.   {
  345.     if (s[0]=='n')
  346.       beg=s;
  347.   }
  348.   return p->cur-beg;
  349. }
  350. uint my_xml_error_lineno(MY_XML_PARSER *p)
  351. {
  352.   uint res=0;
  353.   const char *s;
  354.   for ( s=p->beg ; s<p->cur; s++)
  355.   {
  356.     if (s[0]=='n')
  357.       res++;
  358.   }
  359.   return res;
  360. }