1 /*
2    +----------------------------------------------------------------------+
3    | This source file is subject to version 3.01 of the PHP license,      |
4    | that is bundled with this package in the file LICENSE, and is        |
5    | available through the world-wide-web at the following url:           |
6    | https://www.php.net/license/3_01.txt                                 |
7    | If you did not receive a copy of the PHP license and are unable to   |
8    | obtain it through the world-wide-web, please send a note to          |
9    | license@php.net so we can mail you a copy immediately.               |
10    +----------------------------------------------------------------------+
11    | Authors: Gustavo Lopes <cataphract@php.net>                          |
12    +----------------------------------------------------------------------+
13 */
14 
15 #include "../intl_cppshims.h"
16 
17 #include <unicode/calendar.h>
18 #include <unicode/gregocal.h>
19 
20 #include "dateformat_helpers.h"
21 
22 extern "C" {
23 #include "../php_intl.h"
24 #include <Zend/zend_operators.h>
25 #define USE_CALENDAR_POINTER 1
26 #include "../calendar/calendar_class.h"
27 }
28 
29 using icu::GregorianCalendar;
30 
datefmt_process_calendar_arg(zend_object * calendar_obj,zend_long calendar_long,bool calendar_is_null,Locale const & locale,const char * func_name,intl_error * err,Calendar * & cal,zend_long & cal_int_type,bool & calendar_owned)31 int datefmt_process_calendar_arg(
32 	zend_object *calendar_obj, zend_long calendar_long, bool calendar_is_null, Locale const& locale,
33 	const char *func_name, intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned
34 ) {
35 	char *msg;
36 	UErrorCode status = UErrorCode();
37 
38 	if (calendar_is_null) {
39 		// default requested
40 		cal = new GregorianCalendar(locale, status);
41 		calendar_owned = true;
42 
43 		cal_int_type = UCAL_GREGORIAN;
44 
45 	} else if (!calendar_obj) {
46 		zend_long v = calendar_long;
47 		if (v != (zend_long)UCAL_TRADITIONAL && v != (zend_long)UCAL_GREGORIAN) {
48 			spprintf(&msg, 0, "%s: Invalid value for calendar type; it must be "
49 					"one of IntlDateFormatter::TRADITIONAL (locale's default "
50 					"calendar) or IntlDateFormatter::GREGORIAN. "
51 					"Alternatively, it can be an IntlCalendar object",
52 					func_name);
53 			intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1);
54 			efree(msg);
55 			return FAILURE;
56 		} else if (v == (zend_long)UCAL_TRADITIONAL) {
57 			cal = Calendar::createInstance(locale, status);
58 		} else { //UCAL_GREGORIAN
59 			cal = new GregorianCalendar(locale, status);
60 		}
61 		calendar_owned = true;
62 
63 		cal_int_type = calendar_long;
64 
65 	} else if (calendar_obj) {
66 		cal = calendar_fetch_native_calendar(calendar_obj);
67 		if (cal == NULL) {
68 			spprintf(&msg, 0, "%s: Found unconstructed IntlCalendar object",
69 					func_name);
70 			intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1);
71 			efree(msg);
72 			return FAILURE;
73 		}
74 		calendar_owned = false;
75 
76 		cal_int_type = -1;
77 
78 	} else {
79 		spprintf(&msg, 0, "%s: Invalid calendar argument; should be an integer "
80 				"or an IntlCalendar instance", func_name);
81 		intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1);
82 		efree(msg);
83 		return FAILURE;
84 	}
85 
86 	if (cal == NULL && !U_FAILURE(status)) {
87 		status = U_MEMORY_ALLOCATION_ERROR;
88 	}
89 	if (U_FAILURE(status)) {
90 		spprintf(&msg, 0, "%s: Failure instantiating calendar", func_name);
91 		intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1);
92 		efree(msg);
93 		return FAILURE;
94 	}
95 
96 	return SUCCESS;
97 }
98