php_vm 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/ext/php_vm/php_vm.c +114 -12
  2. data/ext/php_vm/php_vm.h +5 -0
  3. metadata +1 -1
data/ext/php_vm/php_vm.c CHANGED
@@ -160,9 +160,41 @@ int new_php_object(zend_class_entry *ce, VALUE v_args, zval *retval)
160
160
  return result;
161
161
  }
162
162
 
163
+ void define_php_properties(VALUE v_obj, zend_class_entry *ce, int is_static)
164
+ {
165
+ HashPosition pos;
166
+ zend_property_info *prop;
167
+
168
+ zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
169
+
170
+ while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
171
+ int flag = prop->flags;
172
+ const char *getter_name = prop->name;
173
+ char *setter_name = malloc(prop->name_length+ 1);
174
+ sprintf(setter_name, "%s=", getter_name);
175
+
176
+ if (is_static) {
177
+ // static variable
178
+ if (0<(flag & ZEND_ACC_STATIC)) {
179
+ rb_define_singleton_method(v_obj, getter_name, rb_php_class_getter, 0);
180
+ rb_define_singleton_method(v_obj, setter_name, rb_php_class_setter, 1);
181
+ }
182
+ } else {
183
+ // instance variable
184
+ if (0==(flag & ZEND_ACC_STATIC)) {
185
+ rb_define_singleton_method(v_obj, getter_name, rb_php_object_getter, 0);
186
+ rb_define_singleton_method(v_obj, setter_name, rb_php_object_setter, 1);
187
+ }
188
+ }
189
+
190
+ free(setter_name);
191
+ zend_hash_move_forward_ex(&ce->properties_info, &pos);
192
+ }
193
+ }
194
+
163
195
  void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static)
164
196
  {
165
- // TODO: access modifier
197
+ // TODO: access scope
166
198
  // TODO: __toString
167
199
  // TODO: __clone
168
200
  // TODO: __call
@@ -184,6 +216,7 @@ void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static)
184
216
  // class method
