mirror of
https://github.com/libexpat/libexpat.git
synced 2025-04-06 13:45:00 +00:00
New approach for handling predefined entities
This commit is contained in:
parent
496af54711
commit
3a10246912
4 changed files with 88 additions and 33 deletions
|
@ -78,7 +78,6 @@ typedef struct {
|
|||
const XML_Char *publicId;
|
||||
const XML_Char *notation;
|
||||
char open;
|
||||
char magic;
|
||||
} ENTITY;
|
||||
|
||||
typedef struct block {
|
||||
|
@ -811,10 +810,19 @@ doContent(XML_Parser parser,
|
|||
return XML_ERROR_PARTIAL_CHAR;
|
||||
case XML_TOK_ENTITY_REF:
|
||||
{
|
||||
const XML_Char *name = poolStoreString(&dtd.pool, enc,
|
||||
s + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar);
|
||||
const XML_Char *name;
|
||||
ENTITY *entity;
|
||||
XML_Char ch = XmlPredefinedEntityName(enc,
|
||||
s + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar);
|
||||
if (ch) {
|
||||
if (characterDataHandler)
|
||||
characterDataHandler(userData, &ch, 1);
|
||||
break;
|
||||
}
|
||||
name = poolStoreString(&dtd.pool, enc,
|
||||
s + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar);
|
||||
if (!name)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
|
||||
|
@ -826,11 +834,6 @@ doContent(XML_Parser parser,
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (entity->magic) {
|
||||
if (characterDataHandler)
|
||||
characterDataHandler(userData, entity->textPtr, entity->textLen);
|
||||
break;
|
||||
}
|
||||
if (entity->open) {
|
||||
errorPtr = s;
|
||||
return XML_ERROR_RECURSIVE_ENTITY_REF;
|
||||
|
@ -1438,7 +1441,12 @@ prologProcessor(XML_Parser parser,
|
|||
break;
|
||||
case XML_ROLE_GENERAL_ENTITY_NAME:
|
||||
{
|
||||
const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next);
|
||||
const XML_Char *name;
|
||||
if (XmlPredefinedEntityName(encoding, s, next)) {
|
||||
declEntity = 0;
|
||||
break;
|
||||
}
|
||||
name = poolStoreString(&dtd.pool, encoding, s, next);
|
||||
if (!name)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
if (dtd.complete) {
|
||||
|
@ -1694,10 +1702,19 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
|
|||
break;
|
||||
case XML_TOK_ENTITY_REF:
|
||||
{
|
||||
const XML_Char *name = poolStoreString(&temp2Pool, enc,
|
||||
ptr + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar);
|
||||
const XML_Char *name;
|
||||
ENTITY *entity;
|
||||
XML_Char ch = XmlPredefinedEntityName(enc,
|
||||
ptr + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar);
|
||||
if (ch) {
|
||||
if (!poolAppendChar(pool, ch))
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
name = poolStoreString(&temp2Pool, enc,
|
||||
ptr + enc->minBytesPerChar,
|
||||
next - enc->minBytesPerChar);
|
||||
if (!name)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
|
||||
|
@ -1716,12 +1733,6 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
|
|||
errorPtr = ptr;
|
||||
return XML_ERROR_BINARY_ENTITY_REF;
|
||||
}
|
||||
else if (entity->magic) {
|
||||
int i;
|
||||
for (i = 0; i < entity->textLen; i++)
|
||||
if (!poolAppendChar(pool, entity->textPtr[i]))
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
else if (!entity->textPtr) {
|
||||
errorPtr = ptr;
|
||||
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
|
||||
|
@ -1986,20 +1997,8 @@ void normalizePublicId(XML_Char *publicId)
|
|||
|
||||
static int dtdInit(DTD *p)
|
||||
{
|
||||
static const XML_Char *names[] = { XML_T("lt"), XML_T("amp"), XML_T("gt"), XML_T("quot"), XML_T("apos") };
|
||||
static const XML_Char chars[] = { XML_T('<'), XML_T('&'), XML_T('>'), XML_T('"'), XML_T('\'') };
|
||||
int i;
|
||||
|
||||
poolInit(&(p->pool));
|
||||
hashTableInit(&(p->generalEntities));
|
||||
for (i = 0; i < 5; i++) {
|
||||
ENTITY *entity = (ENTITY *)lookup(&(p->generalEntities), names[i], sizeof(ENTITY));
|
||||
if (!entity)
|
||||
return 0;
|
||||
entity->textPtr = chars + i;
|
||||
entity->textLen = 1;
|
||||
entity->magic = 1;
|
||||
}
|
||||
hashTableInit(&(p->elementTypes));
|
||||
hashTableInit(&(p->attributeIds));
|
||||
p->complete = 1;
|
||||
|
@ -2101,8 +2100,6 @@ static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
|
|||
const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
|
||||
if (!oldE)
|
||||
break;
|
||||
if (oldE->magic)
|
||||
continue;
|
||||
name = poolCopyString(&(newDtd->pool), oldE->name);
|
||||
if (!name)
|
||||
return 0;
|
||||
|
|
|
@ -31,6 +31,7 @@ Contributor(s):
|
|||
PREFIX(skipS), \
|
||||
PREFIX(getAtts), \
|
||||
PREFIX(charRefNumber), \
|
||||
PREFIX(predefinedEntityName), \
|
||||
PREFIX(updatePosition), \
|
||||
PREFIX(isPublicId)
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ struct encoding {
|
|||
int (*getAtts)(const ENCODING *enc, const char *ptr,
|
||||
int attsMax, ATTRIBUTE *atts);
|
||||
int (*charRefNumber)(const ENCODING *enc, const char *ptr);
|
||||
int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
|
||||
void (*updatePosition)(const ENCODING *,
|
||||
const char *ptr,
|
||||
const char *end,
|
||||
|
@ -225,6 +226,9 @@ the content of a literal that has already been returned by XmlTok. */
|
|||
#define XmlCharRefNumber(enc, ptr) \
|
||||
(((enc)->charRefNumber)(enc, ptr))
|
||||
|
||||
#define XmlPredefinedEntityName(enc, ptr, end) \
|
||||
(((enc)->predefinedEntityName)(enc, ptr, end))
|
||||
|
||||
#define XmlUpdatePosition(enc, ptr, end, pos) \
|
||||
(((enc)->updatePosition)(enc, ptr, end, pos))
|
||||
|
||||
|
|
|
@ -1424,6 +1424,59 @@ int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
|
|||
return checkCharRefNumber(result);
|
||||
}
|
||||
|
||||
static
|
||||
int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end)
|
||||
{
|
||||
switch (end - ptr) {
|
||||
case 2 * MINBPC:
|
||||
if (CHAR_MATCHES(enc, ptr + MINBPC, 't')) {
|
||||
switch (BYTE_TO_ASCII(enc, ptr)) {
|
||||
case 'l':
|
||||
return '<';
|
||||
case 'g':
|
||||
return '>';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3 * MINBPC:
|
||||
if (CHAR_MATCHES(enc, ptr, 'a')) {
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 'm')) {
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 'p'))
|
||||
return '&';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4 * MINBPC:
|
||||
switch (BYTE_TO_ASCII(enc, ptr)) {
|
||||
case 'q':
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 'u')) {
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 'o')) {
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 't'))
|
||||
return '"';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 'p')) {
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 'o')) {
|
||||
ptr += MINBPC;
|
||||
if (CHAR_MATCHES(enc, ptr, 's'))
|
||||
return '\'';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue