mirror of
https://gitlab.gnome.org/GNOME/libxml2
synced 2025-03-28 21:33:13 +00:00
save: Optimize xmlSerializeText
Use lookup tables.
This commit is contained in:
parent
1b06708271
commit
2adcde3920
@ -210,7 +210,7 @@ DISTCLEANFILES = COPYING missing.lst
|
|||||||
EXTRA_DIST = Copyright libxml2-config.cmake.in autogen.sh \
|
EXTRA_DIST = Copyright libxml2-config.cmake.in autogen.sh \
|
||||||
libxml.h iso8859x.inc \
|
libxml.h iso8859x.inc \
|
||||||
tools/gentest.py \
|
tools/gentest.py \
|
||||||
tools/genChRanges tools/genUnicode.py \
|
tools/genChRanges tools/genEscape.py tools/genUnicode.py \
|
||||||
libxml2.syms timsort.h \
|
libxml2.syms timsort.h \
|
||||||
README.zOS README.md \
|
README.zOS README.md \
|
||||||
CMakeLists.txt config.h.cmake.in libxml2-config.cmake.cmake.in \
|
CMakeLists.txt config.h.cmake.in libxml2-config.cmake.cmake.in \
|
||||||
|
78
tools/genEscape.py
Executable file
78
tools/genEscape.py
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
entities = [
|
||||||
|
[ '', '�' ],
|
||||||
|
[ '\t', '	' ],
|
||||||
|
[ '\n', ' ' ],
|
||||||
|
[ '\r', ' ' ],
|
||||||
|
[ '"', '"' ],
|
||||||
|
[ '&', '&' ],
|
||||||
|
[ '<', '<' ],
|
||||||
|
[ '>', '>' ],
|
||||||
|
]
|
||||||
|
|
||||||
|
### xmlEscapeContent
|
||||||
|
|
||||||
|
offset = [ None ] * 128
|
||||||
|
pos = 0
|
||||||
|
r = ''
|
||||||
|
|
||||||
|
for rec in entities:
|
||||||
|
char, repl = rec
|
||||||
|
|
||||||
|
if char:
|
||||||
|
offset[ord(char)] = pos
|
||||||
|
|
||||||
|
if pos % 12 == 0: r += '\n '
|
||||||
|
else: r += ' '
|
||||||
|
r += '%3d,' % len(repl)
|
||||||
|
pos += 1
|
||||||
|
|
||||||
|
for c in repl:
|
||||||
|
if pos % 12 == 0: r += '\n '
|
||||||
|
else: r += ' '
|
||||||
|
r += "'%s'," % c
|
||||||
|
pos += 1
|
||||||
|
|
||||||
|
print('static const char xmlEscapeContent[] = {%s\n};\n' % r)
|
||||||
|
|
||||||
|
### xmlEscapeTab
|
||||||
|
|
||||||
|
escape = '\r&<>'
|
||||||
|
r = ''
|
||||||
|
|
||||||
|
for i in range(0x80):
|
||||||
|
|
||||||
|
if chr(i) in escape:
|
||||||
|
v = offset[i]
|
||||||
|
elif i != 9 and i != 10 and i < 20:
|
||||||
|
v = 0
|
||||||
|
else:
|
||||||
|
v = -1
|
||||||
|
|
||||||
|
if i % 16 == 0: r += '\n '
|
||||||
|
else: r += ' '
|
||||||
|
r += '%2d,' % v
|
||||||
|
|
||||||
|
print('static const char xmlEscapeTab[128] = {%s\n};\n' % r)
|
||||||
|
|
||||||
|
### xmlEscapeTabAttr
|
||||||
|
|
||||||
|
escape = '\t\n\r"&<>'
|
||||||
|
r = ''
|
||||||
|
|
||||||
|
for i in range(0x80):
|
||||||
|
|
||||||
|
if chr(i) in escape:
|
||||||
|
v = offset[i]
|
||||||
|
elif i != 9 and i != 10 and i < 20:
|
||||||
|
v = 0
|
||||||
|
else:
|
||||||
|
v = -1
|
||||||
|
|
||||||
|
if i % 16 == 0: r += '\n '
|
||||||
|
else: r += ' '
|
||||||
|
r += '%2d,' % v
|
||||||
|
|
||||||
|
print('static const char xmlEscapeTabAttr[128] = {%s\n};\n' % r)
|
||||||
|
|
156
xmlsave.c
156
xmlsave.c
@ -126,100 +126,104 @@ xmlSaveErr(xmlOutputBufferPtr out, int code, xmlNodePtr node,
|
|||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tables generated with tools/genEscape.py
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char xmlEscapeContent[] = {
|
||||||
|
8, '&', '#', 'x', 'F', 'F', 'F', 'D', ';', 4, '&', '#',
|
||||||
|
'9', ';', 5, '&', '#', '1', '0', ';', 5, '&', '#', '1',
|
||||||
|
'3', ';', 6, '&', 'q', 'u', 'o', 't', ';', 5, '&', 'a',
|
||||||
|
'm', 'p', ';', 4, '&', 'l', 't', ';', 4, '&', 'g', 't',
|
||||||
|
';',
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char xmlEscapeTab[128] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 20, 0, 0,
|
||||||
|
0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, 44, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char xmlEscapeTabAttr[128] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 14, 0, 0, 20, 0, 0,
|
||||||
|
0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, 26, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, 44, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xmlSerializeText(xmlOutputBufferPtr buf, const xmlChar *string,
|
xmlSerializeText(xmlOutputBufferPtr buf, const xmlChar *string,
|
||||||
unsigned flags) {
|
unsigned flags) {
|
||||||
const char *base, *cur;
|
const char *cur;
|
||||||
|
const char *tab;
|
||||||
|
|
||||||
if (string == NULL)
|
if (flags & XML_ESCAPE_ATTR)
|
||||||
return;
|
tab = xmlEscapeTabAttr;
|
||||||
|
else
|
||||||
|
tab = xmlEscapeTab;
|
||||||
|
|
||||||
base = cur = (const char *) string;
|
cur = (const char *) string;
|
||||||
|
|
||||||
while (*cur != 0) {
|
while (*cur != 0) {
|
||||||
|
const char *base;
|
||||||
|
int c;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
base = cur;
|
||||||
|
offset = -1;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
c = (unsigned char) *cur;
|
||||||
|
|
||||||
|
if (c < 0x80) {
|
||||||
|
offset = tab[c];
|
||||||
|
if (offset >= 0)
|
||||||
|
break;
|
||||||
|
} else if (flags & XML_ESCAPE_NON_ASCII) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur > base)
|
||||||
|
xmlOutputBufferWrite(buf, cur - base, base);
|
||||||
|
|
||||||
|
if (offset >= 0) {
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
xmlOutputBufferWrite(buf, xmlEscapeContent[offset],
|
||||||
|
&xmlEscapeContent[offset+1]);
|
||||||
|
cur += 1;
|
||||||
|
} else {
|
||||||
char tempBuf[12];
|
char tempBuf[12];
|
||||||
const char *repl = NULL;
|
int tempSize;
|
||||||
int replSize = 0;
|
int val = 0, len = 4;
|
||||||
int chunkSize = 1;
|
|
||||||
int c = (unsigned char) *cur;
|
|
||||||
|
|
||||||
switch (c) {
|
val = xmlGetUTF8Char((const xmlChar *) cur, &len);
|
||||||
case '\t':
|
|
||||||
if (flags & XML_ESCAPE_ATTR) {
|
|
||||||
repl = "	";
|
|
||||||
replSize = 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
if (flags & XML_ESCAPE_ATTR) {
|
|
||||||
repl = " ";
|
|
||||||
replSize = 5;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\r':
|
|
||||||
repl = " ";
|
|
||||||
replSize = 5;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '"':
|
|
||||||
if (flags & XML_ESCAPE_ATTR) {
|
|
||||||
repl = "&#quot;";
|
|
||||||
replSize = 6;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '<':
|
|
||||||
repl = "<";
|
|
||||||
replSize = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '>':
|
|
||||||
repl = ">";
|
|
||||||
replSize = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '&':
|
|
||||||
repl = "&";
|
|
||||||
replSize = 5;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (c < 0x20) {
|
|
||||||
repl = "�";
|
|
||||||
replSize = 8;
|
|
||||||
} else if ((c >= 0x80) && (flags & XML_ESCAPE_NON_ASCII)) {
|
|
||||||
int val = 0, l = 4;
|
|
||||||
|
|
||||||
val = xmlGetUTF8Char((const xmlChar *) cur, &l);
|
|
||||||
if (val < 0) {
|
if (val < 0) {
|
||||||
val = 0xFFFD;
|
val = 0xFFFD;
|
||||||
|
cur += 1;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_CHAR(val))
|
if (!IS_CHAR(val))
|
||||||
val = 0xFFFD;
|
val = 0xFFFD;
|
||||||
chunkSize = l;
|
cur += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
replSize = xmlSerializeHexCharRef(tempBuf, val);
|
tempSize = xmlSerializeHexCharRef(tempBuf, val);
|
||||||
repl = tempBuf;
|
xmlOutputBufferWrite(buf, tempSize, tempBuf);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repl == NULL) {
|
|
||||||
cur++;
|
|
||||||
} else {
|
|
||||||
if (base != cur)
|
|
||||||
xmlOutputBufferWrite(buf, cur - base, base);
|
|
||||||
xmlOutputBufferWrite(buf, replSize, repl);
|
|
||||||
cur += chunkSize;
|
|
||||||
base = cur;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base != cur)
|
|
||||||
xmlOutputBufferWrite(buf, cur - base, base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
Loading…
x
Reference in New Issue
Block a user