You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2011/02/26 22:34:08 UTC

[lucy-commits] svn commit: r1074934 - in /incubator/lucy/trunk/clownfish: lib/Clownfish.xs lib/Clownfish/Dumpable.pm src/CFCDumpable.c src/CFCDumpable.h

Author: marvin
Date: Sat Feb 26 21:34:08 2011
New Revision: 1074934

URL: http://svn.apache.org/viewvc?rev=1074934&view=rev
Log:
Port some of Clownfish::Dumpable to C.

Modified:
    incubator/lucy/trunk/clownfish/lib/Clownfish.xs
    incubator/lucy/trunk/clownfish/lib/Clownfish/Dumpable.pm
    incubator/lucy/trunk/clownfish/src/CFCDumpable.c
    incubator/lucy/trunk/clownfish/src/CFCDumpable.h

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish.xs
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish.xs?rev=1074934&r1=1074933&r2=1074934&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish.xs (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish.xs Sat Feb 26 21:34:08 2011
@@ -404,6 +404,39 @@ DESTROY(self)
 PPCODE:
     CFCDumpable_destroy(self);
 
+SV*
+_make_method_obj(self, klass, method_name)
+    CFCDumpable *self;
+    CFCClass    *klass;
+    const char  *method_name;
+CODE:
+    CFCMethod *method = CFCDumpable_make_method_obj(self, klass, method_name);
+    RETVAL = newRV(CFCBase_get_perl_obj((CFCBase*)method));
+    CFCBase_decref((CFCBase*)method);
+OUTPUT: RETVAL
+
+SV*
+_process_dump_member(member)
+    CFCVariable *member;
+CODE:
+    RETVAL = newSV(400);
+    SvPOK_on(RETVAL);
+    char *buf = SvPVX(RETVAL);
+    CFCDumpable_process_dump_member(member, buf, 400);
+    SvCUR_set(RETVAL, strlen(buf));
+OUTPUT: RETVAL
+
+SV*
+_process_load_member(member)
+    CFCVariable *member;
+CODE:
+    RETVAL = newSV(400);
+    SvPOK_on(RETVAL);
+    char *buf = SvPVX(RETVAL);
+    CFCDumpable_process_load_member(member, buf, 400);
+    SvCUR_set(RETVAL, strlen(buf));
+OUTPUT: RETVAL
+
 
 MODULE = Clownfish    PACKAGE = Clownfish::File
 

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish/Dumpable.pm
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish/Dumpable.pm?rev=1074934&r1=1074933&r2=1074934&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish/Dumpable.pm (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish/Dumpable.pm Sat Feb 26 21:34:08 2011
@@ -48,58 +48,6 @@ sub add_dumpables {
     }
 }
 
-# Create a Clownfish::Method object for either Dump() or Load().
-sub _make_method_obj {
-    my ( $self, $class, $dump_or_load ) = @_;
-    my $return_type = Clownfish::Type->new_object(
-        incremented => 1,
-        specifier   => 'Obj',
-        indirection => 1,
-        parcel      => 'Lucy',
-    );
-    my $self_type = Clownfish::Type->new_object(
-        specifier   => $class->get_struct_sym,
-        indirection => 1,
-        parcel      => $class->get_parcel,
-    );
-    my $self_var = Clownfish::Variable->new(
-        type      => $self_type,
-        parcel    => $class->get_parcel,
-        micro_sym => 'self',
-    );
-
-    my $param_list;
-    if ( $dump_or_load eq 'Dump' ) {
-        $param_list = Clownfish::ParamList->new;
-        $param_list->add_param( $self_var, undef );
-    }
-    else {
-        my $dump_type = Clownfish::Type->new_object(
-            specifier   => 'Obj',
-            indirection => 1,
-            parcel      => 'Lucy',
-        );
-        my $dump_var = Clownfish::Variable->new(
-            type      => $dump_type,
-            parcel    => $class->get_parcel,
-            micro_sym => 'dump',
-        );
-        $param_list = Clownfish::ParamList->new;
-        $param_list->add_param( $self_var, undef );
-        $param_list->add_param( $dump_var, undef );
-    }
-
-    return Clownfish::Method->new(
-        parcel      => $class->get_parcel,
-        return_type => $return_type,
-        class_name  => $class->get_class_name,
-        class_cnick => $class->get_cnick,
-        param_list  => $param_list,
-        macro_sym   => $dump_or_load,
-        exposure    => 'public',
-    );
-}
-
 sub _add_dump_method {
     my ( $self, $class ) = @_;
     my $method = $self->_make_method_obj( $class, 'Dump' );
@@ -136,37 +84,12 @@ END_STUFF
     }
 
     for my $member_var (@members) {
-        $autocode .= $self->_process_dump_member( $class, $member_var );
+        $autocode .= _process_dump_member($member_var);
     }
     $autocode .= "    return (cfish_Obj*)dump;\n}\n\n";
     $class->append_autocode($autocode);
 }
 
