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

📄 mxml-file.c

📁 适用于嵌入式系统的XML解析库, 规模比libxml2小得多.
💻 C
📖 第 1 页 / 共 5 页
字号:
	else if (ch == 0xfe)	{	 /*	  * UTF-16 big-endian BOM?	  */          ch = getc(fp);	  if (ch != 0xff)	    return (EOF);	  *encoding = ENCODE_UTF16BE;	  return (mxml_file_getc(p, encoding));	}	else if (ch == 0xff)	{	 /*	  * UTF-16 little-endian BOM?	  */          ch = getc(fp);	  if (ch != 0xfe)	    return (EOF);	  *encoding = ENCODE_UTF16LE;	  return (mxml_file_getc(p, encoding));	}	else if ((ch & 0xe0) == 0xc0)	{	 /*	  * Two-byte value...	  */	  if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)	    return (EOF);	  ch = ((ch & 0x1f) << 6) | (temp & 0x3f);	  if (ch < 0x80)	    return (EOF);	}	else if ((ch & 0xf0) == 0xe0)	{	 /*	  * Three-byte value...	  */	  if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)	    return (EOF);	  ch = ((ch & 0x0f) << 6) | (temp & 0x3f);	  if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)	    return (EOF);	  ch = (ch << 6) | (temp & 0x3f);	  if (ch < 0x800)	    return (EOF);	}	else if ((ch & 0xf8) == 0xf0)	{	 /*	  * Four-byte value...	  */	  if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)	    return (EOF);	  ch = ((ch & 0x07) << 6) | (temp & 0x3f);	  if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)	    return (EOF);	  ch = (ch << 6) | (temp & 0x3f);	  if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)	    return (EOF);	  ch = (ch << 6) | (temp & 0x3f);	  if (ch < 0x10000)	    return (EOF);	}	else	  return (EOF);	break;    case ENCODE_UTF16BE :       /*        * Read UTF-16 big-endian char...	*/	ch = (ch << 8) | getc(fp);	if (mxml_bad_char(ch))	{	  mxml_error("Bad control character 0x%02x not allowed by XML standard!",        	     ch);	  return (EOF);	}        else if (ch >= 0xd800 && ch <= 0xdbff)	{	 /*	  * Multi-word UTF-16 char...	  */          int lch = (getc(fp) << 8) | getc(fp);          if (lch < 0xdc00 || lch >= 0xdfff)	    return (EOF);          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;	}	break;    case ENCODE_UTF16LE :       /*        * Read UTF-16 little-endian char...	*/	ch |= (getc(fp) << 8);        if (mxml_bad_char(ch))	{	  mxml_error("Bad control character 0x%02x not allowed by XML standard!",        	     ch);	  return (EOF);	}        else if (ch >= 0xd800 && ch <= 0xdbff)	{	 /*	  * Multi-word UTF-16 char...	  */          int lch = getc(fp) | (getc(fp) << 8);          if (lch < 0xdc00 || lch >= 0xdfff)	    return (EOF);          ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;	}	break;  }#if DEBUG > 1  printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);#endif /* DEBUG > 1 */  return (ch);}/* * 'mxml_file_putc()' - Write a character to a file. */static int				/* O - 0 on success, -1 on failure */mxml_file_putc(int  ch,			/* I - Character to write */               void *p)			/* I - Pointer to file */{  char	buffer[4],			/* Buffer for character */	*bufptr;			/* Pointer into buffer */  int	buflen;				/* Number of bytes to write */  if (ch < 0x80)    return (putc(ch, (FILE *)p) == EOF ? -1 : 0);  bufptr = buffer;  if (ch < 0x800)  {   /*    * Two-byte UTF-8 character...    */    *bufptr++ = 0xc0 | (ch >> 6);    *bufptr++ = 0x80 | (ch & 0x3f);  }  else if (ch < 0x10000)  {   /*    * Three-byte UTF-8 character...    */    *bufptr++ = 0xe0 | (ch >> 12);    *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);    *bufptr++ = 0x80 | (ch & 0x3f);  }  else  {   /*    * Four-byte UTF-8 character...    */    *bufptr++ = 0xf0 | (ch >> 18);    *bufptr++ = 0x80 | ((ch >> 12) & 0x3f);    *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);    *bufptr++ = 0x80 | (ch & 0x3f);  }  buflen = bufptr - buffer;  return (fwrite(buffer, 1, buflen, (FILE *)p) < buflen ? -1 : 0);}/* * 'mxml_get_entity()' - Get the character corresponding to an entity... */static int				/* O  - Character value or EOF on error */mxml_get_entity(mxml_node_t *parent,	/* I  - Parent node */		void        *p,		/* I  - Pointer to source */		int         *encoding,	/* IO - Character encoding */                int         (*getc_cb)(void *, int *))					/* I  - Get character function */{  int	ch;				/* Current character */  char	entity[64],			/* Entity string */	*entptr;			/* Pointer into entity */  entptr = entity;  while ((ch = (*getc_cb)(p, encoding)) != EOF)    if (ch > 126 || (!isalnum(ch) && ch != '#'))      break;    else if (entptr < (entity + sizeof(entity) - 1))      *entptr++ = ch;    else    {      mxml_error("Entity name too long under parent <%s>!",	         parent ? parent->value.element.name : "null");      break;    }  *entptr = '\0';  if (ch != ';')  {    mxml_error("Character entity \"%s\" not terminated under parent <%s>!",	       entity, parent ? parent->value.element.name : "null");    return (EOF);  }  if (entity[0] == '#')  {    if (entity[1] == 'x')      ch = strtol(entity + 2, NULL, 16);    else      ch = strtol(entity + 1, NULL, 10);  }  else if ((ch = mxmlEntityGetValue(entity)) < 0)    mxml_error("Entity name \"%s;\" not supported under parent <%s>!",	       entity, parent ? parent->value.element.name : "null");  if (mxml_bad_char(ch))  {    mxml_error("Bad control character 0x%02x under parent <%s> not allowed by XML standard!",               ch, parent ? parent->value.element.name : "null");    return (EOF);  }  return (ch);}/* * 'mxml_load_data()' - Load data into an XML node tree. */static mxml_node_t *			/* O - First node or NULL if the file could not be read. */mxml_load_data(    mxml_node_t     *top,		/* I - Top node */    void            *p,			/* I - Pointer to data */    mxml_load_cb_t  cb,			/* I - Callback function or MXML_NO_CALLBACK */    _mxml_getc_cb_t getc_cb,		/* I - Read function */    mxml_sax_cb_t   sax_cb,		/* I - SAX callback or MXML_NO_CALLBACK */    void            *sax_data)		/* I - SAX user data */{  mxml_node_t	*node,			/* Current node */		*first,			/* First node added */		*parent;		/* Current parent node */  int		ch,			/* Character from file */		whitespace;		/* Non-zero if whitespace seen */  char		*buffer,		/* String buffer */		*bufptr;		/* Pointer into buffer */  int		bufsize;		/* Size of buffer */  mxml_type_t	type;			/* Current node type */  int		encoding;		/* Character encoding */  _mxml_global_t *global = _mxml_global();					/* Global data */  static const char * const types[] =	/* Type strings... */		{		  "MXML_ELEMENT",	/* XML element with attributes */		  "MXML_INTEGER",	/* Integer value */		  "MXML_OPAQUE",	/* Opaque string */		  "MXML_REAL",		/* Real value */		  "MXML_TEXT",		/* Text fragment */		  "MXML_CUSTOM"		/* Custom data */		}; /*  * Read elements and other nodes from the file...  */  if ((buffer = malloc(64)) == NULL)  {    mxml_error("Unable to allocate string buffer!");    return (NULL);  }  bufsize    = 64;  bufptr     = buffer;  parent     = top;  first      = NULL;  whitespace = 0;  encoding   = ENCODE_UTF8;  if (cb && parent)    type = (*cb)(parent);  else    type = MXML_TEXT;  while ((ch = (*getc_cb)(p, &encoding)) != EOF)  {    if ((ch == '<' ||         (mxml_isspace(ch) && type != MXML_OPAQUE && type != MXML_CUSTOM)) &&        bufptr > buffer)    {     /*      * Add a new value node...      */      *bufptr = '\0';      switch (type)      {	case MXML_INTEGER :            node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));	    break;	case MXML_OPAQUE :            node = mxmlNewOpaque(parent, buffer);	    break;	case MXML_REAL :            node = mxmlNewReal(parent, strtod(buffer, &bufptr));	    break;	case MXML_TEXT :            node = mxmlNewText(parent, whitespace, buffer);	    break;	case MXML_CUSTOM :	    if (global->custom_load_cb)	    {	     /*	      * Use the callback to fill in the custom data...	      */              node = mxmlNewCustom(parent, NULL, NULL);	      if ((*global->custom_load_cb)(node, buffer))	      {	        mxml_error("Bad custom value '%s' in parent <%s>!",		           buffer, parent ? parent->value.element.name : "null");		mxmlDelete(node);		node = NULL;	      }	      break;	    }        default : /* Ignore... */	    node = NULL;	    break;      }	        if (*bufptr)      {       /*        * Bad integer/real number value...	*/        mxml_error("Bad %s value '%s' in parent <%s>!",	           type == MXML_INTEGER ? "integer" : "real", buffer,		   parent ? parent->value.element.name : "null");	break;      }      bufptr     = buffer;      whitespace = mxml_isspace(ch) && type == MXML_TEXT;      if (!node && type != MXML_IGNORE)      {       /*	* Print error and return...	*/	mxml_error("Unable to add value node of type %s to parent <%s>!",	           types[type], parent ? parent->value.element.name : "null");	goto error;      }      if (sax_cb)      {        (*sax_cb)(node, MXML_SAX_DATA, sax_data);        if (!mxmlRelease(node))          node = NULL;      }      if (!first && node)        first = node;    }    else if (mxml_isspace(ch) && type == MXML_TEXT)      whitespace = 1;   /*    * Add lone whitespace node if we have an element and existing    * whitespace...    */    if (ch == '<' && whitespace && type == MXML_TEXT)    {      node = mxmlNewText(parent, whitespace, "");      if (sax_cb)      {        (*sax_cb)(node, MXML_SAX_DATA, sax_data);        if (!mxmlRelease(node))          node = NULL;      }      if (!first && node)        first = node;      whitespace = 0;    }    if (ch == '<')    {     /*      * Start of open/close tag...      */      bufptr = buffer;      while ((ch = (*getc_cb)(p, &encoding)) != EOF)        if (mxml_isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))	  break;	else if (ch == '<')	{	  mxml_error("Bare < in element!");	  goto error;	}	else if (ch == '&')	{	  if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)	    goto error;	  if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))	    goto error;	}	else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))	  goto error;	else if (((bufptr - buffer) == 1 && buffer[0] == '?') ||	         ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) ||	         ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8)))	  break;      *bufptr = '\0';      if (!strcmp(buffer, "!--"))      {       /*        * Gather rest of comment...	*/	while ((ch = (*getc_cb)(p, &encoding)) != EOF)	{	  if (ch == '>' && bufptr > (buffer + 4) &&	      bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-')	    break;	  else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))	    goto error;	}       /*        * Error out if we didn't get the whole comment...	*/        if (ch != '>')	{	 /*	  * Print error and return...	  */	  mxml_error("Early EOF in comment node!");	  goto error;	}       /*        * Otherwise add this as an element under the current parent...	*/	*bufptr = '\0';	if ((node = mxmlNewElement(parent, buffer)) == NULL)	{	 /*	  * Just print error for now...	  */	  mxml_error("Unable to add comment node to parent <%s>!",	             parent ? parent->value.element.name : "null");	  break;	}        if (sax_cb)        {          (*sax_cb)(node, MXML_SAX_COMMENT, sax_data);          if (!mxmlRelease(node))            node = NULL;        }	if (node && !first)	  first = node;      }      else if (!strcmp(buffer, "![CDATA["))      {       /*        * Gather CDATA section...	*/	while ((ch = (*getc_cb)(p, &encoding)) != EOF)	{	  if (ch == '>' && !strncmp(bufptr - 2, "]]", 2))	    break;	  else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))	    goto error;	}       /*        * Error out if we didn't get the whole comment...	*/        if (ch != '>')	{	 /*	  * Print error and return...	  */	  mxml_error("Early EOF in CDATA node!");	  goto error;	}       /*        * Otherwise add this as an element under the current parent...	*/	*bufptr = '\0';	if ((node = mxmlNewElement(parent, buffer)) == NULL)	{	 /*	  * Print error and return...	  */	  mxml_error("Unable to add CDATA node to parent <%s>!",	             parent ? parent->value.element.name : "null");	  goto error;	}        if (sax_cb)        {          (*sax_cb)(node, MXML_SAX_CDATA, sax_data);          if (!mxmlRelease(node))            node = NULL;        }	if (node && !first)	  first = node;      }      else if (buffer[0] == '?')      {       /*        * Gather rest of processing instruction...

⌨️ 快捷键说明

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