123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814 |
- /* xmlj_io.c -
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
- This file is part of GNU Classpath.
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GNU Classpath is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
- #include "xmlj_io.h"
- #include "xmlj_error.h"
- #include "xmlj_node.h"
- #include "xmlj_sax.h"
- #include "xmlj_util.h"
- #include <math.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <libxml/xmlIO.h>
- #include <libxml/parserInternals.h>
- #include <pthread.h>
- #define MIN(a, b) (((a) < (b)) ? (a) : (b))
- #define UNSIGN(a) (((a) < 0) ? ((a) + 0x100) : (a))
- #define DETECT_BUFFER_SIZE 50
- typedef struct _OutputStreamContext
- {
- JNIEnv *env;
- jobject outputStream;
- jmethodID outputStreamWriteFunc;
- jmethodID outputStreamCloseFunc;
- }
- OutputStreamContext;
- typedef struct _InputStreamContext
- {
- JNIEnv *env;
- jobject inputStream;
- jmethodID inputStreamReadFunc;
- jmethodID inputStreamCloseFunc;
- jobject bufferByteArray;
- jint bufferLength;
- }
- InputStreamContext;
- InputStreamContext *xmljNewInputStreamContext (JNIEnv * env,
- jobject inputStream);
- void xmljFreeInputStreamContext (InputStreamContext * inContext);
- int xmljInputReadCallback (void *context, char *buffer, int len);
- int xmljInputCloseCallback (void *context);
- int xmljOutputWriteCallback (void *context, const char *buffer, int len);
- int xmljOutputCloseCallback (void *context);
- OutputStreamContext *xmljNewOutputStreamContext (JNIEnv * env,
- jobject outputStream);
- void
- xmljFreeOutputStreamContext (OutputStreamContext * outContext);
- xmlCharEncoding
- xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer);
- #ifdef LIBXML2_NEW_BUFFER
- #define GET_XML_OUTPUT_BUFFER_CONTENT(buf) (gchar *) \
- (char *) xmlOutputBufferGetContent(buf)
- #define GET_XML_OUTPUT_BUFFER_SIZE(buf) \
- xmlOutputBufferGetSize(buf)
- #else
- #define GET_XML_OUTPUT_BUFFER_CONTENT(buf) \
- (buf)->buffer->content
- #define GET_XML_OUTPUT_BUFFER_SIZE(buf) \
- (buf)->buffer->use
- #endif
- int
- xmljOutputWriteCallback (void *context, const char *buffer, int len)
- {
- OutputStreamContext *outContext;
- JNIEnv *env;
- jbyteArray byteArray;
- outContext = (OutputStreamContext *) context;
- env = outContext->env;
- byteArray = (*env)->NewByteArray (env, len);
- if (0 != byteArray)
- {
- (*env)->SetByteArrayRegion (env, byteArray, 0, len, (jbyte *) buffer);
- (*env)->CallVoidMethod (env,
- outContext->outputStream,
- outContext->outputStreamWriteFunc, byteArray);
- (*env)->DeleteLocalRef (env, byteArray);
- return (*env)->ExceptionOccurred (env) ? -1 : len;
- }
- else
- {
- /* Out of memory, signal error */
- return -1;
- }
- }
- int
- xmljOutputCloseCallback (void *context)
- {
- OutputStreamContext *outContext;
- JNIEnv *env;
- outContext = (OutputStreamContext *) context;
- env = outContext->env;
- (*env)->CallVoidMethod (env,
- outContext->outputStream,
- outContext->outputStreamCloseFunc);
- return (*env)->ExceptionOccurred (env) ? -1 : 0;
- }
- int
- xmljInputReadCallback (void *context, char *buffer, int len)
- {
- InputStreamContext *inContext;
- JNIEnv *env;
- jint nread;
- int offset;
- inContext = (InputStreamContext *) context;
- env = inContext->env;
- nread = 0;
- for (offset = 0; offset < len && nread >= 0;)
- {
- nread = (*env)->CallIntMethod (env,
- inContext->inputStream,
- inContext->inputStreamReadFunc,
- inContext->bufferByteArray,
- 0, MIN (len - offset,
- inContext->bufferLength));
- if (nread > 0)
- {
- (*env)->GetByteArrayRegion (env,
- inContext->bufferByteArray,
- 0, nread, ((jbyte *) buffer) + offset);
- offset += nread;
- }
- }
- return (*env)->ExceptionOccurred (env) ? -1 : offset;
- }
- int
- xmljInputCloseCallback (void *context)
- {
- InputStreamContext *inContext;
- JNIEnv *env;
- inContext = (InputStreamContext *) context;
- env = inContext->env;
- (*env)->CallVoidMethod (env, inContext->inputStream,
- inContext->inputStreamCloseFunc);
- return (*env)->ExceptionOccurred (env) ? -1 : 0;
- }
- InputStreamContext *
- xmljNewInputStreamContext (JNIEnv * env, jobject inputStream)
- {
- jclass inputStreamClass;
- InputStreamContext *result;
- inputStreamClass = (*env)->FindClass (env, "java/io/InputStream");
- if (inputStreamClass == NULL)
- {
- return NULL;
- }
- result = (InputStreamContext *) malloc (sizeof (InputStreamContext));
- if (result == NULL)
- {
- return NULL;
- }
- result->env = env;
- result->inputStream = inputStream;
- result->inputStreamReadFunc =
- (*env)->GetMethodID (env, inputStreamClass, "read", "([BII)I");
- result->inputStreamCloseFunc =
- (*env)->GetMethodID (env, inputStreamClass, "close", "()V");
- result->bufferLength = 4096;
- result->bufferByteArray = (*env)->NewByteArray (env, result->bufferLength);
- return result;
- }
- void
- xmljFreeInputStreamContext (InputStreamContext * inContext)
- {
- JNIEnv *env;
- env = inContext->env;
- (*env)->DeleteLocalRef (env, inContext->bufferByteArray);
- free (inContext);
- }
- OutputStreamContext *
- xmljNewOutputStreamContext (JNIEnv * env, jobject outputStream)
- {
- jclass outputStreamClass;
- OutputStreamContext *result;
- outputStreamClass = (*env)->FindClass (env, "java/io/OutputStream");
- if (outputStreamClass == NULL)
- {
- return NULL;
- }
- result = (OutputStreamContext *) malloc (sizeof (OutputStreamContext));
- if (result == NULL)
- {
- return NULL;
- }
- result->env = env;
- result->outputStream = outputStream;
- result->outputStreamWriteFunc =
- (*env)->GetMethodID (env, outputStreamClass, "write", "([B)V");
- result->outputStreamCloseFunc =
- (*env)->GetMethodID (env, outputStreamClass, "close", "()V");
- return result;
- }
- void
- xmljFreeOutputStreamContext (OutputStreamContext * outContext)
- {
- free (outContext);
- }
- SAXParseContext *
- xmljNewSAXParseContext (JNIEnv * env, jobject obj, xmlParserCtxtPtr ctx,
- jstring publicId, jstring systemId)
- {
- SAXParseContext *ret;
-
- ret = (SAXParseContext *) malloc (sizeof (SAXParseContext));
- ret->env = env;
- ret->obj = obj;
- ret->ctx = ctx;
- ret->sax = ctx->sax;
- ret->loc = NULL;
- ret->publicId = publicId;
- ret->systemId = systemId;
-
- ret->startDTD = NULL;
- ret->externalEntityDecl = NULL;
- ret->internalEntityDecl = NULL;
- ret->resolveEntity = NULL;
- ret->notationDecl = NULL;
- ret->attributeDecl = NULL;
- ret->elementDecl = NULL;
- ret->unparsedEntityDecl = NULL;
- ret->setDocumentLocator = NULL;
- ret->startDocument = NULL;
- ret->endDocument = NULL;
- ret->startElement = NULL;
- ret->endElement = NULL;
- ret->characters = NULL;
- ret->ignorableWhitespace = NULL;
- ret->processingInstruction = NULL;
- ret->comment = NULL;
- ret->cdataBlock = NULL;
- ret->warning = NULL;
- ret->error = NULL;
- ret->fatalError = NULL;
- ret->resolveURIAndOpen = NULL;
- ret->stringClass = NULL;
- return ret;
- }
- void
- xmljFreeSAXParseContext (SAXParseContext * saxCtx)
- {
- free (saxCtx);
- }
- xmlCharEncoding
- xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer)
- {
- xmlCharEncoding ret;
- jint nread;
- if (buffer == NULL)
- {
- return XML_CHAR_ENCODING_ERROR;
- }
- nread = (*env)->GetArrayLength (env, buffer);
- if (nread >= 5)
- {
- jbyte nativeBuffer[DETECT_BUFFER_SIZE + 1];
- unsigned char converted[DETECT_BUFFER_SIZE + 1];
- int i;
- memset (nativeBuffer, 0, DETECT_BUFFER_SIZE + 1);
- (*env)->GetByteArrayRegion (env, buffer, 0, nread, nativeBuffer);
- /* Convert from signed to unsigned */
- for (i = 0; i < DETECT_BUFFER_SIZE + 1; i++)
- {
- converted[i] = UNSIGN (nativeBuffer[i]);
- }
- ret = xmlDetectCharEncoding (converted, nread);
- }
- else
- {
- ret = XML_CHAR_ENCODING_NONE;
- }
- return ret;
- }
- xmlParserCtxtPtr
- xmljNewParserContext (JNIEnv * env,
- jobject inputStream,
- jbyteArray detectBuffer,
- jstring publicId,
- jstring systemId,
- jstring base,
- jboolean validate,
- jboolean coalesce,
- jboolean expandEntities,
- jboolean loadEntities)
- {
- InputStreamContext *inputContext;
- xmlCharEncoding encoding;
- xmlParserCtxtPtr ctx;
- int options;
- encoding = xmljDetectCharEncoding (env, detectBuffer);
- if (encoding != XML_CHAR_ENCODING_ERROR)
- {
- inputContext = xmljNewInputStreamContext (env, inputStream);
- if (NULL != inputContext)
- {
- /* NOTE: userdata must be NULL for DOM to work */
- ctx = xmlCreateIOParserCtxt (NULL,
- NULL,
- xmljInputReadCallback,
- xmljInputCloseCallback,
- inputContext,
- encoding);
- if (NULL != ctx)
- {
- ctx->userData = ctx;
-
- /* Set parsing options */
- options = 0;
- if (validate)
- {
- options |= XML_PARSE_DTDVALID;
- }
- if (coalesce)
- {
- options |= XML_PARSE_NOCDATA;
- }
- if (expandEntities)
- {
- options |= XML_PARSE_NOENT;
- }
- if (loadEntities)
- {
- options |= XML_PARSE_DTDLOAD;
- }
- if (xmlCtxtUseOptions (ctx, options))
- {
- xmljThrowException (env,
- "java/lang/RuntimeException",
- "Unable to set xmlParserCtxtPtr options");
- }
- if (base != NULL)
- {
- ctx->input->directory =
- (*env)->GetStringUTFChars (env, base, 0);
- }
- return ctx;
- }
- xmljFreeInputStreamContext (inputContext);
- }
- }
- return NULL;
- }
- void
- xmljFreeParserContext (xmlParserCtxtPtr ctx)
- {
- InputStreamContext *inputStreamContext = NULL;
- if (ctx->input != NULL && ctx->input->buf != NULL)
- {
- inputStreamContext
- = (InputStreamContext *) ctx->input->buf->context;
-
- }
- xmlFreeParserCtxt (ctx);
- if (inputStreamContext != NULL)
- {
- xmljFreeInputStreamContext (inputStreamContext);
- }
- }
- xmlDocPtr
- xmljParseDocument (JNIEnv * env,
- jobject self,
- jobject in,
- jbyteArray detectBuffer,
- jstring publicId,
- jstring systemId,
- jstring base,
- jboolean validate,
- jboolean coalesce,
- jboolean expandEntities,
- jboolean contentHandler,
- jboolean dtdHandler,
- jboolean entityResolver,
- jboolean errorHandler,
- jboolean declarationHandler,
- jboolean lexicalHandler,
- int mode)
- {
- xmlParserCtxtPtr ctx;
- SAXParseContext *saxCtx;
- xmlSAXHandlerPtr sax;
- ctx = xmljNewParserContext (env, in, detectBuffer, publicId, systemId, base,
- validate, coalesce, expandEntities,
- entityResolver);
- if (ctx != NULL)
- {
- saxCtx = xmljNewSAXParseContext (env, self, ctx, publicId, systemId);
- if (saxCtx != NULL)
- {
- sax = xmljNewSAXHandler (contentHandler,
- dtdHandler,
- entityResolver,
- errorHandler,
- declarationHandler,
- lexicalHandler);
- if (sax != NULL)
- {
- return xmljParseDocument2 (env,
- ctx,
- saxCtx,
- sax,
- mode);
- }
- xmljFreeSAXParseContext (saxCtx);
- }
- xmljFreeParserContext (ctx);
- }
- if (!(*env)->ExceptionOccurred (env))
- {
- xmljThrowException (env, "java/io/IOException",
- "Unable to create parser context");
- }
- return NULL;
- }
- xmlDocPtr
- xmljParseDocument2 (JNIEnv * env,
- xmlParserCtxtPtr ctx,
- SAXParseContext *saxCtx,
- xmlSAXHandlerPtr sax,
- int mode)
- {
- xmlSAXHandlerPtr orig;
- xmlDocPtr doc;
- int ret;
-
- ctx->_private = saxCtx;
- ctx->userData = ctx;
- orig = ctx->sax;
- ctx->sax = sax;
-
- xmljSetThreadContext (saxCtx);
- ret = xmlParseDocument (ctx);
- doc = ctx->myDoc;
- if (ret || !doc)
- {
- const char *msg = ctx->lastError.message;
- switch (mode)
- {
- case 0:
- xmljSAXFatalError (ctx, msg);
- break;
- case 1:
- xmljThrowDOMException (env, ret, msg);
- break;
- case 2:
- xmljThrowException (env,
- "javax/xml/transform/TransformerException",
- msg);
- }
- }
-
- xmljClearThreadContext ();
-
- ctx->sax = orig;
- free(sax);
- xmljFreeSAXParseContext (saxCtx);
- xmljFreeParserContext (ctx);
- xmljClearStringCache ();
- return doc;
- }
- xmlParserInputPtr
- xmljNewParserInput (JNIEnv * env,
- jobject inputStream,
- jbyteArray detectBuffer,
- xmlParserCtxtPtr parserContext)
- {
- xmlParserInputPtr ret;
- xmlParserInputBufferPtr input;
- xmlCharEncoding encoding;
- encoding = xmljDetectCharEncoding (env, detectBuffer);
- if (encoding != XML_CHAR_ENCODING_ERROR)
- {
- input = xmljNewParserInputBuffer (env, inputStream, encoding);
- if (input != NULL)
- {
- ret = xmlNewIOInputStream (parserContext, input, encoding);
- return ret;
- }
- xmlFreeParserInputBuffer (input);
- }
- return NULL;
- }
- xmlParserInputBufferPtr
- xmljNewParserInputBuffer (JNIEnv * env,
- jobject inputStream, xmlCharEncoding encoding)
- {
- xmlParserInputBufferPtr ret;
- InputStreamContext *inputContext;
- inputContext = xmljNewInputStreamContext (env, inputStream);
- if (NULL != inputContext)
- {
- ret = xmlParserInputBufferCreateIO (&xmljInputReadCallback,
- &xmljInputCloseCallback,
- inputContext, encoding);
- if (ret != NULL)
- return ret;
- xmljFreeInputStreamContext (inputContext);
- }
- return NULL;
- }
- void
- xmljSaveFileToJavaOutputStream (JNIEnv * env, jobject outputStream,
- xmlDocPtr tree,
- const char *outputEncodingName)
- {
- OutputStreamContext *outputContext =
- xmljNewOutputStreamContext (env, outputStream);
- xmlCharEncoding outputEncoding = xmlParseCharEncoding (outputEncodingName);
- xmlOutputBufferPtr outputBuffer =
- xmlOutputBufferCreateIO (xmljOutputWriteCallback,
- xmljOutputCloseCallback,
- outputContext,
- xmlGetCharEncodingHandler (outputEncoding));
- /* Write result to output stream */
- xmlSaveFileTo (outputBuffer, tree, outputEncodingName);
- xmljFreeOutputStreamContext (outputContext);
- }
- /*
- jobject
- xmljResolveURI (SaxErrorContext * saxErrorContext,
- const char *URL, const char *ID)
- {
- JNIEnv *env = saxErrorContext->env;
- jstring hrefString = (*env)->NewStringUTF (env, URL);
- jstring baseString = saxErrorContext->systemId;
- jobject sourceWrapper = (*env)->CallObjectMethod (env,
- saxErrorContext->
- saxErrorAdapter,
- saxErrorContext->
- resolveURIMethodID,
- hrefString,
- baseString);
- (*env)->DeleteLocalRef (env, hrefString);
- if (NULL == sourceWrapper)
- {
- return NULL;
- }
- else
- {
- jobject sourceInputStream = (*env)->CallObjectMethod (env,
- sourceWrapper,
- saxErrorContext->
- getInputStreamMethodID);
- (*env)->DeleteLocalRef (env, sourceWrapper);
- if ((*env)->ExceptionOccurred (env))
- {
- -* Report to ErrorAdapter here? *-
- return NULL;
- }
- return sourceInputStream;
- }
- }*/
- xmlDocPtr
- xmljResolveURIAndOpen (SAXParseContext *saxContext,
- const char *URL,
- const char *ID)
- {
- jobject libxmlDocument;
- xmlDocPtr doc;
- JNIEnv *env = saxContext->env;
- jstring hrefString = (*env)->NewStringUTF (env, URL);
- jstring baseString = saxContext->systemId;
- if (saxContext->resolveURIAndOpen == NULL)
- {
- jclass cls = (*env)->GetObjectClass (env, saxContext->obj);
- saxContext->resolveURIAndOpen =
- (*env)->GetMethodID (env, cls, "resolveURIAndOpen",
- "Ljava/lang/String;Ljava/lang/String)Lgnu/xml/libxmlj/transform/LibxmlDocument;");
- }
- libxmlDocument =
- (*env)->CallObjectMethod (env,
- saxContext->obj,
- saxContext->resolveURIAndOpen,
- hrefString,
- baseString);
- doc = (xmlDocPtr) xmljGetNodeID (env, libxmlDocument);
- (*env)->DeleteLocalRef (env, libxmlDocument);
- if ((*env)->ExceptionOccurred (env))
- {
- /* Report to ErrorAdapter here? */
- return NULL;
- }
- else
- {
- return doc;
- }
- }
- /*xmlParserInputPtr
- xmljLoadExternalEntity (const char *URL, const char *ID,
- xmlParserCtxtPtr ctxt)
- {
- SaxErrorContext *saxErrorContext = xmljGetThreadContext ();
- JNIEnv *env = saxErrorContext->env;
- jstring hrefString = (*env)->NewStringUTF (env, URL);
- jstring baseString = saxErrorContext->systemId;
- jobject sourceWrapper = (*env)->CallObjectMethod (env,
- saxErrorContext->
- saxErrorAdapter,
- saxErrorContext->
- resolveURIMethodID,
- hrefString,
- baseString);
- (*env)->DeleteLocalRef (env, hrefString);
- if (NULL == sourceWrapper)
- {
- return NULL;
- }
- else
- {
- InputStreamContext *inputContext;
- xmlParserInputBufferPtr inputBuffer;
- xmlParserInputPtr inputStream;
- jobject sourceInputStream = (*env)->CallObjectMethod (env,
- sourceWrapper,
- saxErrorContext->
- getInputStreamMethodID);
- (*env)->DeleteLocalRef (env, sourceWrapper);
- if ((*env)->ExceptionOccurred (env))
- {
- -* Report to ErrorAdapter *-
- return NULL;
- }
- inputContext = xmljNewInputStreamContext (env, sourceInputStream);
- inputBuffer
- = xmlParserInputBufferCreateIO (xmljInputReadCallback,
- xmljInputCloseCallback,
- inputContext, XML_CHAR_ENCODING_NONE);
- inputStream = xmlNewInputStream (ctxt);
- if (inputStream == NULL)
- {
- return (NULL);
- }
- inputStream->filename = NULL;
- inputStream->directory = NULL;
- inputStream->buf = inputBuffer;
- inputStream->base = GET_XML_OUTPUT_BUFFER_CONTENT (inputStream->buf);
- inputStream->cur = GET_XML_OUTPUT_BUFFER_CONTENT (inputStream->buf);
- inputStream->end =
- &inputStream->base[GET_XML_OUTPUT_BUFFER_SIZE (inputStream->buf)];
- if ((ctxt->directory == NULL) && (inputStream->directory != NULL))
- ctxt->directory =
- (char *) xmlStrdup ((const xmlChar *) inputStream->directory);
- return (inputStream);
- }
- }*/
- /* Key for the thread-specific buffer */
- static pthread_key_t thread_context_key;
- /* Once-only initialisation of the key */
- static pthread_once_t thread_context_once = PTHREAD_ONCE_INIT;
- static void
- thread_context_key_alloc (void);
- /* Allocate the key */
- static void
- thread_context_key_alloc ()
- {
- pthread_key_create (&thread_context_key, NULL);
- }
- void
- xmljSetThreadContext (SAXParseContext * context)
- {
- pthread_once (&thread_context_once, thread_context_key_alloc);
- pthread_setspecific (thread_context_key, context);
- }
- void
- xmljClearThreadContext (void)
- {
- pthread_setspecific (thread_context_key, NULL);
- }
- /* Return the thread-specific buffer */
- SAXParseContext *
- xmljGetThreadContext (void)
- {
- return (SAXParseContext *) pthread_getspecific (thread_context_key);
- }
|