]> granicus.if.org Git - php/commitdiff
Improve chunked output buffering - the output handler now knows at which stage it is
authorZeev Suraski <zeev@php.net>
Sun, 4 Mar 2001 01:09:36 +0000 (01:09 +0000)
committerZeev Suraski <zeev@php.net>
Sun, 4 Mar 2001 01:09:36 +0000 (01:09 +0000)
ext/sablot/sablot.c
ext/standard/output.c
ext/standard/php_output.h
main/output.c
main/php_output.h

index edddb53289b66477e74278886107e87b986a201d..4544ebc163f705a72bca0256350822975ab1a7fa 100644 (file)
@@ -348,7 +348,7 @@ PHP_FUNCTION(xslt_output_endtransform)
      * current output buffer (so we don't send data twice) 
      */
     if (tRes)
-        php_end_ob_buffer(0);
+        php_end_ob_buffer(0, 0);
     
     PUTS(tRes);
     
@@ -363,7 +363,7 @@ PHP_FUNCTION(xslt_output_endtransform)
     if (tRes)
         SablotFree(tRes);
     else
-        php_end_ob_buffer(1);
+        php_end_ob_buffer(1, 0);
 }
 /* }}} */
 
index 05646ea1f43f795a22c36da922aba693b15e5d4a..e484ea777c62c410bd91abe6a2d4b8a959fd9d0f 100644 (file)
@@ -68,11 +68,16 @@ PHP_GINIT_FUNCTION(output)
 PHPAPI void php_output_startup()
 {
        OLS_FETCH();
+       ELS_FETCH();
 
        OG(php_body_write) = php_ub_body_write;
        OG(php_header_write) = sapi_module.ub_write;
        OG(nesting_level) = 0;
        OG(lock) = 0;
+
+       REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT);
+       REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_CONT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_END, CONST_CS | CONST_PERSISTENT);
 }
 
 PHPAPI int php_body_write(const char *str, uint str_length)
@@ -102,7 +107,7 @@ PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size)
 
 
 /* End output buffering (one level) */
-PHPAPI void php_end_ob_buffer(int send_buffer)
+PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush)
 {
        char *final_buffer=NULL;
        int final_buffer_length=0;
@@ -116,8 +121,9 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
        }
 
        if (OG(active_ob_buffer).output_handler) {
-               zval **params[1];
+               zval **params[2];
                zval *orig_buffer;
+               zval *z_status;
                CLS_FETCH();
 
                ALLOC_INIT_ZVAL(orig_buffer);
@@ -126,9 +132,23 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
                orig_buffer->type = IS_STRING;
                orig_buffer->refcount=2;        /* don't let call_user_function() destroy our buffer */
 
+               ALLOC_INIT_ZVAL(z_status);
+               Z_TYPE_P(z_status) = IS_LONG;
+               Z_LVAL_P(z_status) = 0;
+               if (!OG(active_ob_buffer).status & PHP_OUTPUT_HANDLER_START) {
+                       /* our first call */
+                       Z_LVAL_P(z_status) |= PHP_OUTPUT_HANDLER_START;
+               }
+               if (just_flush) {
+                       Z_LVAL_P(z_status) |= PHP_OUTPUT_HANDLER_CONT;
+               } else {
+                       Z_LVAL_P(z_status) |= PHP_OUTPUT_HANDLER_END;
+               }
+
                params[0] = &orig_buffer;
+               params[1] = &z_status;
                OG(lock) = 1;
-               if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 1, params, 1, NULL)==SUCCESS) {
+               if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 2, params, 1, NULL)==SUCCESS) {
                        convert_to_string_ex(&alternate_buffer);
                        final_buffer = alternate_buffer->value.str.val;
                        final_buffer_length = alternate_buffer->value.str.len;
@@ -140,6 +160,7 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
                } else {
                        orig_buffer->refcount-=2;
                }
