mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-27 18:50:07 +03:00
buf: Move xmlBuffer code to buf.c
This commit is contained in:
parent
92f30711de
commit
888f70c77e
678
buf.c
678
buf.c
@ -694,3 +694,681 @@ xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Old buffer implementation *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* xmlSetBufferAllocationScheme:
|
||||
* @scheme: allocation method to use
|
||||
*
|
||||
* Set the buffer allocation method. Types are
|
||||
* XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
|
||||
* XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
|
||||
* improves performance
|
||||
*/
|
||||
void
|
||||
xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
|
||||
if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_HYBRID))
|
||||
xmlBufferAllocScheme = scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlGetBufferAllocationScheme:
|
||||
*
|
||||
* Types are
|
||||
* XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
|
||||
* XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
|
||||
* improves performance
|
||||
* XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
|
||||
* in normal usage, and doubleit on large strings to avoid
|
||||
* pathological performance.
|
||||
*
|
||||
* Returns the current allocation scheme
|
||||
*/
|
||||
xmlBufferAllocationScheme
|
||||
xmlGetBufferAllocationScheme(void) {
|
||||
return(xmlBufferAllocScheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCreate:
|
||||
*
|
||||
* routine to create an XML buffer.
|
||||
* returns the new structure.
|
||||
*/
|
||||
xmlBufferPtr
|
||||
xmlBufferCreate(void) {
|
||||
xmlBufferPtr ret;
|
||||
|
||||
ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
ret->use = 0;
|
||||
ret->size = xmlDefaultBufferSize;
|
||||
ret->alloc = xmlBufferAllocScheme;
|
||||
ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
|
||||
if (ret->content == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->content[0] = 0;
|
||||
ret->contentIO = NULL;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCreateSize:
|
||||
* @size: initial size of buffer
|
||||
*
|
||||
* routine to create an XML buffer.
|
||||
* returns the new structure.
|
||||
*/
|
||||
xmlBufferPtr
|
||||
xmlBufferCreateSize(size_t size) {
|
||||
xmlBufferPtr ret;
|
||||
|
||||
if (size >= UINT_MAX)
|
||||
return(NULL);
|
||||
ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
ret->use = 0;
|
||||
ret->alloc = xmlBufferAllocScheme;
|
||||
ret->size = (size ? size + 1 : 0); /* +1 for ending null */
|
||||
if (ret->size){
|
||||
ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
|
||||
if (ret->content == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->content[0] = 0;
|
||||
} else
|
||||
ret->content = NULL;
|
||||
ret->contentIO = NULL;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferDetach:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* Remove the string contained in a buffer and gie it back to the
|
||||
* caller. The buffer is reset to an empty content.
|
||||
* This doesn't work with immutable buffers as they can't be reset.
|
||||
*
|
||||
* Returns the previous string contained by the buffer.
|
||||
*/
|
||||
xmlChar *
|
||||
xmlBufferDetach(xmlBufferPtr buf) {
|
||||
xmlChar *ret;
|
||||
|
||||
if (buf == NULL)
|
||||
return(NULL);
|
||||
|
||||
ret = buf->content;
|
||||
buf->content = NULL;
|
||||
buf->size = 0;
|
||||
buf->use = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlBufferCreateStatic:
|
||||
* @mem: the memory area
|
||||
* @size: the size in byte
|
||||
*
|
||||
* Returns an XML buffer initialized with bytes.
|
||||
*/
|
||||
xmlBufferPtr
|
||||
xmlBufferCreateStatic(void *mem, size_t size) {
|
||||
xmlBufferPtr buf = xmlBufferCreateSize(size);
|
||||
|
||||
xmlBufferAdd(buf, mem, size);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferSetAllocationScheme:
|
||||
* @buf: the buffer to tune
|
||||
* @scheme: allocation scheme to use
|
||||
*
|
||||
* Sets the allocation scheme for this buffer
|
||||
*/
|
||||
void
|
||||
xmlBufferSetAllocationScheme(xmlBufferPtr buf,
|
||||
xmlBufferAllocationScheme scheme) {
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
if (buf->alloc == XML_BUFFER_ALLOC_IO) return;
|
||||
if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_EXACT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_HYBRID))
|
||||
buf->alloc = scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferFree:
|
||||
* @buf: the buffer to free
|
||||
*
|
||||
* Frees an XML buffer. It frees both the content and the structure which
|
||||
* encapsulate it.
|
||||
*/
|
||||
void
|
||||
xmlBufferFree(xmlBufferPtr buf) {
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
|
||||
(buf->contentIO != NULL)) {
|
||||
xmlFree(buf->contentIO);
|
||||
} else if (buf->content != NULL) {
|
||||
xmlFree(buf->content);
|
||||
}
|
||||
xmlFree(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferEmpty:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* empty a buffer.
|
||||
*/
|
||||
void
|
||||
xmlBufferEmpty(xmlBufferPtr buf) {
|
||||
if (buf == NULL) return;
|
||||
if (buf->content == NULL) return;
|
||||
buf->use = 0;
|
||||
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 {
|
||||
buf->content[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferShrink:
|
||||
* @buf: the buffer to dump
|
||||
* @len: the number of xmlChar to remove
|
||||
*
|
||||
* Remove the beginning of an XML buffer.
|
||||
*
|
||||
* Returns the number of #xmlChar removed, or -1 in case of failure.
|
||||
*/
|
||||
int
|
||||
xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
|
||||
if (buf == NULL) return(-1);
|
||||
if (len == 0) return(0);
|
||||
if (len > buf->use) return(-1);
|
||||
|
||||
buf->use -= len;
|
||||
if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
|
||||
/*
|
||||
* we just move the content pointer, but also make sure
|
||||
* the perceived buffer size has shrunk 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);
|
||||
buf->content[buf->use] = 0;
|
||||
}
|
||||
return(len);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferGrow:
|
||||
* @buf: the buffer
|
||||
* @len: the minimum free size to allocate
|
||||
*
|
||||
* Grow the available space of an XML buffer.
|
||||
*
|
||||
* Returns the new available space or -1 in case of error
|
||||
*/
|
||||
int
|
||||
xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
|
||||
unsigned int size;
|
||||
xmlChar *newbuf;
|
||||
|
||||
if (buf == NULL) return(-1);
|
||||
|
||||
if (len < buf->size - buf->use)
|
||||
return(0);
|
||||
if (len >= UINT_MAX - buf->use)
|
||||
return(-1);
|
||||
|
||||
if (buf->size > (size_t) len) {
|
||||
size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
|
||||
} else {
|
||||
size = buf->use + len;
|
||||
size = size > UINT_MAX - 100 ? UINT_MAX : size + 100;
|
||||
}
|
||||
|
||||
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)
|
||||
return(-1);
|
||||
buf->contentIO = newbuf;
|
||||
buf->content = newbuf + start_buf;
|
||||
} else {
|
||||
newbuf = (xmlChar *) xmlRealloc(buf->content, size);
|
||||
if (newbuf == NULL)
|
||||
return(-1);
|
||||
buf->content = newbuf;
|
||||
}
|
||||
buf->size = size;
|
||||
return(buf->size - buf->use - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferDump:
|
||||
* @file: the file output
|
||||
* @buf: the buffer to dump
|
||||
*
|
||||
* Dumps an XML buffer to a FILE *.
|
||||
* Returns the number of #xmlChar written
|
||||
*/
|
||||
int
|
||||
xmlBufferDump(FILE *file, xmlBufferPtr buf) {
|
||||
size_t ret;
|
||||
|
||||
if (buf == NULL) {
|
||||
return(0);
|
||||
}
|
||||
if (buf->content == NULL) {
|
||||
return(0);
|
||||
}
|
||||
if (file == NULL)
|
||||
file = stdout;
|
||||
ret = fwrite(buf->content, 1, buf->use, file);
|
||||
return(ret > INT_MAX ? INT_MAX : ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferContent:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* Function to extract the content of a buffer
|
||||
*
|
||||
* Returns the internal content
|
||||
*/
|
||||
|
||||
const xmlChar *
|
||||
xmlBufferContent(const xmlBuffer *buf)
|
||||
{
|
||||
if(!buf)
|
||||
return NULL;
|
||||
|
||||
return buf->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferLength:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* Function to get the length of a buffer
|
||||
*
|
||||
* Returns the length of data in the internal content
|
||||
*/
|
||||
|
||||
int
|
||||
xmlBufferLength(const xmlBuffer *buf)
|
||||
{
|
||||
if(!buf)
|
||||
return 0;
|
||||
|
||||
return buf->use;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferResize:
|
||||
* @buf: the buffer to resize
|
||||
* @size: the desired size
|
||||
*
|
||||
* Resize a buffer to accommodate minimum size of @size.
|
||||
*
|
||||
* Returns 0 in case of problems, 1 otherwise
|
||||
*/
|
||||
int
|
||||
xmlBufferResize(xmlBufferPtr buf, unsigned int size)
|
||||
{
|
||||
unsigned int newSize;
|
||||
xmlChar* rebuf = NULL;
|
||||
size_t start_buf;
|
||||
|
||||
if (buf == NULL)
|
||||
return(0);
|
||||
|
||||
/* Don't resize if we don't have to */
|
||||
if (size < buf->size)
|
||||
return 1;
|
||||
|
||||
if (size > UINT_MAX - 10)
|
||||
return 0;
|
||||
|
||||
/* figure out new size */
|
||||
switch (buf->alloc){
|
||||
case XML_BUFFER_ALLOC_IO:
|
||||
case XML_BUFFER_ALLOC_DOUBLEIT:
|
||||
/*take care of empty case*/
|
||||
if (buf->size == 0)
|
||||
newSize = size + 10;
|
||||
else
|
||||
newSize = buf->size;
|
||||
while (size > newSize) {
|
||||
if (newSize > UINT_MAX / 2)
|
||||
return 0;
|
||||
newSize *= 2;
|
||||
}
|
||||
break;
|
||||
case XML_BUFFER_ALLOC_EXACT:
|
||||
newSize = size + 10;
|
||||
break;
|
||||
case XML_BUFFER_ALLOC_HYBRID:
|
||||
if (buf->use < BASE_BUFFER_SIZE)
|
||||
newSize = size;
|
||||
else {
|
||||
newSize = buf->size;
|
||||
while (size > newSize) {
|
||||
if (newSize > UINT_MAX / 2)
|
||||
return 0;
|
||||
newSize *= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
newSize = size + 10;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
buf->contentIO = rebuf;
|
||||
buf->content = rebuf + start_buf;
|
||||
}
|
||||
} else {
|
||||
if (buf->content == NULL) {
|
||||
rebuf = (xmlChar *) xmlMallocAtomic(newSize);
|
||||
buf->use = 0;
|
||||
rebuf[buf->use] = 0;
|
||||
} 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)
|
||||
return 0;
|
||||
buf->content = rebuf;
|
||||
}
|
||||
buf->size = newSize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferAdd:
|
||||
* @buf: the buffer to dump
|
||||
* @str: the #xmlChar string
|
||||
* @len: the number of #xmlChar to add
|
||||
*
|
||||
* Add a string range to an XML buffer. if len == -1, the length of
|
||||
* str is recomputed.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
|
||||
unsigned int needSize;
|
||||
|
||||
if ((str == NULL) || (buf == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (len < -1) {
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) return 0;
|
||||
|
||||
if (len < 0)
|
||||
len = xmlStrlen(str);
|
||||
|
||||
if (len < 0) return -1;
|
||||
if (len == 0) return 0;
|
||||
|
||||
/* Note that both buf->size and buf->use can be zero here. */
|
||||
if ((unsigned) len >= buf->size - buf->use) {
|
||||
if ((unsigned) len >= UINT_MAX - buf->use)
|
||||
return XML_ERR_NO_MEMORY;
|
||||
needSize = buf->use + len + 1;
|
||||
if (!xmlBufferResize(buf, needSize))
|
||||
return XML_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memmove(&buf->content[buf->use], str, len);
|
||||
buf->use += len;
|
||||
buf->content[buf->use] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferAddHead:
|
||||
* @buf: the buffer
|
||||
* @str: the #xmlChar string
|
||||
* @len: the number of #xmlChar to add
|
||||
*
|
||||
* Add a string range to the beginning of an XML buffer.
|
||||
* if len == -1, the length of @str is recomputed.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
|
||||
unsigned int needSize;
|
||||
|
||||
if (buf == NULL)
|
||||
return(-1);
|
||||
if (str == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (len < -1) {
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) return 0;
|
||||
|
||||
if (len < 0)
|
||||
len = xmlStrlen(str);
|
||||
|
||||
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 shrunk
|
||||
*/
|
||||
buf->content -= len;
|
||||
memmove(&buf->content[0], str, len);
|
||||
buf->use += len;
|
||||
buf->size += len;
|
||||
buf->content[buf->use] = 0;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* Note that both buf->size and buf->use can be zero here. */
|
||||
if ((unsigned) len >= buf->size - buf->use) {
|
||||
if ((unsigned) len >= UINT_MAX - buf->use)
|
||||
return(-1);
|
||||
needSize = buf->use + len + 1;
|
||||
if (!xmlBufferResize(buf, needSize))
|
||||
return(-1);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCat:
|
||||
* @buf: the buffer to add to
|
||||
* @str: the #xmlChar string
|
||||
*
|
||||
* Append a zero terminated string to an XML buffer.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
|
||||
if (buf == NULL)
|
||||
return(-1);
|
||||
if (str == NULL) return -1;
|
||||
return xmlBufferAdd(buf, str, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCCat:
|
||||
* @buf: the buffer to dump
|
||||
* @str: the C char string
|
||||
*
|
||||
* Append a zero terminated C string to an XML buffer.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferCCat(xmlBufferPtr buf, const char *str) {
|
||||
return xmlBufferCat(buf, (const xmlChar *) str);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferWriteCHAR:
|
||||
* @buf: the XML buffer
|
||||
* @string: the string to add
|
||||
*
|
||||
* routine which manages and grows an output buffer. This one adds
|
||||
* xmlChars at the end of the buffer.
|
||||
*/
|
||||
void
|
||||
xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
|
||||
if (buf == NULL)
|
||||
return;
|
||||
xmlBufferCat(buf, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferWriteChar:
|
||||
* @buf: the XML buffer output
|
||||
* @string: the string to add
|
||||
*
|
||||
* routine which manage and grows an output buffer. This one add
|
||||
* C chars at the end of the array.
|
||||
*/
|
||||
void
|
||||
xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
|
||||
if (buf == NULL)
|
||||
return;
|
||||
xmlBufferCCat(buf, string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlBufferWriteQuotedString:
|
||||
* @buf: the XML buffer output
|
||||
* @string: the string to add
|
||||
*
|
||||
* routine which manage and grows an output buffer. This one writes
|
||||
* a quoted or double quoted #xmlChar string, checking first if it holds
|
||||
* quote or double-quotes internally
|
||||
*/
|
||||
void
|
||||
xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
|
||||
const xmlChar *cur, *base;
|
||||
if (buf == NULL)
|
||||
return;
|
||||
if (xmlStrchr(string, '\"')) {
|
||||
if (xmlStrchr(string, '\'')) {
|
||||
xmlBufferCCat(buf, "\"");
|
||||
base = cur = string;
|
||||
while(*cur != 0){
|
||||
if(*cur == '"'){
|
||||
if (base != cur)
|
||||
xmlBufferAdd(buf, base, cur - base);
|
||||
xmlBufferAdd(buf, BAD_CAST """, 6);
|
||||
cur++;
|
||||
base = cur;
|
||||
}
|
||||
else {
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
if (base != cur)
|
||||
xmlBufferAdd(buf, base, cur - base);
|
||||
xmlBufferCCat(buf, "\"");
|
||||
}
|
||||
else{
|
||||
xmlBufferCCat(buf, "\'");
|
||||
xmlBufferCat(buf, string);
|
||||
xmlBufferCCat(buf, "\'");
|
||||
}
|
||||
} else {
|
||||
xmlBufferCCat(buf, "\"");
|
||||
xmlBufferCat(buf, string);
|
||||
xmlBufferCCat(buf, "\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
679
tree.c
679
tree.c
@ -666,41 +666,6 @@ try_complex:
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* xmlSetBufferAllocationScheme:
|
||||
* @scheme: allocation method to use
|
||||
*
|
||||
* Set the buffer allocation method. Types are
|
||||
* XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
|
||||
* XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
|
||||
* improves performance
|
||||
*/
|
||||
void
|
||||
xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
|
||||
if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_HYBRID))
|
||||
xmlBufferAllocScheme = scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlGetBufferAllocationScheme:
|
||||
*
|
||||
* Types are
|
||||
* XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
|
||||
* XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
|
||||
* improves performance
|
||||
* XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
|
||||
* in normal usage, and doubleit on large strings to avoid
|
||||
* pathological performance.
|
||||
*
|
||||
* Returns the current allocation scheme
|
||||
*/
|
||||
xmlBufferAllocationScheme
|
||||
xmlGetBufferAllocationScheme(void) {
|
||||
return(xmlBufferAllocScheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewNs:
|
||||
* @node: the element carrying the namespace (optional)
|
||||
@ -7018,650 +6983,6 @@ xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
|
||||
return(xmlTextAddContent(node, content, len));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Output : to a FILE or in memory *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* xmlBufferCreate:
|
||||
*
|
||||
* routine to create an XML buffer.
|
||||
* returns the new structure.
|
||||
*/
|
||||
xmlBufferPtr
|
||||
xmlBufferCreate(void) {
|
||||
xmlBufferPtr ret;
|
||||
|
||||
ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
ret->use = 0;
|
||||
ret->size = xmlDefaultBufferSize;
|
||||
ret->alloc = xmlBufferAllocScheme;
|
||||
ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
|
||||
if (ret->content == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->content[0] = 0;
|
||||
ret->contentIO = NULL;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCreateSize:
|
||||
* @size: initial size of buffer
|
||||
*
|
||||
* routine to create an XML buffer.
|
||||
* returns the new structure.
|
||||
*/
|
||||
xmlBufferPtr
|
||||
xmlBufferCreateSize(size_t size) {
|
||||
xmlBufferPtr ret;
|
||||
|
||||
if (size >= UINT_MAX)
|
||||
return(NULL);
|
||||
ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
ret->use = 0;
|
||||
ret->alloc = xmlBufferAllocScheme;
|
||||
ret->size = (size ? size + 1 : 0); /* +1 for ending null */
|
||||
if (ret->size){
|
||||
ret->content = (xmlChar *) xmlMallocAtomic(ret->size);
|
||||
if (ret->content == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->content[0] = 0;
|
||||
} else
|
||||
ret->content = NULL;
|
||||
ret->contentIO = NULL;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferDetach:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* Remove the string contained in a buffer and gie it back to the
|
||||
* caller. The buffer is reset to an empty content.
|
||||
* This doesn't work with immutable buffers as they can't be reset.
|
||||
*
|
||||
* Returns the previous string contained by the buffer.
|
||||
*/
|
||||
xmlChar *
|
||||
xmlBufferDetach(xmlBufferPtr buf) {
|
||||
xmlChar *ret;
|
||||
|
||||
if (buf == NULL)
|
||||
return(NULL);
|
||||
|
||||
ret = buf->content;
|
||||
buf->content = NULL;
|
||||
buf->size = 0;
|
||||
buf->use = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlBufferCreateStatic:
|
||||
* @mem: the memory area
|
||||
* @size: the size in byte
|
||||
*
|
||||
* Returns an XML buffer initialized with bytes.
|
||||
*/
|
||||
xmlBufferPtr
|
||||
xmlBufferCreateStatic(void *mem, size_t size) {
|
||||
xmlBufferPtr buf = xmlBufferCreateSize(size);
|
||||
|
||||
xmlBufferAdd(buf, mem, size);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferSetAllocationScheme:
|
||||
* @buf: the buffer to tune
|
||||
* @scheme: allocation scheme to use
|
||||
*
|
||||
* Sets the allocation scheme for this buffer
|
||||
*/
|
||||
void
|
||||
xmlBufferSetAllocationScheme(xmlBufferPtr buf,
|
||||
xmlBufferAllocationScheme scheme) {
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
if (buf->alloc == XML_BUFFER_ALLOC_IO) return;
|
||||
if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_EXACT) ||
|
||||
(scheme == XML_BUFFER_ALLOC_HYBRID))
|
||||
buf->alloc = scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferFree:
|
||||
* @buf: the buffer to free
|
||||
*
|
||||
* Frees an XML buffer. It frees both the content and the structure which
|
||||
* encapsulate it.
|
||||
*/
|
||||
void
|
||||
xmlBufferFree(xmlBufferPtr buf) {
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
|
||||
(buf->contentIO != NULL)) {
|
||||
xmlFree(buf->contentIO);
|
||||
} else if (buf->content != NULL) {
|
||||
xmlFree(buf->content);
|
||||
}
|
||||
xmlFree(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferEmpty:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* empty a buffer.
|
||||
*/
|
||||
void
|
||||
xmlBufferEmpty(xmlBufferPtr buf) {
|
||||
if (buf == NULL) return;
|
||||
if (buf->content == NULL) return;
|
||||
buf->use = 0;
|
||||
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 {
|
||||
buf->content[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferShrink:
|
||||
* @buf: the buffer to dump
|
||||
* @len: the number of xmlChar to remove
|
||||
*
|
||||
* Remove the beginning of an XML buffer.
|
||||
*
|
||||
* Returns the number of #xmlChar removed, or -1 in case of failure.
|
||||
*/
|
||||
int
|
||||
xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
|
||||
if (buf == NULL) return(-1);
|
||||
if (len == 0) return(0);
|
||||
if (len > buf->use) return(-1);
|
||||
|
||||
buf->use -= len;
|
||||
if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
|
||||
/*
|
||||
* we just move the content pointer, but also make sure
|
||||
* the perceived buffer size has shrunk 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);
|
||||
buf->content[buf->use] = 0;
|
||||
}
|
||||
return(len);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferGrow:
|
||||
* @buf: the buffer
|
||||
* @len: the minimum free size to allocate
|
||||
*
|
||||
* Grow the available space of an XML buffer.
|
||||
*
|
||||
* Returns the new available space or -1 in case of error
|
||||
*/
|
||||
int
|
||||
xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
|
||||
unsigned int size;
|
||||
xmlChar *newbuf;
|
||||
|
||||
if (buf == NULL) return(-1);
|
||||
|
||||
if (len < buf->size - buf->use)
|
||||
return(0);
|
||||
if (len >= UINT_MAX - buf->use)
|
||||
return(-1);
|
||||
|
||||
if (buf->size > (size_t) len) {
|
||||
size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
|
||||
} else {
|
||||
size = buf->use + len;
|
||||
size = size > UINT_MAX - 100 ? UINT_MAX : size + 100;
|
||||
}
|
||||
|
||||
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)
|
||||
return(-1);
|
||||
buf->contentIO = newbuf;
|
||||
buf->content = newbuf + start_buf;
|
||||
} else {
|
||||
newbuf = (xmlChar *) xmlRealloc(buf->content, size);
|
||||
if (newbuf == NULL)
|
||||
return(-1);
|
||||
buf->content = newbuf;
|
||||
}
|
||||
buf->size = size;
|
||||
return(buf->size - buf->use - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferDump:
|
||||
* @file: the file output
|
||||
* @buf: the buffer to dump
|
||||
*
|
||||
* Dumps an XML buffer to a FILE *.
|
||||
* Returns the number of #xmlChar written
|
||||
*/
|
||||
int
|
||||
xmlBufferDump(FILE *file, xmlBufferPtr buf) {
|
||||
size_t ret;
|
||||
|
||||
if (buf == NULL) {
|
||||
return(0);
|
||||
}
|
||||
if (buf->content == NULL) {
|
||||
return(0);
|
||||
}
|
||||
if (file == NULL)
|
||||
file = stdout;
|
||||
ret = fwrite(buf->content, 1, buf->use, file);
|
||||
return(ret > INT_MAX ? INT_MAX : ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferContent:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* Function to extract the content of a buffer
|
||||
*
|
||||
* Returns the internal content
|
||||
*/
|
||||
|
||||
const xmlChar *
|
||||
xmlBufferContent(const xmlBuffer *buf)
|
||||
{
|
||||
if(!buf)
|
||||
return NULL;
|
||||
|
||||
return buf->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferLength:
|
||||
* @buf: the buffer
|
||||
*
|
||||
* Function to get the length of a buffer
|
||||
*
|
||||
* Returns the length of data in the internal content
|
||||
*/
|
||||
|
||||
int
|
||||
xmlBufferLength(const xmlBuffer *buf)
|
||||
{
|
||||
if(!buf)
|
||||
return 0;
|
||||
|
||||
return buf->use;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferResize:
|
||||
* @buf: the buffer to resize
|
||||
* @size: the desired size
|
||||
*
|
||||
* Resize a buffer to accommodate minimum size of @size.
|
||||
*
|
||||
* Returns 0 in case of problems, 1 otherwise
|
||||
*/
|
||||
int
|
||||
xmlBufferResize(xmlBufferPtr buf, unsigned int size)
|
||||
{
|
||||
unsigned int newSize;
|
||||
xmlChar* rebuf = NULL;
|
||||
size_t start_buf;
|
||||
|
||||
if (buf == NULL)
|
||||
return(0);
|
||||
|
||||
/* Don't resize if we don't have to */
|
||||
if (size < buf->size)
|
||||
return 1;
|
||||
|
||||
if (size > UINT_MAX - 10)
|
||||
return 0;
|
||||
|
||||
/* figure out new size */
|
||||
switch (buf->alloc){
|
||||
case XML_BUFFER_ALLOC_IO:
|
||||
case XML_BUFFER_ALLOC_DOUBLEIT:
|
||||
/*take care of empty case*/
|
||||
if (buf->size == 0)
|
||||
newSize = size + 10;
|
||||
else
|
||||
newSize = buf->size;
|
||||
while (size > newSize) {
|
||||
if (newSize > UINT_MAX / 2)
|
||||
return 0;
|
||||
newSize *= 2;
|
||||
}
|
||||
break;
|
||||
case XML_BUFFER_ALLOC_EXACT:
|
||||
newSize = size + 10;
|
||||
break;
|
||||
case XML_BUFFER_ALLOC_HYBRID:
|
||||
if (buf->use < BASE_BUFFER_SIZE)
|
||||
newSize = size;
|
||||
else {
|
||||
newSize = buf->size;
|
||||
while (size > newSize) {
|
||||
if (newSize > UINT_MAX / 2)
|
||||
return 0;
|
||||
newSize *= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
newSize = size + 10;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
buf->contentIO = rebuf;
|
||||
buf->content = rebuf + start_buf;
|
||||
}
|
||||
} else {
|
||||
if (buf->content == NULL) {
|
||||
rebuf = (xmlChar *) xmlMallocAtomic(newSize);
|
||||
buf->use = 0;
|
||||
rebuf[buf->use] = 0;
|
||||
} 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)
|
||||
return 0;
|
||||
buf->content = rebuf;
|
||||
}
|
||||
buf->size = newSize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferAdd:
|
||||
* @buf: the buffer to dump
|
||||
* @str: the #xmlChar string
|
||||
* @len: the number of #xmlChar to add
|
||||
*
|
||||
* Add a string range to an XML buffer. if len == -1, the length of
|
||||
* str is recomputed.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
|
||||
unsigned int needSize;
|
||||
|
||||
if ((str == NULL) || (buf == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (len < -1) {
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) return 0;
|
||||
|
||||
if (len < 0)
|
||||
len = xmlStrlen(str);
|
||||
|
||||
if (len < 0) return -1;
|
||||
if (len == 0) return 0;
|
||||
|
||||
/* Note that both buf->size and buf->use can be zero here. */
|
||||
if ((unsigned) len >= buf->size - buf->use) {
|
||||
if ((unsigned) len >= UINT_MAX - buf->use)
|
||||
return XML_ERR_NO_MEMORY;
|
||||
needSize = buf->use + len + 1;
|
||||
if (!xmlBufferResize(buf, needSize))
|
||||
return XML_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memmove(&buf->content[buf->use], str, len);
|
||||
buf->use += len;
|
||||
buf->content[buf->use] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferAddHead:
|
||||
* @buf: the buffer
|
||||
* @str: the #xmlChar string
|
||||
* @len: the number of #xmlChar to add
|
||||
*
|
||||
* Add a string range to the beginning of an XML buffer.
|
||||
* if len == -1, the length of @str is recomputed.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
|
||||
unsigned int needSize;
|
||||
|
||||
if (buf == NULL)
|
||||
return(-1);
|
||||
if (str == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (len < -1) {
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) return 0;
|
||||
|
||||
if (len < 0)
|
||||
len = xmlStrlen(str);
|
||||
|
||||
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 shrunk
|
||||
*/
|
||||
buf->content -= len;
|
||||
memmove(&buf->content[0], str, len);
|
||||
buf->use += len;
|
||||
buf->size += len;
|
||||
buf->content[buf->use] = 0;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
/* Note that both buf->size and buf->use can be zero here. */
|
||||
if ((unsigned) len >= buf->size - buf->use) {
|
||||
if ((unsigned) len >= UINT_MAX - buf->use)
|
||||
return(-1);
|
||||
needSize = buf->use + len + 1;
|
||||
if (!xmlBufferResize(buf, needSize))
|
||||
return(-1);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCat:
|
||||
* @buf: the buffer to add to
|
||||
* @str: the #xmlChar string
|
||||
*
|
||||
* Append a zero terminated string to an XML buffer.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
|
||||
if (buf == NULL)
|
||||
return(-1);
|
||||
if (str == NULL) return -1;
|
||||
return xmlBufferAdd(buf, str, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferCCat:
|
||||
* @buf: the buffer to dump
|
||||
* @str: the C char string
|
||||
*
|
||||
* Append a zero terminated C string to an XML buffer.
|
||||
*
|
||||
* Returns 0 successful, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlBufferCCat(xmlBufferPtr buf, const char *str) {
|
||||
return xmlBufferCat(buf, (const xmlChar *) str);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferWriteCHAR:
|
||||
* @buf: the XML buffer
|
||||
* @string: the string to add
|
||||
*
|
||||
* routine which manages and grows an output buffer. This one adds
|
||||
* xmlChars at the end of the buffer.
|
||||
*/
|
||||
void
|
||||
xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
|
||||
if (buf == NULL)
|
||||
return;
|
||||
xmlBufferCat(buf, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlBufferWriteChar:
|
||||
* @buf: the XML buffer output
|
||||
* @string: the string to add
|
||||
*
|
||||
* routine which manage and grows an output buffer. This one add
|
||||
* C chars at the end of the array.
|
||||
*/
|
||||
void
|
||||
xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
|
||||
if (buf == NULL)
|
||||
return;
|
||||
xmlBufferCCat(buf, string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlBufferWriteQuotedString:
|
||||
* @buf: the XML buffer output
|
||||
* @string: the string to add
|
||||
*
|
||||
* routine which manage and grows an output buffer. This one writes
|
||||
* a quoted or double quoted #xmlChar string, checking first if it holds
|
||||
* quote or double-quotes internally
|
||||
*/
|
||||
void
|
||||
xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
|
||||
const xmlChar *cur, *base;
|
||||
if (buf == NULL)
|
||||
return;
|
||||
if (xmlStrchr(string, '\"')) {
|
||||
if (xmlStrchr(string, '\'')) {
|
||||
xmlBufferCCat(buf, "\"");
|
||||
base = cur = string;
|
||||
while(*cur != 0){
|
||||
if(*cur == '"'){
|
||||
if (base != cur)
|
||||
xmlBufferAdd(buf, base, cur - base);
|
||||
xmlBufferAdd(buf, BAD_CAST """, 6);
|
||||
cur++;
|
||||
base = cur;
|
||||
}
|
||||
else {
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
if (base != cur)
|
||||
xmlBufferAdd(buf, base, cur - base);
|
||||
xmlBufferCCat(buf, "\"");
|
||||
}
|
||||
else{
|
||||
xmlBufferCCat(buf, "\'");
|
||||
xmlBufferCat(buf, string);
|
||||
xmlBufferCCat(buf, "\'");
|
||||
}
|
||||
} else {
|
||||
xmlBufferCCat(buf, "\"");
|
||||
xmlBufferCat(buf, string);
|
||||
xmlBufferCCat(buf, "\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlGetDocCompressMode:
|
||||
* @doc: the document
|
||||
|
Loading…
x
Reference in New Issue
Block a user