Annotation of XML/xmlIO.c, revision 1.34
1.1 daniel 1: /*
2: * xmlIO.c : implementation of the I/O interfaces used by the parser
3: *
4: * See Copyright for the status of this software.
5: *
6: * Daniel.Veillard@w3.org
7: */
8:
1.10 daniel 9: #ifdef WIN32
1.16 daniel 10: #include "win32config.h"
1.10 daniel 11: #else
1.12 daniel 12: #include "config.h"
1.10 daniel 13: #endif
14:
15: #include <stdio.h>
16: #include <string.h>
1.1 daniel 17:
1.10 daniel 18: #ifdef HAVE_SYS_TYPES_H
1.1 daniel 19: #include <sys/types.h>
1.10 daniel 20: #endif
21: #ifdef HAVE_SYS_STAT_H
1.1 daniel 22: #include <sys/stat.h>
1.10 daniel 23: #endif
24: #ifdef HAVE_FCNTL_H
1.1 daniel 25: #include <fcntl.h>
1.10 daniel 26: #endif
1.1 daniel 27: #ifdef HAVE_UNISTD_H
28: #include <unistd.h>
29: #endif
1.10 daniel 30: #ifdef HAVE_STDLIB_H
31: #include <stdlib.h>
32: #endif
1.1 daniel 33: #ifdef HAVE_ZLIB_H
34: #include <zlib.h>
35: #endif
36:
1.21 daniel 37: #include <libxml/xmlmemory.h>
38: #include <libxml/parser.h>
39: #include <libxml/parserInternals.h>
40: #include <libxml/xmlIO.h>
41: #include <libxml/nanohttp.h>
42: #include <libxml/nanoftp.h>
1.1 daniel 43:
1.2 daniel 44: /* #define VERBOSE_FAILURE */
1.5 daniel 45: /* #define DEBUG_EXTERNAL_ENTITIES */
1.28 daniel 46: /* #define DEBUG_INPUT */
1.1 daniel 47:
48: #ifdef DEBUG_INPUT
49: #define MINLEN 40
50: #else
51: #define MINLEN 4000
52: #endif
53:
1.22 daniel 54: /*
55: * Input I/O callback sets
56: */
57: typedef struct _xmlInputCallback {
58: xmlInputMatchCallback matchcallback;
59: xmlInputOpenCallback opencallback;
60: xmlInputReadCallback readcallback;
61: xmlInputCloseCallback closecallback;
62: } xmlInputCallback;
63:
1.23 daniel 64: #define MAX_INPUT_CALLBACK 15
1.22 daniel 65:
1.23 daniel 66: xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
67: int xmlInputCallbackNr = 0;
68: int xmlInputCallbackInitialized = 0;
69:
1.27 daniel 70: /*
71: * Output I/O callback sets
72: */
73: typedef struct _xmlOutputCallback {
74: xmlOutputMatchCallback matchcallback;
75: xmlOutputOpenCallback opencallback;
76: xmlOutputWriteCallback writecallback;
77: xmlOutputCloseCallback closecallback;
78: } xmlOutputCallback;
79:
80: #define MAX_OUTPUT_CALLBACK 15
81:
82: xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
83: int xmlOutputCallbackNr = 0;
84: int xmlOutputCallbackInitialized = 0;
85:
1.23 daniel 86: /************************************************************************
87: * *
88: * Standard I/O for file accesses *
89: * *
90: ************************************************************************/
1.22 daniel 91:
1.32 veillard 92: int
93: xmlNop(void) {
94: return(0);
95: }
96:
1.22 daniel 97: /**
1.23 daniel 98: * xmlFdMatch:
1.22 daniel 99: * @filename: the URI for matching
100: *
101: * input from file descriptor
102: *
103: * Returns 1 if matches, 0 otherwise
104: */
1.23 daniel 105: int
106: xmlFdMatch (const char *filename) {
107: return(1);
108: }
109:
110: /**
111: * xmlFdOpen:
112: * @filename: the URI for matching
113: *
114: * input from file descriptor, supports compressed input
115: * if @filename is " " then the standard input is used
116: *
117: * Returns an I/O context or NULL in case of error
118: */
119: void *
120: xmlFdOpen (const char *filename) {
121: const char *path = NULL;
122: int fd;
123:
124: if (!strcmp(filename, "-")) {
125: fd = 0;
126: return((void *) fd);
127: }
128:
1.22 daniel 129: if (!strncmp(filename, "file://localhost", 16))
1.23 daniel 130: path = &filename[16];
131: else if (!strncmp(filename, "file:///", 8))
132: path = &filename[8];
133: else if (filename[0] == '/')
134: path = filename;
135: if (path == NULL)
136: return(NULL);
137:
138: #ifdef WIN32
139: fd = _open (filename, O_RDONLY | _O_BINARY);
140: #else
141: fd = open (filename, O_RDONLY);
142: #endif
143:
144: return((void *) fd);
145: }
146:
147: /**
1.28 daniel 148: * xmlFdOpenW:
149: * @filename: the URI for matching
150: *
151: * input from file descriptor,
152: * if @filename is "-" then the standard output is used
153: *
154: * Returns an I/O context or NULL in case of error
155: */
156: void *
157: xmlFdOpenW (const char *filename) {
158: const char *path = NULL;
159: int fd;
160:
161: if (!strcmp(filename, "-")) {
162: fd = 1;
163: return((void *) fd);
164: }
165:
166: if (!strncmp(filename, "file://localhost", 16))
167: path = &filename[16];
168: else if (!strncmp(filename, "file:///", 8))
169: path = &filename[8];
170: else if (filename[0] == '/')
171: path = filename;
172: if (path == NULL)
173: return(NULL);
174:
175: fd = open (filename, O_WRONLY);
176:
177: return((void *) fd);
178: }
179:
180: /**
1.23 daniel 181: * xmlFdRead:
182: * @context: the I/O context
183: * @buffer: where to drop data
1.27 daniel 184: * @len: number of bytes to read
1.23 daniel 185: *
186: * Read @len bytes to @buffer from the I/O channel.
187: *
188: * Returns the number of bytes written
189: */
190: int
191: xmlFdRead (void * context, char * buffer, int len) {
192: return(read((int) context, &buffer[0], len));
193: }
194:
195: /**
1.27 daniel 196: * xmlFdWrite:
197: * @context: the I/O context
198: * @buffer: where to get data
199: * @len: number of bytes to write
200: *
201: * Write @len bytes from @buffer to the I/O channel.
202: *
203: * Returns the number of bytes written
204: */
205: int
206: xmlFdWrite (void * context, const char * buffer, int len) {
207: return(write((int) context, &buffer[0], len));
208: }
209:
210: /**
1.23 daniel 211: * xmlFdClose:
212: * @context: the I/O context
213: *
214: * Close an I/O channel
215: */
216: void
217: xmlFdClose (void * context) {
218: close((int) context);
1.22 daniel 219: }
1.23 daniel 220:
1.22 daniel 221: /**
1.23 daniel 222: * xmlFileMatch:
1.22 daniel 223: * @filename: the URI for matching
224: *
1.23 daniel 225: * input from FILE *
1.22 daniel 226: *
227: * Returns 1 if matches, 0 otherwise
228: */
1.23 daniel 229: int
230: xmlFileMatch (const char *filename) {
231: return(1);
232: }
233:
234: /**
235: * xmlFileOpen:
236: * @filename: the URI for matching
237: *
238: * input from FILE *, supports compressed input
239: * if @filename is " " then the standard input is used
240: *
241: * Returns an I/O context or NULL in case of error
242: */
243: void *
244: xmlFileOpen (const char *filename) {
1.22 daniel 245: const char *path = NULL;
1.23 daniel 246: FILE *fd;
247:
248: if (!strcmp(filename, "-")) {
249: fd = stdin;
250: return((void *) fd);
251: }
1.22 daniel 252:
253: if (!strncmp(filename, "file://localhost", 16))
254: path = &filename[16];
255: else if (!strncmp(filename, "file:///", 8))
1.23 daniel 256: path = &filename[8];
257: else
1.22 daniel 258: path = filename;
259: if (path == NULL)
1.23 daniel 260: return(NULL);
261:
1.22 daniel 262: #ifdef WIN32
1.23 daniel 263: fd = fopen(path, "rb");
1.22 daniel 264: #else
1.23 daniel 265: fd = fopen(path, "r");
266: #endif /* WIN32 */
267: return((void *) fd);
268: }
269:
270: /**
1.28 daniel 271: * xmlFileOpenW:
272: * @filename: the URI for matching
273: *
274: * output to from FILE *,
275: * if @filename is "-" then the standard output is used
276: *
277: * Returns an I/O context or NULL in case of error
278: */
279: void *
280: xmlFileOpenW (const char *filename) {
281: const char *path = NULL;
282: FILE *fd;
283:
284: if (!strcmp(filename, "-")) {
285: fd = stdout;
286: return((void *) fd);
287: }
288:
289: if (!strncmp(filename, "file://localhost", 16))
290: path = &filename[16];
291: else if (!strncmp(filename, "file:///", 8))
292: path = &filename[8];
293: else
294: path = filename;
295: if (path == NULL)
296: return(NULL);
297:
298: fd = fopen(path, "w");
299: return((void *) fd);
300: }
301:
302: /**
1.23 daniel 303: * xmlFileRead:
304: * @context: the I/O context
305: * @buffer: where to drop data
306: * @len: number of bytes to write
307: *
308: * Read @len bytes to @buffer from the I/O channel.
309: *
310: * Returns the number of bytes written
311: */
312: int
313: xmlFileRead (void * context, char * buffer, int len) {
314: return(fread(&buffer[0], 1, len, (FILE *) context));
315: }
316:
317: /**
1.27 daniel 318: * xmlFileWrite:
319: * @context: the I/O context
320: * @buffer: where to drop data
321: * @len: number of bytes to write
322: *
323: * Write @len bytes from @buffer to the I/O channel.
324: *
325: * Returns the number of bytes written
326: */
327: int
328: xmlFileWrite (void * context, const char * buffer, int len) {
329: return(fwrite(&buffer[0], 1, len, (FILE *) context));
330: }
331:
332: /**
1.23 daniel 333: * xmlFileClose:
334: * @context: the I/O context
335: *
336: * Close an I/O channel
337: */
338: void
339: xmlFileClose (void * context) {
340: fclose((FILE *) context);
341: }
342:
343: #ifdef HAVE_ZLIB_H
344: /************************************************************************
345: * *
346: * I/O for compressed file accesses *
347: * *
348: ************************************************************************/
349: /**
350: * xmlGzfileMatch:
351: * @filename: the URI for matching
352: *
353: * input from compressed file test
354: *
355: * Returns 1 if matches, 0 otherwise
356: */
357: int
358: xmlGzfileMatch (const char *filename) {
359: return(1);
360: }
361:
362: /**
363: * xmlGzfileOpen:
364: * @filename: the URI for matching
365: *
366: * input from compressed file open
367: * if @filename is " " then the standard input is used
368: *
369: * Returns an I/O context or NULL in case of error
370: */
371: void *
372: xmlGzfileOpen (const char *filename) {
373: const char *path = NULL;
374: gzFile fd;
375:
376: if (!strcmp(filename, "-")) {
377: fd = gzdopen (fileno(stdin), "r");
378: return((void *) fd);
379: }
380:
381: if (!strncmp(filename, "file://localhost", 16))
382: path = &filename[16];
383: else if (!strncmp(filename, "file:///", 8))
384: path = &filename[8];
385: else
386: path = filename;
387:
388: fd = gzopen(filename, "r");
389: return((void *) fd);
390: }
391:
392: /**
1.28 daniel 393: * xmlGzfileOpenW:
394: * @filename: the URI for matching
395: * @compression: the compression factor (0 - 9 included)
396: *
397: * input from compressed file open
398: * if @filename is " " then the standard input is used
399: *
400: * Returns an I/O context or NULL in case of error
401: */
402: void *
403: xmlGzfileOpenW (const char *filename, int compression) {
404: const char *path = NULL;
405: char mode[15];
406: gzFile fd;
407:
408: sprintf(mode, "w%d", compression);
409: if (!strcmp(filename, "-")) {
410: fd = gzdopen(1, mode);
411: return((void *) fd);
412: }
413:
414: if (!strncmp(filename, "file://localhost", 16))
415: path = &filename[16];
416: else if (!strncmp(filename, "file:///", 8))
417: path = &filename[8];
418: else
419: path = filename;
420:
421: fd = gzopen(filename, mode);
422: return((void *) fd);
423: }
424:
425: /**
1.23 daniel 426: * xmlGzfileRead:
427: * @context: the I/O context
428: * @buffer: where to drop data
429: * @len: number of bytes to write
430: *
431: * Read @len bytes to @buffer from the compressed I/O channel.
432: *
433: * Returns the number of bytes written
434: */
435: int
436: xmlGzfileRead (void * context, char * buffer, int len) {
437: return(gzread((gzFile) context, &buffer[0], len));
438: }
439:
440: /**
1.28 daniel 441: * xmlGzfileWrite:
442: * @context: the I/O context
443: * @buffer: where to drop data
444: * @len: number of bytes to write
445: *
446: * Write @len bytes from @buffer to the compressed I/O channel.
447: *
448: * Returns the number of bytes written
449: */
450: int
451: xmlGzfileWrite (void * context, const char * buffer, int len) {
452: return(gzwrite((gzFile) context, (char *) &buffer[0], len));
453: }
454:
455: /**
1.23 daniel 456: * xmlGzfileClose:
457: * @context: the I/O context
458: *
459: * Close a compressed I/O channel
460: */
461: void
462: xmlGzfileClose (void * context) {
463: gzclose((gzFile) context);
464: }
465: #endif /* HAVE_ZLIB_H */
466:
467: #ifdef LIBXML_HTTP_ENABLED
468: /************************************************************************
469: * *
470: * I/O for HTTP file accesses *
471: * *
472: ************************************************************************/
473: /**
474: * xmlIOHTTPMatch:
475: * @filename: the URI for matching
476: *
477: * check if the URI matches an HTTP one
478: *
479: * Returns 1 if matches, 0 otherwise
480: */
481: int
482: xmlIOHTTPMatch (const char *filename) {
483: if (!strncmp(filename, "http://", 7))
484: return(1);
485: return(0);
486: }
487:
488: /**
489: * xmlIOHTTPOpen:
490: * @filename: the URI for matching
491: *
492: * open an HTTP I/O channel
493: *
494: * Returns an I/O context or NULL in case of error
495: */
496: void *
497: xmlIOHTTPOpen (const char *filename) {
498: return(xmlNanoHTTPOpen(filename, NULL));
499: }
500:
501: /**
502: * xmlIOHTTPRead:
503: * @context: the I/O context
504: * @buffer: where to drop data
505: * @len: number of bytes to write
506: *
507: * Read @len bytes to @buffer from the I/O channel.
508: *
509: * Returns the number of bytes written
510: */
511: int
512: xmlIOHTTPRead(void * context, char * buffer, int len) {
513: return(xmlNanoHTTPRead(context, &buffer[0], len));
1.22 daniel 514: }
515:
1.23 daniel 516: /**
517: * xmlIOHTTPClose:
518: * @context: the I/O context
519: *
520: * Close an HTTP I/O channel
521: */
522: void
523: xmlIOHTTPClose (void * context) {
524: xmlNanoHTTPClose(context);
1.22 daniel 525: }
1.23 daniel 526: #endif /* LIBXML_HTTP_ENABLED */
527:
528: #ifdef LIBXML_FTP_ENABLED
529: /************************************************************************
530: * *
531: * I/O for FTP file accesses *
532: * *
533: ************************************************************************/
534: /**
535: * xmlIOFTPMatch:
536: * @filename: the URI for matching
537: *
538: * check if the URI matches an FTP one
539: *
540: * Returns 1 if matches, 0 otherwise
541: */
542: int
543: xmlIOFTPMatch (const char *filename) {
544: if (!strncmp(filename, "ftp://", 6))
545: return(1);
546: return(0);
1.22 daniel 547: }
548:
1.23 daniel 549: /**
550: * xmlIOFTPOpen:
551: * @filename: the URI for matching
552: *
553: * open an FTP I/O channel
554: *
555: * Returns an I/O context or NULL in case of error
556: */
557: void *
558: xmlIOFTPOpen (const char *filename) {
559: return(xmlNanoFTPOpen(filename));
1.22 daniel 560: }
1.23 daniel 561:
562: /**
563: * xmlIOFTPRead:
564: * @context: the I/O context
565: * @buffer: where to drop data
566: * @len: number of bytes to write
567: *
568: * Read @len bytes to @buffer from the I/O channel.
569: *
570: * Returns the number of bytes written
571: */
572: int
573: xmlIOFTPRead(void * context, char * buffer, int len) {
574: return(xmlNanoFTPRead(context, &buffer[0], len));
1.22 daniel 575: }
1.23 daniel 576:
577: /**
578: * xmlIOFTPClose:
579: * @context: the I/O context
580: *
581: * Close an FTP I/O channel
582: */
583: void
584: xmlIOFTPClose (void * context) {
585: xmlNanoFTPClose(context);
1.22 daniel 586: }
1.23 daniel 587: #endif /* LIBXML_FTP_ENABLED */
588:
589:
590: /**
591: * xmlRegisterInputCallbacks:
592: * @match: the xmlInputMatchCallback
593: * @open: the xmlInputOpenCallback
594: * @read: the xmlInputReadCallback
595: * @close: the xmlInputCloseCallback
596: *
597: * Register a new set of I/O callback for handling parser input.
598: *
599: * Returns the registered handler number or -1 in case of error
600: */
601: int
602: xmlRegisterInputCallbacks(xmlInputMatchCallback match,
603: xmlInputOpenCallback open, xmlInputReadCallback read,
604: xmlInputCloseCallback close) {
605: if (xmlInputCallbackNr >= MAX_INPUT_CALLBACK) {
606: return(-1);
607: }
608: xmlInputCallbackTable[xmlInputCallbackNr].matchcallback = match;
609: xmlInputCallbackTable[xmlInputCallbackNr].opencallback = open;
610: xmlInputCallbackTable[xmlInputCallbackNr].readcallback = read;
611: xmlInputCallbackTable[xmlInputCallbackNr].closecallback = close;
612: return(xmlInputCallbackNr++);
1.22 daniel 613: }
614:
1.23 daniel 615: /**
1.27 daniel 616: * xmlRegisterOutputCallbacks:
617: * @match: the xmlOutputMatchCallback
618: * @open: the xmlOutputOpenCallback
619: * @write: the xmlOutputWriteCallback
620: * @close: the xmlOutputCloseCallback
621: *
622: * Register a new set of I/O callback for handling output.
623: *
624: * Returns the registered handler number or -1 in case of error
625: */
626: int
627: xmlRegisterOutputCallbacks(xmlOutputMatchCallback match,
628: xmlOutputOpenCallback open, xmlOutputWriteCallback write,
629: xmlOutputCloseCallback close) {
630: if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
631: return(-1);
632: }
633: xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = match;
634: xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = open;
635: xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = write;
636: xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = close;
637: return(xmlOutputCallbackNr++);
638: }
639:
640: /**
1.23 daniel 641: * xmlRegisterDefaultInputCallbacks:
642: *
643: * Registers the default compiled-in I/O handlers.
644: */
645: void
646: xmlRegisterDefaultInputCallbacks(void) {
1.34 ! veillard 647: if (xmlInputCallbackInitialized)
! 648: return;
! 649:
1.23 daniel 650: xmlRegisterInputCallbacks(xmlFileMatch, xmlFileOpen,
651: xmlFileRead, xmlFileClose);
652: #ifdef HAVE_ZLIB_H
653: xmlRegisterInputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
654: xmlGzfileRead, xmlGzfileClose);
655: #endif /* HAVE_ZLIB_H */
656:
657: #ifdef LIBXML_HTTP_ENABLED
658: xmlRegisterInputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
659: xmlIOHTTPRead, xmlIOHTTPClose);
660: #endif /* LIBXML_HTTP_ENABLED */
661:
662: #ifdef LIBXML_FTP_ENABLED
663: xmlRegisterInputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
664: xmlIOFTPRead, xmlIOFTPClose);
665: #endif /* LIBXML_FTP_ENABLED */
1.34 ! veillard 666: xmlInputCallbackInitialized = 1;
1.23 daniel 667: }
1.22 daniel 668:
1.1 daniel 669: /**
1.27 daniel 670: * xmlRegisterDefaultOutputCallbacks:
671: *
672: * Registers the default compiled-in I/O handlers.
673: */
674: void
675: xmlRegisterDefaultOutputCallbacks(void) {
1.34 ! veillard 676: if (xmlOutputCallbackInitialized)
! 677: return;
! 678:
1.28 daniel 679: xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
1.27 daniel 680: xmlFileWrite, xmlFileClose);
681: /*********************************
682: No way a-priori to distinguish between gzipped files from
683: uncompressed ones except opening if existing then closing
684: and saving with same compression ratio ... a pain.
685:
686: #ifdef HAVE_ZLIB_H
687: xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
688: xmlGzfileWrite, xmlGzfileClose);
689: #endif
690: No HTTP PUT support yet, patches welcome
691:
692: #ifdef LIBXML_HTTP_ENABLED
693: xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
694: xmlIOHTTPWrite, xmlIOHTTPClose);
695: #endif
696:
697: Nor FTP PUT ....
698: #ifdef LIBXML_FTP_ENABLED
699: xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
700: xmlIOFTPWrite, xmlIOFTPClose);
701: #endif
702: **********************************/
1.34 ! veillard 703: xmlOutputCallbackInitialized = 1;
1.27 daniel 704: }
705:
706: /**
1.1 daniel 707: * xmlAllocParserInputBuffer:
708: * @enc: the charset encoding if known
709: *
710: * Create a buffered parser input for progressive parsing
711: *
712: * Returns the new parser input or NULL
713: */
714: xmlParserInputBufferPtr
715: xmlAllocParserInputBuffer(xmlCharEncoding enc) {
716: xmlParserInputBufferPtr ret;
717:
1.8 daniel 718: ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer));
1.1 daniel 719: if (ret == NULL) {
720: fprintf(stderr, "xmlAllocParserInputBuffer : out of memory!\n");
721: return(NULL);
722: }
1.3 veillard 723: memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
1.1 daniel 724: ret->buffer = xmlBufferCreate();
1.17 daniel 725: if (ret->buffer == NULL) {
726: xmlFree(ret);
727: return(NULL);
728: }
729: ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
1.1 daniel 730: ret->encoder = xmlGetCharEncodingHandler(enc);
1.26 daniel 731: if (ret->encoder != NULL)
732: ret->raw = xmlBufferCreate();
733: else
734: ret->raw = NULL;
1.23 daniel 735: ret->readcallback = NULL;
736: ret->closecallback = NULL;
737: ret->context = NULL;
1.1 daniel 738:
739: return(ret);
740: }
741:
742: /**
1.27 daniel 743: * xmlAllocOutputBuffer:
744: * @encoder: the encoding converter or NULL
745: *
746: * Create a buffered parser output
747: *
748: * Returns the new parser output or NULL
749: */
750: xmlOutputBufferPtr
751: xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
752: xmlOutputBufferPtr ret;
753:
754: ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
755: if (ret == NULL) {
756: fprintf(stderr, "xmlAllocOutputBuffer : out of memory!\n");
757: return(NULL);
758: }
759: memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
760: ret->buffer = xmlBufferCreate();
761: if (ret->buffer == NULL) {
762: xmlFree(ret);
763: return(NULL);
764: }
765: ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
766: ret->encoder = encoder;
1.28 daniel 767: if (encoder != NULL) {
768: ret->conv = xmlBufferCreateSize(4000);
769: /*
770: * This call is designed to initiate the encoder state
771: */
772: xmlCharEncOutFunc(encoder, ret->conv, NULL);
773: } else
774: ret->conv = NULL;
1.27 daniel 775: ret->writecallback = NULL;
776: ret->closecallback = NULL;
777: ret->context = NULL;
1.28 daniel 778: ret->written = 0;
1.27 daniel 779:
780: return(ret);
781: }
782:
783: /**
1.1 daniel 784: * xmlFreeParserInputBuffer:
785: * @in: a buffered parser input
786: *
787: * Free up the memory used by a buffered parser input
788: */
789: void
790: xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
1.26 daniel 791: if (in->raw) {
792: xmlBufferFree(in->raw);
793: in->raw = NULL;
794: }
1.25 daniel 795: if (in->encoder != NULL) {
796: xmlCharEncCloseFunc(in->encoder);
797: }
798: if (in->closecallback != NULL) {
799: in->closecallback(in->context);
800: }
1.1 daniel 801: if (in->buffer != NULL) {
802: xmlBufferFree(in->buffer);
803: in->buffer = NULL;
804: }
1.23 daniel 805:
1.3 veillard 806: memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer));
1.8 daniel 807: xmlFree(in);
1.1 daniel 808: }
809:
810: /**
1.28 daniel 811: * xmlOutputBufferClose:
812: * @out: a buffered output
813: *
814: * flushes and close the output I/O channel
815: * and free up all the associated resources
816: *
817: * Returns the number of byte written or -1 in case of error.
818: */
819: int
820: xmlOutputBufferClose(xmlOutputBufferPtr out) {
821: int written;
822:
823: if (out == NULL)
824: return(-1);
825: xmlOutputBufferFlush(out);
826: if (out->closecallback != NULL) {
827: out->closecallback(out->context);
828: }
829: written = out->written;
830: if (out->conv) {
831: xmlBufferFree(out->conv);
832: out->conv = NULL;
833: }
834: if (out->encoder != NULL) {
835: xmlCharEncCloseFunc(out->encoder);
836: }
837: if (out->buffer != NULL) {
838: xmlBufferFree(out->buffer);
839: out->buffer = NULL;
840: }
841:
842: memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer));
843: xmlFree(out);
844: return(written);
845: }
846:
847: /**
1.1 daniel 848: * xmlParserInputBufferCreateFilename:
1.23 daniel 849: * @URI: a C string containing the URI or filename
1.1 daniel 850: * @enc: the charset encoding if known
851: *
852: * Create a buffered parser input for the progressive parsing of a file
853: * If filename is "-' then we use stdin as the input.
854: * Automatic support for ZLIB/Compress compressed document is provided
855: * by default if found at compile-time.
1.20 daniel 856: * Do an encoding check if enc == XML_CHAR_ENCODING_NONE
1.1 daniel 857: *
858: * Returns the new parser input or NULL
859: */
860: xmlParserInputBufferPtr
1.23 daniel 861: xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
1.1 daniel 862: xmlParserInputBufferPtr ret;
1.23 daniel 863: int i;
864: void *context = NULL;
865:
866: if (xmlInputCallbackInitialized == 0)
867: xmlRegisterDefaultInputCallbacks();
1.1 daniel 868:
1.23 daniel 869: if (URI == NULL) return(NULL);
1.1 daniel 870:
1.23 daniel 871: /*
872: * Try to find one of the input accept method accepting taht scheme
873: * Go in reverse to give precedence to user defined handlers.
874: */
875: for (i = xmlInputCallbackNr - 1;i >= 0;i--) {
876: if ((xmlInputCallbackTable[i].matchcallback != NULL) &&
877: (xmlInputCallbackTable[i].matchcallback(URI) != 0)) {
878: context = xmlInputCallbackTable[i].opencallback(URI);
879: if (context != NULL)
880: break;
1.1 daniel 881: }
1.23 daniel 882: }
883: if (context == NULL) {
884: return(NULL);
1.1 daniel 885: }
1.20 daniel 886:
887: /*
888: * Allocate the Input buffer front-end.
1.1 daniel 889: */
890: ret = xmlAllocParserInputBuffer(enc);
891: if (ret != NULL) {
1.23 daniel 892: ret->context = context;
893: ret->readcallback = xmlInputCallbackTable[i].readcallback;
894: ret->closecallback = xmlInputCallbackTable[i].closecallback;
1.1 daniel 895: }
896: return(ret);
897: }
898:
899: /**
1.27 daniel 900: * xmlOutputBufferCreateFilename:
901: * @URI: a C string containing the URI or filename
902: * @encoder: the encoding converter or NULL
1.28 daniel 903: * @compression: the compression ration (0 none, 9 max).
1.27 daniel 904: *
905: * Create a buffered output for the progressive saving of a file
906: * If filename is "-' then we use stdout as the output.
907: * Automatic support for ZLIB/Compress compressed document is provided
908: * by default if found at compile-time.
1.28 daniel 909: * TODO: currently if compression is set, the library only support
910: * writing to a local file.
1.27 daniel 911: *
912: * Returns the new output or NULL
913: */
914: xmlOutputBufferPtr
915: xmlOutputBufferCreateFilename(const char *URI,
1.28 daniel 916: xmlCharEncodingHandlerPtr encoder,
917: int compression) {
1.27 daniel 918: xmlOutputBufferPtr ret;
919: int i;
920: void *context = NULL;
921:
922: if (xmlOutputCallbackInitialized == 0)
923: xmlRegisterDefaultOutputCallbacks();
924:
925: if (URI == NULL) return(NULL);
926:
1.28 daniel 927: #ifdef HAVE_ZLIB_H
928: if ((compression > 0) && (compression <= 9)) {
929: context = xmlGzfileOpenW(URI, compression);
930: if (context != NULL) {
931: ret = xmlAllocOutputBuffer(encoder);
932: if (ret != NULL) {
933: ret->context = context;
934: ret->writecallback = xmlGzfileWrite;
935: ret->closecallback = xmlGzfileClose;
936: }
937: return(ret);
938: }
939: }
940: #endif
941:
1.27 daniel 942: /*
943: * Try to find one of the output accept method accepting taht scheme
944: * Go in reverse to give precedence to user defined handlers.
945: */
946: for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
947: if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
948: (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
949: context = xmlOutputCallbackTable[i].opencallback(URI);
950: if (context != NULL)
951: break;
952: }
953: }
954: if (context == NULL) {
955: return(NULL);
956: }
957:
958: /*
959: * Allocate the Output buffer front-end.
960: */
961: ret = xmlAllocOutputBuffer(encoder);
962: if (ret != NULL) {
963: ret->context = context;
964: ret->writecallback = xmlOutputCallbackTable[i].writecallback;
965: ret->closecallback = xmlOutputCallbackTable[i].closecallback;
966: }
967: return(ret);
968: }
969:
970: /**
1.1 daniel 971: * xmlParserInputBufferCreateFile:
972: * @file: a FILE*
973: * @enc: the charset encoding if known
974: *
975: * Create a buffered parser input for the progressive parsing of a FILE *
976: * buffered C I/O
977: *
978: * Returns the new parser input or NULL
979: */
980: xmlParserInputBufferPtr
981: xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
982: xmlParserInputBufferPtr ret;
983:
1.23 daniel 984: if (xmlInputCallbackInitialized == 0)
985: xmlRegisterDefaultInputCallbacks();
986:
1.1 daniel 987: if (file == NULL) return(NULL);
988:
989: ret = xmlAllocParserInputBuffer(enc);
1.23 daniel 990: if (ret != NULL) {
991: ret->context = file;
992: ret->readcallback = xmlFileRead;
993: ret->closecallback = xmlFileClose;
994: }
1.1 daniel 995:
996: return(ret);
997: }
998:
999: /**
1.27 daniel 1000: * xmlOutputBufferCreateFile:
1001: * @file: a FILE*
1002: * @encoder: the encoding converter or NULL
1003: *
1004: * Create a buffered output for the progressive saving to a FILE *
1005: * buffered C I/O
1006: *
1007: * Returns the new parser output or NULL
1008: */
1009: xmlOutputBufferPtr
1010: xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
1011: xmlOutputBufferPtr ret;
1012:
1013: if (xmlOutputCallbackInitialized == 0)
1014: xmlRegisterDefaultOutputCallbacks();
1015:
1016: if (file == NULL) return(NULL);
1017:
1018: ret = xmlAllocOutputBuffer(encoder);
1019: if (ret != NULL) {
1020: ret->context = file;
1021: ret->writecallback = xmlFileWrite;
1022: ret->closecallback = xmlFileClose;
1023: }
1024:
1025: return(ret);
1026: }
1027:
1028: /**
1.1 daniel 1029: * xmlParserInputBufferCreateFd:
1030: * @fd: a file descriptor number
1031: * @enc: the charset encoding if known
1032: *
1033: * Create a buffered parser input for the progressive parsing for the input
1034: * from a file descriptor
1035: *
1036: * Returns the new parser input or NULL
1037: */
1038: xmlParserInputBufferPtr
1039: xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
1040: xmlParserInputBufferPtr ret;
1041:
1042: if (fd < 0) return(NULL);
1043:
1044: ret = xmlAllocParserInputBuffer(enc);
1.23 daniel 1045: if (ret != NULL) {
1046: ret->context = (void *) fd;
1047: ret->readcallback = xmlFdRead;
1048: ret->closecallback = xmlFdClose;
1049: }
1.1 daniel 1050:
1051: return(ret);
1052: }
1053:
1054: /**
1.31 veillard 1055: * xmlParserInputBufferCreateMem:
1056: * @mem: the memory input
1057: * @size: the length of the memory block
1058: * @enc: the charset encoding if known
1059: *
1060: * Create a buffered parser input for the progressive parsing for the input
1061: * from a file descriptor
1062: *
1063: * Returns the new parser input or NULL
1064: */
1065: xmlParserInputBufferPtr
1066: xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
1067: xmlParserInputBufferPtr ret;
1068:
1069: if (size <= 0) return(NULL);
1070: if (mem == NULL) return(NULL);
1071:
1072: ret = xmlAllocParserInputBuffer(enc);
1073: if (ret != NULL) {
1074: ret->context = (void *) mem;
1.32 veillard 1075: ret->readcallback = (xmlInputReadCallback) xmlNop;
1.31 veillard 1076: ret->closecallback = NULL;
1077: xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size);
1078: }
1079:
1080: return(ret);
1081: }
1082:
1083: /**
1.27 daniel 1084: * xmlOutputBufferCreateFd:
1085: * @fd: a file descriptor number
1086: * @encoder: the encoding converter or NULL
1087: *
1088: * Create a buffered output for the progressive saving
1089: * to a file descriptor
1090: *
1091: * Returns the new parser output or NULL
1092: */
1093: xmlOutputBufferPtr
1094: xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
1095: xmlOutputBufferPtr ret;
1096:
1097: if (fd < 0) return(NULL);
1098:
1099: ret = xmlAllocOutputBuffer(encoder);
1100: if (ret != NULL) {
1101: ret->context = (void *) fd;
1102: ret->writecallback = xmlFdWrite;
1103: ret->closecallback = xmlFdClose;
1104: }
1105:
1106: return(ret);
1107: }
1108:
1109: /**
1.24 daniel 1110: * xmlParserInputBufferCreateIO:
1111: * @ioread: an I/O read function
1112: * @ioclose: an I/O close function
1113: * @ioctx: an I/O handler
1114: * @enc: the charset encoding if known
1115: *
1116: * Create a buffered parser input for the progressive parsing for the input
1.27 daniel 1117: * from an I/O handler
1.24 daniel 1118: *
1119: * Returns the new parser input or NULL
1120: */
1121: xmlParserInputBufferPtr
1122: xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
1123: xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc) {
1124: xmlParserInputBufferPtr ret;
1125:
1126: if (ioread == NULL) return(NULL);
1127:
1128: ret = xmlAllocParserInputBuffer(enc);
1129: if (ret != NULL) {
1130: ret->context = (void *) ioctx;
1131: ret->readcallback = ioread;
1132: ret->closecallback = ioclose;
1133: }
1134:
1135: return(ret);
1136: }
1137:
1138: /**
1.27 daniel 1139: * xmlOutputBufferCreateIO:
1140: * @iowrite: an I/O write function
1141: * @ioclose: an I/O close function
1142: * @ioctx: an I/O handler
1143: * @enc: the charset encoding if known
1144: *
1145: * Create a buffered output for the progressive saving
1146: * to an I/O handler
1147: *
1148: * Returns the new parser output or NULL
1149: */
1150: xmlOutputBufferPtr
1151: xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
1152: xmlOutputCloseCallback ioclose, void *ioctx,
1153: xmlCharEncodingHandlerPtr encoder) {
1154: xmlOutputBufferPtr ret;
1155:
1156: if (iowrite == NULL) return(NULL);
1157:
1158: ret = xmlAllocOutputBuffer(encoder);
1159: if (ret != NULL) {
1160: ret->context = (void *) ioctx;
1161: ret->writecallback = iowrite;
1162: ret->closecallback = ioclose;
1163: }
1164:
1165: return(ret);
1166: }
1167:
1168: /**
1.14 daniel 1169: * xmlParserInputBufferPush:
1170: * @in: a buffered parser input
1.27 daniel 1171: * @len: the size in bytes of the array.
1.14 daniel 1172: * @buf: an char array
1173: *
1174: * Push the content of the arry in the input buffer
1175: * This routine handle the I18N transcoding to internal UTF-8
1176: * This is used when operating the parser in progressive (push) mode.
1177: *
1178: * Returns the number of chars read and stored in the buffer, or -1
1179: * in case of error.
1180: */
1181: int
1.15 daniel 1182: xmlParserInputBufferPush(xmlParserInputBufferPtr in, int len, const char *buf) {
1.14 daniel 1183: int nbchars = 0;
1184:
1185: if (len < 0) return(0);
1186: if (in->encoder != NULL) {
1.26 daniel 1187: /*
1188: * Store the data in the incoming raw buffer
1189: */
1190: if (in->raw == NULL) {
1191: in->raw = xmlBufferCreate();
1192: }
1193: xmlBufferAdd(in->raw, (const xmlChar *) buf, len);
1.14 daniel 1194:
1195: /*
1.26 daniel 1196: * convert as much as possible to the parser reading buffer.
1.14 daniel 1197: */
1.26 daniel 1198: nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1.20 daniel 1199: if (nbchars < 0) {
1200: fprintf(stderr, "xmlParserInputBufferPush: encoder error\n");
1201: return(-1);
1202: }
1.14 daniel 1203: } else {
1204: nbchars = len;
1.17 daniel 1205: xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars);
1.14 daniel 1206: }
1207: #ifdef DEBUG_INPUT
1208: fprintf(stderr, "I/O: pushed %d chars, buffer %d/%d\n",
1209: nbchars, in->buffer->use, in->buffer->size);
1210: #endif
1211: return(nbchars);
1212: }
1213:
1214: /**
1.1 daniel 1215: * xmlParserInputBufferGrow:
1216: * @in: a buffered parser input
1217: * @len: indicative value of the amount of chars to read
1218: *
1219: * Grow up the content of the input buffer, the old data are preserved
1220: * This routine handle the I18N transcoding to internal UTF-8
1.14 daniel 1221: * This routine is used when operating the parser in normal (pull) mode
1.26 daniel 1222: *
1223: * TODO: one should be able to remove one extra copy by copying directy
1224: * onto in->buffer or in->raw
1.1 daniel 1225: *
1226: * Returns the number of chars read and stored in the buffer, or -1
1227: * in case of error.
1228: */
1229: int
1230: xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
1231: char *buffer = NULL;
1232: int res = 0;
1233: int nbchars = 0;
1234: int buffree;
1235:
1236: if ((len <= MINLEN) && (len != 4))
1237: len = MINLEN;
1238: buffree = in->buffer->size - in->buffer->use;
1239: if (buffree <= 0) {
1240: fprintf(stderr, "xmlParserInputBufferGrow : buffer full !\n");
1241: return(0);
1242: }
1243: if (len > buffree)
1244: len = buffree;
1245:
1.30 veillard 1246: buffer = (char *) xmlMalloc((len + 1) * sizeof(char));
1.1 daniel 1247: if (buffer == NULL) {
1248: fprintf(stderr, "xmlParserInputBufferGrow : out of memory !\n");
1249: return(-1);
1250: }
1.23 daniel 1251:
1252: /*
1253: * Call the read method for this I/O type.
1254: */
1255: if (in->readcallback != NULL) {
1256: res = in->readcallback(in->context, &buffer[0], len);
1.1 daniel 1257: } else {
1258: fprintf(stderr, "xmlParserInputBufferGrow : no input !\n");
1.8 daniel 1259: xmlFree(buffer);
1.1 daniel 1260: return(-1);
1261: }
1262: if (res < 0) {
1263: perror ("read error");
1.8 daniel 1264: xmlFree(buffer);
1.1 daniel 1265: return(-1);
1266: }
1.29 daniel 1267: len = res;
1.1 daniel 1268: if (in->encoder != NULL) {
1.26 daniel 1269: /*
1270: * Store the data in the incoming raw buffer
1271: */
1272: if (in->raw == NULL) {
1273: in->raw = xmlBufferCreate();
1.1 daniel 1274: }
1.26 daniel 1275: xmlBufferAdd(in->raw, (const xmlChar *) buffer, len);
1.20 daniel 1276:
1277: /*
1.26 daniel 1278: * convert as much as possible to the parser reading buffer.
1.20 daniel 1279: */
1.26 daniel 1280: nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
1281: if (nbchars < 0) {
1282: fprintf(stderr, "xmlParserInputBufferGrow: encoder error\n");
1283: return(-1);
1.20 daniel 1284: }
1.1 daniel 1285: } else {
1.29 daniel 1286: nbchars = len;
1.3 veillard 1287: buffer[nbchars] = 0;
1.13 daniel 1288: xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
1.1 daniel 1289: }
1290: #ifdef DEBUG_INPUT
1291: fprintf(stderr, "I/O: read %d chars, buffer %d/%d\n",
1292: nbchars, in->buffer->use, in->buffer->size);
1293: #endif
1.8 daniel 1294: xmlFree(buffer);
1.1 daniel 1295: return(nbchars);
1296: }
1297:
1298: /**
1299: * xmlParserInputBufferRead:
1300: * @in: a buffered parser input
1301: * @len: indicative value of the amount of chars to read
1302: *
1303: * Refresh the content of the input buffer, the old data are considered
1304: * consumed
1305: * This routine handle the I18N transcoding to internal UTF-8
1306: *
1307: * Returns the number of chars read and stored in the buffer, or -1
1308: * in case of error.
1309: */
1310: int
1311: xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
1312: /* xmlBufferEmpty(in->buffer); */
1.23 daniel 1313: if (in->readcallback != NULL)
1.17 daniel 1314: return(xmlParserInputBufferGrow(in, len));
1315: else
1.27 daniel 1316: return(-1);
1317: }
1318:
1319: /**
1320: * xmlOutputBufferWrite:
1321: * @out: a buffered parser output
1322: * @len: the size in bytes of the array.
1323: * @buf: an char array
1324: *
1325: * Write the content of the array in the output I/O buffer
1326: * This routine handle the I18N transcoding from internal UTF-8
1327: * The buffer is lossless, i.e. will store in case of partial
1328: * or delayed writes.
1329: *
1330: * Returns the number of chars immediately written, or -1
1331: * in case of error.
1332: */
1333: int
1334: xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
1335: int nbchars = 0, ret;
1336:
1337: if (len < 0) return(0);
1338:
1339: /*
1340: * first handle encoding stuff.
1341: */
1342: if (out->encoder != NULL) {
1343: /*
1344: * Store the data in the incoming raw buffer
1345: */
1.28 daniel 1346: if (out->conv == NULL) {
1347: out->conv = xmlBufferCreate();
1.27 daniel 1348: }
1.28 daniel 1349: xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
1.27 daniel 1350:
1.28 daniel 1351: if (out->buffer->use < MINLEN)
1.27 daniel 1352: return(0);
1353:
1354: /*
1355: * convert as much as possible to the parser reading buffer.
1356: */
1.28 daniel 1357: nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
1.27 daniel 1358: if (nbchars < 0) {
1359: fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
1360: return(-1);
1361: }
1.28 daniel 1362: nbchars = out->conv->use;
1.27 daniel 1363: } else {
1364: xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
1.28 daniel 1365: nbchars = out->buffer->use;
1.27 daniel 1366: }
1367: if (nbchars < MINLEN)
1368: return(0);
1369:
1370: /*
1371: * second write the stuff to the I/O channel
1372: */
1.28 daniel 1373: if (out->encoder != NULL) {
1374: ret = out->writecallback(out->context,
1375: (const char *)out->conv->content, nbchars);
1376: if (ret >= 0)
1377: xmlBufferShrink(out->conv, nbchars);
1378: } else {
1379: ret = out->writecallback(out->context,
1.27 daniel 1380: (const char *)out->buffer->content, nbchars);
1.28 daniel 1381: if (ret >= 0)
1382: xmlBufferShrink(out->buffer, nbchars);
1383: }
1.27 daniel 1384: if (ret < 0) {
1385: fprintf(stderr, "I/O: error %d writing %d bytes\n", ret, nbchars);
1386: return(ret);
1387: }
1.28 daniel 1388: out->written += ret;
1.27 daniel 1389:
1390: #ifdef DEBUG_INPUT
1391: fprintf(stderr, "I/O: wrote %d chars\n", ret);
1392: #endif
1393: return(nbchars);
1.28 daniel 1394: }
1395:
1396: /**
1397: * xmlOutputBufferWriteString:
1398: * @out: a buffered parser output
1399: * @str: a zero terminated C string
1400: *
1401: * Write the content of the string in the output I/O buffer
1402: * This routine handle the I18N transcoding from internal UTF-8
1403: * The buffer is lossless, i.e. will store in case of partial
1404: * or delayed writes.
1405: *
1406: * Returns the number of chars immediately written, or -1
1407: * in case of error.
1408: */
1409: int
1410: xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
1411: int len;
1412:
1413: if (str == NULL)
1414: return(-1);
1415: len = strlen(str);
1416:
1417: if (len > 0)
1418: return(xmlOutputBufferWrite(out, len, str));
1419: return(len);
1420: }
1421:
1422: /**
1423: * xmlOutputBufferFlush:
1424: * @out: a buffered output
1425: *
1426: * flushes the output I/O channel
1427: *
1428: * Returns the number of byte written or -1 in case of error.
1429: */
1430: int
1431: xmlOutputBufferFlush(xmlOutputBufferPtr out) {
1432: int nbchars = 0, ret;
1433:
1434: /*
1435: * first handle encoding stuff.
1436: */
1437: if ((out->conv != NULL) && (out->encoder != NULL)) {
1438: /*
1439: * convert as much as possible to the parser reading buffer.
1440: */
1441: nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
1442: if (nbchars < 0) {
1443: fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
1444: return(-1);
1445: }
1446: }
1447:
1448: /*
1449: * second flush the stuff to the I/O channel
1450: */
1451: if ((out->conv != NULL) && (out->encoder != NULL)) {
1452: ret = out->writecallback(out->context,
1453: (const char *)out->conv->content, out->conv->use);
1454: if (ret >= 0)
1455: xmlBufferShrink(out->conv, ret);
1456: } else {
1457: ret = out->writecallback(out->context,
1458: (const char *)out->buffer->content, out->buffer->use);
1459: if (ret >= 0)
1460: xmlBufferShrink(out->buffer, ret);
1461: }
1462: if (ret < 0) {
1463: fprintf(stderr, "I/O: error %d flushing %d bytes\n", ret, nbchars);
1464: return(ret);
1465: }
1466: out->written += ret;
1467:
1468: #ifdef DEBUG_INPUT
1469: fprintf(stderr, "I/O: flushed %d chars\n", ret);
1470: #endif
1471: return(ret);
1.4 daniel 1472: }
1473:
1474: /*
1475: * xmlParserGetDirectory:
1476: * @filename: the path to a file
1477: *
1478: * lookup the directory for that file
1479: *
1480: * Returns a new allocated string containing the directory, or NULL.
1481: */
1482: char *
1483: xmlParserGetDirectory(const char *filename) {
1484: char *ret = NULL;
1485: char dir[1024];
1486: char *cur;
1487: char sep = '/';
1.23 daniel 1488:
1489: if (xmlInputCallbackInitialized == 0)
1490: xmlRegisterDefaultInputCallbacks();
1.4 daniel 1491:
1492: if (filename == NULL) return(NULL);
1493: #ifdef WIN32
1494: sep = '\\';
1495: #endif
1496:
1497: strncpy(dir, filename, 1023);
1498: dir[1023] = 0;
1499: cur = &dir[strlen(dir)];
1500: while (cur > dir) {
1501: if (*cur == sep) break;
1502: cur --;
1503: }
1504: if (*cur == sep) {
1505: if (cur == dir) dir[1] = 0;
1506: else *cur = 0;
1.8 daniel 1507: ret = xmlMemStrdup(dir);
1.4 daniel 1508: } else {
1509: if (getcwd(dir, 1024) != NULL) {
1510: dir[1023] = 0;
1.8 daniel 1511: ret = xmlMemStrdup(dir);
1.4 daniel 1512: }
1513: }
1514: return(ret);
1.5 daniel 1515: }
1516:
1517: /****************************************************************
1518: * *
1519: * External entities loading *
1520: * *
1521: ****************************************************************/
1522:
1523: /*
1524: * xmlDefaultExternalEntityLoader:
1525: * @URL: the URL for the entity to load
1526: * @ID: the System ID for the entity to load
1.18 daniel 1527: * @ctxt: the context in which the entity is called or NULL
1.5 daniel 1528: *
1529: * By default we don't load external entitites, yet.
1530: *
1531: * Returns a new allocated xmlParserInputPtr, or NULL.
1532: */
1533: static
1534: xmlParserInputPtr
1535: xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
1.18 daniel 1536: xmlParserCtxtPtr ctxt) {
1537: xmlParserInputPtr ret = NULL;
1.33 veillard 1538:
1.5 daniel 1539: #ifdef DEBUG_EXTERNAL_ENTITIES
1540: fprintf(stderr, "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
1541: #endif
1.18 daniel 1542: if (URL == NULL) {
1543: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1544: ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
1545: ID);
1546: return(NULL);
1547: }
1548: ret = xmlNewInputFromFile(ctxt, URL);
1549: if (ret == NULL) {
1550: if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1551: ctxt->sax->warning(ctxt, "failed to load external entity \"%s\"\n",
1552: URL);
1553: }
1554: return(ret);
1.5 daniel 1555: }
1556:
1557: static xmlExternalEntityLoader xmlCurrentExternalEntityLoader =
1558: xmlDefaultExternalEntityLoader;
1559:
1560: /*
1561: * xmlSetExternalEntityLoader:
1562: * @f: the new entity resolver function
1563: *
1564: * Changes the defaultexternal entity resolver function for the application
1565: */
1566: void
1567: xmlSetExternalEntityLoader(xmlExternalEntityLoader f) {
1568: xmlCurrentExternalEntityLoader = f;
1569: }
1570:
1571: /*
1572: * xmlGetExternalEntityLoader:
1573: *
1574: * Get the default external entity resolver function for the application
1575: *
1576: * Returns the xmlExternalEntityLoader function pointer
1577: */
1578: xmlExternalEntityLoader
1579: xmlGetExternalEntityLoader(void) {
1580: return(xmlCurrentExternalEntityLoader);
1581: }
1582:
1583: /*
1584: * xmlLoadExternalEntity:
1585: * @URL: the URL for the entity to load
1586: * @ID: the System ID for the entity to load
1.18 daniel 1587: * @ctxt: the context in which the entity is called or NULL
1.5 daniel 1588: *
1589: * Load an external entity, note that the use of this function for
1590: * unparsed entities may generate problems
1.6 daniel 1591: * TODO: a more generic External entitiy API must be designed
1.5 daniel 1592: *
1593: * Returns the xmlParserInputPtr or NULL
1594: */
1595: xmlParserInputPtr
1596: xmlLoadExternalEntity(const char *URL, const char *ID,
1.18 daniel 1597: xmlParserCtxtPtr ctxt) {
1598: return(xmlCurrentExternalEntityLoader(URL, ID, ctxt));
1.1 daniel 1599: }
1600:
Webmaster