Я занимаюсь анализом terminfo файлов базы данных, которые являются типом двоичных файлов. Вы можете прочитать о своем storage format своими силами и подтвердить проблему, с которой я сталкиваюсь.read little endian 16-разрядное целое без знака
Руководство говорит -
Секция заголовка начинается файл. Этот раздел содержит шесть коротких целых чисел в формате, описанном ниже. Эти целые числа:
(1) магическое число (октал 0432);
...
...
Короткие целые числа хранятся в двух 8-битовых байтов. Первый байт содержит наименее значимые 8 бит значения, , а второй байт содержит наиболее важные 8 бит. (Таким образом, представленное значение составляет 256 * второй + первый.) Значение -1 представлено двумя байтами 0377, 0377; другие отрицательные значения являются незаконными. Это значение обычно означает , что соответствующая возможность отсутствует на этом терминале . Машины, в которых это не соответствует аппарату , должны считывать целые числа в виде двух байтов и вычислять значение little-endian.
Первая проблема при анализе этого типа ввода является то, что он фиксирует размер 8 бит, так что обычный старый символ не может использоваться, поскольку он не гарантирует размер, чтобы быть точно 8 бит. Таким образом, я смотрел «Fixed width integer types», но снова столкнулся с выбором из b/w
int8_t
илиuint8_t
, который четко указывает - «предоставляется, только если реализация напрямую поддерживает тип». Итак, что я должен выбрать, чтобы тип был достаточно переносимым.Вторая проблема заключается в отсутствии метода
buffer.readInt16LE()
в стандартной библиотеке C++, которая может читать 16 байтов данных в формате Little Endian. Итак, как я должен продолжить реализацию этой функции снова в переносном & безопасном пути.
Я уже пробовал читать его с 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',
....
....
Опубликовать код какой-либо другой. попробуйте прочитать несколько байтов в буфер и взглянуть на него с помощью вашего отладчика. –
'char' гарантированно будет наименьшим адресуемым устройством в любой системе (поэтому' sizeof (char) 'указано всегда как' 1'). Таким образом, для системы с 8-битными байтами 'char' гарантированно будет 8 бит. И поскольку это практически * все * системы, созданные за последние 30 лет или около того, нет необходимости беспокоиться. Если вам нужно перенести свою программу на какую-то старую систему (или более старую) в 1970-е годы, тогда вам может понадобиться беспокоиться об этом, но не иначе. –
Вы должны использовать 'uint8_t' или' unsigned char'. Тип 'char' может быть' unsigned', 'signed' или' char' * в зависимости от настройки компилятора *. –