簡體   English   中英

針對已知長度的任何數據優化Ragel語義條件

[英]Optimize Ragel semantic conditions for any data of known length

Ragel手冊 6.5語義條件中有一個示例,該示例演示了如何使用when子句為可變大小的結構編寫語法。

action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
data_fields = (
’d’
[0-9]+ %rec_num
’:’
( [a-z] when test_len )*
)**;

它適用於小型結構,但是對於較大的結構,它會減慢速度,因為解析器會嘗試評估每個字符的條件。

我想要做的是跳過掃描,僅將數據復制到緩沖區中,以獲得這樣的語法(請注意any * ):

action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
data_fields = (
’d’
[0-9]+ %rec_num
’:’
( any* when test_len )*
)**;

因此,我想立即復制長度為n的緩沖區而不進行迭代。 如何在不離開解析器上下文的情況下做到這一點?

您可能需要自己處理問題。 ragel用戶指南提到,您可以在機器中更改fpc / p變量,因此這應該足夠安全。 假設您正在以一個塊處理所有數據(即,數據字段不會分解)

machine foo;

action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
action buffer_data_field {
  /* p is still pointing to ':' at this point. */
  if (p + 1 + n >= pe) { fgoto *foo_error; }
  buffer(p + 1, n);
  p += n;
}
action buffer_data_field_eof {
  /* check for eof while data was expected */
  /* p is pointing past the ':' at this point */
  if (n) { fgoto *foo_error; }
}

data_fields = (
'd'
[0-9]+ %rec_num
':' 
$buffer_data_field
$eof(buffer_data_field_eof)

)**;

如果將數據分塊,則可以將緩沖分開:

buffer_data :=
    any+
    $eof{ fnext *foo_error; }
    ${
        size_t avail = pe - p;
        if (avail >= n) {
            buffer(p, n);
            p += n - 1;
            fnext data_fields;
        } else {
            buffer_partial(p, avail);
            n -= avail;
            p += avail - 1;
        }
    }
    ;


data_fields = (
    'd'
    [0-9]+ %rec_num
    ':'  ${ if (n) fnext buffer_data; }
    )**;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM