瀏覽代碼

FIX: thread safe

viest 7 年之前
父節點
當前提交
7eafed3213
共有 6 個文件被更改,包括 106 次插入75 次删除
  1. 73 50
      kernel/excel.c
  2. 17 6
      kernel/include.h
  3. 3 5
      kernel/write.c
  4. 5 2
      tests/002.phpt
  5. 4 6
      tests/003.phpt
  6. 4 6
      tests/004.phpt

+ 73 - 50
kernel/excel.c

@@ -18,7 +18,40 @@
 
 zend_class_entry *vtiful_excel_ce;
 
-static excel_resource_t *excel_res;
+static zend_object_handlers vtiful_excel_handlers;
+
+static zend_always_inline void *vtiful_object_alloc(size_t obj_size, zend_class_entry *ce) {
+    void *obj = emalloc(obj_size + zend_object_properties_size(ce));
+    memset(obj, 0, obj_size);
+    return obj;
+}
+
+/* {{{ excel_objects_new
+ */
+PHP_VTIFUL_API zend_object *excel_objects_new(zend_class_entry *ce)
+{
+    excel_object *intern = vtiful_object_alloc(sizeof(excel_object), ce);
+
+    zend_object_std_init(&intern->zo, ce);
+    object_properties_init(&intern->zo, ce);
+
+    intern->zo.handlers = &vtiful_excel_handlers;
+
+    return &intern->zo;
+}
+/* }}} */
+
+/* {{{ vtiful_excel_objects_free
+ */
+static void vtiful_excel_objects_free(zend_object *object)
+{
+    excel_object *intern = php_vtiful_excel_fetch_object(object);
+
+    lxw_workbook_free(intern->ptr.workbook);
+
+    zend_object_std_dtor(&intern->zo);
+}
+/* }}} */
 
 /* {{{ ARG_INFO
  */
@@ -122,13 +155,12 @@ PHP_METHOD(vtiful_excel, fileName)
 
     excel_file_path(file_name, dir_path, &file_path);
 
-    excel_res = malloc(sizeof(excel_resource_t));
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    excel_res->workbook  = workbook_new(Z_STRVAL(file_path));
-    excel_res->worksheet = workbook_add_worksheet(excel_res->workbook, NULL);
+    obj->ptr.workbook  = workbook_new(Z_STRVAL(file_path));
+    obj->ptr.worksheet = workbook_add_worksheet(obj->ptr.workbook, NULL);
 
     add_property_zval(return_value, V_EXCEL_FIL, &file_path);
-    add_property_resource(return_value, V_EXCEL_HANDLE, zend_register_resource(excel_res, le_excel_writer));
 
     zval_ptr_dtor(&file_path);
 }
@@ -153,13 +185,12 @@ PHP_METHOD(vtiful_excel, constMemory)
 
     lxw_workbook_options options = {.constant_memory = LXW_TRUE, .tmpdir = NULL};
 
-    excel_res = malloc(sizeof(excel_resource_t));
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    excel_res->workbook  = workbook_new_opt(Z_STRVAL(file_path), &options);
-    excel_res->worksheet = workbook_add_worksheet(excel_res->workbook, NULL);
+    obj->ptr.workbook  = workbook_new_opt(Z_STRVAL(file_path), &options);
+    obj->ptr.worksheet = workbook_add_worksheet(obj->ptr.workbook, NULL);
 
     add_property_zval(return_value, V_EXCEL_FIL, &file_path);
-    add_property_resource(return_value, V_EXCEL_HANDLE, zend_register_resource(excel_res, le_excel_writer));
 
     zval_ptr_dtor(&file_path);
 }
@@ -179,12 +210,12 @@ PHP_METHOD(vtiful_excel, header)
 
     ZVAL_COPY(return_value, getThis());
 
