better datetime handling
[m6w6/ext-pq] / src / php_pq_misc.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: pq |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <php.h>
18 #include <ext/date/php_date.h>
19 #if defined(HAVE_JSON) && !defined(COMPILE_DL_JSON)
20 # include <ext/json/php_json.h>
21 #endif
22
23 #include <Zend/zend_interfaces.h>
24
25 #include <libpq/libpq-fs.h>
26
27 #include "php_pq.h"
28 #include "php_pq_misc.h"
29
30 char *rtrim(char *e)
31 {
32 size_t l = strlen(e);
33
34 while (l-- > 0 && e[l] == '\n') {
35 e[l] = '\0';
36 }
37 return e;
38 }
39
40 const char *strmode(long mode)
41 {
42 switch (mode & (INV_READ|INV_WRITE)) {
43 case INV_READ|INV_WRITE:
44 return "rw";
45 case INV_READ:
46 return "r";
47 case INV_WRITE:
48 return "w";
49 default:
50 return "-";
51 }
52 }
53
54 int compare_index(const void *lptr, const void *rptr TSRMLS_DC)
55 {
56 const Bucket *l = *(const Bucket **) lptr;
57 const Bucket *r = *(const Bucket **) rptr;
58
59 if (l->h < r->h) {
60 return -1;
61 }
62 if (l->h > r->h) {
63 return 1;
64 }
65 return 0;
66 }
67
68 static int apply_to_oid(void *p, void *arg TSRMLS_DC)
69 {
70 Oid **types = arg;
71 zval **ztype = p;
72
73 if (Z_TYPE_PP(ztype) != IS_LONG) {
74 convert_to_long_ex(ztype);
75 }
76
77 **types = Z_LVAL_PP(ztype);
78 ++*types;
79
80 if (*ztype != *(zval **)p) {
81 zval_ptr_dtor(ztype);
82 }
83 return ZEND_HASH_APPLY_KEEP;
84 }
85
86 static int apply_to_param(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key)
87 {
88 char ***params;
89 HashTable *zdtor;
90 zval **zparam = p;
91
92 params = (char ***) va_arg(argv, char ***);
93 zdtor = (HashTable *) va_arg(argv, HashTable *);
94
95 switch (Z_TYPE_PP(zparam)) {
96 case IS_NULL:
97 **params = NULL;
98 ++*params;
99 break;
100
101 case IS_BOOL:
102 **params = Z_BVAL_PP(zparam) ? "t" : "f";
103 ++*params;
104 break;
105
106 case IS_DOUBLE:
107 SEPARATE_ZVAL(zparam);
108 Z_TYPE_PP(zparam) = IS_STRING;
109 Z_STRLEN_PP(zparam) = spprintf(&Z_STRVAL_PP(zparam), 0, "%F", Z_DVAL_PP((zval **)p));
110 /* no break */
111
112 default:
113 convert_to_string_ex(zparam);
114 /* no break */
115
116 case IS_STRING:
117 **params = Z_STRVAL_PP(zparam);
118 ++*params;
119
120 if (*zparam != *(zval **)p) {
121 zend_hash_next_index_insert(zdtor, zparam, sizeof(zval *), NULL);
122 }
123 break;
124 }
125
126 return ZEND_HASH_APPLY_KEEP;
127 }
128
129 int php_pq_types_to_array(HashTable *ht, Oid **types TSRMLS_DC)
130 {
131 int count = zend_hash_num_elements(ht);
132
133 *types = NULL;
134
135 if (count) {
136 Oid *tmp;
137
138 /* +1 for when less types than params are specified */
139 *types = tmp = ecalloc(count + 1, sizeof(**types));
140 zend_hash_apply_with_argument(ht, apply_to_oid, &tmp TSRMLS_CC);
141 }
142
143 return count;
144 }
145
146 int php_pq_params_to_array(HashTable *ht, char ***params, HashTable *zdtor TSRMLS_DC)
147 {
148 int count = zend_hash_num_elements(ht);
149
150 *params = NULL;
151
152 if (count) {
153 char **tmp;
154
155 *params = tmp = ecalloc(count, sizeof(char *));
156 zend_hash_apply_with_arguments(ht TSRMLS_CC, apply_to_param, 2, &tmp, zdtor);
157 }
158
159 return count;
160 }
161
162 /*
163 Oid *php_pq_ntypes_to_array(zend_bool fill, int argc, ...)
164 {
165 int i;
166 Oid *oids = ecalloc(argc + 1, sizeof(*oids));
167 va_list argv;
168
169 va_start(argv, argc);
170 for (i = 0; i < argc; ++i) {
171 if (!fill || !i) {
172 oids[i] = va_arg(argv, Oid);
173 } else {
174 oids[i] = oids[0];
175 }
176 }
177 va_end(argv);
178
179 return oids;
180 }
181 */
182
183 zend_class_entry *php_pqdt_class_entry;
184
185 ZEND_BEGIN_ARG_INFO_EX(ai_pqdt_to_string, 0, 0, 0)
186 ZEND_END_ARG_INFO();
187 static PHP_METHOD(pqdt, __toString)
188 {
189 zval *rv;
190
191 zend_call_method_with_1_params(&getThis(), php_pqdt_class_entry, NULL, "format", &rv,
192 zend_read_property(php_pqdt_class_entry, getThis(), ZEND_STRL("format"), 0 TSRMLS_CC));
193 RETVAL_ZVAL(rv, 1, 1);
194 }
195
196 static zend_function_entry php_pqdt_methods[] = {
197 PHP_ME(pqdt, __toString, ai_pqdt_to_string, ZEND_ACC_PUBLIC)
198 PHP_MALIAS(pqdt, jsonSerialize, __toString, ai_pqdt_to_string, ZEND_ACC_PUBLIC)
199 {0}
200 };
201
202 zval *php_pqdt_from_string(char *dt_str, size_t dt_len, char *fmt, zval *zv TSRMLS_DC)
203 {
204 php_date_obj *dobj;
205
206 if (!zv) {
207 MAKE_STD_ZVAL(zv);
208 }
209
210 php_date_instantiate(php_pqdt_class_entry, zv TSRMLS_CC);
211 dobj = zend_object_store_get_object(zv TSRMLS_CC);
212 if (!php_date_initialize(dobj, dt_str, dt_len, NULL, NULL, 1 TSRMLS_CC)) {
213 zval_dtor(zv);
214 ZVAL_NULL(zv);
215 } else if (fmt) {
216 zend_update_property_string(php_pqdt_class_entry, zv, ZEND_STRL("format"), fmt TSRMLS_CC);
217 }
218
219 return zv;
220 }
221
222 PHP_MINIT_FUNCTION(pq_misc)
223 {
224 zend_class_entry **json, ce = {0};
225
226 INIT_NS_CLASS_ENTRY(ce ,"pq", "DateTime", php_pqdt_methods);
227 php_pqdt_class_entry = zend_register_internal_class_ex(&ce, php_date_get_date_ce(), "DateTime" TSRMLS_CC);
228
229 zend_declare_property_stringl(php_pqdt_class_entry, ZEND_STRL("format"), ZEND_STRL("Y-m-d H:i:s.u"), ZEND_ACC_PUBLIC TSRMLS_CC);
230
231 /* stop reading this file right here! */
232 if (SUCCESS == zend_hash_find(CG(class_table), ZEND_STRS("jsonserializable"), (void *) &json)) {
233 zend_class_implements(php_pqdt_class_entry TSRMLS_CC, 1, *json);
234 }
235
236 return SUCCESS;
237 }
238
239 /*
240 * Local variables:
241 * tab-width: 4
242 * c-basic-offset: 4
243 * End:
244 * vim600: noet sw=4 ts=4 fdm=marker
245 * vim<600: noet sw=4 ts=4
246 */