(root)/
libxml2-2.12.3/
buf.c
       1  /*
       2   * buf.c: memory buffers for libxml2
       3   *
       4   * new buffer structures and entry points to simplify the maintenance
       5   * of libxml2 and ensure we keep good control over memory allocations
       6   * and stay 64 bits clean.
       7   * The new entry point use the xmlBufPtr opaque structure and
       8   * xmlBuf...() counterparts to the old xmlBuf...() functions
       9   *
      10   * See Copyright for the status of this software.
      11   *
      12   * daniel@veillard.com
      13   */
      14  
      15  #define IN_LIBXML
      16  #include "libxml.h"
      17  
      18  #include <string.h> /* for memset() only ! */
      19  #include <limits.h>
      20  #include <ctype.h>
      21  #include <stdlib.h>
      22  
      23  #include <libxml/tree.h>
      24  #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
      25  
      26  #include "private/buf.h"
      27  #include "private/error.h"
      28  
      29  #ifndef SIZE_MAX
      30  #define SIZE_MAX ((size_t) -1)
      31  #endif
      32  
      33  #define WITH_BUFFER_COMPAT
      34  
      35  /**
      36   * xmlBuf:
      37   *
      38   * A buffer structure. The base of the structure is somehow compatible
      39   * with struct _xmlBuffer to limit risks on application which accessed
      40   * directly the input->buf->buffer structures.
      41   */
      42  
      43  struct _xmlBuf {
      44      xmlChar *content;		/* The buffer content UTF8 */
      45      unsigned int compat_use;    /* for binary compatibility */
      46      unsigned int compat_size;   /* for binary compatibility */
      47      xmlBufferAllocationScheme alloc; /* The realloc method */
      48      xmlChar *contentIO;		/* in IO mode we may have a different base */
      49      size_t use;		        /* The buffer size used */
      50      size_t size;		/* The buffer size */
      51      xmlBufferPtr buffer;        /* wrapper for an old buffer */
      52      int error;                  /* an error code if a failure occurred */
      53  };
      54  
      55  #ifdef WITH_BUFFER_COMPAT
      56  /*
      57   * Macro for compatibility with xmlBuffer to be used after an xmlBuf
      58   * is updated. This makes sure the compat fields are updated too.
      59   */
      60  #define UPDATE_COMPAT(buf)				    \
      61       if (buf->size < INT_MAX) buf->compat_size = buf->size; \
      62       else buf->compat_size = INT_MAX;			    \
      63       if (buf->use < INT_MAX) buf->compat_use = buf->use; \
      64       else buf->compat_use = INT_MAX;
      65  
      66  /*
      67   * Macro for compatibility with xmlBuffer to be used in all the xmlBuf
      68   * entry points, it checks that the compat fields have not been modified
      69   * by direct call to xmlBuffer function from code compiled before 2.9.0 .
      70   */
      71  #define CHECK_COMPAT(buf)				    \
      72       if (buf->size != (size_t) buf->compat_size)	    \
      73           if (buf->compat_size < INT_MAX)		    \
      74  	     buf->size = buf->compat_size;		    \
      75       if (buf->use != (size_t) buf->compat_use)		    \
      76           if (buf->compat_use < INT_MAX)			    \
      77  	     buf->use = buf->compat_use;
      78  
      79  #else /* ! WITH_BUFFER_COMPAT */
      80  #define UPDATE_COMPAT(buf)
      81  #define CHECK_COMPAT(buf)
      82  #endif /* WITH_BUFFER_COMPAT */
      83  
      84  /**
      85   * xmlBufMemoryError:
      86   * @extra:  extra information
      87   *
      88   * Handle an out of memory condition
      89   * To be improved...
      90   */
      91  static void
      92  xmlBufMemoryError(xmlBufPtr buf, const char *extra)
      93  {
      94      __xmlSimpleError(XML_FROM_BUFFER, XML_ERR_NO_MEMORY, NULL, NULL, extra);
      95      if ((buf) && (buf->error == 0))
      96          buf->error = XML_ERR_NO_MEMORY;
      97  }
      98  
      99  /**
     100   * xmlBufOverflowError:
     101   * @extra:  extra information
     102   *
     103   * Handle a buffer overflow error
     104   * To be improved...
     105   */
     106  static void
     107  xmlBufOverflowError(xmlBufPtr buf, const char *extra)
     108  {
     109      __xmlSimpleError(XML_FROM_BUFFER, XML_BUF_OVERFLOW, NULL, NULL, extra);
     110      if ((buf) && (buf->error == 0))
     111          buf->error = XML_BUF_OVERFLOW;
     112  }
     113  
     114  
     115  /**
     116   * xmlBufCreate:
     117   *
     118   * routine to create an XML buffer.
     119   * returns the new structure.
     120   */
     121  xmlBufPtr
     122  xmlBufCreate(void) {
     123      xmlBufPtr ret;
     124  
     125      ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
     126      if (ret == NULL) {
     127  	xmlBufMemoryError(NULL, "creating buffer");
     128          return(NULL);
     129      }
     130      ret->use = 0;
     131      ret->error = 0;
     132      ret->buffer = NULL;
     133      ret->size = xmlDefaultBufferSize;
     134      UPDATE_COMPAT(ret);
     135      ret->alloc = xmlBufferAllocScheme;
     136      ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
     137      if (ret->content == NULL) {
     138  	xmlBufMemoryError(ret, "creating buffer");
     139  	xmlFree(ret);
     140          return(NULL);
     141      }
     142      ret->content[0] = 0;
     143      ret->contentIO = NULL;
     144      return(ret);
     145  }
     146  
     147  /**
     148   * xmlBufCreateSize:
     149   * @size: initial size of buffer
     150   *
     151   * routine to create an XML buffer.
     152   * returns the new structure.
     153   */
     154  xmlBufPtr
     155  xmlBufCreateSize(size_t size) {
     156      xmlBufPtr ret;
     157  
     158      if (size == SIZE_MAX)
     159          return(NULL);
     160      ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
     161      if (ret == NULL) {
     162  	xmlBufMemoryError(NULL, "creating buffer");
     163          return(NULL);
     164      }
     165      ret->use = 0;
     166      ret->error = 0;
     167      ret->buffer = NULL;
     168      ret->alloc = xmlBufferAllocScheme;
     169      ret->size = (size ? size + 1 : 0);         /* +1 for ending null */
     170      UPDATE_COMPAT(ret);
     171      if (ret->size){
     172          ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
     173          if (ret->content == NULL) {
     174  	    xmlBufMemoryError(ret, "creating buffer");
     175              xmlFree(ret);
     176              return(NULL);
     177          }
     178          ret->content[0] = 0;
     179      } else
     180  	ret->content = NULL;
     181      ret->contentIO = NULL;
     182      return(ret);
     183  }
     184  
     185  /**
     186   * xmlBufDetach:
     187   * @buf:  the buffer
     188   *
     189   * Remove the string contained in a buffer and give it back to the
     190   * caller. The buffer is reset to an empty content.
     191   * This doesn't work with immutable buffers as they can't be reset.
     192   *
     193   * Returns the previous string contained by the buffer.
     194   */
     195  xmlChar *
     196  xmlBufDetach(xmlBufPtr buf) {
     197      xmlChar *ret;
     198  
     199      if (buf == NULL)
     200          return(NULL);
     201      if (buf->buffer != NULL)
     202          return(NULL);
     203      if (buf->error)
     204          return(NULL);
     205  
     206      ret = buf->content;
     207      buf->content = NULL;
     208      buf->size = 0;
     209      buf->use = 0;
     210      UPDATE_COMPAT(buf);
     211  
     212      return ret;
     213  }
     214  
     215  /**
     216   * xmlBufGetAllocationScheme:
     217   * @buf:  the buffer
     218   *
     219   * Get the buffer allocation scheme
     220   *
     221   * Returns the scheme or -1 in case of error
     222   */
     223  int
     224  xmlBufGetAllocationScheme(xmlBufPtr buf) {
     225      if (buf == NULL) {
     226          return(-1);
     227      }
     228      return(buf->alloc);
     229  }
     230  
     231  /**
     232   * xmlBufSetAllocationScheme:
     233   * @buf:  the buffer to tune
     234   * @scheme:  allocation scheme to use
     235   *
     236   * Sets the allocation scheme for this buffer
     237   *
     238   * returns 0 in case of success and -1 in case of failure
     239   */
     240  int
     241  xmlBufSetAllocationScheme(xmlBufPtr buf,
     242                            xmlBufferAllocationScheme scheme) {
     243      if ((buf == NULL) || (buf->error != 0)) {
     244          return(-1);
     245      }
     246      if (buf->alloc == XML_BUFFER_ALLOC_IO)
     247          return(-1);
     248      if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
     249          (scheme == XML_BUFFER_ALLOC_EXACT) ||
     250          (scheme == XML_BUFFER_ALLOC_HYBRID) ||
     251  	(scheme == XML_BUFFER_ALLOC_BOUNDED)) {
     252  	buf->alloc = scheme;
     253          if (buf->buffer)
     254              buf->buffer->alloc = scheme;
     255          return(0);
     256      }
     257      /*
     258       * Switching a buffer ALLOC_IO has the side effect of initializing
     259       * the contentIO field with the current content
     260       */
     261      if (scheme == XML_BUFFER_ALLOC_IO) {
     262          buf->alloc = XML_BUFFER_ALLOC_IO;
     263          buf->contentIO = buf->content;
     264      }
     265      return(-1);
     266  }
     267  
     268  /**
     269   * xmlBufFree:
     270   * @buf:  the buffer to free
     271   *
     272   * Frees an XML buffer. It frees both the content and the structure which
     273   * encapsulate it.
     274   */
     275  void
     276  xmlBufFree(xmlBufPtr buf) {
     277      if (buf == NULL) {
     278  	return;
     279      }
     280  
     281      if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
     282          (buf->contentIO != NULL)) {
     283          xmlFree(buf->contentIO);
     284      } else if (buf->content != NULL) {
     285          xmlFree(buf->content);
     286      }
     287      xmlFree(buf);
     288  }
     289  
     290  /**
     291   * xmlBufEmpty:
     292   * @buf:  the buffer
     293   *
     294   * empty a buffer.
     295   */
     296  void
     297  xmlBufEmpty(xmlBufPtr buf) {
     298      if ((buf == NULL) || (buf->error != 0)) return;
     299      if (buf->content == NULL) return;
     300      CHECK_COMPAT(buf)
     301      buf->use = 0;
     302      if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
     303                 (buf->contentIO != NULL)) {
     304          size_t start_buf = buf->content - buf->contentIO;
     305  
     306  	buf->size += start_buf;
     307          buf->content = buf->contentIO;
     308          buf->content[0] = 0;
     309      } else {
     310          buf->content[0] = 0;
     311      }
     312      UPDATE_COMPAT(buf)
     313  }
     314  
     315  /**
     316   * xmlBufShrink:
     317   * @buf:  the buffer to dump
     318   * @len:  the number of xmlChar to remove
     319   *
     320   * Remove the beginning of an XML buffer.
     321   * NOTE that this routine behaviour differs from xmlBufferShrink()
     322   * as it will return 0 on error instead of -1 due to size_t being
     323   * used as the return type.
     324   *
     325   * Returns the number of byte removed or 0 in case of failure
     326   */
     327  size_t
     328  xmlBufShrink(xmlBufPtr buf, size_t len) {
     329      if ((buf == NULL) || (buf->error != 0)) return(0);
     330      CHECK_COMPAT(buf)
     331      if (len == 0) return(0);
     332      if (len > buf->use) return(0);
     333  
     334      buf->use -= len;
     335      if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
     336  	/*
     337  	 * we just move the content pointer, but also make sure
     338  	 * the perceived buffer size has shrunk accordingly
     339  	 */
     340          buf->content += len;
     341  	buf->size -= len;
     342  
     343          /*
     344  	 * sometimes though it maybe be better to really shrink
     345  	 * on IO buffers
     346  	 */
     347  	if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
     348  	    size_t start_buf = buf->content - buf->contentIO;
     349  	    if (start_buf >= buf->size) {
     350  		memmove(buf->contentIO, &buf->content[0], buf->use);
     351  		buf->content = buf->contentIO;
     352  		buf->content[buf->use] = 0;
     353  		buf->size += start_buf;
     354  	    }
     355  	}
     356      } else {
     357  	memmove(buf->content, &buf->content[len], buf->use);
     358  	buf->content[buf->use] = 0;
     359      }
     360      UPDATE_COMPAT(buf)
     361      return(len);
     362  }
     363  
     364  /**
     365   * xmlBufGrowInternal:
     366   * @buf:  the buffer
     367   * @len:  the minimum free size to allocate
     368   *
     369   * Grow the available space of an XML buffer, @len is the target value
     370   * Error checking should be done on buf->error since using the return
     371   * value doesn't work that well
     372   *
     373   * Returns 0 in case of error or the length made available otherwise
     374   */
     375  static size_t
     376  xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
     377      size_t size;
     378      xmlChar *newbuf;
     379  
     380      if ((buf == NULL) || (buf->error != 0)) return(0);
     381      CHECK_COMPAT(buf)
     382  
     383      if (len < buf->size - buf->use)
     384          return(buf->size - buf->use - 1);
     385      if (len >= SIZE_MAX - buf->use) {
     386          xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");
     387          return(0);
     388      }
     389  
     390      if (buf->size > (size_t) len) {
     391          size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2;
     392      } else {
     393          size = buf->use + len;
     394          size = size > SIZE_MAX - 100 ? SIZE_MAX : size + 100;
     395      }
     396  
     397      if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
     398          /*
     399  	 * Used to provide parsing limits
     400  	 */
     401          if ((buf->use + len + 1 >= XML_MAX_TEXT_LENGTH) ||
     402  	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
     403  	    xmlBufMemoryError(buf, "buffer error: text too long\n");
     404  	    return(0);
     405  	}
     406  	if (size >= XML_MAX_TEXT_LENGTH)
     407  	    size = XML_MAX_TEXT_LENGTH;
     408      }
     409      if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
     410          size_t start_buf = buf->content - buf->contentIO;
     411  
     412  	newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
     413  	if (newbuf == NULL) {
     414  	    xmlBufMemoryError(buf, "growing buffer");
     415  	    return(0);
     416  	}
     417  	buf->contentIO = newbuf;
     418  	buf->content = newbuf + start_buf;
     419      } else {
     420  	newbuf = (xmlChar *) xmlRealloc(buf->content, size);
     421  	if (newbuf == NULL) {
     422  	    xmlBufMemoryError(buf, "growing buffer");
     423  	    return(0);
     424  	}
     425  	buf->content = newbuf;
     426      }
     427      buf->size = size;
     428      UPDATE_COMPAT(buf)
     429      return(buf->size - buf->use - 1);
     430  }
     431  
     432  /**
     433   * xmlBufGrow:
     434   * @buf:  the buffer
     435   * @len:  the minimum free size to allocate
     436   *
     437   * Grow the available space of an XML buffer, @len is the target value
     438   * This is been kept compatible with xmlBufferGrow() as much as possible
     439   *
     440   * Returns -1 in case of error or the length made available otherwise
     441   */
     442  int
     443  xmlBufGrow(xmlBufPtr buf, int len) {
     444      size_t ret;
     445  
     446      if ((buf == NULL) || (len < 0)) return(-1);
     447      if (len == 0)
     448          return(0);
     449      ret = xmlBufGrowInternal(buf, len);
     450      if (buf->error != 0)
     451          return(-1);
     452      return(ret > INT_MAX ? INT_MAX : ret);
     453  }
     454  
     455  /**
     456   * xmlBufDump:
     457   * @file:  the file output
     458   * @buf:  the buffer to dump
     459   *
     460   * Dumps an XML buffer to  a FILE *.
     461   * Returns the number of #xmlChar written
     462   */
     463  size_t
     464  xmlBufDump(FILE *file, xmlBufPtr buf) {
     465      size_t ret;
     466  
     467      if ((buf == NULL) || (buf->error != 0)) {
     468  	return(0);
     469      }
     470      if (buf->content == NULL) {
     471  	return(0);
     472      }
     473      CHECK_COMPAT(buf)
     474      if (file == NULL)
     475  	file = stdout;
     476      ret = fwrite(buf->content, 1, buf->use, file);
     477      return(ret);
     478  }
     479  
     480  /**
     481   * xmlBufContent:
     482   * @buf:  the buffer
     483   *
     484   * Function to extract the content of a buffer
     485   *
     486   * Returns the internal content
     487   */
     488  
     489  xmlChar *
     490  xmlBufContent(const xmlBuf *buf)
     491  {
     492      if ((!buf) || (buf->error))
     493          return NULL;
     494  
     495      return(buf->content);
     496  }
     497  
     498  /**
     499   * xmlBufEnd:
     500   * @buf:  the buffer
     501   *
     502   * Function to extract the end of the content of a buffer
     503   *
     504   * Returns the end of the internal content or NULL in case of error
     505   */
     506  
     507  xmlChar *
     508  xmlBufEnd(xmlBufPtr buf)
     509  {
     510      if ((!buf) || (buf->error))
     511          return NULL;
     512      CHECK_COMPAT(buf)
     513  
     514      return(&buf->content[buf->use]);
     515  }
     516  
     517  /**
     518   * xmlBufAddLen:
     519   * @buf:  the buffer
     520   * @len:  the size which were added at the end
     521   *
     522   * Sometime data may be added at the end of the buffer without
     523   * using the xmlBuf APIs that is used to expand the used space
     524   * and set the zero terminating at the end of the buffer
     525   *
     526   * Returns -1 in case of error and 0 otherwise
     527   */
     528  int
     529  xmlBufAddLen(xmlBufPtr buf, size_t len) {
     530      if ((buf == NULL) || (buf->error))
     531          return(-1);
     532      CHECK_COMPAT(buf)
     533      if (len >= (buf->size - buf->use))
     534          return(-1);
     535      buf->use += len;
     536      buf->content[buf->use] = 0;
     537      UPDATE_COMPAT(buf)
     538      return(0);
     539  }
     540  
     541  /**
     542   * xmlBufLength:
     543   * @buf:  the buffer
     544   *
     545   * Function to get the length of a buffer
     546   *
     547   * Returns the length of data in the internal content
     548   */
     549  
     550  size_t
     551  xmlBufLength(const xmlBufPtr buf)
     552  {
     553      if ((!buf) || (buf->error))
     554          return 0;
     555      CHECK_COMPAT(buf)
     556  
     557      return(buf->use);
     558  }
     559  
     560  /**
     561   * xmlBufUse:
     562   * @buf:  the buffer
     563   *
     564   * Function to get the length of a buffer
     565   *
     566   * Returns the length of data in the internal content
     567   */
     568  
     569  size_t
     570  xmlBufUse(const xmlBufPtr buf)
     571  {
     572      if ((!buf) || (buf->error))
     573          return 0;
     574      CHECK_COMPAT(buf)
     575  
     576      return(buf->use);
     577  }
     578  
     579  /**
     580   * xmlBufAvail:
     581   * @buf:  the buffer
     582   *
     583   * Function to find how much free space is allocated but not
     584   * used in the buffer. It reserves one byte for the NUL
     585   * terminator character that is usually needed, so there is
     586   * no need to subtract 1 from the result anymore.
     587   *
     588   * Returns the amount, or 0 if none or if an error occurred.
     589   */
     590  
     591  size_t
     592  xmlBufAvail(const xmlBufPtr buf)
     593  {
     594      if ((!buf) || (buf->error))
     595          return 0;
     596      CHECK_COMPAT(buf)
     597  
     598      return((buf->size > buf->use) ? (buf->size - buf->use - 1) : 0);
     599  }
     600  
     601  /**
     602   * xmlBufIsEmpty:
     603   * @buf:  the buffer
     604   *
     605   * Tell if a buffer is empty
     606   *
     607   * Returns 0 if no, 1 if yes and -1 in case of error
     608   */
     609  int
     610  xmlBufIsEmpty(const xmlBufPtr buf)
     611  {
     612      if ((!buf) || (buf->error))
     613          return(-1);
     614      CHECK_COMPAT(buf)
     615  
     616      return(buf->use == 0);
     617  }
     618  
     619  /**
     620   * xmlBufResize:
     621   * @buf:  the buffer to resize
     622   * @size:  the desired size
     623   *
     624   * Resize a buffer to accommodate minimum size of @size.
     625   *
     626   * Returns  0 in case of problems, 1 otherwise
     627   */
     628  int
     629  xmlBufResize(xmlBufPtr buf, size_t size)
     630  {
     631      size_t newSize;
     632      xmlChar* rebuf = NULL;
     633      size_t start_buf;
     634  
     635      if ((buf == NULL) || (buf->error))
     636          return(0);
     637      CHECK_COMPAT(buf)
     638  
     639      if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
     640          /*
     641  	 * Used to provide parsing limits
     642  	 */
     643          if (size >= XML_MAX_TEXT_LENGTH) {
     644  	    xmlBufMemoryError(buf, "buffer error: text too long\n");
     645  	    return(0);
     646  	}
     647      }
     648  
     649      /* Don't resize if we don't have to */
     650      if (size < buf->size)
     651          return 1;
     652  
     653      /* figure out new size */
     654      switch (buf->alloc){
     655  	case XML_BUFFER_ALLOC_IO:
     656  	case XML_BUFFER_ALLOC_DOUBLEIT:
     657  	    /*take care of empty case*/
     658              if (buf->size == 0) {
     659                  newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
     660              } else {
     661                  newSize = buf->size;
     662              }
     663  	    while (size > newSize) {
     664  	        if (newSize > SIZE_MAX / 2) {
     665  	            xmlBufMemoryError(buf, "growing buffer");
     666  	            return 0;
     667  	        }
     668  	        newSize *= 2;
     669  	    }
     670  	    break;
     671  	case XML_BUFFER_ALLOC_EXACT:
     672              newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
     673  	    break;
     674          case XML_BUFFER_ALLOC_HYBRID:
     675              if (buf->use < BASE_BUFFER_SIZE)
     676                  newSize = size;
     677              else {
     678                  newSize = buf->size;
     679                  while (size > newSize) {
     680                      if (newSize > SIZE_MAX / 2) {
     681                          xmlBufMemoryError(buf, "growing buffer");
     682                          return 0;
     683                      }
     684                      newSize *= 2;
     685                  }
     686              }
     687              break;
     688  
     689  	default:
     690              newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
     691  	    break;
     692      }
     693  
     694      if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
     695          start_buf = buf->content - buf->contentIO;
     696  
     697          if (start_buf > newSize) {
     698  	    /* move data back to start */
     699  	    memmove(buf->contentIO, buf->content, buf->use);
     700  	    buf->content = buf->contentIO;
     701  	    buf->content[buf->use] = 0;
     702  	    buf->size += start_buf;
     703  	} else {
     704  	    rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
     705  	    if (rebuf == NULL) {
     706  		xmlBufMemoryError(buf, "growing buffer");
     707  		return 0;
     708  	    }
     709  	    buf->contentIO = rebuf;
     710  	    buf->content = rebuf + start_buf;
     711  	}
     712      } else {
     713  	if (buf->content == NULL) {
     714  	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
     715  	    buf->use = 0;
     716              if (rebuf != NULL)
     717  	        rebuf[buf->use] = 0;
     718  	} else if (buf->size - buf->use < 100) {
     719  	    rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
     720          } else {
     721  	    /*
     722  	     * if we are reallocating a buffer far from being full, it's
     723  	     * better to make a new allocation and copy only the used range
     724  	     * and free the old one.
     725  	     */
     726  	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
     727  	    if (rebuf != NULL) {
     728  		memcpy(rebuf, buf->content, buf->use);
     729  		xmlFree(buf->content);
     730  		rebuf[buf->use] = 0;
     731  	    }
     732  	}
     733  	if (rebuf == NULL) {
     734  	    xmlBufMemoryError(buf, "growing buffer");
     735  	    return 0;
     736  	}
     737  	buf->content = rebuf;
     738      }
     739      buf->size = newSize;
     740      UPDATE_COMPAT(buf)
     741  
     742      return 1;
     743  }
     744  
     745  /**
     746   * xmlBufAdd:
     747   * @buf:  the buffer to dump
     748   * @str:  the #xmlChar string
     749   * @len:  the number of #xmlChar to add
     750   *
     751   * Add a string range to an XML buffer. if len == -1, the length of
     752   * str is recomputed.
     753   *
     754   * Returns 0 successful, a positive error code number otherwise
     755   *         and -1 in case of internal or API error.
     756   */
     757  int
     758  xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
     759      size_t needSize;
     760  
     761      if ((str == NULL) || (buf == NULL) || (buf->error))
     762  	return -1;
     763      CHECK_COMPAT(buf)
     764  
     765      if (len < -1) {
     766  	return -1;
     767      }
     768      if (len == 0) return 0;
     769  
     770      if (len < 0)
     771          len = xmlStrlen(str);
     772  
     773      if (len < 0) return -1;
     774      if (len == 0) return 0;
     775  
     776      /* Note that both buf->size and buf->use can be zero here. */
     777      if ((size_t) len >= buf->size - buf->use) {
     778          if ((size_t) len >= SIZE_MAX - buf->use) {
     779              xmlBufMemoryError(buf, "growing buffer past SIZE_MAX");
     780              return(-1);
     781          }
     782          needSize = buf->use + len + 1;
     783  	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
     784  	    /*
     785  	     * Used to provide parsing limits
     786  	     */
     787  	    if (needSize >= XML_MAX_TEXT_LENGTH) {
     788  		xmlBufMemoryError(buf, "buffer error: text too long\n");
     789  		return(-1);
     790  	    }
     791  	}
     792          if (!xmlBufResize(buf, needSize)){
     793  	    xmlBufMemoryError(buf, "growing buffer");
     794              return XML_ERR_NO_MEMORY;
     795          }
     796      }
     797  
     798      memmove(&buf->content[buf->use], str, len);
     799      buf->use += len;
     800      buf->content[buf->use] = 0;
     801      UPDATE_COMPAT(buf)
     802      return 0;
     803  }
     804  
     805  /**
     806   * xmlBufCat:
     807   * @buf:  the buffer to add to
     808   * @str:  the #xmlChar string
     809   *
     810   * Append a zero terminated string to an XML buffer.
     811   *
     812   * Returns 0 successful, a positive error code number otherwise
     813   *         and -1 in case of internal or API error.
     814   */
     815  int
     816  xmlBufCat(xmlBufPtr buf, const xmlChar *str) {
     817      if ((buf == NULL) || (buf->error))
     818          return(-1);
     819      CHECK_COMPAT(buf)
     820      if (str == NULL) return -1;
     821      return xmlBufAdd(buf, str, -1);
     822  }
     823  
     824  /**
     825   * xmlBufCCat:
     826   * @buf:  the buffer to dump
     827   * @str:  the C char string
     828   *
     829   * Append a zero terminated C string to an XML buffer.
     830   *
     831   * Returns 0 successful, a positive error code number otherwise
     832   *         and -1 in case of internal or API error.
     833   */
     834  int
     835  xmlBufCCat(xmlBufPtr buf, const char *str) {
     836      return xmlBufCat(buf, (const xmlChar *) str);
     837  }
     838  
     839  /**
     840   * xmlBufWriteQuotedString:
     841   * @buf:  the XML buffer output
     842   * @string:  the string to add
     843   *
     844   * routine which manage and grows an output buffer. This one writes
     845   * a quoted or double quoted #xmlChar string, checking first if it holds
     846   * quote or double-quotes internally
     847   *
     848   * Returns 0 if successful, a positive error code number otherwise
     849   *         and -1 in case of internal or API error.
     850   */
     851  int
     852  xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) {
     853      const xmlChar *cur, *base;
     854      if ((buf == NULL) || (buf->error))
     855          return(-1);
     856      CHECK_COMPAT(buf)
     857      if (xmlStrchr(string, '\"')) {
     858          if (xmlStrchr(string, '\'')) {
     859  	    xmlBufCCat(buf, "\"");
     860              base = cur = string;
     861              while(*cur != 0){
     862                  if(*cur == '"'){
     863                      if (base != cur)
     864                          xmlBufAdd(buf, base, cur - base);
     865                      xmlBufAdd(buf, BAD_CAST "&quot;", 6);
     866                      cur++;
     867                      base = cur;
     868                  }
     869                  else {
     870                      cur++;
     871                  }
     872              }
     873              if (base != cur)
     874                  xmlBufAdd(buf, base, cur - base);
     875  	    xmlBufCCat(buf, "\"");
     876  	}
     877          else{
     878  	    xmlBufCCat(buf, "\'");
     879              xmlBufCat(buf, string);
     880  	    xmlBufCCat(buf, "\'");
     881          }
     882      } else {
     883          xmlBufCCat(buf, "\"");
     884          xmlBufCat(buf, string);
     885          xmlBufCCat(buf, "\"");
     886      }
     887      return(0);
     888  }
     889  
     890  /**
     891   * xmlBufFromBuffer:
     892   * @buffer: incoming old buffer to convert to a new one
     893   *
     894   * Helper routine to switch from the old buffer structures in use
     895   * in various APIs. It creates a wrapper xmlBufPtr which will be
     896   * used for internal processing until the xmlBufBackToBuffer() is
     897   * issued.
     898   *
     899   * Returns a new xmlBufPtr unless the call failed and NULL is returned
     900   */
     901  xmlBufPtr
     902  xmlBufFromBuffer(xmlBufferPtr buffer) {
     903      xmlBufPtr ret;
     904  
     905      if (buffer == NULL)
     906          return(NULL);
     907  
     908      ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
     909      if (ret == NULL) {
     910  	xmlBufMemoryError(NULL, "creating buffer");
     911          return(NULL);
     912      }
     913      ret->use = buffer->use;
     914      ret->size = buffer->size;
     915      UPDATE_COMPAT(ret);
     916      ret->error = 0;
     917      ret->buffer = buffer;
     918      ret->alloc = buffer->alloc;
     919      ret->content = buffer->content;
     920      ret->contentIO = buffer->contentIO;
     921  
     922      return(ret);
     923  }
     924  
     925  /**
     926   * xmlBufBackToBuffer:
     927   * @buf: new buffer wrapping the old one
     928   *
     929   * Function to be called once internal processing had been done to
     930   * update back the buffer provided by the user. This can lead to
     931   * a failure in case the size accumulated in the xmlBuf is larger
     932   * than what an xmlBuffer can support on 64 bits (INT_MAX)
     933   * The xmlBufPtr @buf wrapper is deallocated by this call in any case.
     934   *
     935   * Returns the old xmlBufferPtr unless the call failed and NULL is returned
     936   */
     937  xmlBufferPtr
     938  xmlBufBackToBuffer(xmlBufPtr buf) {
     939      xmlBufferPtr ret;
     940  
     941      if (buf == NULL)
     942          return(NULL);
     943      CHECK_COMPAT(buf)
     944      if ((buf->error) || (buf->buffer == NULL)) {
     945          xmlBufFree(buf);
     946          return(NULL);
     947      }
     948  
     949      ret = buf->buffer;
     950      /*
     951       * What to do in case of error in the buffer ???
     952       */
     953      if (buf->use > INT_MAX) {
     954          /*
     955           * Worse case, we really allocated and used more than the
     956           * maximum allowed memory for an xmlBuffer on this architecture.
     957           * Keep the buffer but provide a truncated size value.
     958           */
     959          xmlBufOverflowError(buf, "Used size too big for xmlBuffer");
     960          ret->use = INT_MAX;
     961          ret->size = INT_MAX;
     962      } else if (buf->size > INT_MAX) {
     963          /*
     964           * milder case, we allocated more than the maximum allowed memory
     965           * for an xmlBuffer on this architecture, but used less than the
     966           * limit.
     967           * Keep the buffer but provide a truncated size value.
     968           */
     969          xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");
     970          ret->use = buf->use;
     971          ret->size = INT_MAX;
     972      } else {
     973          ret->use = buf->use;
     974          ret->size = buf->size;
     975      }
     976      ret->alloc = buf->alloc;
     977      ret->content = buf->content;
     978      ret->contentIO = buf->contentIO;
     979      xmlFree(buf);
     980      return(ret);
     981  }
     982  
     983  /**
     984   * xmlBufMergeBuffer:
     985   * @buf: an xmlBufPtr
     986   * @buffer: the buffer to consume into @buf
     987   *
     988   * The content of @buffer is appended to @buf and @buffer is freed
     989   *
     990   * Returns -1 in case of error, 0 otherwise, in any case @buffer is freed
     991   */
     992  int
     993  xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) {
     994      int ret = 0;
     995  
     996      if ((buf == NULL) || (buf->error)) {
     997  	xmlBufferFree(buffer);
     998          return(-1);
     999      }
    1000      CHECK_COMPAT(buf)
    1001      if ((buffer != NULL) && (buffer->content != NULL) &&
    1002               (buffer->use > 0)) {
    1003          ret = xmlBufAdd(buf, buffer->content, buffer->use);
    1004      }
    1005      xmlBufferFree(buffer);
    1006      return(ret);
    1007  }
    1008  
    1009  /**
    1010   * xmlBufResetInput:
    1011   * @buf: an xmlBufPtr
    1012   * @input: an xmlParserInputPtr
    1013   *
    1014   * Update the input to use the current set of pointers from the buffer.
    1015   *
    1016   * Returns -1 in case of error, 0 otherwise
    1017   */
    1018  int
    1019  xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) {
    1020      if (input == NULL)
    1021          return(-1);
    1022      if ((buf == NULL) || (buf->error)) {
    1023          input->base = input->cur = input->end = BAD_CAST "";
    1024          return(-1);
    1025      }
    1026      CHECK_COMPAT(buf)
    1027      input->base = input->cur = buf->content;
    1028      input->end = &buf->content[buf->use];
    1029      return(0);
    1030  }
    1031  
    1032  /**
    1033   * xmlBufUpdateInput:
    1034   * @buf: an xmlBufPtr
    1035   * @input: an xmlParserInputPtr
    1036   * @pos: the cur value relative to the beginning of the buffer
    1037   *
    1038   * Update the input to use the base and cur relative to the buffer
    1039   * after a possible reallocation of its content
    1040   *
    1041   * Returns -1 in case of error, 0 otherwise
    1042   */
    1043  int
    1044  xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos) {
    1045      if (input == NULL)
    1046          return(-1);
    1047      /*
    1048       * TODO: It might be safer to keep using the buffer content if there
    1049       * was an error.
    1050       */
    1051      if ((buf == NULL) || (buf->error)) {
    1052          input->base = input->cur = input->end = BAD_CAST "";
    1053          return(-1);
    1054      }
    1055      CHECK_COMPAT(buf)
    1056      input->base = buf->content;
    1057      input->cur = input->base + pos;
    1058      input->end = &buf->content[buf->use];
    1059      return(0);
    1060  }
    1061