mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-31 06:50:06 +03:00
parser: Optimize memory buffer I/O
Reenable zero-copy IO for zero-terminated static memory buffers. Don't stream zero-terminated dynamic memory buffers on top of creating a copy.
This commit is contained in:
parent
34c9108f15
commit
7148b77820
8
parser.c
8
parser.c
@ -7988,13 +7988,17 @@ xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
|
||||
}
|
||||
|
||||
length = xmlBufUse(input->buf->buffer);
|
||||
content = xmlBufDetach(input->buf->buffer);
|
||||
|
||||
if (length > INT_MAX) {
|
||||
xmlErrMemory(ctxt);
|
||||
goto error;
|
||||
}
|
||||
|
||||
content = xmlStrndup(xmlBufContent(input->buf->buffer), length);
|
||||
if (content == NULL) {
|
||||
xmlErrMemory(ctxt);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; ) {
|
||||
int clen = length - i;
|
||||
int c = xmlGetUTF8Char(content + i, &clen);
|
||||
|
118
xmlIO.c
118
xmlIO.c
@ -1748,7 +1748,6 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *mem;
|
||||
const char *cur;
|
||||
size_t size;
|
||||
} xmlMemIOCtxt;
|
||||
@ -1771,8 +1770,6 @@ static int
|
||||
xmlMemClose(void *vctxt) {
|
||||
xmlMemIOCtxt *ctxt = vctxt;
|
||||
|
||||
if (ctxt->mem != NULL)
|
||||
xmlFree(ctxt->mem);
|
||||
xmlFree(ctxt);
|
||||
return(0);
|
||||
}
|
||||
@ -1792,42 +1789,46 @@ xmlParserInputBufferPtr
|
||||
xmlNewInputBufferMemory(const void *mem, size_t size, int flags,
|
||||
xmlCharEncoding enc) {
|
||||
xmlParserInputBufferPtr ret;
|
||||
xmlMemIOCtxt *ctxt;
|
||||
char *copy = NULL;
|
||||
|
||||
if ((flags & XML_INPUT_BUF_STATIC) == 0) {
|
||||
if (size + 1 == 0)
|
||||
if ((flags & XML_INPUT_BUF_STATIC) &&
|
||||
((flags & XML_INPUT_BUF_ZERO_TERMINATED) == 0)) {
|
||||
xmlMemIOCtxt *ctxt;
|
||||
|
||||
/*
|
||||
* Static buffer without zero terminator.
|
||||
* Stream memory to avoid a copy.
|
||||
*/
|
||||
ret = xmlAllocParserInputBuffer(enc);
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
copy = xmlMalloc(size + 1);
|
||||
if (copy == NULL)
|
||||
|
||||
ctxt = xmlMalloc(sizeof(*ctxt));
|
||||
if (ctxt == NULL) {
|
||||
xmlFreeParserInputBuffer(ret);
|
||||
return(NULL);
|
||||
memcpy(copy, mem, size);
|
||||
copy[size] = 0;
|
||||
}
|
||||
|
||||
mem = copy;
|
||||
ctxt->cur = mem;
|
||||
ctxt->size = size;
|
||||
|
||||
ret->context = ctxt;
|
||||
ret->readcallback = xmlMemRead;
|
||||
ret->closecallback = xmlMemClose;
|
||||
} else {
|
||||
ret = xmlMalloc(sizeof(*ret));
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
memset(ret, 0, sizeof(xmlParserInputBuffer));
|
||||
ret->compressed = -1;
|
||||
|
||||
ret->buffer = xmlBufCreateMem((const xmlChar *) mem, size,
|
||||
(flags & XML_INPUT_BUF_STATIC ? 1 : 0));
|
||||
if (ret->buffer == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ret = xmlAllocParserInputBuffer(enc);
|
||||
if (ret == NULL) {
|
||||
xmlFree(copy);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ctxt = xmlMalloc(sizeof(*ctxt));
|
||||
if (ctxt == NULL) {
|
||||
xmlFreeParserInputBuffer(ret);
|
||||
xmlFree(copy);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ctxt->mem = copy;
|
||||
ctxt->cur = mem;
|
||||
ctxt->size = size;
|
||||
|
||||
ret->context = ctxt;
|
||||
ret->readcallback = xmlMemRead;
|
||||
ret->closecallback = xmlMemClose;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -1889,31 +1890,6 @@ xmlParserInputBufferCreateStatic(const char *mem, int size,
|
||||
return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *str;
|
||||
} xmlStringIOCtxt;
|
||||
|
||||
static int
|
||||
xmlStringRead(void *vctxt, char *buf, int size) {
|
||||
xmlStringIOCtxt *ctxt = vctxt;
|
||||
const char *zero;
|
||||
size_t len;
|
||||
|
||||
zero = memchr(ctxt->str, 0, size);
|
||||
len = zero ? zero - ctxt->str : size;
|
||||
|
||||
memcpy(buf, ctxt->str, len);
|
||||
ctxt->str += len;
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
static int
|
||||
xmlStringClose(void *vctxt) {
|
||||
xmlFree(vctxt);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewInputBufferString:
|
||||
* @str: C string
|
||||
@ -1926,28 +1902,20 @@ xmlStringClose(void *vctxt) {
|
||||
xmlParserInputBufferPtr
|
||||
xmlNewInputBufferString(const char *str, int flags) {
|
||||
xmlParserInputBufferPtr ret;
|
||||
xmlStringIOCtxt *ctxt;
|
||||
|
||||
if ((flags & XML_INPUT_BUF_STATIC) == 0)
|
||||
return(xmlNewInputBufferMemory(str, strlen(str), flags,
|
||||
XML_CHAR_ENCODING_NONE));
|
||||
|
||||
ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
|
||||
ret = xmlMalloc(sizeof(*ret));
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
return(NULL);
|
||||
memset(ret, 0, sizeof(xmlParserInputBuffer));
|
||||
ret->compressed = -1;
|
||||
|
||||
ctxt = xmlMalloc(sizeof(*ctxt));
|
||||
if (ctxt == NULL) {
|
||||
xmlFreeParserInputBuffer(ret);
|
||||
return(NULL);
|
||||
ret->buffer = xmlBufCreateMem((const xmlChar *) str, strlen(str),
|
||||
(flags & XML_INPUT_BUF_STATIC ? 1 : 0));
|
||||
if (ret->buffer == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ctxt->str = str;
|
||||
|
||||
ret->context = ctxt;
|
||||
ret->readcallback = xmlStringRead;
|
||||
ret->closecallback = xmlStringClose;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user