libxml2 r3787 - in trunk: . include/libxml
- From: veillard svn gnome org
- To: svn-commits-list gnome org
- Subject: libxml2 r3787 - in trunk: . include/libxml
- Date: Sat, 30 Aug 2008 12:52:27 +0000 (UTC)
Author: veillard
Date: Sat Aug 30 12:52:26 2008
New Revision: 3787
URL: http://svn.gnome.org/viewvc/libxml2?rev=3787&view=rev
Log:
* include/libxml/tree.h tree.c: make a new kind of buffer where
shrinking and adding in head can avoid reallocation or full
buffer memmoves
* encoding.c xmlIO.c: use the new kind of buffers for output
buffers
Daniel
Modified:
trunk/ChangeLog
trunk/encoding.c
trunk/include/libxml/tree.h
trunk/tree.c
trunk/xmlIO.c
Modified: trunk/encoding.c
==============================================================================
--- trunk/encoding.c (original)
+++ trunk/encoding.c Sat Aug 30 12:52:26 2008
@@ -1999,9 +1999,11 @@
if (handler->output != NULL) {
ret = handler->output(&out->content[out->use], &written,
in->content, &toconv);
- xmlBufferShrink(in, toconv);
- out->use += written;
- writtentot += written;
+ if (written > 0) {
+ xmlBufferShrink(in, toconv);
+ out->use += written;
+ writtentot += written;
+ }
out->content[out->use] = 0;
}
#ifdef LIBXML_ICONV_ENABLED
Modified: trunk/include/libxml/tree.h
==============================================================================
--- trunk/include/libxml/tree.h (original)
+++ trunk/include/libxml/tree.h Sat Aug 30 12:52:26 2008
@@ -71,9 +71,10 @@
*/
typedef enum {
- XML_BUFFER_ALLOC_DOUBLEIT,
- XML_BUFFER_ALLOC_EXACT,
- XML_BUFFER_ALLOC_IMMUTABLE
+ XML_BUFFER_ALLOC_DOUBLEIT, /* double each time one need to grow */
+ XML_BUFFER_ALLOC_EXACT, /* grow only to the minimal size */
+ XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
+ XML_BUFFER_ALLOC_IO /* special allocation scheme used for I/O */
} xmlBufferAllocationScheme;
/**
@@ -88,6 +89,7 @@
unsigned int use; /* The buffer size used */
unsigned int size; /* The buffer size */
xmlBufferAllocationScheme alloc; /* The realloc method */
+ xmlChar *contentIO; /* in IO mode we may have a different base */
};
/**
Modified: trunk/tree.c
==============================================================================
--- trunk/tree.c (original)
+++ trunk/tree.c Sat Aug 30 12:52:26 2008
@@ -6652,6 +6652,7 @@
return(NULL);
}
ret->content[0] = 0;
+ ret->contentIO = NULL;
return(ret);
}
@@ -6684,6 +6685,7 @@
ret->content[0] = 0;
} else
ret->content = NULL;
+ ret->contentIO = NULL;
return(ret);
}
@@ -6756,7 +6758,10 @@
return;
}
- if ((buf->content != NULL) &&
+ if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
+ (buf->contentIO != NULL)) {
+ xmlFree(buf->contentIO);
+ } else if ((buf->content != NULL) &&
(buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
xmlFree(buf->content);
}
@@ -6776,8 +6781,18 @@
buf->use = 0;
if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
buf->content = BAD_CAST "";
+ } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
+ (buf->contentIO != NULL)) {
+ size_t start_buf = buf->content - buf->contentIO;
+
+ buf->size += start_buf;
+ buf->content = buf->contentIO;
+ buf->content[0] = 0;
} else {
- memset(buf->content, 0, buf->size);
+ buf->content[0] = 0;
+ }
+ if (buf->size > 10000000) {
+ xmlTreeErr(XML_ERR_INTERNAL_ERROR, NULL,"Buffer grew too much");
}
}
@@ -6797,12 +6812,35 @@
if (len > buf->use) return(-1);
buf->use -= len;
- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
+ if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
+ ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
+ /*
+ * we just move the content pointer, but also make sure
+ * the perceived buffer size has shrinked accordingly
+ */
buf->content += len;
+ buf->size -= len;
+
+ /*
+ * sometimes though it maybe be better to really shrink
+ * on IO buffers
+ */
+ if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
+ size_t start_buf = buf->content - buf->contentIO;
+ if (start_buf >= buf->size) {
+ memmove(buf->contentIO, &buf->content[0], buf->use);
+ buf->content = buf->contentIO;
+ buf->content[buf->use] = 0;
+ buf->size += start_buf;
+ }
+ }
} else {
- memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
+ memmove(buf->content, &buf->content[len], buf->use);
buf->content[buf->use] = 0;
}
+ if (buf->size > 10000000) {
+ xmlTreeErr(XML_ERR_INTERNAL_ERROR, NULL,"Buffer grew too much");
+ }
return(len);
}
@@ -6838,13 +6876,28 @@
size = buf->use + len + 100;
#endif
- newbuf = (xmlChar *) xmlRealloc(buf->content, size);
- if (newbuf == NULL) {
- xmlTreeErrMemory("growing buffer");
- return(-1);
+ if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
+ size_t start_buf = buf->content - buf->contentIO;
+
+ newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
+ if (newbuf == NULL) {
+ xmlTreeErrMemory("growing buffer");
+ return(-1);
+ }
+ buf->contentIO = newbuf;
+ buf->content = newbuf + start_buf;
+ } else {
+ newbuf = (xmlChar *) xmlRealloc(buf->content, size);
+ if (newbuf == NULL) {
+ xmlTreeErrMemory("growing buffer");
+ return(-1);
+ }
+ buf->content = newbuf;
}
- buf->content = newbuf;
buf->size = size;
+ if (buf->size > 10000000) {
+ xmlTreeErr(XML_ERR_INTERNAL_ERROR, NULL,"Buffer grew too much");
+ }
return(buf->size - buf->use);
}
@@ -6930,6 +6983,7 @@
{
unsigned int newSize;
xmlChar* rebuf = NULL;
+ size_t start_buf;
if (buf == NULL)
return(0);
@@ -6942,43 +6996,66 @@
/* figure out new size */
switch (buf->alloc){
- case XML_BUFFER_ALLOC_DOUBLEIT:
- /*take care of empty case*/
- newSize = (buf->size ? buf->size*2 : size + 10);
- while (size > newSize) newSize *= 2;
- break;
- case XML_BUFFER_ALLOC_EXACT:
- newSize = size+10;
- break;
- default:
- newSize = size+10;
- break;
- }
-
- if (buf->content == NULL)
- rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
- else if (buf->size - buf->use < 100) {
- rebuf = (xmlChar *) xmlRealloc(buf->content,
- newSize * sizeof(xmlChar));
- } else {
- /*
- * if we are reallocating a buffer far from being full, it's
- * better to make a new allocation and copy only the used range
- * and free the old one.
- */
- rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
- if (rebuf != NULL) {
- memcpy(rebuf, buf->content, buf->use);
- xmlFree(buf->content);
- rebuf[buf->use] = 0;
- }
+ case XML_BUFFER_ALLOC_IO:
+ case XML_BUFFER_ALLOC_DOUBLEIT:
+ /*take care of empty case*/
+ newSize = (buf->size ? buf->size*2 : size + 10);
+ while (size > newSize) newSize *= 2;
+ break;
+ case XML_BUFFER_ALLOC_EXACT:
+ newSize = size+10;
+ break;
+ default:
+ newSize = size+10;
+ break;
}
- if (rebuf == NULL) {
- xmlTreeErrMemory("growing buffer");
- return 0;
+
+ if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
+ start_buf = buf->content - buf->contentIO;
+
+ if (start_buf > newSize) {
+ /* move data back to start */
+ memmove(buf->contentIO, buf->content, buf->use);
+ buf->content = buf->contentIO;
+ buf->content[buf->use] = 0;
+ buf->size += start_buf;
+ } else {
+ rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
+ if (rebuf == NULL) {
+ xmlTreeErrMemory("growing buffer");
+ return 0;
+ }
+ buf->contentIO = rebuf;
+ buf->content = rebuf + start_buf;
+ }
+ } else {
+ if (buf->content == NULL) {
+ rebuf = (xmlChar *) xmlMallocAtomic(newSize);
+ } else if (buf->size - buf->use < 100) {
+ rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
+ } else {
+ /*
+ * if we are reallocating a buffer far from being full, it's
+ * better to make a new allocation and copy only the used range
+ * and free the old one.
+ */
+ rebuf = (xmlChar *) xmlMallocAtomic(newSize);
+ if (rebuf != NULL) {
+ memcpy(rebuf, buf->content, buf->use);
+ xmlFree(buf->content);
+ rebuf[buf->use] = 0;
+ }
+ }
+ if (rebuf == NULL) {
+ xmlTreeErrMemory("growing buffer");
+ return 0;
+ }
+ buf->content = rebuf;
}
- buf->content = rebuf;
buf->size = newSize;
+ if (buf->size > 10000000) {
+ xmlTreeErr(XML_ERR_INTERNAL_ERROR, NULL,"Buffer grew too much");
+ }
return 1;
}
@@ -7072,6 +7149,20 @@
if (len <= 0) return -1;
+ if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
+ size_t start_buf = buf->content - buf->contentIO;
+
+ if (start_buf > (unsigned int) len) {
+ /*
+ * We can add it in the space previously shrinked
+ */
+ buf->content -= len;
+ memmove(&buf->content[0], str, len);
+ buf->use += len;
+ buf->size += len;
+ return(0);
+ }
+ }
needSize = buf->use + len + 2;
if (needSize > buf->size){
if (!xmlBufferResize(buf, needSize)){
@@ -7080,8 +7171,8 @@
}
}
- memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar));
- memmove(&buf->content[0], str, len * sizeof(xmlChar));
+ memmove(&buf->content[len], &buf->content[0], buf->use);
+ memmove(&buf->content[0], str, len);
buf->use += len;
buf->content[buf->use] = 0;
return 0;
Modified: trunk/xmlIO.c
==============================================================================
--- trunk/xmlIO.c (original)
+++ trunk/xmlIO.c Sat Aug 30 12:52:26 2008
@@ -2274,10 +2274,21 @@
xmlFree(ret);
return(NULL);
}
- ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
+
+ /*
+ * For conversion buffers we use the special IO handling
+ */
+ ret->buffer->alloc = XML_BUFFER_ALLOC_IO;
+ ret->buffer->contentIO = ret->buffer->content;
+
ret->encoder = encoder;
if (encoder != NULL) {
ret->conv = xmlBufferCreateSize(4000);
+ if (ret->conv == NULL) {
+ xmlFree(ret);
+ return(NULL);
+ }
+
/*
* This call is designed to initiate the encoder state
*/
@@ -3320,9 +3331,10 @@
* not the case force a flush, but make sure we stay in the loop
*/
if (chunk < 40) {
- nbchars = 0;
- oldwritten = -1;
- goto flush;
+ if (xmlBufferGrow(out->buffer, out->buffer->size + 100) < 0)
+ return(-1);
+ oldwritten = -1;
+ continue;
}
/*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]