24
24
#include "ext/standard/info.h"
25
25
#include "php_xmlwriter.h"
26
26
#include "php_xmlwriter_arginfo.h"
27
+ #include "zend_smart_str.h"
27
28
28
29
static zend_class_entry * xmlwriter_class_entry_ce ;
29
30
@@ -47,11 +48,9 @@ static zend_object_handlers xmlwriter_object_handlers;
47
48
static zend_always_inline void xmlwriter_destroy_libxml_objects (ze_xmlwriter_object * intern )
48
49
{
49
50
if (intern -> ptr ) {
51
+ /* Note: this call will also free the output pointer. */
50
52
xmlFreeTextWriter (intern -> ptr );
51
53
intern -> ptr = NULL ;
52
- }
53
- if (intern -> output ) {
54
- xmlBufferFree (intern -> output );
55
54
intern -> output = NULL ;
56
55
}
57
56
}
@@ -178,14 +177,14 @@ static char *_xmlwriter_get_valid_file_path(char *source, char *resolved_path, i
178
177
}
179
178
/* }}} */
180
179
181
- static void xml_writer_create_static (INTERNAL_FUNCTION_PARAMETERS , xmlTextWriterPtr writer , xmlBufferPtr output )
180
+ static void xml_writer_create_static (INTERNAL_FUNCTION_PARAMETERS , xmlTextWriterPtr writer , smart_str * output )
182
181
{
183
182
if (object_init_with_constructor (return_value , Z_CE_P (ZEND_THIS ), 0 , NULL , NULL ) == SUCCESS ) {
184
183
ze_xmlwriter_object * intern = Z_XMLWRITER_P (return_value );
185
184
intern -> ptr = writer ;
186
185
intern -> output = output ;
187
186
} else {
188
- xmlBufferFree ( output );
187
+ // output is freed by writer, so we don't need to free it here.
189
188
xmlFreeTextWriter (writer );
190
189
}
191
190
}
@@ -877,11 +876,45 @@ PHP_METHOD(XMLWriter, toUri)
877
876
xml_writer_create_static (INTERNAL_FUNCTION_PARAM_PASSTHRU , writer , NULL );
878
877
}
879
878
879
+ static int xml_writer_stream_write_memory (void * context , const char * buffer , int len )
880
+ {
881
+ smart_str * output = context ;
882
+ smart_str_appendl (output , buffer , len );
883
+ return len ;
884
+ }
885
+
886
+ static int xml_writer_stream_close_memory (void * context )
887
+ {
888
+ smart_str * output = context ;
889
+ smart_str_free_ex (output , false);
890
+ efree (output );
891
+ return 0 ;
892
+ }
893
+
894
+ static xmlTextWriterPtr xml_writer_create_in_memory (smart_str * * output_ptr )
895
+ {
896
+ smart_str * output = emalloc (sizeof (* output ));
897
+ memset (output , 0 , sizeof (* output ));
898
+
899
+ xmlOutputBufferPtr output_buffer = xmlOutputBufferCreateIO (xml_writer_stream_write_memory , xml_writer_stream_close_memory , output , NULL );
900
+ if (output_buffer == NULL ) {
901
+ efree (output );
902
+ return NULL ;
903
+ }
904
+
905
+ xmlTextWriterPtr writer = xmlNewTextWriter (output_buffer );
906
+ if (!writer ) {
907
+ /* This call will free output too. */
908
+ xmlOutputBufferClose (output_buffer );
909
+ return NULL ;
910
+ }
911
+ * output_ptr = output ;
912
+ return writer ;
913
+ }
914
+
880
915
/* {{{ Create new xmlwriter using memory for string output */
881
916
PHP_FUNCTION (xmlwriter_open_memory )
882
917
{
883
- xmlTextWriterPtr ptr ;
884
- xmlBufferPtr buffer ;
885
918
zval * self = getThis ();
886
919
ze_xmlwriter_object * ze_obj = NULL ;
887
920
@@ -894,28 +927,21 @@ PHP_FUNCTION(xmlwriter_open_memory)
894
927
ze_obj = Z_XMLWRITER_P (self );
895
928
}
896
929
897
- buffer = xmlBufferCreate ();
898
-
899
- if (buffer == NULL ) {
900
- php_error_docref (NULL , E_WARNING , "Unable to create output buffer" );
901
- RETURN_FALSE ;
902
- }
903
-
904
- ptr = xmlNewTextWriterMemory (buffer , 0 );
930
+ smart_str * output ;
931
+ xmlTextWriterPtr ptr = xml_writer_create_in_memory (& output );
905
932
if (! ptr ) {
906
- xmlBufferFree (buffer );
907
933
RETURN_FALSE ;
908
934
}
909
935
910
936
if (self ) {
911
937
xmlwriter_destroy_libxml_objects (ze_obj );
912
938
ze_obj -> ptr = ptr ;
913
- ze_obj -> output = buffer ;
939
+ ze_obj -> output = output ;
914
940
RETURN_TRUE ;
915
941
} else {
916
942
ze_obj = php_xmlwriter_fetch_object (xmlwriter_object_new (xmlwriter_class_entry_ce ));
917
943
ze_obj -> ptr = ptr ;
918
- ze_obj -> output = buffer ;
944
+ ze_obj -> output = output ;
919
945
RETURN_OBJ (& ze_obj -> std );
920
946
}
921
947
@@ -926,17 +952,16 @@ PHP_METHOD(XMLWriter, toMemory)
926
952
{
927
953
ZEND_PARSE_PARAMETERS_NONE ();
928
954
929
- xmlBufferPtr buffer = xmlBufferCreate () ;
930
- xmlTextWriterPtr writer = xmlNewTextWriterMemory ( buffer , 0 );
955
+ smart_str * output ;
956
+ xmlTextWriterPtr writer = xml_writer_create_in_memory ( & output );
931
957
932
958
/* No need for an explicit buffer check as this will fail on a NULL buffer. */
933
959
if (!writer ) {
934
- xmlBufferFree (buffer );
935
960
zend_throw_error (NULL , "Could not construct libxml writer" );
936
961
RETURN_THROWS ();
937
962
}
938
963
939
- xml_writer_create_static (INTERNAL_FUNCTION_PARAM_PASSTHRU , writer , buffer );
964
+ xml_writer_create_static (INTERNAL_FUNCTION_PARAM_PASSTHRU , writer , output );
940
965
}
941
966
942
967
static int xml_writer_stream_write (void * context , const char * buffer , int len )
@@ -992,7 +1017,6 @@ PHP_METHOD(XMLWriter, toStream)
992
1017
/* {{{ php_xmlwriter_flush */
993
1018
static void php_xmlwriter_flush (INTERNAL_FUNCTION_PARAMETERS , int force_string ) {
994
1019
xmlTextWriterPtr ptr ;
995
- xmlBufferPtr buffer ;
996
1020
bool empty = 1 ;
997
1021
int output_bytes ;
998
1022
zval * self ;
@@ -1002,16 +1026,18 @@ static void php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS, int force_string)
1002
1026
}
1003
1027
XMLWRITER_FROM_OBJECT (ptr , self );
1004
1028
1005
- buffer = Z_XMLWRITER_P (self )-> output ;
1006
- if (force_string == 1 && buffer == NULL ) {
1029
+ smart_str * output = Z_XMLWRITER_P (self )-> output ;
1030
+ if (force_string == 1 && output == NULL ) {
1007
1031
RETURN_EMPTY_STRING ();
1008
1032
}
1009
1033
output_bytes = xmlTextWriterFlush (ptr );
1010
- if (buffer ) {
1011
- const xmlChar * content = xmlBufferContent (buffer );
1012
- RETVAL_STRING ((const char * ) content );
1034
+ if (output ) {
1013
1035
if (empty ) {
1014
- xmlBufferEmpty (buffer );
1036
+ RETURN_STR (smart_str_extract (output ));
1037
+ } else if (smart_str_get_len (output ) > 0 ) {
1038
+ RETURN_NEW_STR (zend_string_dup (output -> s , false));
1039
+ } else {
1040
+ RETURN_EMPTY_STRING ();
1015
1041
}
1016
1042
} else {
1017
1043
RETVAL_LONG (output_bytes );
0 commit comments