diff options
Diffstat (limited to 'libcoopgamma_get_crtcs_recv.c')
-rw-r--r-- | libcoopgamma_get_crtcs_recv.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/libcoopgamma_get_crtcs_recv.c b/libcoopgamma_get_crtcs_recv.c new file mode 100644 index 0000000..16e9ba5 --- /dev/null +++ b/libcoopgamma_get_crtcs_recv.c @@ -0,0 +1,70 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * List all available CRTC:s, receive response part + * + * @param ctx The state of the library, must be connected + * @param async Information about the request + * @return A `NULL`-terminated list of names. You should only free + * the outer pointer, inner pointers are subpointers of the + * outer pointer and cannot be freed. `NULL` on error, in + * which case `ctx->error` (rather than `errno`) is read + * for information about the error. + */ +char ** +libcoopgamma_get_crtcs_recv(libcoopgamma_context_t *restrict ctx, libcoopgamma_async_context_t *restrict async) +{ + char *line; + char *payload; + char *end; + int command_ok = 0; + size_t i, n, lines, len, length; + char **rc; + + if (libcoopgamma_check_error__(ctx, async)) + return NULL; + + for (;;) { + line = libcoopgamma_next_header__(ctx); + if (!*line) + break; + else if (!strcmp(line, "Command: crtc-enumeration")) + command_ok = 1; + } + + payload = libcoopgamma_next_payload__(ctx, &n); + + if (!command_ok || (n > 0 && payload[n - 1U] != '\n')) { + errno = EBADMSG; + copy_errno(ctx); + return NULL; + } + + line = payload; + end = &payload[n]; + lines = length = 0; + while (line != end) { + lines += 1U; + length += len = (size_t)(&strchr(line, '\n')[1U] - line); + line += len; + line[-1] = '\0'; + } + + rc = malloc((lines + 1U) * sizeof(char *) + length); + if (!rc) { + copy_errno(ctx); + return NULL; + } + + line = ((char *)rc) + (lines + 1U) * sizeof(char *); + memcpy(line, payload, length); + rc[lines] = NULL; + for (i = 0; i < lines; i++) { + rc[i] = line; + line = &strchr(line, '\0')[1U]; + } + + return rc; +} |