+               zval_ptr_dtor(&z_status);
        }
 
        if (!final_buffer) {
@@ -157,16 +178,18 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
 
        to_be_destroyed_buffer = OG(active_ob_buffer).buffer;
 
-       if (OG(nesting_level)>1) { /* restore previous buffer */
-               php_ob_buffer *ob_buffer_p;
+       if (!just_flush) {
+               if (OG(nesting_level)>1) { /* restore previous buffer */
+                       php_ob_buffer *ob_buffer_p;
 
-               zend_stack_top(&OG(ob_buffers), (void **) &ob_buffer_p);
-               OG(active_ob_buffer) = *ob_buffer_p;
-               zend_stack_del_top(&OG(ob_buffers));
-               if (OG(nesting_level)==2) { /* destroy the stack */
-                       zend_stack_destroy(&OG(ob_buffers));
+                       zend_stack_top(&OG(ob_buffers), (void **) &ob_buffer_p);
+                       OG(active_ob_buffer) = *ob_buffer_p;
+                       zend_stack_del_top(&OG(ob_buffers));
+                       if (OG(nesting_level)==2) { /* destroy the stack */
+                               zend_stack_destroy(&OG(ob_buffers));
+                       }
                }
-       } 
+       }
 
        if (send_buffer) {
                OG(php_body_write)(final_buffer, final_buffer_length);
@@ -176,19 +199,25 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
                zval_ptr_dtor(&alternate_buffer);
        }
 
-       efree(to_be_destroyed_buffer);
+       if (!just_flush) {
+               efree(to_be_destroyed_buffer);
 
-       OG(nesting_level)--;
+               OG(nesting_level)--;
+       } else {
+               OG(active_ob_buffer).text_length = 0;
+               OG(active_ob_buffer).status |= PHP_OUTPUT_HANDLER_START;
+               OG(php_body_write) = php_b_body_write;
+       }
 }
 
 
 /* End output buffering (all buffers) */
-PHPAPI void php_end_ob_buffers(int send_buffer)
+PHPAPI void php_end_ob_buffers(zend_bool send_buffer)
 {
        OLS_FETCH();
 
        while (OG(nesting_level)!=0) {
-               php_end_ob_buffer(send_buffer);
+               php_end_ob_buffer(send_buffer, 0);
        }
 }
 
@@ -197,7 +226,7 @@ PHPAPI void php_start_implicit_flush()
 {
        OLS_FETCH();
 
-       php_end_ob_buffer(1);           /* Switch out of output buffering if we're in it */
+       php_end_ob_buffer(1, 0);                /* Switch out of output buffering if we're in it */
        OG(implicit_flush)=1;
 }
 
@@ -245,6 +274,7 @@ static void php_ob_init(uint initial_size, uint block_size, zval *output_handler
        OG(active_ob_buffer).text_length = 0;
        OG(active_ob_buffer).output_handler = output_handler;
        OG(active_ob_buffer).chunk_size = chunk_size;
+       OG(active_ob_buffer).status = 0;
 }
 
 
@@ -270,8 +300,7 @@ static void php_ob_append(const char *text, uint text_length)
                if (output_handler) {
                        output_handler->refcount++;
                }
-               php_end_ob_buffer(1);
-               php_start_ob_buffer(output_handler, chunk_size);
+               php_end_ob_buffer(1, 1);
                return;
        }
 }
@@ -453,7 +482,7 @@ PHP_FUNCTION(ob_start)
    Flush (send) the output buffer, and turn off output buffering */
 PHP_FUNCTION(ob_end_flush)
 {
-       php_end_ob_buffer(1);
+       php_end_ob_buffer(1, 0);
 }
 /* }}} */
 
@@ -462,7 +491,7 @@ PHP_FUNCTION(ob_end_flush)
    Clean (erase) the output buffer, and turn off output buffering */
 PHP_FUNCTION(ob_end_clean)
 {
-       php_end_ob_buffer(0);
+       php_end_ob_buffer(0, 0);
 }
 /* }}} */
 
index d18736796aacbc4e13df68f1a9a25deec55f38c0..d7d617ba1257bd3464e10ede83ee5bc19fae3c60 100644 (file)
@@ -27,8 +27,8 @@ PHPAPI void php_output_startup(void);
 PHPAPI int  php_body_write(const char *str, uint str_length);
 PHPAPI int  php_header_write(const char *str, uint str_length);
 PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size);
-PHPAPI void php_end_ob_buffer(int send_buffer);
-PHPAPI void php_end_ob_buffers(int send_buffer);
+PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush);
+PHPAPI void php_end_ob_buffers(zend_bool send_buffer);
 PHPAPI int php_ob_get_buffer(pval *p);
 PHPAPI int php_ob_get_length(pval *p);
 PHPAPI void php_start_implicit_flush(void);