+    excel_object *obj = Z_EXCEL_P(getThis());
+
     ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(header), header_l_key, header_value) {
-         type_writer(header_value, 0, header_l_key, excel_res, NULL);
+         type_writer(header_value, 0, header_l_key, &obj->ptr, NULL);
          zval_ptr_dtor(header_value);
     } ZEND_HASH_FOREACH_END();
-
-    add_property_resource(return_value, V_EXCEL_HANDLE, zend_register_resource(excel_res, le_excel_writer));
 }
 /* }}} */
 
@@ -201,16 +232,16 @@ PHP_METHOD(vtiful_excel, data)
 
     ZVAL_COPY(return_value, getThis());
 
+    excel_object *obj = Z_EXCEL_P(getThis());
+
     ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data), data_r_key, data_r_value) {
         if(Z_TYPE_P(data_r_value) == IS_ARRAY) {
             ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data_r_value), data_l_key, data_l_value) {
-                type_writer(data_l_value, data_r_key+1, data_l_key, excel_res, NULL);
+                type_writer(data_l_value, data_r_key+1, data_l_key, &obj->ptr, NULL);
                 zval_ptr_dtor(data_l_value);
             } ZEND_HASH_FOREACH_END();
         }
     } ZEND_HASH_FOREACH_END();
-
-    add_property_resource(return_value, V_EXCEL_HANDLE, zend_register_resource(excel_res, le_excel_writer));
 }
 /* }}} */
 
@@ -218,14 +249,13 @@ PHP_METHOD(vtiful_excel, data)
  */
 PHP_METHOD(vtiful_excel, output)
 {
-    zval rv, *handle, *file_path;
+    zval rv, *file_path;
 
-    handle    = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_HANDLE), 0, &rv TSRMLS_DC);
     file_path = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_FIL), 0, &rv TSRMLS_DC);
 
-    workbook_file(excel_res, handle);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    free(excel_res);
+    workbook_file(&obj->ptr);
 
     add_property_null(getThis(), V_EXCEL_HANDLE);
     add_property_null(getThis(), V_EXCEL_PAT);
@@ -238,12 +268,9 @@ PHP_METHOD(vtiful_excel, output)
  */
 PHP_METHOD(vtiful_excel, getHandle)
 {
-    zval rv;
-    zval *handle;
-
-    handle = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_HANDLE), 0, &rv TSRMLS_DC);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_COPY(return_value, handle);
+    RETURN_RES(zend_register_resource(&obj->ptr, le_excel_writer));
 }
 /* }}} */
 
@@ -251,7 +278,6 @@ PHP_METHOD(vtiful_excel, getHandle)
  */
 PHP_METHOD(vtiful_excel, insertText)
 {
-    zval res_handle;
     zval *data;
     zend_long row, column;
     zend_string *format = NULL;
@@ -266,10 +292,9 @@ PHP_METHOD(vtiful_excel, insertText)
 
     ZVAL_COPY(return_value, getThis());
 
-    type_writer(data, row, column, excel_res, format);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    type_writer(data, row, column, &obj->ptr, format);
 }
 /* }}} */
 
@@ -277,7 +302,6 @@ PHP_METHOD(vtiful_excel, insertText)
  */
 PHP_METHOD(vtiful_excel, insertImage)
 {
-    zval res_handle;
     zval *image;
     zend_long row, column;
 
@@ -289,10 +313,9 @@ PHP_METHOD(vtiful_excel, insertImage)
 
     ZVAL_COPY(return_value, getThis());
 
-    image_writer(image, row, column, excel_res);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    image_writer(image, row, column, &obj->ptr);
 }
 /* }}} */
 
@@ -300,7 +323,6 @@ PHP_METHOD(vtiful_excel, insertImage)
  */
 PHP_METHOD(vtiful_excel, insertFormula)
 {
-    zval res_handle;
     zval *formula;
     zend_long row, column;
 
@@ -312,10 +334,9 @@ PHP_METHOD(vtiful_excel, insertFormula)
 
     ZVAL_COPY(return_value, getThis());
 
-    formula_writer(formula, row, column, excel_res);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    formula_writer(formula, row, column, &obj->ptr);
 }
 /* }}} */
 
