Parser: merge the break-handling code in enter_container()

There was a section of code that was mostly the same, dealing with the
possibility of reading a Break (0xFF) as the next element in a map or
array. The only difference was that preparse_next_value() also
decremented the item count for the current list.

We could have used that, but that would have meant a +1 on the list,
which in turn lowers the number of possible elements from UINT32_MAX-1
to UINT32_MAX-2. Not a big deal, but we can avoid it by just splitting
to a new function and retaining tail-call optimisations.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
diff --git a/src/cborparser.c b/src/cborparser.c
index 6410faf..099cdc8 100644
--- a/src/cborparser.c
+++ b/src/cborparser.c
@@ -297,15 +297,9 @@
     return CborNoError;
 }
 
-static CborError preparse_next_value(CborValue *it)
+static CborError preparse_next_value_nodecrement(CborValue *it)
 {
-    if (it->remaining != UINT32_MAX) {
-        /* don't decrement the item count if the current item is tag: they don't count */
-        if (it->type != CborTagType && !--it->remaining) {
-            it->type = CborInvalidType;
-            return CborNoError;
-        }
-    } else if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) {
+    if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) {
         /* end of map or array */
         ++it->ptr;
         it->type = CborInvalidType;
@@ -316,6 +310,18 @@
     return preparse_value(it);
 }
 
+static CborError preparse_next_value(CborValue *it)
+{
+    if (it->remaining != UINT32_MAX) {
+        /* don't decrement the item count if the current item is tag: they don't count */
+        if (it->type != CborTagType && --it->remaining == 0) {
+            it->type = CborInvalidType;
+            return CborNoError;
+        }
+    }
+    return preparse_next_value_nodecrement(it);
+}
+
 static CborError advance_internal(CborValue *it)
 {
     uint64_t length;
@@ -578,22 +584,15 @@
  */
 CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed)
 {
-    CborError err;
     cbor_assert(cbor_value_is_container(it));
     *recursed = *it;
 
     if (it->flags & CborIteratorFlag_UnknownLength) {
         recursed->remaining = UINT32_MAX;
         ++recursed->ptr;
-        err = preparse_value(recursed);
-        if (err != CborErrorUnexpectedBreak)
-            return err;
-        /* actually, break was expected here
-         * it's just an empty container */
-        ++recursed->ptr;
     } else {
         uint64_t len;
-        err = _cbor_value_extract_number(&recursed->ptr, recursed->parser->end, &len);
+        CborError err = _cbor_value_extract_number(&recursed->ptr, recursed->parser->end, &len);
         cbor_assert(err == CborNoError);
 
         recursed->remaining = (uint32_t)len;
@@ -611,14 +610,13 @@
             }
             recursed->remaining *= 2;
         }
-        if (len != 0)
-            return preparse_value(recursed);
+        if (len == 0) {
+            /* the case of the empty container */
+            recursed->type = CborInvalidType;
+            return CborNoError;
+        }
     }
-
-    /* the case of the empty container */
-    recursed->type = CborInvalidType;
-    recursed->remaining = 0;
-    return CborNoError;
+    return preparse_next_value_nodecrement(recursed);
 }
 
 /**