@@ -52,6 +52,7 @@ typedef struct _php_ob_buffer {
        int block_size;
        zval *output_handler;
        uint chunk_size;
+       int status;
 } php_ob_buffer;
 
 typedef struct _php_output_globals {
@@ -81,5 +82,8 @@ ZEND_API extern int output_globals_id;
 ZEND_API extern php_output_globals output_globals;
 #endif
 
+#define PHP_OUTPUT_HANDLER_START               (1<<0)
+#define PHP_OUTPUT_HANDLER_CONT                        (1<<1)
+#define PHP_OUTPUT_HANDLER_END                 (1<<2)
 
 #endif /* PHP_OUTPUT_H */
index 05646ea1f43f795a22c36da922aba693b15e5d4a..e484ea777c62c410bd91abe6a2d4b8a959fd9d0f 100644 (file)
@@ -68,11 +68,16 @@ PHP_GINIT_FUNCTION(output)
 PHPAPI void php_output_startup()
 {
        OLS_FETCH();
+       ELS_FETCH();
 
        OG(php_body_write) = php_ub_body_write;
        OG(php_header_write) = sapi_module.ub_write;
        OG(nesting_level) = 0;
        OG(lock) = 0;
+
+       REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT);
+       REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_CONT, CONST_CS | CONST_PERSISTENT);
+       REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_END, CONST_CS | CONST_PERSISTENT);
 }
 
 PHPAPI int php_body_write(const char *str, uint str_length)
@@ -102,7 +107,7 @@ PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size)
 
 
 /* End output buffering (one level) */
-PHPAPI void php_end_ob_buffer(int send_buffer)
+PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush)
 {
        char *final_buffer=NULL;
        int final_buffer_length=0;
@@ -116,8 +121,9 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
        }
 
        if (OG(active_ob_buffer).output_handler) {
-               zval **params[1];
+               zval **params[2];
                zval *orig_buffer;
+               zval *z_status;
                CLS_FETCH();
 
                ALLOC_INIT_ZVAL(orig_buffer);
@@ -126,9 +132,23 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
                orig_buffer->type = IS_STRING;
                orig_buffer->refcount=2;        /* don't let call_user_function() destroy our buffer */
 
+               ALLOC_INIT_ZVAL(z_status);
+               Z_TYPE_P(z_status) = IS_LONG;
+               Z_LVAL_P(z_status) = 0;
+               if (!OG(active_ob_buffer).status & PHP_OUTPUT_HANDLER_START) {
+                       /* our first call */
+                       Z_LVAL_P(z_status) |= PHP_OUTPUT_HANDLER_START;
+               }
+               if (just_flush) {
+                       Z_LVAL_P(z_status) |= PHP_OUTPUT_HANDLER_CONT;
+               } else {
+                       Z_LVAL_P(z_status) |= PHP_OUTPUT_HANDLER_END;
+               }
+
                params[0] = &orig_buffer;
+               params[1] = &z_status;
                OG(lock) = 1;
-               if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 1, params, 1, NULL)==SUCCESS) {
+               if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 2, params, 1, NULL)==SUCCESS) {
                        convert_to_string_ex(&alternate_buffer);
                        final_buffer = alternate_buffer->value.str.val;
                        final_buffer_length = alternate_buffer->value.str.len;
@@ -140,6 +160,7 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
                } else {
                        orig_buffer->refcount-=2;
                }
