xref: /reactos/sdk/lib/3rdparty/libxml2/buf.c (revision 40ee59d6)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * buf.c: memory buffers for libxml2
3c2c66affSColin Finck  *
4f22fa382SThomas Faber  * new buffer structures and entry points to simplify the maintenance
5c2c66affSColin Finck  * of libxml2 and ensure we keep good control over memory allocations
6c2c66affSColin Finck  * and stay 64 bits clean.
7c2c66affSColin Finck  * The new entry point use the xmlBufPtr opaque structure and
8c2c66affSColin Finck  * xmlBuf...() counterparts to the old xmlBuf...() functions
9c2c66affSColin Finck  *
10c2c66affSColin Finck  * See Copyright for the status of this software.
11c2c66affSColin Finck  *
12c2c66affSColin Finck  * daniel@veillard.com
13c2c66affSColin Finck  */
14c2c66affSColin Finck 
15c2c66affSColin Finck #define IN_LIBXML
16c2c66affSColin Finck #include "libxml.h"
17c2c66affSColin Finck 
18c2c66affSColin Finck #include <string.h> /* for memset() only ! */
19c2c66affSColin Finck #include <limits.h>
20c2c66affSColin Finck #ifdef HAVE_CTYPE_H
21c2c66affSColin Finck #include <ctype.h>
22c2c66affSColin Finck #endif
23c2c66affSColin Finck #ifdef HAVE_STDLIB_H
24c2c66affSColin Finck #include <stdlib.h>
25c2c66affSColin Finck #endif
26c2c66affSColin Finck 
27c2c66affSColin Finck #include <libxml/tree.h>
28c2c66affSColin Finck #include <libxml/globals.h>
29c2c66affSColin Finck #include <libxml/tree.h>
30c2c66affSColin Finck #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
31c2c66affSColin Finck #include "buf.h"
32c2c66affSColin Finck 
33c2c66affSColin Finck #define WITH_BUFFER_COMPAT
34c2c66affSColin Finck 
35c2c66affSColin Finck /**
36c2c66affSColin Finck  * xmlBuf:
37c2c66affSColin Finck  *
38c2c66affSColin Finck  * A buffer structure. The base of the structure is somehow compatible
39c2c66affSColin Finck  * with struct _xmlBuffer to limit risks on application which accessed
40c2c66affSColin Finck  * directly the input->buf->buffer structures.
41c2c66affSColin Finck  */
42c2c66affSColin Finck 
43c2c66affSColin Finck struct _xmlBuf {
44c2c66affSColin Finck     xmlChar *content;		/* The buffer content UTF8 */
45c2c66affSColin Finck     unsigned int compat_use;    /* for binary compatibility */
46c2c66affSColin Finck     unsigned int compat_size;   /* for binary compatibility */
47c2c66affSColin Finck     xmlBufferAllocationScheme alloc; /* The realloc method */
48c2c66affSColin Finck     xmlChar *contentIO;		/* in IO mode we may have a different base */
49c2c66affSColin Finck     size_t use;		        /* The buffer size used */
50c2c66affSColin Finck     size_t size;		/* The buffer size */
51c2c66affSColin Finck     xmlBufferPtr buffer;        /* wrapper for an old buffer */
52fc82f8e2SThomas Faber     int error;                  /* an error code if a failure occurred */
53c2c66affSColin Finck };
54c2c66affSColin Finck 
55c2c66affSColin Finck #ifdef WITH_BUFFER_COMPAT
56c2c66affSColin Finck /*
57c2c66affSColin Finck  * Macro for compatibility with xmlBuffer to be used after an xmlBuf
58c2c66affSColin Finck  * is updated. This makes sure the compat fields are updated too.
59c2c66affSColin Finck  */
60c2c66affSColin Finck #define UPDATE_COMPAT(buf)				    \
61c2c66affSColin Finck      if (buf->size < INT_MAX) buf->compat_size = buf->size; \
62c2c66affSColin Finck      else buf->compat_size = INT_MAX;			    \
63c2c66affSColin Finck      if (buf->use < INT_MAX) buf->compat_use = buf->use; \
64c2c66affSColin Finck      else buf->compat_use = INT_MAX;
65c2c66affSColin Finck 
66c2c66affSColin Finck /*
67c2c66affSColin Finck  * Macro for compatibility with xmlBuffer to be used in all the xmlBuf
68c2c66affSColin Finck  * entry points, it checks that the compat fields have not been modified
69c2c66affSColin Finck  * by direct call to xmlBuffer function from code compiled before 2.9.0 .
70c2c66affSColin Finck  */
71c2c66affSColin Finck #define CHECK_COMPAT(buf)				    \
72c2c66affSColin Finck      if (buf->size != (size_t) buf->compat_size)	    \
73c2c66affSColin Finck          if (buf->compat_size < INT_MAX)		    \
74c2c66affSColin Finck 	     buf->size = buf->compat_size;		    \
75c2c66affSColin Finck      if (buf->use != (size_t) buf->compat_use)		    \
76c2c66affSColin Finck          if (buf->compat_use < INT_MAX)			    \
77c2c66affSColin Finck 	     buf->use = buf->compat_use;
78c2c66affSColin Finck 
79c2c66affSColin Finck #else /* ! WITH_BUFFER_COMPAT */
80c2c66affSColin Finck #define UPDATE_COMPAT(buf)
81c2c66affSColin Finck #define CHECK_COMPAT(buf)
82c2c66affSColin Finck #endif /* WITH_BUFFER_COMPAT */
83c2c66affSColin Finck 
84c2c66affSColin Finck /**
85c2c66affSColin Finck  * xmlBufMemoryError:
86*40ee59d6SThomas Faber  * @extra:  extra information
87c2c66affSColin Finck  *
88c2c66affSColin Finck  * Handle an out of memory condition
89c2c66affSColin Finck  * To be improved...
90c2c66affSColin Finck  */
91c2c66affSColin Finck static void
92c2c66affSColin Finck xmlBufMemoryError(xmlBufPtr buf, const char *extra)
93c2c66affSColin Finck {
94c2c66affSColin Finck     __xmlSimpleError(XML_FROM_BUFFER, XML_ERR_NO_MEMORY, NULL, NULL, extra);
95c2c66affSColin Finck     if ((buf) && (buf->error == 0))
96c2c66affSColin Finck         buf->error = XML_ERR_NO_MEMORY;
97c2c66affSColin Finck }
98c2c66affSColin Finck 
99c2c66affSColin Finck /**
100c2c66affSColin Finck  * xmlBufOverflowError:
101*40ee59d6SThomas Faber  * @extra:  extra information
102c2c66affSColin Finck  *
103c2c66affSColin Finck  * Handle a buffer overflow error
104c2c66affSColin Finck  * To be improved...
105c2c66affSColin Finck  */
106c2c66affSColin Finck static void
107c2c66affSColin Finck xmlBufOverflowError(xmlBufPtr buf, const char *extra)
108c2c66affSColin Finck {
109c2c66affSColin Finck     __xmlSimpleError(XML_FROM_BUFFER, XML_BUF_OVERFLOW, NULL, NULL, extra);
110c2c66affSColin Finck     if ((buf) && (buf->error == 0))
111c2c66affSColin Finck         buf->error = XML_BUF_OVERFLOW;
112c2c66affSColin Finck }
113c2c66affSColin Finck 
114c2c66affSColin Finck 
115c2c66affSColin Finck /**
116c2c66affSColin Finck  * xmlBufCreate:
117c2c66affSColin Finck  *
118c2c66affSColin Finck  * routine to create an XML buffer.
119c2c66affSColin Finck  * returns the new structure.
120c2c66affSColin Finck  */
121c2c66affSColin Finck xmlBufPtr
122c2c66affSColin Finck xmlBufCreate(void) {
123c2c66affSColin Finck     xmlBufPtr ret;
124c2c66affSColin Finck 
125c2c66affSColin Finck     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
126c2c66affSColin Finck     if (ret == NULL) {
127c2c66affSColin Finck 	xmlBufMemoryError(NULL, "creating buffer");
128c2c66affSColin Finck         return(NULL);
129c2c66affSColin Finck     }
130c2c66affSColin Finck     ret->compat_use = 0;
131c2c66affSColin Finck     ret->use = 0;
132c2c66affSColin Finck     ret->error = 0;
133c2c66affSColin Finck     ret->buffer = NULL;
134c2c66affSColin Finck     ret->size = xmlDefaultBufferSize;
135c2c66affSColin Finck     ret->compat_size = xmlDefaultBufferSize;
136c2c66affSColin Finck     ret->alloc = xmlBufferAllocScheme;
137c2c66affSColin Finck     ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
138c2c66affSColin Finck     if (ret->content == NULL) {
139c2c66affSColin Finck 	xmlBufMemoryError(ret, "creating buffer");
140c2c66affSColin Finck 	xmlFree(ret);
141c2c66affSColin Finck         return(NULL);
142c2c66affSColin Finck     }
143c2c66affSColin Finck     ret->content[0] = 0;
144c2c66affSColin Finck     ret->contentIO = NULL;
145c2c66affSColin Finck     return(ret);
146c2c66affSColin Finck }
147c2c66affSColin Finck 
148c2c66affSColin Finck /**
149c2c66affSColin Finck  * xmlBufCreateSize:
150c2c66affSColin Finck  * @size: initial size of buffer
151c2c66affSColin Finck  *
152c2c66affSColin Finck  * routine to create an XML buffer.
153c2c66affSColin Finck  * returns the new structure.
154c2c66affSColin Finck  */
155c2c66affSColin Finck xmlBufPtr
156c2c66affSColin Finck xmlBufCreateSize(size_t size) {
157c2c66affSColin Finck     xmlBufPtr ret;
158c2c66affSColin Finck 
159c2c66affSColin Finck     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
160c2c66affSColin Finck     if (ret == NULL) {
161c2c66affSColin Finck 	xmlBufMemoryError(NULL, "creating buffer");
162c2c66affSColin Finck         return(NULL);
163c2c66affSColin Finck     }
164c2c66affSColin Finck     ret->compat_use = 0;
165c2c66affSColin Finck     ret->use = 0;
166c2c66affSColin Finck     ret->error = 0;
167c2c66affSColin Finck     ret->buffer = NULL;
168c2c66affSColin Finck     ret->alloc = xmlBufferAllocScheme;
169c2c66affSColin Finck     ret->size = (size ? size+2 : 0);         /* +1 for ending null */
170c2c66affSColin Finck     ret->compat_size = (int) ret->size;
171c2c66affSColin Finck     if (ret->size){
172c2c66affSColin Finck         ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
173c2c66affSColin Finck         if (ret->content == NULL) {
174c2c66affSColin Finck 	    xmlBufMemoryError(ret, "creating buffer");
175c2c66affSColin Finck             xmlFree(ret);
176c2c66affSColin Finck             return(NULL);
177c2c66affSColin Finck         }
178c2c66affSColin Finck         ret->content[0] = 0;
179c2c66affSColin Finck     } else
180c2c66affSColin Finck 	ret->content = NULL;
181c2c66affSColin Finck     ret->contentIO = NULL;
182c2c66affSColin Finck     return(ret);
183c2c66affSColin Finck }
184c2c66affSColin Finck 
185c2c66affSColin Finck /**
186c2c66affSColin Finck  * xmlBufDetach:
187c2c66affSColin Finck  * @buf:  the buffer
188c2c66affSColin Finck  *
189c2c66affSColin Finck  * Remove the string contained in a buffer and give it back to the
190c2c66affSColin Finck  * caller. The buffer is reset to an empty content.
191c2c66affSColin Finck  * This doesn't work with immutable buffers as they can't be reset.
192c2c66affSColin Finck  *
193c2c66affSColin Finck  * Returns the previous string contained by the buffer.
194c2c66affSColin Finck  */
195c2c66affSColin Finck xmlChar *
196c2c66affSColin Finck xmlBufDetach(xmlBufPtr buf) {
197c2c66affSColin Finck     xmlChar *ret;
198c2c66affSColin Finck 
199c2c66affSColin Finck     if (buf == NULL)
200c2c66affSColin Finck         return(NULL);
201c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
202c2c66affSColin Finck         return(NULL);
203c2c66affSColin Finck     if (buf->buffer != NULL)
204c2c66affSColin Finck         return(NULL);
205c2c66affSColin Finck     if (buf->error)
206c2c66affSColin Finck         return(NULL);
207c2c66affSColin Finck 
208c2c66affSColin Finck     ret = buf->content;
209c2c66affSColin Finck     buf->content = NULL;
210c2c66affSColin Finck     buf->size = 0;
211c2c66affSColin Finck     buf->use = 0;
212c2c66affSColin Finck     buf->compat_use = 0;
213c2c66affSColin Finck     buf->compat_size = 0;
214c2c66affSColin Finck 
215c2c66affSColin Finck     return ret;
216c2c66affSColin Finck }
217c2c66affSColin Finck 
218c2c66affSColin Finck 
219c2c66affSColin Finck /**
220c2c66affSColin Finck  * xmlBufCreateStatic:
221c2c66affSColin Finck  * @mem: the memory area
222c2c66affSColin Finck  * @size:  the size in byte
223c2c66affSColin Finck  *
224c2c66affSColin Finck  * routine to create an XML buffer from an immutable memory area.
225c2c66affSColin Finck  * The area won't be modified nor copied, and is expected to be
226c2c66affSColin Finck  * present until the end of the buffer lifetime.
227c2c66affSColin Finck  *
228c2c66affSColin Finck  * returns the new structure.
229c2c66affSColin Finck  */
230c2c66affSColin Finck xmlBufPtr
231c2c66affSColin Finck xmlBufCreateStatic(void *mem, size_t size) {
232c2c66affSColin Finck     xmlBufPtr ret;
233c2c66affSColin Finck 
234fc82f8e2SThomas Faber     if (mem == NULL)
235c2c66affSColin Finck         return(NULL);
236c2c66affSColin Finck 
237c2c66affSColin Finck     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
238c2c66affSColin Finck     if (ret == NULL) {
239c2c66affSColin Finck 	xmlBufMemoryError(NULL, "creating buffer");
240c2c66affSColin Finck         return(NULL);
241c2c66affSColin Finck     }
242c2c66affSColin Finck     if (size < INT_MAX) {
243c2c66affSColin Finck         ret->compat_use = size;
244c2c66affSColin Finck         ret->compat_size = size;
245c2c66affSColin Finck     } else {
246c2c66affSColin Finck         ret->compat_use = INT_MAX;
247c2c66affSColin Finck         ret->compat_size = INT_MAX;
248c2c66affSColin Finck     }
249c2c66affSColin Finck     ret->use = size;
250c2c66affSColin Finck     ret->size = size;
251c2c66affSColin Finck     ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
252c2c66affSColin Finck     ret->content = (xmlChar *) mem;
253c2c66affSColin Finck     ret->error = 0;
254c2c66affSColin Finck     ret->buffer = NULL;
255c2c66affSColin Finck     return(ret);
256c2c66affSColin Finck }
257c2c66affSColin Finck 
258c2c66affSColin Finck /**
259c2c66affSColin Finck  * xmlBufGetAllocationScheme:
260c2c66affSColin Finck  * @buf:  the buffer
261c2c66affSColin Finck  *
262c2c66affSColin Finck  * Get the buffer allocation scheme
263c2c66affSColin Finck  *
264c2c66affSColin Finck  * Returns the scheme or -1 in case of error
265c2c66affSColin Finck  */
266c2c66affSColin Finck int
267c2c66affSColin Finck xmlBufGetAllocationScheme(xmlBufPtr buf) {
268c2c66affSColin Finck     if (buf == NULL) {
269c2c66affSColin Finck #ifdef DEBUG_BUFFER
270c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
271c2c66affSColin Finck 		"xmlBufGetAllocationScheme: buf == NULL\n");
272c2c66affSColin Finck #endif
273c2c66affSColin Finck         return(-1);
274c2c66affSColin Finck     }
275c2c66affSColin Finck     return(buf->alloc);
276c2c66affSColin Finck }
277c2c66affSColin Finck 
278c2c66affSColin Finck /**
279c2c66affSColin Finck  * xmlBufSetAllocationScheme:
280c2c66affSColin Finck  * @buf:  the buffer to tune
281c2c66affSColin Finck  * @scheme:  allocation scheme to use
282c2c66affSColin Finck  *
283c2c66affSColin Finck  * Sets the allocation scheme for this buffer
284c2c66affSColin Finck  *
285c2c66affSColin Finck  * returns 0 in case of success and -1 in case of failure
286c2c66affSColin Finck  */
287c2c66affSColin Finck int
288c2c66affSColin Finck xmlBufSetAllocationScheme(xmlBufPtr buf,
289c2c66affSColin Finck                           xmlBufferAllocationScheme scheme) {
290c2c66affSColin Finck     if ((buf == NULL) || (buf->error != 0)) {
291c2c66affSColin Finck #ifdef DEBUG_BUFFER
292c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
293c2c66affSColin Finck 		"xmlBufSetAllocationScheme: buf == NULL or in error\n");
294c2c66affSColin Finck #endif
295c2c66affSColin Finck         return(-1);
296c2c66affSColin Finck     }
297c2c66affSColin Finck     if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
298c2c66affSColin Finck         (buf->alloc == XML_BUFFER_ALLOC_IO))
299c2c66affSColin Finck         return(-1);
300c2c66affSColin Finck     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
301c2c66affSColin Finck         (scheme == XML_BUFFER_ALLOC_EXACT) ||
302c2c66affSColin Finck         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
303c2c66affSColin Finck         (scheme == XML_BUFFER_ALLOC_IMMUTABLE) ||
304c2c66affSColin Finck 	(scheme == XML_BUFFER_ALLOC_BOUNDED)) {
305c2c66affSColin Finck 	buf->alloc = scheme;
306c2c66affSColin Finck         if (buf->buffer)
307c2c66affSColin Finck             buf->buffer->alloc = scheme;
308c2c66affSColin Finck         return(0);
309c2c66affSColin Finck     }
310c2c66affSColin Finck     /*
311c2c66affSColin Finck      * Switching a buffer ALLOC_IO has the side effect of initializing
312c2c66affSColin Finck      * the contentIO field with the current content
313c2c66affSColin Finck      */
314c2c66affSColin Finck     if (scheme == XML_BUFFER_ALLOC_IO) {
315c2c66affSColin Finck         buf->alloc = XML_BUFFER_ALLOC_IO;
316c2c66affSColin Finck         buf->contentIO = buf->content;
317c2c66affSColin Finck     }
318c2c66affSColin Finck     return(-1);
319c2c66affSColin Finck }
320c2c66affSColin Finck 
321c2c66affSColin Finck /**
322c2c66affSColin Finck  * xmlBufFree:
323c2c66affSColin Finck  * @buf:  the buffer to free
324c2c66affSColin Finck  *
325c2c66affSColin Finck  * Frees an XML buffer. It frees both the content and the structure which
326c2c66affSColin Finck  * encapsulate it.
327c2c66affSColin Finck  */
328c2c66affSColin Finck void
329c2c66affSColin Finck xmlBufFree(xmlBufPtr buf) {
330c2c66affSColin Finck     if (buf == NULL) {
331c2c66affSColin Finck #ifdef DEBUG_BUFFER
332c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
333c2c66affSColin Finck 		"xmlBufFree: buf == NULL\n");
334c2c66affSColin Finck #endif
335c2c66affSColin Finck 	return;
336c2c66affSColin Finck     }
337c2c66affSColin Finck 
338c2c66affSColin Finck     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
339c2c66affSColin Finck         (buf->contentIO != NULL)) {
340c2c66affSColin Finck         xmlFree(buf->contentIO);
341c2c66affSColin Finck     } else if ((buf->content != NULL) &&
342c2c66affSColin Finck         (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
343c2c66affSColin Finck         xmlFree(buf->content);
344c2c66affSColin Finck     }
345c2c66affSColin Finck     xmlFree(buf);
346c2c66affSColin Finck }
347c2c66affSColin Finck 
348c2c66affSColin Finck /**
349c2c66affSColin Finck  * xmlBufEmpty:
350c2c66affSColin Finck  * @buf:  the buffer
351c2c66affSColin Finck  *
352c2c66affSColin Finck  * empty a buffer.
353c2c66affSColin Finck  */
354c2c66affSColin Finck void
355c2c66affSColin Finck xmlBufEmpty(xmlBufPtr buf) {
356c2c66affSColin Finck     if ((buf == NULL) || (buf->error != 0)) return;
357c2c66affSColin Finck     if (buf->content == NULL) return;
358c2c66affSColin Finck     CHECK_COMPAT(buf)
359c2c66affSColin Finck     buf->use = 0;
360c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
361c2c66affSColin Finck         buf->content = BAD_CAST "";
362c2c66affSColin Finck     } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
363c2c66affSColin Finck                (buf->contentIO != NULL)) {
364c2c66affSColin Finck         size_t start_buf = buf->content - buf->contentIO;
365c2c66affSColin Finck 
366c2c66affSColin Finck 	buf->size += start_buf;
367c2c66affSColin Finck         buf->content = buf->contentIO;
368c2c66affSColin Finck         buf->content[0] = 0;
369c2c66affSColin Finck     } else {
370c2c66affSColin Finck         buf->content[0] = 0;
371c2c66affSColin Finck     }
372c2c66affSColin Finck     UPDATE_COMPAT(buf)
373c2c66affSColin Finck }
374c2c66affSColin Finck 
375c2c66affSColin Finck /**
376c2c66affSColin Finck  * xmlBufShrink:
377c2c66affSColin Finck  * @buf:  the buffer to dump
378c2c66affSColin Finck  * @len:  the number of xmlChar to remove
379c2c66affSColin Finck  *
380c2c66affSColin Finck  * Remove the beginning of an XML buffer.
381c2c66affSColin Finck  * NOTE that this routine behaviour differs from xmlBufferShrink()
382c2c66affSColin Finck  * as it will return 0 on error instead of -1 due to size_t being
383c2c66affSColin Finck  * used as the return type.
384c2c66affSColin Finck  *
385c2c66affSColin Finck  * Returns the number of byte removed or 0 in case of failure
386c2c66affSColin Finck  */
387c2c66affSColin Finck size_t
388c2c66affSColin Finck xmlBufShrink(xmlBufPtr buf, size_t len) {
389c2c66affSColin Finck     if ((buf == NULL) || (buf->error != 0)) return(0);
390c2c66affSColin Finck     CHECK_COMPAT(buf)
391c2c66affSColin Finck     if (len == 0) return(0);
392c2c66affSColin Finck     if (len > buf->use) return(0);
393c2c66affSColin Finck 
394c2c66affSColin Finck     buf->use -= len;
395c2c66affSColin Finck     if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
396c2c66affSColin Finck         ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
397c2c66affSColin Finck 	/*
398c2c66affSColin Finck 	 * we just move the content pointer, but also make sure
399f22fa382SThomas Faber 	 * the perceived buffer size has shrunk accordingly
400c2c66affSColin Finck 	 */
401c2c66affSColin Finck         buf->content += len;
402c2c66affSColin Finck 	buf->size -= len;
403c2c66affSColin Finck 
404c2c66affSColin Finck         /*
405c2c66affSColin Finck 	 * sometimes though it maybe be better to really shrink
406c2c66affSColin Finck 	 * on IO buffers
407c2c66affSColin Finck 	 */
408c2c66affSColin Finck 	if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
409c2c66affSColin Finck 	    size_t start_buf = buf->content - buf->contentIO;
410c2c66affSColin Finck 	    if (start_buf >= buf->size) {
411c2c66affSColin Finck 		memmove(buf->contentIO, &buf->content[0], buf->use);
412c2c66affSColin Finck 		buf->content = buf->contentIO;
413c2c66affSColin Finck 		buf->content[buf->use] = 0;
414c2c66affSColin Finck 		buf->size += start_buf;
415c2c66affSColin Finck 	    }
416c2c66affSColin Finck 	}
417c2c66affSColin Finck     } else {
418c2c66affSColin Finck 	memmove(buf->content, &buf->content[len], buf->use);
419c2c66affSColin Finck 	buf->content[buf->use] = 0;
420c2c66affSColin Finck     }
421c2c66affSColin Finck     UPDATE_COMPAT(buf)
422c2c66affSColin Finck     return(len);
423c2c66affSColin Finck }
424c2c66affSColin Finck 
425c2c66affSColin Finck /**
426c2c66affSColin Finck  * xmlBufGrowInternal:
427c2c66affSColin Finck  * @buf:  the buffer
428c2c66affSColin Finck  * @len:  the minimum free size to allocate
429c2c66affSColin Finck  *
430c2c66affSColin Finck  * Grow the available space of an XML buffer, @len is the target value
431c2c66affSColin Finck  * Error checking should be done on buf->error since using the return
432c2c66affSColin Finck  * value doesn't work that well
433c2c66affSColin Finck  *
434c2c66affSColin Finck  * Returns 0 in case of error or the length made available otherwise
435c2c66affSColin Finck  */
436c2c66affSColin Finck static size_t
437c2c66affSColin Finck xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
438c2c66affSColin Finck     size_t size;
439c2c66affSColin Finck     xmlChar *newbuf;
440c2c66affSColin Finck 
441c2c66affSColin Finck     if ((buf == NULL) || (buf->error != 0)) return(0);
442c2c66affSColin Finck     CHECK_COMPAT(buf)
443c2c66affSColin Finck 
444c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
445c2c66affSColin Finck     if (buf->use + len < buf->size)
446c2c66affSColin Finck         return(buf->size - buf->use);
447c2c66affSColin Finck 
448c2c66affSColin Finck     /*
449c2c66affSColin Finck      * Windows has a BIG problem on realloc timing, so we try to double
450c2c66affSColin Finck      * the buffer size (if that's enough) (bug 146697)
451c2c66affSColin Finck      * Apparently BSD too, and it's probably best for linux too
452c2c66affSColin Finck      * On an embedded system this may be something to change
453c2c66affSColin Finck      */
454c2c66affSColin Finck #if 1
455c2c66affSColin Finck     if (buf->size > (size_t) len)
456c2c66affSColin Finck         size = buf->size * 2;
457c2c66affSColin Finck     else
458c2c66affSColin Finck         size = buf->use + len + 100;
459c2c66affSColin Finck #else
460c2c66affSColin Finck     size = buf->use + len + 100;
461c2c66affSColin Finck #endif
462c2c66affSColin Finck 
463c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
464c2c66affSColin Finck         /*
465c2c66affSColin Finck 	 * Used to provide parsing limits
466c2c66affSColin Finck 	 */
467c2c66affSColin Finck         if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
468c2c66affSColin Finck 	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
469c2c66affSColin Finck 	    xmlBufMemoryError(buf, "buffer error: text too long\n");
470c2c66affSColin Finck 	    return(0);
471c2c66affSColin Finck 	}
472c2c66affSColin Finck 	if (size >= XML_MAX_TEXT_LENGTH)
473c2c66affSColin Finck 	    size = XML_MAX_TEXT_LENGTH;
474c2c66affSColin Finck     }
475c2c66affSColin Finck     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
476c2c66affSColin Finck         size_t start_buf = buf->content - buf->contentIO;
477c2c66affSColin Finck 
478c2c66affSColin Finck 	newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
479c2c66affSColin Finck 	if (newbuf == NULL) {
480c2c66affSColin Finck 	    xmlBufMemoryError(buf, "growing buffer");
481c2c66affSColin Finck 	    return(0);
482c2c66affSColin Finck 	}
483c2c66affSColin Finck 	buf->contentIO = newbuf;
484c2c66affSColin Finck 	buf->content = newbuf + start_buf;
485c2c66affSColin Finck     } else {
486c2c66affSColin Finck 	newbuf = (xmlChar *) xmlRealloc(buf->content, size);
487c2c66affSColin Finck 	if (newbuf == NULL) {
488c2c66affSColin Finck 	    xmlBufMemoryError(buf, "growing buffer");
489c2c66affSColin Finck 	    return(0);
490c2c66affSColin Finck 	}
491c2c66affSColin Finck 	buf->content = newbuf;
492c2c66affSColin Finck     }
493c2c66affSColin Finck     buf->size = size;
494c2c66affSColin Finck     UPDATE_COMPAT(buf)
495c2c66affSColin Finck     return(buf->size - buf->use);
496c2c66affSColin Finck }
497c2c66affSColin Finck 
498c2c66affSColin Finck /**
499c2c66affSColin Finck  * xmlBufGrow:
500c2c66affSColin Finck  * @buf:  the buffer
501c2c66affSColin Finck  * @len:  the minimum free size to allocate
502c2c66affSColin Finck  *
503c2c66affSColin Finck  * Grow the available space of an XML buffer, @len is the target value
504c2c66affSColin Finck  * This is been kept compatible with xmlBufferGrow() as much as possible
505c2c66affSColin Finck  *
506c2c66affSColin Finck  * Returns -1 in case of error or the length made available otherwise
507c2c66affSColin Finck  */
508c2c66affSColin Finck int
509c2c66affSColin Finck xmlBufGrow(xmlBufPtr buf, int len) {
510c2c66affSColin Finck     size_t ret;
511c2c66affSColin Finck 
512c2c66affSColin Finck     if ((buf == NULL) || (len < 0)) return(-1);
513c2c66affSColin Finck     if (len == 0)
514c2c66affSColin Finck         return(0);
515c2c66affSColin Finck     ret = xmlBufGrowInternal(buf, len);
516c2c66affSColin Finck     if (buf->error != 0)
517c2c66affSColin Finck         return(-1);
518c2c66affSColin Finck     return((int) ret);
519c2c66affSColin Finck }
520c2c66affSColin Finck 
521c2c66affSColin Finck /**
522c2c66affSColin Finck  * xmlBufInflate:
523c2c66affSColin Finck  * @buf:  the buffer
524c2c66affSColin Finck  * @len:  the minimum extra free size to allocate
525c2c66affSColin Finck  *
526c2c66affSColin Finck  * Grow the available space of an XML buffer, adding at least @len bytes
527c2c66affSColin Finck  *
528c2c66affSColin Finck  * Returns 0 if successful or -1 in case of error
529c2c66affSColin Finck  */
530c2c66affSColin Finck int
531c2c66affSColin Finck xmlBufInflate(xmlBufPtr buf, size_t len) {
532c2c66affSColin Finck     if (buf == NULL) return(-1);
533c2c66affSColin Finck     xmlBufGrowInternal(buf, len + buf->size);
534c2c66affSColin Finck     if (buf->error)
535c2c66affSColin Finck         return(-1);
536c2c66affSColin Finck     return(0);
537c2c66affSColin Finck }
538c2c66affSColin Finck 
539c2c66affSColin Finck /**
540c2c66affSColin Finck  * xmlBufDump:
541c2c66affSColin Finck  * @file:  the file output
542c2c66affSColin Finck  * @buf:  the buffer to dump
543c2c66affSColin Finck  *
544c2c66affSColin Finck  * Dumps an XML buffer to  a FILE *.
545c2c66affSColin Finck  * Returns the number of #xmlChar written
546c2c66affSColin Finck  */
547c2c66affSColin Finck size_t
548c2c66affSColin Finck xmlBufDump(FILE *file, xmlBufPtr buf) {
549c2c66affSColin Finck     size_t ret;
550c2c66affSColin Finck 
551c2c66affSColin Finck     if ((buf == NULL) || (buf->error != 0)) {
552c2c66affSColin Finck #ifdef DEBUG_BUFFER
553c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
554c2c66affSColin Finck 		"xmlBufDump: buf == NULL or in error\n");
555c2c66affSColin Finck #endif
556c2c66affSColin Finck 	return(0);
557c2c66affSColin Finck     }
558c2c66affSColin Finck     if (buf->content == NULL) {
559c2c66affSColin Finck #ifdef DEBUG_BUFFER
560c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
561c2c66affSColin Finck 		"xmlBufDump: buf->content == NULL\n");
562c2c66affSColin Finck #endif
563c2c66affSColin Finck 	return(0);
564c2c66affSColin Finck     }
565c2c66affSColin Finck     CHECK_COMPAT(buf)
566c2c66affSColin Finck     if (file == NULL)
567c2c66affSColin Finck 	file = stdout;
568c2c66affSColin Finck     ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
569c2c66affSColin Finck     return(ret);
570c2c66affSColin Finck }
571c2c66affSColin Finck 
572c2c66affSColin Finck /**
573c2c66affSColin Finck  * xmlBufContent:
574c2c66affSColin Finck  * @buf:  the buffer
575c2c66affSColin Finck  *
576c2c66affSColin Finck  * Function to extract the content of a buffer
577c2c66affSColin Finck  *
578c2c66affSColin Finck  * Returns the internal content
579c2c66affSColin Finck  */
580c2c66affSColin Finck 
581c2c66affSColin Finck xmlChar *
582c2c66affSColin Finck xmlBufContent(const xmlBuf *buf)
583c2c66affSColin Finck {
584c2c66affSColin Finck     if ((!buf) || (buf->error))
585c2c66affSColin Finck         return NULL;
586c2c66affSColin Finck 
587c2c66affSColin Finck     return(buf->content);
588c2c66affSColin Finck }
589c2c66affSColin Finck 
590c2c66affSColin Finck /**
591c2c66affSColin Finck  * xmlBufEnd:
592c2c66affSColin Finck  * @buf:  the buffer
593c2c66affSColin Finck  *
594c2c66affSColin Finck  * Function to extract the end of the content of a buffer
595c2c66affSColin Finck  *
596c2c66affSColin Finck  * Returns the end of the internal content or NULL in case of error
597c2c66affSColin Finck  */
598c2c66affSColin Finck 
599c2c66affSColin Finck xmlChar *
600c2c66affSColin Finck xmlBufEnd(xmlBufPtr buf)
601c2c66affSColin Finck {
602c2c66affSColin Finck     if ((!buf) || (buf->error))
603c2c66affSColin Finck         return NULL;
604c2c66affSColin Finck     CHECK_COMPAT(buf)
605c2c66affSColin Finck 
606c2c66affSColin Finck     return(&buf->content[buf->use]);
607c2c66affSColin Finck }
608c2c66affSColin Finck 
609c2c66affSColin Finck /**
610c2c66affSColin Finck  * xmlBufAddLen:
611c2c66affSColin Finck  * @buf:  the buffer
612c2c66affSColin Finck  * @len:  the size which were added at the end
613c2c66affSColin Finck  *
614c2c66affSColin Finck  * Sometime data may be added at the end of the buffer without
615c2c66affSColin Finck  * using the xmlBuf APIs that is used to expand the used space
616c2c66affSColin Finck  * and set the zero terminating at the end of the buffer
617c2c66affSColin Finck  *
618c2c66affSColin Finck  * Returns -1 in case of error and 0 otherwise
619c2c66affSColin Finck  */
620c2c66affSColin Finck int
621c2c66affSColin Finck xmlBufAddLen(xmlBufPtr buf, size_t len) {
622c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
623c2c66affSColin Finck         return(-1);
624c2c66affSColin Finck     CHECK_COMPAT(buf)
625c2c66affSColin Finck     if (len > (buf->size - buf->use))
626c2c66affSColin Finck         return(-1);
627c2c66affSColin Finck     buf->use += len;
628c2c66affSColin Finck     UPDATE_COMPAT(buf)
629c2c66affSColin Finck     if (buf->size > buf->use)
630c2c66affSColin Finck         buf->content[buf->use] = 0;
631c2c66affSColin Finck     else
632c2c66affSColin Finck         return(-1);
633c2c66affSColin Finck     return(0);
634c2c66affSColin Finck }
635c2c66affSColin Finck 
636c2c66affSColin Finck /**
637c2c66affSColin Finck  * xmlBufErase:
638c2c66affSColin Finck  * @buf:  the buffer
639c2c66affSColin Finck  * @len:  the size to erase at the end
640c2c66affSColin Finck  *
641c2c66affSColin Finck  * Sometime data need to be erased at the end of the buffer
642c2c66affSColin Finck  *
643c2c66affSColin Finck  * Returns -1 in case of error and 0 otherwise
644c2c66affSColin Finck  */
645c2c66affSColin Finck int
646c2c66affSColin Finck xmlBufErase(xmlBufPtr buf, size_t len) {
647c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
648c2c66affSColin Finck         return(-1);
649c2c66affSColin Finck     CHECK_COMPAT(buf)
650c2c66affSColin Finck     if (len > buf->use)
651c2c66affSColin Finck         return(-1);
652c2c66affSColin Finck     buf->use -= len;
653c2c66affSColin Finck     buf->content[buf->use] = 0;
654c2c66affSColin Finck     UPDATE_COMPAT(buf)
655c2c66affSColin Finck     return(0);
656c2c66affSColin Finck }
657c2c66affSColin Finck 
658c2c66affSColin Finck /**
659c2c66affSColin Finck  * xmlBufLength:
660c2c66affSColin Finck  * @buf:  the buffer
661c2c66affSColin Finck  *
662c2c66affSColin Finck  * Function to get the length of a buffer
663c2c66affSColin Finck  *
664c2c66affSColin Finck  * Returns the length of data in the internal content
665c2c66affSColin Finck  */
666c2c66affSColin Finck 
667c2c66affSColin Finck size_t
668c2c66affSColin Finck xmlBufLength(const xmlBufPtr buf)
669c2c66affSColin Finck {
670c2c66affSColin Finck     if ((!buf) || (buf->error))
671c2c66affSColin Finck         return 0;
672c2c66affSColin Finck     CHECK_COMPAT(buf)
673c2c66affSColin Finck 
674c2c66affSColin Finck     return(buf->use);
675c2c66affSColin Finck }
676c2c66affSColin Finck 
677c2c66affSColin Finck /**
678c2c66affSColin Finck  * xmlBufUse:
679c2c66affSColin Finck  * @buf:  the buffer
680c2c66affSColin Finck  *
681c2c66affSColin Finck  * Function to get the length of a buffer
682c2c66affSColin Finck  *
683c2c66affSColin Finck  * Returns the length of data in the internal content
684c2c66affSColin Finck  */
685c2c66affSColin Finck 
686c2c66affSColin Finck size_t
687c2c66affSColin Finck xmlBufUse(const xmlBufPtr buf)
688c2c66affSColin Finck {
689c2c66affSColin Finck     if ((!buf) || (buf->error))
690c2c66affSColin Finck         return 0;
691c2c66affSColin Finck     CHECK_COMPAT(buf)
692c2c66affSColin Finck 
693c2c66affSColin Finck     return(buf->use);
694c2c66affSColin Finck }
695c2c66affSColin Finck 
696c2c66affSColin Finck /**
697c2c66affSColin Finck  * xmlBufAvail:
698c2c66affSColin Finck  * @buf:  the buffer
699c2c66affSColin Finck  *
700c2c66affSColin Finck  * Function to find how much free space is allocated but not
701c2c66affSColin Finck  * used in the buffer. It does not account for the terminating zero
702c2c66affSColin Finck  * usually needed
703c2c66affSColin Finck  *
704fc82f8e2SThomas Faber  * Returns the amount or 0 if none or an error occurred
705c2c66affSColin Finck  */
706c2c66affSColin Finck 
707c2c66affSColin Finck size_t
708c2c66affSColin Finck xmlBufAvail(const xmlBufPtr buf)
709c2c66affSColin Finck {
710c2c66affSColin Finck     if ((!buf) || (buf->error))
711c2c66affSColin Finck         return 0;
712c2c66affSColin Finck     CHECK_COMPAT(buf)
713c2c66affSColin Finck 
714c2c66affSColin Finck     return(buf->size - buf->use);
715c2c66affSColin Finck }
716c2c66affSColin Finck 
717c2c66affSColin Finck /**
718c2c66affSColin Finck  * xmlBufIsEmpty:
719c2c66affSColin Finck  * @buf:  the buffer
720c2c66affSColin Finck  *
721c2c66affSColin Finck  * Tell if a buffer is empty
722c2c66affSColin Finck  *
723c2c66affSColin Finck  * Returns 0 if no, 1 if yes and -1 in case of error
724c2c66affSColin Finck  */
725c2c66affSColin Finck int
726c2c66affSColin Finck xmlBufIsEmpty(const xmlBufPtr buf)
727c2c66affSColin Finck {
728c2c66affSColin Finck     if ((!buf) || (buf->error))
729c2c66affSColin Finck         return(-1);
730c2c66affSColin Finck     CHECK_COMPAT(buf)
731c2c66affSColin Finck 
732c2c66affSColin Finck     return(buf->use == 0);
733c2c66affSColin Finck }
734c2c66affSColin Finck 
735c2c66affSColin Finck /**
736c2c66affSColin Finck  * xmlBufResize:
737c2c66affSColin Finck  * @buf:  the buffer to resize
738c2c66affSColin Finck  * @size:  the desired size
739c2c66affSColin Finck  *
740c2c66affSColin Finck  * Resize a buffer to accommodate minimum size of @size.
741c2c66affSColin Finck  *
742c2c66affSColin Finck  * Returns  0 in case of problems, 1 otherwise
743c2c66affSColin Finck  */
744c2c66affSColin Finck int
745c2c66affSColin Finck xmlBufResize(xmlBufPtr buf, size_t size)
746c2c66affSColin Finck {
747c2c66affSColin Finck     unsigned int newSize;
748c2c66affSColin Finck     xmlChar* rebuf = NULL;
749c2c66affSColin Finck     size_t start_buf;
750c2c66affSColin Finck 
751c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
752c2c66affSColin Finck         return(0);
753c2c66affSColin Finck     CHECK_COMPAT(buf)
754c2c66affSColin Finck 
755c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
756c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
757c2c66affSColin Finck         /*
758c2c66affSColin Finck 	 * Used to provide parsing limits
759c2c66affSColin Finck 	 */
760c2c66affSColin Finck         if (size >= XML_MAX_TEXT_LENGTH) {
761c2c66affSColin Finck 	    xmlBufMemoryError(buf, "buffer error: text too long\n");
762c2c66affSColin Finck 	    return(0);
763c2c66affSColin Finck 	}
764c2c66affSColin Finck     }
765c2c66affSColin Finck 
766c2c66affSColin Finck     /* Don't resize if we don't have to */
767c2c66affSColin Finck     if (size < buf->size)
768c2c66affSColin Finck         return 1;
769c2c66affSColin Finck 
770c2c66affSColin Finck     /* figure out new size */
771c2c66affSColin Finck     switch (buf->alloc){
772c2c66affSColin Finck 	case XML_BUFFER_ALLOC_IO:
773c2c66affSColin Finck 	case XML_BUFFER_ALLOC_DOUBLEIT:
774c2c66affSColin Finck 	    /*take care of empty case*/
775c2c66affSColin Finck 	    newSize = (buf->size ? buf->size*2 : size + 10);
776c2c66affSColin Finck 	    while (size > newSize) {
777c2c66affSColin Finck 	        if (newSize > UINT_MAX / 2) {
778c2c66affSColin Finck 	            xmlBufMemoryError(buf, "growing buffer");
779c2c66affSColin Finck 	            return 0;
780c2c66affSColin Finck 	        }
781c2c66affSColin Finck 	        newSize *= 2;
782c2c66affSColin Finck 	    }
783c2c66affSColin Finck 	    break;
784c2c66affSColin Finck 	case XML_BUFFER_ALLOC_EXACT:
785c2c66affSColin Finck 	    newSize = size+10;
786c2c66affSColin Finck 	    break;
787c2c66affSColin Finck         case XML_BUFFER_ALLOC_HYBRID:
788c2c66affSColin Finck             if (buf->use < BASE_BUFFER_SIZE)
789c2c66affSColin Finck                 newSize = size;
790c2c66affSColin Finck             else {
791c2c66affSColin Finck                 newSize = buf->size * 2;
792c2c66affSColin Finck                 while (size > newSize) {
793c2c66affSColin Finck                     if (newSize > UINT_MAX / 2) {
794c2c66affSColin Finck                         xmlBufMemoryError(buf, "growing buffer");
795c2c66affSColin Finck                         return 0;
796c2c66affSColin Finck                     }
797c2c66affSColin Finck                     newSize *= 2;
798c2c66affSColin Finck                 }
799c2c66affSColin Finck             }
800c2c66affSColin Finck             break;
801c2c66affSColin Finck 
802c2c66affSColin Finck 	default:
803c2c66affSColin Finck 	    newSize = size+10;
804c2c66affSColin Finck 	    break;
805c2c66affSColin Finck     }
806c2c66affSColin Finck 
807c2c66affSColin Finck     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
808c2c66affSColin Finck         start_buf = buf->content - buf->contentIO;
809c2c66affSColin Finck 
810c2c66affSColin Finck         if (start_buf > newSize) {
811c2c66affSColin Finck 	    /* move data back to start */
812c2c66affSColin Finck 	    memmove(buf->contentIO, buf->content, buf->use);
813c2c66affSColin Finck 	    buf->content = buf->contentIO;
814c2c66affSColin Finck 	    buf->content[buf->use] = 0;
815c2c66affSColin Finck 	    buf->size += start_buf;
816c2c66affSColin Finck 	} else {
817c2c66affSColin Finck 	    rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
818c2c66affSColin Finck 	    if (rebuf == NULL) {
819c2c66affSColin Finck 		xmlBufMemoryError(buf, "growing buffer");
820c2c66affSColin Finck 		return 0;
821c2c66affSColin Finck 	    }
822c2c66affSColin Finck 	    buf->contentIO = rebuf;
823c2c66affSColin Finck 	    buf->content = rebuf + start_buf;
824c2c66affSColin Finck 	}
825c2c66affSColin Finck     } else {
826c2c66affSColin Finck 	if (buf->content == NULL) {
827c2c66affSColin Finck 	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
828c2c66affSColin Finck 	} else if (buf->size - buf->use < 100) {
829c2c66affSColin Finck 	    rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
830c2c66affSColin Finck         } else {
831c2c66affSColin Finck 	    /*
832c2c66affSColin Finck 	     * if we are reallocating a buffer far from being full, it's
833c2c66affSColin Finck 	     * better to make a new allocation and copy only the used range
834c2c66affSColin Finck 	     * and free the old one.
835c2c66affSColin Finck 	     */
836c2c66affSColin Finck 	    rebuf = (xmlChar *) xmlMallocAtomic(newSize);
837c2c66affSColin Finck 	    if (rebuf != NULL) {
838c2c66affSColin Finck 		memcpy(rebuf, buf->content, buf->use);
839c2c66affSColin Finck 		xmlFree(buf->content);
840c2c66affSColin Finck 		rebuf[buf->use] = 0;
841c2c66affSColin Finck 	    }
842c2c66affSColin Finck 	}
843c2c66affSColin Finck 	if (rebuf == NULL) {
844c2c66affSColin Finck 	    xmlBufMemoryError(buf, "growing buffer");
845c2c66affSColin Finck 	    return 0;
846c2c66affSColin Finck 	}
847c2c66affSColin Finck 	buf->content = rebuf;
848c2c66affSColin Finck     }
849c2c66affSColin Finck     buf->size = newSize;
850c2c66affSColin Finck     UPDATE_COMPAT(buf)
851c2c66affSColin Finck 
852c2c66affSColin Finck     return 1;
853c2c66affSColin Finck }
854c2c66affSColin Finck 
855c2c66affSColin Finck /**
856c2c66affSColin Finck  * xmlBufAdd:
857c2c66affSColin Finck  * @buf:  the buffer to dump
858c2c66affSColin Finck  * @str:  the #xmlChar string
859c2c66affSColin Finck  * @len:  the number of #xmlChar to add
860c2c66affSColin Finck  *
861c2c66affSColin Finck  * Add a string range to an XML buffer. if len == -1, the length of
862c2c66affSColin Finck  * str is recomputed.
863c2c66affSColin Finck  *
864c2c66affSColin Finck  * Returns 0 successful, a positive error code number otherwise
865c2c66affSColin Finck  *         and -1 in case of internal or API error.
866c2c66affSColin Finck  */
867c2c66affSColin Finck int
868c2c66affSColin Finck xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
869c2c66affSColin Finck     unsigned int needSize;
870c2c66affSColin Finck 
871c2c66affSColin Finck     if ((str == NULL) || (buf == NULL) || (buf->error))
872c2c66affSColin Finck 	return -1;
873c2c66affSColin Finck     CHECK_COMPAT(buf)
874c2c66affSColin Finck 
875c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
876c2c66affSColin Finck     if (len < -1) {
877c2c66affSColin Finck #ifdef DEBUG_BUFFER
878c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
879c2c66affSColin Finck 		"xmlBufAdd: len < 0\n");
880c2c66affSColin Finck #endif
881c2c66affSColin Finck 	return -1;
882c2c66affSColin Finck     }
883c2c66affSColin Finck     if (len == 0) return 0;
884c2c66affSColin Finck 
885c2c66affSColin Finck     if (len < 0)
886c2c66affSColin Finck         len = xmlStrlen(str);
887c2c66affSColin Finck 
888c2c66affSColin Finck     if (len < 0) return -1;
889c2c66affSColin Finck     if (len == 0) return 0;
890c2c66affSColin Finck 
891c2c66affSColin Finck     needSize = buf->use + len + 2;
892c2c66affSColin Finck     if (needSize > buf->size){
893c2c66affSColin Finck 	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
894c2c66affSColin Finck 	    /*
895c2c66affSColin Finck 	     * Used to provide parsing limits
896c2c66affSColin Finck 	     */
897c2c66affSColin Finck 	    if (needSize >= XML_MAX_TEXT_LENGTH) {
898c2c66affSColin Finck 		xmlBufMemoryError(buf, "buffer error: text too long\n");
899c2c66affSColin Finck 		return(-1);
900c2c66affSColin Finck 	    }
901c2c66affSColin Finck 	}
902c2c66affSColin Finck         if (!xmlBufResize(buf, needSize)){
903c2c66affSColin Finck 	    xmlBufMemoryError(buf, "growing buffer");
904c2c66affSColin Finck             return XML_ERR_NO_MEMORY;
905c2c66affSColin Finck         }
906c2c66affSColin Finck     }
907c2c66affSColin Finck 
908c2c66affSColin Finck     memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
909c2c66affSColin Finck     buf->use += len;
910c2c66affSColin Finck     buf->content[buf->use] = 0;
911c2c66affSColin Finck     UPDATE_COMPAT(buf)
912c2c66affSColin Finck     return 0;
913c2c66affSColin Finck }
914c2c66affSColin Finck 
915c2c66affSColin Finck /**
916c2c66affSColin Finck  * xmlBufAddHead:
917c2c66affSColin Finck  * @buf:  the buffer
918c2c66affSColin Finck  * @str:  the #xmlChar string
919c2c66affSColin Finck  * @len:  the number of #xmlChar to add
920c2c66affSColin Finck  *
921c2c66affSColin Finck  * Add a string range to the beginning of an XML buffer.
922c2c66affSColin Finck  * if len == -1, the length of @str is recomputed.
923c2c66affSColin Finck  *
924c2c66affSColin Finck  * Returns 0 successful, a positive error code number otherwise
925c2c66affSColin Finck  *         and -1 in case of internal or API error.
926c2c66affSColin Finck  */
927c2c66affSColin Finck int
928c2c66affSColin Finck xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len) {
929c2c66affSColin Finck     unsigned int needSize;
930c2c66affSColin Finck 
931c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
932c2c66affSColin Finck         return(-1);
933c2c66affSColin Finck     CHECK_COMPAT(buf)
934c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
935c2c66affSColin Finck     if (str == NULL) {
936c2c66affSColin Finck #ifdef DEBUG_BUFFER
937c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
938c2c66affSColin Finck 		"xmlBufAddHead: str == NULL\n");
939c2c66affSColin Finck #endif
940c2c66affSColin Finck 	return -1;
941c2c66affSColin Finck     }
942c2c66affSColin Finck     if (len < -1) {
943c2c66affSColin Finck #ifdef DEBUG_BUFFER
944c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
945c2c66affSColin Finck 		"xmlBufAddHead: len < 0\n");
946c2c66affSColin Finck #endif
947c2c66affSColin Finck 	return -1;
948c2c66affSColin Finck     }
949c2c66affSColin Finck     if (len == 0) return 0;
950c2c66affSColin Finck 
951c2c66affSColin Finck     if (len < 0)
952c2c66affSColin Finck         len = xmlStrlen(str);
953c2c66affSColin Finck 
954c2c66affSColin Finck     if (len <= 0) return -1;
955c2c66affSColin Finck 
956c2c66affSColin Finck     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
957c2c66affSColin Finck         size_t start_buf = buf->content - buf->contentIO;
958c2c66affSColin Finck 
959c2c66affSColin Finck 	if (start_buf > (unsigned int) len) {
960c2c66affSColin Finck 	    /*
961f22fa382SThomas Faber 	     * We can add it in the space previously shrunk
962c2c66affSColin Finck 	     */
963c2c66affSColin Finck 	    buf->content -= len;
964c2c66affSColin Finck             memmove(&buf->content[0], str, len);
965c2c66affSColin Finck 	    buf->use += len;
966c2c66affSColin Finck 	    buf->size += len;
967c2c66affSColin Finck 	    UPDATE_COMPAT(buf)
968c2c66affSColin Finck 	    return(0);
969c2c66affSColin Finck 	}
970c2c66affSColin Finck     }
971c2c66affSColin Finck     needSize = buf->use + len + 2;
972c2c66affSColin Finck     if (needSize > buf->size){
973c2c66affSColin Finck 	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
974c2c66affSColin Finck 	    /*
975c2c66affSColin Finck 	     * Used to provide parsing limits
976c2c66affSColin Finck 	     */
977c2c66affSColin Finck 	    if (needSize >= XML_MAX_TEXT_LENGTH) {
978c2c66affSColin Finck 		xmlBufMemoryError(buf, "buffer error: text too long\n");
979c2c66affSColin Finck 		return(-1);
980c2c66affSColin Finck 	    }
981c2c66affSColin Finck 	}
982c2c66affSColin Finck         if (!xmlBufResize(buf, needSize)){
983c2c66affSColin Finck 	    xmlBufMemoryError(buf, "growing buffer");
984c2c66affSColin Finck             return XML_ERR_NO_MEMORY;
985c2c66affSColin Finck         }
986c2c66affSColin Finck     }
987c2c66affSColin Finck 
988c2c66affSColin Finck     memmove(&buf->content[len], &buf->content[0], buf->use);
989c2c66affSColin Finck     memmove(&buf->content[0], str, len);
990c2c66affSColin Finck     buf->use += len;
991c2c66affSColin Finck     buf->content[buf->use] = 0;
992c2c66affSColin Finck     UPDATE_COMPAT(buf)
993c2c66affSColin Finck     return 0;
994c2c66affSColin Finck }
995c2c66affSColin Finck 
996c2c66affSColin Finck /**
997c2c66affSColin Finck  * xmlBufCat:
998c2c66affSColin Finck  * @buf:  the buffer to add to
999c2c66affSColin Finck  * @str:  the #xmlChar string
1000c2c66affSColin Finck  *
1001c2c66affSColin Finck  * Append a zero terminated string to an XML buffer.
1002c2c66affSColin Finck  *
1003c2c66affSColin Finck  * Returns 0 successful, a positive error code number otherwise
1004c2c66affSColin Finck  *         and -1 in case of internal or API error.
1005c2c66affSColin Finck  */
1006c2c66affSColin Finck int
1007c2c66affSColin Finck xmlBufCat(xmlBufPtr buf, const xmlChar *str) {
1008c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
1009c2c66affSColin Finck         return(-1);
1010c2c66affSColin Finck     CHECK_COMPAT(buf)
1011c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
1012c2c66affSColin Finck     if (str == NULL) return -1;
1013c2c66affSColin Finck     return xmlBufAdd(buf, str, -1);
1014c2c66affSColin Finck }
1015c2c66affSColin Finck 
1016c2c66affSColin Finck /**
1017c2c66affSColin Finck  * xmlBufCCat:
1018c2c66affSColin Finck  * @buf:  the buffer to dump
1019c2c66affSColin Finck  * @str:  the C char string
1020c2c66affSColin Finck  *
1021c2c66affSColin Finck  * Append a zero terminated C string to an XML buffer.
1022c2c66affSColin Finck  *
1023c2c66affSColin Finck  * Returns 0 successful, a positive error code number otherwise
1024c2c66affSColin Finck  *         and -1 in case of internal or API error.
1025c2c66affSColin Finck  */
1026c2c66affSColin Finck int
1027c2c66affSColin Finck xmlBufCCat(xmlBufPtr buf, const char *str) {
1028c2c66affSColin Finck     const char *cur;
1029c2c66affSColin Finck 
1030c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
1031c2c66affSColin Finck         return(-1);
1032c2c66affSColin Finck     CHECK_COMPAT(buf)
1033c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
1034c2c66affSColin Finck     if (str == NULL) {
1035c2c66affSColin Finck #ifdef DEBUG_BUFFER
1036c2c66affSColin Finck         xmlGenericError(xmlGenericErrorContext,
1037c2c66affSColin Finck 		"xmlBufCCat: str == NULL\n");
1038c2c66affSColin Finck #endif
1039c2c66affSColin Finck 	return -1;
1040c2c66affSColin Finck     }
1041c2c66affSColin Finck     for (cur = str;*cur != 0;cur++) {
1042c2c66affSColin Finck         if (buf->use  + 10 >= buf->size) {
1043c2c66affSColin Finck             if (!xmlBufResize(buf, buf->use+10)){
1044c2c66affSColin Finck 		xmlBufMemoryError(buf, "growing buffer");
1045c2c66affSColin Finck                 return XML_ERR_NO_MEMORY;
1046c2c66affSColin Finck             }
1047c2c66affSColin Finck         }
1048c2c66affSColin Finck         buf->content[buf->use++] = *cur;
1049c2c66affSColin Finck     }
1050c2c66affSColin Finck     buf->content[buf->use] = 0;
1051c2c66affSColin Finck     UPDATE_COMPAT(buf)
1052c2c66affSColin Finck     return 0;
1053c2c66affSColin Finck }
1054c2c66affSColin Finck 
1055c2c66affSColin Finck /**
1056c2c66affSColin Finck  * xmlBufWriteCHAR:
1057c2c66affSColin Finck  * @buf:  the XML buffer
1058c2c66affSColin Finck  * @string:  the string to add
1059c2c66affSColin Finck  *
1060c2c66affSColin Finck  * routine which manages and grows an output buffer. This one adds
1061c2c66affSColin Finck  * xmlChars at the end of the buffer.
1062c2c66affSColin Finck  *
1063c2c66affSColin Finck  * Returns 0 if successful, a positive error code number otherwise
1064c2c66affSColin Finck  *         and -1 in case of internal or API error.
1065c2c66affSColin Finck  */
1066c2c66affSColin Finck int
1067c2c66affSColin Finck xmlBufWriteCHAR(xmlBufPtr buf, const xmlChar *string) {
1068c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
1069c2c66affSColin Finck         return(-1);
1070c2c66affSColin Finck     CHECK_COMPAT(buf)
1071c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
1072c2c66affSColin Finck         return(-1);
1073c2c66affSColin Finck     return(xmlBufCat(buf, string));
1074c2c66affSColin Finck }
1075c2c66affSColin Finck 
1076c2c66affSColin Finck /**
1077c2c66affSColin Finck  * xmlBufWriteChar:
1078c2c66affSColin Finck  * @buf:  the XML buffer output
1079c2c66affSColin Finck  * @string:  the string to add
1080c2c66affSColin Finck  *
1081c2c66affSColin Finck  * routine which manage and grows an output buffer. This one add
1082c2c66affSColin Finck  * C chars at the end of the array.
1083c2c66affSColin Finck  *
1084c2c66affSColin Finck  * Returns 0 if successful, a positive error code number otherwise
1085c2c66affSColin Finck  *         and -1 in case of internal or API error.
1086c2c66affSColin Finck  */
1087c2c66affSColin Finck int
1088c2c66affSColin Finck xmlBufWriteChar(xmlBufPtr buf, const char *string) {
1089c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
1090c2c66affSColin Finck         return(-1);
1091c2c66affSColin Finck     CHECK_COMPAT(buf)
1092c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
1093c2c66affSColin Finck         return(-1);
1094c2c66affSColin Finck     return(xmlBufCCat(buf, string));
1095c2c66affSColin Finck }
1096c2c66affSColin Finck 
1097c2c66affSColin Finck 
1098c2c66affSColin Finck /**
1099c2c66affSColin Finck  * xmlBufWriteQuotedString:
1100c2c66affSColin Finck  * @buf:  the XML buffer output
1101c2c66affSColin Finck  * @string:  the string to add
1102c2c66affSColin Finck  *
1103c2c66affSColin Finck  * routine which manage and grows an output buffer. This one writes
1104c2c66affSColin Finck  * a quoted or double quoted #xmlChar string, checking first if it holds
1105c2c66affSColin Finck  * quote or double-quotes internally
1106c2c66affSColin Finck  *
1107c2c66affSColin Finck  * Returns 0 if successful, a positive error code number otherwise
1108c2c66affSColin Finck  *         and -1 in case of internal or API error.
1109c2c66affSColin Finck  */
1110c2c66affSColin Finck int
1111c2c66affSColin Finck xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) {
1112c2c66affSColin Finck     const xmlChar *cur, *base;
1113c2c66affSColin Finck     if ((buf == NULL) || (buf->error))
1114c2c66affSColin Finck         return(-1);
1115c2c66affSColin Finck     CHECK_COMPAT(buf)
1116c2c66affSColin Finck     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
1117c2c66affSColin Finck         return(-1);
1118c2c66affSColin Finck     if (xmlStrchr(string, '\"')) {
1119c2c66affSColin Finck         if (xmlStrchr(string, '\'')) {
1120c2c66affSColin Finck #ifdef DEBUG_BUFFER
1121c2c66affSColin Finck 	    xmlGenericError(xmlGenericErrorContext,
1122c2c66affSColin Finck  "xmlBufWriteQuotedString: string contains quote and double-quotes !\n");
1123c2c66affSColin Finck #endif
1124c2c66affSColin Finck 	    xmlBufCCat(buf, "\"");
1125c2c66affSColin Finck             base = cur = string;
1126c2c66affSColin Finck             while(*cur != 0){
1127c2c66affSColin Finck                 if(*cur == '"'){
1128c2c66affSColin Finck                     if (base != cur)
1129c2c66affSColin Finck                         xmlBufAdd(buf, base, cur - base);
1130c2c66affSColin Finck                     xmlBufAdd(buf, BAD_CAST "&quot;", 6);
1131c2c66affSColin Finck                     cur++;
1132c2c66affSColin Finck                     base = cur;
1133c2c66affSColin Finck                 }
1134c2c66affSColin Finck                 else {
1135c2c66affSColin Finck                     cur++;
1136c2c66affSColin Finck                 }
1137c2c66affSColin Finck             }
1138c2c66affSColin Finck             if (base != cur)
1139c2c66affSColin Finck                 xmlBufAdd(buf, base, cur - base);
1140c2c66affSColin Finck 	    xmlBufCCat(buf, "\"");
1141c2c66affSColin Finck 	}
1142c2c66affSColin Finck         else{
1143c2c66affSColin Finck 	    xmlBufCCat(buf, "\'");
1144c2c66affSColin Finck             xmlBufCat(buf, string);
1145c2c66affSColin Finck 	    xmlBufCCat(buf, "\'");
1146c2c66affSColin Finck         }
1147c2c66affSColin Finck     } else {
1148c2c66affSColin Finck         xmlBufCCat(buf, "\"");
1149c2c66affSColin Finck         xmlBufCat(buf, string);
1150c2c66affSColin Finck         xmlBufCCat(buf, "\"");
1151c2c66affSColin Finck     }
1152c2c66affSColin Finck     return(0);
1153c2c66affSColin Finck }
1154c2c66affSColin Finck 
1155c2c66affSColin Finck /**
1156c2c66affSColin Finck  * xmlBufFromBuffer:
1157c2c66affSColin Finck  * @buffer: incoming old buffer to convert to a new one
1158c2c66affSColin Finck  *
1159c2c66affSColin Finck  * Helper routine to switch from the old buffer structures in use
1160c2c66affSColin Finck  * in various APIs. It creates a wrapper xmlBufPtr which will be
1161c2c66affSColin Finck  * used for internal processing until the xmlBufBackToBuffer() is
1162c2c66affSColin Finck  * issued.
1163c2c66affSColin Finck  *
1164c2c66affSColin Finck  * Returns a new xmlBufPtr unless the call failed and NULL is returned
1165c2c66affSColin Finck  */
1166c2c66affSColin Finck xmlBufPtr
1167c2c66affSColin Finck xmlBufFromBuffer(xmlBufferPtr buffer) {
1168c2c66affSColin Finck     xmlBufPtr ret;
1169c2c66affSColin Finck 
1170c2c66affSColin Finck     if (buffer == NULL)
1171c2c66affSColin Finck         return(NULL);
1172c2c66affSColin Finck 
1173c2c66affSColin Finck     ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
1174c2c66affSColin Finck     if (ret == NULL) {
1175c2c66affSColin Finck 	xmlBufMemoryError(NULL, "creating buffer");
1176c2c66affSColin Finck         return(NULL);
1177c2c66affSColin Finck     }
1178c2c66affSColin Finck     ret->use = buffer->use;
1179c2c66affSColin Finck     ret->size = buffer->size;
1180c2c66affSColin Finck     ret->compat_use = buffer->use;
1181c2c66affSColin Finck     ret->compat_size = buffer->size;
1182c2c66affSColin Finck     ret->error = 0;
1183c2c66affSColin Finck     ret->buffer = buffer;
1184c2c66affSColin Finck     ret->alloc = buffer->alloc;
1185c2c66affSColin Finck     ret->content = buffer->content;
1186c2c66affSColin Finck     ret->contentIO = buffer->contentIO;
1187c2c66affSColin Finck 
1188c2c66affSColin Finck     return(ret);
1189c2c66affSColin Finck }
1190c2c66affSColin Finck 
1191c2c66affSColin Finck /**
1192c2c66affSColin Finck  * xmlBufBackToBuffer:
1193c2c66affSColin Finck  * @buf: new buffer wrapping the old one
1194c2c66affSColin Finck  *
1195c2c66affSColin Finck  * Function to be called once internal processing had been done to
1196c2c66affSColin Finck  * update back the buffer provided by the user. This can lead to
1197c2c66affSColin Finck  * a failure in case the size accumulated in the xmlBuf is larger
1198c2c66affSColin Finck  * than what an xmlBuffer can support on 64 bits (INT_MAX)
1199c2c66affSColin Finck  * The xmlBufPtr @buf wrapper is deallocated by this call in any case.
1200c2c66affSColin Finck  *
1201c2c66affSColin Finck  * Returns the old xmlBufferPtr unless the call failed and NULL is returned
1202c2c66affSColin Finck  */
1203c2c66affSColin Finck xmlBufferPtr
1204c2c66affSColin Finck xmlBufBackToBuffer(xmlBufPtr buf) {
1205c2c66affSColin Finck     xmlBufferPtr ret;
1206c2c66affSColin Finck 
1207f22fa382SThomas Faber     if (buf == NULL)
1208c2c66affSColin Finck         return(NULL);
1209c2c66affSColin Finck     CHECK_COMPAT(buf)
1210f22fa382SThomas Faber     if ((buf->error) || (buf->buffer == NULL)) {
1211c2c66affSColin Finck         xmlBufFree(buf);
1212c2c66affSColin Finck         return(NULL);
1213c2c66affSColin Finck     }
1214c2c66affSColin Finck 
1215c2c66affSColin Finck     ret = buf->buffer;
1216c2c66affSColin Finck     /*
1217c2c66affSColin Finck      * What to do in case of error in the buffer ???
1218c2c66affSColin Finck      */
1219c2c66affSColin Finck     if (buf->use > INT_MAX) {
1220c2c66affSColin Finck         /*
1221c2c66affSColin Finck          * Worse case, we really allocated and used more than the
1222c2c66affSColin Finck          * maximum allowed memory for an xmlBuffer on this architecture.
1223c2c66affSColin Finck          * Keep the buffer but provide a truncated size value.
1224c2c66affSColin Finck          */
1225c2c66affSColin Finck         xmlBufOverflowError(buf, "Used size too big for xmlBuffer");
1226c2c66affSColin Finck         ret->use = INT_MAX;
1227c2c66affSColin Finck         ret->size = INT_MAX;
1228c2c66affSColin Finck     } else if (buf->size > INT_MAX) {
1229c2c66affSColin Finck         /*
1230c2c66affSColin Finck          * milder case, we allocated more than the maximum allowed memory
1231c2c66affSColin Finck          * for an xmlBuffer on this architecture, but used less than the
1232c2c66affSColin Finck          * limit.
1233c2c66affSColin Finck          * Keep the buffer but provide a truncated size value.
1234c2c66affSColin Finck          */
1235c2c66affSColin Finck         xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");
1236*40ee59d6SThomas Faber         ret->use = (int) buf->use;
1237c2c66affSColin Finck         ret->size = INT_MAX;
1238*40ee59d6SThomas Faber     } else {
1239c2c66affSColin Finck         ret->use = (int) buf->use;
1240c2c66affSColin Finck         ret->size = (int) buf->size;
1241*40ee59d6SThomas Faber     }
1242c2c66affSColin Finck     ret->alloc = buf->alloc;
1243c2c66affSColin Finck     ret->content = buf->content;
1244c2c66affSColin Finck     ret->contentIO = buf->contentIO;
1245c2c66affSColin Finck     xmlFree(buf);
1246c2c66affSColin Finck     return(ret);
1247c2c66affSColin Finck }
1248c2c66affSColin Finck 
1249c2c66affSColin Finck /**
1250c2c66affSColin Finck  * xmlBufMergeBuffer:
1251c2c66affSColin Finck  * @buf: an xmlBufPtr
1252c2c66affSColin Finck  * @buffer: the buffer to consume into @buf
1253c2c66affSColin Finck  *
1254c2c66affSColin Finck  * The content of @buffer is appended to @buf and @buffer is freed
1255c2c66affSColin Finck  *
1256c2c66affSColin Finck  * Returns -1 in case of error, 0 otherwise, in any case @buffer is freed
1257c2c66affSColin Finck  */
1258c2c66affSColin Finck int
1259c2c66affSColin Finck xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) {
1260c2c66affSColin Finck     int ret = 0;
1261c2c66affSColin Finck 
1262c2c66affSColin Finck     if ((buf == NULL) || (buf->error)) {
1263c2c66affSColin Finck 	xmlBufferFree(buffer);
1264c2c66affSColin Finck         return(-1);
1265c2c66affSColin Finck     }
1266c2c66affSColin Finck     CHECK_COMPAT(buf)
1267c2c66affSColin Finck     if ((buffer != NULL) && (buffer->content != NULL) &&
1268c2c66affSColin Finck              (buffer->use > 0)) {
1269c2c66affSColin Finck         ret = xmlBufAdd(buf, buffer->content, buffer->use);
1270c2c66affSColin Finck     }
1271c2c66affSColin Finck     xmlBufferFree(buffer);
1272c2c66affSColin Finck     return(ret);
1273c2c66affSColin Finck }
1274c2c66affSColin Finck 
1275c2c66affSColin Finck /**
1276c2c66affSColin Finck  * xmlBufResetInput:
1277c2c66affSColin Finck  * @buf: an xmlBufPtr
1278c2c66affSColin Finck  * @input: an xmlParserInputPtr
1279c2c66affSColin Finck  *
1280c2c66affSColin Finck  * Update the input to use the current set of pointers from the buffer.
1281c2c66affSColin Finck  *
1282c2c66affSColin Finck  * Returns -1 in case of error, 0 otherwise
1283c2c66affSColin Finck  */
1284c2c66affSColin Finck int
1285c2c66affSColin Finck xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) {
1286c2c66affSColin Finck     if ((input == NULL) || (buf == NULL) || (buf->error))
1287c2c66affSColin Finck         return(-1);
1288c2c66affSColin Finck     CHECK_COMPAT(buf)
1289c2c66affSColin Finck     input->base = input->cur = buf->content;
1290c2c66affSColin Finck     input->end = &buf->content[buf->use];
1291c2c66affSColin Finck     return(0);
1292c2c66affSColin Finck }
1293c2c66affSColin Finck 
1294c2c66affSColin Finck /**
1295c2c66affSColin Finck  * xmlBufGetInputBase:
1296c2c66affSColin Finck  * @buf: an xmlBufPtr
1297c2c66affSColin Finck  * @input: an xmlParserInputPtr
1298c2c66affSColin Finck  *
1299c2c66affSColin Finck  * Get the base of the @input relative to the beginning of the buffer
1300c2c66affSColin Finck  *
1301c2c66affSColin Finck  * Returns the size_t corresponding to the displacement
1302c2c66affSColin Finck  */
1303c2c66affSColin Finck size_t
1304c2c66affSColin Finck xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
1305c2c66affSColin Finck     size_t base;
1306c2c66affSColin Finck 
1307c2c66affSColin Finck     if ((input == NULL) || (buf == NULL) || (buf->error))
1308c2c66affSColin Finck         return(-1);
1309c2c66affSColin Finck     CHECK_COMPAT(buf)
1310c2c66affSColin Finck     base = input->base - buf->content;
1311c2c66affSColin Finck     /*
1312f22fa382SThomas Faber      * We could do some pointer arithmetic checks but that's probably
1313c2c66affSColin Finck      * sufficient.
1314c2c66affSColin Finck      */
1315c2c66affSColin Finck     if (base > buf->size) {
1316c2c66affSColin Finck         xmlBufOverflowError(buf, "Input reference outside of the buffer");
1317c2c66affSColin Finck         base = 0;
1318c2c66affSColin Finck     }
1319c2c66affSColin Finck     return(base);
1320c2c66affSColin Finck }
1321c2c66affSColin Finck 
1322c2c66affSColin Finck /**
1323c2c66affSColin Finck  * xmlBufSetInputBaseCur:
1324c2c66affSColin Finck  * @buf: an xmlBufPtr
1325c2c66affSColin Finck  * @input: an xmlParserInputPtr
1326c2c66affSColin Finck  * @base: the base value relative to the beginning of the buffer
1327c2c66affSColin Finck  * @cur: the cur value relative to the beginning of the buffer
1328c2c66affSColin Finck  *
1329c2c66affSColin Finck  * Update the input to use the base and cur relative to the buffer
1330c2c66affSColin Finck  * after a possible reallocation of its content
1331c2c66affSColin Finck  *
1332c2c66affSColin Finck  * Returns -1 in case of error, 0 otherwise
1333c2c66affSColin Finck  */
1334c2c66affSColin Finck int
1335c2c66affSColin Finck xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
1336c2c66affSColin Finck                       size_t base, size_t cur) {
1337*40ee59d6SThomas Faber     if (input == NULL)
1338c2c66affSColin Finck         return(-1);
1339*40ee59d6SThomas Faber     if ((buf == NULL) || (buf->error)) {
1340*40ee59d6SThomas Faber         input->base = input->cur = input->end = BAD_CAST "";
1341*40ee59d6SThomas Faber         return(-1);
1342*40ee59d6SThomas Faber     }
1343c2c66affSColin Finck     CHECK_COMPAT(buf)
1344c2c66affSColin Finck     input->base = &buf->content[base];
1345c2c66affSColin Finck     input->cur = input->base + cur;
1346c2c66affSColin Finck     input->end = &buf->content[buf->use];
1347c2c66affSColin Finck     return(0);
1348c2c66affSColin Finck }
1349c2c66affSColin Finck 
1350c2c66affSColin Finck #define bottom_buf
1351c2c66affSColin Finck #include "elfgcchack.h"
1352