Re: [xml] PATCH: implement xmlSaveToBuffer()



Daniel,

  The xmlBuffer should be used when you don't dump to an I/O channel.
Then the user just want a memory string and an xmlBuffer makes way more sense
than an xmlOutputBuffer in that case.

See the attached patch. I took your original suggestion and used the original prototype for xmlSaveToBuffer(). I now create an xmlOutputBuffer from the xmlBuffer. This is done by a new function in xmlIO.c: xmlOutputBufferCreateBuffer(). It uses xmlAllocOutputBuffer() to create a new output buffer and then replaces either .buffer or .conv by the user supplied buffer. This requires me to free one buffer that was just allocated. This isn't ideal but I thought this would be better than either duplicating xmlAllocOutputBuffer() or changing it signature to accept a flag indicating that it should not allocate buffers.

In order to ensure that xmlFreeSaveCtxt() does not free the user supplied buffer, I had to extend xmlSaveCtxt with two members: "user_buffer" and "user_conv" to indicate that buffer or conv respectively are allocated by the user and should not be freed. I didn't feel very confident about extending this structure but I could not come up with something else. Did you have something else in mind?

Regards,
Geert
diff -ur libxml2-2.6.22.orig/include/libxml/xmlIO.h libxml2-2.6.22/include/libxml/xmlIO.h
--- libxml2-2.6.22.orig/include/libxml/xmlIO.h  2005-07-27 22:59:37.000000000 +0200
+++ libxml2-2.6.22/include/libxml/xmlIO.h       2005-11-06 22:51:07.000000000 +0100
@@ -149,6 +149,8 @@
     xmlBufferPtr conv;      /* if encoder != NULL buffer for output */
     int written;            /* total number of byte written */
     int error;
+    int user_buffer;        /* User allocated buffer */
+    int user_conv;          /* User allocated conv */
 };
 #endif /* LIBXML_OUTPUT_ENABLED */
 
@@ -232,6 +234,10 @@
                                         xmlCharEncodingHandlerPtr encoder);
 
 XMLPUBFUN xmlOutputBufferPtr XMLCALL
+       xmlOutputBufferCreateBuffer     (xmlBufferPtr buffer,
+                                        xmlCharEncodingHandlerPtr encoder);
+
+XMLPUBFUN xmlOutputBufferPtr XMLCALL
        xmlOutputBufferCreateFd         (int fd,
                                         xmlCharEncodingHandlerPtr encoder);
 
diff -ur libxml2-2.6.22.orig/include/libxml/xmlsave.h libxml2-2.6.22/include/libxml/xmlsave.h
--- libxml2-2.6.22.orig/include/libxml/xmlsave.h        2005-09-12 17:34:25.000000000 +0200
+++ libxml2-2.6.22/include/libxml/xmlsave.h     2005-11-06 22:49:37.000000000 +0100
@@ -45,14 +45,12 @@
                xmlSaveToFilename       (const char *filename,
                                         const char *encoding,
                                         int options);
-/******
-  Not yet implemented.
 
 XMLPUBFUN xmlSaveCtxtPtr XMLCALL
                xmlSaveToBuffer         (xmlBufferPtr buffer,
                                         const char *encoding,
                                         int options);
- ******/
+
 XMLPUBFUN xmlSaveCtxtPtr XMLCALL
                xmlSaveToIO             (xmlOutputWriteCallback iowrite,
                                         xmlOutputCloseCallback ioclose,
diff -ur libxml2-2.6.22.orig/xmlIO.c libxml2-2.6.22/xmlIO.c
--- libxml2-2.6.22.orig/xmlIO.c 2005-08-05 15:53:39.000000000 +0200
+++ libxml2-2.6.22/xmlIO.c      2005-11-06 23:07:09.000000000 +0100
@@ -2071,6 +2071,8 @@
     ret->closecallback = NULL;
     ret->context = NULL;
     ret->written = 0;
+    ret->user_buffer = 0;
+    ret->user_conv = 0;
 
     return(ret);
 }
@@ -2128,14 +2130,14 @@
         err_rc = out->closecallback(out->context);
     }
     written = out->written;
-    if (out->conv) {
+    if (out->conv && !out->user_conv) {
         xmlBufferFree(out->conv);
         out->conv = NULL;
     }
     if (out->encoder != NULL) {
         xmlCharEncCloseFunc(out->encoder);
     }
-    if (out->buffer != NULL) {
+    if (out->buffer && !out->user_buffer) {
         xmlBufferFree(out->buffer);
         out->buffer = NULL;
     }
@@ -2436,6 +2438,39 @@
 
     return(ret);
 }
+
+/**
+ * xmlOutputBufferCreateBuffer:
+ * @buffer:  a xmlBufferPtr
+ * @encoder:  the encoding converter or NULL
+ *
+ * Create a buffered output for the progressive saving to a xmlBuffer
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateBuffer(xmlBufferPtr buffer,
+                            xmlCharEncodingHandlerPtr encoder) {
+    xmlOutputBufferPtr ret;
+
+    if (buffer == NULL) return(NULL);
+
+    ret = xmlAllocOutputBuffer(encoder);
+    if (ret != NULL) {
+        if (ret->encoder == NULL) {
+            if (ret->buffer) xmlBufferFree(ret->buffer);
+            ret->buffer = buffer;
+            ret->user_buffer = 1;
+        } else {
+            if (ret->conv) xmlBufferFree(ret->conv);
+            ret->conv = buffer;
+            ret->user_conv = 1;
+        }
+    }
+
+    return(ret);
+}
+
 #endif /* LIBXML_OUTPUT_ENABLED */
 
 /**
diff -ur libxml2-2.6.22.orig/xmlsave.c libxml2-2.6.22/xmlsave.c
--- libxml2-2.6.22.orig/xmlsave.c       2005-09-12 17:35:07.000000000 +0200
+++ libxml2-2.6.22/xmlsave.c    2005-11-06 23:06:09.000000000 +0100
@@ -1473,13 +1473,36 @@
  * with the encoding and the options given
  *
  * Returns a new serialization context or NULL in case of error.
+ */
+
 xmlSaveCtxtPtr
 xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
 {
-    TODO
-    return(NULL);
+    xmlSaveCtxtPtr ret;
+    xmlOutputBufferPtr out_buff;
+    xmlCharEncodingHandlerPtr handler;
+
+    ret = xmlNewSaveCtxt(encoding, options);
+    if (ret == NULL) return(NULL);
+
+    if (encoding != NULL) {
+        handler = xmlFindCharEncodingHandler(encoding);
+        if (handler == NULL) {
+            xmlFree(ret);
+            return(NULL);
+        }
+    } else
+        handler = NULL;
+    out_buff = xmlOutputBufferCreateBuffer(buffer, handler);
+    if (out_buff == NULL) {
+        xmlFree(ret);
+        if (handler) xmlCharEncCloseFunc(handler);
+        return(NULL);
+    }
+
+    ret->buf = out_buff;
+    return(ret);
 }
- */
 
 /**
  * xmlSaveToIO:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]