+               zval_ptr_dtor(&z_status);
        }
 
        if (!final_buffer) {
@@ -157,16 +178,18 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
 
        to_be_destroyed_buffer = OG(active_ob_buffer).buffer;
 
-       if (OG(nesting_level)>1) { /* restore previous buffer */
-               php_ob_buffer *ob_buffer_p;
+       if (!just_flush) {
+               if (OG(nesting_level)>1) { /* restore previous buffer */
+                       php_ob_buffer *ob_buffer_p;
 
-               zend_stack_top(&OG(ob_buffers), (void **) &ob_buffer_p);
-               OG(active_ob_buffer) = *ob_buffer_p;
-               zend_stack_del_top(&OG(ob_buffers));
-               if (OG(nesting_level)==2) { /* destroy the stack */
-                       zend_stack_destroy(&OG(ob_buffers));
+                       zend_stack_top(&OG(ob_buffers), (void **) &ob_buffer_p);
+                       OG(active_ob_buffer) = *ob_buffer_p;
+                       zend_stack_del_top(&OG(ob_buffers));
+                       if (OG(nesting_level)==2) { /* destroy the stack */
+                               zend_stack_destroy(&OG(ob_buffers));
+                       }
                }
-       } 
+       }
 
        if (send_buffer) {
                OG(php_body_write)(final_buffer, final_buffer_length);
@@ -176,19 +199,25 @@ PHPAPI void php_end_ob_buffer(int send_buffer)
                zval_ptr_dtor(&alternate_buffer);
        }
 
-       efree(to_be_destroyed_buffer);
+       if (!just_flush) {
+               efree(to_be_destroyed_buffer);
 
-       OG(nesting_level)--;
+               OG(nesting_level)--;
+       } else {
+               OG(active_ob_buffer).text_length = 0;
+               OG(active_ob_buffer).status |= PHP_OUTPUT_HANDLER_START;
+               OG(php_body_write) = php_b_body_write;
+       }
 }
 
 
 /* End output buffering (all buffers) */
-PHPAPI void php_end_ob_buffers(int send_buffer)
+PHPAPI void php_end_ob_buffers(zend_bool send_buffer)
 {
        OLS_FETCH();
 
        while (OG(nesting_level)!=0) {
-               php_end_ob_buffer(send_buffer);
+               php_end_ob_buffer(send_buffer, 0);
        }
 }
 
@@ -197,7 +226,7 @@ PHPAPI void php_start_implicit_flush()
 {
        OLS_FETCH();
 
-       php_end_ob_buffer(1);           /* Switch out of output buffering if we're in it */
+       php_end_ob_buffer(1, 0);                /* Switch out of output buffering if we're in it */
        OG(implicit_flush)=1;
 }
 
@@ -245,6 +274,7 @@ static void php_ob_init(uint initial_size, uint block_size, zval *output_handler
        OG(active_ob_buffer).text_length = 0;
        OG(active_ob_buffer).output_handler = output_handler;
        OG(active_ob_buffer).chunk_size = chunk_size;
+       OG(active_ob_buffer).status = 0;
 }
 
 
@@ -270,8 +300,7 @@ static void php_ob_append(const char *text, uint text_length)
                if (output_handler) {
                        output_handler->refcount++;
                }
-               php_end_ob_buffer(1);
-               php_start_ob_buffer(output_handler, chunk_size);
+               php_end_ob_buffer(1, 1);
                return;
        }
 }
@@ -453,7 +482,7 @@ PHP_FUNCTION(ob_start)
    Flush (send) the output buffer, and turn off output buffering */
 PHP_FUNCTION(ob_end_flush)
 {
-       php_end_ob_buffer(1);
+       php_end_ob_buffer(1, 0);
 }
 /* }}} */
 
@@ -462,7 +491,7 @@ PHP_FUNCTION(ob_end_flush)
    Clean (erase) the output buffer, and turn off output buffering */
 PHP_FUNCTION(ob_end_clean)
 {
-       php_end_ob_buffer(0);
+       php_end_ob_buffer(0, 0);
 }
 /* }}} */
 
index d18736796aacbc4e13df68f1a9a25deec55f38c0..d7d617ba1257bd3464e10ede83ee5bc19fae3c60 100644 (file)
@@ -27,8 +27,8 @@ PHPAPI void php_output_startup(void);
 PHPAPI int  php_body_write(const char *str, uint str_length);
 PHPAPI int  php_header_write(const char *str, uint str_length);
 PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size);
-PHPAPI void php_end_ob_buffer(int send_buffer);
-PHPAPI void php_end_ob_buffers(int send_buffer);
+PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush);
+PHPAPI void php_end_ob_buffers(zend_bool send_buffer);
 PHPAPI int php_ob_get_buffer(pval *p);
 PHPAPI int php_ob_get_length(pval *p);
 PHPAPI void php_start_implicit_flush(void);
@@ -52,6 +52,7 @@ typedef struct _php_ob_buffer {
        int block_size;
        zval *output_handler;
        uint chunk_size;
+       int status;
 } php_ob_buffer;
 
 typedef struct _php_output_globals {
@@ -81,5 +82,8 @@ ZEND_API extern int output_globals_id;
 ZEND_API extern php_output_globals output_globals;
 #endif
 
+#define PHP_OUTPUT_HANDLER_START               (1<<0)
+#define PHP_OUTPUT_HANDLER_CONT                        (1<<1)
+#define PHP_OUTPUT_HANDLER_END                 (1<<2)
 
 #endif /* PHP_OUTPUT_H */