2

调查 ragel 并且无法弄清楚如何合理地从文件中读取。据我了解,它需要一个不会在令牌中间损坏的内存缓冲区。这显然需要大量的工作来实现,特别是如果我不知道标记的大小,例如带有换行符、转义符等的字符串。如果我正在实现所有这些,我不确定我是否需要愤怒了。

没有更好的办法吗?

4

2 回答 2

1

如果您将文件映射到内存(mmap、CreateFileMapping),您将拥有整个文件作为一个连续的内存块。

另请查看 Ragel 用户指南(5.9 维护输入数据的指针),其中包含一些用于处理这种情况的示例代码。对于可能超过固定缓冲区大小的字符串或标记,您可以使用根据需要增长的可变大小的缓冲区。

于 2017-12-06T19:36:09.370 回答
1

正确处理它非常棘手,并且取决于您正在执行的解析类型。

对于文件,您可以将整个文件映射到内存中并进行处理。

这是最好的选择。

如果您以块的形式读取数据,您仍然可以解析它,但您需要在解析调用中跟踪您的状态变量。我通常通过将它们放在一个类中并拥有一个可以增量解析数据缓冲区的方法 parse 来做到这一点。

如果要从数据中提取标记,则需要在返回之前将标记捕获到字符串中。当您恢复解析时,当您完成匹配令牌时,您将其与先前匹配的部分连接起来,这就是完整的令牌。在最坏的情况下,您的令牌缓冲区可能与原始文件一样大。

你可以在这里看到一些例子:

  1. 如果解析器标记了令牌的开始,但尚未完成,则会将其存储:https://github.com/kurocha/async-http/blob/eff77f61f7a85a3ac21f7a8f51ba07f069063cbe/source/Async/HTTP/V1/RequestParser。 rl#L52-L54
  2. 解析器状态在解析调用中被保留:https ://github.com/kurocha/async-http/blob/eff77f61f7a85a3ac21f7a8f51ba07f069063cbe/source/Async/HTTP/V1/Parser.hpp#L57-L73
  3. 读取数据和调用的循环parsehttps ://github.com/kurocha/async-http/blob/eff77f61f7a85a3ac21f7a8f51ba07f069063cbe/source/Async/HTTP/V1/Protocol.cpp#L36-L54
于 2018-01-09T08:33:16.353 回答