// This file is generated by apc_parsers.py do not edit! #pragma once #include "base64.h" static inline void parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) { unsigned int pos = 0; size_t payload_start = 0; enum PARSER_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE, PAYLOAD }; enum PARSER_STATES state = KEY, value_state = FLAG; DnDCommand g = {0}; unsigned int i, code; uint64_t lcode; int64_t accumulator; bool is_negative; (void)is_negative; size_t sz; enum KEYS { type = 't', more = 'm', client_id = 'i', operation = 'o', cell_x = 'x', cell_y = 'y', pixel_x = 'X', pixel_y = 'Y' }; enum KEYS key = 'a'; if (parser_buf[pos] == ';') state = AFTER_VALUE; while (pos < parser_buf_pos) { switch (state) { case KEY: key = parser_buf[pos++]; state = EQUAL; switch (key) { case type: value_state = FLAG; break; case more: value_state = UINT; break; case client_id: value_state = UINT; break; case operation: value_state = UINT; break; case cell_x: value_state = INT; break; case cell_y: value_state = INT; break; case pixel_x: value_state = INT; break; case pixel_y: value_state = INT; break; default: REPORT_ERROR( "Malformed DnDCommand control block, invalid key character: 0x%x", key); return; } break; case EQUAL: if (parser_buf[pos++] != '=') { REPORT_ERROR("Malformed DnDCommand control block, no = after key, " "found: 0x%x instead", parser_buf[pos - 1]); return; } state = value_state; break; case FLAG: switch (key) { case type: { g.type = parser_buf[pos++]; if (g.type != 'A' && g.type != 'E' && g.type != 'M' && g.type != 'P' && g.type != 'R' && g.type != 'a' && g.type != 'e' && g.type != 'k' && g.type != 'm' && g.type != 'o' && g.type != 'p' && g.type != 'r') { REPORT_ERROR("Malformed DnDCommand control block, unknown flag value " "for type: 0x%x", g.type); return; }; } break; default: break; } state = AFTER_VALUE; break; case INT: #define READ_UINT \ for (i = pos, accumulator = 0; i < MIN(parser_buf_pos, pos + 10); i++) { \ int64_t n = parser_buf[i] - '0'; \ if (n < 0 || n > 9) \ break; \ accumulator += n * digit_multipliers[i - pos]; \ } \ if (i == pos) { \ REPORT_ERROR("Malformed DnDCommand control block, expecting an integer " \ "value for key: %c", \ key & 0xFF); \ return; \ } \ lcode = accumulator / digit_multipliers[i - pos - 1]; \ pos = i; \ if (lcode > UINT32_MAX) { \ REPORT_ERROR("Malformed DnDCommand control block, number is too large"); \ return; \ } \ code = lcode; is_negative = false; if (parser_buf[pos] == '-') { is_negative = true; pos++; } #define I(x) \ case x: \ g.x = is_negative ? 0 - (int32_t)code : (int32_t)code; \ break READ_UINT; switch (key) { I(cell_x); I(cell_y); I(pixel_x); I(pixel_y); default: break; } state = AFTER_VALUE; break; #undef I case UINT: READ_UINT; #define U(x) \ case x: \ g.x = code; \ break switch (key) { U(more); U(client_id); U(operation); default: break; } state = AFTER_VALUE; break; #undef U #undef READ_UINT case AFTER_VALUE: switch (parser_buf[pos++]) { default: REPORT_ERROR("Malformed DnDCommand control block, expecting a : or " "semi-colon after a value, found: 0x%x", parser_buf[pos - 1]); return; case ':': state = KEY; break; case ';': state = PAYLOAD; break; } break; case PAYLOAD: { sz = parser_buf_pos - pos; payload_start = pos; g.payload_sz = sz; pos = parser_buf_pos; } break; } // end switch } // end while switch (state) { case EQUAL: REPORT_ERROR("Malformed DnDCommand control block, no = after key"); return; case INT: case UINT: REPORT_ERROR( "Malformed DnDCommand control block, expecting an integer value"); return; case FLAG: REPORT_ERROR("Malformed DnDCommand control block, expecting a flag value"); return; default: break; } REPORT_VA_COMMAND( "K s {sc sI sI sI si si si si ss#}", self->window_id, "dnd_command", "type", g.type, "more", (unsigned int)g.more, "client_id", (unsigned int)g.client_id, "operation", (unsigned int)g.operation, "cell_x", (int)g.cell_x, "cell_y", (int)g.cell_y, "pixel_x", (int)g.pixel_x, "pixel_y", (int)g.pixel_y, "", (char *)parser_buf + payload_start, g.payload_sz); screen_handle_dnd_command(self->screen, &g, parser_buf + payload_start); }