Author: rhuijben
Date: Wed Nov 11 09:39:09 2015
New Revision: 1713788

URL: http://svn.apache.org/viewvc?rev=1713788&view=rev
Log:
Implement a best effort serf_default_readline() via read() and peek() to
be used on buckets that don't have a specialized implementation and currently
use a NULL function.

* buckets/buckets.c
  (serf_default_readline): New function.

* buckets/dechunk_buckets.c
  (serf_bucket_type_dechunk): Use default api.

* buckets/deflate_buckets.c
  (serf_bucket_type_deflate): Use default api.

* buckets/hpack_buckets.c
  (serf_bucket_type__hpack): Use default api.

* buckets/http2_frame_buckets.c
  (serf_bucket_type__http2_unframe): Use default api.

* buckets/prefix_buckets.c
  (serf_bucket_type__http2_unpad): Use default api.

* serf_bucket_util.h
  (serf_default_readline): New function.

Modified:
    serf/trunk/buckets/buckets.c
    serf/trunk/buckets/dechunk_buckets.c
    serf/trunk/buckets/deflate_buckets.c
    serf/trunk/buckets/hpack_buckets.c
    serf/trunk/buckets/http2_frame_buckets.c
    serf/trunk/buckets/prefix_buckets.c
    serf/trunk/serf_bucket_util.h

Modified: serf/trunk/buckets/buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/buckets.c?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/buckets/buckets.c (original)
+++ serf/trunk/buckets/buckets.c Wed Nov 11 09:39:09 2015
@@ -125,6 +125,93 @@ apr_status_t serf_default_peek(
     return APR_SUCCESS;
 }
 
+apr_status_t serf_default_readline(serf_bucket_t *bucket, int acceptable,
+                                   int *found,
+                                   const char **data, apr_size_t *len)
+{
+    apr_status_t status;
+    const char *peek_data;
+    apr_size_t peek_len;
+    apr_size_t requested;
+
+    status = bucket->type->peek(bucket, &peek_data, &peek_len);
+
+    if (SERF_BUCKET_READ_ERROR(status))
+        return status;
+
+    if (peek_len > 0) {
+        const char *cr = NULL;
+        const char *lf = NULL;
+
+        if ((acceptable & SERF_NEWLINE_CR) || (acceptable & SERF_NEWLINE_CRLF))
+            cr = memchr(peek_data, '\r', peek_len);
+        if ((acceptable & SERF_NEWLINE_LF))
+            lf = memchr(peek_data, '\n', peek_len);
+
+        if (cr && lf)
+            cr = MIN(cr, lf);
+        else if (lf)
+            cr = lf;
+
+        /* ### When we are only looking for CRLF we may return too small
+               chunks here when the data contains CR or LF without the other.
+               That isn't incorrect, but it could be optimized.
+
+           ### But as that case is not common, the caller has to assume
+               partial reads anyway and this is just a not very inefficient
+               fallback implementation...
+
+               Let's make the buffering in the caller handle that case
+               for now. */
+
+        if (*cr == '\r' && (acceptable & SERF_NEWLINE_CRLF)
+            && ((cr + 1) < (peek_data + peek_len)) && *(cr + 1) == '\n')
+        {
+            requested = (cr + 2) - peek_data;
+        }
+        else if (cr)
+            requested = (cr + 1) - peek_data;
+        else
+            requested = peek_len;
+    }
+    else {
+        /* We can't peek...
+           The only valid thing to do is try to read upto one EOL */
+        if ((acceptable & SERF_NEWLINE_ANY) == SERF_NEWLINE_CRLF)
+            requested = 2;
+        else
+            requested = 1;
+    }
+
+    status = bucket->type->read(bucket, requested, data, len);
+
+    if (SERF_BUCKET_READ_ERROR(status))
+        return status;
+
+    if (*len == 0) {
+        *found = SERF_NEWLINE_NONE;
+    }
+    else if ((acceptable & SERF_NEWLINE_CRLF) && *len >= 2
+        && data[*len - 1] == '\n' && data[*len - 2] == '\r')
+    {
+        *found = SERF_NEWLINE_CRLF;
+    }
+    else if ((acceptable & SERF_NEWLINE_LF) && data[*len - 1] == '\n')
+    {
+        *found = SERF_NEWLINE_LF;
+    }
+    else if ((acceptable & (SERF_NEWLINE_CRLF | SERF_NEWLINE_CR))
+             && data[*len - 1] == '\r')
+    {
+        *found = (acceptable & (SERF_NEWLINE_CRLF)) ? SERF_NEWLINE_CRLF_SPLIT
+                                                    : SERF_NEWLINE_CR;
+    }
+    else
+        *found = SERF_NEWLINE_NONE;
+
+    return status;
+}
+
 
 void serf_default_destroy(serf_bucket_t *bucket)
 {

Modified: serf/trunk/buckets/dechunk_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/dechunk_buckets.c?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/buckets/dechunk_buckets.c (original)
+++ serf/trunk/buckets/dechunk_buckets.c Wed Nov 11 09:39:09 2015
@@ -197,14 +197,10 @@ static apr_status_t serf_dechunk_set_con
     return serf_bucket_set_config(ctx->stream, config);
 }
 
