Author: rhuijben
Date: Mon Oct 12 14:26:17 2015
New Revision: 1708128
URL: http://svn.apache.org/viewvc?rev=1708128&view=rev
Log:
Reimplement the buckets_are_v2 code in a different style to handle cases
where pointer equality of serf_buckets_are_v2() is not guaranteed.
* serf-dev/dev/buckets/buckets.c
(v2_check): New constant.
(serf_buckets_are_v2): Check for passing v2_check.
(fallback_bucket_type): New constant.
(serf_get_type): New function.
* serf-dev/dev/serf.h
(serf_bucket_type_t): Update comments.
(serf_get_type): New function.
(serf_bucket_get_remaining,
serf_bucket_set_config): Reimplement using serf_get_type().
Modified:
serf/trunk/buckets/buckets.c
serf/trunk/serf.h
Modified: serf/trunk/buckets/buckets.c
URL: http://svn.apache.org/viewvc/serf/trunk/buckets/buckets.c?rev=1708128&r1=1708127&r2=1708128&view=diff
==============================================================================
--- serf/trunk/buckets/buckets.c (original)
+++ serf/trunk/buckets/buckets.c Mon Oct 12 14:26:17 2015
@@ -134,9 +134,33 @@ apr_uint64_t serf_default_get_remaining(
return SERF_LENGTH_UNKNOWN;
}
+/* serf_bucket_type_t that is only used for version checking
+ between serf_buckets_are_v2() and serf_get_type().
+
+ Use a specific value for the name that API users can't depend
+ on, but that the compiler and linker can't optimize away
+ as 100% the same as another instance */
+static const serf_bucket_type_t v2_check =
+{
+ "\0serf_buckets_are_v2",
+ NULL /* read */,
+ NULL /* readline */,
+ NULL /* read_iovec */,
+ NULL /* read_for_sendfile */,
+ NULL /* buckets_are_v2 */,
+ NULL /* peek */,
+ NULL /* destroy */,
+ NULL /* read_bucket_v2 */,
+ NULL /* get_remaining */,
+ NULL /* set_config */
+};
+
serf_bucket_t * serf_buckets_are_v2(serf_bucket_t *bucket,
const serf_bucket_type_t *type)
{
+ if (type == &v2_check)
+ return bucket;
+
return bucket->type->read_bucket_v2(bucket, type);
}
@@ -145,6 +169,53 @@ apr_status_t serf_default_ignore_config(
{
return APR_SUCCESS;
}
+
+/* Fallback type definition to return for buckets that don't implement
+ a specific version of the bucket spec */
+static const serf_bucket_type_t fallback_bucket_type =
+{
+ "\0serf_buckets_old",
+ NULL /* read */,
+ NULL /* readline */,
+ NULL /* read_iovec */,
+ NULL /* read_for_sendfile */,
+ NULL /* read_bucket */,
+ NULL /* peek */,
+ NULL /* destroy */,
+ serf_buckets_are_v2,
+ serf_default_get_remaining,
+ serf_default_ignore_config,
+};
+
+const serf_bucket_type_t *serf_get_type(const serf_bucket_t *bucket,
+ int min_version)
+{
+ serf_bucket_t *r;
+
+ switch (min_version) {
+ case 1:
+ r = bucket; /* Always supported */
+ break;
+#if 0
+ case 3:
+ r = bucket->type->read_bucket(bucket, &v3_check);
+ break;
+#endif
+
+ case 2:
+ r = bucket->type->read_bucket(bucket, &v2_check);
+ break;
+
+ default:
+ abort();
+ }
+
+ if (r != NULL)
+ return r->type;
+
+ return &fallback_bucket_type;
+}
+
/* ==================================================================== */
Modified: serf/trunk/serf.h
URL: http://svn.apache.org/viewvc/serf/trunk/serf.h?rev=1708128&r1=1708127&r2=1708128&view=diff
==============================================================================
--- serf/trunk/serf.h (original)
+++ serf/trunk/serf.h Mon Oct 12 14:26:17 2015
@@ -921,24 +921,27 @@ struct serf_bucket_type_t {
void (*destroy)(serf_bucket_t *bucket);
/* The following members are valid only if read_bucket equals to
- * serf_buckets_are_v2(). */
+ * serf_buckets_are_v2() (or in a future spec _v3, etc.). */
/* Real pointer to read_bucket() method when read_bucket is
- * serf_buckets_are_v2(). */
+ * serf_buckets_are_v2().
+ *
+ * @since New in 1.4 / Buckets v2.
+ */
serf_bucket_t * (*read_bucket_v2)(serf_bucket_t *bucket,
const serf_bucket_type_t *type);
/* Returns length of remaining data to be read in @a bucket. Returns
* SERF_LENGTH_UNKNOWN if length is unknown.
*
- * @since New in 1.4.
+ * @since New in 1.4 / Buckets v2.
*/
apr_uint64_t (*get_remaining)(serf_bucket_t *bucket);
/* Provides a reference to a config object containing all configuration
* values relevant for this bucket.
*
- * @since New in 1.4.
+ * @since New in 1.4 / Buckets v2
*/
apr_status_t (*set_config)(serf_bucket_t *bucket, serf_config_t *config);
@@ -976,6 +979,14 @@ struct serf_bucket_type_t {
serf_bucket_t * serf_buckets_are_v2(serf_bucket_t *bucket,
const serf_bucket_type_t *type);
+/** Gets the serf bucket type of the bucket if the bucket implements at least
+ * buckets version, or if not a bucket type providing a default implementation
+ *
+ * @since New in 1.4.
+ */
+const serf_bucket_type_t *serf_get_type(const serf_bucket_t *bucket,
+ int min_version);
+
/* Internal macros for tracking bucket use. */
#ifdef SERF_DEBUG_BUCKET_USE
#define SERF__RECREAD(b,s) serf_debug__record_read(b,s)
@@ -993,14 +1004,8 @@ serf_bucket_t * serf_buckets_are_v2(serf
#define serf_bucket_read_bucket(b,t) ((b)->type->read_bucket(b,t))
#define serf_bucket_peek(b,d,l) ((b)->type->peek(b,d,l))
#define serf_bucket_destroy(b) ((b)->type->destroy(b))
-#define serf_bucket_get_remaining(b) \
- ((b)->type->read_bucket == serf_buckets_are_v2 ? \
- (b)->type->get_remaining(b) : \
- SERF_LENGTH_UNKNOWN)
-#define serf_bucket_set_config(b,c) \
- ((b)->type->read_bucket == serf_buckets_are_v2 ? \
- (b)->type->set_config(b,c) : \
- APR_ENOTIMPL)
+#define serf_bucket_get_remaining(b) (serf_get_type(b, 2)->get_remaining(b))
+#define serf_bucket_set_config(b,c) (serf_get_type(b, 2)->set_config(b, c))
/**
* Check whether a real error occurred. Note that bucket read functions
|