@@ -323,7 +344,6 @@ PHP_METHOD(vtiful_excel, insertFormula)
  */
 PHP_METHOD(vtiful_excel, autoFilter)
 {
-    zval res_handle;
     zend_string *range;
 
     ZEND_PARSE_PARAMETERS_START(1, 1)
@@ -332,10 +352,9 @@ PHP_METHOD(vtiful_excel, autoFilter)
 
     ZVAL_COPY(return_value, getThis());
 
-    auto_filter(range, excel_res);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    auto_filter(range, &obj->ptr);
 }
 /* }}} */
 
@@ -353,10 +372,9 @@ PHP_METHOD(vtiful_excel, mergeCells)
 
     ZVAL_COPY(return_value, getThis());
 
-    merge_cells(range, data, excel_res);
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    merge_cells(range, data, &obj->ptr);
 }
 /* }}} */
 
@@ -383,10 +401,9 @@ PHP_METHOD(vtiful_excel, setColumn)
         width = 10;
     }
 
-    set_column(range, width, excel_res, zval_get_format(format_handle));
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    set_column(range, width, &obj->ptr, zval_get_format(format_handle));
 }
 /* }}} */
 
@@ -413,10 +430,9 @@ PHP_METHOD(vtiful_excel, setRow)
         height = 18;
     }
 
-    set_row(range, height, excel_res, zval_get_format(format_handle));
+    excel_object *obj = Z_EXCEL_P(getThis());
 
-    ZVAL_RES(&res_handle, zend_register_resource(excel_res, le_excel_writer));
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
+    set_row(range, height, &obj->ptr, zval_get_format(format_handle));
 }
 /* }}} */
 
@@ -447,9 +463,16 @@ VTIFUL_STARTUP_FUNCTION(excel) {
     zend_class_entry ce;
 
     INIT_NS_CLASS_ENTRY(ce, "Vtiful\\Kernel", "Excel", excel_methods);
-
+    ce.create_object = excel_objects_new;
     vtiful_excel_ce = zend_register_internal_class(&ce);
 
+    memcpy(&vtiful_excel_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+    vtiful_excel_handlers.offset   = XtOffsetOf(excel_object, zo);
+    vtiful_excel_handlers.free_obj = vtiful_excel_objects_free;
+
+    REGISTER_CLASS_PROPERTY_NULL(vtiful_excel_ce, V_EXCEL_COF, ZEND_ACC_PRIVATE);
+    REGISTER_CLASS_PROPERTY_NULL(vtiful_excel_ce, V_EXCEL_FIL, ZEND_ACC_PRIVATE);
+
     return SUCCESS;
 }
 /* }}} */

+ 17 - 6
kernel/include.h

@@ -17,20 +17,31 @@
 #include "exception.h"
 #include "format.h"
 
+typedef struct {
+    lxw_workbook  *workbook;
+    lxw_worksheet *worksheet;
+} excel_resource_t;
+
+typedef struct _vtiful_excel_object {
+    excel_resource_t ptr;
+    zend_object      zo;
+} excel_object;
+
+static inline excel_object *php_vtiful_excel_fetch_object(zend_object *obj) {
+    return (excel_object *)((char *)(obj) - XtOffsetOf(excel_object, zo));
+}
+
 #define REGISTER_CLASS_CONST_LONG(class_name, const_name, value) \
     zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (zend_long)value);
 
 #define REGISTER_CLASS_PROPERTY_NULL(class_name, property_name, acc) \
     zend_declare_property_null(class_name, ZEND_STRL(property_name), acc);
 
+#define Z_EXCEL_P(zv) php_vtiful_excel_fetch_object(Z_OBJ_P(zv));
+
 #define ROW(range) \
     lxw_name_to_row(range)
 