-
-/* ### need to implement */
-#define serf_dechunk_readline NULL
-
 const serf_bucket_type_t serf_bucket_type_dechunk = {
     "DECHUNK",
     serf_dechunk_read,
-    serf_dechunk_readline /* ### TODO */,
+    serf_default_readline,
     serf_default_read_iovec,
     serf_default_read_for_sendfile,
     serf_buckets_are_v2,

Modified: serf/trunk/buckets/deflate_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/deflate_buckets.c?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/buckets/deflate_buckets.c (original)
+++ serf/trunk/buckets/deflate_buckets.c Wed Nov 11 09:39:09 2015
@@ -444,13 +444,10 @@ static apr_status_t serf_deflate_set_con
     return serf_bucket_set_config(ctx->stream, config);
 }
 
-/* ### need to implement */
-#define serf_deflate_readline NULL
-
 const serf_bucket_type_t serf_bucket_type_deflate = {
     "DEFLATE",
     serf_deflate_read,
-    serf_deflate_readline /* ### TODO */,
+    serf_default_readline,
     serf_default_read_iovec,
     serf_default_read_for_sendfile,
     serf_buckets_are_v2,

Modified: serf/trunk/buckets/hpack_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/hpack_buckets.c?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/buckets/hpack_buckets.c (original)
+++ serf/trunk/buckets/hpack_buckets.c Wed Nov 11 09:39:09 2015
@@ -1029,13 +1029,10 @@ serf_hpack_destroy_and_data(serf_bucket_
 }
 
 
-/* ### need to implement */
-#define serf_hpack_readline NULL
-
 const serf_bucket_type_t serf_bucket_type__hpack = {
   "HPACK",
   serf_hpack_read,
-  serf_hpack_readline,
+  serf_default_readline,
   serf_hpack_read_iovec,
   serf_default_read_for_sendfile,
   serf_buckets_are_v2,

Modified: serf/trunk/buckets/http2_frame_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/http2_frame_buckets.c?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/buckets/http2_frame_buckets.c (original)
+++ serf/trunk/buckets/http2_frame_buckets.c Wed Nov 11 09:39:09 2015
@@ -322,13 +322,10 @@ serf_http2_unframe_get_remaining(serf_bu
   return ctx->payload_remaining;
 }
 
-/* ### need to implement */
-#define serf_http2_unframe_readline NULL
-
 const serf_bucket_type_t serf_bucket_type__http2_unframe = {
   "H2-UNFRAME",
   serf_http2_unframe_read,
-  serf_http2_unframe_readline /* ### TODO */,
+  serf_default_readline,
   serf_http2_unframe_read_iovec,
   serf_default_read_for_sendfile,
   serf_buckets_are_v2,
@@ -587,13 +584,10 @@ serf_http2_unpad_get_remaining(serf_buck
   return ctx->payload_remaining;
 }
 
-/* ### need to implement */
-#define serf_h2_dechunk_readline NULL
-
 const serf_bucket_type_t serf_bucket_type__http2_unpad = {
   "H2-UNPAD",
   serf_http2_unpad_read,
-  serf_h2_dechunk_readline /* ### TODO */,
+  serf_default_readline,
   serf_http2_unpad_read_iovec,
   serf_default_read_for_sendfile,
   serf_buckets_are_v2,
@@ -961,13 +955,10 @@ serf_http2_frame_destroy(serf_bucket_t *
   serf_default_destroy_and_data(bucket);
 }
 
-/* ### need to implement */
-#define serf_http2_frame_readline NULL
-
 const serf_bucket_type_t serf_bucket_type__http2_frame = {
   "H2-FRAME",
   serf_http2_frame_read,
-  serf_http2_frame_readline,
+  serf_default_readline,
   serf_http2_frame_read_iovec,
   serf_default_read_for_sendfile,
   serf_buckets_are_v2,

Modified: serf/trunk/buckets/prefix_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/prefix_buckets.c?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/buckets/prefix_buckets.c (original)
+++ serf/trunk/buckets/prefix_buckets.c Wed Nov 11 09:39:09 2015
@@ -226,13 +226,10 @@ static void serf_prefix_destroy(serf_buc
     serf_default_destroy_and_data(bucket);
 }
 
-/* ### need to implement */
-#define serf_prefix_readline NULL
-
 const serf_bucket_type_t serf_bucket_type_prefix = {
   "prefix",
   serf_prefix_read,
-  serf_prefix_readline, /* #### */
+  serf_default_readline,
   serf_prefix_read_iovec,
   serf_default_read_for_sendfile,
   serf_buckets_are_v2,

Modified: serf/trunk/serf_bucket_util.h
URL: 
http://svn.apache.org/viewvc/serf/trunk/serf_bucket_util.h?rev=1713788&r1=1713787&r2=1713788&view=diff
==============================================================================
--- serf/trunk/serf_bucket_util.h (original)
+++ serf/trunk/serf_bucket_util.h Wed Nov 11 09:39:09 2015
@@ -61,6 +61,17 @@ apr_status_t serf_default_read_iovec(
     int *vecs_used);
 
 /**
+ * Default implementation of the @see readline functionality.
+ *
+ * This function will use the @see read function, when possible optimized by
+ * the @a peek function to return the requested result.
+ */
+apr_status_t serf_default_readline(serf_bucket_t *bucket, int acceptable,
+                                   int *found,
+                                   const char **data, apr_size_t *len);
+
+
+/**
  * Default implementation of the @see read_for_sendfile functionality.
  *
  * This function will use the @see read function to get a block of memory,


Reply via email to