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/03 00:02:11 UTC
[lucy-commits] svn commit: r1066678 - in /incubator/lucy/trunk/clownfish: lib/Clownfish.xs
lib/Clownfish/Symbol.pm src/CFCSymbol.c t/051-symbol.t
Author: marvin
Date: Wed Feb 2 23:02:11 2011
New Revision: 1066678
URL: http://svn.apache.org/viewvc?rev=1066678&view=rev
Log:
Move some functionality (primarily validation) in the Clownfish::Symbol
constructor from Perl to C.
Modified:
incubator/lucy/trunk/clownfish/lib/Clownfish.xs
incubator/lucy/trunk/clownfish/lib/Clownfish/Symbol.pm
incubator/lucy/trunk/clownfish/src/CFCSymbol.c
incubator/lucy/trunk/clownfish/t/051-symbol.t
Modified: incubator/lucy/trunk/clownfish/lib/Clownfish.xs
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish.xs?rev=1066678&r1=1066677&r2=1066678&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish.xs (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish.xs Wed Feb 2 23:02:11 2011
@@ -162,18 +162,20 @@ PPCODE:
MODULE = Clownfish PACKAGE = Clownfish::Symbol
SV*
-_new(klass, parcel, exposure, class_name_sv, class_cnick_sv, micro_sym)
+_new(klass, parcel, exposure, class_name_sv, class_cnick_sv, micro_sym_sv)
const char *klass;
SV *parcel;
const char *exposure;
SV *class_name_sv;
SV *class_cnick_sv;
- const char *micro_sym;
+ SV *micro_sym_sv;
CODE:
const char *class_name = SvOK(class_name_sv)
? SvPV_nolen(class_name_sv) : NULL;
const char *class_cnick = SvOK(class_cnick_sv)
? SvPV_nolen(class_cnick_sv) : NULL;
+ const char *micro_sym = SvOK(micro_sym_sv)
+ ? SvPV_nolen(micro_sym_sv) : NULL;
CFCSymbol *self = CFCSymbol_new(parcel, exposure, class_name, class_cnick,
micro_sym);
RETVAL = newSV(0);
Modified: incubator/lucy/trunk/clownfish/lib/Clownfish/Symbol.pm
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/lib/Clownfish/Symbol.pm?rev=1066678&r1=1066677&r2=1066678&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/lib/Clownfish/Symbol.pm (original)
+++ incubator/lucy/trunk/clownfish/lib/Clownfish/Symbol.pm Wed Feb 2 23:02:11 2011
@@ -55,31 +55,6 @@ sub new {
$parcel = Clownfish::Parcel->singleton( name => $parcel );
}
- # Validate micro_sym.
- confess "micro_sym is required" unless $micro_sym;
- confess("Invalid micro_sym: '$micro_sym'")
- unless $micro_sym =~ /^[A-Za-z_][A-Za-z0-9_]*$/;
-
- # Validate exposure.
- confess("Invalid value for 'exposure': $exposure")
- unless $exposure =~ /^(?:public|parcel|private|local)$/;
-
- # Validate class name, validate or derive class_cnick.
- if ( defined $class_name ) {
- confess("Invalid class name: $class_name")
- unless $class_name =~ $class_name_regex;
- if ( !defined $class_cnick ) {
- $class_name =~ /(\w+)$/;
- $class_cnick = $1;
- }
- confess("Invalid class_cnick: $class_cnick")
- unless $class_cnick =~ /^[A-Z]+[A-Za-z0-9]*$/;
- }
- elsif ( defined $class_cnick ) {
- # Sanity check class_cnick without class_name.
- confess("Can't supply class_cnick without class_name");
- }
-
# Create the object.
my $class_class = ref($either) || $either;
return $class_class->_new( $parcel, $exposure, $class_name, $class_cnick,
Modified: incubator/lucy/trunk/clownfish/src/CFCSymbol.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/src/CFCSymbol.c?rev=1066678&r1=1066677&r2=1066678&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/src/CFCSymbol.c (original)
+++ incubator/lucy/trunk/clownfish/src/CFCSymbol.c Wed Feb 2 23:02:11 2011
@@ -15,10 +15,17 @@
*/
#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
+#ifndef true
+ #define true 1
+ #define false 0
+#endif
+
#define CFC_NEED_SYMBOL_STRUCT_DEF
#include "CFCSymbol.h"
@@ -36,16 +43,130 @@ CFCSymbol_new(void *parcel, const char *
micro_sym);
}
+static int
+S_validate_exposure(const char *exposure)
+{
+ if (!exposure) { return false; }
+ if ( strcmp(exposure, "public")
+ && strcmp(exposure, "parcel")
+ && strcmp(exposure, "private")
+ && strcmp(exposure, "local")
+ ) {
+ return false;
+ }
+ return true;
+}
+
+static int
+S_validate_class_name(const char *class_name)
+{
+ const char *ptr;
+
+ // Must be UpperCamelCase, separated by "::".
+ for (ptr = class_name; *ptr != 0; ) {
+ if (!isupper(*ptr)) { return false; }
+
+ // Each component must contain lowercase letters.
+ const char *substring;
+ for (substring = ptr; ; substring++) {
+ if (*substring == 0) { return false; }
+ else if (*substring == ':') { return false; }
+ else if (islower(*substring)) { break; }
+ }
+
+ while(*ptr != 0) {
+ if (*ptr == 0) { break; }
+ else if (*ptr == ':') {
+ ptr++;
+ if (*ptr != ':') { return false; }
+ ptr++;
+ if (*ptr == 0) { return false; }
+ break;
+ }
+ else if (!isalnum(*ptr)) { return false; }
+ ptr++;
+ }
+ }
+
+ return true;
+}
+
+static int
+S_validate_class_cnick(const char *class_cnick)
+{
+ // Allow all caps.
+ const char *ptr;
+ for (ptr = class_cnick; ; ptr++) {
+ if (*ptr == 0) {
+ if (strlen(class_cnick)) { return true; }
+ else { break; }
+ }
+ else if (!isupper(*ptr)) { break; }
+ }
+
+ // Same as one component of a class name.
+ if (!S_validate_class_name(class_cnick)) { return false; }
+ if (strchr(class_cnick, ':') != NULL) { return false; }
+ return true;
+}
+
+static int
+S_validate_identifier(const char *identifier)
+{
+ const char *ptr = identifier;
+ if (!isalpha(*ptr) && *ptr != '_') { return false; }
+ for ( ; *ptr != 0; ptr++) {
+ if (!isalnum(*ptr) && *ptr != '_') { return false; }
+ }
+ return true;
+}
+
CFCSymbol*
CFCSymbol_init(CFCSymbol *self, void *parcel, const char *exposure,
const char *class_name, const char *class_cnick,
const char *micro_sym)
{
- self->parcel = newSVsv((SV*)parcel);
- self->exposure = savepv(exposure);
- self->class_name = savepv(class_name);
- self->class_cnick = savepv(class_cnick);
- self->micro_sym = savepv(micro_sym);
+ self->parcel = newSVsv((SV*)parcel);
+
+ // Validate exposure.
+ if (!S_validate_exposure(exposure)) {
+ croak("Invalid exposure: '%s'", exposure ? exposure : "[NULL]");
+ }
+ self->exposure = savepv(exposure);
+
+ // Validate class name (if supplied);
+ if (class_name && !S_validate_class_name(class_name)) {
+ croak("Invalid class_name: '%s'", class_name);
+ }
+ self->class_name = savepv(class_name);
+
+ // Derive class_cnick if necessary, then validate.
+ if (class_name) {
+ if (class_cnick) {
+ self->class_cnick = savepv(class_cnick);
+ }
+ else {
+ const char *last_colon = strrchr(class_name, ':');
+ const char *cnick = last_colon ? last_colon + 1 : class_name;
+ self->class_cnick = savepv(cnick);
+ }
+ }
+ else if (class_cnick) {
+ // Sanity check class_cnick without class_name.
+ croak("Can't supply class_cnick without class_name");
+ }
+ else {
+ self->class_cnick = NULL;
+ }
+ if (self->class_cnick && !S_validate_class_cnick(self->class_cnick)) {
+ croak("Invalid class_cnick: '%s'", self->class_cnick);
+ }
+
+ if (!micro_sym || !S_validate_identifier(micro_sym)) {
+ croak("Invalid micro_sym: '%s'", micro_sym ? micro_sym : "[NULL]");
+ }
+ self->micro_sym = savepv(micro_sym);
+
return self;
}
Modified: incubator/lucy/trunk/clownfish/t/051-symbol.t
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/clownfish/t/051-symbol.t?rev=1066678&r1=1066677&r2=1066678&view=diff
==============================================================================
--- incubator/lucy/trunk/clownfish/t/051-symbol.t (original)
+++ incubator/lucy/trunk/clownfish/t/051-symbol.t Wed Feb 2 23:02:11 2011
@@ -28,10 +28,10 @@ use Test::More tests => 44;
for (qw( foo FOO 1Foo Foo_Bar FOOBAR 1FOOBAR )) {
eval { my $thing = ClownfishyThing->new( class_name => $_ ) };
- like( $@, qr/class name/, "Reject invalid class name $_" );
+ like( $@, qr/class_name/, "Reject invalid class name $_" );
my $bogus_middle = "Foo::" . $_ . "::Bar";
eval { my $thing = ClownfishyThing->new( class_name => $bogus_middle ) };
- like( $@, qr/class name/, "Reject invalid class name $bogus_middle" );
+ like( $@, qr/class_name/, "Reject invalid class name $bogus_middle" );
}
my @exposures = qw( public private parcel local );