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; }
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; }