Guest User

Untitled

a guest
Jun 20th, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.09 KB | None | 0 0
  1. #include "xshelper.h"
  2.  
  3. #define IsObject(sv) (SvROK(sv) && SvOBJECT(SvRV(sv)))
  4. #define IsArrayRef(sv) (SvROK(sv) && !SvOBJECT(SvRV(sv)) && SvTYPE(SvRV(sv)) == SVt_PVAV)
  5. #define IsHashRef(sv) (SvROK(sv) && !SvOBJECT(SvRV(sv)) && SvTYPE(SvRV(sv)) == SVt_PVHV)
  6. #define IsCodeRef(sv) (SvROK(sv) && !SvOBJECT(SvRV(sv)) && SvTYPE(SvRV(sv)) == SVt_PVCV)
  7.  
  8. #define XSCON_xc_stash(a) ( (HV*)XSCON_av_at((a), XSCON_XC_STASH) )
  9.  
  10. static HV*
  11. xscon_buildargs(char* const klass, I32 ax, I32 items) {
  12. HV* args;
  13.  
  14. /* shift @_ */
  15. ax++;
  16. items--;
  17.  
  18. if(items == 1){
  19. SV* const args_ref = ST(0);
  20. if(!IsHashRef(args_ref)){
  21. croak("Single parameters to new() must be a HASH ref");
  22. }
  23. args = newHVhv((HV*)SvRV(args_ref));
  24. sv_2mortal((SV*)args);
  25. }
  26. else{
  27. I32 i;
  28.  
  29. if( (items % 2) != 0 ){
  30. croak("Odd number of parameters to new()");
  31. }
  32.  
  33. args = newHV_mortal();
  34. for(i = 0; i < items; i += 2){
  35. (void)hv_store_ent(args, ST(i), newSVsv(ST(i+1)), 0U);
  36. }
  37.  
  38. }
  39. return args;
  40. }
  41.  
  42. SV*
  43. xscon_create_instance(char* const klass) {
  44. SV* instance;
  45. instance = sv_bless( newRV_noinc((SV*)newHV()), gv_stashpv(klass, 1) );
  46. return sv_2mortal(instance);
  47. }
  48.  
  49. static void
  50. xscon_initialize_object(char* const klass, SV* const object, HV* const args, bool const is_cloning) {
  51.  
  52. assert(object);
  53. assert(SvTYPE(object) == SVt_PVHV);
  54.  
  55. assert(args);
  56. assert(SvTYPE(args) == SVt_PVHV);
  57. if(mg_find((SV*)args, PERL_MAGIC_tied)){
  58. croak("You cannot use tied HASH reference as initializing arguments");
  59. }
  60.  
  61. HV* const stash = gv_stashpv(klass, 1);
  62. assert(stash != NULL);
  63.  
  64. /* find out allowed attributes */
  65. SV** const HAS_globref = hv_fetch(stash, "XSCON_HAS", 9, 0);
  66. AV* const HAS_attrs = GvAV(*HAS_globref);
  67. I32 const HAS_len = av_len(HAS_attrs) + 1;
  68.  
  69.  
  70. /* copy allowed attributes */
  71. I32 i;
  72. SV* attr;
  73. SV** tmp;
  74. char* keyname;
  75. I32 keylen;
  76. for (i = 0; i < HAS_len; i++) {
  77. tmp = av_fetch(HAS_attrs, i, 0);
  78. assert(tmp);
  79. attr = *tmp;
  80. keyname = SvPV(attr, keylen);
  81.  
  82. if (hv_exists(args, keyname, keylen)) {
  83. SV** val = hv_fetch(args, keyname, keylen, 0);
  84. SV* val2 = newSVsv(*val);
  85. sv_dump(val2);
  86. SV** val3 = hv_store(object, keyname, keylen, val2, 0);
  87. sv_dump(*val3);
  88. SvREFCNT_inc(*val3); //
  89. }
  90. }
  91. }
  92.  
  93. static void
  94. xscon_buildall(SV* const object, SV* const args) {
  95. /* todo */
  96. }
  97.  
  98. MODULE = Class::XSConstructor PACKAGE = Class::XSConstructor
  99.  
  100. void
  101. new(SV* klass, ...)
  102. CODE:
  103. {
  104. char* klassname;
  105. SV* args;
  106. SV* object;
  107.  
  108. klassname = SvROK(klass) ? sv_reftype(SvRV(klass), 1) : SvPV_nolen_const(klass);
  109. args = newRV_inc((SV*)xscon_buildargs(klassname, ax, items));
  110. sv_2mortal(args);
  111. object = xscon_create_instance(klassname);
  112. xscon_initialize_object(klassname, object, (HV*)SvRV(args), FALSE);
  113. xscon_buildall(object, args);
  114. ST(0) = object; /* because object is mortal, we should return it as is */
  115. XSRETURN(1);
  116. }
Add Comment
Please, Sign In to add comment