mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-24 14:12:02 +00:00
Cleanup OSC/APC number parsing
This commit is contained in:
parent
5e2660143f
commit
b381d2eb65
5 changed files with 365 additions and 612 deletions
|
|
@ -168,7 +168,7 @@ static inline void
|
|||
enum PARSER_STATES state = KEY, value_state = FLAG;
|
||||
{command_class} g = {{0}};{post_init_line}
|
||||
unsigned int i, code;
|
||||
uint64_t lcode; int64_t accumulator;
|
||||
uint64_t lcode;
|
||||
bool is_negative; (void)is_negative;
|
||||
size_t sz;
|
||||
{keys_enum}
|
||||
|
|
@ -207,12 +207,12 @@ static inline void
|
|||
|
||||
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]; \\
|
||||
for (i = pos, lcode=0; i < MIN(parser_buf_pos, pos + 10); i++) {{ \\
|
||||
uint8_t n = parser_buf[i] - '0'; if (n > 9) break; \\
|
||||
lcode = lcode * 10 + n; \\
|
||||
}} \\
|
||||
if (i == pos) {{ REPORT_ERROR("Malformed {command_class} control block, expecting an integer value for key: %c", key & 0xFF); return; }} \\
|
||||
lcode = accumulator / digit_multipliers[i - pos - 1]; pos = i; \\
|
||||
pos = i; \\
|
||||
if (lcode > UINT32_MAX) {{ REPORT_ERROR("Malformed {command_class} control block, number is too large"); return; }} \\
|
||||
code = lcode;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
|||
DnDCommand g = {0};
|
||||
unsigned int i, code;
|
||||
uint64_t lcode;
|
||||
int64_t accumulator;
|
||||
bool is_negative;
|
||||
(void)is_negative;
|
||||
size_t sz;
|
||||
|
|
@ -43,10 +42,7 @@ parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
|||
|
||||
case EQUAL:
|
||||
if (parser_buf[pos++] != '=') {
|
||||
REPORT_ERROR(
|
||||
"Malformed DnDCommand control block, no = after key, "
|
||||
"found: 0x%x instead",
|
||||
parser_buf[pos - 1]);
|
||||
REPORT_ERROR("Malformed DnDCommand control block, no = after key, found: 0x%x instead", parser_buf[pos - 1]);
|
||||
return;
|
||||
}
|
||||
state = value_state;
|
||||
|
|
@ -58,10 +54,7 @@ parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
|||
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 != 'q' && g.type != 'r') {
|
||||
REPORT_ERROR(
|
||||
"Malformed DnDCommand control block, unknown flag value "
|
||||
"for type: 0x%x",
|
||||
g.type);
|
||||
REPORT_ERROR("Malformed DnDCommand control block, unknown flag value for type: 0x%x", g.type);
|
||||
return;
|
||||
};
|
||||
} break;
|
||||
|
|
@ -72,25 +65,21 @@ parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
|||
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; \
|
||||
} \
|
||||
#define READ_UINT \
|
||||
for (i = pos, lcode = 0; i < MIN(parser_buf_pos, pos + 10); i++) { \
|
||||
uint8_t n = parser_buf[i] - '0'; \
|
||||
if (n > 9) break; \
|
||||
lcode = lcode * 10 + n; \
|
||||
} \
|
||||
if (i == pos) { \
|
||||
REPORT_ERROR("Malformed DnDCommand control block, expecting an integer value for key: %c", key & 0xFF); \
|
||||
return; \
|
||||
} \
|
||||
pos = i; \
|
||||
if (lcode > UINT32_MAX) { \
|
||||
REPORT_ERROR("Malformed DnDCommand control block, number is too large"); \
|
||||
return; \
|
||||
} \
|
||||
code = lcode;
|
||||
|
||||
is_negative = false;
|
||||
|
|
@ -128,16 +117,14 @@ parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
|||
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]);
|
||||
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;
|
||||
|
|
@ -145,6 +132,7 @@ parse_dnd_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
|||
pos = parser_buf_pos;
|
||||
} break;
|
||||
|
||||
|
||||
} // end switch
|
||||
} // end while
|
||||
|
||||
|
|
|
|||
581
kitty/parse-graphics-command.h
generated
581
kitty/parse-graphics-command.h
generated
|
|
@ -2,395 +2,238 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "base64.h"
|
||||
#include "base64.h"
|
||||
|
||||
static inline void parse_graphics_code(PS *self, uint8_t *parser_buf,
|
||||
const size_t parser_buf_pos) {
|
||||
unsigned int pos = 1;
|
||||
static inline void
|
||||
parse_graphics_code(PS *self, uint8_t *parser_buf, const size_t parser_buf_pos) {
|
||||
unsigned int pos = 1;
|
||||
|
||||
enum PARSER_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE , PAYLOAD };
|
||||
enum PARSER_STATES state = KEY, value_state = FLAG;
|
||||
GraphicsCommand g = {0};
|
||||
unsigned int i, code;
|
||||
uint64_t lcode;
|
||||
bool is_negative; (void)is_negative;
|
||||
size_t sz;
|
||||
|
||||
enum KEYS {
|
||||
action='a',
|
||||
delete_action='d',
|
||||
transmission_type='t',
|
||||
compressed='o',
|
||||
format='f',
|
||||
more='m',
|
||||
id='i',
|
||||
image_number='I',
|
||||
placement_id='p',
|
||||
quiet='q',
|
||||
width='w',
|
||||
height='h',
|
||||
x_offset='x',
|
||||
y_offset='y',
|
||||
data_height='v',
|
||||
data_width='s',
|
||||
data_sz='S',
|
||||
data_offset='O',
|
||||
num_cells='c',
|
||||
num_lines='r',
|
||||
cell_x_offset='X',
|
||||
cell_y_offset='Y',
|
||||
z_index='z',
|
||||
cursor_movement='C',
|
||||
unicode_placement='U',
|
||||
parent_id='P',
|
||||
parent_placement_id='Q',
|
||||
usage_hints='N',
|
||||
offset_from_parent_x='H',
|
||||
offset_from_parent_y='V'
|
||||
};
|
||||
|
||||
enum KEYS key = 'a';
|
||||
if (parser_buf[pos] == ';') state = AFTER_VALUE;
|
||||
|
||||
enum PARSER_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE, PAYLOAD };
|
||||
enum PARSER_STATES state = KEY, value_state = FLAG;
|
||||
GraphicsCommand g = {0};
|
||||
unsigned int i, code;
|
||||
uint64_t lcode;
|
||||
int64_t accumulator;
|
||||
bool is_negative;
|
||||
(void)is_negative;
|
||||
size_t sz;
|
||||
while (pos < parser_buf_pos) {
|
||||
switch(state) {
|
||||
case KEY:
|
||||
key = parser_buf[pos++];
|
||||
state = EQUAL;
|
||||
switch(key) {
|
||||
case action: value_state = FLAG; break;
|
||||
case delete_action: value_state = FLAG; break;
|
||||
case transmission_type: value_state = FLAG; break;
|
||||
case compressed: value_state = FLAG; break;
|
||||
case format: value_state = UINT; break;
|
||||
case more: value_state = UINT; break;
|
||||
case id: value_state = UINT; break;
|
||||
case image_number: value_state = UINT; break;
|
||||
case placement_id: value_state = UINT; break;
|
||||
case quiet: value_state = UINT; break;
|
||||
case width: value_state = UINT; break;
|
||||
case height: value_state = UINT; break;
|
||||
case x_offset: value_state = UINT; break;
|
||||
case y_offset: value_state = UINT; break;
|
||||
case data_height: value_state = UINT; break;
|
||||
case data_width: value_state = UINT; break;
|
||||
case data_sz: value_state = UINT; break;
|
||||
case data_offset: value_state = UINT; break;
|
||||
case num_cells: value_state = UINT; break;
|
||||
case num_lines: value_state = UINT; break;
|
||||
case cell_x_offset: value_state = UINT; break;
|
||||
case cell_y_offset: value_state = UINT; break;
|
||||
case z_index: value_state = INT; break;
|
||||
case cursor_movement: value_state = UINT; break;
|
||||
case unicode_placement: value_state = UINT; break;
|
||||
case parent_id: value_state = UINT; break;
|
||||
case parent_placement_id: value_state = UINT; break;
|
||||
case usage_hints: value_state = UINT; break;
|
||||
case offset_from_parent_x: value_state = INT; break;
|
||||
case offset_from_parent_y: value_state = INT; break;
|
||||
default:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, invalid key character: 0x%x", key);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
enum KEYS {
|
||||
action = 'a',
|
||||
delete_action = 'd',
|
||||
transmission_type = 't',
|
||||
compressed = 'o',
|
||||
format = 'f',
|
||||
more = 'm',
|
||||
id = 'i',
|
||||
image_number = 'I',
|
||||
placement_id = 'p',
|
||||
quiet = 'q',
|
||||
width = 'w',
|
||||
height = 'h',
|
||||
x_offset = 'x',
|
||||
y_offset = 'y',
|
||||
data_height = 'v',
|
||||
data_width = 's',
|
||||
data_sz = 'S',
|
||||
data_offset = 'O',
|
||||
num_cells = 'c',
|
||||
num_lines = 'r',
|
||||
cell_x_offset = 'X',
|
||||
cell_y_offset = 'Y',
|
||||
z_index = 'z',
|
||||
cursor_movement = 'C',
|
||||
unicode_placement = 'U',
|
||||
parent_id = 'P',
|
||||
parent_placement_id = 'Q',
|
||||
usage_hints = 'N',
|
||||
offset_from_parent_x = 'H',
|
||||
offset_from_parent_y = 'V'
|
||||
};
|
||||
case EQUAL:
|
||||
if (parser_buf[pos++] != '=') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key, found: 0x%x instead", parser_buf[pos-1]);
|
||||
return;
|
||||
}
|
||||
state = value_state;
|
||||
break;
|
||||
|
||||
enum KEYS key = 'a';
|
||||
if (parser_buf[pos] == ';')
|
||||
state = AFTER_VALUE;
|
||||
case FLAG:
|
||||
switch(key) {
|
||||
|
||||
case action: {
|
||||
g.action = parser_buf[pos++];
|
||||
if (g.action != 'T' && g.action != 'a' && g.action != 'c' && g.action != 'd' && g.action != 'f' && g.action != 'p' && g.action != 'q' && g.action != 't') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for action: 0x%x", g.action);
|
||||
return;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
while (pos < parser_buf_pos) {
|
||||
switch (state) {
|
||||
case KEY:
|
||||
key = parser_buf[pos++];
|
||||
state = EQUAL;
|
||||
switch (key) {
|
||||
case action:
|
||||
value_state = FLAG;
|
||||
break;
|
||||
case delete_action:
|
||||
value_state = FLAG;
|
||||
break;
|
||||
case transmission_type:
|
||||
value_state = FLAG;
|
||||
break;
|
||||
case compressed:
|
||||
value_state = FLAG;
|
||||
break;
|
||||
case format:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case more:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case id:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case image_number:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case placement_id:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case quiet:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case width:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case height:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case x_offset:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case y_offset:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case data_height:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case data_width:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case data_sz:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case data_offset:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case num_cells:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case num_lines:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case cell_x_offset:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case cell_y_offset:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case z_index:
|
||||
value_state = INT;
|
||||
break;
|
||||
case cursor_movement:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case unicode_placement:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case parent_id:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case parent_placement_id:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case usage_hints:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case offset_from_parent_x:
|
||||
value_state = INT;
|
||||
break;
|
||||
case offset_from_parent_y:
|
||||
value_state = INT;
|
||||
break;
|
||||
default:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, invalid key "
|
||||
"character: 0x%x",
|
||||
key);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case delete_action: {
|
||||
g.delete_action = parser_buf[pos++];
|
||||
if (g.delete_action != 'A' && g.delete_action != 'C' && g.delete_action != 'F' && g.delete_action != 'I' && g.delete_action != 'N' && g.delete_action != 'P' && g.delete_action != 'Q' && g.delete_action != 'R' && g.delete_action != 'X' && g.delete_action != 'Y' && g.delete_action != 'Z' && g.delete_action != 'a' && g.delete_action != 'c' && g.delete_action != 'f' && g.delete_action != 'i' && g.delete_action != 'n' && g.delete_action != 'p' && g.delete_action != 'q' && g.delete_action != 'r' && g.delete_action != 'x' && g.delete_action != 'y' && g.delete_action != 'z') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for delete_action: 0x%x", g.delete_action);
|
||||
return;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case EQUAL:
|
||||
if (parser_buf[pos++] != '=') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key, "
|
||||
"found: 0x%x instead",
|
||||
parser_buf[pos - 1]);
|
||||
return;
|
||||
}
|
||||
state = value_state;
|
||||
break;
|
||||
case transmission_type: {
|
||||
g.transmission_type = parser_buf[pos++];
|
||||
if (g.transmission_type != 'd' && g.transmission_type != 'f' && g.transmission_type != 's' && g.transmission_type != 't') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for transmission_type: 0x%x", g.transmission_type);
|
||||
return;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FLAG:
|
||||
switch (key) {
|
||||
case compressed: {
|
||||
g.compressed = parser_buf[pos++];
|
||||
if (g.compressed != 'z') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for compressed: 0x%x", g.compressed);
|
||||
return;
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
|
||||
case action: {
|
||||
g.action = parser_buf[pos++];
|
||||
if (g.action != 'T' && g.action != 'a' && g.action != 'c' &&
|
||||
g.action != 'd' && g.action != 'f' && g.action != 'p' &&
|
||||
g.action != 'q' && g.action != 't') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||
"value for action: 0x%x",
|
||||
g.action);
|
||||
return;
|
||||
};
|
||||
} break;
|
||||
case INT:
|
||||
#define READ_UINT \
|
||||
for (i = pos, lcode=0; i < MIN(parser_buf_pos, pos + 10); i++) { \
|
||||
uint8_t n = parser_buf[i] - '0'; if (n > 9) break; \
|
||||
lcode = lcode * 10 + n; \
|
||||
} \
|
||||
if (i == pos) { REPORT_ERROR("Malformed GraphicsCommand control block, expecting an integer value for key: %c", key & 0xFF); return; } \
|
||||
pos = i; \
|
||||
if (lcode > UINT32_MAX) { REPORT_ERROR("Malformed GraphicsCommand control block, number is too large"); return; } \
|
||||
code = lcode;
|
||||
|
||||
case delete_action: {
|
||||
g.delete_action = parser_buf[pos++];
|
||||
if (g.delete_action != 'A' && g.delete_action != 'C' &&
|
||||
g.delete_action != 'F' && g.delete_action != 'I' &&
|
||||
g.delete_action != 'N' && g.delete_action != 'P' &&
|
||||
g.delete_action != 'Q' && g.delete_action != 'R' &&
|
||||
g.delete_action != 'X' && g.delete_action != 'Y' &&
|
||||
g.delete_action != 'Z' && g.delete_action != 'a' &&
|
||||
g.delete_action != 'c' && g.delete_action != 'f' &&
|
||||
g.delete_action != 'i' && g.delete_action != 'n' &&
|
||||
g.delete_action != 'p' && g.delete_action != 'q' &&
|
||||
g.delete_action != 'r' && g.delete_action != 'x' &&
|
||||
g.delete_action != 'y' && g.delete_action != 'z') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||
"value for delete_action: 0x%x",
|
||||
g.delete_action);
|
||||
return;
|
||||
};
|
||||
} break;
|
||||
|
||||
case transmission_type: {
|
||||
g.transmission_type = parser_buf[pos++];
|
||||
if (g.transmission_type != 'd' && g.transmission_type != 'f' &&
|
||||
g.transmission_type != 's' && g.transmission_type != 't') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||
"value for transmission_type: 0x%x",
|
||||
g.transmission_type);
|
||||
return;
|
||||
};
|
||||
} break;
|
||||
|
||||
case compressed: {
|
||||
g.compressed = parser_buf[pos++];
|
||||
if (g.compressed != 'z') {
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||
"value for compressed: 0x%x",
|
||||
g.compressed);
|
||||
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 GraphicsCommand 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 GraphicsCommand 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(z_index);
|
||||
I(offset_from_parent_x);
|
||||
I(offset_from_parent_y);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
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(z_index); I(offset_from_parent_x); I(offset_from_parent_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(format);
|
||||
U(more);
|
||||
U(id);
|
||||
U(image_number);
|
||||
U(placement_id);
|
||||
U(quiet);
|
||||
U(width);
|
||||
U(height);
|
||||
U(x_offset);
|
||||
U(y_offset);
|
||||
U(data_height);
|
||||
U(data_width);
|
||||
U(data_sz);
|
||||
U(data_offset);
|
||||
U(num_cells);
|
||||
U(num_lines);
|
||||
U(cell_x_offset);
|
||||
U(cell_y_offset);
|
||||
U(cursor_movement);
|
||||
U(unicode_placement);
|
||||
U(parent_id);
|
||||
U(parent_placement_id);
|
||||
U(usage_hints);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
case UINT:
|
||||
READ_UINT;
|
||||
#define U(x) case x: g.x = code; break
|
||||
switch(key) {
|
||||
U(format); U(more); U(id); U(image_number); U(placement_id); U(quiet); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(data_sz); U(data_offset); U(num_cells); U(num_lines); U(cell_x_offset); U(cell_y_offset); U(cursor_movement); U(unicode_placement); U(parent_id); U(parent_placement_id); U(usage_hints);
|
||||
default: break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
#undef U
|
||||
#undef READ_UINT
|
||||
|
||||
case AFTER_VALUE:
|
||||
switch (parser_buf[pos++]) {
|
||||
default:
|
||||
REPORT_ERROR("Malformed GraphicsCommand 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 AFTER_VALUE:
|
||||
switch (parser_buf[pos++]) {
|
||||
default:
|
||||
REPORT_ERROR("Malformed GraphicsCommand 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;
|
||||
g.payload_sz = MAX(BUF_EXTRA, sz);
|
||||
if (!base64_decode8(parser_buf + pos, sz, parser_buf, &g.payload_sz)) {
|
||||
g.payload_sz = MAX(BUF_EXTRA, sz);
|
||||
REPORT_ERROR("Failed to parse GraphicsCommand command payload with "
|
||||
"error: invalid base64 data in chunk of size: %zu "
|
||||
"with output buffer size: %zu",
|
||||
sz, g.payload_sz);
|
||||
return;
|
||||
}
|
||||
pos = parser_buf_pos;
|
||||
} break;
|
||||
|
||||
case PAYLOAD: {
|
||||
sz = parser_buf_pos - pos;
|
||||
g.payload_sz = MAX(BUF_EXTRA, sz);
|
||||
if (!base64_decode8(parser_buf + pos, sz, parser_buf, &g.payload_sz)) {
|
||||
g.payload_sz = MAX(BUF_EXTRA, sz);
|
||||
REPORT_ERROR("Failed to parse GraphicsCommand command payload with error: invalid base64 data in chunk of size: %zu with output buffer size: %zu", sz, g.payload_sz); return; }
|
||||
pos = parser_buf_pos;
|
||||
} break;
|
||||
|
||||
|
||||
} // end switch
|
||||
} // end while
|
||||
} // end switch
|
||||
} // end while
|
||||
|
||||
switch (state) {
|
||||
case EQUAL:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key");
|
||||
return;
|
||||
case INT:
|
||||
case UINT:
|
||||
REPORT_ERROR(
|
||||
"Malformed GraphicsCommand control block, expecting an integer value");
|
||||
return;
|
||||
case FLAG:
|
||||
REPORT_ERROR(
|
||||
"Malformed GraphicsCommand control block, expecting a flag value");
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(state) {
|
||||
case EQUAL:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key"); return;
|
||||
case INT:
|
||||
case UINT:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, expecting an integer value"); return;
|
||||
case FLAG:
|
||||
REPORT_ERROR("Malformed GraphicsCommand control block, expecting a flag value"); return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
REPORT_VA_COMMAND(
|
||||
"K s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI "
|
||||
"sI sI sI sI sI si si si ss#}",
|
||||
self->window_id, "graphics_command",
|
||||
REPORT_VA_COMMAND("K s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si si si ss#}", self->window_id, "graphics_command",
|
||||
|
||||
"action", g.action, "delete_action", g.delete_action, "transmission_type",
|
||||
g.transmission_type, "compressed", g.compressed,
|
||||
"action", g.action, "delete_action", g.delete_action, "transmission_type", g.transmission_type, "compressed", g.compressed,
|
||||
|
||||
"format", (unsigned int)g.format, "more", (unsigned int)g.more, "id",
|
||||
(unsigned int)g.id, "image_number", (unsigned int)g.image_number,
|
||||
"placement_id", (unsigned int)g.placement_id, "quiet",
|
||||
(unsigned int)g.quiet, "width", (unsigned int)g.width, "height",
|
||||
(unsigned int)g.height, "x_offset", (unsigned int)g.x_offset, "y_offset",
|
||||
(unsigned int)g.y_offset, "data_height", (unsigned int)g.data_height,
|
||||
"data_width", (unsigned int)g.data_width, "data_sz",
|
||||
(unsigned int)g.data_sz, "data_offset", (unsigned int)g.data_offset,
|
||||
"num_cells", (unsigned int)g.num_cells, "num_lines",
|
||||
(unsigned int)g.num_lines, "cell_x_offset", (unsigned int)g.cell_x_offset,
|
||||
"cell_y_offset", (unsigned int)g.cell_y_offset, "cursor_movement",
|
||||
(unsigned int)g.cursor_movement, "unicode_placement",
|
||||
(unsigned int)g.unicode_placement, "parent_id", (unsigned int)g.parent_id,
|
||||
"parent_placement_id", (unsigned int)g.parent_placement_id, "usage_hints",
|
||||
(unsigned int)g.usage_hints,
|
||||
"format", (unsigned int)g.format, "more", (unsigned int)g.more, "id", (unsigned int)g.id, "image_number", (unsigned int)g.image_number, "placement_id", (unsigned int)g.placement_id, "quiet", (unsigned int)g.quiet, "width", (unsigned int)g.width, "height", (unsigned int)g.height, "x_offset", (unsigned int)g.x_offset, "y_offset", (unsigned int)g.y_offset, "data_height", (unsigned int)g.data_height, "data_width", (unsigned int)g.data_width, "data_sz", (unsigned int)g.data_sz, "data_offset", (unsigned int)g.data_offset, "num_cells", (unsigned int)g.num_cells, "num_lines", (unsigned int)g.num_lines, "cell_x_offset", (unsigned int)g.cell_x_offset, "cell_y_offset", (unsigned int)g.cell_y_offset, "cursor_movement", (unsigned int)g.cursor_movement, "unicode_placement", (unsigned int)g.unicode_placement, "parent_id", (unsigned int)g.parent_id, "parent_placement_id", (unsigned int)g.parent_placement_id, "usage_hints", (unsigned int)g.usage_hints,
|
||||
|
||||
"z_index", (int)g.z_index, "offset_from_parent_x",
|
||||
(int)g.offset_from_parent_x, "offset_from_parent_y",
|
||||
(int)g.offset_from_parent_y,
|
||||
"z_index", (int)g.z_index, "offset_from_parent_x", (int)g.offset_from_parent_x, "offset_from_parent_y", (int)g.offset_from_parent_y,
|
||||
|
||||
"", (char *)parser_buf, g.payload_sz);
|
||||
"", (char*)parser_buf, g.payload_sz
|
||||
);
|
||||
|
||||
screen_handle_graphics_command(self->screen, &g, parser_buf);
|
||||
screen_handle_graphics_command(self->screen, &g, parser_buf);
|
||||
}
|
||||
|
||||
|
|
|
|||
304
kitty/parse-multicell-command.h
generated
304
kitty/parse-multicell-command.h
generated
|
|
@ -2,201 +2,145 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "base64.h"
|
||||
#include "base64.h"
|
||||
|
||||
static inline void parse_multicell_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;
|
||||
MultiCellCommand g = {0};
|
||||
unsigned int i, code;
|
||||
uint64_t lcode;
|
||||
int64_t accumulator;
|
||||
bool is_negative;
|
||||
(void)is_negative;
|
||||
size_t sz;
|
||||
static inline void
|
||||
parse_multicell_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;
|
||||
MultiCellCommand g = {0};
|
||||
unsigned int i, code;
|
||||
uint64_t lcode;
|
||||
bool is_negative; (void)is_negative;
|
||||
size_t sz;
|
||||
|
||||
enum KEYS {
|
||||
width='w',
|
||||
scale='s',
|
||||
subscale_n='n',
|
||||
subscale_d='d',
|
||||
vertical_align='v',
|
||||
horizontal_align='h'
|
||||
};
|
||||
|
||||
enum KEYS key = 'a';
|
||||
if (parser_buf[pos] == ';') state = AFTER_VALUE;
|
||||
|
||||
enum KEYS {
|
||||
width = 'w',
|
||||
scale = 's',
|
||||
subscale_n = 'n',
|
||||
subscale_d = 'd',
|
||||
vertical_align = 'v',
|
||||
horizontal_align = 'h'
|
||||
};
|
||||
while (pos < parser_buf_pos) {
|
||||
switch(state) {
|
||||
case KEY:
|
||||
key = parser_buf[pos++];
|
||||
state = EQUAL;
|
||||
switch(key) {
|
||||
case width: value_state = UINT; break;
|
||||
case scale: value_state = UINT; break;
|
||||
case subscale_n: value_state = UINT; break;
|
||||
case subscale_d: value_state = UINT; break;
|
||||
case vertical_align: value_state = UINT; break;
|
||||
case horizontal_align: value_state = UINT; break;
|
||||
default:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, invalid key character: 0x%x", key);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
enum KEYS key = 'a';
|
||||
if (parser_buf[pos] == ';')
|
||||
state = AFTER_VALUE;
|
||||
case EQUAL:
|
||||
if (parser_buf[pos++] != '=') {
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, no = after key, found: 0x%x instead", parser_buf[pos-1]);
|
||||
return;
|
||||
}
|
||||
state = value_state;
|
||||
break;
|
||||
|
||||
while (pos < parser_buf_pos) {
|
||||
switch (state) {
|
||||
case KEY:
|
||||
key = parser_buf[pos++];
|
||||
state = EQUAL;
|
||||
switch (key) {
|
||||
case width:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case scale:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case subscale_n:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case subscale_d:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case vertical_align:
|
||||
value_state = UINT;
|
||||
break;
|
||||
case horizontal_align:
|
||||
value_state = UINT;
|
||||
break;
|
||||
default:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, invalid key "
|
||||
"character: 0x%x",
|
||||
key);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case FLAG:
|
||||
switch(key) {
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
|
||||
case EQUAL:
|
||||
if (parser_buf[pos++] != '=') {
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, no = after "
|
||||
"key, found: 0x%x instead",
|
||||
parser_buf[pos - 1]);
|
||||
return;
|
||||
}
|
||||
state = value_state;
|
||||
break;
|
||||
case INT:
|
||||
#define READ_UINT \
|
||||
for (i = pos, lcode=0; i < MIN(parser_buf_pos, pos + 10); i++) { \
|
||||
uint8_t n = parser_buf[i] - '0'; if (n > 9) break; \
|
||||
lcode = lcode * 10 + n; \
|
||||
} \
|
||||
if (i == pos) { REPORT_ERROR("Malformed MultiCellCommand control block, expecting an integer value for key: %c", key & 0xFF); return; } \
|
||||
pos = i; \
|
||||
if (lcode > UINT32_MAX) { REPORT_ERROR("Malformed MultiCellCommand control block, number is too large"); return; } \
|
||||
code = lcode;
|
||||
|
||||
case FLAG:
|
||||
switch (key) {
|
||||
|
||||
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 MultiCellCommand 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 MultiCellCommand 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) {
|
||||
;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
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) {
|
||||
;
|
||||
default: break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
#undef I
|
||||
case UINT:
|
||||
READ_UINT;
|
||||
#define U(x) \
|
||||
case x: \
|
||||
g.x = code; \
|
||||
break
|
||||
switch (key) {
|
||||
U(width);
|
||||
U(scale);
|
||||
U(subscale_n);
|
||||
U(subscale_d);
|
||||
U(vertical_align);
|
||||
U(horizontal_align);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
case UINT:
|
||||
READ_UINT;
|
||||
#define U(x) case x: g.x = code; break
|
||||
switch(key) {
|
||||
U(width); U(scale); U(subscale_n); U(subscale_d); U(vertical_align); U(horizontal_align);
|
||||
default: break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
break;
|
||||
#undef U
|
||||
#undef READ_UINT
|
||||
|
||||
case AFTER_VALUE:
|
||||
switch (parser_buf[pos++]) {
|
||||
default:
|
||||
REPORT_ERROR("Malformed MultiCellCommand 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 AFTER_VALUE:
|
||||
switch (parser_buf[pos++]) {
|
||||
default:
|
||||
REPORT_ERROR("Malformed MultiCellCommand 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;
|
||||
|
||||
case PAYLOAD: {
|
||||
sz = parser_buf_pos - pos;
|
||||
payload_start = pos;
|
||||
g.payload_sz = sz;
|
||||
pos = parser_buf_pos;
|
||||
} break;
|
||||
|
||||
|
||||
} // end switch
|
||||
} // end while
|
||||
} // end switch
|
||||
} // end while
|
||||
|
||||
switch (state) {
|
||||
case EQUAL:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, no = after key");
|
||||
return;
|
||||
case INT:
|
||||
case UINT:
|
||||
REPORT_ERROR(
|
||||
"Malformed MultiCellCommand control block, expecting an integer value");
|
||||
return;
|
||||
case FLAG:
|
||||
REPORT_ERROR(
|
||||
"Malformed MultiCellCommand control block, expecting a flag value");
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(state) {
|
||||
case EQUAL:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, no = after key"); return;
|
||||
case INT:
|
||||
case UINT:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, expecting an integer value"); return;
|
||||
case FLAG:
|
||||
REPORT_ERROR("Malformed MultiCellCommand control block, expecting a flag value"); return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
REPORT_VA_COMMAND(
|
||||
"K s { sI sI sI sI sI sI ss#}", self->window_id, "multicell_command",
|
||||
REPORT_VA_COMMAND("K s { sI sI sI sI sI sI ss#}", self->window_id, "multicell_command",
|
||||
|
||||
"width", (unsigned int)g.width, "scale", (unsigned int)g.scale,
|
||||
"subscale_n", (unsigned int)g.subscale_n, "subscale_d",
|
||||
(unsigned int)g.subscale_d, "vertical_align",
|
||||
(unsigned int)g.vertical_align, "horizontal_align",
|
||||
(unsigned int)g.horizontal_align,
|
||||
"width", (unsigned int)g.width, "scale", (unsigned int)g.scale, "subscale_n", (unsigned int)g.subscale_n, "subscale_d", (unsigned int)g.subscale_d, "vertical_align", (unsigned int)g.vertical_align, "horizontal_align", (unsigned int)g.horizontal_align,
|
||||
|
||||
"", (char *)parser_buf + payload_start, g.payload_sz);
|
||||
"", (char*)parser_buf + payload_start, g.payload_sz
|
||||
);
|
||||
|
||||
screen_handle_multicell_command(self->screen, &g, parser_buf + payload_start);
|
||||
screen_handle_multicell_command(self->screen, &g, parser_buf + payload_start);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -179,24 +179,6 @@ _report_params_with_first(PyObject *dump_callback, id_type window_id, const char
|
|||
// }}}
|
||||
|
||||
// Utils {{{
|
||||
static const int64_t digit_multipliers[] = {
|
||||
10000000000000000l,
|
||||
1000000000000000l,
|
||||
100000000000000l,
|
||||
10000000000000l,
|
||||
1000000000000l,
|
||||
100000000000l,
|
||||
10000000000l,
|
||||
1000000000l,
|
||||
100000000l,
|
||||
10000000l,
|
||||
1000000l,
|
||||
100000l,
|
||||
10000l,
|
||||
1000l,
|
||||
100l,
|
||||
1l};
|
||||
|
||||
// }}}
|
||||
|
||||
// Data structures {{{
|
||||
|
|
@ -548,18 +530,14 @@ dispatch_osc(PS *self, uint8_t *buf, size_t limit, bool is_extended_osc) {
|
|||
break; \
|
||||
}
|
||||
|
||||
int64_t accumulator = 0;
|
||||
int code = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < MIN(limit, 5u); i++) {
|
||||
int64_t num = buf[i] - '0';
|
||||
if (num < 0 || num > 9) break;
|
||||
accumulator += num * digit_multipliers[i];
|
||||
}
|
||||
if (i > 0) {
|
||||
code = accumulator / digit_multipliers[i - 1];
|
||||
if (i < limit && buf[i] == ';') i++;
|
||||
uint8_t num = buf[i] - '0';
|
||||
if (num > 9) break;
|
||||
code = code * 10 + num;
|
||||
}
|
||||
if (i < limit && buf[i] == ';') i++;
|
||||
|
||||
switch (code) {
|
||||
case 0:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue