php_vm 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: