[glibmm] gmmproc, _WRAP_ENUM: Add optional CONV_TO_INT parameter



commit be0177f8b8705a7df8c65feedda8ecda234dbd65
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Sun Jun 11 12:56:36 2017 +0200

    gmmproc, _WRAP_ENUM: Add optional CONV_TO_INT parameter
    
    CONV_TO_INT "Convertible to int": Generate a plain enum (not an enum class)
    within a class. Such an enum is scoped like an enum class, and it can be
    implicitly converted to int like a plain enum. Bug 86864

 tools/m4/enum.m4       |  101 +++++++++++++++++++++++++++---------------------
 tools/pm/Output.pm     |   17 ++++----
 tools/pm/WrapParser.pm |   24 ++++++++----
 3 files changed, 82 insertions(+), 60 deletions(-)
---
diff --git a/tools/m4/enum.m4 b/tools/m4/enum.m4
index 5e908dc..ab7e816 100644
--- a/tools/m4/enum.m4
+++ b/tools/m4/enum.m4
@@ -1,25 +1,17 @@
 dnl
-dnl _ENUM(cpp_type, c_type, value_suffix, `element_list', `no_gtype', in_class,
-dnl          $1       $2         $3             $4           $5          $6
-dnl `optional_refdoc_comment', 'deprecated')
-dnl           $7                   $8
+dnl _ENUM(cpp_type, c_type, value_suffix, `element_list', `no_gtype', `conv_to_int',
+dnl          $1       $2         $3             $4           $5            $6
+dnl in_class, `optional_refdoc_comment', 'deprecated')
+dnl   $7                $8                    $9
 dnl
 m4_define(`_ENUM',`dnl
 _PUSH()
 
-dnl Concerning __ENUM_CLASS_NOLINK__:
-dnl The percent signs prevent Doxygen from creating links in the html files.
-dnl If a % precedes the class name, another % must precede the enum name,
-dnl otherwise Doxygen removes the double colons.
-dnl Possibly the percent signs are unnecessary. Even without them Doxygen
-dnl version 1.7.1 does not create links from the enum descriptions.
-dnl Other versions may behave differently.
-
 m4_define(`__ENUM_CPPNAME__',`$1')
 m4_define(`__ENUM_CNAME__',`$2')
-m4_define(`__ENUM_CLASS_CPPNAME__',m4_ifelse($6,0,,`__CPPNAME__::')`__ENUM_CPPNAME__')
-m4_define(`__ENUM_CLASS_NOLINK__',m4_ifelse($6,0,,`%__CPPNAME__::')`%__ENUM_CPPNAME__')
-m4_define(`__ENUM_INDENT__',m4_ifelse($6,0,,`  '))
+m4_define(`__ENUM_CLASS_CPPNAME__',m4_ifelse($7,0,,`__CPPNAME__::')`__ENUM_CPPNAME__')
+m4_define(`__ENUM_INDENT1__',m4_ifelse($7,0,,`  '))
+m4_define(`__ENUM_INDENT2__',__ENUM_INDENT1__`'m4_ifelse($6,,,`  '))
 m4_define(`__ENUM_VALUE_BASE__',`Glib::Value_$3<__NAMESPACE__::__ENUM_CLASS_CPPNAME__>')
 
 _POP()
@@ -30,33 +22,54 @@ m4_ifdef(`__DOCGROUP_'__MODULE_CANONICAL__`_ENUMS__',,`dnl else
 m4_define(`__DOCGROUP_'__MODULE_CANONICAL__`_ENUMS__')dnl
 /** @addtogroup '__MODULE_CANONICAL__`Enums __MODULE_CANONICAL__ Enums and Flags */
 
-__ENUM_INDENT__')`'dnl endif
+__ENUM_INDENT1__')`'dnl endif
 dnl
 dnl
-ifelse(`$8',,,`_DEPRECATE_IFDEF_START'`'__ENUM_INDENT__)`'dnl The expansion of _DEPRECATE_IFDEF_START ends 
with a newline
-/** $7
-__ENUM_INDENT__ *
-__ENUM_INDENT__ * @ingroup __MODULE_CANONICAL__`'Enums
+ifelse(`$9',,,`_DEPRECATE_IFDEF_START'`'__ENUM_INDENT1__)`'dnl The expansion of _DEPRECATE_IFDEF_START ends 
with a newline
+ifelse($6,,,`/** Wrapper for enum __ENUM_CPPNAME__.
+__ENUM_INDENT1__ * __ENUM_CPPNAME__ enumerators are scoped and can be implicitly converted to int.
+__ENUM_INDENT1__ * The scope is __NAMESPACE__::__ENUM_CLASS_CPPNAME__::
+__ENUM_INDENT1__ *
+__ENUM_INDENT1__ * @ingroup __MODULE_CANONICAL__`'Enums
+__ENUM_INDENT1__ */
+__ENUM_INDENT1__`'class __ENUM_CPPNAME__`'_Wrapper final
+__ENUM_INDENT1__{
+__ENUM_INDENT1__`'public:
+__ENUM_INDENT2__')`'dnl endif conv_to_int
+/** $8
+__ENUM_INDENT2__ *
+__ENUM_INDENT2__ * @ingroup __MODULE_CANONICAL__`'Enums
 m4_ifelse($3,`Flags',`dnl
-__ENUM_INDENT__ * @par Bitwise operators:
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__ operator|(__ENUM_CLASS_CPPNAME__, 
__ENUM_CLASS_CPPNAME__)</tt><br>
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__ operator&(__ENUM_CLASS_CPPNAME__, 
__ENUM_CLASS_CPPNAME__)</tt><br>
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__ operator^(__ENUM_CLASS_CPPNAME__, 
__ENUM_CLASS_CPPNAME__)</tt><br>
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__ operator~(__ENUM_CLASS_CPPNAME__)</tt><br>
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__& operator|=(__ENUM_CLASS_CPPNAME__&, 
__ENUM_CLASS_CPPNAME__)</tt><br>
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__& operator&=(__ENUM_CLASS_CPPNAME__&, 
__ENUM_CLASS_CPPNAME__)</tt><br>
-__ENUM_INDENT__ * <tt>__ENUM_CLASS_NOLINK__& operator^=(__ENUM_CLASS_CPPNAME__&, 
__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * @par Bitwise operators:
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__ operator|(__ENUM_CLASS_CPPNAME__, 
__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__ operator&(__ENUM_CLASS_CPPNAME__, 
__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__ operator^(__ENUM_CLASS_CPPNAME__, 
__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__ operator~(__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__& operator|=(__ENUM_CLASS_CPPNAME__&, 
__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__& operator&=(__ENUM_CLASS_CPPNAME__&, 
__ENUM_CLASS_CPPNAME__)</tt><br>
+__ENUM_INDENT2__ * <tt>__ENUM_CLASS_CPPNAME__& operator^=(__ENUM_CLASS_CPPNAME__&, 
__ENUM_CLASS_CPPNAME__)</tt><br>
 ')dnl endif
-__ENUM_INDENT__ */
-__ENUM_INDENT__`'enum class __ENUM_CPPNAME__
-__ENUM_INDENT__{
+__ENUM_INDENT2__ */
+__ENUM_INDENT2__`'enum ifelse($6,,`class ',)`'__ENUM_CPPNAME__
+__ENUM_INDENT2__{
 $4
-__ENUM_INDENT__};
+__ENUM_INDENT2__};
+ifelse($6,,,`__ENUM_INDENT2__`'#ifndef DOXYGEN_SHOULD_SKIP_THIS
+__ENUM_INDENT2__`'__ENUM_CPPNAME__`'_Wrapper`'() = delete;
+__ENUM_INDENT2__`'#endif
+__ENUM_INDENT1__};
+__ENUM_INDENT1__/** __ENUM_CPPNAME__ enumerators are scoped by the wrapper class
+__ENUM_INDENT1__ * and can be implicitly converted to int.
+__ENUM_INDENT1__ *
+__ENUM_INDENT1__ * @ingroup __MODULE_CANONICAL__`'Enums
+__ENUM_INDENT1__ */
+__ENUM_INDENT1__`'using __ENUM_CPPNAME__ = __ENUM_CPPNAME__`'_Wrapper::__ENUM_CPPNAME__;
+')`'dnl endif conv_to_int
 m4_ifelse($3,`Flags',`dnl
-m4_ifelse($6,0,,`dnl  in_class
+m4_ifelse($7,0,,`dnl  in_class
 _PUSH(SECTION_HEADER3)
 __NAMESPACE_BEGIN__
-ifelse(`$8',,,`_DEPRECATE_IFDEF_START')`'dnl
+ifelse(`$9',,,`_DEPRECATE_IFDEF_START')`'dnl
 ')dnl endif
 
 /** @ingroup __MODULE_CANONICAL__`'Enums */
@@ -86,17 +99,17 @@ inline __ENUM_CLASS_CPPNAME__& operator&=(__ENUM_CLASS_CPPNAME__& lhs, __ENUM_CL
 /** @ingroup __MODULE_CANONICAL__`'Enums */
 inline __ENUM_CLASS_CPPNAME__& operator^=(__ENUM_CLASS_CPPNAME__& lhs, __ENUM_CLASS_CPPNAME__ rhs)
   { return (lhs = static_cast<__ENUM_CLASS_CPPNAME__>(static_cast<unsigned>(lhs) ^ 
static_cast<unsigned>(rhs))); }
-m4_ifelse($6,0,,`dnl  in_class
-ifelse(`$8',,,`_DEPRECATE_IFDEF_END')`'dnl
+m4_ifelse($7,0,,`dnl  in_class
+ifelse(`$9',,,`_DEPRECATE_IFDEF_END')`'dnl
 __NAMESPACE_END__
 _POP()
 ')dnl endif
-')dnl endif !NO_OPERATORS
+')dnl endif Flags
 
-ifelse(`$8',,,`_DEPRECATE_IFDEF_END')`'dnl The expansion of _DEPRECATE_IFDEF_END ends with a newline
+ifelse(`$9',,,`_DEPRECATE_IFDEF_END')`'dnl The expansion of _DEPRECATE_IFDEF_END ends with a newline
 
 m4_ifelse($5,`NO_GTYPE',,`dnl else
-m4_ifelse($6,0,`dnl  not in_class
+m4_ifelse($7,0,`dnl  not in_class
 __NAMESPACE_END__
 ',`dnl else
 _PUSH(SECTION_HEADER3)
@@ -106,31 +119,31 @@ _PUSH(SECTION_HEADER3)
 namespace Glib
 {
 
-ifelse(`$8',,,`_DEPRECATE_IFDEF_START')`'dnl
+ifelse(`$9',,,`_DEPRECATE_IFDEF_START')`'dnl
 template <>
 class Value<__NAMESPACE__::__ENUM_CLASS_CPPNAME__> : public __ENUM_VALUE_BASE__
 {
 public:
   static GType value_type() G_GNUC_CONST;
 };
-ifelse(`$8',,,`_DEPRECATE_IFDEF_END')`'dnl
+ifelse(`$9',,,`_DEPRECATE_IFDEF_END')`'dnl
 
 } // namespace Glib
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
-m4_ifelse($6,0,`dnl  not in_class
+m4_ifelse($7,0,`dnl  not in_class
 __NAMESPACE_BEGIN__
 ',`dnl else
 _POP()
 ')dnl endif
 _PUSH(SECTION_SRC_GENERATED)
-ifelse(`$8',,,`_DEPRECATE_IFDEF_START')`'dnl
+ifelse(`$9',,,`_DEPRECATE_IFDEF_START')`'dnl
 // static
 GType Glib::Value<__NAMESPACE__::__ENUM_CLASS_CPPNAME__>::value_type()
 {
   return _GET_TYPE_FUNC(__ENUM_CNAME__);
 }
-ifelse(`$8',,,`_DEPRECATE_IFDEF_END')`'dnl
+ifelse(`$9',,,`_DEPRECATE_IFDEF_END')`'dnl
 
 _POP()
 ')dnl endif !NO_GTYPE
diff --git a/tools/pm/Output.pm b/tools/pm/Output.pm
index d266e63..1913f01 100644
--- a/tools/pm/Output.pm
+++ b/tools/pm/Output.pm
@@ -690,13 +690,13 @@ sub output_wrap_sig_decl($$$$$$$$$$$$$$)
 }
 
 # void output_wrap_enum($filename, $line_num, $cpp_type, $c_type,
-#   $comment, $ref_subst_in, $ref_subst_out, $no_gtype, $in_class,
-#   $deprecated, $deprecation_docs, $newin)
-sub output_wrap_enum($$$$$$$$$$$$$)
+#   $comment, $ref_subst_in, $ref_subst_out, $no_gtype, $conv_to_int,
+#   $in_class, $deprecated, $deprecation_docs, $newin)
+sub output_wrap_enum($$$$$$$$$$$$$$)
 {
   my ($self, $filename, $line_num, $cpp_type, $c_type,
-    $comment, $ref_subst_in, $ref_subst_out, $no_gtype, $in_class,
-    $deprecated, $deprecation_docs, $newin) = @_;
+    $comment, $ref_subst_in, $ref_subst_out, $no_gtype, $conv_to_int,
+    $in_class, $deprecated, $deprecation_docs, $newin) = @_;
 
   my $objEnum = GtkDefs::lookup_enum($c_type);
   if(!$objEnum)
@@ -709,6 +709,7 @@ sub output_wrap_enum($$$$$$$$$$$$$)
 
   my $indent = "  ";
   $indent .= "  " if ($in_class);
+  $indent .= "  " if ($conv_to_int);
   my $elements = $objEnum->build_element_list(1, $ref_subst_in, $ref_subst_out, $indent);
 
   if(!$elements)
@@ -723,8 +724,7 @@ sub output_wrap_enum($$$$$$$$$$$$$)
   unshift(@$ref_subst_out, "");
 
   # Get the enum documentation from the parsed docs.
-  $indent = " ";
-  $indent .= "  " if ($in_class);
+  $indent = substr($indent, 1); # Remove one blank
   my $enum_docs = DocsParser::lookup_enum_documentation("$c_type", "$cpp_type",
     $indent, $ref_subst_in, $ref_subst_out, $deprecation_docs, $newin);
 
@@ -734,12 +734,13 @@ sub output_wrap_enum($$$$$$$$$$$$$)
   my $value_suffix = "Enum";
   $value_suffix = "Flags" if ($$objEnum{flags});
 
-  my $str = sprintf("_ENUM(%s,%s,%s,\`%s\',\`%s\',%d,\`%s\',\`%s\')dnl\n",
+  my $str = sprintf("_ENUM(%s,%s,%s,\`%s\',\`%s\',\`%s\',%d,\`%s\',\`%s\')dnl\n",
     $cpp_type,
     $c_type,
     $value_suffix,
     $elements,
     $no_gtype,
+    $conv_to_int,
     $in_class,
     $comment,
     $deprecated
diff --git a/tools/pm/WrapParser.pm b/tools/pm/WrapParser.pm
index 829f9b1..b99c5b0 100644
--- a/tools/pm/WrapParser.pm
+++ b/tools/pm/WrapParser.pm
@@ -1436,6 +1436,7 @@ sub on_wrap_any_enum($$)
   my @subst_in  = [];
   my @subst_out = [];
   my $no_gtype = "";
+  my $conv_to_int = "";
   my $argDeprecated = "";
   my $deprecation_docs = "";
   my $newin = "";
@@ -1447,7 +1448,11 @@ sub on_wrap_any_enum($$)
 
     if ($arg eq "NO_GTYPE")
     {
-      $no_gtype = "NO_GTYPE";
+      $no_gtype = $arg;
+    }
+    elsif (!$is_gerror and $arg eq "CONV_TO_INT")
+    {
+      $conv_to_int = $arg;
     }
     elsif ($arg =~ /^s#([^#]+)#([^#]*)#$/)
     {
@@ -1469,15 +1474,18 @@ sub on_wrap_any_enum($$)
     }
   }
   return ($cpp_type, $c_type, $domain, \@subst_in, \@subst_out, $no_gtype,
-    $argDeprecated, $deprecation_docs, $newin);
+    $conv_to_int, $argDeprecated, $deprecation_docs, $newin);
 }
 
 # void on_wrap_enum()
-# _WRAP_ENUM(cpp_type, c_type [,NO_GTYPE] [,s#regexpr#subst#]*)
+# _WRAP_ENUM(cpp_type, c_type [,NO_GTYPE] [,CONV_TO_INT] [,s#regexpr#subst#]*)
 # Optional arguments:
 # NO_GTYPE Don't generate code for a specialization of the template
 #          Glib::Value_Enum or Glib::Value_Flags.
 #          Necessary, if the C type enum is not registered as a GType.
+# CONV_TO_INT "Convertible to int" Generate a plain enum (not an enum class)
+#             within a class. Such an enum is scoped like an enum class,
+#             and it can be implicitly converted to int like a plain enum.
 # s#regexpr#subst# Zero or more substitutions in names of enum constants, e.g. s#^DATE_##.
 #
 # _WRAP_ENUM can be located either in a class or outside all classes.
@@ -1497,13 +1505,13 @@ sub on_wrap_enum($)
   my $comment = $self->extract_preceding_documentation();
 
   # get the arguments
-  my ($cpp_type, $c_type, undef, $ref_subst_in, $ref_subst_out, $no_gtype,
+  my ($cpp_type, $c_type, undef, $ref_subst_in, $ref_subst_out, $no_gtype, $conv_to_int,
     $argDeprecated, $deprecation_docs, $newin) = $self->on_wrap_any_enum(0);
 
   $$self{objOutputter}->output_wrap_enum(
     $$self{filename}, $$self{line_num}, $cpp_type, $c_type,
-    $comment, $ref_subst_in, $ref_subst_out, $no_gtype, $$self{in_class},
-    $argDeprecated, $deprecation_docs, $newin);
+    $comment, $ref_subst_in, $ref_subst_out, $no_gtype, $conv_to_int,
+    $$self{in_class}, $argDeprecated, $deprecation_docs, $newin);
 }
 
 sub on_wrap_enum_docs_only($)
@@ -1515,7 +1523,7 @@ sub on_wrap_enum_docs_only($)
   my $comment = $self->extract_preceding_documentation();
 
   # get the arguments
-  my ($cpp_type, $c_type, undef, $ref_subst_in, $ref_subst_out, undef,
+  my ($cpp_type, $c_type, undef, $ref_subst_in, $ref_subst_out, undef, undef,
     $argDeprecated, $deprecation_docs, $newin) = $self->on_wrap_any_enum(0);
 
   # Get the module name so the enum docs can be included in the module's
@@ -1539,7 +1547,7 @@ sub on_wrap_gerror($)
   my $class_docs = $self->extract_preceding_documentation();
 
   # get the arguments
-  my ($cpp_type, $c_type, $domain, $ref_subst_in, $ref_subst_out, $no_gtype,
+  my ($cpp_type, $c_type, $domain, $ref_subst_in, $ref_subst_out, $no_gtype, undef,
     $argDeprecated, $deprecation_docs, $newin) = $self->on_wrap_any_enum(1);
 
   $$self{objOutputter}->output_wrap_gerror(


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]