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/20 03:44:08 UTC

[lucy-commits] svn commit: r1072480 - in /incubator/lucy/trunk/clownfish: lib/Clownfish.xs lib/Clownfish/File.pm lib/Clownfish/Parser.pm src/CFCFile.c src/CFCFile.h

Author: marvin
Date: Sun Feb 20 02:44:07 2011
New Revision: 1072480

URL: http://svn.apache.org/viewvc?rev=1072480&view=rev
Log:
Port the rest of Clownfish::File to C.

Modified:
    incubator/lucy/trunk/clownfish/lib/Clownfish.xs
    incubator/lucy/trunk/clownfish/lib/Clownfish/File.pm
    incubator/lucy/trunk/clownfish/lib/Clownfish/Parser.pm
    incubator/lucy/trunk/clownfish/src/CFCFile.c
    incubator/lucy/trunk/clownfish/src/CFCFile.h

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish.xs
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish.xs?rev=1072480&r1=1072479&r2=1072480&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish.xs (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish.xs Sun Feb 20 02:44:07 2011
@@ -210,6 +210,13 @@ PPCODE:
     CFCFile_destroy(self);
 
 void
+add_block(self, block)
+    CFCFile *self;
+    CFCBase *block;
+PPCODE:
+    CFCFile_add_block(self, block);
+
+void
 _set_or_get(self, ...)
     CFCFile *self;
 ALIAS:
@@ -219,6 +226,8 @@ ALIAS:
     guard_name         = 6
     guard_start        = 8
     guard_close        = 10 
+    blocks             = 12
+    classes            = 14
 PPCODE:
 {
     START_SET_OR_GET_SWITCH
@@ -248,9 +257,66 @@ PPCODE:
                 retval = newSVpv(value, strlen(value));
             }
             break;
+        case 12: {
+            AV *av = newAV();
+            CFCBase **blocks = CFCFile_blocks(self);
+            size_t i;
+            for (i = 0; blocks[i] != NULL; i++) {
+                SV *ref = newRV((SV*)CFCBase_get_perl_obj(blocks[i]));
+                av_store(av, i, ref);
+            }
+            retval = newRV((SV*)av);
+            SvREFCNT_dec(av);
+            break;
+        }
+        case 14: {
+            AV *av = newAV();
+            CFCClass **classes = CFCFile_classes(self);
+            size_t i;
+            for (i = 0; classes[i] != NULL; i++) {
+                SV *ref = newRV((SV*)CFCBase_get_perl_obj(
+                    (CFCBase*)classes[i]));
+                av_store(av, i, ref);
+            }
+            retval = newRV((SV*)av);
+            SvREFCNT_dec(av);
+            break;
+        }
     END_SET_OR_GET_SWITCH
 }
 