185
217
  if (strcmp("new", fname)==0) {
186
218
  // new => no define
219
+
187
220
  } else if (0<(flag & ZEND_ACC_STATIC)) {
188
221
  // other method
189
222
  rb_define_singleton_method(v_obj, fname, rb_php_class_call, -1);
@@ -258,15 +291,16 @@ int call_php_method(zend_class_entry *ce, zval *obj, zend_function *mptr, int ar
258
291
 
259
292
  // Ruby
260
293
 
294
+ VALUE backtrace_re;
295
+
261
296
  VALUE get_callee_name()
262
297
  {
263
298
  VALUE backtrace_arr = rb_funcall(rb_mKernel, rb_intern("caller"), 1, INT2NUM(0));
264
299
  if (backtrace_arr) {
265
300
  VALUE backtrace = rb_funcall(backtrace_arr, rb_intern("first"), 0);
266
301
  if (backtrace) {
267
- VALUE re = rb_funcall(rb_cRegexp, rb_intern("new"), 1, rb_str_new2("^(.+?):(\\d+)(?::in `(.*)')?"));
268
- VALUE m = rb_funcall(backtrace, rb_intern("match"), 1, re);
269
- if (m) {
302
+ VALUE m = rb_funcall(backtrace, rb_intern("match"), 1, backtrace_re);
303
+ if (m!=Qnil) {
270
304
  return rb_funcall(m, rb_intern("[]"), 1, INT2NUM(3));
271
305
  }
272
306
  }
@@ -287,16 +321,50 @@ VALUE call_php_method_bridge(zend_class_entry *ce, zval *obj, VALUE callee, int
287
321
  find_zend_function(ce, RSTRING_PTR(callee), RSTRING_LEN(callee), &mptr);
288
322
 
289
323
  // call
290
- zval *retval;
291
- int result = call_php_method(ce, obj, mptr, argc, argv, &retval TSRMLS_CC);
324
+ zval *z_val;
325
+ if (mptr) {
326
+ // call method
327
+ int result = call_php_method(ce, obj, mptr, argc, argv, &z_val TSRMLS_CC);
292
328
 
293
- // exception
294
- if (result==FAILURE) {
295
- // TODO: read var
296
- // TODO: raise exception. method missing
329
+ // exception
330
+ if (result==FAILURE) {
331
+ char *message = malloc(32+RSTRING_LEN(callee));
332
+ sprintf(message, "raise exception: %s", RSTRING_PTR(callee));
333
+ VALUE exception = rb_exc_new2(rb_ePHPError, message);
334
+ free(message);
335
+ rb_exc_raise(exception);
336
+ }
337
+ } else {
338
+ VALUE is_setter = rb_funcall(callee, rb_intern("end_with?"), 1, rb_str_new2("="));
339
+
340
+ if (is_setter) {
341
+ // setter
342
+ rb_funcall(callee, rb_intern("gsub!"), 2, rb_str_new2("="), rb_str_new2(""));
343
+ MAKE_STD_ZVAL(z_val);
344
+ value_to_zval(argv[0], z_val);
345
+
346
+ if (obj) {
347
+ // instance
348
+ add_property_zval(obj, RSTRING_PTR(callee), z_val);
349
+ } else {
350
+ // static
351
+ zend_update_static_property(ce, RSTRING_PTR(callee), RSTRING_LEN(callee), z_val TSRMLS_CC);
352
+ }
353
+
354
+ return Qnil;
355
+ } else {
356
+ // getter
357
+ if (obj) {
358
+ // instance
359
+ z_val = zend_read_property(ce, obj, RSTRING_PTR(callee), RSTRING_LEN(callee), 0 TSRMLS_CC);
360
+ } else {
361
+ // static
362
+ z_val = zend_read_static_property(ce, RSTRING_PTR(callee), RSTRING_LEN(callee), 0 TSRMLS_CC);
363
+ }
364
+ }
297
365
  }
298
366
 
299
- return zval_to_value(retval);
367
+ return zval_to_value(z_val);
300
368
  }
301
369
 
302
370
 
@@ -426,6 +494,7 @@ VALUE rb_php_class_initialize(VALUE self, VALUE v_name)
426
494
  rb_iv_set(self, "php_native_resource", resource);
427
495
 
428
496
  // define php static methods
497
+ define_php_properties(self, *ce, 1);
429
498
  define_php_methods(self, *ce, 1);
430
499
 
431
500
  return self;
@@ -451,11 +520,26 @@ VALUE rb_php_class_new(int argc, VALUE *argv, VALUE self)
451
520
  rb_php_object_initialize(obj, self, args);
452
521
 
453
522
  // define php instance method
523
+ define_php_properties(obj, ce, 0);
454
524
  define_php_methods(obj, ce, 0);
455
525
 
456
526
  return obj;
457
527
  }
458
528
 
529
+ VALUE rb_php_class_getter(VALUE self)
530
+ {
531
+ zend_class_entry *ce = get_zend_class_entry(self);
532
+ VALUE callee = get_callee_name();
533
+ return call_php_method_bridge(ce, NULL, callee, 0, NULL);
534
+ }
535
+
536
+ VALUE rb_php_class_setter(VALUE self, VALUE value)
537
+ {
538
+ zend_class_entry *ce = get_zend_class_entry(self);
539
+ VALUE callee = get_callee_name();
540
+ return call_php_method_bridge(ce, NULL, callee, 1, &value);
541
+ }
542
+
459
543
  VALUE rb_php_class_call(int argc, VALUE *argv, VALUE self)
460
544
  {
461
545
  zend_class_entry *ce = get_zend_class_entry(self);
@@ -492,6 +576,22 @@ VALUE rb_php_object_php_class(VALUE self)
492
576
  return rb_iv_get(self, "php_class");
493
577
  }
494
578
 
579
+ VALUE rb_php_object_getter(VALUE self)
580
+ {
581
+ zend_class_entry *ce = get_zend_class_entry(self);
582
+ zval *zobj = get_zval(self);
583
+ VALUE callee = get_callee_name();
584
+ return call_php_method_bridge(ce, zobj, callee, 0, NULL);
585
+ }
586
+
587
+ VALUE rb_php_object_setter(VALUE self, VALUE value)
588
+ {
589
+ zend_class_entry *ce = get_zend_class_entry(self);
590
+ zval *zobj = get_zval(self);
591
+ VALUE callee = get_callee_name();
592
+ return call_php_method_bridge(ce, zobj, callee, 1, &value);
593
+ }
594
+
495
595
  VALUE rb_php_object_call(int argc, VALUE *argv, VALUE self)
496
596
  {
497
597
  zend_class_entry *ce = get_zend_class_entry(self);
@@ -531,6 +631,8 @@ void Init_php_vm()
531
631
  php_vm_module_init();
532
632
  atexit(php_vm_module_exit);
533
633
 
634
+ backtrace_re = rb_funcall(rb_cRegexp, rb_intern("new"), 1, rb_str_new2("^(.+?):(\\d+)(?::in `(.*)')?"));
635
+
534
636
  // module PHPVM
535
637
  rb_mPHPVM = rb_define_module("PHPVM");
536
638
 
@@ -539,7 +641,7 @@ void Init_php_vm()
539
641
  rb_define_singleton_method(rb_mPHPVM, "exec", rb_php_vm_exec, 1);
540
642
  rb_define_singleton_method(rb_mPHPVM, "getClass", rb_php_vm_getClass, 1);
541
643
 
542
- rb_define_const(rb_mPHPVM, "VERSION", rb_str_new2("1.0.4"));
644
+ rb_define_const(rb_mPHPVM, "VERSION", rb_str_new2("1.1.0"));
543
645
 
544
646
  // class PHPVM::PHPClass
545
647
  rb_cPHPClass = rb_define_class_under(rb_mPHPVM, "PHPClass", rb_cObject);
data/ext/php_vm/php_vm.h CHANGED
@@ -27,6 +27,7 @@ extern void find_zend_class_entry2(char *name, zend_class_entry ***ce);
27
27
  extern int is_exception_zend_class_entry(zend_class_entry *ce TSRMLS_DC);
28
28
  extern int is_exception_zval(zval *z TSRMLS_DC);
29
29
  extern int new_php_object(zend_class_entry *ce, VALUE v_args, zval *retval);
30
+ extern void define_php_properties(VALUE v_obj, zend_class_entry *ce, int is_static);
30
31
  extern void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static);
31
32
  extern int call_php_method(zend_class_entry *ce, zval *obj, zend_function *mptr, int argc, VALUE *v_argv, zval **retval_ptr TSRMLS_DC);
32
33
 
@@ -49,11 +50,15 @@ extern VALUE rb_php_class_get(VALUE cls, VALUE rbv_name);
49
50
  extern VALUE rb_php_class_initialize(VALUE self, VALUE rbv_name);
50
51
  extern VALUE rb_php_class_name(VALUE self);
51
52
  extern VALUE rb_php_class_new(int argc, VALUE *argv, VALUE self);
53
+ extern VALUE rb_php_class_getter(VALUE self);
54
+ extern VALUE rb_php_class_setter(VALUE self, VALUE value);
52
55
  extern VALUE rb_php_class_call(int argc, VALUE *argv, VALUE self);
53
56
 
54
57
  // class PHPVM::PHPObject
55
58
  extern VALUE rb_php_object_initialize(VALUE self, VALUE class, VALUE arg_arr);
56
59
  extern VALUE rb_php_object_php_class(VALUE self);
60
+ extern VALUE rb_php_object_getter(VALUE self);
61
+ extern VALUE rb_php_object_setter(VALUE self, VALUE value);
57
62
  extern VALUE rb_php_object_call(int argc, VALUE *argv, VALUE self);
58
63
 
59
64
  // module
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: php_vm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: