void write_var(std::fstream &stream, T variable)
{
    static_assert(std::is_signed<T>::value == false, "Value must be unsigned");

    constexpr const BYTE ZERO_BITTED = std::numeric_limits<BYTE>::max() / 2;
    constexpr const BYTE ONE_BITTED = ZERO_BITTED + 1;

    loop:
    {
        if ((variable & ~ZERO_BITTED) == 0)
        {
            stream.put(static_cast<BYTE>(variable));
            return;
        }
        else
        {
            stream.put(static_cast<BYTE>((variable & ZERO_BITTED) | ONE_BITTED));
            variable >>= 7;
        }
    }
    goto loop;
}
예제 #2
0
uint64_t erase (const size_t offset, std::fstream &lib)
{
	// ar header format:
	// offset, length, description
	// 0	16	File name, ASCII
	// 16	12	File modification timestamp, Decimal
	// 28	6	Owner ID, Decimal
	// 34	6	Group ID, Decimal
	// 40	8	File mode, Octal
	// 48	10	File size in bytes, Decimal
	// 58	2	File magic, 0x60 0x0A

	// we will use this a lot. this are right-padded.
	const char zero = 0x30;
	const char pad = 0x20;

	// first of all, archive creation timestamp goes to zero
	lib.seekp (static_cast<int64_t> (offset + 16));
	lib.put (zero);
	for (size_t i = 0; i < 11; ++i)
		lib.put (pad);

	// now the uid:
	lib.seekp (static_cast<int64_t> (offset + 28));
	lib.put (zero);
	for (size_t i = 0; i < 5; ++i)
		lib.put (pad);
	// and gid
	lib.seekp (static_cast<int64_t> (offset + 34));
	lib.put (zero);
	for (size_t i = 0; i < 5; ++i)
		lib.put (pad);

	// return the size:
	lib.seekg (static_cast<int64_t> (offset + 48));
	char size[10];
	lib.read (size, 10);
	for (ssize_t i = 9; i >= 0; --i) {
		if (size[i] == pad)
			size[i] = '\0';
	}
	uint64_t ret = static_cast<uint64_t> (std::atol (size));
	if (ret % 2 != 0)
		++ret;	// everything is aligned to uint16_t, but file size is the
				// actual file size.
	ret += 60; // add header size
	return ret;
}