Annotation of embedaddon/libxml2/buf.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>