+SV*
+_gen_path(self, base_dir = NULL)
+    CFCFile *self;
+    const char *base_dir;
+ALIAS:
+    c_path       = 1
+    h_path       = 2
+    cfh_path     = 3
+CODE:
+{
+    size_t buf_size = CFCFile_path_buf_size(self, base_dir);
+    RETVAL = newSV(buf_size);
+    SvPOK_on(RETVAL);
+    char *buf = SvPVX(RETVAL);
+    switch(ix) {
+        case 1: 
+            CFCFile_c_path(self, buf, buf_size, base_dir);
+            break;
+        case 2: 
+            CFCFile_h_path(self, buf, buf_size, base_dir);
+            break;
+        case 3: 
+            CFCFile_cfh_path(self, buf, buf_size, base_dir);
+            break;
+        default:
+            croak("unexpected ix value: %d", ix);
+    }
+    SvCUR_set(RETVAL, strlen(buf));
+}
+OUTPUT: RETVAL
+
+
 MODULE = Clownfish    PACKAGE = Clownfish::Function
 
 SV*

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish/File.pm
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish/File.pm?rev=1072480&r1=1072479&r2=1072480&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish/File.pm (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish/File.pm Sun Feb 20 02:44:07 2011
@@ -17,68 +17,16 @@ use strict;
 use warnings;
 
 package Clownfish::File;
-use Clownfish::Util qw( verify_args a_isa_b );
-use Clownfish::Parcel;
-use Scalar::Util qw( blessed );
-use File::Spec::Functions qw( catfile );
+use Clownfish::Util qw( verify_args );
 use Carp;
 
-# Inside out member vars.
-our %blocks;
-
-our %new_PARAMS = (
-    source_class => undef,
-);
+our %new_PARAMS = ( source_class => undef, );
 
 sub new {
     my ( $either, %args ) = @_;
     verify_args( \%new_PARAMS, %args ) or confess $@;
     my $package = ref($either) || $either;
-    my $self = $either->_new($args{source_class});
-    $blocks{$self} = [];
-    return $self;
-}
-
-sub DESTROY {
-    my $self = shift;
-    delete $blocks{$self};
-    $self->_destroy;
-}
-
-our %block_types = (
-    'Clownfish::Parcel' => 1,
-    'Clownfish::Class'  => 1,
-    'Clownfish::CBlock' => 1,
-);
-
-sub add_block {
-    my ( $self, $block ) = @_;
-    my $block_class = ref($block);
-    confess("Invalid block type: $block_class")
-        unless $block_types{$block_class};
-    push @{ $blocks{$self} }, $block;
-}
-
-sub blocks { $blocks{ +shift } }
-
-sub classes {
-    my $self = shift;
-    my @classes
-        = grep { ref $_ and $_->isa('Clownfish::Class') } @{ $self->blocks };
-    return \@classes;
-}
-
-sub c_path   { return $_[0]->_some_path( $_[1], '.c' ) }
-sub h_path   { return $_[0]->_some_path( $_[1], '.h' ) }
-sub cfh_path { return $_[0]->_some_path( $_[1], '.cfh' ) }
-
-sub _some_path {
-    my ( $self, $base_dir, $ext ) = @_;
-    my @components = split( '::', $self->get_source_class );
-    unshift @components, $base_dir
-        if defined $base_dir;
-    $components[-1] .= $ext;
-    return catfile(@components);
+    return $either->_new( $args{source_class} );
 }
 
 1;

Modified: incubator/lucy/trunk/clownfish/lib/Clownfish/Parser.pm
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish/Parser.pm?rev=1072480&r1=1072479&r2=1072480&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish/Parser.pm (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish/Parser.pm Sun Feb 20 02:44:07 2011
@@ -508,7 +508,7 @@ sub new_file {
     my ( undef, $item, $arg ) = @_;
     my $file = Clownfish::File->new( source_class => $arg->{source_class}, );
     for my $block ( @{ $item->{'major_block(s)'} } ) {
-        $file->add_block( $block, ref($block) );
+        $file->add_block($block);
     }
     return $file;
 }

Modified: incubator/lucy/trunk/clownfish/src/CFCFile.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCFile.c?rev=1072480&r1=1072479&r2=1072480&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCFile.c (original)
+++ incubator/lucy/trunk/clownfish/src/CFCFile.c Sun Feb 20 02:44:07 2011
@@ -24,18 +24,30 @@
     #define false 0
 #endif
 
+#ifdef _WIN32
+#define PATH_SEP "\\"
+#define PATH_SEP_CHAR '\\' 
+#else
+#define PATH_SEP "/"
+#define PATH_SEP_CHAR '/' 
+#endif
+
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCFile.h"
 #include "CFCUtil.h"
+#include "CFCClass.h"
 
 struct CFCFile {
     CFCBase base;
+    CFCBase **blocks;
+    CFCClass **classes;
     int modified;
     char *source_class;
     char *guard_name;
     char *guard_start;
     char *guard_close;
+    char *path_part;
 };
 
 CFCFile*
@@ -53,6 +65,9 @@ CFCFile_init(CFCFile *self, const char *
     CFCUTIL_NULL_CHECK(source_class);
     self->modified = false;
     self->source_class = CFCUtil_strdup(source_class);
+    self->blocks = (CFCBase**)calloc(1, sizeof(CFCBase*));
+    self->classes = (CFCClass**)calloc(1, sizeof(CFCBase*));
+    if (!self->blocks || !self->classes) { croak("malloc failed"); }
 
     // Derive include guard name, plus C code for opening and closing the
     // guard.
@@ -72,7 +87,7 @@ CFCFile_init(CFCFile *self, const char *
             i++;
         }
         else {
-            self->guard_name[j] = toupper(source_class[i]);
+            self->guard_name[j] = toupper(c);
         }
     }
     self->guard_name[j] = '\0';
@@ -83,20 +98,157 @@ CFCFile_init(CFCFile *self, const char *
         self->guard_name);
     if (check < 0) { croak("sprintf failed"); }
 
+    // Cache partial path derived from source_class.
+    self->path_part = malloc(len + 1);
+    if (!self->path_part) { croak("malloc failed"); }
+    for (i = 0, j = 0; i < len; i++, j++) {
+        char c = source_class[i];
+        if (c == ':') {
+            self->path_part[j] = PATH_SEP_CHAR;
+            i++;
+        }
+        else {
+            self->path_part[j] = c;
+        }
+    }
+    self->path_part[j] = '\0';
+
     return self;
 }
 
 void
 CFCFile_destroy(CFCFile *self)
 {
+    size_t i;
+    /*
+    for (i = 0; self->blocks[i] != NULL; i++) {
+        CFCBase_decref(self->blocks[i]);
+    }
+    free(self->blocks);
+    for (i = 0; self->classes[i] != NULL; i++) {
+        CFCBase_decref((CFCBase*)self->classes[i]);
+    }
+    */
+    free(self->classes);
     free(self->guard_name);
     free(self->guard_start);
     free(self->guard_close);
     free(self->source_class);
+    free(self->path_part);
     CFCBase_destroy((CFCBase*)self);
 }
 
 void
+CFCFile_add_block(CFCFile *self, CFCBase *block)
+{
+    CFCUTIL_NULL_CHECK(block);
+    const char *cfc_class = CFCBase_get_cfc_class(block);
+
+    // Add to classes array if the block is a CFCClass.
+    if (strcmp(cfc_class, "Clownfish::Class") == 0) {
+        size_t num_class_blocks = 0;
+        while (self->classes[num_class_blocks] != NULL) { 
+            num_class_blocks++;
+        }
+        num_class_blocks++;
+        size_t size = (num_class_blocks + 1) * sizeof(CFCClass*);
+        self->classes = (CFCClass**)realloc(self->classes, size);
+        if (!self->classes) { croak("realloc failed"); }
+        self->classes[num_class_blocks - 1] 
+            = (CFCClass*)CFCBase_incref(block);
+        self->classes[num_class_blocks] = NULL;
+    }
+
+    // Add to blocks array.
+    if (   strcmp(cfc_class, "Clownfish::Class") == 0
+        || strcmp(cfc_class, "Clownfish::Parcel") == 0
+        || strcmp(cfc_class, "Clownfish::CBlock") == 0
+    ) {
+        size_t num_blocks = 0;
+        while (self->blocks[num_blocks] != NULL) { 
+            num_blocks++;
+        }
+        num_blocks++;
+        size_t size = (num_blocks + 1) * sizeof(CFCBase*);
+        self->blocks = (CFCBase**)realloc(self->blocks, size);
+        if (!self->blocks) { croak("realloc failed"); }
+        self->blocks[num_blocks - 1] = CFCBase_incref(block);
+        self->blocks[num_blocks] = NULL;
+    }
+    else {
+        croak("Wrong kind of object: '%s'", cfc_class);
+    }
+}
+
+static void
+S_some_path(CFCFile *self, char *buf, size_t buf_size, const char *base_dir, 
+            const char *ext)
+{
+    size_t needed = CFCFile_path_buf_size(self, base_dir);
+    if (strlen(ext) > 4) {
+        croak("ext cannot be more than 4 characters.");
+    }
+    if (needed > buf_size) {
+        croak("Need buf_size of %lu, but got %lu", needed, buf_size);
+    }
+    if (base_dir) {
+        int check = sprintf(buf, "%s" PATH_SEP "%s%s", base_dir, 
+            self->path_part, ext);
+        if (check < 0) { croak("sprintf failed"); }
+    }
+    else {
+        int check = sprintf(buf, "%s%s", self->path_part, ext);
+        if (check < 0) { croak("sprintf failed"); }
+    }
+}
+
+size_t
+CFCFile_path_buf_size(CFCFile *self, const char *base_dir)
+{
+    size_t size = strlen(self->path_part);
+    size += 4; // Max extension length.
+    size += 1; // NULL-termination.
+    if (base_dir) { 
+        size += strlen(base_dir);
+        size += strlen(PATH_SEP);
+    }
+    return size;
+}
+
+void
+CFCFile_c_path(CFCFile *self, char *buf, size_t buf_size, 
+               const char *base_dir)
+{
+    S_some_path(self, buf, buf_size, base_dir, ".c");
+}
+
+void
+CFCFile_h_path(CFCFile *self, char *buf, size_t buf_size, 
+               const char *base_dir)
+{
+    S_some_path(self, buf, buf_size, base_dir, ".h");
+}
+
+void
+CFCFile_cfh_path(CFCFile *self, char *buf, size_t buf_size, 
+                 const char *base_dir)
+{
+    S_some_path(self, buf, buf_size, base_dir, ".cfh");
+}
+
+CFCBase**
+CFCFile_blocks(CFCFile *self)
+{
+    return self->blocks;
+}
+
+CFCClass**
+CFCFile_classes(CFCFile *self)
+{
+    return self->classes;
+}
+
+void
 CFCFile_set_modified(CFCFile *self, int modified)
 {
     self->modified = !!modified;

Modified: incubator/lucy/trunk/clownfish/src/CFCFile.h
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCFile.h?rev=1072480&r1=1072479&r2=1072480&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCFile.h (original)
+++ incubator/lucy/trunk/clownfish/src/CFCFile.h Sun Feb 20 02:44:07 2011
@@ -18,6 +18,8 @@
 #define H_CFCFILE
 
 typedef struct CFCFile CFCFile;
+struct CFCBase;
+struct CFCClass;
 
 CFCFile*
 CFCFile_new(const char *source_class);
@@ -29,6 +31,33 @@ void
 CFCFile_destroy(CFCFile *self);
 
 void
+CFCFile_add_block(CFCFile *self, CFCBase *block);
+
+/** Calculate the size of the buffer needed for a call to c_path(), h_path(),
+ * or cfh_path().
+ */
+size_t
+CFCFile_path_buf_size(CFCFile *self, const char *base_dir);
+
+void
+CFCFile_c_path(CFCFile *self, char *buf, size_t buf_size, 
+               const char *base_dir);
+
+void
+CFCFile_h_path(CFCFile *self, char *buf, size_t buf_size, 
+               const char *base_dir);
+
+void
+CFCFile_cfh_path(CFCFile *self, char *buf, size_t buf_size, 
+                 const char *base_dir);
+
+struct CFCBase**
+CFCFile_blocks(CFCFile *self);
+
+struct CFCClass**
+CFCFile_classes(CFCFile *self);
+
+void
 CFCFile_set_modified(CFCFile *self, int modified);
 
 int