-sub _process_dump_member {
-    my ( $self, $class, $member ) = @_;
-    my $type = $member->get_type;
-    my $name = $member->micro_sym;
-    my $len  = length($name);
-    if ( $type->is_integer ) {
-        return qq|    Cfish_Hash_Store_Str(dump, "$name", $len, |
-            . qq|(cfish_Obj*)cfish_CB_newf("%i64", (int64_t)self->$name));\n|;
-    }
-    elsif ( $type->is_floating ) {
-        return qq|    Cfish_Hash_Store_Str(dump, "$name", $len, |
-            . qq|(cfish_Obj*)cfish_CB_newf("%f64", (double)self->$name));\n|;
-    }
-    elsif ( $type->is_object ) {
-        return <<END_STUFF;
-    if (self->$name) {
-         Cfish_Hash_Store_Str(dump, "$name", $len, Cfish_Obj_Dump((cfish_Obj*)self->$name));
-    }
-END_STUFF
-    }
-    else {
-        confess( "Don't know how to dump a " . $type->get_specifier );
-    }
-}
-
 sub _add_load_method {
     my ( $self, $class ) = @_;
     my $method = $self->_make_method_obj( $class, 'Load' );
@@ -209,34 +132,12 @@ END_STUFF
     }
 
     for my $member_var (@members) {
-        $autocode .= $self->_process_load_member( $class, $member_var );
+        $autocode .= _process_load_member($member_var);
     }
     $autocode .= "    return (cfish_Obj*)loaded;\n}\n\n";
     $class->append_autocode($autocode);
 }
 
-sub _process_load_member {
-    my ( $self, $class, $member ) = @_;
-    my $type       = $member->get_type;
-    my $type_str   = $type->to_c;
-    my $name       = $member->micro_sym;
-    my $len        = length($name);
-    my $struct_sym = $type->get_specifier;
-    my $vtable_var = uc($struct_sym);
-    my $extraction
-        = $type->is_integer  ? qq|($type_str)Cfish_Obj_To_I64(var)|
-        : $type->is_floating ? qq|($type_str)Cfish_Obj_To_F64(var)|
-        : $type->is_object
-        ? qq|($struct_sym*)CFISH_CERTIFY(Cfish_Obj_Load(var, var), $vtable_var)|
-        : confess( "Don't know how to load " . $type->get_specifier );
-    return <<END_STUFF;
-    {
-        cfish_Obj *var = Cfish_Hash_Fetch_Str(source, "$name", $len);
-        if (var) { loaded->$name = $extraction; }
-    }
-END_STUFF
-}
-
 1;
 
 __END__

Modified: incubator/lucy/trunk/clownfish/src/CFCDumpable.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCDumpable.c?rev=1074934&r1=1074933&r2=1074934&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCDumpable.c (original)
+++ incubator/lucy/trunk/clownfish/src/CFCDumpable.c Sat Feb 26 21:34:08 2011
@@ -19,9 +19,21 @@
 #include "perl.h"
 #include "XSUB.h"
 
+#ifndef true
+    #define true 1
+    #define false 0
+#endif
+
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCDumpable.h"
+#include "CFCClass.h"
+#include "CFCMethod.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCSymbol.h"
+#include "CFCType.h"
+#include "CFCVariable.h"
 #include "CFCUtil.h"
 
 struct CFCDumpable {
@@ -48,3 +60,154 @@ CFCDumpable_destroy(CFCDumpable *self)
     CFCBase_destroy((CFCBase*)self);
 }
 
