3

我正在研究解析terminfo数据库文件,这是一种二进制文件。您可以自行阅读其存储格式并确认我面临的问题。

手册说——

标题部分开始文件。本节包含六个短整数,格式如下所述。这些整数是

(1) 幻数(八进制 0432);

...

...

短整数存储在两个 8 位字节中。第一个字节包含值的最低有效 8 位,第二个字节包含最高有效 8 位。(因此,表示的值为256*second+first。)值-1由0377、0377这两个字节表示;其他负值是非法的。该值通常表示该终端缺少相应的能力。这与硬件不对应的机器必须将整数读取为两个字节并计算 little-endian 值


  • 解析这种类型的输入时的第一个问题是将大小固定为 8 位,因此不能使用普通的 old char,因为它不能保证大小正好是 8 位。所以我在寻找'固定宽度整数类型',但再次面临选择黑白int8_tuint8_t明确指出的困境 - “仅在实现直接支持该类型时提供”。那么我应该选择什么才能使类型足够便携。

  • 第二个问题是buffer.readInt16LE()C++ 标准库中没有可以读取 Little Endian 格式的 16 字节数据的方法。那么我应该如何继续以便携和安全的方式再次实现此功能。

我已经尝试使用char数据类型读取它,但它肯定会在我的机器上产生垃圾。可以通过infocmp命令读取正确的输入,例如 - $ infocmp xterm


#include <fstream>
#include <iostream>
#include <vector>

int main()
{
    std::ifstream db(
      "/usr/share/terminfo/g/gnome", std::ios::binary | std::ios::ate);

    std::vector<unsigned char> buffer;

    if (db) {
        auto size = db.tellg();
        buffer.resize(size);
        db.seekg(0, std::ios::beg);
        db.read(reinterpret_cast<char*>(&buffer.front()), size);
    }
    std::cout << "\n";
}

$1 = std::vector of length 3069, capacity 3069 = {26 '\032', 1 '\001', 21 '\025',
  0 '\000', 38 '&', 0 '\000', 16 '\020', 0 '\000', 157 '\235', 1 '\001',
  193 '\301', 4 '\004', 103 'g', 110 'n', 111 'o', 109 'm', 101 'e', 124 '|',
  71 'G', 78 'N', 79 'O', 77 'M', 69 'E', 32 ' ', 84 'T', 101 'e', 114 'r',
  109 'm', 105 'i', 110 'n', 97 'a', 108 'l', 0 '\000', 0 '\000', 1 '\001',
  0 '\000', 0 '\000', 1 '\001', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 1 '\001', 1 '\001', 0 '\000',
....
....
4

1 回答 1

2

解析这种类型的输入时的第一个问题是将大小固定为 8 位,因此不能使用普通的 old char,因为它不能保证大小正好是 8 位。

任何至少 8 位的整数都可以。虽然char不能保证正好是 8 位,但它至少需要 8 位,因此就大小而言,除了在某些情况下您可能需要屏蔽高位(如果存在)之外没有问题。但是,char可能不是无符号的,并且您不希望八位字节被解释为有符号值,因此请unsigned char改用。

第二个问题是 c++ 标准库中没有 buffer.readInt16LE() 方法可以读取 Little Endian 格式的 16 字节数据。那么我应该如何继续以便携和安全的方式再次实现此功能。

一次将一个八位字节读入unsigned char. 将第一个八位组分配给变量(大到足以表示至少 16 位)。将第二个八位组的位左移 8 位,并使用复合按位或分配给变量。

或者更好的是,不要重新实现它,而是使用第三方现有的库。

我已经尝试使用 char 数据类型读取它,但它肯定会在我的机器上产生垃圾。

然后你的尝试是错误的。没有问题char会导致垃圾输出。我建议使用调试器来解决这个问题。

于 2016-12-24T23:46:44.577 回答