-typedef struct {
-    lxw_workbook *workbook;
-    lxw_worksheet *worksheet;
-} excel_resource_t;
-
 excel_resource_t * zval_get_resource(zval *handle);
 lxw_format       * zval_get_format(zval *handle);
 
@@ -50,7 +61,7 @@ void auto_filter(zend_string *range, excel_resource_t *res);
 void merge_cells(zend_string *range, zend_string *value, excel_resource_t *res);
 void set_column(zend_string *range, double width, excel_resource_t *res, lxw_format *format);
 void set_row(zend_string *range, double height, excel_resource_t *res, lxw_format *format);
-lxw_error workbook_file(excel_resource_t *self, zval *handle);
+lxw_error workbook_file(excel_resource_t *self);
 
 void excel_file_path(zend_string *file_name, zval *dir_path, zval *file_path);
 

+ 3 - 5
kernel/write.c

@@ -96,7 +96,7 @@ void set_row(zend_string *range, double height, excel_resource_t *res, lxw_forma
  * Call finalization code and close file.
  */
 lxw_error
-workbook_file(excel_resource_t *self, zval *handle)
+workbook_file(excel_resource_t *self)
 {
     lxw_worksheet *worksheet = NULL;
     lxw_packager *packager = NULL;
@@ -174,11 +174,9 @@ workbook_file(excel_resource_t *self, zval *handle)
     }
 
     mem_error:
-    if (handle) {
-        zend_list_close(Z_RES_P(handle));
         lxw_packager_free(packager);
-        lxw_workbook_free(self->workbook);
-    }
+//        lxw_workbook_free(self->workbook);
+//        self->worksheet->index
 
     return error;
 }

+ 5 - 2
tests/002.phpt

@@ -9,10 +9,13 @@ $excel = new \Vtiful\Kernel\Excel($config);
 var_dump($excel);
 ?>
 --EXPECT--
-object(Vtiful\Kernel\Excel)#1 (1) {
-  ["config"]=>
+object(Vtiful\Kernel\Excel)#1 (2) {
+  ["config":"Vtiful\Kernel\Excel":private]=>
   array(1) {
     ["path"]=>
     string(7) "./tests"
   }
+  ["fileName":"Vtiful\Kernel\Excel":private]=>
+  NULL
 }
+

+ 4 - 6
tests/003.phpt

@@ -10,14 +10,12 @@ $fileFd = $excel->fileName('tutorial01.xlsx');
 var_dump($fileFd);
 ?>
 --EXPECT--
-object(Vtiful\Kernel\Excel)#1 (3) {
-  ["config"]=>
+object(Vtiful\Kernel\Excel)#1 (2) {
+  ["config":"Vtiful\Kernel\Excel":private]=>
   array(1) {
     ["path"]=>
     string(7) "./tests"
   }
-  ["fileName"]=>
+  ["fileName":"Vtiful\Kernel\Excel":private]=>
   string(23) "./tests/tutorial01.xlsx"
-  ["handle"]=>
-  resource(4) of type (excel)
-}
+}

+ 4 - 6
tests/004.phpt

@@ -11,14 +11,12 @@ $setHeader = $fileFd->header(['Item', 'Cost']);
 var_dump($setHeader);
 ?>
 --EXPECT--
-object(Vtiful\Kernel\Excel)#1 (3) {
-  ["config"]=>
+object(Vtiful\Kernel\Excel)#1 (2) {
+  ["config":"Vtiful\Kernel\Excel":private]=>
   array(1) {
     ["path"]=>
     string(7) "./tests"
   }
-  ["fileName"]=>
+  ["fileName":"Vtiful\Kernel\Excel":private]=>
   string(23) "./tests/tutorial01.xlsx"
-  ["handle"]=>
-  resource(5) of type (excel)
-}
+}