+CFCMethod*
+CFCDumpable_make_method_obj(CFCDumpable *self, CFCClass *klass, 
+                            const char *method_name)
+{
+    const char *klass_struct_sym = CFCClass_get_struct_sym(klass);
+    const char *klass_name   = CFCSymbol_get_class_name((CFCSymbol*)klass);
+    const char *klass_cnick  = CFCSymbol_get_class_cnick((CFCSymbol*)klass);
+    CFCParcel  *klass_parcel = CFCSymbol_get_parcel((CFCSymbol*)klass);
+    CFCParcel  *cf_parcel    = CFCParcel_clownfish_parcel();
+
+    CFCType *return_type 
+        = CFCType_new_object(CFCTYPE_INCREMENTED, cf_parcel, "Obj", 1);
+    CFCType *self_type = CFCType_new_object(0, klass_parcel, klass_struct_sym, 1);
+    CFCVariable *self_var = CFCVariable_new(klass_parcel, NULL, klass_name,
+        klass_cnick, "self", self_type);
+    CFCParamList *param_list = NULL;
+
+    if (strcmp(method_name, "Dump") == 0) {
+        param_list = CFCParamList_new(false);
+        CFCParamList_add_param(param_list, self_var, NULL);
+    }
+    else if (strcmp(method_name, "Load") == 0) {
+        CFCType *dump_type = CFCType_new_object(0, cf_parcel, "Obj", 1);
+        CFCVariable *dump_var = CFCVariable_new(cf_parcel, NULL, NULL,
+            NULL, "dump", dump_type);
+        param_list = CFCParamList_new(false);
+        CFCParamList_add_param(param_list, self_var, NULL);
+        CFCParamList_add_param(param_list, dump_var, NULL);
+        CFCBase_decref((CFCBase*)dump_var);
+        CFCBase_decref((CFCBase*)dump_type);
+    }
+    else {
+        croak("Unexpected method_name: '%s'", method_name);
+    }
+
+    CFCMethod *method = CFCMethod_new(klass_parcel, "public", klass_name,
+        klass_cnick, method_name, return_type, param_list, NULL, false, 
+        false);
+
+    CFCBase_decref((CFCBase*)param_list);
+    CFCBase_decref((CFCBase*)self_type);
+    CFCBase_decref((CFCBase*)self_var);
+    CFCBase_decref((CFCBase*)return_type);
+
+    return method;
+}
+
+void
+CFCDumpable_process_dump_member(CFCVariable *member, char *buf, 
+                                size_t buf_size)
+{
+    CFCUTIL_NULL_CHECK(member);
+    CFCType *type = CFCVariable_get_type(member);
+    const char *name = CFCSymbol_micro_sym((CFCSymbol*)member);
+    unsigned name_len = (unsigned)strlen(name);
+
+    if (CFCType_is_integer(type) || CFCType_is_floating(type)) {
+        char int_template[] = 
+            "    Cfish_Hash_Store_Str(dump, \"%s\", %u, (cfish_Obj*)cfish_CB_newf(\"%%i64\", (int64_t)self->%s));\n";
+        char float_template[] = 
+            "    Cfish_Hash_Store_Str(dump, \"%s\", %u, (cfish_Obj*)cfish_CB_newf(\"%%f64\", (double)self->%s));\n";
+        const char *template = CFCType_is_integer(type) 
+                             ? int_template : float_template;
+        size_t needed = strlen(template) + name_len * 2 + 20;
+        if (buf_size < needed) {
+            croak("Buffer not big enough (%lu < %lu)", 
+                (unsigned long)buf_size, (unsigned long)needed);
+        }
+        int check = sprintf(buf, template, name, name_len, name);
+        if (check < 0) { croak("sprintf failed"); }
+        return;
+    }
+    else if (CFCType_is_object(type)) {
+        char template[] = 
+            "    if (self->%s) {\n"
+            "        Cfish_Hash_Store_Str(dump, \"%s\", %u, Cfish_Obj_Dump((cfish_Obj*)self->%s));\n"
+            "    }\n";
+
+        size_t needed = strlen(template) + name_len * 3 + 20;
+        if (buf_size < needed) {
+            croak("Buffer not big enough (%lu < %lu)", 
+                (unsigned long)buf_size, (unsigned long)needed);
+        }
+        int check = sprintf(buf, template, name, name, name_len, name);
+        if (check < 0) { croak("sprintf failed"); }
+        return;
+    }
+    else {
+        croak("Don't know how to dump a %s", CFCType_get_specifier(type));
+    }
+}
+
+void
+CFCDumpable_process_load_member(CFCVariable *member, char *buf, 
+                                size_t buf_size)
+{
+    CFCUTIL_NULL_CHECK(member);
+    CFCType *type = CFCVariable_get_type(member);
+    const char *type_str = CFCType_to_c(type);
+    const char *name = CFCSymbol_micro_sym((CFCSymbol*)member);
+    unsigned name_len = (unsigned)strlen(name);
+    char extraction[200];
+    if (strlen(type_str) + 100 > sizeof(extraction)) { // play it safe
+        croak("type_str too long: '%s'", type_str);
+    }
+    if (CFCType_is_integer(type)) {
+        int check = sprintf(extraction, "(%s)Cfish_Obj_To_I64(var)", type_str);
+        if (check < 0) { croak("sprintf failed"); }
+    }
+    else if (CFCType_is_floating(type)) {
+        int check = sprintf(extraction, "(%s)Cfish_Obj_To_I64(var)", type_str);
+        if (check < 0) { croak("sprintf failed"); }
+    }
+    else if (CFCType_is_object(type)) {
+        const char *specifier = CFCType_get_specifier(type);
+        size_t specifier_len = strlen(specifier);
+        char vtable_var[50];
+        if (specifier_len > sizeof(vtable_var) - 2) {
+            croak("specifier too long: '%s'", specifier);
+        }
+        size_t i;
+        for (i = 0; i <= specifier_len; i++) {
+            vtable_var[i] = toupper(specifier[i]);
+        }
+        int check = sprintf(extraction, 
+             "(%s*)CFISH_CERTIFY(Cfish_Obj_Load(var, var), %s)",
+             specifier, vtable_var);
+        if (check < 0) { croak("sprintf failed"); }
+    }
+    else {
+        croak("Don't know how to load %s", CFCType_get_specifier(type));
+    }
+    
+    const char *template = 
+    "    {\n"
+    "        cfish_Obj *var = Cfish_Hash_Fetch_Str(source, \"%s\", %u);\n"
+    "        if (var) { loaded->%s = %s; }\n"
+    "    }\n";
+    size_t needed = sizeof(template) 
+                  + (name_len * 2) 
+                  + strlen(extraction) 
+                  + 20;
+    if (buf_size < needed) {
+        croak("Buffer not big enough (%lu < %lu)", (unsigned long)buf_size,
+            (unsigned long)needed);
+    }
+    int check = sprintf(buf, template, name, name_len, name, extraction);
+    if (check < 0) { croak("sprintf failed"); }
+}
+
+

