Я пишу машину Ragel для довольно простого бинарного протокола, и то, что я представляю здесь, является еще более упрощенной версией без какого-либо восстановления ошибок, просто чтобы продемонстрировать проблему. m пытается решить.Ragel: избегать избыточного вызова функции «when»
Таким образом, сообщение будет проанализировано здесь выглядит следующим образом:
<1 byte: length> <$length bytes: user data> <1 byte: checksum>
машина выглядит следующим образом:
%%{
machine my_machine;
write data;
alphtype unsigned char;
}%%
%%{
action message_reset {
/* TODO */
data_received = 0;
}
action got_len {
len = fc;
}
action got_data_byte {
/* TODO */
}
action message_received {
/* TODO */
}
action is_waiting_for_data {
(data_received++ < len);
}
action is_checksum_correct {
1/*TODO*/
}
len = (any);
fmt_separate_len = (0x80 any);
data = (any);
checksum = (any);
message =
(
# first byte: length of the data
(len @got_len)
# user data
(data when is_waiting_for_data @got_data_byte)*
# place higher priority on the previous machine (i.e. data)
<:
# last byte: checksum
(checksum when is_checksum_correct @message_received)
) >to(message_reset)
;
main := (msg_start: message)*;
# Initialize and execute.
write init;
write exec;
}%%
Как вы видите, первый мы получаем 1 байты, представляющие длину; то мы получаем data
байт, пока не получим необходимое количество байтов (проверка выполняется is_waiting_for_data
), и когда мы получаем следующий (дополнительный) байт, мы проверяем, является ли он правильной контрольной суммой (на is_checksum_correct
). Если это так, машина ждет следующего сообщения; в противном случае эта конкретная машина останавливается (я не включил здесь никаких исправлений ошибок, чтобы упростить диаграмму).
Диаграмма это выглядит следующим образом:
$ ragel -Vp ./msg.rl | dot -Tpng -o msg.png
Как вы видите, в состоянии 1, в то время как мы приема пользовательских данных, условия следующие:
0..255(is_waiting_for_data, !is_checksum_correct),
0..255(is_waiting_for_data, is_checksum_correct)
Таким образом, на каждом байте данных он избыточно называет is_checksum_correct
, хотя результат не имеет значения.
условие должно быть просто: 0..255(is_waiting_for_data)
Как добиться этого?