从 Ada 中的 Stream 读取数据时,如何调整记录组件的大小/匹配?

Jos*_*osh 3 embedded ada stream

非常具体的问题,但我们这里有一些优秀的 Ada 人,所以我想听听想法。我正在从用于嵌入式系统的文件中读取数据。我使用的数据块总是有一个可预测的报头格式……但有一个问题……数据有效载荷长度在有效载荷发生之前作为格式的一部分给出。所以我不知道有效载荷大小,直到我在标头中的已知位置读取某个字节。块一个接一个地出现。

字面上的格式是([ ] 用于可读性)

[ 2byte TAG ] [ 1byte 有效载荷长度 (LSB) ] [ 1byte 有效载荷长度 (MSB) ] [ PAYLOAD ]

负载是人类可读的配置文本。下一个 TAG 将是前一个有效载荷之后的下两个字节,依此类推,直到我在最后一个有效载荷之后看不到任何匹配的已知 TAG。然后我知道我已经完成了。

我正在使用 direct_IO 流从文件中读取它,但我可能会切换到更通用的流并开始执行转换。

我想在一天结束时将所有这些存储在一个简单的记录中我正在寻找一种技术,我可以在其中读取数据并读取第 3 个字节我现在知道有效负载大小并且可以调整数组的大小或当记录已经作为读取缓冲区时,字符串组件在那个时刻保存数据。那就是我需要读取 TAG 和长度数据,所以我想立即将它们存储在记录中。如果可以,我想将有效负载存储在同一条记录中。我可以考虑使用访问类型并动态创建有效负载存储,但这意味着我必须在 3 个字节后停止读取,执行工作,然后继续。另外,这意味着写入将有同样的问题,因为对象的表示不再与期望的块格式匹配。

我正在考虑尝试使用记录来保存所有这些,并带有有效载荷大小的判别式,并在该记录上使用表示子句来模拟上述格式。由于判别式是记录和数据块中的第三个字节,我可能能够进行对话并简单地将数据“放置”到对象中……但是当我实例化时,我没有办法调整组件的大小记录而无需读取 TAG 和长度。我假设我不能同时读取和创建对象,所以要创建对象我需要一个长度。虽然我可以继续摆弄文件位置并阅读我需要的内容,然后回到开头,然后创建并使用整个块,但我知道必须有更好的“Ada”方式。

有没有办法可以使用表示子句将标头填充到记录中,并且当判别式填充数据中的值时,将设置记录数组或字符串有效负载组件大小?

此外,这不仅仅是为了阅读,我需要找到一种在配置更改时将这种确切格式输出到文件中的好方法。所以我希望使用一个表示子句来匹配底层格式,这样我就可以从字面上将对象“写”到文件中,这将是正确的格式。我希望对阅读也做同样的事情。

到目前为止,我看到的所有 Ada 读取示例都是具有已知长度(或已知最大长度)的记录,其中记录在静态大小的数据块中读取。

有人有一个例子或者可以指出我如何使用这种方法来处理这种可变大小的有效载荷的正确方向吗?

感谢您的任何帮助,您可以提供,

-乔希

Mar*_*c C 5

本质上,这样做的方法是进行部分读取,足以获取字节数,然后将其余数据读取到可区分的记录中。

类似于以下伪 Ada 中的内容:

type Payloads is array (Payload_Sizes range <>) of Your_One_Byte_Payload_Type;

type Data (Payload_Length : Payload_Sizes) is
   record
      Tag : Tag_Type;
      Payload : Payloads(1 .. Payload_Length);
   end record;

for Data use record
   Tag            at 0 range 0 .. 15;
   Payload_Length at 2 range 0 .. 15;
   -- Omit a rep spec for Payload
end record;
Run Code Online (Sandbox Code Playgroud)

通常,编译器会在最后一个代表指定的字段之后立即定位 Payload 数据,但您需要与供应商确认这一点,或者执行一些测试程序。(可能有更明确的方式来指定这一点,如果有人提供了可行的方法,我愿意更新此答案。)

而且也没有提供对Payload_Length判别一个默认情况下,将导致记录的情况下,总是保留所需要的最大价值的最大存储量。

然后,在您的数据读取代码中,类似以下内容:

loop
   Get(Data_File, Tag);
   Get(Data_File, Payload_Length)

   declare
      Data_Item : Data(Payload_Length);
   begin
      Data_Item.Tag := Tag;
      Get(Data_File, Data_Item.Payload);
      Process_Data(Data_Item);
   end;
   ...
   exit when Whatever;
end loop;
Run Code Online (Sandbox Code Playgroud)

(您需要制定退出标准。)

Data_Item 然后将根据 Payload_Length 动态调整大小。但是请注意,如果该长度是奇数,则可能会出现填充......