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 """, 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