Modified: incubator/lucy/trunk/clownfish/src/CFCDumpable.h
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCDumpable.h?rev=1074934&r1=1074933&r2=1074934&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCDumpable.h (original)
+++ incubator/lucy/trunk/clownfish/src/CFCDumpable.h Sat Feb 26 21:34:08 2011
@@ -18,6 +18,9 @@
 #define H_CFCDUMPABLE
 
 typedef struct CFCDumpable CFCDumpable;
+struct CFCClass;
+struct CFCMethod;
+struct CFCVariable;
 
 CFCDumpable*
 CFCDumpable_new(void);
@@ -28,5 +31,20 @@ CFCDumpable_init(CFCDumpable *self);
 void
 CFCDumpable_destroy(CFCDumpable *self);
 
+
+/** Create a Clownfish::Method object for either Dump() or Load().
+ */
+struct CFCMethod*
+CFCDumpable_make_method_obj(CFCDumpable *self, struct CFCClass *klass, 
+                            const char *method_name);
+
+void
+CFCDumpable_process_dump_member(struct CFCVariable *member, char *buf,
+                                size_t buf_size);
+
+void
+CFCDumpable_process_load_member(struct CFCVariable *member, char *buf,
+                                size_t buf_size);
+
 #endif /* H_CFCDUMPABLE */