change legacy_demangle to be more idiomatic C

the code used to be translated line-to-line from Rust iterators, change
it to be more idiomatic C and guarantee there is no weird for loop.

Fuzzing passes.
diff --git a/crates/native-c/src/demangle.c b/crates/native-c/src/demangle.c
index bb36fe4..b28baf6 100644
--- a/crates/native-c/src/demangle.c
+++ b/crates/native-c/src/demangle.c
@@ -1707,10 +1707,8 @@
     if (chars_len == 0) {
         return DemangleInvalid;
     }
-    char c = *chars++;
-    chars_len--;
-
-    while (c != 'E') {
+    char c;
+    while ((c = *chars) != 'E') {
         // Decode an identifier element's length
         if (c < '0' || c > '9') {
             return DemangleInvalid;
@@ -1726,25 +1724,25 @@
                 return DemangleInvalid;
             }
             len += d;
+
+            chars++;
+            chars_len--;
             if (chars_len == 0) {
                 return DemangleInvalid;
             }
-            c = *chars++;
-            chars_len--;
+            c = *chars;
         }
 
         // Advance by the length
-        for (size_t i = 0; i < len; i++) {
-            if (chars_len == 0) {
-                return DemangleInvalid;
-            }
-            c = *chars++;
-            chars_len--;
+        if (chars_len <= len) {
+            return DemangleInvalid;
         }
+        chars += len;
+        chars_len -= len;
         elements++;
     }
     *res = (struct demangle_legacy) { inner, inner_len, elements };
-    *rest = chars;
+    *rest = chars + 1;
     return DemangleOk;
 }