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

📄 mxml-file.c

📁 asterisk 是一个很有知名度开源软件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * "$Id: mxml-file.c 22267 2006-04-24 17:11:45Z kpfleming $" * * File loading code for Mini-XML, a small XML-like file parsing library. * * Copyright 2003-2005 by Michael Sweet. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2, 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. * * Contents: * *   mxmlLoadFd()            - Load a file descriptor into an XML node tree. *   mxmlLoadFile()          - Load a file into an XML node tree. *   mxmlLoadString()        - Load a string into an XML node tree. *   mxmlSaveAllocString()   - Save an XML node tree to an allocated string. *   mxmlSaveFd()            - Save an XML tree to a file descriptor. *   mxmlSaveFile()          - Save an XML tree to a file. *   mxmlSaveString()        - Save an XML node tree to a string. *   mxmlSetCustomHandlers() - Set the handling functions for custom data. *   mxmlSetErrorCallback()  - Set the error message callback. *   mxml_add_char()         - Add a character to a buffer, expanding as needed. *   mxml_fd_getc()          - Read a character from a file descriptor. *   mxml_fd_putc()          - Write a character to a file descriptor. *   mxml_fd_read()          - Read a buffer of data from a file descriptor. *   mxml_fd_write()         - Write a buffer of data to a file descriptor. *   mxml_file_getc()        - Get a character from a file. *   mxml_file_putc()        - Write a character to a file. *   mxml_get_entity()       - Get the character corresponding to an entity... *   mxml_load_data()        - Load data into an XML node tree. *   mxml_parse_element()    - Parse an element for any attributes... *   mxml_string_getc()      - Get a character from a string. *   mxml_string_putc()      - Write a character to a string. *   mxml_write_name()       - Write a name string. *   mxml_write_node()       - Save an XML node to a file. *   mxml_write_string()     - Write a string, escaping & and < as needed. *   mxml_write_ws()         - Do whitespace callback... *//* * Include necessary headers... */#include "config.h"#include "mxml.h"#ifdef WIN32#  include <io.h>#else#  include <unistd.h>#endif /* WIN32 *//* * Character encoding... */#define ENCODE_UTF8	0		/* UTF-8 */#define ENCODE_UTF16BE	1		/* UTF-16 Big-Endian */#define ENCODE_UTF16LE	2		/* UTF-16 Little-Endian *//* * Macro to test for a bad XML character... */#define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) != '\t')/* * Structures... */typedef struct mxml_fdbuf_s		/**** File descriptor buffer (@private) ****/{  int		fd;			/* File descriptor */  unsigned char	*current,		/* Current position in buffer */		*end,			/* End of buffer */		buffer[8192];		/* Character buffer */} mxml_fdbuf_t;/* * Global error handler... */extern void	(*mxml_error_cb)(const char *);/* * Custom data handlers... */static mxml_custom_load_cb_t	mxml_custom_load_cb = NULL;static mxml_custom_save_cb_t	mxml_custom_save_cb = NULL;/* * Local functions... */static int		mxml_add_char(int ch, char **ptr, char **buffer,			              int *bufsize);static int		mxml_fd_getc(void *p, int *encoding);static int		mxml_fd_putc(int ch, void *p);static int		mxml_fd_read(mxml_fdbuf_t *buf);static int		mxml_fd_write(mxml_fdbuf_t *buf);static int		mxml_file_getc(void *p, int *encoding);static int		mxml_file_putc(int ch, void *p);static int		mxml_get_entity(mxml_node_t *parent, void *p,			                int *encoding,					int (*getc_cb)(void *, int *));static mxml_node_t	*mxml_load_data(mxml_node_t *top, void *p,			                mxml_type_t (*cb)(mxml_node_t *),			                int (*getc_cb)(void *, int *));static int		mxml_parse_element(mxml_node_t *node, void *p,			                   int *encoding,					   int (*getc_cb)(void *, int *));static int		mxml_string_getc(void *p, int *encoding);static int		mxml_string_putc(int ch, void *p);static int		mxml_write_name(const char *s, void *p,					int (*putc_cb)(int, void *));static int		mxml_write_node(mxml_node_t *node, void *p,			                const char *(*cb)(mxml_node_t *, int),					int col,					int (*putc_cb)(int, void *));static int		mxml_write_string(const char *s, void *p,					  int (*putc_cb)(int, void *));static int		mxml_write_ws(mxml_node_t *node, void *p, 			              const char *(*cb)(mxml_node_t *, int), int ws,				      int col, int (*putc_cb)(int, void *));/* * 'mxmlLoadFd()' - Load a file descriptor into an XML node tree. * * The nodes in the specified file are added to the specified top node. * If no top node is provided, the XML file MUST be well-formed with a * single parent node like <?xml> for the entire file. The callback * function returns the value type that should be used for child nodes. * If MXML_NO_CALLBACK is specified then all child nodes will be either * MXML_ELEMENT or MXML_TEXT nodes. * * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading * child nodes of the specified type. */mxml_node_t *				/* O - First node or NULL if the file could not be read. */mxmlLoadFd(mxml_node_t *top,		/* I - Top node */           int         fd,		/* I - File descriptor to read from */           mxml_type_t (*cb)(mxml_node_t *node))					/* I - Callback function or MXML_NO_CALLBACK */{  mxml_fdbuf_t	buf;			/* File descriptor buffer */ /*  * Initialize the file descriptor buffer...  */  buf.fd      = fd;  buf.current = buf.buffer;  buf.end     = buf.buffer; /*  * Read the XML data...  */  return (mxml_load_data(top, &buf, cb, mxml_fd_getc));}/* * 'mxmlLoadFile()' - Load a file into an XML node tree. * * The nodes in the specified file are added to the specified top node. * If no top node is provided, the XML file MUST be well-formed with a * single parent node like <?xml> for the entire file. The callback * function returns the value type that should be used for child nodes. * If MXML_NO_CALLBACK is specified then all child nodes will be either * MXML_ELEMENT or MXML_TEXT nodes. * * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading * child nodes of the specified type. */mxml_node_t *				/* O - First node or NULL if the file could not be read. */mxmlLoadFile(mxml_node_t *top,		/* I - Top node */             FILE        *fp,		/* I - File to read from */             mxml_type_t (*cb)(mxml_node_t *node))					/* I - Callback function or MXML_NO_CALLBACK */{ /*  * Read the XML data...  */  return (mxml_load_data(top, fp, cb, mxml_file_getc));}/* * 'mxmlLoadString()' - Load a string into an XML node tree. * * The nodes in the specified string are added to the specified top node. * If no top node is provided, the XML string MUST be well-formed with a * single parent node like <?xml> for the entire string. The callback * function returns the value type that should be used for child nodes. * If MXML_NO_CALLBACK is specified then all child nodes will be either * MXML_ELEMENT or MXML_TEXT nodes. * * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading * child nodes of the specified type. */mxml_node_t *				/* O - First node or NULL if the string has errors. */mxmlLoadString(mxml_node_t *top,	/* I - Top node */               const char  *s,		/* I - String to load */               mxml_type_t (*cb)(mxml_node_t *node))					/* I - Callback function or MXML_NO_CALLBACK */{ /*  * Read the XML data...  */  return (mxml_load_data(top, &s, cb, mxml_string_getc));}/* * 'mxmlSaveAllocString()' - Save an XML node tree to an allocated string. * * This function returns a pointer to a string containing the textual * representation of the XML node tree.  The string should be freed * using the free() function when you are done with it.  NULL is returned * if the node would produce an empty string or if the string cannot be * allocated. * * The callback argument specifies a function that returns a whitespace * string or NULL before and after each element. If MXML_NO_CALLBACK * is specified, whitespace will only be added before MXML_TEXT nodes * with leading whitespace and before attribute names inside opening * element tags. */char *					/* O - Allocated string or NULL */mxmlSaveAllocString(mxml_node_t *node,	/* I - Node to write */                    const char  *(*cb)(mxml_node_t *node, int ws))					/* I - Whitespace callback or MXML_NO_CALLBACK */{  int	bytes;				/* Required bytes */  char	buffer[8192];			/* Temporary buffer */  char	*s;				/* Allocated string */ /*  * Write the node to the temporary buffer...  */  bytes = mxmlSaveString(node, buffer, sizeof(buffer), cb);  if (bytes <= 0)    return (NULL);  if (bytes < (int)(sizeof(buffer) - 1))  {   /*    * Node fit inside the buffer, so just duplicate that string and    * return...    */    return (strdup(buffer));  } /*  * Allocate a buffer of the required size and save the node to the  * new buffer...  */  if ((s = malloc(bytes + 1)) == NULL)    return (NULL);  mxmlSaveString(node, s, bytes + 1, cb); /*  * Return the allocated string...  */  return (s);}/* * 'mxmlSaveFd()' - Save an XML tree to a file descriptor. * * The callback argument specifies a function that returns a whitespace * string or NULL before and after each element. If MXML_NO_CALLBACK * is specified, whitespace will only be added before MXML_TEXT nodes * with leading whitespace and before attribute names inside opening * element tags. */int					/* O - 0 on success, -1 on error. */mxmlSaveFd(mxml_node_t *node,		/* I - Node to write */           int         fd,		/* I - File descriptor to write to */	   const char  *(*cb)(mxml_node_t *node, int ws))					/* I - Whitespace callback or MXML_NO_CALLBACK */{  int		col;			/* Final column */  mxml_fdbuf_t	buf;			/* File descriptor buffer */ /*  * Initialize the file descriptor buffer...  */  buf.fd      = fd;  buf.current = buf.buffer;  buf.end     = buf.buffer + sizeof(buf.buffer) - 4; /*  * Write the node...  */  if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc)) < 0)    return (-1);  if (col > 0)    if (mxml_fd_putc('\n', &buf) < 0)      return (-1); /*  * Flush and return...  */  return (mxml_fd_write(&buf));}/* * 'mxmlSaveFile()' - Save an XML tree to a file. * * The callback argument specifies a function that returns a whitespace * string or NULL before and after each element. If MXML_NO_CALLBACK * is specified, whitespace will only be added before MXML_TEXT nodes * with leading whitespace and before attribute names inside opening * element tags. */int					/* O - 0 on success, -1 on error. */mxmlSaveFile(mxml_node_t *node,		/* I - Node to write */             FILE        *fp,		/* I - File to write to */	     const char  *(*cb)(mxml_node_t *node, int ws))					/* I - Whitespace callback or MXML_NO_CALLBACK */{  int	col;				/* Final column */ /*  * Write the node...  */  if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc)) < 0)    return (-1);  if (col > 0)    if (putc('\n', fp) < 0)      return (-1); /*  * Return 0 (success)...  */  return (0);}/* * 'mxmlSaveString()' - Save an XML node tree to a string. * * This function returns the total number of bytes that would be * required for the string but only copies (bufsize - 1) characters * into the specified buffer. * * The callback argument specifies a function that returns a whitespace * string or NULL before and after each element. If MXML_NO_CALLBACK * is specified, whitespace will only be added before MXML_TEXT nodes * with leading whitespace and before attribute names inside opening * element tags. */int					/* O - Size of string */mxmlSaveString(mxml_node_t *node,	/* I - Node to write */               char        *buffer,	/* I - String buffer */               int         bufsize,	/* I - Size of string buffer */               const char  *(*cb)(mxml_node_t *node, int ws))					/* I - Whitespace callback or MXML_NO_CALLBACK */{  int	col;				/* Final column */  char	*ptr[2];			/* Pointers for putc_cb */ /*  * Write the node...  */  ptr[0] = buffer;  ptr[1] = buffer + bufsize;  if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc)) < 0)    return (-1);  if (col > 0)    mxml_string_putc('\n', ptr); /*  * Nul-terminate the buffer...  */  if (ptr[0] >= ptr[1])    buffer[bufsize - 1] = '\0';  else    ptr[0][0] = '\0'; /*  * Return the number of characters...  */  return (ptr[0] - buffer);}/* * 'mxmlSetCustomHandlers()' - Set the handling functions for custom data. * * The load function accepts a node pointer and a data string and must * return 0 on success and non-zero on error. * * The save function accepts a node pointer and must return a malloc'd * string on success and NULL on error. *  */voidmxmlSetCustomHandlers(mxml_custom_load_cb_t load,					/* I - Load function */                      mxml_custom_save_cb_t save)					/* I - Save function */{  mxml_custom_load_cb = load;  mxml_custom_save_cb = save;}/* * 'mxmlSetErrorCallback()' - Set the error message callback. */voidmxmlSetErrorCallback(void (*cb)(const char *))					/* I - Error callback function */{  mxml_error_cb = cb;}/* * 'mxml_add_char()' - Add a character to a buffer, expanding as needed. */static int				/* O  - 0 on success, -1 on error */mxml_add_char(int  ch,			/* I  - Character to add */              char **bufptr,		/* IO - Current position in buffer */	      char **buffer,		/* IO - Current buffer */	      int  *bufsize)		/* IO - Current buffer size */{  char	*newbuffer;			/* New buffer value */  if (*bufptr >= (*buffer + *bufsize - 4))  {   /*    * Increase the size of the buffer...    */    if (*bufsize < 1024)      (*bufsize) *= 2;    else      (*bufsize) += 1024;    if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)    {      free(*buffer);      mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);      return (-1);    }    *bufptr = newbuffer + (*bufptr - *buffer);    *buffer = newbuffer;  }  if (ch < 0x80)  {   /*    * Single byte ASCII...    */    *(*bufptr)++ = ch;  }  else if (ch < 0x800)  {   /*    * Two-byte UTF-8...    */    *(*bufptr)++ = 0xc0 | (ch >> 6);    *(*bufptr)++ = 0x80 | (ch & 0x3f);  }  else if (ch < 0x10000)  {   /*    * Three-byte UTF-8...    */    *(*bufptr)++ = 0xe0 | (ch >> 12);    *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);    *(*bufptr)++ = 0x80 | (ch & 0x3f);  }  else  {   /*    * Four-byte UTF-8...    */    *(*bufptr)++ = 0xf0 | (ch >> 18);    *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);    *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);    *(*bufptr)++ = 0x80 | (ch & 0x3f);  }  return (0);}/* * 'mxml_fd_getc()' - Read a character from a file descriptor. */static int				/* O  - Character or EOF */mxml_fd_getc(void *p,			/* I  - File descriptor buffer */             int  *encoding)		/* IO - Encoding */{  mxml_fdbuf_t	*buf;			/* File descriptor buffer */  int		ch,			/* Current character */		temp;			/* Temporary character */ /*  * Grab the next character in the buffer...  */  buf = (mxml_fdbuf_t *)p;  if (buf->current >= buf->end)    if (mxml_fd_read(buf) < 0)      return (EOF);  ch = *(buf->current)++;  switch (*encoding)  {    case ENCODE_UTF8 :       /*	* Got a UTF-8 character; convert UTF-8 to Unicode and return...	*/	if (!(ch & 0x80))	{#if DEBUG > 1          printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);#endif /* DEBUG > 1 */	  if (mxml_bad_char(ch))	  {	    mxml_error("Bad control character 0x%02x not allowed by XML standard!",        	       ch);	    return (EOF);	  }	  return (ch);        }	else if (ch == 0xfe)	{	 /*	  * UTF-16 big-endian BOM?	  */	  if (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);	  ch = *(buf->current)++;          	  if (ch != 0xff)	    return (EOF);	  *encoding = ENCODE_UTF16BE;	  return (mxml_fd_getc(p, encoding));	}	else if (ch == 0xff)	{	 /*	  * UTF-16 little-endian BOM?	  */	  if (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);	  ch = *(buf->current)++;          	  if (ch != 0xfe)	    return (EOF);	  *encoding = ENCODE_UTF16LE;	  return (mxml_fd_getc(p, encoding));	}	else if ((ch & 0xe0) == 0xc0)	{	 /*	  * Two-byte value...	  */	  if (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);	  temp = *(buf->current)++;	  if ((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 (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);	  temp = *(buf->current)++;	  if ((temp & 0xc0) != 0x80)	    return (EOF);	  ch = ((ch & 0x0f) << 6) | (temp & 0x3f);	  if (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);	  temp = *(buf->current)++;	  if ((temp & 0xc0) != 0x80)	    return (EOF);	  ch = (ch << 6) | (temp & 0x3f);	  if (ch < 0x800)	    return (EOF);	}	else if ((ch & 0xf8) == 0xf0)	{	 /*	  * Four-byte value...	  */	  if (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);	  temp = *(buf->current)++;	  if ((temp & 0xc0) != 0x80)	    return (EOF);	  ch = ((ch & 0x07) << 6) | (temp & 0x3f);	  if (buf->current >= buf->end)	    if (mxml_fd_read(buf) < 0)	      return (EOF);

⌨️ 快捷键说明

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