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 */