[perl-Cairo] Add support for flag types
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-Cairo] Add support for flag types
- Date: Sun, 16 May 2010 20:18:13 +0000 (UTC)
commit 97788e474d94f45306cb24d91aa1cb2342d3158e
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date: Sun May 16 21:03:54 2010 +0200
Add support for flag types
This will be needed for cairo_text_cluster_flags_t.
The refactoring during this change also fixes an off-by-one error in the enum
value conversion.
.gitignore | 1 +
Makefile.PL | 14 ++-
inc/MakeHelper.pm | 291 ++++++++++++++++++++++++++++++++++++++++-------------
3 files changed, 230 insertions(+), 76 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index b3a78f6..ac375d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ Makefile
blib
build
cairo-perl-enums.*
+cairo-perl-flags.*
pm_to_blib
diff --git a/Makefile.PL b/Makefile.PL
index 760f11d..335e751 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -215,6 +215,8 @@ my %enums = (
/],
);
+my %flags = ();
+
# --------------------------------------------------------------------------- #
my $have_cairo_1_2 = ExtUtils::PkgConfig->atleast_version("cairo", "1.2.0");
@@ -319,9 +321,11 @@ if ($have_cairo_1_6) {
my %enum_guards = (
cairo_svg_version_t => $backend_guards{cairo_svg_surface_t},
);
-
MakeHelper::do_enums (\%enums, \%enum_guards);
+my %flag_guards = ();
+MakeHelper::do_flags (\%flags, \%flag_guards);
+
my @xs_files = qw(
Cairo.xs
CairoFont.xs
@@ -345,15 +349,17 @@ MakeHelper::write_boot (
ignore => '^Cairo$',
);
-my @typemaps = MakeHelper::do_typemaps (\%objects, \%structs, \%enums,
- \%backend_guards, \%enum_guards);
+my @typemaps = MakeHelper::do_typemaps (\%objects, \%structs, \%enums, \%flags,
+ \%backend_guards,
+ \%enum_guards,
+ \%flag_guards);
push @typemaps, 'cairo-perl.typemap';
my $dep = ExtUtils::Depends->new ('Cairo');
$dep->set_inc ('-I. -I'.$autogen_dir.' '.$cairo_cfg{cflags});
$dep->set_libs ($cairo_cfg{libs});
$dep->add_xs (@xs_files);
-$dep->add_c ('cairo-perl-enums.c');
+$dep->add_c (qw/cairo-perl-enums.c cairo-perl-flags.c/);
$dep->add_pm ('lib/Cairo.pm' => '$(INST_LIBDIR)/Cairo.pm');
$dep->add_typemaps (@typemaps);
diff --git a/inc/MakeHelper.pm b/inc/MakeHelper.pm
index 568ba1f..3daa129 100644
--- a/inc/MakeHelper.pm
+++ b/inc/MakeHelper.pm
@@ -66,13 +66,21 @@ sub write_boot
# --------------------------------------------------------------------------- #
+sub name
+{
+ $_[0] =~ /cairo_(\w+)_t/;
+ return $1;
+}
+
sub do_typemaps
{
my %objects = %{shift ()};
my %structs = %{shift ()};
my %enums = %{shift ()};
+ my %flags = %{shift ()};
my %backend_guards = %{shift ()};
my %enum_guards = %{shift ()};
+ my %flag_guards = %{shift ()};
my $cairo_perl = File::Spec->catfile ($autogen_dir,
'cairo-perl-auto.typemap');
@@ -101,7 +109,7 @@ EOS
$1;
}
- foreach (keys %objects, keys %structs, keys %enums)
+ foreach (keys %objects, keys %structs, keys %enums, keys %flags)
{
print TYPEMAP "$_\tT_CAIROPERL_GENERIC_WRAPPER\n";
}
@@ -182,12 +190,6 @@ EOS
return $ref;
}
- sub name
- {
- $_[0] =~ /cairo_(\w+)_t/;
- return $1;
- }
-
# ------------------------------------------------------------------- #
print HEADER "\n/* objects */\n\n";
@@ -264,6 +266,33 @@ EOS
}
}
+ # ------------------------------------------------------------------- #
+
+ print HEADER "\n/* flags */\n\n";
+
+ foreach my $type (keys %flags)
+ {
+ my $mangled = mangle ($type);
+ my $name = name ($type);
+
+ next unless @{$flags{$type}};
+
+ if (exists $flag_guards{$type}) {
+ print HEADER "#ifdef $flag_guards{$type}\n";
+ }
+
+ print HEADER <<"EOS";
+$type cairo_${name}_from_sv (SV * $name);
+SV * cairo_${name}_to_sv ($type val);
+#define Sv$mangled(sv) (cairo_${name}_from_sv (sv))
+#define newSV$mangled(val) (cairo_${name}_to_sv (val))
+EOS
+
+ if (exists $flag_guards{$type}) {
+ print HEADER "#endif /* $flag_guards{$type} */\n";
+ }
+ }
+
close HEADER;
return ($cairo_perl);
@@ -271,6 +300,58 @@ EOS
# --------------------------------------------------------------------------- #
+sub canonicalize_enum_name
+{
+ my ($name, $prefix) = @_;
+ $name =~ s/$prefix//;
+ $name =~ tr/_/-/;
+ $name = lc ($name);
+ return $name;
+}
+
+sub enum_if_tree_from
+{
+ my ($prefix, @enums) = @_;
+ my $str = '';
+
+ my $is_first = 1;
+ foreach my $full (@enums)
+ {
+ my $name = canonicalize_enum_name($full, $prefix);
+ # +1 so that strncmp also looks at the trailing \0, and
+ # discerns 'color' and 'color-alpha', for example.
+ my $len = length ($name) + 1;
+ my $conditional = $is_first ? 'if' : 'else if';
+ $str .= <<"EOS";
+ $conditional (strncmp (str, "$name", $len) == 0)
+ return $full;
+EOS
+ $is_first = 0;
+ }
+
+ return $str;
+}
+
+sub enum_if_tree_to
+{
+ my ($prefix, @enums) = @_;
+ my $str = '';
+
+ my $is_first = 1;
+ foreach my $full (@enums)
+ {
+ my $name = canonicalize_enum_name($full, $prefix);
+ my $conditional = $is_first ? 'if' : 'else if';
+ $str .= <<"EOS";
+ $conditional (val == $full)
+ return newSVpv ("$name", 0);
+EOS
+ $is_first = 0;
+ }
+
+ return $str;
+}
+
sub do_enums
{
my %enums = %{shift ()};
@@ -280,124 +361,190 @@ sub do_enums
open ENUMS, '>', $cairo_enums
or die "unable to open ($cairo_enums) for output";
- print ENUMS "
+ print ENUMS <<'EOS';
/*
* This file was automatically generated. Do not edit.
*/
#include <cairo-perl.h>
-";
+EOS
- sub canonicalize
+ foreach my $type (keys %enums)
{
- my ($name, $prefix) = @_;
- $name =~ s/$prefix//;
- $name =~ tr/_/-/;
- $name = lc ($name);
- return $name;
- }
+ my $name = name($type);
+ my @enum_values = @{$enums{$type}};
- sub if_tree_from
- {
- my @enums = @_;
+ next unless @enum_values;
- my $prefix = shift @enums;
+ my $value_list =
+ join ", ", map {
+ canonicalize_enum_name($_, $enum_values[0])
+ } @enum_values[1..$#enum_values];
+ my $tree_from = enum_if_tree_from (@enum_values);
+ my $tree_to = enum_if_tree_to (@enum_values);
- my $full = shift @enums;
- my $name = canonicalize($full, $prefix);
+ if (exists $guards{$type}) {
+ print ENUMS "#ifdef $guards{$type}\n\n";
+ }
- # +1 so that strncmp also looks at the trailing \0, and discerns
- # 'color' and 'color-alpha', for example.
- my $len = length ($name) + 1;
+ print ENUMS <<"EOS";
+$type
+cairo_${name}_from_sv (SV * $name)
+{
+ char * str = SvPV_nolen ($name);
- my $str = <<"EOS";
- if (strncmp (str, "$name", $len) == 0)
- return $full;
-EOS
+ $tree_from
+ croak ("`%s' is not a valid $type value; valid values are: $value_list", str);
- foreach $full (@enums)
- {
- my $name = canonicalize($full, $prefix);
- $len = length ($name);
+ return 0;
+}
+
+SV *
+cairo_${name}_to_sv ($type val)
+{
+ $tree_to
+ warn ("unknown $type value %d encountered", val);
+ return &PL_sv_undef;
+}
- $str .= <<"EOS";
- else if (strncmp (str, "$name", $len) == 0)
- return $full;
EOS
- }
- $str;
+ if (exists $guards{$type}) {
+ print ENUMS "#endif /* $guards{$type} */\n";
+ }
}
- sub if_tree_to
- {
- my @enums = @_;
+ close ENUMS;
+}
- my $prefix = shift @enums;
- my $full = shift @enums;
- my $name = canonicalize($full, $prefix);
+# --------------------------------------------------------------------------- #
- my $str = <<"EOS";
- if (val == $full)
- return newSVpv ("$name", 0);
-EOS
+sub flag_if_tree_from
+{
+ my ($prefix, @flags) = @_;
+ my $str = '';
- foreach $full (@enums)
- {
- my $name = canonicalize($full, $prefix);
- $str .= <<"EOS";
- else if (val == $full)
- return newSVpv ("$name", 0);
+ my $is_first = 1;
+ foreach my $full (@flags)
+ {
+ my $name = canonicalize_enum_name($full, $prefix);
+ # +1 so that strncmp also looks at the trailing \0, and
+ # discerns 'color' and 'color-alpha', for example.
+ my $len = length ($name) + 1;
+ my $conditional = $is_first ? 'if' : 'else if';
+ $str .= <<"EOS";
+ $conditional (strncmp (str, "$name", $len) == 0) {
+ return $full;
+ }
EOS
- }
+ $is_first = 0;
+ }
+
+ return $str;
+}
- $str;
+sub flag_if_tree_to
+{
+ my ($prefix, @flags) = @_;
+ my $str = '';
+
+ foreach my $full (@flags)
+ {
+ my $name = canonicalize_enum_name($full, $prefix);
+ $str .= <<"EOS";
+ if ((val & $full) == $full) {
+ val -= $full;
+ av_push (flags, newSVpv ("$name", 0));
+ }
+EOS
}
- foreach my $type (keys %enums)
+ return $str;
+}
+
+sub do_flags
+{
+ my %flags = %{shift ()};
+ my %guards = %{shift ()};
+
+ my $cairo_flags = 'cairo-perl-flags.c';
+ open FLAGS, '>', $cairo_flags
+ or die "unable to open ($cairo_flags) for output";
+
+ print FLAGS <<'EOS';
+/*
+ * This file was automatically generated. Do not edit.
+ */
+
+#include <cairo-perl.h>
+#include <cairo-perl-private.h>
+
+EOS
+
+ foreach my $type (keys %flags)
{
my $name = name($type);
- my @enum_values = @{$enums{$type}};
+ my @flag_values = @{$flags{$type}};
- next unless @enum_values;
+ next unless @flag_values;
- my $value_list = join ", ", map { canonicalize($_, $enum_values[0]) } @enum_values[1..$#enum_values];
- my $tree_from = if_tree_from (@enum_values);
- my $tree_to = if_tree_to (@enum_values);
+ my $value_list =
+ join ", ", map {
+ canonicalize_enum_name($_, $flag_values[0])
+ } @flag_values[1..$#flag_values];
+ my $tree_from = flag_if_tree_from (@flag_values);
+ my $tree_to = flag_if_tree_to (@flag_values);
if (exists $guards{$type}) {
- print ENUMS "#ifdef $guards{$type}\n\n";
+ print FLAGS "#ifdef $guards{$type}\n\n";
}
- print ENUMS <<"EOS";
-$type
-cairo_${name}_from_sv (SV * $name)
+ print FLAGS <<"EOS";
+static $type
+cairo_${name}_from_sv_part (const char *str)
{
- char * str = SvPV_nolen ($name);
-
$tree_from
croak ("`%s' is not a valid $type value; valid values are: $value_list", str);
+ return 0;
+}
+$type
+cairo_${name}_from_sv (SV * $name)
+{
+ if (cairo_perl_sv_is_array_ref ($name)) {
+ AV *vals = (AV *) SvRV ($name);
+ $type value = 0;
+ int i;
+ for (i=0; i<=av_len(vals); i++)
+ value |= cairo_${name}_from_sv_part (
+ SvPV_nolen (*av_fetch (vals, i, 0)));
+ return value;
+ }
+ if (SvPOK ($name))
+ return cairo_${name}_from_sv_part (SvPV_nolen ($name));
+ croak ("`%s' is not a valid $type value, expecting a string scalar "
+ "or an arrayref of strings",
+ SvPV_nolen ($name));
return 0;
}
SV *
cairo_${name}_to_sv ($type val)
{
+ AV *flags = newAV ();
$tree_to
- warn ("unknown $type value %d encountered", val);
- return &PL_sv_undef;
+ return newRV_noinc ((SV *) flags);
}
EOS
if (exists $guards{$type}) {
- print ENUMS "#endif /* $guards{$type} */\n";
+ print FLAGS "#endif /* $guards{$type} */\n";
}
}
- close ENUMS;
+ close FLAGS;
}
1;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]