- const char *p = types;
-
- for (;;)
- {
- uint8_t c;
-
- /* Find next type character. */
- while (*p == ' ')
- p++;
- if (*p == '\0')
- return BACKDOOR_OK;
-
- /* Check type character in input. */
- if (!in (&c, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (c != *p++)
- return BACKDOOR_TYPE_MISMATCH;
-
- switch (c)
- {
- case 's':
- {
- int32_t length;
-
- if (!unmarshal_int32 (&length, in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (length < 0)
- return BACKDOOR_NEGATIVE_SIZE;
- if (*p == '\'')
- {
- const char *end = strchr (++p, '\'');
- if (length != end - p)
- return BACKDOOR_STRING_MISMATCH;
- while (p < end)
- {
- uint8_t q;
- if (!in (&q, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (q != *p++)
- return BACKDOOR_STRING_MISMATCH;
- }
- p++;
- }
- else
- {
- char *s = malloc (length + 1);
- if (s == NULL)
- return BACKDOOR_NOMEM;
- if (!unmarshal_bytes (s, length, in, aux))
- {
- free (s);
- return BACKDOOR_UNEXPECTED_EOF;
- }
- s[length] = '\0';
- *va_arg (args, char **) = s;
- }
- }
- break;
-
- case 'i':
- if (!unmarshal_int32 (va_arg (args, int32_t *), in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- break;
-
- case 'B':
- {
- int32_t size;
- void *buffer;
-
- if (!unmarshal_int32 (&size, in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (size < 0)
- return BACKDOOR_NEGATIVE_SIZE;
- buffer = malloc (size);
- if (size > 0 && buffer == NULL)
- return BACKDOOR_NOMEM;
- if (!unmarshal_bytes (buffer, size, in, aux))
- {
- free (buffer);
- return BACKDOOR_UNEXPECTED_EOF;
- }
- *va_arg (args, size_t *) = size;
- *va_arg (args, void **) = buffer;
- }
- break;
-
- case 'b':
- {
- int32_t b;
- if (!unmarshal_int32 (&b, in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- *va_arg (args, bool *) = b;
- }
- break;
-
- default:
- return BACKDOOR_BAD_TYPE;
- }
- }