Implement skipstone_message_unpack()

This commit is contained in:
XANTRONIX Development 2020-09-22 09:35:54 -05:00
parent ae3c45fe02
commit 448937b6fb
2 changed files with 78 additions and 0 deletions

View file

@ -14,4 +14,8 @@ ssize_t skipstone_message_pack(void *message,
size_t len,
const char *template, ...);
ssize_t skipstone_message_unpack(void *message,
size_t len,
const char *template, ...);
#endif /* _SKIPSTONE_MESSAGE_H */

View file

@ -95,3 +95,77 @@ error_invalid_template:
return -1;
}
#define case_unpack(t, bytes) \
case t: \
if (len < offset + bytes) { \
goto done; \
} \
memcpy(va_arg(args, void *), (uint8_t *)message + offset, bytes); \
offset += bytes; \
break;
ssize_t skipstone_message_unpack(void *message,
size_t len,
const char *template, ...) {
va_list args;
size_t offset = 0,
i;
va_start(args, template);
for (i=0; template[i]; i++) {
char c = template[i];
switch (c) {
case_unpack('c', sizeof(int8_t));
case_unpack('C', sizeof(uint8_t));
case_unpack('s', sizeof(int16_t));
case_unpack('S', sizeof(uint16_t));
case_unpack('l', sizeof(int32_t));
case_unpack('L', sizeof(uint32_t));
case_unpack('q', sizeof(int64_t));
case_unpack('Q', sizeof(uint64_t));
case 'z': {
uint8_t sz;
void *dest;
if (len < offset + 1) {
goto done;
}
sz = ((uint8_t *)message)[offset++];
if (len < offset + sz + 1) {
goto done;
}
dest = va_arg(args, void *);
memcpy(dest, (uint8_t *)message + offset, sz);
offset += sz;
((uint8_t *)message)[offset++] = '\0';
break;
}
default:
errno = EINVAL;
goto error_invalid;
}
}
va_end(args);
done:
return offset;
error_invalid:
va_end(args);
return -1;
}