@@ -43,48 +43,32 @@ static inline GregorianCalendar *fetch_greg(Calendar_object *co) {
43
43
return (GregorianCalendar*)co->ucal ;
44
44
}
45
45
46
- static void _php_intlgregcal_constructor_body (
47
- INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
46
+ static void _php_intlgregcal_constructor_body (INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
48
47
{
49
- zval *tz_object = NULL ;
50
- zval args_a[6 ],
51
- *args = &args_a[0 ];
52
- char *locale = NULL ;
53
- size_t locale_len;
54
- zend_long largs[6 ];
55
- UErrorCode status = U_ZERO_ERROR;
56
- int variant;
57
- intl_error_reset (NULL );
58
-
59
- // parameter number validation / variant determination
60
- if (ZEND_NUM_ARGS () > 6 ||
61
- zend_get_parameters_array_ex (ZEND_NUM_ARGS (), args) == FAILURE) {
62
- zend_argument_count_error (" Too many arguments" );
63
- RETURN_THROWS ();
64
- }
65
-
66
- for (variant = ZEND_NUM_ARGS ();
67
- variant > 0 && Z_TYPE (args[variant - 1 ]) == IS_NULL;
68
- variant--) {}
69
- if (variant == 4 ) {
70
- zend_argument_count_error (" No variant with 4 arguments (excluding trailing NULLs)" );
71
- RETURN_THROWS ();
72
- }
48
+ UErrorCode status = U_ZERO_ERROR;
49
+ zval *timezone_or_year = NULL ;
50
+ zend_string *locale = NULL ;
51
+ zend_long month;
52
+ bool is_month_null = true ;
53
+ zend_long day_of_month = 0 ;
54
+ bool is_dom_null = true ;
55
+ zend_long hour = 0 ;
56
+ zend_long minutes = 0 ;
57
+ zend_long seconds = 0 ;
58
+
59
+ ZEND_PARSE_PARAMETERS_START (0 , 6 )
60
+ Z_PARAM_OPTIONAL
61
+ Z_PARAM_ZVAL (timezone_or_year)
62
+ Z_PARAM_STR_OR_LONG_OR_NULL (locale, month, is_month_null)
63
+ Z_PARAM_LONG_OR_NULL (day_of_month, is_dom_null)
64
+ Z_PARAM_LONG (hour)
65
+ Z_PARAM_LONG (minutes)
66
+ Z_PARAM_LONG (seconds)
67
+ ZEND_PARSE_PARAMETERS_END ();
73
68
74
- // argument parsing
75
- if (variant <= 2 ) {
76
- if (zend_parse_parameters (MIN (ZEND_NUM_ARGS (), 2 ),
77
- " |z!s!" , &tz_object, &locale, &locale_len) == FAILURE) {
78
- RETURN_THROWS ();
79
- }
80
- }
81
- if (variant > 2 && zend_parse_parameters (ZEND_NUM_ARGS (),
82
- " lll|lll" , &largs[0 ], &largs[1 ], &largs[2 ], &largs[3 ], &largs[4 ],
83
- &largs[5 ]) == FAILURE) {
84
- RETURN_THROWS ();
85
- }
69
+ intl_error_reset (NULL );
86
70
87
- // instantion of ICU object
71
+ // instantiation of ICU object
88
72
Calendar_object *co = Z_INTL_CALENDAR_P (return_value);
89
73
GregorianCalendar *gcal = NULL ;
90
74
@@ -93,27 +77,33 @@ static void _php_intlgregcal_constructor_body(
93
77
RETURN_THROWS ();
94
78
}
95
79
96
- if (variant <= 2 ) {
97
- // From timezone and locale (0 to 2 arguments)
98
- TimeZone *tz = timezone_process_timezone_argument (tz_object, NULL ,
80
+ if (!timezone_or_year || Z_TYPE_P (timezone_or_year) != IS_LONG) {
81
+ if (!locale && !is_month_null) {
82
+ zend_argument_value_error (2 , " must be ?string if argument 1 is a timezone" );
83
+ RETURN_THROWS ();
84
+ }
85
+
86
+ TimeZone *tz = timezone_process_timezone_argument (timezone_or_year, NULL ,
99
87
" intlgregcal_create_instance" );
100
88
if (tz == NULL ) {
101
89
if (!EG (exception)) {
102
90
zend_throw_exception (IntlException_ce_ptr, " Constructor failed" , 0 );
103
91
}
104
92
if (!is_constructor) {
105
93
zval_ptr_dtor (return_value);
106
- RETVAL_NULL ();
94
+ RETURN_NULL ();
107
95
}
108
- return ;
96
+ RETURN_THROWS () ;
109
97
}
110
- if (!locale) {
111
- locale = const_cast <char *>(intl_locale_get_default ());
98
+ char *intl_locale;
99
+ if (locale) {
100
+ intl_locale = ZSTR_VAL (locale);
101
+ } else {
102
+ intl_locale = const_cast <char *>(intl_locale_get_default ());
112
103
}
113
104
114
- gcal = new GregorianCalendar (tz, Locale::createFromName (locale),
115
- status);
116
- // Should this throw?
105
+ gcal = new GregorianCalendar (tz, Locale::createFromName (intl_locale), status);
106
+ // Should this always throw?
117
107
if (U_FAILURE (status)) {
118
108
intl_error_set (NULL , status, " intlgregcal_create_instance: error "
119
109
" creating ICU GregorianCalendar from time zone and locale" , 0 );
@@ -123,31 +113,50 @@ static void _php_intlgregcal_constructor_body(
123
113
delete tz;
124
114
if (!is_constructor) {
125
115
zval_ptr_dtor (return_value);
126
- RETVAL_NULL ();
116
+ RETURN_NULL ();
127
117
}
128
- return ;
118
+ RETURN_THROWS () ;
129
119
}
130
120
} else {
131
- // From date/time (3, 5 or 6 arguments)
132
- for (int i = 0 ; i < variant; i++) {
133
- if (largs[i] < INT32_MIN || largs[i] > INT32_MAX) {
134
- zend_argument_value_error (getThis () ? (i-1 ) : i,
135
- " must be between %d and %d" , INT32_MIN, INT32_MAX);
136
- RETURN_THROWS ();
137
- }
121
+ ZEND_ASSERT (Z_TYPE_P (timezone_or_year) == IS_LONG);
122
+ if (locale || is_month_null) {
123
+ zend_argument_value_error (2 , " must be int if argument 1 is an int" );
124
+ RETURN_THROWS ();
125
+ }
126
+ if (is_dom_null) {
127
+ zend_argument_value_error (3 , " must be provided" );
128
+ RETURN_THROWS ();
138
129
}
139
130
140
- if (variant == 3 ) {
141
- gcal = new GregorianCalendar ((int32_t )largs[0 ], (int32_t )largs[1 ],
142
- (int32_t )largs[2 ], status);
143
- } else if (variant == 5 ) {
144
- gcal = new GregorianCalendar ((int32_t )largs[0 ], (int32_t )largs[1 ],
145
- (int32_t )largs[2 ], (int32_t )largs[3 ], (int32_t )largs[4 ], status);
146
- } else if (variant == 6 ) {
147
- gcal = new GregorianCalendar ((int32_t )largs[0 ], (int32_t )largs[1 ],
148
- (int32_t )largs[2 ], (int32_t )largs[3 ], (int32_t )largs[4 ], (int32_t )largs[5 ],
149
- status);
131
+ zend_long year = Z_LVAL_P (timezone_or_year);
132
+ if (year < INT32_MIN || year > INT32_MAX) {
133
+ zend_argument_value_error (3 , " must be between %d and %d" , INT32_MIN, INT32_MAX);
134
+ RETURN_THROWS ();
135
+ }
136
+ if (month < INT32_MIN || month > INT32_MAX) {
137
+ zend_argument_value_error (3 , " must be between %d and %d" , INT32_MIN, INT32_MAX);
138
+ RETURN_THROWS ();
139
+ }
140
+ if (day_of_month < INT32_MIN || day_of_month > INT32_MAX) {
141
+ zend_argument_value_error (3 , " must be between %d and %d" , INT32_MIN, INT32_MAX);
142
+ RETURN_THROWS ();
143
+ }
144
+ if (hour < INT32_MIN || hour > INT32_MAX) {
145
+ zend_argument_value_error (4 , " must be between %d and %d" , INT32_MIN, INT32_MAX);
146
+ RETURN_THROWS ();
147
+ }
148
+ if (minutes < INT32_MIN || minutes > INT32_MAX) {
149
+ zend_argument_value_error (5 , " must be between %d and %d" , INT32_MIN, INT32_MAX);
150
+ RETURN_THROWS ();
151
+ }
152
+ if (seconds < INT32_MIN || seconds > INT32_MAX) {
153
+ zend_argument_value_error (6 , " must be between %d and %d" , INT32_MIN, INT32_MAX);
154
+ RETURN_THROWS ();
150
155
}
156
+
157
+ gcal = new GregorianCalendar ((int32_t )year, (int32_t )month, (int32_t )day_of_month,
158
+ (int32_t )hour, (int32_t )minutes, (int32_t )seconds, status);
159
+
151
160
if (U_FAILURE (status)) {
152
161
intl_error_set (NULL , status, " intlgregcal_create_instance: error "
153
162
" creating ICU GregorianCalendar from date" , 0 );
@@ -156,9 +165,9 @@ static void _php_intlgregcal_constructor_body(
156
165
}
157
166
if (!is_constructor) {
158
167
zval_ptr_dtor (return_value);
159
- RETVAL_NULL ();
168
+ RETURN_NULL ();
160
169
}
161
- return ;
170
+ RETURN_THROWS () ;
162
171
}
163
172
164
173
timelib_tzinfo *tzinfo = get_timezone_info ();
@@ -171,9 +180,9 @@ static void _php_intlgregcal_constructor_body(
171
180
delete gcal;
172
181
if (!is_constructor) {
173
182
zval_ptr_dtor (return_value);
174
- RETVAL_NULL ();
183
+ RETURN_NULL ();
175
184
}
176
- return ;
185
+ RETURN_THROWS () ;
177
186
}
178
187
179
188
TimeZone *tz = TimeZone::createTimeZone (tzstr);
0 commit comments