1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <Properties.h>
6 #include <Util.h>
7
8 using namespace std;
9 using namespace IcePHP;
10
11 ZEND_EXTERN_MODULE_GLOBALS(ice)
12
13 //
14 // Class entries represent the PHP class implementations we have registered.
15 //
16 namespace IcePHP
17 {
18 zend_class_entry* propertiesClassEntry = 0;
19 }
20
21 //
22 // Properties support.
23 //
24 static zend_object_handlers _handlers;
25
26 extern "C"
27 {
28 static zend_object_value handleAlloc(zend_class_entry* TSRMLS_DC);
29 static void handleFreeStorage(void* TSRMLS_DC);
30 static zend_object_value handleClone(zval* TSRMLS_DC);
31 }
32
ZEND_METHOD(Ice_Properties,__construct)33 ZEND_METHOD(Ice_Properties, __construct)
34 {
35 runtimeError("properties objects cannot be instantiated, use createProperties()" TSRMLS_CC);
36 }
37
ZEND_METHOD(Ice_Properties,__toString)38 ZEND_METHOD(Ice_Properties, __toString)
39 {
40 if(ZEND_NUM_ARGS() > 0)
41 {
42 WRONG_PARAM_COUNT;
43 }
44
45 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
46 assert(_this);
47
48 try
49 {
50 Ice::PropertyDict val = _this->getPropertiesForPrefix("");
51 string str;
52 for(Ice::PropertyDict::const_iterator p = val.begin(); p != val.end(); ++p)
53 {
54 if(p != val.begin())
55 {
56 str.append("\n");
57 }
58 str.append(p->first + "=" + p->second);
59 }
60 RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1);
61 }
62 catch(const IceUtil::Exception& ex)
63 {
64 throwException(ex TSRMLS_CC);
65 RETURN_NULL();
66 }
67 }
68
ZEND_METHOD(Ice_Properties,getProperty)69 ZEND_METHOD(Ice_Properties, getProperty)
70 {
71 char* name;
72 int nameLen;
73
74 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &nameLen) == FAILURE)
75 {
76 RETURN_NULL();
77 }
78
79 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
80 assert(_this);
81
82 string propName(name, nameLen);
83 try
84 {
85 string val = _this->getProperty(propName);
86 RETURN_STRINGL(STRCAST(val.c_str()), static_cast<int>(val.length()), 1);
87 }
88 catch(const IceUtil::Exception& ex)
89 {
90 throwException(ex TSRMLS_CC);
91 RETURN_NULL();
92 }
93 }
94
ZEND_METHOD(Ice_Properties,getPropertyWithDefault)95 ZEND_METHOD(Ice_Properties, getPropertyWithDefault)
96 {
97 char* name;
98 int nameLen;
99 char* def;
100 int defLen;
101
102 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ss!"), &name, &nameLen, &def, &defLen) ==
103 FAILURE)
104 {
105 RETURN_NULL();
106 }
107
108 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
109 assert(_this);
110
111 string propName(name, nameLen);
112 string defaultValue;
113 if(def)
114 {
115 defaultValue = string(def, defLen);
116 }
117
118 try
119 {
120 string val = _this->getPropertyWithDefault(propName, defaultValue);
121 RETURN_STRINGL(STRCAST(val.c_str()), static_cast<int>(val.length()), 1);
122 }
123 catch(const IceUtil::Exception& ex)
124 {
125 throwException(ex TSRMLS_CC);
126 RETURN_NULL();
127 }
128 }
129
ZEND_METHOD(Ice_Properties,getPropertyAsInt)130 ZEND_METHOD(Ice_Properties, getPropertyAsInt)
131 {
132 char* name;
133 int nameLen;
134
135 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &nameLen) == FAILURE)
136 {
137 RETURN_NULL();
138 }
139
140 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
141 assert(_this);
142
143 string propName(name, nameLen);
144 try
145 {
146 Ice::Int val = _this->getPropertyAsInt(propName);
147 RETURN_LONG(static_cast<long>(val));
148 }
149 catch(const IceUtil::Exception& ex)
150 {
151 throwException(ex TSRMLS_CC);
152 RETURN_NULL();
153 }
154 }
155
ZEND_METHOD(Ice_Properties,getPropertyAsIntWithDefault)156 ZEND_METHOD(Ice_Properties, getPropertyAsIntWithDefault)
157 {
158 char* name;
159 int nameLen;
160 long def;
161
162 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sl"), &name, &nameLen, &def) == FAILURE)
163 {
164 RETURN_NULL();
165 }
166
167 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
168 assert(_this);
169
170 string propName(name, nameLen);
171 try
172 {
173 Ice::Int val = _this->getPropertyAsIntWithDefault(propName, def);
174 RETURN_LONG(static_cast<long>(val));
175 }
176 catch(const IceUtil::Exception& ex)
177 {
178 throwException(ex TSRMLS_CC);
179 RETURN_NULL();
180 }
181 }
182
ZEND_METHOD(Ice_Properties,getPropertyAsList)183 ZEND_METHOD(Ice_Properties, getPropertyAsList)
184 {
185 char* name;
186 int nameLen;
187
188 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &name, &nameLen) == FAILURE)
189 {
190 RETURN_NULL();
191 }
192
193 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
194 assert(_this);
195
196 string propName(name, nameLen);
197 try
198 {
199 Ice::StringSeq val = _this->getPropertyAsList(propName);
200 if(!createStringArray(return_value, val TSRMLS_CC))
201 {
202 RETURN_NULL();
203 }
204 }
205 catch(const IceUtil::Exception& ex)
206 {
207 throwException(ex TSRMLS_CC);
208 RETURN_NULL();
209 }
210 }
211
ZEND_METHOD(Ice_Properties,getPropertyAsListWithDefault)212 ZEND_METHOD(Ice_Properties, getPropertyAsListWithDefault)
213 {
214 char* name;
215 int nameLen;
216 zval* def;
217
218 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("sa!"), &name, &nameLen, &def) == FAILURE)
219 {
220 RETURN_NULL();
221 }
222
223 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
224 assert(_this);
225
226 string propName(name, nameLen);
227 Ice::StringSeq defaultValue;
228 if(def && !extractStringArray(def, defaultValue TSRMLS_CC))
229 {
230 RETURN_NULL();
231 }
232
233 try
234 {
235 Ice::StringSeq val = _this->getPropertyAsListWithDefault(propName, defaultValue);
236 if(!createStringArray(return_value, val TSRMLS_CC))
237 {
238 RETURN_NULL();
239 }
240 }
241 catch(const IceUtil::Exception& ex)
242 {
243 throwException(ex TSRMLS_CC);
244 RETURN_NULL();
245 }
246 }
247
ZEND_METHOD(Ice_Properties,getPropertiesForPrefix)248 ZEND_METHOD(Ice_Properties, getPropertiesForPrefix)
249 {
250 char* p;
251 int pLen;
252
253 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!"), &p, &pLen) == FAILURE)
254 {
255 RETURN_NULL();
256 }
257
258 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
259 assert(_this);
260
261 string prefix;
262 if(p)
263 {
264 prefix = string(p, pLen);
265 }
266
267 try
268 {
269 Ice::PropertyDict val = _this->getPropertiesForPrefix(prefix);
270 if(!createStringMap(return_value, val TSRMLS_CC))
271 {
272 RETURN_NULL();
273 }
274 }
275 catch(const IceUtil::Exception& ex)
276 {
277 throwException(ex TSRMLS_CC);
278 RETURN_NULL();
279 }
280 }
281
ZEND_METHOD(Ice_Properties,setProperty)282 ZEND_METHOD(Ice_Properties, setProperty)
283 {
284 char* name;
285 int nameLen;
286 char* val;
287 int valLen;
288
289 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("ss!"), &name, &nameLen, &val, &valLen) ==
290 FAILURE)
291 {
292 RETURN_NULL();
293 }
294
295 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
296 assert(_this);
297
298 string propName(name, nameLen);
299 string propValue;
300 if(val)
301 {
302 propValue = string(val, valLen);
303 }
304
305 try
306 {
307 _this->setProperty(propName, propValue);
308 }
309 catch(const IceUtil::Exception& ex)
310 {
311 throwException(ex TSRMLS_CC);
312 RETURN_NULL();
313 }
314 }
315
ZEND_METHOD(Ice_Properties,getCommandLineOptions)316 ZEND_METHOD(Ice_Properties, getCommandLineOptions)
317 {
318 if(ZEND_NUM_ARGS() != 0)
319 {
320 WRONG_PARAM_COUNT;
321 }
322
323 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
324 assert(_this);
325
326 try
327 {
328 Ice::StringSeq val = _this->getCommandLineOptions();
329 if(!createStringArray(return_value, val TSRMLS_CC))
330 {
331 RETURN_NULL();
332 }
333 }
334 catch(const IceUtil::Exception& ex)
335 {
336 throwException(ex TSRMLS_CC);
337 RETURN_NULL();
338 }
339 }
340
ZEND_METHOD(Ice_Properties,parseCommandLineOptions)341 ZEND_METHOD(Ice_Properties, parseCommandLineOptions)
342 {
343 char* p;
344 int pLen;
345 zval* opts;
346
347 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s!a!"), &p, &pLen, &opts) == FAILURE)
348 {
349 RETURN_NULL();
350 }
351
352 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
353 assert(_this);
354
355 string prefix;
356 if(p)
357 {
358 prefix = string(p, pLen);
359 }
360 Ice::StringSeq options;
361 if(opts && !extractStringArray(opts, options TSRMLS_CC))
362 {
363 RETURN_NULL();
364 }
365
366 try
367 {
368 Ice::StringSeq val = _this->parseCommandLineOptions(prefix, options);
369 if(!createStringArray(return_value, val TSRMLS_CC))
370 {
371 RETURN_NULL();
372 }
373 }
374 catch(const IceUtil::Exception& ex)
375 {
376 throwException(ex TSRMLS_CC);
377 RETURN_NULL();
378 }
379 }
380
ZEND_METHOD(Ice_Properties,parseIceCommandLineOptions)381 ZEND_METHOD(Ice_Properties, parseIceCommandLineOptions)
382 {
383 zval* opts;
384
385 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("a!"), &opts) == FAILURE)
386 {
387 RETURN_NULL();
388 }
389
390 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
391 assert(_this);
392
393 Ice::StringSeq options;
394 if(opts && !extractStringArray(opts, options TSRMLS_CC))
395 {
396 RETURN_NULL();
397 }
398
399 try
400 {
401 Ice::StringSeq val = _this->parseIceCommandLineOptions(options);
402 if(!createStringArray(return_value, val TSRMLS_CC))
403 {
404 RETURN_NULL();
405 }
406 }
407 catch(const IceUtil::Exception& ex)
408 {
409 throwException(ex TSRMLS_CC);
410 RETURN_NULL();
411 }
412 }
413
ZEND_METHOD(Ice_Properties,load)414 ZEND_METHOD(Ice_Properties, load)
415 {
416 char* f;
417 int fLen;
418
419 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("s"), &f, &fLen) == FAILURE)
420 {
421 RETURN_NULL();
422 }
423
424 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
425 assert(_this);
426
427 string file(f, fLen);
428
429 try
430 {
431 _this->load(file);
432 }
433 catch(const IceUtil::Exception& ex)
434 {
435 throwException(ex TSRMLS_CC);
436 RETURN_NULL();
437 }
438 }
439
ZEND_METHOD(Ice_Properties,clone)440 ZEND_METHOD(Ice_Properties, clone)
441 {
442 if(ZEND_NUM_ARGS() > 0)
443 {
444 WRONG_PARAM_COUNT;
445 }
446
447 Ice::PropertiesPtr _this = Wrapper<Ice::PropertiesPtr>::value(getThis() TSRMLS_CC);
448 assert(_this);
449
450 try
451 {
452 Ice::PropertiesPtr pclone = _this->clone();
453
454 if(!createProperties(return_value, pclone TSRMLS_CC))
455 {
456 RETURN_NULL();
457 }
458 }
459 catch(const IceUtil::Exception& ex)
460 {
461 throwException(ex TSRMLS_CC);
462 RETURN_NULL();
463 }
464 }
465
466 #ifdef _WIN32
467 extern "C"
468 #endif
469 static zend_object_value
handleAlloc(zend_class_entry * ce TSRMLS_DC)470 handleAlloc(zend_class_entry* ce TSRMLS_DC)
471 {
472 zend_object_value result;
473
474 Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::create(ce TSRMLS_CC);
475 assert(obj);
476
477 result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleFreeStorage, 0 TSRMLS_CC);
478 result.handlers = &_handlers;
479
480 return result;
481 }
482
483 #ifdef _WIN32
484 extern "C"
485 #endif
486 static void
handleFreeStorage(void * p TSRMLS_DC)487 handleFreeStorage(void* p TSRMLS_DC)
488 {
489 Wrapper<Ice::PropertiesPtr>* obj = static_cast<Wrapper<Ice::PropertiesPtr>*>(p);
490 delete obj->ptr;
491 zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC);
492 efree(p);
493 }
494
495 #ifdef _WIN32
496 extern "C"
497 #endif
498 static zend_object_value
handleClone(zval * zv TSRMLS_DC)499 handleClone(zval* zv TSRMLS_DC)
500 {
501 zend_object_value result;
502 memset(&result, 0, sizeof(zend_object_value));
503
504 Ice::PropertiesPtr p = Wrapper<Ice::PropertiesPtr>::value(zv TSRMLS_CC);
505 assert(p);
506
507 Ice::PropertiesPtr pclone = p->clone();
508
509 zval* clone;
510 MAKE_STD_ZVAL(clone);
511 if(!createProperties(clone, pclone TSRMLS_CC))
512 {
513 return result;
514 }
515
516 //
517 // We only need to return the new object's handle, so we must destroy the zval containing
518 // a reference to the new object. We increment the object's reference count to ensure it
519 // does not get destroyed.
520 //
521 result = clone->value.obj;
522 Z_OBJ_HT_P(clone)->add_ref(clone TSRMLS_CC);
523 zval_dtor(clone);
524 efree(clone);
525
526 return result;
527 }
528
ZEND_FUNCTION(Ice_createProperties)529 ZEND_FUNCTION(Ice_createProperties)
530 {
531 zval* arglist = 0;
532 zval* defaultsObj = 0;
533
534 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("|a!O!"), &arglist, &defaultsObj,
535 propertiesClassEntry) == FAILURE)
536 {
537 RETURN_NULL();
538 }
539
540 Ice::StringSeq seq;
541 if(arglist && !extractStringArray(arglist, seq TSRMLS_CC))
542 {
543 RETURN_NULL();
544 }
545
546 Ice::PropertiesPtr defaults;
547 if(defaultsObj && !fetchProperties(defaultsObj, defaults TSRMLS_CC))
548 {
549 RETURN_NULL();
550 }
551
552 try
553 {
554 Ice::PropertiesPtr props;
555 if(arglist || defaults)
556 {
557 props = Ice::createProperties(seq, defaults);
558 }
559 else
560 {
561 props = Ice::createProperties();
562 }
563
564 if(!createProperties(return_value, props TSRMLS_CC))
565 {
566 RETURN_NULL();
567 }
568
569 if(arglist && PZVAL_IS_REF(arglist))
570 {
571 zval_dtor(arglist);
572 if(!createStringArray(arglist, seq TSRMLS_CC))
573 {
574 RETURN_NULL();
575 }
576 }
577 }
578 catch(const IceUtil::Exception& ex)
579 {
580 throwException(ex TSRMLS_CC);
581 RETURN_NULL();
582 }
583 }
584
585 //
586 // Necessary to suppress warnings from zend_function_entry in php-5.2.
587 //
588 #if defined(__GNUC__)
589 # pragma GCC diagnostic ignored "-Wwrite-strings"
590 #endif
591
592 //
593 // Predefined methods for Properties.
594 //
595 static zend_function_entry _interfaceMethods[] =
596 {
597 {0, 0, 0}
598 };
599 static zend_function_entry _classMethods[] =
600 {
601 ZEND_ME(Ice_Properties, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
602 ZEND_ME(Ice_Properties, __toString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
603 ZEND_ME(Ice_Properties, getProperty, ICE_NULLPTR, ZEND_ACC_PUBLIC)
604 ZEND_ME(Ice_Properties, getPropertyWithDefault, ICE_NULLPTR, ZEND_ACC_PUBLIC)
605 ZEND_ME(Ice_Properties, getPropertyAsInt, ICE_NULLPTR, ZEND_ACC_PUBLIC)
606 ZEND_ME(Ice_Properties, getPropertyAsIntWithDefault, ICE_NULLPTR, ZEND_ACC_PUBLIC)
607 ZEND_ME(Ice_Properties, getPropertyAsList, ICE_NULLPTR, ZEND_ACC_PUBLIC)
608 ZEND_ME(Ice_Properties, getPropertyAsListWithDefault, ICE_NULLPTR, ZEND_ACC_PUBLIC)
609 ZEND_ME(Ice_Properties, getPropertiesForPrefix, ICE_NULLPTR, ZEND_ACC_PUBLIC)
610 ZEND_ME(Ice_Properties, setProperty, ICE_NULLPTR, ZEND_ACC_PUBLIC)
611 ZEND_ME(Ice_Properties, getCommandLineOptions, ICE_NULLPTR, ZEND_ACC_PUBLIC)
612 ZEND_ME(Ice_Properties, parseCommandLineOptions, ICE_NULLPTR, ZEND_ACC_PUBLIC)
613 ZEND_ME(Ice_Properties, parseIceCommandLineOptions, ICE_NULLPTR, ZEND_ACC_PUBLIC)
614 ZEND_ME(Ice_Properties, load, ICE_NULLPTR, ZEND_ACC_PUBLIC)
615 ZEND_ME(Ice_Properties, clone, ICE_NULLPTR, ZEND_ACC_PUBLIC)
616 {0, 0, 0}
617 };
618
619 //
620 // enable warning again
621 //
622 #if defined(__GNUC__)
623 # pragma GCC diagnostic error "-Wwrite-strings"
624 #endif
625
626 bool
propertiesInit(TSRMLS_D)627 IcePHP::propertiesInit(TSRMLS_D)
628 {
629 //
630 // We register an interface and a class that implements the interface. This allows
631 // applications to safely include the Slice-generated code for the type.
632 //
633
634 //
635 // Register the Properties interface.
636 //
637 zend_class_entry ce;
638 #ifdef ICEPHP_USE_NAMESPACES
639 INIT_NS_CLASS_ENTRY(ce, "Ice", "Properties", _interfaceMethods);
640 #else
641 INIT_CLASS_ENTRY(ce, "Ice_Properties", _interfaceMethods);
642 #endif
643 zend_class_entry* interface = zend_register_internal_interface(&ce TSRMLS_CC);
644
645 //
646 // Register the Properties class.
647 //
648 INIT_CLASS_ENTRY(ce, "IcePHP_Properties", _classMethods);
649 ce.create_object = handleAlloc;
650 propertiesClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
651 memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
652 _handlers.clone_obj = handleClone;
653 zend_class_implements(propertiesClassEntry TSRMLS_CC, 1, interface);
654
655 return true;
656 }
657
658 bool
createProperties(zval * zv,const Ice::PropertiesPtr & p TSRMLS_DC)659 IcePHP::createProperties(zval* zv, const Ice::PropertiesPtr& p TSRMLS_DC)
660 {
661 if(object_init_ex(zv, propertiesClassEntry) != SUCCESS)
662 {
663 runtimeError("unable to initialize properties object" TSRMLS_CC);
664 return false;
665 }
666
667 Wrapper<Ice::PropertiesPtr>* obj = Wrapper<Ice::PropertiesPtr>::extract(zv TSRMLS_CC);
668 assert(!obj->ptr);
669 obj->ptr = new Ice::PropertiesPtr(p);
670
671 return true;
672 }
673
674 bool
fetchProperties(zval * zv,Ice::PropertiesPtr & p TSRMLS_DC)675 IcePHP::fetchProperties(zval* zv, Ice::PropertiesPtr& p TSRMLS_DC)
676 {
677 if(!ZVAL_IS_NULL(zv))
678 {
679 if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != propertiesClassEntry)
680 {
681 invalidArgument("value is not a properties object" TSRMLS_CC);
682 return false;
683 }
684 p = Wrapper<Ice::PropertiesPtr>::value(zv TSRMLS_CC);
685 if(!p)
686 {
687 runtimeError("unable to retrieve properties object from object store" TSRMLS_CC);
688 return false;
689 }
690 }
691 return true;
692 }
693