Skip to content

Commit fb5a9d6

Browse files
committed
Refactor document and array visitors
1 parent ac89d43 commit fb5a9d6

File tree

1 file changed

+107
-118
lines changed

1 file changed

+107
-118
lines changed

src/phongo_bson.c

Lines changed: 107 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -861,81 +861,76 @@ static bool php_phongo_bson_visit_document(const bson_iter_t* iter ARG_UNUSED, c
861861
zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
862862
bson_iter_t child;
863863
php_phongo_bson_state* parent_state = (php_phongo_bson_state*) data;
864+
php_phongo_bson_state state;
865+
866+
if (!bson_iter_init(&child, v_document)) {
867+
return false;
868+
}
864869

865870
php_phongo_field_path_push(parent_state->field_path, key, PHONGO_FIELD_PATH_ITEM_DOCUMENT);
866871

867-
if (bson_iter_init(&child, v_document)) {
868-
php_phongo_bson_state state;
872+
PHONGO_BSON_INIT_STATE(state);
873+
php_phongo_bson_state_copy_ctor(&state, parent_state);
869874

870-
PHONGO_BSON_INIT_STATE(state);
871-
php_phongo_bson_state_copy_ctor(&state, parent_state);
875+
array_init(&state.zchild);
872876

873-
array_init(&state.zchild);
877+
if (bson_iter_visit_all(&child, &php_bson_visitors, &state) || child.err_off) {
878+
/* Iteration stopped prematurely due to corruption or a failed
879+
* visitor. Free state.zchild, which we just initialized, and return
880+
* true to stop iteration for our parent context. */
881+
zval_ptr_dtor(&state.zchild);
882+
php_phongo_bson_state_dtor(&state);
883+
return true;
884+
}
874885

875-
if (!bson_iter_visit_all(&child, &php_bson_visitors, &state) && !child.err_off) {
876-
/* Check for entries in the fieldPath type map key, and use them to
877-
* override the default ones for this type */
878-
php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.document);
886+
/* Check for entries in the fieldPath type map key, and use them to
887+
* override the default ones for this type */
888+
php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.document);
879889

880-
/* If php_phongo_bson_visit_binary() finds an ODM class, it should
881-
* supersede a default type map and named document class. */
882-
if (state.odm && state.map.document.type == PHONGO_TYPEMAP_NONE) {
883-
state.map.document.type = PHONGO_TYPEMAP_CLASS;
884-
}
890+
/* If php_phongo_bson_visit_binary() finds an ODM class, it should
891+
* supersede a default type map and named document class. */
892+
if (state.odm && state.map.document.type == PHONGO_TYPEMAP_NONE) {
893+
state.map.document.type = PHONGO_TYPEMAP_CLASS;
894+
}
885895

886-
switch (state.map.document.type) {
887-
case PHONGO_TYPEMAP_NATIVE_ARRAY:
888-
if (((php_phongo_bson_state*) data)->is_visiting_array) {
889-
add_next_index_zval(retval, &state.zchild);
890-
} else {
891-
ADD_ASSOC_ZVAL(retval, key, &state.zchild);
892-
}
893-
break;
894-
895-
case PHONGO_TYPEMAP_CLASS: {
896-
zval obj;
897-
zend_class_entry* obj_ce = state.odm ? state.odm : state.map.document.class;
898-
899-
if (!php_phongo_bson_init_document_object(&state.zchild, obj_ce, &obj)) {
900-
/* Exception already thrown. Clean up and return
901-
* true to stop iteration for our parent context. */
902-
zval_ptr_dtor(&state.zchild);
903-
php_phongo_bson_state_dtor(&state);
904-
return true;
905-
}
906-
907-
zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
908-
if (((php_phongo_bson_state*) data)->is_visiting_array) {
909-
add_next_index_zval(retval, &obj);
910-
} else {
911-
ADD_ASSOC_ZVAL(retval, key, &obj);
912-
}
913-
zval_ptr_dtor(&state.zchild);
914-
break;
915-
}
896+
switch (state.map.document.type) {
897+
case PHONGO_TYPEMAP_NATIVE_ARRAY:
898+
/* Do nothing, item will be added later */
899+
break;
916900

917-
case PHONGO_TYPEMAP_NATIVE_OBJECT:
918-
default:
919-
convert_to_object(&state.zchild);
920-
if (((php_phongo_bson_state*) data)->is_visiting_array) {
921-
add_next_index_zval(retval, &state.zchild);
922-
} else {
923-
ADD_ASSOC_ZVAL(retval, key, &state.zchild);
924-
}
901+
case PHONGO_TYPEMAP_CLASS: {
902+
zval obj;
903+
zend_class_entry* obj_ce = state.odm ? state.odm : state.map.document.class;
904+
905+
if (!php_phongo_bson_init_document_object(&state.zchild, obj_ce, &obj)) {
906+
/* Exception already thrown. Clean up and return
907+
* true to stop iteration for our parent context. */
908+
zval_ptr_dtor(&state.zchild);
909+
php_phongo_bson_state_dtor(&state);
910+
return true;
925911
}
926-
} else {
927-
/* Iteration stopped prematurely due to corruption or a failed
928-
* visitor. Free state.zchild, which we just initialized, and return
929-
* true to stop iteration for our parent context. */
912+
913+
zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
914+
930915
zval_ptr_dtor(&state.zchild);
931-
php_phongo_bson_state_dtor(&state);
932-
return true;
916+
ZVAL_COPY_VALUE(&state.zchild, &obj);
917+
break;
933918
}
934919

935-
php_phongo_bson_state_dtor(&state);
936-
php_phongo_field_path_pop(parent_state->field_path);
920+
case PHONGO_TYPEMAP_NATIVE_OBJECT:
921+
default:
922+
convert_to_object(&state.zchild);
937923
}
938924

925+
if (parent_state->is_visiting_array) {
926+
add_next_index_zval(retval, &state.zchild);
927+
} else {
928+
ADD_ASSOC_ZVAL(retval, key, &state.zchild);
929+
}
930+
931+
php_phongo_bson_state_dtor(&state);
932+
php_phongo_field_path_pop(parent_state->field_path);
933+
939934
return false;
940935
}
941936

@@ -944,74 +939,68 @@ static bool php_phongo_bson_visit_array(const bson_iter_t* iter ARG_UNUSED, cons
944939
zval* retval = PHONGO_BSON_STATE_ZCHILD(data);
945940
bson_iter_t child;
946941
php_phongo_bson_state* parent_state = (php_phongo_bson_state*) data;
942+
php_phongo_bson_state state;
943+
944+
if (!bson_iter_init(&child, v_array)) {
945+
return false;
946+
}
947947

948948
php_phongo_field_path_push(parent_state->field_path, key, PHONGO_FIELD_PATH_ITEM_ARRAY);
949949

950-
if (bson_iter_init(&child, v_array)) {
951-
php_phongo_bson_state state;
950+
PHONGO_BSON_INIT_STATE(state);
951+
php_phongo_bson_state_copy_ctor(&state, parent_state);
952952

953-
PHONGO_BSON_INIT_STATE(state);
954-
php_phongo_bson_state_copy_ctor(&state, parent_state);
955-
956-
/* Note that we are visiting an array, so element visitors know to use
957-
* add_next_index() (i.e. disregard BSON keys) instead of add_assoc()
958-
* when building the PHP array.
959-
*/
960-
state.is_visiting_array = true;
961-
962-
array_init(&state.zchild);
963-
964-
if (!bson_iter_visit_all(&child, &php_bson_visitors, &state) && !child.err_off) {
965-
/* Check for entries in the fieldPath type map key, and use them to
966-
* override the default ones for this type */
967-
php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.array);
968-
969-
switch (state.map.array.type) {
970-
case PHONGO_TYPEMAP_CLASS: {
971-
zval obj;
972-
973-
object_init_ex(&obj, state.map.array.class);
974-
zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
975-
if (((php_phongo_bson_state*) data)->is_visiting_array) {
976-
add_next_index_zval(retval, &obj);
977-
} else {
978-
ADD_ASSOC_ZVAL(retval, key, &obj);
979-
}
980-
zval_ptr_dtor(&state.zchild);
981-
break;
982-
}
953+
/* Note that we are visiting an array, so element visitors know to use
954+
* add_next_index() (i.e. disregard BSON keys) instead of add_assoc()
955+
* when building the PHP array.
956+
*/
957+
state.is_visiting_array = true;
983958

984-
case PHONGO_TYPEMAP_NATIVE_OBJECT:
985-
convert_to_object(&state.zchild);
986-
if (((php_phongo_bson_state*) data)->is_visiting_array) {
987-
add_next_index_zval(retval, &state.zchild);
988-
} else {
989-
ADD_ASSOC_ZVAL(retval, key, &state.zchild);
990-
}
991-
break;
992-
993-
case PHONGO_TYPEMAP_NATIVE_ARRAY:
994-
default:
995-
if (((php_phongo_bson_state*) data)->is_visiting_array) {
996-
add_next_index_zval(retval, &state.zchild);
997-
} else {
998-
ADD_ASSOC_ZVAL(retval, key, &state.zchild);
999-
}
1000-
break;
1001-
}
1002-
} else {
1003-
/* Iteration stopped prematurely due to corruption or a failed
1004-
* visitor. Free state.zchild, which we just initialized, and return
1005-
* true to stop iteration for our parent context. */
959+
array_init(&state.zchild);
960+
961+
if (bson_iter_visit_all(&child, &php_bson_visitors, &state) || child.err_off) {
962+
/* Iteration stopped prematurely due to corruption or a failed
963+
* visitor. Free state.zchild, which we just initialized, and return
964+
* true to stop iteration for our parent context. */
965+
zval_ptr_dtor(&state.zchild);
966+
php_phongo_bson_state_dtor(&state);
967+
return true;
968+
}
969+
970+
/* Check for entries in the fieldPath type map key, and use them to
971+
* override the default ones for this type */
972+
php_phongo_handle_field_path_entry_for_compound_type(&state, &state.map.array);
973+
974+
switch (state.map.array.type) {
975+
case PHONGO_TYPEMAP_CLASS: {
976+
zval obj;
977+
978+
object_init_ex(&obj, state.map.array.class);
979+
zend_call_method_with_1_params(PHONGO_COMPAT_OBJ_P(&obj), NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, &state.zchild);
1006980
zval_ptr_dtor(&state.zchild);
1007-
php_phongo_bson_state_dtor(&state);
1008-
return true;
981+
ZVAL_COPY_VALUE(&state.zchild, &obj);
982+
break;
1009983
}
1010984

1011-
php_phongo_bson_state_dtor(&state);
1012-
php_phongo_field_path_pop(parent_state->field_path);
985+
case PHONGO_TYPEMAP_NATIVE_OBJECT:
986+
convert_to_object(&state.zchild);
987+
break;
988+
989+
case PHONGO_TYPEMAP_NATIVE_ARRAY:
990+
default:
991+
/* Do nothing, will be added later */
992+
break;
1013993
}
1014994

995+
if (parent_state->is_visiting_array) {
996+
add_next_index_zval(retval, &state.zchild);
997+
} else {
998+
ADD_ASSOC_ZVAL(retval, key, &state.zchild);
999+
}
1000+
1001+
php_phongo_bson_state_dtor(&state);
1002+
php_phongo_field_path_pop(parent_state->field_path);
1003+
10151004
return false;
10161005
}
10171006

0 commit comments

Comments
 (0)