2 * buf.c: memory buffers for libxml2
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
10 * See Copyright for the status of this software.
18 #include <string.h> /* for memset() only ! */
27 #include <libxml/tree.h>
28 #include <libxml/globals.h>
29 #include <libxml/tree.h>
32 #define WITH_BUFFER_COMPAT
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.
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 */
54 #ifdef WITH_BUFFER_COMPAT
56 * Macro for compatibility with xmlBuffer to be used after an xmlBuf
57 * is updated. This makes sure the compat fields are updated too.
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;
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 .
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;
78 #else /* ! WITH_BUFFER_COMPAT */
79 #define UPDATE_COMPAT(buf)
80 #define CHECK_COMPAT(buf)
81 #endif /* WITH_BUFFER_COMPAT */
85 * @extra: extra informations
87 * Handle an out of memory condition
91 xmlBufMemoryError(xmlBufPtr buf, const char *extra)
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;
99 * xmlBufOverflowError:
100 * @extra: extra informations
102 * Handle a buffer overflow error
106 xmlBufOverflowError(xmlBufPtr buf, const char *extra)
108 __xmlSimpleError(XML_FROM_BUFFER, XML_BUF_OVERFLOW, NULL, NULL, extra);
109 if ((buf) && (buf->error == 0))
110 buf->error = XML_BUF_OVERFLOW;
117 * routine to create an XML buffer.
118 * returns the new structure.
124 ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
126 xmlBufMemoryError(NULL, "creating buffer");
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");
143 ret->contentIO = NULL;
149 * @size: initial size of buffer
151 * routine to create an XML buffer.
152 * returns the new structure.
155 xmlBufCreateSize(size_t size) {
158 ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
160 xmlBufMemoryError(NULL, "creating buffer");
167 ret->alloc = xmlBufferAllocScheme;
168 ret->size = (size ? size+2 : 0); /* +1 for ending null */
169 ret->compat_size = (int) ret->size;
171 ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
172 if (ret->content == NULL) {
173 xmlBufMemoryError(ret, "creating buffer");
180 ret->contentIO = NULL;
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.
192 * Returns the previous string contained by the buffer.
195 xmlBufDetach(xmlBufPtr buf) {
200 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
202 if (buf->buffer != NULL)
212 buf->compat_size = 0;
219 * xmlBufCreateStatic:
220 * @mem: the memory area
221 * @size: the size in byte
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.
227 * returns the new structure.
230 xmlBufCreateStatic(void *mem, size_t size) {
233 if ((mem == NULL) || (size == 0))
236 ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
238 xmlBufMemoryError(NULL, "creating buffer");
241 if (size < INT_MAX) {
242 ret->compat_use = size;
243 ret->compat_size = size;
245 ret->compat_use = INT_MAX;
246 ret->compat_size = INT_MAX;
250 ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
251 ret->content = (xmlChar *) mem;
258 * xmlBufGetAllocationScheme:
261 * Get the buffer allocation scheme
263 * Returns the scheme or -1 in case of error
266 xmlBufGetAllocationScheme(xmlBufPtr buf) {
269 xmlGenericError(xmlGenericErrorContext,
270 "xmlBufGetAllocationScheme: buf == NULL\n");
278 * xmlBufSetAllocationScheme:
279 * @buf: the buffer to tune
280 * @scheme: allocation scheme to use
282 * Sets the allocation scheme for this buffer
284 * returns 0 in case of success and -1 in case of failure
287 xmlBufSetAllocationScheme(xmlBufPtr buf,
288 xmlBufferAllocationScheme scheme) {
289 if ((buf == NULL) || (buf->error != 0)) {
291 xmlGenericError(xmlGenericErrorContext,
292 "xmlBufSetAllocationScheme: buf == NULL or in error\n");
296 if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
297 (buf->alloc == XML_BUFFER_ALLOC_IO))
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)) {
305 buf->buffer->alloc = scheme;
309 * Switching a buffer ALLOC_IO has the side effect of initializing
310 * the contentIO field with the current content
312 if (scheme == XML_BUFFER_ALLOC_IO) {
313 buf->alloc = XML_BUFFER_ALLOC_IO;
314 buf->contentIO = buf->content;
321 * @buf: the buffer to free
323 * Frees an XML buffer. It frees both the content and the structure which
327 xmlBufFree(xmlBufPtr buf) {
330 xmlGenericError(xmlGenericErrorContext,
331 "xmlBufFree: buf == NULL\n");
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);
353 xmlBufEmpty(xmlBufPtr buf) {
354 if ((buf == NULL) || (buf->error != 0)) return;
355 if (buf->content == NULL) return;
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;
364 buf->size += start_buf;
365 buf->content = buf->contentIO;
375 * @buf: the buffer to dump
376 * @len: the number of xmlChar to remove
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.
383 * Returns the number of byte removed or 0 in case of failure
386 xmlBufShrink(xmlBufPtr buf, size_t len) {
387 if ((buf == NULL) || (buf->error != 0)) return(0);
389 if (len == 0) return(0);
390 if (len > buf->use) return(0);
393 if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
394 ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
396 * we just move the content pointer, but also make sure
397 * the perceived buffer size has shrinked accordingly
403 * sometimes though it maybe be better to really shrink
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;
416 memmove(buf->content, &buf->content[len], buf->use);
417 buf->content[buf->use] = 0;
424 * xmlBufGrowInternal:
426 * @len: the minimum free size to allocate
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
432 * Returns 0 in case of error or the length made available otherwise
435 xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
439 if ((buf == NULL) || (buf->error != 0)) return(0);
442 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
443 if (buf->use + len < buf->size)
444 return(buf->size - buf->use);
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
453 if (buf->size > (size_t) len)
454 size = buf->size * 2;
456 size = buf->use + len + 100;
458 size = buf->use + len + 100;
461 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
462 size_t start_buf = buf->content - buf->contentIO;
464 newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
465 if (newbuf == NULL) {
466 xmlBufMemoryError(buf, "growing buffer");
469 buf->contentIO = newbuf;
470 buf->content = newbuf + start_buf;
472 newbuf = (xmlChar *) xmlRealloc(buf->content, size);
473 if (newbuf == NULL) {
474 xmlBufMemoryError(buf, "growing buffer");
477 buf->content = newbuf;
481 return(buf->size - buf->use);
487 * @len: the minimum free size to allocate
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
492 * Returns -1 in case of error or the length made available otherwise
495 xmlBufGrow(xmlBufPtr buf, int len) {
498 if ((buf == NULL) || (len < 0)) return(-1);
501 ret = xmlBufGrowInternal(buf, len);
510 * @len: the minimum extra free size to allocate
512 * Grow the available space of an XML buffer, adding at least @len bytes
514 * Returns 0 if successful or -1 in case of error
517 xmlBufInflate(xmlBufPtr buf, size_t len) {
518 if (buf == NULL) return(-1);
519 xmlBufGrowInternal(buf, len + buf->size);
527 * @file: the file output
528 * @buf: the buffer to dump
530 * Dumps an XML buffer to a FILE *.
531 * Returns the number of #xmlChar written
534 xmlBufDump(FILE *file, xmlBufPtr buf) {
537 if ((buf == NULL) || (buf->error != 0)) {
539 xmlGenericError(xmlGenericErrorContext,
540 "xmlBufDump: buf == NULL or in error\n");
544 if (buf->content == NULL) {
546 xmlGenericError(xmlGenericErrorContext,
547 "xmlBufDump: buf->content == NULL\n");
554 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
562 * Function to extract the content of a buffer
564 * Returns the internal content
568 xmlBufContent(const xmlBuf *buf)
570 if ((!buf) || (buf->error))
573 return(buf->content);
580 * Function to extract the end of the content of a buffer
582 * Returns the end of the internal content or NULL in case of error
586 xmlBufEnd(xmlBufPtr buf)
588 if ((!buf) || (buf->error))
592 return(&buf->content[buf->use]);
598 * @len: the size which were added at the end
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
604 * Returns -1 in case of error and 0 otherwise
607 xmlBufAddLen(xmlBufPtr buf, size_t len) {
608 if ((buf == NULL) || (buf->error))
611 if (len > (buf->size - buf->use))
615 if (buf->size > buf->use)
616 buf->content[buf->use] = 0;
625 * @len: the size to erase at the end
627 * Sometime data need to be erased at the end of the buffer
629 * Returns -1 in case of error and 0 otherwise
632 xmlBufErase(xmlBufPtr buf, size_t len) {
633 if ((buf == NULL) || (buf->error))
639 buf->content[buf->use] = 0;
648 * Function to get the length of a buffer
650 * Returns the length of data in the internal content
654 xmlBufLength(const xmlBufPtr buf)
656 if ((!buf) || (buf->error))
667 * Function to get the length of a buffer
669 * Returns the length of data in the internal content
673 xmlBufUse(const xmlBufPtr buf)
675 if ((!buf) || (buf->error))
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
690 * Returns the amount or 0 if none or an error occured
694 xmlBufAvail(const xmlBufPtr buf)
696 if ((!buf) || (buf->error))
700 return(buf->size - buf->use);
707 * Tell if a buffer is empty
709 * Returns 0 if no, 1 if yes and -1 in case of error
712 xmlBufIsEmpty(const xmlBufPtr buf)
714 if ((!buf) || (buf->error))
718 return(buf->use == 0);
723 * @buf: the buffer to resize
724 * @size: the desired size
726 * Resize a buffer to accommodate minimum size of @size.
728 * Returns 0 in case of problems, 1 otherwise
731 xmlBufResize(xmlBufPtr buf, size_t size)
733 unsigned int newSize;
734 xmlChar* rebuf = NULL;
737 if ((buf == NULL) || (buf->error))
741 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
743 /* Don't resize if we don't have to */
744 if (size < buf->size)
747 /* figure out new size */
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");
761 case XML_BUFFER_ALLOC_EXACT:
764 case XML_BUFFER_ALLOC_HYBRID:
765 if (buf->use < BASE_BUFFER_SIZE)
768 newSize = buf->size * 2;
769 while (size > newSize) {
770 if (newSize > UINT_MAX / 2) {
771 xmlBufMemoryError(buf, "growing buffer");
784 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
785 start_buf = buf->content - buf->contentIO;
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;
794 rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
796 xmlBufMemoryError(buf, "growing buffer");
799 buf->contentIO = rebuf;
800 buf->content = rebuf + start_buf;
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);
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.
813 rebuf = (xmlChar *) xmlMallocAtomic(newSize);
815 memcpy(rebuf, buf->content, buf->use);
816 xmlFree(buf->content);
821 xmlBufMemoryError(buf, "growing buffer");
824 buf->content = rebuf;
834 * @buf: the buffer to dump
835 * @str: the #xmlChar string
836 * @len: the number of #xmlChar to add
838 * Add a string range to an XML buffer. if len == -1, the length of
841 * Returns 0 successful, a positive error code number otherwise
842 * and -1 in case of internal or API error.
845 xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
846 unsigned int needSize;
848 if ((str == NULL) || (buf == NULL) || (buf->error))
852 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
855 xmlGenericError(xmlGenericErrorContext,
856 "xmlBufAdd: len < 0\n");
860 if (len == 0) return 0;
863 len = xmlStrlen(str);
865 if (len < 0) return -1;
866 if (len == 0) return 0;
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;
876 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
878 buf->content[buf->use] = 0;
886 * @str: the #xmlChar string
887 * @len: the number of #xmlChar to add
889 * Add a string range to the beginning of an XML buffer.
890 * if len == -1, the length of @str is recomputed.
892 * Returns 0 successful, a positive error code number otherwise
893 * and -1 in case of internal or API error.
896 xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len) {
897 unsigned int needSize;
899 if ((buf == NULL) || (buf->error))
902 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
905 xmlGenericError(xmlGenericErrorContext,
906 "xmlBufAddHead: str == NULL\n");
912 xmlGenericError(xmlGenericErrorContext,
913 "xmlBufAddHead: len < 0\n");
917 if (len == 0) return 0;
920 len = xmlStrlen(str);
922 if (len <= 0) return -1;
924 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
925 size_t start_buf = buf->content - buf->contentIO;
927 if (start_buf > (unsigned int) len) {
929 * We can add it in the space previously shrinked
932 memmove(&buf->content[0], str, len);
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;
947 memmove(&buf->content[len], &buf->content[0], buf->use);
948 memmove(&buf->content[0], str, len);
950 buf->content[buf->use] = 0;
957 * @buf: the buffer to add to
958 * @str: the #xmlChar string
960 * Append a zero terminated string to an XML buffer.
962 * Returns 0 successful, a positive error code number otherwise
963 * and -1 in case of internal or API error.
966 xmlBufCat(xmlBufPtr buf, const xmlChar *str) {
967 if ((buf == NULL) || (buf->error))
970 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
971 if (str == NULL) return -1;
972 return xmlBufAdd(buf, str, -1);
977 * @buf: the buffer to dump
978 * @str: the C char string
980 * Append a zero terminated C string to an XML buffer.
982 * Returns 0 successful, a positive error code number otherwise
983 * and -1 in case of internal or API error.
986 xmlBufCCat(xmlBufPtr buf, const char *str) {
989 if ((buf == NULL) || (buf->error))
992 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
995 xmlGenericError(xmlGenericErrorContext,
996 "xmlBufCCat: str == NULL\n");
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;
1007 buf->content[buf->use++] = *cur;
1009 buf->content[buf->use] = 0;
1016 * @buf: the XML buffer
1017 * @string: the string to add
1019 * routine which manages and grows an output buffer. This one adds
1020 * xmlChars at the end of the buffer.
1022 * Returns 0 if successful, a positive error code number otherwise
1023 * and -1 in case of internal or API error.
1026 xmlBufWriteCHAR(xmlBufPtr buf, const xmlChar *string) {
1027 if ((buf == NULL) || (buf->error))
1030 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
1032 return(xmlBufCat(buf, string));
1037 * @buf: the XML buffer output
1038 * @string: the string to add
1040 * routine which manage and grows an output buffer. This one add
1041 * C chars at the end of the array.
1043 * Returns 0 if successful, a positive error code number otherwise
1044 * and -1 in case of internal or API error.
1047 xmlBufWriteChar(xmlBufPtr buf, const char *string) {
1048 if ((buf == NULL) || (buf->error))
1051 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
1053 return(xmlBufCCat(buf, string));
1058 * xmlBufWriteQuotedString:
1059 * @buf: the XML buffer output
1060 * @string: the string to add
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
1066 * Returns 0 if successful, a positive error code number otherwise
1067 * and -1 in case of internal or API error.
1070 xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) {
1071 const xmlChar *cur, *base;
1072 if ((buf == NULL) || (buf->error))
1075 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
1077 if (xmlStrchr(string, '\"')) {
1078 if (xmlStrchr(string, '\'')) {
1080 xmlGenericError(xmlGenericErrorContext,
1081 "xmlBufWriteQuotedString: string contains quote and double-quotes !\n");
1083 xmlBufCCat(buf, "\"");
1084 base = cur = string;
1088 xmlBufAdd(buf, base, cur - base);
1089 xmlBufAdd(buf, BAD_CAST """, 6);
1098 xmlBufAdd(buf, base, cur - base);
1099 xmlBufCCat(buf, "\"");
1102 xmlBufCCat(buf, "\'");
1103 xmlBufCat(buf, string);
1104 xmlBufCCat(buf, "\'");
1107 xmlBufCCat(buf, "\"");
1108 xmlBufCat(buf, string);
1109 xmlBufCCat(buf, "\"");
1116 * @buffer: incoming old buffer to convert to a new one
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
1123 * Returns a new xmlBufPtr unless the call failed and NULL is returned
1126 xmlBufFromBuffer(xmlBufferPtr buffer) {
1132 ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
1134 xmlBufMemoryError(NULL, "creating buffer");
1137 ret->use = buffer->use;
1138 ret->size = buffer->size;
1139 ret->compat_use = buffer->use;
1140 ret->compat_size = buffer->size;
1142 ret->buffer = buffer;
1143 ret->alloc = buffer->alloc;
1144 ret->content = buffer->content;
1145 ret->contentIO = buffer->contentIO;
1151 * xmlBufBackToBuffer:
1152 * @buf: new buffer wrapping the old one
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.
1160 * Returns the old xmlBufferPtr unless the call failed and NULL is returned
1163 xmlBufBackToBuffer(xmlBufPtr buf) {
1166 if ((buf == NULL) || (buf->error))
1169 if (buf->buffer == NULL) {
1176 * What to do in case of error in the buffer ???
1178 if (buf->use > INT_MAX) {
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.
1184 xmlBufOverflowError(buf, "Used size too big for xmlBuffer");
1186 ret->size = INT_MAX;
1187 } else if (buf->size > INT_MAX) {
1189 * milder case, we allocated more than the maximum allowed memory
1190 * for an xmlBuffer on this architecture, but used less than the
1192 * Keep the buffer but provide a truncated size value.
1194 xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");
1195 ret->size = INT_MAX;
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;
1207 * xmlBufMergeBuffer:
1208 * @buf: an xmlBufPtr
1209 * @buffer: the buffer to consume into @buf
1211 * The content of @buffer is appended to @buf and @buffer is freed
1213 * Returns -1 in case of error, 0 otherwise, in any case @buffer is freed
1216 xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) {
1219 if ((buf == NULL) || (buf->error)) {
1220 xmlBufferFree(buffer);
1224 if ((buffer != NULL) && (buffer->content != NULL) &&
1225 (buffer->use > 0)) {
1226 ret = xmlBufAdd(buf, buffer->content, buffer->use);
1228 xmlBufferFree(buffer);
1234 * @buf: an xmlBufPtr
1235 * @input: an xmlParserInputPtr
1237 * Update the input to use the current set of pointers from the buffer.
1239 * Returns -1 in case of error, 0 otherwise
1242 xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) {
1243 if ((input == NULL) || (buf == NULL) || (buf->error))
1246 input->base = input->cur = buf->content;
1247 input->end = &buf->content[buf->use];
1252 * xmlBufGetInputBase:
1253 * @buf: an xmlBufPtr
1254 * @input: an xmlParserInputPtr
1256 * Get the base of the @input relative to the beginning of the buffer
1258 * Returns the size_t corresponding to the displacement
1261 xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
1264 if ((input == NULL) || (buf == NULL) || (buf->error))
1267 base = input->base - buf->content;
1269 * We could do some pointer arythmetic checks but that's probably
1272 if (base > buf->size) {
1273 xmlBufOverflowError(buf, "Input reference outside of the buffer");
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
1286 * Update the input to use the base and cur relative to the buffer
1287 * after a possible reallocation of its content
1289 * Returns -1 in case of error, 0 otherwise
1292 xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
1293 size_t base, size_t cur) {
1294 if ((input == NULL) || (buf == NULL) || (buf->error))
1297 input->base = &buf->content[base];
1298 input->cur = input->base + cur;
1299 input->end = &buf->content[buf->use];
1304 #include "elfgcchack.h"