blob: e1ec0af62c346e77738c5e1646eef93bc16c0240 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * entities.c : implementation for the XML entities handking
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
9#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000010#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000011#include <string.h>
12#include "entities.h"
13
14/*
15 * The XML predefined entities.
16 */
17
18struct xmlPredefinedEntityValue {
19 const char *name;
20 const char *value;
21};
22struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
23 { "lt", "<" },
24 { "gt", ">" },
25 { "apos", "'" },
26 { "quot", "\"" },
27 { "amp", "&" }
28};
29
30xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
31
32/*
Daniel Veillard260a68f1998-08-13 03:39:55 +000033 * xmlFreeEntity : clean-up an entity record.
34 */
Daniel Veillard260a68f1998-08-13 03:39:55 +000035void xmlFreeEntity(xmlEntityPtr entity) {
36 if (entity == NULL) return;
37
38 if (entity->name != NULL)
39 free((char *) entity->name);
40 if (entity->ExternalID != NULL)
41 free((char *) entity->ExternalID);
42 if (entity->SystemID != NULL)
43 free((char *) entity->SystemID);
44 if (entity->content != NULL)
45 free((char *) entity->content);
Daniel Veillard011b63c1999-06-02 17:44:04 +000046 if (entity->orig != NULL)
47 free((char *) entity->orig);
Daniel Veillard260a68f1998-08-13 03:39:55 +000048 memset(entity, -1, sizeof(xmlEntity));
49}
50
51/*
Daniel Veillardbe36afe1998-11-27 06:39:50 +000052 * xmlAddEntity : register a new entity for an entities table.
Daniel Veillard260a68f1998-08-13 03:39:55 +000053 *
54 * TODO !!! We should check here that the combination of type
55 * ExternalID and SystemID is valid.
56 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +000057static void
58xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
Daniel Veillard260a68f1998-08-13 03:39:55 +000059 const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
60 int i;
61 xmlEntityPtr cur;
62 int len;
63
64 for (i = 0;i < table->nb_entities;i++) {
65 cur = &table->table[i];
66 if (!xmlStrcmp(cur->name, name)) {
67 /*
68 * The entity is already defined in this Dtd, the spec says to NOT
69 * override it ... Is it worth a Warning ??? !!!
70 */
71 return;
72 }
73 }
74 if (table->nb_entities >= table->max_entities) {
75 /*
76 * need more elements.
77 */
78 table->max_entities *= 2;
79 table->table = (xmlEntityPtr)
80 realloc(table->table, table->max_entities * sizeof(xmlEntity));
81 if (table->table) {
82 perror("realloc failed");
83 exit(1);
84 }
85 }
86 cur = &table->table[table->nb_entities];
87 cur->name = xmlStrdup(name);
88 for (len = 0;name[0] != 0;name++)len++;
89 cur->len = len;
90 cur->type = type;
91 if (ExternalID != NULL)
92 cur->ExternalID = xmlStrdup(ExternalID);
93 else
94 cur->ExternalID = NULL;
95 if (SystemID != NULL)
96 cur->SystemID = xmlStrdup(SystemID);
97 else
98 cur->SystemID = NULL;
99 if (content != NULL)
100 cur->content = xmlStrdup(content);
101 else
102 cur->content = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000103 cur->orig = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000104 table->nb_entities++;
105}
106
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000107/**
108 * xmlInitializePredefinedEntities:
109 *
110 * Set up the predefined entities.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000111 */
112void xmlInitializePredefinedEntities(void) {
113 int i;
114 CHAR name[50];
115 CHAR value[50];
116 const char *in;
117 CHAR *out;
118
119 if (xmlPredefinedEntities != NULL) return;
120
121 xmlPredefinedEntities = xmlCreateEntitiesTable();
122 for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
123 sizeof(xmlPredefinedEntityValues[0]);i++) {
124 in = xmlPredefinedEntityValues[i].name;
125 out = &name[0];
126 for (;(*out++ = (CHAR) *in);)in++;
127 in = xmlPredefinedEntityValues[i].value;
128 out = &value[0];
129 for (;(*out++ = (CHAR) *in);)in++;
130 xmlAddEntity(xmlPredefinedEntities, (const CHAR *) &name[0],
Daniel Veillard25940b71998-10-29 05:51:30 +0000131 XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000132 &value[0]);
133 }
134}
135
Daniel Veillardccb09631998-10-27 06:21:04 +0000136/**
137 * xmlGetPredefinedEntity:
138 * @name: the entity name
139 *
140 * Check whether this name is an predefined entity.
141 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000142 * Returns NULL if not, othervise the entity
Daniel Veillardccb09631998-10-27 06:21:04 +0000143 */
144xmlEntityPtr
145xmlGetPredefinedEntity(const CHAR *name) {
146 int i;
147 xmlEntityPtr cur;
148
149 if (xmlPredefinedEntities == NULL)
150 xmlInitializePredefinedEntities();
151 for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
152 cur = &xmlPredefinedEntities->table[i];
153 if (!xmlStrcmp(cur->name, name)) return(cur);
154 }
155 return(NULL);
156}
157
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000158/**
159 * xmlAddDtdEntity:
160 * @doc: the document
161 * @name: the entity name
162 * @type: the entity type XML_xxx_yyy_ENTITY
163 * @ExternalID: the entity external ID if available
164 * @SystemID: the entity system ID if available
165 * @content: the entity content
166 *
167 * Register a new entity for this document DTD.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000168 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000169void
170xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000171 const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
172 xmlEntitiesTablePtr table;
173
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000174 if (doc->extSubset == NULL) {
175 fprintf(stderr,
176 "xmlAddDtdEntity: document without external subset !\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000177 return;
178 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000179 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000180 if (table == NULL) {
181 table = xmlCreateEntitiesTable();
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000182 doc->extSubset->entities = table;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000183 }
184 xmlAddEntity(table, name, type, ExternalID, SystemID, content);
185}
186
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000187/**
188 * xmlAddDocEntity:
189 * @doc: the document
190 * @name: the entity name
191 * @type: the entity type XML_xxx_yyy_ENTITY
192 * @ExternalID: the entity external ID if available
193 * @SystemID: the entity system ID if available
194 * @content: the entity content
195 *
196 * Register a new entity for this document.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000197 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000198void
199xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000200 const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
201 xmlEntitiesTablePtr table;
202
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000203 if (doc == NULL) {
204 fprintf(stderr,
205 "xmlAddDocEntity: document is NULL !\n");
206 return;
207 }
208 if (doc->intSubset == NULL) {
209 fprintf(stderr,
210 "xmlAddDtdEntity: document without internal subset !\n");
211 return;
212 }
213 table = (xmlEntitiesTablePtr) doc->intSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000214 if (table == NULL) {
215 table = xmlCreateEntitiesTable();
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000216 doc->intSubset->entities = table;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000217 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000218 xmlAddEntity(table, name, type, ExternalID, SystemID, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000219}
220
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000221/**
222 * xmlGetDtdEntity:
223 * @doc: the document referencing the entity
224 * @name: the entity name
225 *
226 * Do an entity lookup in the Dtd entity hash table and
227 * returns the corresponding entity, if found.
228 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000229 * Returns A pointer to the entity structure or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000230 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000231xmlEntityPtr
232xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000233 int i;
234 xmlEntityPtr cur;
235 xmlEntitiesTablePtr table;
236
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000237 if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
238 table = (xmlEntitiesTablePtr) doc->extSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000239 for (i = 0;i < table->nb_entities;i++) {
240 cur = &table->table[i];
241 if (!xmlStrcmp(cur->name, name)) return(cur);
242 }
243 }
244 return(NULL);
245}
246
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000247/**
248 * xmlGetDocEntity:
249 * @doc: the document referencing the entity
250 * @name: the entity name
251 *
252 * Do an entity lookup in the document entity hash table and
253 * returns the corrsponding entity, otherwise a lookup is done
254 * in the predefined entities too.
255 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000256 * Returns A pointer to the entity structure or NULL if not found.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000257 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000258xmlEntityPtr
259xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000260 int i;
261 xmlEntityPtr cur;
262 xmlEntitiesTablePtr table;
263
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000264 if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
265 table = (xmlEntitiesTablePtr) doc->intSubset->entities;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000266 for (i = 0;i < table->nb_entities;i++) {
267 cur = &table->table[i];
268 if (!xmlStrcmp(cur->name, name)) return(cur);
269 }
270 }
271 if (xmlPredefinedEntities == NULL)
272 xmlInitializePredefinedEntities();
273 table = xmlPredefinedEntities;
274 for (i = 0;i < table->nb_entities;i++) {
275 cur = &table->table[i];
276 if (!xmlStrcmp(cur->name, name)) return(cur);
277 }
278
279 return(NULL);
280}
281
282/*
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000283 * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
284 * | [#x10000-#x10FFFF]
285 * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
286 */
287#define IS_CHAR(c) \
288 (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
289 (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
290
Daniel Veillard14fff061999-06-22 21:49:07 +0000291/*
292 * A buffer used for converting entities to their equivalent and back.
293 *
294 * TODO: remove this, this helps performances but forbid reentrancy in a
295 * stupid way.
296 */
297static int buffer_size = 0;
298static CHAR *buffer = NULL;
299
300void growBuffer(void) {
301 buffer_size *= 2;
302 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
303 if (buffer == NULL) {
304 perror("realloc failed");
305 exit(1);
306 }
307}
308
309
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000310/**
311 * xmlEncodeEntities:
312 * @doc: the document containing the string
313 * @input: A string to convert to XML.
314 *
315 * Do a global encoding of a string, replacing the predefined entities
316 * and non ASCII values with their entities and CharRef counterparts.
317 *
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000318 * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
319 * get erroneous.
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000320 *
Daniel Veillard14fff061999-06-22 21:49:07 +0000321 * TODO This routine is not reentrant, the interface
322 * should not be modified though.
323 *
324 * People must migrate their code to xmlEncodeEntitiesReentrant !
325 *
326 * Returns A newly allocated string with the substitution done.
327 */
328const CHAR *
329xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
330 const CHAR *cur = input;
331 CHAR *out = buffer;
332
333 if (input == NULL) return(NULL);
334 if (buffer == NULL) {
335 buffer_size = 1000;
336 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
337 if (buffer == NULL) {
338 perror("malloc failed");
339 exit(1);
340 }
341 out = buffer;
342 }
343 while (*cur != '\0') {
344 if (out - buffer > buffer_size - 100) {
345 int index = out - buffer;
346
347 growBuffer();
348 out = &buffer[index];
349 }
350
351 /*
352 * By default one have to encode at least '<', '>', '"' and '&' !
353 */
354 if (*cur == '<') {
355 *out++ = '&';
356 *out++ = 'l';
357 *out++ = 't';
358 *out++ = ';';
359 } else if (*cur == '>') {
360 *out++ = '&';
361 *out++ = 'g';
362 *out++ = 't';
363 *out++ = ';';
364 } else if (*cur == '&') {
365 *out++ = '&';
366 *out++ = 'a';
367 *out++ = 'm';
368 *out++ = 'p';
369 *out++ = ';';
370 } else if (*cur == '"') {
371 *out++ = '&';
372 *out++ = 'q';
373 *out++ = 'u';
374 *out++ = 'o';
375 *out++ = 't';
376 *out++ = ';';
377 } else if (*cur == '\'') {
378 *out++ = '&';
379 *out++ = 'a';
380 *out++ = 'p';
381 *out++ = 'o';
382 *out++ = 's';
383 *out++ = ';';
384 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
385 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
386 /*
387 * default case, just copy !
388 */
389 *out++ = *cur;
390#ifndef USE_UTF_8
391 } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
392 char buf[10], *ptr;
393#ifdef HAVE_SNPRINTF
394 snprintf(buf, 9, "&#%d;", *cur);
395#else
396 sprintf(buf, "&#%d;", *cur);
397#endif
398 ptr = buf;
399 while (*ptr != 0) *out++ = *ptr++;
400#endif
401 } else if (IS_CHAR(*cur)) {
402 char buf[10], *ptr;
403
404#ifdef HAVE_SNPRINTF
405 snprintf(buf, 9, "&#%d;", *cur);
406#else
407 sprintf(buf, "&#%d;", *cur);
408#endif
409 ptr = buf;
410 while (*ptr != 0) *out++ = *ptr++;
411 }
412#if 0
413 else {
414 /*
415 * default case, this is not a valid char !
416 * Skip it...
417 */
418 fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
419 }
420#endif
421 cur++;
422 }
423 *out++ = 0;
424 return(buffer);
425}
426
427/*
428 * Macro used to grow the current buffer.
429 */
430#define growBufferReentrant() { \
431 buffer_size *= 2; \
432 buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR)); \
433 if (buffer == NULL) { \
434 perror("realloc failed"); \
435 exit(1); \
436 } \
437}
438
439
440/**
441 * xmlEncodeEntitiesReentrant:
442 * @doc: the document containing the string
443 * @input: A string to convert to XML.
444 *
445 * Do a global encoding of a string, replacing the predefined entities
446 * and non ASCII values with their entities and CharRef counterparts.
447 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
448 * must be deallocated.
449 *
450 * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
451 * get erroneous.
452 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000453 * Returns A newly allocated string with the substitution done.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000454 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000455CHAR *
Daniel Veillard14fff061999-06-22 21:49:07 +0000456xmlEncodeEntitiesReentrant(xmlDocPtr doc, const CHAR *input) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000457 const CHAR *cur = input;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000458 CHAR *buffer = NULL;
459 CHAR *out = NULL;
460 int buffer_size = 0;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000461
Daniel Veillard242590e1998-11-13 18:04:35 +0000462 if (input == NULL) return(NULL);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000463
464 /*
465 * allocate an translation buffer.
466 */
467 buffer_size = 1000;
468 buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000469 if (buffer == NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000470 perror("malloc failed");
471 exit(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000472 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000473 out = buffer;
474
Daniel Veillard260a68f1998-08-13 03:39:55 +0000475 while (*cur != '\0') {
476 if (out - buffer > buffer_size - 100) {
477 int index = out - buffer;
478
Daniel Veillard14fff061999-06-22 21:49:07 +0000479 growBufferReentrant();
Daniel Veillard260a68f1998-08-13 03:39:55 +0000480 out = &buffer[index];
481 }
482
483 /*
484 * By default one have to encode at least '<', '>', '"' and '&' !
Daniel Veillard260a68f1998-08-13 03:39:55 +0000485 */
486 if (*cur == '<') {
487 *out++ = '&';
488 *out++ = 'l';
489 *out++ = 't';
490 *out++ = ';';
491 } else if (*cur == '>') {
492 *out++ = '&';
493 *out++ = 'g';
494 *out++ = 't';
495 *out++ = ';';
496 } else if (*cur == '&') {
497 *out++ = '&';
498 *out++ = 'a';
499 *out++ = 'm';
500 *out++ = 'p';
501 *out++ = ';';
502 } else if (*cur == '"') {
503 *out++ = '&';
504 *out++ = 'q';
505 *out++ = 'u';
506 *out++ = 'o';
507 *out++ = 't';
508 *out++ = ';';
509 } else if (*cur == '\'') {
510 *out++ = '&';
511 *out++ = 'a';
512 *out++ = 'p';
513 *out++ = 'o';
514 *out++ = 's';
515 *out++ = ';';
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000516 } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
517 (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
518 /*
519 * default case, just copy !
520 */
521 *out++ = *cur;
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000522#ifndef USE_UTF_8
523 } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
524 char buf[10], *ptr;
Daniel Veillardda4d3c41998-11-04 20:07:05 +0000525#ifdef HAVE_SNPRINTF
526 snprintf(buf, 9, "&#%d;", *cur);
527#else
528 sprintf(buf, "&#%d;", *cur);
529#endif
Daniel Veillard0ba4d531998-11-01 19:34:31 +0000530 ptr = buf;
531 while (*ptr != 0) *out++ = *ptr++;
532#endif
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000533 } else if (IS_CHAR(*cur)) {
534 char buf[10], *ptr;
535
536#ifdef HAVE_SNPRINTF
537 snprintf(buf, 9, "&#%d;", *cur);
538#else
539 sprintf(buf, "&#%d;", *cur);
540#endif
541 ptr = buf;
542 while (*ptr != 0) *out++ = *ptr++;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000543 }
Daniel Veillard8cc0d1f1998-11-16 01:04:26 +0000544#if 0
545 else {
546 /*
547 * default case, this is not a valid char !
548 * Skip it...
549 */
550 fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
551 }
552#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000553 cur++;
554 }
555 *out++ = 0;
556 return(buffer);
557}
558
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000559/**
560 * xmlCreateEntitiesTable:
561 *
562 * create and initialize an empty entities hash table.
563 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000564 * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000565 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000566xmlEntitiesTablePtr
567xmlCreateEntitiesTable(void) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000568 xmlEntitiesTablePtr ret;
569
570 ret = (xmlEntitiesTablePtr)
571 malloc(sizeof(xmlEntitiesTable));
572 if (ret == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +0000573 fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
574 (long)sizeof(xmlEntitiesTable));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000575 return(NULL);
576 }
577 ret->max_entities = XML_MIN_ENTITIES_TABLE;
578 ret->nb_entities = 0;
579 ret->table = (xmlEntityPtr )
580 malloc(ret->max_entities * sizeof(xmlEntity));
581 if (ret == NULL) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +0000582 fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
583 ret->max_entities * (long)sizeof(xmlEntity));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000584 free(ret);
585 return(NULL);
586 }
587 return(ret);
588}
589
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000590/**
591 * xmlFreeEntitiesTable:
592 * @table: An entity table
593 *
594 * Deallocate the memory used by an entities hash table.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000595 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000596void
597xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000598 int i;
599
600 if (table == NULL) return;
601
602 for (i = 0;i < table->nb_entities;i++) {
603 xmlFreeEntity(&table->table[i]);
604 }
605 free(table->table);
606 free(table);
607}
608
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000609/**
610 * xmlCopyEntitiesTable:
611 * @table: An entity table
612 *
613 * Build a copy of an entity table.
614 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000615 * Returns the new xmlEntitiesTablePtr or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000616 */
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000617xmlEntitiesTablePtr
618xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
619 xmlEntitiesTablePtr ret;
620 xmlEntityPtr cur, ent;
621 int i;
622
623 ret = (xmlEntitiesTablePtr) malloc(sizeof(xmlEntitiesTable));
624 if (ret == NULL) {
625 fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
626 return(NULL);
627 }
628 ret->table = (xmlEntityPtr) malloc(table->max_entities *
629 sizeof(xmlEntity));
630 if (ret->table == NULL) {
631 fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
632 free(ret);
633 return(NULL);
634 }
635 ret->max_entities = table->max_entities;
636 ret->nb_entities = table->nb_entities;
637 for (i = 0;i < ret->nb_entities;i++) {
638 cur = &ret->table[i];
639 ent = &table->table[i];
640 cur->len = ent->len;
641 cur->type = ent->type;
642 if (ent->name != NULL)
643 cur->name = xmlStrdup(ent->name);
644 else
645 cur->name = NULL;
646 if (ent->ExternalID != NULL)
647 cur->ExternalID = xmlStrdup(ent->ExternalID);
648 else
649 cur->ExternalID = NULL;
650 if (ent->SystemID != NULL)
651 cur->SystemID = xmlStrdup(ent->SystemID);
652 else
653 cur->SystemID = NULL;
654 if (ent->content != NULL)
655 cur->content = xmlStrdup(ent->content);
656 else
657 cur->content = NULL;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000658 if (ent->orig != NULL)
659 cur->orig = xmlStrdup(ent->orig);
660 else
661 cur->orig = NULL;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000662 }
663 return(ret);
664}
665
666/**
667 * xmlDumpEntitiesTable:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000668 * @buf: An XML buffer.
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000669 * @table: An entity table
670 *
671 * This will dump the content of the entity table as an XML DTD definition
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000672 */
673void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000674xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000675 int i;
676 xmlEntityPtr cur;
677
678 if (table == NULL) return;
679
680 for (i = 0;i < table->nb_entities;i++) {
681 cur = &table->table[i];
682 switch (cur->type) {
683 case XML_INTERNAL_GENERAL_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000684 xmlBufferWriteChar(buf, "<!ENTITY ");
685 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000686 xmlBufferWriteChar(buf, " ");
687 if (cur->orig != NULL)
688 xmlBufferWriteQuotedString(buf, cur->orig);
689 else
690 xmlBufferWriteQuotedString(buf, cur->content);
691 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000692 break;
693 case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000694 xmlBufferWriteChar(buf, "<!ENTITY ");
695 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000696 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000697 xmlBufferWriteChar(buf, " PUBLIC ");
698 xmlBufferWriteQuotedString(buf, cur->ExternalID);
699 xmlBufferWriteChar(buf, " ");
700 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000701 } else {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000702 xmlBufferWriteChar(buf, " SYSTEM ");
703 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000704 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000705 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000706 break;
707 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000708 xmlBufferWriteChar(buf, "<!ENTITY ");
709 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000710 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000711 xmlBufferWriteChar(buf, " PUBLIC ");
712 xmlBufferWriteQuotedString(buf, cur->ExternalID);
713 xmlBufferWriteChar(buf, " ");
714 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000715 } else {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000716 xmlBufferWriteChar(buf, " SYSTEM ");
717 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000718 }
719 if (cur->content != NULL) { /* Should be true ! */
Daniel Veillard5099ae81999-04-21 20:12:07 +0000720 xmlBufferWriteChar(buf, " NDATA ");
Daniel Veillard011b63c1999-06-02 17:44:04 +0000721 if (cur->orig != NULL)
722 xmlBufferWriteCHAR(buf, cur->orig);
723 else
724 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000725 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000726 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000727 break;
728 case XML_INTERNAL_PARAMETER_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000729 xmlBufferWriteChar(buf, "<!ENTITY % ");
730 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000731 xmlBufferWriteChar(buf, " ");
732 if (cur->orig == NULL)
733 xmlBufferWriteQuotedString(buf, cur->content);
734 else
735 xmlBufferWriteQuotedString(buf, cur->orig);
736 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000737 break;
738 case XML_EXTERNAL_PARAMETER_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000739 xmlBufferWriteChar(buf, "<!ENTITY % ");
740 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000741 if (cur->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000742 xmlBufferWriteChar(buf, " PUBLIC ");
743 xmlBufferWriteQuotedString(buf, cur->ExternalID);
744 xmlBufferWriteChar(buf, " ");
745 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000746 } else {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000747 xmlBufferWriteChar(buf, " SYSTEM ");
748 xmlBufferWriteQuotedString(buf, cur->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000749 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000750 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000751 break;
752 default:
753 fprintf(stderr,
754 "xmlDumpEntitiesTable: internal: unknown type %d\n",
755 cur->type);
756 }
757 }
758}