Summary: I propose to create one or possibly several new public header
files that will be used by both the C and C++ public APIs.


I would like to completely hide the dependency on APR from the public
parts of the C++ API. In order to do that, public C++ headers must not
include the C headers directly, because most if not all of them do
expose APR.

Up to now I've been "solving" this in an unsatisfactory and error-prone
way, redefining enumeration values in C++ to be the same as in C,
forward-declaring C structures in C++ headers, and so on. Instead, I'd
like to extract certain parts of the C public API into a new header that
is independent of APR, and use that in both APIs. This way I won't avoid
redefining enumerations, for example, but I can ensure that both the C
and C++ APIs use the same enumeration constant values.

I'm attaching a patch that shows an example of what I have in mind.

Please raise your objections by next year. :)

-- Brane
Index: subversion/include/svn__impl__types.h
===================================================================
--- subversion/include/svn__impl__types.h       (nonexistent)
+++ subversion/include/svn__impl__types.h       (working copy)
@@ -0,0 +1,95 @@
+/**
+ * @copyright
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_types.h
+ * @brief Types implementation.
+ * This is a @b private implementation-specific header file.
+ * User code should not include it directly.
+ */
+
+#ifndef SVN_X_IMPL_X_TYPES_H
+#define SVN_X_IMPL_X_TYPES_H
+
+/*
+ * Define Subversion types that do not depend on APR or other
+ * external libraries (except for the C standard libvrary) and are
+ * shared betwen the C and C++ APIs. Do not include any headers
+ * except for the C standard library headers here.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Tristate values
+ * See: svn_tristate_t in svn_types.h
+ *      tristate in svnxx/tristate.hpp
+ */
+enum svn__impl__tristate_t
+  {
+    /* This constant must not evaluate to either TRUE or FALSE. */
+    svn__impl__tristate_false = 2,
+    svn__impl__tristate_true,
+    svn__impl__tristate_unknown
+  };
+
+/* Depth values
+ * See: svn_depth_t in svn_types.h
+ *      depth in svnxx/depth.hpp
+ */
+enum svn__impl__depth_t
+  {
+    svn__impl__depth_unknown    = -2,
+    svn__impl__depth_exclude    = -1,
+    svn__impl__depth_empty      =  0,
+    svn__impl__depth_files      =  1,
+    svn__impl__depth_immediates =  2,
+    svn__impl__depth_infinity   =  3
+  };
+
+/* Revision number type
+ * See: svn_revnum_t in svn_types.h
+ *      revision::number in svnxx/revision.hpp
+ */
+typedef long int svn__impl__revnum_t;
+#define SVN__IMPL__INVALID_REVNUM ((svn__impl__revnum_t) -1)
+
+/* Revision kind
+ * See: svn_opt_revision_kind in svn_opt.h
+ *      revision::kind in svnxx/revision.hpp
+ */
+enum svn__impl__revision_kind_t {
+  svn__impl__revision_unspecified,
+  svn__impl__revision_number,
+  svn__impl__revision_date,
+  svn__impl__revision_committed,
+  svn__impl__revision_previous,
+  svn__impl__revision_base,
+  svn__impl__revision_working,
+  svn__impl__revision_head
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_X_IMPL_X_TYPES_H */
Index: subversion/include/svn_opt.h
===================================================================
--- subversion/include/svn_opt.h        (revision 1850008)
+++ subversion/include/svn_opt.h        (working copy)
@@ -39,6 +39,7 @@
 #include <apr_want.h>   /* for FILE* */
 
 #include "svn_types.h"
+#include "svn__impl__types.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -453,30 +454,31 @@
  * with respect to its base revision.  In other contexts, `working'
  * should behave the same as `committed' or `current'.
  */
+/* NOTE: See svn__impl__revision_kind_t in svn__impl__types.h. */
 enum svn_opt_revision_kind {
   /** No revision information given. */
-  svn_opt_revision_unspecified,
+  svn_opt_revision_unspecified = svn__impl__revision_unspecified,
 
   /** revision given as number */
-  svn_opt_revision_number,
+  svn_opt_revision_number      = svn__impl__revision_number,
 
   /** revision given as date */
-  svn_opt_revision_date,
+  svn_opt_revision_date        = svn__impl__revision_date,
 
   /** rev of most recent change */
-  svn_opt_revision_committed,
+  svn_opt_revision_committed   = svn__impl__revision_committed,
 
   /** (rev of most recent change) - 1 */
-  svn_opt_revision_previous,
+  svn_opt_revision_previous    = svn__impl__revision_previous,
 
   /** .svn/entries current revision */
-  svn_opt_revision_base,
+  svn_opt_revision_base        = svn__impl__revision_base,
 
   /** current, plus local mods */
-  svn_opt_revision_working,
+  svn_opt_revision_working     = svn__impl__revision_working,
 
   /** repository youngest */
-  svn_opt_revision_head
+  svn_opt_revision_head        = svn__impl__revision_head
 
   /* please update svn_opt__revision_to_string() when extending this enum */
 };
Index: subversion/include/svn_types.h
===================================================================
--- subversion/include/svn_types.h      (revision 1850008)
+++ subversion/include/svn_types.h      (working copy)
@@ -40,6 +40,8 @@
 #include <apr_time.h>    /* for apr_time_t */
 #include <apr_strings.h> /* for apr_atoi64() */
 
+#include "svn__impl__types.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -354,14 +356,15 @@
  * not a valid value.
  *
  * @since New in 1.7. */
+/* NOTE: See svn__impl__tristate_t in svn__impl__types.h. */
 typedef enum svn_tristate_t
 {
   /** state known to be false (the constant does not evaulate to false) */
-  svn_tristate_false = 2,
+  svn_tristate_false = svn__impl__tristate_false,
   /** state known to be true */
-  svn_tristate_true,
+  svn_tristate_true = svn__impl__tristate_true,
   /** state could be true or false */
-  svn_tristate_unknown
+  svn_tristate_unknown = svn__impl__tristate_unknown
 } svn_tristate_t;
 
 /** Return a constant string "true", "false" or NULL representing the value of
@@ -423,19 +426,19 @@
 
 
 /** A revision number. */
-typedef long int svn_revnum_t;
+typedef svn__impl__revnum_t svn_revnum_t;
 
 /** Valid revision numbers begin at 0 */
 #define SVN_IS_VALID_REVNUM(n) ((n) >= 0)
 
 /** The 'official' invalid revision num */
-#define SVN_INVALID_REVNUM ((svn_revnum_t) -1)
+#define SVN_INVALID_REVNUM SVN__IMPL__INVALID_REVNUM
 
 /** Not really invalid...just unimportant -- one day, this can be its
  * own unique value, for now, just make it the same as
  * #SVN_INVALID_REVNUM.
  */
-#define SVN_IGNORED_REVNUM ((svn_revnum_t) -1)
+#define SVN_IGNORED_REVNUM SVN__IMPL__INVALID_REVNUM
 
 /** Convert NULL-terminated C string @a str to a revision number. */
 #define SVN_STR_TO_REV(str) ((svn_revnum_t) atol(str))
@@ -501,6 +504,7 @@
  *
  * @since New in 1.5.
  */
+/* NOTE: See svn__impl__depth_t in svn__impl__types.h. */
 typedef enum svn_depth_t
 {
   /* The order of these depths is important: the higher the number,
@@ -510,7 +514,7 @@
   /** Depth undetermined or ignored.  In some contexts, this means the
       client should choose an appropriate default depth.  The server
       will generally treat it as #svn_depth_infinity. */
-  svn_depth_unknown    = -2,
+  svn_depth_unknown    = svn__impl__depth_unknown,
 
   /** Exclude (i.e., don't descend into) directory D.
       @note In Subversion 1.5, svn_depth_exclude is *not* supported
@@ -521,26 +525,26 @@
       svn_depth_exclude behavior, once we get a chance to implement
       client-side support for svn_depth_exclude.)
   */
-  svn_depth_exclude    = -1,
+  svn_depth_exclude    = svn__impl__depth_exclude,
 
   /** Just the named directory D, no entries.  Updates will not pull in
       any files or subdirectories not already present. */
-  svn_depth_empty      =  0,
+  svn_depth_empty      =  svn__impl__depth_empty,
 
   /** D + its file children, but not subdirs.  Updates will pull in any
       files not already present, but not subdirectories. */
-  svn_depth_files      =  1,
+  svn_depth_files      =  svn__impl__depth_files,
 
   /** D + immediate children (D and its entries).  Updates will pull in
       any files or subdirectories not already present; those
       subdirectories' this_dir entries will have depth-empty. */
-  svn_depth_immediates =  2,
+  svn_depth_immediates =  svn__impl__depth_immediates,
 
   /** D + all descendants (full recursion from D).  Updates will pull
       in any files or subdirectories not already present; those
       subdirectories' this_dir entries will have depth-infinity.
       Equivalent to the pre-1.5 default update behavior. */
-  svn_depth_infinity   =  3
+  svn_depth_infinity   =  svn__impl__depth_infinity
 
 } svn_depth_t;
 
Index: subversion/bindings/cxx/include/svnxx/depth.hpp
===================================================================
--- subversion/bindings/cxx/include/svnxx/depth.hpp     (revision 1850008)
+++ subversion/bindings/cxx/include/svnxx/depth.hpp     (working copy)
@@ -28,6 +28,8 @@
 #include <cstdint>
 #include <string>
 
+#include "svn__impl__types.h"
+
 namespace apache {
 namespace subversion {
 namespace svnxx {
@@ -35,15 +37,15 @@
 /**
  * @brief The concept of depth for directories (see @ref svn_depth_t).
  */
-// NOTE: Keep these values identical to those in svn_depth_t!
+// NOTE: See svn__impl__depth_t in svn__impl__types.h.
 enum class depth : std::int8_t
   {
-    unknown = -2,
-    exclude = -1,
-    empty = 0,
-    files = 1,
-    immediates = 2,
-    infinity = 3,
+    unknown    = svn__impl__depth_unknown,
+    exclude    = svn__impl__depth_exclude,
+    empty      = svn__impl__depth_empty,
+    files      = svn__impl__depth_files,
+    immediates = svn__impl__depth_immediates,
+    infinity   = svn__impl__depth_infinity,
   };
 
 /**
Index: subversion/bindings/cxx/include/svnxx/revision.hpp
===================================================================
--- subversion/bindings/cxx/include/svnxx/revision.hpp  (revision 1850008)
+++ subversion/bindings/cxx/include/svnxx/revision.hpp  (working copy)
@@ -28,6 +28,8 @@
 #include <chrono>
 #include <cstdint>
 
+#include "svn__impl__types.h"
+
 #include "tristate.hpp"
 
 namespace apache {
@@ -47,9 +49,9 @@
   /**
    * @brief Revision number type.
    */
-  enum class number : long
+  enum class number : svn__impl__revnum_t
     {
-      invalid = -1,             ///< Invalid revision number.
+      invalid = SVN__IMPL__INVALID_REVNUM, ///< Invalid revision number.
     };
 
   /**
@@ -66,17 +68,17 @@
   /**
    * @brief Revision kind discriminator (see @ref svn_opt_revision_kind).
    */
-  // NOTE: Keep these values identical to those in svn_opt_revision_kind!
+  // NOTE: See svn__impl__revision_kind_t in svn__impl__types.h.
   enum class kind : std::int8_t
     {
-      unspecified,
-      number,
-      date,
-      committed,
-      previous,
-      base,
-      working,
-      head,
+      unspecified = svn__impl__revision_unspecified,
+      number      = svn__impl__revision_number,
+      date        = svn__impl__revision_date,
+      committed   = svn__impl__revision_committed,
+      previous    = svn__impl__revision_previous,
+      base        = svn__impl__revision_base,
+      working     = svn__impl__revision_working,
+      head        = svn__impl__revision_head,
     };
 
   /**
Index: subversion/bindings/cxx/include/svnxx/tristate.hpp
===================================================================
--- subversion/bindings/cxx/include/svnxx/tristate.hpp  (revision 1850008)
+++ subversion/bindings/cxx/include/svnxx/tristate.hpp  (working copy)
@@ -25,6 +25,9 @@
 #ifndef SVNXX_TRISTATE_HPP
 #define SVNXX_TRISTATE_HPP
 
+#include <cstdint>
+#include "svn__impl__types.h"
+
 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
 #include <boost/logic/tribool.hpp>
 #endif
@@ -132,11 +135,11 @@
     }
 
 private:
-  // See svn_tristate_t in svn_types.h.
-  enum: unsigned char {
-    false_value = 2,
-    true_value,
-    unknown_value
+  // NOTE: See svn__impl__tristate_t in svn__impl__types.h.
+  enum : std::uint8_t {
+    false_value   = svn__impl__tristate_false,
+    true_value    = svn__impl__tristate_true,
+    unknown_value = svn__impl__tristate_unknown
   } value;
 
 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)

Reply via email to