diff --git a/CMakeLists.txt b/CMakeLists.txt index 20dc15a..7ae3f0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,6 @@ endif() # Helper scrips include(CheckSymbolExists) -include(TestBigEndian) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # For custom cmake modules include(BuildType) @@ -216,8 +215,6 @@ check_symbol_exists(bswap_16 "byteswap.h" INNOEXTRACT_HAVE_BSWAP_16) check_symbol_exists(bswap_32 "byteswap.h" INNOEXTRACT_HAVE_BSWAP_32) check_symbol_exists(bswap_64 "byteswap.h" INNOEXTRACT_HAVE_BSWAP_64) -test_big_endian(INNOEXTRACT_IS_BIG_ENDIAN) - # All sources: diff --git a/src/cli/main.cpp b/src/cli/main.cpp index 666632e..7894279 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -210,9 +210,16 @@ static void process_file(const fs::path & file, const options & o) { } #endif + setup::info::entry_types entries = setup::info::DataEntries | setup::info::Files; +#ifdef DEBUG + if(logger::debug) { + entries = setup::info::entry_types::all(); + } +#endif + ifs.seekg(offsets.header_offset); setup::info info; - info.load(ifs); + info.load(ifs, entries); if(!o.quiet) { const std::string & name = info.header.app_versioned_name.empty() @@ -368,7 +375,7 @@ static void process_file(const fs::path & file, const options & o) { } if(file.offset > offset) { debug("discarding " << print_bytes(file.offset - offset)); - discard(*chunk_source, file.offset - offset); + util::discard(*chunk_source, file.offset - offset); } offset = file.offset + file.size; diff --git a/src/configure.hpp.in b/src/configure.hpp.in index bb8e9dc..4cb6853 100644 --- a/src/configure.hpp.in +++ b/src/configure.hpp.in @@ -21,7 +21,6 @@ #cmakedefine01 INNOEXTRACT_HAVE_UTIMES // Endianness -#cmakedefine01 INNOEXTRACT_IS_BIG_ENDIAN #cmakedefine01 INNOEXTRACT_HAVE_BSWAP_16 #cmakedefine01 INNOEXTRACT_HAVE_BSWAP_32 #cmakedefine01 INNOEXTRACT_HAVE_BSWAP_64 diff --git a/src/crypto/checksum.hpp b/src/crypto/checksum.hpp index cb56959..bf56627 100644 --- a/src/crypto/checksum.hpp +++ b/src/crypto/checksum.hpp @@ -57,7 +57,7 @@ struct checksum { }; template -class checksum_base : public static_polymorphic { +class checksum_base : public util::static_polymorphic { public: @@ -66,13 +66,11 @@ public: * Data is processed as-is and then converted according to Endianness. */ template - T load_number(std::istream & is) { - T result; - char buf[sizeof(result)]; - is.read(buf, std::streamsize(sizeof(buf))); - this->impl().update(buf, sizeof(buf)); - std::memcpy(&result, buf, sizeof(result)); - return little_endian::byteswap_if_alien(result); + T load(std::istream & is) { + char buffer[sizeof(T)]; + is.read(buffer, std::streamsize(sizeof(buffer))); + this->impl().update(buffer, sizeof(buffer)); + return Endianness::template load(buffer); } /*! @@ -80,8 +78,8 @@ public: * Data is processed as-is and then converted if the host endianness is not little_endian. */ template - T load_number(std::istream & is) { - return load_number(is); + T load(std::istream & is) { + return load(is); } }; diff --git a/src/crypto/crc32.cpp b/src/crypto/crc32.cpp index bb4cbb1..a2804d4 100644 --- a/src/crypto/crc32.cpp +++ b/src/crypto/crc32.cpp @@ -27,19 +27,8 @@ namespace crypto { -#if INNOEXTRACT_ENDIANNESS == LITTLE_ENDIAN -#define CRC32_INDEX(c) (c & 0xff) -#define CRC32_SHIFTED(c) (c >> 8) -#elif INNOEXTRACT_ENDIANNESS == BIG_ENDIAN -#define CRC32_INDEX(c) (c >> 24) -#define CRC32_SHIFTED(c) (c << 8) -#else -#error "Unsupported host endianness." -#endif - /* Table of CRC-32's of all single byte values (made by makecrc.c) */ -const boost::uint32_t crc32::table[] = { -#if INNOEXTRACT_ENDIANNESS == LITTLE_ENDIAN +static const boost::uint32_t crc32_table[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, @@ -92,84 +81,35 @@ const boost::uint32_t crc32::table[] = { 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL -#else - 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, - 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, - 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, - 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, - 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, - 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, - 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, - 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, - 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, - 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, - 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, - 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, - 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, - 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, - 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, - 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, - 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, - 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, - 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, - 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, - 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, - 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, - 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, - 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, - 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, - 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, - 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, - 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, - 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, - 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, - 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, - 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, - 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, - 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, - 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, - 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, - 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, - 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, - 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, - 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, - 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, - 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, - 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, - 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, - 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, - 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, - 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, - 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, - 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, - 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, - 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, - 0x8def022dL -#endif }; +static boost::uint8_t crc32_index(boost::uint32_t crc) { + return boost::uint8_t(crc & 0xff); +} + +static boost::uint32_t crc32_shifted(boost::uint32_t crc) { + return crc >> 8; +} + void crc32::update(const char * s, size_t n) { for(; (size_t(s) % 4 != 0) && n > 0; n--) { - crc = table[CRC32_INDEX(crc) ^ boost::uint8_t(*s++)] ^ CRC32_SHIFTED(crc); + crc = crc32_table[crc32_index(crc) ^ boost::uint8_t(*s++)] ^ crc32_shifted(crc); } while(n >= 4) { - crc ^= *reinterpret_cast(s); - crc = table[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); - crc = table[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); - crc = table[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); - crc = table[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc); + crc ^= util::little_endian::load(s); + crc = crc32_table[crc32_index(crc)] ^ crc32_shifted(crc); + crc = crc32_table[crc32_index(crc)] ^ crc32_shifted(crc); + crc = crc32_table[crc32_index(crc)] ^ crc32_shifted(crc); + crc = crc32_table[crc32_index(crc)] ^ crc32_shifted(crc); n -= 4; s += 4; } while(n--) { - crc = table[CRC32_INDEX(crc) ^ boost::uint8_t(*s++)] ^ CRC32_SHIFTED(crc); + crc = crc32_table[crc32_index(crc) ^ boost::uint8_t(*s++)] ^ crc32_shifted(crc); } } -#undef CRC32_INDEX -#undef CRC32_SHIFTED - } // namespace crypto diff --git a/src/crypto/crc32.hpp b/src/crypto/crc32.hpp index 2ea59b3..408f12b 100644 --- a/src/crypto/crc32.hpp +++ b/src/crypto/crc32.hpp @@ -40,7 +40,6 @@ private: static const boost::uint32_t CRC32_NEGL = 0xffffffffl; - static const boost::uint32_t table[256]; boost::uint32_t crc; }; diff --git a/src/crypto/iteratedhash.hpp b/src/crypto/iteratedhash.hpp index e55f7d2..92ff87d 100644 --- a/src/crypto/iteratedhash.hpp +++ b/src/crypto/iteratedhash.hpp @@ -43,7 +43,7 @@ public: typedef typename transform::hash_word hash_word; typedef typename transform::byte_order byte_order; static const size_t block_size = transform::block_size; - static const size_t hash_size = transform::hash_size; + static const size_t hash_size = transform::hash_size / sizeof(hash_word); void init() { count_lo = count_hi = 0; transform::init(state); } @@ -53,16 +53,16 @@ public: private: - size_t hash(const hash_word * input, size_t length); - void pad(size_t last_block_size, boost::uint8_t pad_first = 0x80); + size_t hash(const char * input, size_t length); + void pad(size_t last_block_size, char pad_first = '\x80'); hash_word bit_count_hi() const { return (count_lo >> (8 * sizeof(hash_word) - 3)) + (count_hi << 3); } hash_word bit_count_lo() const { return count_lo << 3; } - hash_word data[block_size / sizeof(hash_word)]; - hash_word state[hash_size / sizeof(hash_word)]; + char data[block_size]; + hash_word state[hash_size]; hash_word count_lo, count_hi; @@ -77,102 +77,97 @@ void iterated_hash::update(const char * input, size_t len) { count_hi++; // carry from low to high } - count_hi += hash_word(safe_right_shift<8 * sizeof(hash_word)>(len)); + count_hi += hash_word(util::safe_right_shift<8 * sizeof(hash_word)>(len)); - size_t num = mod_power_of_2(old_count_lo, size_t(block_size)); - boost::uint8_t * d = reinterpret_cast(data); + size_t num = util::mod_power_of_2(old_count_lo, size_t(block_size)); if(num != 0) { // process left over data if(num + len >= block_size) { - std::memcpy(d + num, input, block_size-num); + std::memcpy(data + num, input, block_size-num); hash(data, block_size); input += (block_size - num); len -= (block_size - num); // drop through and do the rest } else { - std::memcpy(d + num, input, len); + std::memcpy(data + num, input, len); return; } } // now process the input data in blocks of BlockSize bytes and save the leftovers to m_data if(len >= block_size) { - - if(is_aligned(input)) { - size_t leftOver = hash(reinterpret_cast(input), len); - input += (len - leftOver); - len = leftOver; - - } else { - do { // copy input first if it's not aligned correctly - std::memcpy(d, input, block_size); - hash(data, block_size); - input += block_size; - len -= block_size; - } while(len >= block_size); - } + size_t leftOver = hash(input, len); + input += (len - leftOver); + len = leftOver; } - + if(len) { - memcpy(d, input, len); + memcpy(data, input, len); } } template -size_t iterated_hash::hash(const hash_word * input, size_t length) { +size_t iterated_hash::hash(const char * input, size_t length) { - do { + if(byte_order::native() && util::is_aligned(input)) { - if(byte_order::native) { - transform::transform(state, input); - } else { - byteswap(data, input, block_size); - transform::transform(state, data); - } + do { + + transform::transform(state, reinterpret_cast(input)); + + input += block_size; + length -= block_size; + + } while(length >= block_size); - input += block_size / sizeof(hash_word); - length -= block_size; + } else { + + do { + + hash_word buffer[block_size / sizeof(hash_word)]; + byte_order::load(input, buffer, ARRAY_SIZE(buffer)); + + transform::transform(state, buffer); + + input += block_size; + length -= block_size; + + } while(length >= block_size); - } while(length >= block_size); + } return length; } template -void iterated_hash::pad(size_t last_block_size, boost::uint8_t pad_first) { - - size_t num = mod_power_of_2(count_lo, size_t(block_size)); +void iterated_hash::pad(size_t last_block_size, char pad_first) { - boost::uint8_t * d = reinterpret_cast(data); + size_t num = util::mod_power_of_2(count_lo, size_t(block_size)); - d[num++] = pad_first; + data[num++] = pad_first; if(num <= last_block_size) { - memset(d + num, 0, last_block_size - num); + memset(data + num, 0, last_block_size - num); } else { - memset(d + num, 0, block_size - num); + memset(data + num, 0, block_size - num); hash(data, block_size); - memset(d, 0, last_block_size); + memset(data, 0, last_block_size); } } template void iterated_hash::finalize(char * digest) { - size_t order = byte_order::offset; + size_t order = transform::offset * sizeof(hash_word); - pad(block_size - 2 * sizeof(hash_word)); - data[block_size / sizeof(hash_word) - 2 + order] = byte_order::byteswap_if_alien(bit_count_lo()); - data[block_size / sizeof(hash_word) - 1 - order] = byte_order::byteswap_if_alien(bit_count_hi()); + size_t size = block_size - 2 * sizeof(hash_word); + pad(size); + byte_order::store(bit_count_lo(), data + size + order); + byte_order::store(bit_count_hi(), data + size + sizeof(hash_word) - order); hash(data, block_size); - if(is_aligned(digest) && hash_size % sizeof(hash_word) == 0) { - byte_order::byteswap_if_alien(state, reinterpret_cast(digest), hash_size); - } else { - byte_order::byteswap_if_alien(state, state, hash_size); - memcpy(digest, state, hash_size); - } + byte_order::store(state, hash_size, digest); } diff --git a/src/crypto/md5.cpp b/src/crypto/md5.cpp index 62c3f8f..1d3d148 100644 --- a/src/crypto/md5.cpp +++ b/src/crypto/md5.cpp @@ -43,7 +43,7 @@ void md5_transform::transform(hash_word * digest, const hash_word * in) { #define F4(x, y, z) (y ^ (x | ~z)) #define MD5STEP(f, w, x, y, z, data, s) \ - w = rotl_fixed(w + f(x, y, z) + data, s) + x + w = util::rotl_fixed(w + f(x, y, z) + data, s) + x hash_word a, b, c, d; diff --git a/src/crypto/md5.hpp b/src/crypto/md5.hpp index dcd7a6f..fdd8c7b 100644 --- a/src/crypto/md5.hpp +++ b/src/crypto/md5.hpp @@ -33,7 +33,8 @@ class md5_transform { public: typedef boost::uint32_t hash_word; - typedef little_endian byte_order; + typedef util::little_endian byte_order; + static const size_t offset = 0; static const size_t block_size = 64; static const size_t hash_size = 16; diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 274421f..36ca8b6 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -38,8 +38,8 @@ void sha1_transform::init(hash_word * state) { void sha1_transform::transform(hash_word * state, const hash_word * data) { #define blk0(i) (W[i] = data[i]) -#define blk1(i) (W[i & 15] = rotl_fixed(W[(i + 13) & 15] ^ W[(i + 8) & 15] \ - ^ W[(i + 2) & 15] ^ W[i & 15], 1)) +#define blk1(i) (W[i & 15] = util::rotl_fixed(W[(i + 13) & 15] ^ W[(i + 8) & 15] \ + ^ W[(i + 2) & 15] ^ W[i & 15], 1)) #define f1(x, y, z) (z ^ (x & (y ^ z))) #define f2(x, y, z) (x ^ y ^ z) @@ -47,16 +47,21 @@ void sha1_transform::transform(hash_word * state, const hash_word * data) { #define f4(x, y, z) (x ^ y ^ z) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v, w, x, y, z, i) z += f1(w, x, y) + blk0(i) + 0x5A827999 + rotl_fixed(v, 5); \ - w = rotl_fixed(w, 30); -#define R1(v, w, x, y, z, i) z += f1(w, x, y) + blk1(i) + 0x5A827999 + rotl_fixed(v, 5); \ - w = rotl_fixed(w, 30); -#define R2(v, w, x, y, z, i) z += f2(w, x, y) + blk1(i) + 0x6ED9EBA1 + rotl_fixed(v, 5); \ - w = rotl_fixed(w, 30); -#define R3(v, w, x, y, z, i) z += f3(w, x, y) + blk1(i) + 0x8F1BBCDC + rotl_fixed(v, 5); \ - w = rotl_fixed(w, 30); -#define R4(v, w, x, y, z, i) z += f4(w, x, y) + blk1(i) + 0xCA62C1D6 + rotl_fixed(v, 5); \ - w = rotl_fixed(w, 30); +#define R0(v, w, x, y, z, i) \ + z += f1(w, x, y) + blk0(i) + 0x5A827999 + util::rotl_fixed(v, 5); \ + w = util::rotl_fixed(w, 30); +#define R1(v, w, x, y, z, i) \ + z += f1(w, x, y) + blk1(i) + 0x5A827999 + util::rotl_fixed(v, 5); \ + w = util::rotl_fixed(w, 30); +#define R2(v, w, x, y, z, i) \ + z += f2(w, x, y) + blk1(i) + 0x6ED9EBA1 + util::rotl_fixed(v, 5); \ + w = util::rotl_fixed(w, 30); +#define R3(v, w, x, y, z, i) \ + z += f3(w, x, y) + blk1(i) + 0x8F1BBCDC + util::rotl_fixed(v, 5); \ + w = util::rotl_fixed(w, 30); +#define R4(v, w, x, y, z, i) \ + z += f4(w, x, y) + blk1(i) + 0xCA62C1D6 + util::rotl_fixed(v, 5); \ + w = util::rotl_fixed(w, 30); hash_word W[16]; diff --git a/src/crypto/sha1.hpp b/src/crypto/sha1.hpp index 34ba7c4..c8687d5 100644 --- a/src/crypto/sha1.hpp +++ b/src/crypto/sha1.hpp @@ -33,7 +33,8 @@ class sha1_transform { public: typedef boost::uint32_t hash_word; - typedef big_endian byte_order; + typedef util::big_endian byte_order; + static const size_t offset = 1; static const size_t block_size = 64; static const size_t hash_size = 20; diff --git a/src/loader/exereader.cpp b/src/loader/exereader.cpp index e260240..81a8a17 100644 --- a/src/loader/exereader.cpp +++ b/src/loader/exereader.cpp @@ -107,10 +107,10 @@ boost::uint32_t exe_reader_impl::find_resource_entry(std::istream & is, boost::u } // Number of named resource entries. - boost::uint16_t nbnames = load_number(is); + boost::uint16_t nbnames = util::load(is); // Number of id resource entries. - boost::uint16_t nbids = load_number(is); + boost::uint16_t nbids = util::load(is); // Ignore named resource entries. @@ -121,8 +121,8 @@ boost::uint32_t exe_reader_impl::find_resource_entry(std::istream & is, boost::u for(size_t i = 0; i < nbids; i++) { - boost::uint32_t id = load_number(is); - boost::uint32_t offset = load_number(is); + boost::uint32_t id = util::load(is); + boost::uint32_t offset = util::load(is); if(is.fail()) { return 0; } @@ -138,7 +138,7 @@ boost::uint32_t exe_reader_impl::find_resource_entry(std::istream & is, boost::u bool exe_reader_impl::load_header(std::istream & is, header & coff) { // Skip the DOS stub. - boost::uint16_t peOffset = load_number(is.seekg(0x3c)); + boost::uint16_t peOffset = util::load(is.seekg(0x3c)); if(is.fail()) { return false; } @@ -152,15 +152,15 @@ bool exe_reader_impl::load_header(std::istream & is, header & coff) { } is.seekg(2, std::ios_base::cur); // machine - coff.nsections = load_number(is); + coff.nsections = util::load(is); is.seekg(4 + 4 + 4, std::ios_base::cur); // creation time + symbol table offset + nbsymbols - boost::uint16_t optional_header_size = load_number(is); + boost::uint16_t optional_header_size = util::load(is); is.seekg(2, std::ios_base::cur); // characteristics coff.section_table_offset = boost::uint32_t(is.tellg()) + optional_header_size; // Skip the optional header. - boost::uint16_t optionalHeaderMagic = load_number(is); + boost::uint16_t optionalHeaderMagic = util::load(is); if(is.fail()) { return false; } @@ -170,7 +170,7 @@ bool exe_reader_impl::load_header(std::istream & is, header & coff) { is.seekg(90, std::ios_base::cur); } - boost::uint32_t ndirectories = load_number(is); + boost::uint32_t ndirectories = util::load(is); if(is.fail() || ndirectories < 3) { return false; } @@ -178,8 +178,8 @@ bool exe_reader_impl::load_header(std::istream & is, header & coff) { is.seekg(2 * directory_header_size, std::ios_base::cur); // Virtual memory address and size of the start of resource directory. - coff.resource_table_address = load_number(is); - boost::uint32_t resource_size = load_number(is); + coff.resource_table_address = util::load(is); + boost::uint32_t resource_size = util::load(is); if(is.fail() || !coff.resource_table_address || !resource_size) { return false; } @@ -198,11 +198,11 @@ bool exe_reader_impl::load_section_list(std::istream & is, const header & coff, is.seekg(8, std::ios_base::cur); // name - section.virtual_size = load_number(is); - section.virtual_address = load_number(is); + section.virtual_size = util::load(is); + section.virtual_address = util::load(is); is.seekg(4, std::ios_base::cur); // raw size - section.raw_address = load_number(is); + section.raw_address = util::load(is); // relocation addr + line number addr + relocation count // + line number count + characteristics @@ -271,8 +271,8 @@ exe_reader_impl::resource exe_reader_impl::find_resource(std::istream & is, // Virtual memory address and size of the resource data. is.seekg(leaf_offset); - boost::uint32_t data_address = load_number(is); - boost::uint32_t data_size = load_number(is); + boost::uint32_t data_address = util::load(is); + boost::uint32_t data_size = util::load(is); // ignore codepage and reserved word if(is.fail()) { return result; diff --git a/src/loader/offsets.cpp b/src/loader/offsets.cpp index c8d6900..b401e22 100644 --- a/src/loader/offsets.cpp +++ b/src/loader/offsets.cpp @@ -66,14 +66,14 @@ bool offsets::load_from_exe_file(std::istream & is) { is.seekg(SetupLoaderHeaderOffset); - boost::uint32_t magic = load_number(is); + boost::uint32_t magic = util::load(is); if(is.fail() || magic != SetupLoaderHeaderMagic) { is.clear(); return false; } - boost::uint32_t offset_table_offset = load_number(is); - boost::uint32_t not_offset_table_offset = load_number(is); + boost::uint32_t offset_table_offset = util::load(is); + boost::uint32_t not_offset_table_offset = util::load(is); if(is.fail() || offset_table_offset != ~not_offset_table_offset) { is.clear(); return false; @@ -124,40 +124,40 @@ bool offsets::load_offsets_at(std::istream & is, boost::uint32_t pos) { checksum.update(magic, ARRAY_SIZE(magic)); if(version >= INNO_VERSION(5, 1, 5)) { - boost::uint32_t revision = checksum.load_number(is); + boost::uint32_t revision = checksum.load(is); if(is.fail() || revision != 1) { is.clear(); return false; } } - (void)checksum.load_number(is); - exe_offset = checksum.load_number(is); + (void)checksum.load(is); + exe_offset = checksum.load(is); if(version >= INNO_VERSION(4, 1, 6)) { exe_compressed_size = 0; } else { - exe_compressed_size = checksum.load_number(is); + exe_compressed_size = checksum.load(is); } - exe_uncompressed_size = checksum.load_number(is); + exe_uncompressed_size = checksum.load(is); if(version >= INNO_VERSION(4, 0, 3)) { exe_checksum.type = crypto::CRC32; - exe_checksum.crc32 = checksum.load_number(is); + exe_checksum.crc32 = checksum.load(is); } else { exe_checksum.type = crypto::Adler32; - exe_checksum.adler32 = checksum.load_number(is); + exe_checksum.adler32 = checksum.load(is); } if(version >= INNO_VERSION(4, 0, 0)) { message_offset = 0; } else { - message_offset = load_number(is); + message_offset = util::load(is); } - header_offset = checksum.load_number(is); - data_offset = checksum.load_number(is); + header_offset = checksum.load(is); + data_offset = checksum.load(is); if(is.fail()) { is.clear(); @@ -165,7 +165,7 @@ bool offsets::load_offsets_at(std::istream & is, boost::uint32_t pos) { } if(version >= INNO_VERSION(4, 0, 10)) { - boost::uint32_t expected = load_number(is); + boost::uint32_t expected = util::load(is); if(is.fail()) { is.clear(); return false; diff --git a/src/setup/component.cpp b/src/setup/component.cpp index de16e3a..18b2b84 100644 --- a/src/setup/component.cpp +++ b/src/setup/component.cpp @@ -55,29 +55,29 @@ STORED_FLAGS_MAP(stored_component_flags_2, void component_entry::load(std::istream & is, const version & version) { - is >> encoded_string(name, version.codepage()); - is >> encoded_string(description, version.codepage()); - is >> encoded_string(types, version.codepage()); + is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(description, version.codepage()); + is >> util::encoded_string(types, version.codepage()); if(version >= INNO_VERSION(4, 0, 1)) { - is >> encoded_string(languages, version.codepage()); + is >> util::encoded_string(languages, version.codepage()); } else { languages.clear(); } if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - is >> encoded_string(check, version.codepage()); + is >> util::encoded_string(check, version.codepage()); } else { check.clear(); } if(version >= INNO_VERSION(4, 0, 0)) { - extra_disk_pace_required = load_number(is); + extra_disk_pace_required = util::load(is); } else { - extra_disk_pace_required = load_number(is); + extra_disk_pace_required = util::load(is); } if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - level = load_number(is); - used = load_bool(is); + level = util::load(is); + used = util::load_bool(is); } else { level = 0, used = true; } @@ -93,9 +93,9 @@ void component_entry::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(4, 0, 0)) { - size = load_number(is); + size = util::load(is); } else { - size = load_number(is); + size = util::load(is); } } diff --git a/src/setup/data.cpp b/src/setup/data.cpp index 086e118..37047ac 100644 --- a/src/setup/data.cpp +++ b/src/setup/data.cpp @@ -31,8 +31,8 @@ namespace setup { void data_entry::load(std::istream & is, const version & version) { - chunk.first_slice = load_number(is, version.bits); - chunk.last_slice = load_number(is, version.bits); + chunk.first_slice = util::load(is, version.bits); + chunk.last_slice = util::load(is, version.bits); if(version < INNO_VERSION(4, 0, 0)) { if(chunk.first_slice < 1 || chunk.last_slice < 1) { log_warning << "[file location] unexpected disk number: " << chunk.first_slice @@ -42,20 +42,20 @@ void data_entry::load(std::istream & is, const version & version) { } } - chunk.offset = load_number(is); + chunk.offset = util::load(is); if(version >= INNO_VERSION(4, 0, 1)) { - file.offset = load_number(is); + file.offset = util::load(is); } else { file.offset = 0; } if(version >= INNO_VERSION(4, 0, 0)) { - file.size = load_number(is); - chunk.size = load_number(is); + file.size = util::load(is); + chunk.size = util::load(is); } else { - file.size = load_number(is); - chunk.size = load_number(is); + file.size = util::load(is); + chunk.size = util::load(is); } if(version >= INNO_VERSION(5, 3, 9)) { @@ -65,10 +65,10 @@ void data_entry::load(std::istream & is, const version & version) { is.read(file.checksum.md5, std::streamsize(sizeof(file.checksum.md5))); file.checksum.type = crypto::MD5; } else if(version >= INNO_VERSION(4, 0, 1)) { - file.checksum.crc32 = load_number(is); + file.checksum.crc32 = util::load(is); file.checksum.type = crypto::CRC32; } else { - file.checksum.adler32 = load_number(is); + file.checksum.adler32 = util::load(is); file.checksum.type = crypto::Adler32; } @@ -76,16 +76,16 @@ void data_entry::load(std::istream & is, const version & version) { // 16-bit installers use the FAT filetime format - boost::uint16_t time = load_number(is); - boost::uint16_t date = load_number(is); + boost::uint16_t time = util::load(is); + boost::uint16_t date = util::load(is); struct tm t; - t.tm_sec = get_bits(time, 0, 4) * 2; // [0, 58] - t.tm_min = get_bits(time, 5, 10); // [0, 59] - t.tm_hour = get_bits(time, 11, 15); // [0, 23] - t.tm_mday = get_bits(date, 0, 4); // [1, 31] - t.tm_mon = get_bits(date, 5, 8) - 1; // [0, 11] - t.tm_year = get_bits(date, 9, 15) + 1980 - 1900; // [80, 199] + t.tm_sec = util::get_bits(time, 0, 4) * 2; // [0, 58] + t.tm_min = util::get_bits(time, 5, 10); // [0, 59] + t.tm_hour = util::get_bits(time, 11, 15); // [0, 23] + t.tm_mday = util::get_bits(date, 0, 4); // [1, 31] + t.tm_mon = util::get_bits(date, 5, 8) - 1; // [0, 11] + t.tm_year = util::get_bits(date, 9, 15) + 1980 - 1900; // [80, 199] timestamp = util::parse_time(t); timestamp_nsec = 0; @@ -94,7 +94,7 @@ void data_entry::load(std::istream & is, const version & version) { // 32-bit installers use the Win32 FILETIME format - boost::int64_t filetime = load_number(is); + boost::int64_t filetime = util::load(is); static const boost::int64_t FiletimeOffset = 0x19DB1DED53E8000ll; if(filetime < FiletimeOffset) { @@ -107,8 +107,8 @@ void data_entry::load(std::istream & is, const version & version) { } - file_version_ms = load_number(is); - file_version_ls = load_number(is); + file_version_ms = util::load(is); + file_version_ls = util::load(is); options = 0; diff --git a/src/setup/delete.cpp b/src/setup/delete.cpp index 675fc19..b3c5aa5 100644 --- a/src/setup/delete.cpp +++ b/src/setup/delete.cpp @@ -39,10 +39,10 @@ STORED_ENUM_MAP(delete_target_type_map, delete_entry::Files, void delete_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the directory entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(name, version.codepage()); + is >> util::encoded_string(name, version.codepage()); load_condition_data(is, version); diff --git a/src/setup/directory.cpp b/src/setup/directory.cpp index 2ece298..ee7b3e2 100644 --- a/src/setup/directory.cpp +++ b/src/setup/directory.cpp @@ -48,21 +48,21 @@ STORED_FLAGS_MAP(stored_inno_directory_options_1, void directory_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the directory entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(name, version.codepage()); + is >> util::encoded_string(name, version.codepage()); load_condition_data(is, version); if(version >= INNO_VERSION(4, 0, 11) && version < INNO_VERSION(4, 1, 0)) { - is >> encoded_string(permissions, version.codepage()); + is >> util::encoded_string(permissions, version.codepage()); } else { permissions.clear(); } if(version >= INNO_VERSION(2, 0, 11)) { - attributes = load_number(is); + attributes = util::load(is); } else { attributes = 0; } @@ -70,7 +70,7 @@ void directory_entry::load(std::istream & is, const version & version) { load_version_data(is, version); if(version >= INNO_VERSION(4, 1, 0)) { - permission = load_number(is); + permission = util::load(is); } else { permission = -1; } diff --git a/src/setup/file.cpp b/src/setup/file.cpp index 19b772e..296a141 100644 --- a/src/setup/file.cpp +++ b/src/setup/file.cpp @@ -77,14 +77,14 @@ void file_entry::load(std::istream & is, const version & version) { options = 0; if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the file entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(source, version.codepage()); - is >> encoded_string(destination, version.codepage()); - is >> encoded_string(install_font_name, version.codepage()); + is >> util::encoded_string(source, version.codepage()); + is >> util::encoded_string(destination, version.codepage()); + is >> util::encoded_string(install_font_name, version.codepage()); if(version >= INNO_VERSION(5, 2, 5)) { - is >> encoded_string(strong_assembly_name, version.codepage()); + is >> util::encoded_string(strong_assembly_name, version.codepage()); } else { strong_assembly_name.clear(); } @@ -93,10 +93,10 @@ void file_entry::load(std::istream & is, const version & version) { load_version_data(is, version); - location = load_number(is, version.bits); - attributes = load_number(is, version.bits); - external_size = (version >= INNO_VERSION(4, 0, 0)) ? load_number(is) - : load_number(is); + location = util::load(is, version.bits); + attributes = util::load(is, version.bits); + external_size = (version >= INNO_VERSION(4, 0, 0)) ? util::load(is) + : util::load(is); if(version < INNO_VERSION(3, 0, 5)) { file_copy_mode copyMode = stored_enum(is).get(); @@ -109,7 +109,7 @@ void file_entry::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(4, 1, 0)) { - permission = load_number(is); + permission = util::load(is); } else { permission = -1; } diff --git a/src/setup/header.cpp b/src/setup/header.cpp index 3d6f546..c0514b8 100644 --- a/src/setup/header.cpp +++ b/src/setup/header.cpp @@ -128,106 +128,106 @@ void header::load(std::istream & is, const version & version) { options = 0; if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the setup header structure + (void)util::load(is); // uncompressed size of the setup header } - is >> encoded_string(app_name, version.codepage()); - is >> encoded_string(app_versioned_name, version.codepage()); + is >> util::encoded_string(app_name, version.codepage()); + is >> util::encoded_string(app_versioned_name, version.codepage()); if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(app_id, version.codepage()); + is >> util::encoded_string(app_id, version.codepage()); } - is >> encoded_string(app_copyright, version.codepage()); + is >> util::encoded_string(app_copyright, version.codepage()); if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(app_publisher, version.codepage()); - is >> encoded_string(app_publisher_url, version.codepage()); + is >> util::encoded_string(app_publisher, version.codepage()); + is >> util::encoded_string(app_publisher_url, version.codepage()); } else { app_publisher.clear(), app_publisher_url.clear(); } if(version >= INNO_VERSION(5, 1, 13)) { - is >> encoded_string(app_support_phone, version.codepage()); + is >> util::encoded_string(app_support_phone, version.codepage()); } else { app_support_phone.clear(); } if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(app_support_url, version.codepage()); - is >> encoded_string(app_updates_url, version.codepage()); - is >> encoded_string(app_version, version.codepage()); + is >> util::encoded_string(app_support_url, version.codepage()); + is >> util::encoded_string(app_updates_url, version.codepage()); + is >> util::encoded_string(app_version, version.codepage()); } else { app_support_url.clear(), app_updates_url.clear(), app_version.clear(); } - is >> encoded_string(default_dir_name, version.codepage()); - is >> encoded_string(default_group_name, version.codepage()); + is >> util::encoded_string(default_dir_name, version.codepage()); + is >> util::encoded_string(default_group_name, version.codepage()); if(version < INNO_VERSION(3, 0, 0)) { - is >> ansi_string(uninstall_icon_name); + is >> util::ansi_string(uninstall_icon_name); } else { uninstall_icon_name.clear(); } - is >> encoded_string(base_filename, version.codepage()); + is >> util::encoded_string(base_filename, version.codepage()); if(version >= INNO_VERSION(1, 3, 21)) { if(version < INNO_VERSION(5, 2, 5)) { - is >> ansi_string(license_text); - is >> ansi_string(info_before); - is >> ansi_string(info_after); + is >> util::ansi_string(license_text); + is >> util::ansi_string(info_before); + is >> util::ansi_string(info_after); } - is >> encoded_string(uninstall_files_dir, version.codepage()); - is >> encoded_string(uninstall_name, version.codepage()); - is >> encoded_string(uninstall_icon, version.codepage()); - is >> encoded_string(app_mutex, version.codepage()); + is >> util::encoded_string(uninstall_files_dir, version.codepage()); + is >> util::encoded_string(uninstall_name, version.codepage()); + is >> util::encoded_string(uninstall_icon, version.codepage()); + is >> util::encoded_string(app_mutex, version.codepage()); } else { license_text.clear(), info_before.clear(), info_after.clear(); uninstall_files_dir.clear(), uninstall_name.clear(); uninstall_icon.clear(), app_mutex.clear(); } if(version >= INNO_VERSION(3, 0, 0)) { - is >> encoded_string(default_user_name, version.codepage()); - is >> encoded_string(default_user_organisation, version.codepage()); + is >> util::encoded_string(default_user_name, version.codepage()); + is >> util::encoded_string(default_user_organisation, version.codepage()); } else { default_user_name.clear(), default_user_organisation.clear(); } if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - is >> encoded_string(default_serial, version.codepage()); + is >> util::encoded_string(default_serial, version.codepage()); if(version < INNO_VERSION(5, 2, 5)) { - is >> binary_string(compiled_code); + is >> util::binary_string(compiled_code); } } else { default_serial.clear(), compiled_code.clear(); } if(version >= INNO_VERSION(4, 2, 4)) { - is >> encoded_string(app_readme_file, version.codepage()); - is >> encoded_string(app_contact, version.codepage()); - is >> encoded_string(app_comments, version.codepage()); - is >> encoded_string(app_modify_path, version.codepage()); + is >> util::encoded_string(app_readme_file, version.codepage()); + is >> util::encoded_string(app_contact, version.codepage()); + is >> util::encoded_string(app_comments, version.codepage()); + is >> util::encoded_string(app_modify_path, version.codepage()); } else { app_readme_file.clear(), app_contact.clear(); app_comments.clear(), app_modify_path.clear(); } if(version >= INNO_VERSION(5, 3, 8)) { - is >> encoded_string(create_uninstall_registry_key, version.codepage()); + is >> util::encoded_string(create_uninstall_registry_key, version.codepage()); } else { create_uninstall_registry_key.clear(); } if(version >= INNO_VERSION(5, 3, 10)) { - is >> encoded_string(uninstallable, version.codepage()); + is >> util::encoded_string(uninstallable, version.codepage()); } else { uninstallable.clear(); } if(version >= INNO_VERSION(5, 5, 0)) { - is >> encoded_string(close_applications_filter, version.codepage()); + is >> util::encoded_string(close_applications_filter, version.codepage()); } else { close_applications_filter.clear(); } if(version >= INNO_VERSION(5, 2, 5)) { - is >> ansi_string(license_text); - is >> ansi_string(info_before); - is >> ansi_string(info_after); + is >> util::ansi_string(license_text); + is >> util::ansi_string(info_before); + is >> util::ansi_string(info_after); } if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { - is >> binary_string(uninstaller_signature); + is >> util::binary_string(uninstaller_signature); } else { uninstaller_signature.clear(); } if(version >= INNO_VERSION(5, 2, 5)) { - is >> binary_string(compiled_code); + is >> util::binary_string(compiled_code); } if(version >= INNO_VERSION(2, 0, 6) && !version.unicode) { @@ -237,7 +237,7 @@ void header::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(4, 0, 0)) { - language_count = load_number(is); + language_count = util::load(is); } else if(version >= INNO_VERSION(2, 0, 1)) { language_count = 1; } else { @@ -245,62 +245,62 @@ void header::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(4, 2, 1)) { - message_count = load_number(is); + message_count = util::load(is); } else { message_count = 0; } if(version >= INNO_VERSION(4, 1, 0)) { - permission_count = load_number(is); + permission_count = util::load(is); } else { permission_count = 0; } if(version >= INNO_VERSION(2, 0, 0)) { - type_count = load_number(is); - component_count = load_number(is); - task_count = load_number(is); + type_count = util::load(is); + component_count = util::load(is); + task_count = util::load(is); } else { type_count = 0, component_count = 0, task_count = 0; } - directory_count = load_number(is, version.bits); - file_count = load_number(is, version.bits); - data_entry_count = load_number(is, version.bits); - icon_count = load_number(is, version.bits); - ini_entry_count = load_number(is, version.bits); - registry_entry_count = load_number(is, version.bits); - delete_entry_count = load_number(is, version.bits); - uninstall_delete_entry_count = load_number(is, version.bits); - run_entry_count = load_number(is, version.bits); - uninstall_run_entry_count = load_number(is, version.bits); + directory_count = util::load(is, version.bits); + file_count = util::load(is, version.bits); + data_entry_count = util::load(is, version.bits); + icon_count = util::load(is, version.bits); + ini_entry_count = util::load(is, version.bits); + registry_entry_count = util::load(is, version.bits); + delete_entry_count = util::load(is, version.bits); + uninstall_delete_entry_count = util::load(is, version.bits); + run_entry_count = util::load(is, version.bits); + uninstall_run_entry_count = util::load(is, version.bits); boost::int32_t license_size = 0; boost::int32_t info_before_size = 0; boost::int32_t info_after_size = 0; if(version < INNO_VERSION(1, 3, 21)) { - license_size = load_number(is, version.bits); - info_before_size = load_number(is, version.bits); - info_after_size = load_number(is, version.bits); + license_size = util::load(is, version.bits); + info_before_size = util::load(is, version.bits); + info_after_size = util::load(is, version.bits); } winver.load(is, version); - back_color = load_number(is); + back_color = util::load(is); if(version >= INNO_VERSION(1, 3, 21)) { - back_color2 = load_number(is); + back_color2 = util::load(is); } else { back_color2 = 0; } - image_back_color = load_number(is); + image_back_color = util::load(is); if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) { - small_image_back_color = load_number(is); + small_image_back_color = util::load(is); } else { small_image_back_color = 0; } if(version < INNO_VERSION(4, 2, 0)) { - password.crc32 = load_number(is); + password.crc32 = util::load(is); password.type = crypto::CRC32; } else if(version < INNO_VERSION(5, 3, 9)) { is.read(password.md5, std::streamsize(sizeof(password.md5))); @@ -316,10 +316,10 @@ void header::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(4, 0, 0)) { - extra_disk_space_required = load_number(is); - slices_per_disk = load_number(is); + extra_disk_space_required = util::load(is); + slices_per_disk = util::load(is); } else { - extra_disk_space_required = load_number(is); + extra_disk_space_required = util::load(is); slices_per_disk = 1; } @@ -386,8 +386,8 @@ void header::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { - signed_uninstaller_original_size = load_number(is); - signed_uninstaller_header_checksum = load_number(is); + signed_uninstaller_original_size = util::load(is); + signed_uninstaller_header_checksum = util::load(is); } else { signed_uninstaller_original_size = signed_uninstaller_header_checksum = 0; } @@ -398,9 +398,9 @@ void header::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(5, 5, 0)) { - uninstall_display_size = load_number(is); + uninstall_display_size = util::load(is); } else if(version >= INNO_VERSION(5, 3, 6)) { - uninstall_display_size = load_number(is); + uninstall_display_size = util::load(is); } else { uninstall_display_size = 0; } @@ -566,19 +566,19 @@ void header::load(std::istream & is, const version & version) { std::string temp; temp.resize(size_t(license_size)); is.read(&temp[0], license_size); - to_utf8(temp, license_text); + util::to_utf8(temp, license_text); } if(info_before_size > 0) { std::string temp; temp.resize(size_t(info_before_size)); is.read(&temp[0], info_before_size); - to_utf8(temp, info_before); + util::to_utf8(temp, info_before); } if(info_after_size > 0) { std::string temp; temp.resize(size_t(info_after_size)); is.read(&temp[0], info_after_size); - to_utf8(temp, info_after); + util::to_utf8(temp, info_after); } } diff --git a/src/setup/icon.cpp b/src/setup/icon.cpp index 5f21fa1..c531ece 100644 --- a/src/setup/icon.cpp +++ b/src/setup/icon.cpp @@ -39,37 +39,37 @@ STORED_ENUM_MAP(stored_close_setting, icon_entry::NoSetting, void icon_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the icon entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(name, version.codepage()); - is >> encoded_string(filename, version.codepage()); - is >> encoded_string(parameters, version.codepage()); - is >> encoded_string(working_dir, version.codepage()); - is >> encoded_string(icon_file, version.codepage()); - is >> encoded_string(comment, version.codepage()); + is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(filename, version.codepage()); + is >> util::encoded_string(parameters, version.codepage()); + is >> util::encoded_string(working_dir, version.codepage()); + is >> util::encoded_string(icon_file, version.codepage()); + is >> util::encoded_string(comment, version.codepage()); load_condition_data(is, version); if(version >= INNO_VERSION(5, 3, 5)) { - is >> encoded_string(app_user_model_id, version.codepage()); + is >> util::encoded_string(app_user_model_id, version.codepage()); } else { app_user_model_id.clear(); } load_version_data(is, version); - icon_index = load_number(is, version.bits); + icon_index = util::load(is, version.bits); if(version >= INNO_VERSION(1, 3, 21)) { - show_command = load_number(is); + show_command = util::load(is); close_on_exit = stored_enum(is).get(); } else { show_command = 1, close_on_exit = NoSetting; } if(version >= INNO_VERSION(2, 0, 7)) { - hotkey = load_number(is); + hotkey = util::load(is); } else { hotkey = 0; } diff --git a/src/setup/info.cpp b/src/setup/info.cpp index 9e96444..186aaf4 100644 --- a/src/setup/info.cpp +++ b/src/setup/info.cpp @@ -48,52 +48,98 @@ namespace setup { namespace { +struct no_arg { }; + +template +static void load_entry(std::istream & is, const setup::version & version, + Entry & entity, Arg arg) { + entity.load(is, version, arg); +} template +static void load_entry(std::istream & is, const setup::version & version, + Entry & entity, no_arg arg) { + (void)arg; + entity.load(is, version); +} + +template static void load_entries(std::istream & is, const setup::version & version, info::entry_types entry_types, size_t count, - std::vector & entries, info::entry_types::enum_type entry_type) { + std::vector & entries, info::entry_types::enum_type entry_type, + Arg arg = Arg()) { + entries.clear(); if(entry_types & entry_type) { entries.resize(count); for(size_t i = 0; i < count; i++) { Entry & entry = entries[i]; - entry.load(is, version); + load_entry(is, version, entry, arg); } } else { for(size_t i = 0; i < count; i++) { Entry entry; - entry.load(is, version); + load_entry(is, version, entry, arg); } } } +template +static void load_entries(std::istream & is, const setup::version & version, + info::entry_types entry_types, size_t count, + std::vector & entries, info::entry_types::enum_type entry_type) { + load_entries(is, version, entry_types, count, entries, entry_type); +} + static void load_wizard_and_decompressor(std::istream & is, const setup::version & version, const setup::header & header, setup::info & info, info::entry_types entries) { (void)entries; - is >> binary_string(info.wizard_image); - - if(version >= INNO_VERSION(2, 0, 0)) { - is >> binary_string(info.wizard_image_small); + if(entries & (info::WizardImages | info::NoSkip)) { + is >> util::binary_string(info.wizard_image); + if(version >= INNO_VERSION(2, 0, 0)) { + is >> util::binary_string(info.wizard_image_small); + } + } else { + info.wizard_image.clear(); + util::binary_string::skip(is); + info.wizard_image_small.clear(); + if(version >= INNO_VERSION(2, 0, 0)) { + util::binary_string::skip(is); + } } + info.decompressor_dll.clear(); if(header.compression == stream::BZip2 || (header.compression == stream::LZMA1 && version == INNO_VERSION(4, 1, 5)) || (header.compression == stream::Zlib && version >= INNO_VERSION(4, 2, 6))) { - - is >> binary_string(info.decompressor_dll); + if(entries & (info::DecompressorDll | info::NoSkip)) { + is >> util::binary_string(info.decompressor_dll); + } else { + // decompressor dll - we don't need this + util::binary_string::skip(is); + } } } } // anonymous namespace +static void check_is_end(stream::block_reader::pointer & is) { + is->exceptions(std::ios_base::goodbit); + char dummy; + if(!is->get(dummy).eof()) { + throw std::ios_base::failure("expected end of stream"); + } +} + void info::load(std::istream & ifs, entry_types e, const setup::version & v) { + if(e & (Messages|NoSkip)) { + e |= Languages; + } + stream::block_reader::pointer is = stream::block_reader::get(ifs, v); - assert(is.get() != NULL); - is->exceptions(std::ios_base::badbit | std::ios_base::failbit); header.load(*is, v); @@ -103,7 +149,7 @@ void info::load(std::istream & ifs, entry_types e, const setup::version & v) { load_wizard_and_decompressor(*is, v, header, *this, e); } - load_entries(*is, v, e, header.message_count, messages, Messages); + load_entries(*is, v, e, header.message_count, messages, Messages, languages); load_entries(*is, v, e, header.permission_count, permissions, Permissions); load_entries(*is, v, e, header.type_count, types, Types); load_entries(*is, v, e, header.component_count, components, Components); @@ -124,42 +170,14 @@ void info::load(std::istream & ifs, entry_types e, const setup::version & v) { load_wizard_and_decompressor(*is, v, header, *this, e); } - is->exceptions(std::ios_base::goodbit); - char dummy; - if(!is->get(dummy).eof()) { - throw std::ios_base::failure("expected end of stream"); - } - + // restart the compression stream + check_is_end(is); is = stream::block_reader::get(ifs, v); - assert(is.get() != NULL); - is->exceptions(std::ios_base::badbit | std::ios_base::failbit); load_entries(*is, v, e, header.data_entry_count, data_entries, DataEntries); is->exceptions(std::ios_base::goodbit); - if(!is->get(dummy).eof()) { - throw std::ios_base::failure("expected end of stream"); - } - - BOOST_FOREACH(setup::message_entry & entry, messages) { - - if(entry.language >= 0 ? size_t(entry.language) >= languages.size() - : entry.language != -1) { - log_warning << "unexpected language index: " << entry.language; - continue; - } - - boost::uint32_t codepage; - if(entry.language < 0) { - codepage = v.codepage(); - } else { - codepage = languages[size_t(entry.language)].codepage; - } - - std::string decoded; - to_utf8(entry.value, decoded, codepage); - entry.value = decoded; - } + check_is_end(is); } void info::load(std::istream & is, entry_types entries) { @@ -171,11 +189,13 @@ void info::load(std::istream & is, entry_types entries) { << color::white << version << color::reset; } + // Some setup versions didn't increment the data version number when they should have. + // To work around this, we try to parse the headers for both data versions. bool ambiguous = version.is_ambiguous(); if(ambiguous) { + // Force parsing all headers so that we don't miss any errors. entries |= NoSkip; } - if(!version.known || ambiguous) { std::ios_base::streampos start = is.tellg(); try { @@ -186,6 +206,7 @@ void info::load(std::istream & is, entry_types entries) { if(!version) { throw; } + is.clear(); is.seekg(start); } } diff --git a/src/setup/info.hpp b/src/setup/info.hpp index 881f1ce..fa97b7e 100644 --- a/src/setup/info.hpp +++ b/src/setup/info.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Central point to load all the different headers in the correct order. + */ #ifndef INNOEXTRACT_SETUP_INFO_HPP #define INNOEXTRACT_SETUP_INFO_HPP @@ -45,6 +48,9 @@ struct run_entry; struct task_entry; struct type_entry; +/*! + * Class used to hold and load the various \ref setup headers. + */ struct info { info(); @@ -76,30 +82,56 @@ struct info { setup::header header; - std::vector components; - std::vector data_entries; - std::vector delete_entries; - std::vector uninstall_delete_entries; - std::vector directories; - std::vector files; - std::vector icons; - std::vector ini_entries; - std::vector languages; - std::vector messages; - std::vector permissions; - std::vector registry_entries; - std::vector run_entries; - std::vector uninstall_run_entries; - std::vector tasks; - std::vector types; + std::vector components; //! \ref Components + std::vector data_entries; //! \ref DataEntries + std::vector delete_entries; //! \ref DeleteEntries + std::vector uninstall_delete_entries; //! \ref UninstallDeleteEntries + std::vector directories; //! \ref Directories + std::vector files; //! \ref Files + std::vector icons; //! \ref Icons + std::vector ini_entries; //! \ref IniEntries + std::vector languages; //! \ref Languages + std::vector messages; //! \ref Messages + std::vector permissions; //! \ref Permissions + std::vector registry_entries; //! \ref RegistryEntries + std::vector run_entries; //! \ref RunEntries + std::vector uninstall_run_entries; //! \ref UninstallRunEntries + std::vector tasks; //! \ref Tasks + std::vector types; //! \ref Types + //! Images displayed in the installer UI. + //! Loading enabled by \ref WizardImages std::string wizard_image; std::string wizard_image_small; + //! Contents of the helper DLL used to decompress setup data in some versions. + //! Loading enabled by \ref DecompressorDll std::string decompressor_dll; - void load(std::istream & is, entry_types entries = setup::info::entry_types::all()); + /*! + * Load setup headers. + * + * \param is The input stream to load the setup headers from. + * It must already be positioned at start of \ref setup::version + * identifier whose position is given by + * \ref loader::offsets::header_offset. + * \param entries What kinds of entries to load. + */ + void load(std::istream & is, entry_types entries); + /*! + * Load setup headers for a specific version. + * + * \param is The input stream to load the setup headers from. + * It must already be positioned at start of the compressed headers. + * The compressed headers start directly after the \ref setup::version + * identifier whose position is given by + * \ref loader::offsets::header_offset. + * \param entries What kinds of entries to load. + * \param version The setup data version of the headers. + * + * This function does not set the \ref version member. + */ void load(std::istream & is, entry_types entries, const setup::version & version); }; diff --git a/src/setup/ini.cpp b/src/setup/ini.cpp index cbcb04b..4ede639 100644 --- a/src/setup/ini.cpp +++ b/src/setup/ini.cpp @@ -43,16 +43,16 @@ STORED_FLAGS_MAP(stored_ini_flags, void ini_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the ini entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(inifile, version.codepage()); + is >> util::encoded_string(inifile, version.codepage()); if(inifile.empty()) { inifile = "{windows}/WIN.INI"; } - is >> encoded_string(section, version.codepage()); - is >> encoded_string(key, version.codepage()); - is >> encoded_string(value, version.codepage()); + is >> util::encoded_string(section, version.codepage()); + is >> util::encoded_string(key, version.codepage()); + is >> util::encoded_string(value, version.codepage()); load_condition_data(is, version); diff --git a/src/setup/item.cpp b/src/setup/item.cpp index 82a783e..c19e93b 100644 --- a/src/setup/item.cpp +++ b/src/setup/item.cpp @@ -28,25 +28,25 @@ namespace setup { void item::load_condition_data(std::istream & is, const version & version) { if(version >= INNO_VERSION(2, 0, 0)) { - is >> encoded_string(components, version.codepage()); - is >> encoded_string(tasks, version.codepage()); + is >> util::encoded_string(components, version.codepage()); + is >> util::encoded_string(tasks, version.codepage()); } else { components.clear(), tasks.clear(); } if(version >= INNO_VERSION(4, 0, 1)) { - is >> encoded_string(languages, version.codepage()); + is >> util::encoded_string(languages, version.codepage()); } else { languages.clear(); } if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - is >> encoded_string(check, version.codepage()); + is >> util::encoded_string(check, version.codepage()); } else { check.clear(); } if(version >= INNO_VERSION(4, 1, 0)) { - is >> encoded_string(after_install, version.codepage()); - is >> encoded_string(before_install, version.codepage()); + is >> util::encoded_string(after_install, version.codepage()); + is >> util::encoded_string(before_install, version.codepage()); } else { after_install.clear(), before_install.clear(); } diff --git a/src/setup/language.cpp b/src/setup/language.cpp index 90d1da2..d87bccb 100644 --- a/src/setup/language.cpp +++ b/src/setup/language.cpp @@ -28,34 +28,34 @@ namespace setup { void language_entry::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(4, 0, 0)) { - is >> encoded_string(name, version.codepage()); + is >> util::encoded_string(name, version.codepage()); } else { name = "default"; } - is >> encoded_string(language_name, (version >= INNO_VERSION(4, 2, 2)) ? 1200u : 1252u); + is >> util::encoded_string(language_name, (version >= INNO_VERSION(4, 2, 2)) ? 1200u : 1252u); - is >> encoded_string(dialog_font, version.codepage()); - is >> encoded_string(title_font, version.codepage()); - is >> encoded_string(welcome_font, version.codepage()); - is >> encoded_string(copyright_font, version.codepage()); + is >> util::encoded_string(dialog_font, version.codepage()); + is >> util::encoded_string(title_font, version.codepage()); + is >> util::encoded_string(welcome_font, version.codepage()); + is >> util::encoded_string(copyright_font, version.codepage()); if(version >= INNO_VERSION(4, 0, 0)) { - is >> binary_string(data); + is >> util::binary_string(data); } if(version >= INNO_VERSION(4, 0, 1)) { - is >> ansi_string(license_text); - is >> ansi_string(info_before); - is >> ansi_string(info_after); + is >> util::ansi_string(license_text); + is >> util::ansi_string(info_before); + is >> util::ansi_string(info_after); } else { license_text.clear(), info_before.clear(), info_after.clear(); } - language_id = load_number(is); + language_id = util::load(is); if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) { - codepage = load_number(is); + codepage = util::load(is); } else { codepage = 0; } @@ -63,20 +63,20 @@ void language_entry::load(std::istream & is, const version & version) { codepage = version.codepage(); } - dialog_font_size = load_number(is); + dialog_font_size = util::load(is); if(version < INNO_VERSION(4, 1, 0)) { - dialog_font_standard_height = load_number(is); + dialog_font_standard_height = util::load(is); } else { dialog_font_standard_height = 0; } - title_font_size = load_number(is); - welcome_font_size = load_number(is); - copyright_font_size = load_number(is); + title_font_size = util::load(is); + welcome_font_size = util::load(is); + copyright_font_size = util::load(is); if(version >= INNO_VERSION(5, 2, 3)) { - right_to_left = load_bool(is); + right_to_left = util::load_bool(is); } else { right_to_left = false; } diff --git a/src/setup/message.cpp b/src/setup/message.cpp index d8978c0..92e9aa0 100644 --- a/src/setup/message.cpp +++ b/src/setup/message.cpp @@ -22,18 +22,31 @@ #include +#include "setup/language.hpp" #include "setup/version.hpp" #include "util/load.hpp" namespace setup { -void message_entry::load(std::istream & is, const version & version) { +void message_entry::load(std::istream & is, const version & version, + const std::vector & languages) { - is >> encoded_string(name, version.codepage()); - is >> binary_string(value); // encoding depends on the codepage in the LanguageEntry + is >> util::encoded_string(name, version.codepage()); + std::string raw_value = util::binary_string::load(is); - language = load_number(is); + language = util::load(is); + boost::uint32_t codepage; + if(language < 0) { + codepage = version.codepage(); + } else if(language < 0 || size_t(language) >= languages.size()) { + value.clear(); + return; + } else { + codepage = languages[size_t(language)].codepage; + } + + util::to_utf8(raw_value, value, codepage); } } // namespace setup diff --git a/src/setup/message.hpp b/src/setup/message.hpp index 1c468ae..d0fcb3e 100644 --- a/src/setup/message.hpp +++ b/src/setup/message.hpp @@ -23,10 +23,12 @@ #include #include +#include namespace setup { struct version; +struct language_entry; struct message_entry { @@ -41,7 +43,8 @@ struct message_entry { // Index into the default language entry list or -1. int language; - void load(std::istream & is, const version & version); + void load(std::istream & is, const version & version, + const std::vector & languages); }; diff --git a/src/setup/permission.cpp b/src/setup/permission.cpp index 131d7ff..02c3f1d 100644 --- a/src/setup/permission.cpp +++ b/src/setup/permission.cpp @@ -29,7 +29,7 @@ void permission_entry::load(std::istream & is, const version & v) { (void)v; - is >> binary_string(permissions); // an array of TGrantPermissionEntry's + is >> util::binary_string(permissions); // an array of TGrantPermissionEntry's } diff --git a/src/setup/registry.cpp b/src/setup/registry.cpp index bc2b434..f5f4e11 100644 --- a/src/setup/registry.cpp +++ b/src/setup/registry.cpp @@ -61,21 +61,21 @@ STORED_ENUM_MAP(stored_registry_entry_type_2, registry_entry::None, void registry_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the directory entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(key, version.codepage()); + is >> util::encoded_string(key, version.codepage()); if(version.bits != 16) { - is >> encoded_string(name, version.codepage()); + is >> util::encoded_string(name, version.codepage()); } else { name.clear(); } - is >> encoded_string(value, version.codepage()); + is >> util::encoded_string(value, version.codepage()); load_condition_data(is, version); if(version >= INNO_VERSION(4, 0, 11) && version < INNO_VERSION(4, 1, 0)) { - is >> encoded_string(permissions, version.codepage()); + is >> util::encoded_string(permissions, version.codepage()); } else { permissions.clear(); } @@ -83,13 +83,13 @@ void registry_entry::load(std::istream & is, const version & version) { load_version_data(is, version); if(version.bits != 16) { - hive = hive_name(load_number(is) & ~0x80000000); + hive = hive_name(util::load(is) & ~0x80000000); } else { hive = Unset; } if(version >= INNO_VERSION(4, 1, 0)) { - permission = load_number(is); + permission = util::load(is); } else { permission = -1; } diff --git a/src/setup/run.cpp b/src/setup/run.cpp index 58464e0..ca7247b 100644 --- a/src/setup/run.cpp +++ b/src/setup/run.cpp @@ -41,29 +41,29 @@ STORED_ENUM_MAP(stored_run_wait_condition, run_entry::WaitUntilTerminated, void run_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the directory entry structure + (void)util::load(is); // uncompressed size of the entry } - is >> encoded_string(name, version.codepage()); - is >> encoded_string(parameters, version.codepage()); - is >> encoded_string(working_dir, version.codepage()); + is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(parameters, version.codepage()); + is >> util::encoded_string(working_dir, version.codepage()); if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(run_once_id, version.codepage()); + is >> util::encoded_string(run_once_id, version.codepage()); } else { run_once_id.clear(); } if(version >= INNO_VERSION(2, 0, 2)) { - is >> encoded_string(status_message, version.codepage()); + is >> util::encoded_string(status_message, version.codepage()); } else { status_message.clear(); } if(version >= INNO_VERSION(5, 1, 13)) { - is >> encoded_string(verb, version.codepage()); + is >> util::encoded_string(verb, version.codepage()); } else { verb.clear(); } if(version >= INNO_VERSION(2, 0, 0)) { - is >> encoded_string(description, version.codepage()); + is >> util::encoded_string(description, version.codepage()); } load_condition_data(is, version); @@ -71,7 +71,7 @@ void run_entry::load(std::istream & is, const version & version) { load_version_data(is, version); if(version >= INNO_VERSION(1, 3, 21)) { - show_command = load_number(is); + show_command = util::load(is); } else { show_command = 0; } diff --git a/src/setup/task.cpp b/src/setup/task.cpp index daf8c8b..ea850c0 100644 --- a/src/setup/task.cpp +++ b/src/setup/task.cpp @@ -30,19 +30,19 @@ namespace setup { void task_entry::load(std::istream & is, const version & version) { - is >> encoded_string(name, version.codepage()); - is >> encoded_string(description, version.codepage()); - is >> encoded_string(group_description, version.codepage()); - is >> encoded_string(components, version.codepage()); + is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(description, version.codepage()); + is >> util::encoded_string(group_description, version.codepage()); + is >> util::encoded_string(components, version.codepage()); if(version >= INNO_VERSION(4, 0, 1)) { - is >> encoded_string(languages, version.codepage()); + is >> util::encoded_string(languages, version.codepage()); } else { languages.clear(); } if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - is >> encoded_string(check, version.codepage()); - level = load_number(is); - used = load_bool(is); + is >> util::encoded_string(check, version.codepage()); + level = util::load(is); + used = util::load_bool(is); } else { check.clear(), level = 0, used = true; } diff --git a/src/setup/type.cpp b/src/setup/type.cpp index fd4eaab..b72dde5 100644 --- a/src/setup/type.cpp +++ b/src/setup/type.cpp @@ -55,15 +55,15 @@ void type_entry::load(std::istream & is, const version & version) { USE_FLAG_NAMES(setup::type_flags) - is >> encoded_string(name, version.codepage()); - is >> encoded_string(description, version.codepage()); + is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(description, version.codepage()); if(version >= INNO_VERSION(4, 0, 1)) { - is >> encoded_string(languages, version.codepage()); + is >> util::encoded_string(languages, version.codepage()); } else { languages.clear(); } if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - is >> encoded_string(check, version.codepage()); + is >> util::encoded_string(check, version.codepage()); } else { check.clear(); } @@ -80,9 +80,9 @@ void type_entry::load(std::istream & is, const version & version) { } if(version >= INNO_VERSION(4, 0, 0)) { - size = load_number(is); + size = util::load(is); } else { - size = load_number(is); + size = util::load(is); } } diff --git a/src/setup/windows.cpp b/src/setup/windows.cpp index 498a9d9..2489bf1 100644 --- a/src/setup/windows.cpp +++ b/src/setup/windows.cpp @@ -35,13 +35,13 @@ const windows_version windows_version::none = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0 void windows_version::data::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(1, 3, 21)) { - build = load_number(is); + build = util::load(is); } else { build = 0; } - minor = load_number(is); - major = load_number(is); + minor = util::load(is); + major = util::load(is); } @@ -51,8 +51,8 @@ void windows_version::load(std::istream & is, const version & version) { nt_version.load(is, version); if(version >= INNO_VERSION(1, 3, 21)) { - nt_service_pack.minor = load_number(is); - nt_service_pack.major = load_number(is); + nt_service_pack.minor = util::load(is); + nt_service_pack.major = util::load(is); } else { nt_service_pack.major = 0, nt_service_pack.minor = 0; } diff --git a/src/stream/block.cpp b/src/stream/block.cpp index e93ccdc..4113e8c 100644 --- a/src/stream/block.cpp +++ b/src/stream/block.cpp @@ -81,8 +81,7 @@ public: template bool read_chunk(Source & src) { - boost::uint32_t block_crc32; - char temp[sizeof(block_crc32)]; + char temp[sizeof(boost::uint32_t)]; std::streamsize temp_size = std::streamsize(sizeof(temp)); std::streamsize nread = boost::iostreams::read(src, temp, temp_size); if(nread == EOF) { @@ -90,8 +89,7 @@ public: } else if(nread != sizeof(temp)) { throw block_error("unexpected block end"); } - std::memcpy(&block_crc32, temp, sizeof(block_crc32)); - block_crc32 = little_endian::byteswap_if_alien(block_crc32); + boost::uint32_t block_crc32 = util::little_endian::load(temp); length = size_t(boost::iostreams::read(src, buffer, std::streamsize(sizeof(buffer)))); if(length == size_t(EOF)) { @@ -156,7 +154,7 @@ block_reader::pointer block_reader::get(std::istream & base, const setup::versio USE_ENUM_NAMES(block_compression) - boost::uint32_t expected_checksum = load_number(base); + boost::uint32_t expected_checksum = util::load(base); crypto::crc32 actual_checksum; actual_checksum.init(); @@ -165,15 +163,15 @@ block_reader::pointer block_reader::get(std::istream & base, const setup::versio if(version >= INNO_VERSION(4, 0, 9)) { - stored_size = actual_checksum.load_number(base); - boost::uint8_t compressed = actual_checksum.load_number(base); + stored_size = actual_checksum.load(base); + boost::uint8_t compressed = actual_checksum.load(base); compression = compressed ? (version >= INNO_VERSION(4, 1, 6) ? LZMA1 : Zlib) : Stored; } else { - boost::uint32_t compressed_size = actual_checksum.load_number(base); - boost::uint32_t uncompressed_size = actual_checksum.load_number(base); + boost::uint32_t compressed_size = actual_checksum.load(base); + boost::uint32_t uncompressed_size = actual_checksum.load(base); if(compressed_size == boost::uint32_t(-1)) { stored_size = uncompressed_size, compression = Stored; @@ -182,7 +180,7 @@ block_reader::pointer block_reader::get(std::istream & base, const setup::versio } // Add the size of a CRC32 checksum for each 4KiB subblock. - stored_size += boost::uint32_t(ceildiv(stored_size, 4096) * 4); + stored_size += boost::uint32_t(util::ceildiv(stored_size, 4096) * 4); } if(actual_checksum.finalize() != expected_checksum) { @@ -208,6 +206,8 @@ block_reader::pointer block_reader::get(std::istream & base, const setup::versio fis->push(io::restrict(base, 0, stored_size)); + fis->exceptions(std::ios_base::badbit | std::ios_base::failbit); + return pointer(fis.release()); } diff --git a/src/stream/block.hpp b/src/stream/block.hpp index 19f1775..bd7167d 100644 --- a/src/stream/block.hpp +++ b/src/stream/block.hpp @@ -46,7 +46,7 @@ struct block_error : public std::ios_base::failure { /*! * Wrapper to read compressed and checksumed block of data used to store setup headers. * - * The decompressed headers are parsed in \ref setup::info. + * The decompressed headers are parsed in \ref setup::info, which also uses this class. */ class block_reader { diff --git a/src/stream/lzma.cpp b/src/stream/lzma.cpp index 6ca00a5..3d0657d 100644 --- a/src/stream/lzma.cpp +++ b/src/stream/lzma.cpp @@ -26,6 +26,9 @@ #include +#include "util/endian.hpp" +#include "util/load.hpp" + namespace stream { static lzma_stream * init_raw_lzma_stream(lzma_vli filter, lzma_options_lzma & options) { @@ -108,10 +111,7 @@ bool inno_lzma1_decompressor_impl::filter(const char * & begin_in, const char * options.lp = (properties % (9 * 5)) / 9; options.lc = properties % 9; - options.dict_size = 0; - for(size_t i = 0; i < 4; i++) { - options.dict_size += boost::uint32_t(boost::uint8_t(header[i + 1])) << (i * 8); - } + options.dict_size = util::little_endian::load(header + 1); stream = init_raw_lzma_stream(LZMA_FILTER_LZMA1, options); } diff --git a/src/stream/slice.cpp b/src/stream/slice.cpp index 798d42d..f3ab10e 100644 --- a/src/stream/slice.cpp +++ b/src/stream/slice.cpp @@ -110,7 +110,7 @@ bool slice_reader::open_file(const path_type & file) { throw slice_error("bad slice magic number"); } - slice_size = load_number(ifs); + slice_size = util::load(ifs); if(ifs.fail()) { ifs.close(); throw slice_error("error reading slice size"); diff --git a/src/util/boostfs_compat.hpp b/src/util/boostfs_compat.hpp index 7014397..0c85a54 100644 --- a/src/util/boostfs_compat.hpp +++ b/src/util/boostfs_compat.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Compatibility functions for older \ref boost::filesystem versions. + */ #ifndef INNOEXTRACT_UTIL_BOOSTFS_COMPAT_HPP #define INNOEXTRACT_UTIL_BOOSTFS_COMPAT_HPP diff --git a/src/util/console.hpp b/src/util/console.hpp index 90f698b..4c666b3 100644 --- a/src/util/console.hpp +++ b/src/util/console.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Terminal output functions: colors, progress bar. + */ #ifndef INNOEXTRACT_UTIL_CONSOLE_HPP #define INNOEXTRACT_UTIL_CONSOLE_HPP @@ -31,7 +34,12 @@ namespace color { - +/*! + * Object that can be written to the console to change the output color. + * + * On some operating systems these will only work if streamed directly into std::cout + * ot std::cerr. + */ struct shell_command { #if defined(_WIN32) boost::uint16_t command; @@ -42,6 +50,7 @@ struct shell_command { std::ostream & operator<<(std::ostream & os, const shell_command command); +//! Reset the output color to the original value. extern shell_command reset; extern shell_command black; @@ -62,6 +71,7 @@ extern shell_command dim_magenta; extern shell_command dim_cyan; extern shell_command dim_white; +//! The last set output color. extern shell_command current; #if !defined(_WIN32) @@ -77,10 +87,17 @@ enum is_enabled { automatic }; +/*! + * Initilize console output functions. + * + * \param color Enable or disable color output. + * \param progress Enable or disable progress bar output. + */ void init(is_enabled color = automatic, is_enabled progress = automatic); } // namespace color +//! A text-based progress bar for terminals. class progress { boost::uint64_t max; @@ -97,20 +114,47 @@ class progress { public: + /*! + * \param max Maximumum progress values. + * If this value is \c 0, the progress bar will be unbounded. + * \param show_rate Display the rate at which the progress changes. + */ progress(boost::uint64_t max = 0, bool show_rate = true); progress(const progress & o) : max(o.max), value(o.value), show_rate(o.show_rate), start_time(o.start_time), last_status(o.last_status), last_time(o.last_time), last_rate(o.last_rate), label(o.label.str()) { } + /*! + * Update the progress bar. + * + * \param delta Value to add to the progress. When the total progress value reaches the + * maximum set in the constructor, the bar will be full. + * \param force Force updating the progress bar. Normally, the progress bar. Otherwise, + * updates are rate-limited and small deltas are not displayed immediately. + */ void update(boost::uint64_t delta = 0, bool force = false); + /*! + * Draw a bounded progress bar (with a maximum). + * + * \param value The progress value, between \c 0.f and \c 1.f. + * \param label A label to draw next to the progress bar. + */ static void show(float value, const std::string & label = std::string()); + /*! + * Draw an unbounded progress bar (without a maximum). + * + * \param value The progress value, between \c 0.f and \c 1.f. + * \param label A label to draw next to the progress bar. + */ static void show_unbounded(float value, const std::string & label = std::string()); + //! Clear any progress bar to make way for other output. static int clear(); + //! Enable or disable the progress bar. static void set_enabled(bool enable); }; diff --git a/src/util/endian.hpp b/src/util/endian.hpp index 9e97c77..326f450 100644 --- a/src/util/endian.hpp +++ b/src/util/endian.hpp @@ -18,10 +18,14 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Utility function for dealing with different endiannesses. + */ #ifndef INNOEXTRACT_UTIL_ENDIAN_HPP #define INNOEXTRACT_UTIL_ENDIAN_HPP #include +#include #include "configure.hpp" @@ -31,6 +35,10 @@ #include +namespace util { + +namespace detail { + inline boost::uint8_t byteswap(boost::uint8_t value) { return value; } @@ -93,74 +101,182 @@ inline boost::int64_t byteswap(boost::int64_t value) { return boost::int64_t(byteswap(boost::uint64_t(value))); } -template -void byteswap(T * out, const T * in, size_t byte_count) { - for(size_t i = 0; i < byte_count / sizeof(T); i++) { - out[i] = byteswap(in[i]); - } -} +} // namespace detail -template +//! Load/store functions for a specific endianness. +template struct endianness { - static const size_t native = false; + /*! + * Load a single integer. + * + * \param buffer Memory location containing the integer. Will read sizeof(T) bytes. + * \return the loaded integer. + */ + template + static T load(const char * buffer) { + if(Endianness::native()) { + T value; + std::memcpy(&value, buffer, sizeof(value)); + return value; + } else { + return load_alien(buffer); + } + } - template - static T byteswap_if_alien(T value) { return byteswap(value); } + /*! + * Load an array of integers. + * + * \param buffer Memory location containing the integers (without padding). + * Will read sizeof(T) * count bytes. + * \param values Output array for the loaded integers. + * \param count How many integers to load. + */ + template + static void load(const char * buffer, T * values, size_t count) { + if(Endianness::native() || sizeof(*values) == 8) { + std::memcpy(values, buffer, sizeof(*values) * count); + } else { + for(size_t i = 0; i < count; i++, buffer += sizeof(*values)) { + values[i] = load_alien(buffer); + } + } + } - template - static void byteswap_if_alien(const T * in, T * out, size_t byte_count) { - byteswap(out, in, byte_count); + /*! + * Store a single integer. + * + * \param value The integer to store. + * \param buffer Memory location to receive the integer. Will write sizeof(T) bytes. + */ + template + static void store(T value, char * buffer) { + if(Endianness::native()) { + std::memcpy(buffer, &value, sizeof(value)); + } else { + return store_alien(value, buffer); + } } -}; - -template <> -struct endianness { + /*! + * Store an array of integers. + * + * \param value The integers to store. + * \param count How many integers to store. + * \param buffer Memory location to receive the integers (without padding). + * Will write sizeof(T) * count bytes. + */ + template + static void store(T * values, size_t count, char * buffer) { + if(Endianness::native() || sizeof(*values) == 8) { + std::memcpy(buffer, values, sizeof(*values) * count); + } else { + for(size_t i = 0; i < count; i++, buffer += sizeof(*values)) { + store_alien(values[i], buffer); + } + } + } + +private: - static const size_t native = true; + bool reversed() { return false; } - template - static T byteswap_if_alien(T value) { return value; } + template + static T load_alien(const char * buffer) { + if(Endianness::reversed()) { + T value; + std::memcpy(&value, buffer, sizeof(value)); + return detail::byteswap(value); + } else { + return Endianness::template decode(buffer); + } + } - template - static void byteswap_if_alien(const T * in, T * out, size_t byte_count) { - if(in != out) { - std::memcpy(out, in, byte_count); + template + static void store_alien(T value, char * buffer) { + if(Endianness::reversed()) { + value = detail::byteswap(value); + std::memcpy(buffer, &value, sizeof(value)); + } else { + Endianness::template encode(value, buffer); } } }; -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif +namespace detail { -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif +inline bool is_little_endian() { + boost::uint32_t signature = 0x04030201; + return (*reinterpret_cast(&signature) == 1); +} -#if INNOEXTRACT_IS_BIG_ENDIAN -#define INNOEXTRACT_ENDIANNESS BIG_ENDIAN -#else -#define INNOEXTRACT_ENDIANNESS LITTLE_ENDIAN -#endif +inline bool is_big_endian() { + boost::uint32_t signature = 0x04030201; + return (*reinterpret_cast(&signature) == 4); +} +} // namespace detail -struct little_endian : public endianness { - static const size_t offset = 0; + +//! Load and store little-endian integers. +struct little_endian : endianness { + + //! \return true if we are running on a little-endian machine. + static bool native() { return detail::is_little_endian(); } + +private: + + static bool reversed() { return detail::is_big_endian(); } + + template + static T decode(const char * buffer) { + T value = 0; + for(size_t i = 0; i < sizeof(T); i++) { + value |= T(T(buffer[i]) << (i * 8)); + } + return value; + } + + template + static void encode(T value, char * buffer) { + for(size_t i = 0; i < sizeof(T); i++) { + buffer[i] = char((value >> (i * 8)) & 0xff); + } + } + + friend class endianness; }; -struct big_endian : public endianness { - static const size_t offset = 1; +//! Load and store big-endian integers. +struct big_endian : endianness { + + //! \return true if we are running on a big-endian machine. + static bool native() { return detail::is_big_endian(); } + +private: + + static bool reversed() { return detail::is_little_endian(); } + + template + static T decode(const char * buffer) { + T value = 0; + for(size_t i = 0; i < sizeof(T); i++) { + value |= T(T(buffer[i]) << ((sizeof(T) - i - 1) * 8)); + } + return value; + } + + template + static void encode(T value, char * buffer) { + for(size_t i = 0; i < sizeof(T); i++) { + buffer[i] = char((value >> ((sizeof(T) - i - 1) * 8)) & 0xff); + } + } + + friend class endianness; }; -#if INNOEXTRACT_ENDIANNESS == LITTLE_ENDIAN -typedef little_endian native_endian; -#elif INNOEXTRACT_ENDIANNESS == BIG_ENDIAN -typedef big_endian native_endian; -#else -#error "Unsupported host endianness." -#endif +} // namespace util #endif // INNOEXTRACT_UTIL_ENDIAN_HPP diff --git a/src/util/flags.hpp b/src/util/flags.hpp index 5a39be3..8ab902b 100644 --- a/src/util/flags.hpp +++ b/src/util/flags.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Typesafe flags. + */ #ifndef INNOEXTRACT_UTIL_FLAGS_HPP #define INNOEXTRACT_UTIL_FLAGS_HPP @@ -66,10 +69,12 @@ public: return flags(_flags, true); } + //! Test if a specific flag is set. bool has(enum_type flag) const { return _flags.test(size_t(flag)); } + //! Test if a collection of flags are all set. bool hasAll(flags o) const { return (_flags & o._flags) == o._flags; } @@ -142,6 +147,7 @@ public: return *this; } + //! Get a set of flags with all possible values set. static flags all() { return flags(Type().flip()); } diff --git a/src/util/load.cpp b/src/util/load.cpp index 3d42f8a..12555be 100644 --- a/src/util/load.cpp +++ b/src/util/load.cpp @@ -33,6 +33,8 @@ #include "util/log.hpp" +namespace util { + namespace { static const boost::uint32_t cp_utf8 = 65001; @@ -183,7 +185,7 @@ static void to_utf8_fallback(const std::string & from, std::string & to, void binary_string::load(std::istream & is, std::string & target) { - boost::int32_t length = load_number(is); + boost::uint32_t length = util::load(is); if(is.fail()) { return; } @@ -192,19 +194,25 @@ void binary_string::load(std::istream & is, std::string & target) { while(length) { char buffer[10 * 1024]; - boost::int32_t buf_size = std::min(length, boost::int32_t(sizeof(buffer))); - is.read(buffer, buf_size); - target.append(buffer, size_t(buf_size)); + boost::uint32_t buf_size = std::min(length, boost::uint32_t(sizeof(buffer))); + is.read(buffer, std::streamsize(buf_size)); + target.append(buffer, buf_size); length -= buf_size; } } -void encoded_string::load(std::istream & is, std::string & target, boost::uint32_t codepage) { +void binary_string::skip(std::istream& is) { - std::string temp; - binary_string::load(is, temp); + boost::uint32_t length = util::load(is); + if(is.fail()) { + return; + } - to_utf8(temp, target, codepage); + discard(is, length); +} + +void encoded_string::load(std::istream & is, std::string & target, boost::uint32_t codepage) { + to_utf8(binary_string::load(is), target, codepage); } void to_utf8(const std::string & from, std::string & to, boost::uint32_t codepage) { @@ -287,3 +295,5 @@ void to_utf8(const std::string & from, std::string & to, boost::uint32_t codepag to.resize(outbase); } + +} // namespace util diff --git a/src/util/load.hpp b/src/util/load.hpp index 87bf913..6483565 100644 --- a/src/util/load.hpp +++ b/src/util/load.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Utility function to load stored data while properly handling encodings and endianness. + */ #ifndef INNOEXTRACT_UTIL_LOAD_HPP #define INNOEXTRACT_UTIL_LOAD_HPP @@ -31,87 +34,139 @@ #include "util/types.hpp" #include "util/util.hpp" +namespace util { + +/*! + * Convert a string to UTF-8 from a specified encoding. + * \param from The input string to convert. + * \param to The output for the converted string. + * \param codepage The Windows codepage number for the input string encoding. + */ +void to_utf8(const std::string & from, std::string & to, boost::uint32_t codepage = 1252); + +/*! + * Wrapper to load a length-prefixed string from an input stream into a std::string. + * The string length is stored as 32-bit integer. + * + * Usage: is >> binary_string(str) + * + * Use \ref encoded_string to also convert the string to UTF-8. + */ struct binary_string { std::string & data; + /*! + * \param target The std::string object to receive the loaded string. + */ explicit binary_string(std::string & target) : data(target) { } + //! Load a length-prefixed string static void load(std::istream & is, std::string & target); + static void skip(std::istream & is); + + //! Load a length-prefixed string + static std::string load(std::istream & is) { + std::string target; + load(is, target); + return target; + } + }; - inline std::istream & operator>>(std::istream & is, const binary_string & str) { binary_string::load(is, str.data); return is; } -void to_utf8(const std::string & from, std::string & to, boost::uint32_t codepage = 1252); - +/*! + * Wrapper to load a length-prefixed string with a specified encoding from an input stream + * into a UTF-8 encoded std::string. + * The string length is stored as 32-bit integer. + * + * Usage: is >> encoded_string(str, codepage) + * + * You can also use the \ref ansi_string convenience wrapper for Windows-1252 strings. + */ struct encoded_string { std::string & data; boost::uint32_t codepage; - encoded_string(std::string & target, boost::uint32_t _codepage) - : data(target), codepage(_codepage) { } + /*! + * \param target The std::string object to receive the loaded UTF-8 string. + * \param codepage The Windows codepage for the encoding of the stored string. + */ + encoded_string(std::string & target, boost::uint32_t codepage) + : data(target), codepage(codepage) { } + //! Load and convert a length-prefixed string static void load(std::istream & is, std::string & target, boost::uint32_t codepage); + //! Load and convert a length-prefixed string + static std::string load(std::istream & is, boost::uint32_t codepage) { + std::string target; + load(is, target, codepage); + return target; + } + }; - inline std::istream & operator>>(std::istream & is, const encoded_string & str) { encoded_string::load(is, str.data, str.codepage); return is; } +//! Convenience specialization of \ref encoded_string for loading Windows-1252 strings struct ansi_string : encoded_string { explicit ansi_string(std::string & target) : encoded_string(target, 1252) { } }; -template +//! Load a value of type T that is stored with a specific endianness. +template T load(std::istream & is) { - T value; - char buffer[sizeof(value)]; + char buffer[sizeof(T)]; is.read(buffer, std::streamsize(sizeof(buffer))); - std::memcpy(&value, buffer, sizeof(value)); - return value; + return Endianness::template load(buffer); } +//! Load a value of type T that is stored as little endian. +template +T load(std::istream & is) { return load(is); } +//! Load a bool value inline bool load_bool(std::istream & is) { - return (load(is) != 0); -} - -template -T load_number(std::istream & is) { - return Endianness::byteswap_if_alien(load(is)); -} - -template -T load_number(std::istream & is) { - return load_number(is); + return !!load(is); } +/*! + * Load a value of type T that is stored with a specific endianness. + * \param bits The number of bits used to store the number. + */ template -T load_number(std::istream & is, size_t bits) { +T load(std::istream & is, size_t bits) { if(bits == 8) { - return load_number::type, Endianness>(is); + return load::type, Endianness>(is); } else if(bits == 16) { - return load_number::type, Endianness>(is); + return load::type, Endianness>(is); } else if(bits == 32) { - return load_number::type, Endianness>(is); + return load::type, Endianness>(is); } else { - return load_number::type, Endianness>(is); + return load::type, Endianness>(is); } } - +/*! + * Load a value of type T that is stored as little endian. + * \param bits The number of bits used to store the number. + */ template -T load_number(std::istream & is, size_t bits) { - return load_number(is, bits); -} +T load(std::istream & is, size_t bits) { return load(is, bits); } +/*! + * Discard a number of bytes from a non-seekable input stream or stream-like object + * \param is The stream to "seek" + * \param bytes Number of bytes to skip ahead + */ template void discard(T & is, boost::uint64_t bytes) { char buf[1024]; @@ -122,13 +177,22 @@ void discard(T & is, boost::uint64_t bytes) { } } +/*! + * Get the number represented by a specific range of bits of another number. + * All other bis are masked and the requested bits are shifted to position 0. + * \param number The number containing the desired bits. + * \param first Index of the first desired bit. + * \param last Index of the last desired bit (inclusive). + */ template T get_bits(T number, int first, int last) { - typedef typename detail::uint_t::exact UT; + typedef typename uint_t::exact UT; UT data = UT(number); data = UT(data >> first), last -= first; UT mask = UT(((last + 1 == sizeof(T) * 8) ? UT(0) : UT(UT(1) << (last + 1))) - 1); return T(data & mask); } +} // namespace util + #endif // INNOEXTRACT_UTIL_LOAD_HPP diff --git a/src/util/log.hpp b/src/util/log.hpp index 1366b16..0db02e4 100644 --- a/src/util/log.hpp +++ b/src/util/log.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Logging functions. + */ #ifndef INNOEXTRACT_UTIL_LOG_HPP #define INNOEXTRACT_UTIL_LOG_HPP @@ -60,12 +63,18 @@ private: public: - static size_t total_warnings; - static size_t total_errors; + static size_t total_warnings; //! Total number of \ref log_warning uses so far. + static size_t total_errors; //! Total number of \ref log_error uses so far. - static bool debug; - static bool quiet; + static bool debug; //! Is \ref debug output enabled? + static bool quiet; //! Is \ref log_info disabled? + /*! + * Construct a log line output stream. + * + * You probably don't want to use this directly - use \ref debug, \ref log_info, + * \ref log_warning and \ref log_error instead. + */ explicit logger(log_level _level) : level(_level) { } template diff --git a/src/util/output.hpp b/src/util/output.hpp index e8cf1f6..b91500f 100644 --- a/src/util/output.hpp +++ b/src/util/output.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Output utility functions. + */ #ifndef INNOEXTRACT_UTIL_OUTPUT_HPP #define INNOEXTRACT_UTIL_OUTPUT_HPP diff --git a/src/util/storedenum.hpp b/src/util/storedenum.hpp index d442e08..de8cc86 100644 --- a/src/util/storedenum.hpp +++ b/src/util/storedenum.hpp @@ -71,7 +71,7 @@ public: explicit stored_enum(std::istream & is) { BOOST_STATIC_ASSERT(size <= (1 << 8)); - value = load_number(is); + value = util::load(is); } enum_type get() { @@ -107,11 +107,11 @@ public: explicit stored_bitfield(std::istream & is) { for(size_t i = 0; i < count; i++) { - bits[i] = load_number(is); + bits[i] = util::load(is); } if(count == 3 && PadBits == 32) { // 3-byte sets are padded to 4 bytes - (void)load_number(is); + (void)util::load(is); } } @@ -139,7 +139,7 @@ public: std::bitset result(0); for(size_t i = 0; i < count; i++) { - for(size_t j = 0; j < ceildiv(base_size, construct_size); j++) { + for(size_t j = 0; j < util::ceildiv(base_size, construct_size); j++) { construct_type chunk = static_cast(bits[i] >> (j * construct_size)); result |= std::bitset(chunk) << ((i * base_size) + (j * construct_size)); } @@ -227,7 +227,7 @@ public: if(pos == 0) { bytes++; - buffer = load_number(is); + buffer = util::load(is); } if(buffer & (stored_type(1) << pos)) { @@ -240,7 +240,7 @@ public: operator flag_type() const { if(bytes == 3 && pad_bits == 32) { // 3-byte sets are padded to 4 bytes - (void)load_number(is); + (void)util::load(is); } return result; } diff --git a/src/util/time.hpp b/src/util/time.hpp index 5b064b8..6f55f7d 100644 --- a/src/util/time.hpp +++ b/src/util/time.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Time parsing, formatting, onversion and filetime manipulation functions. + */ #ifndef INNOEXTRACT_UTIL_TIME_HPP #define INNOEXTRACT_UTIL_TIME_HPP diff --git a/src/util/types.hpp b/src/util/types.hpp index 6c08a49..746bd0e 100644 --- a/src/util/types.hpp +++ b/src/util/types.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Utility functions for dealing with types. + */ #ifndef INNOEXTRACT_UTIL_TYPES_HPP #define INNOEXTRACT_UTIL_TYPES_HPP @@ -29,87 +32,63 @@ #include "util/util.hpp" -template ::is_signed> -struct compatible_integer { - typedef void type; -}; +namespace util { #if BOOST_VERSION < 104200 -namespace detail { - - template - struct uint_t { }; - - template <> - struct uint_t<8> : public boost::uint_t<8> { - typedef boost::uint8_t exact; - }; - - template <> - struct uint_t<16> : public boost::uint_t<16> { - typedef boost::uint16_t exact; - }; - - template <> - struct uint_t<32> : public boost::uint_t<32> { - typedef boost::uint32_t exact; - }; - - template <> - struct uint_t<64> { - typedef boost::uint64_t exact; - }; - - template - struct int_t { }; - - template <> - struct int_t<8> : public boost::int_t<8> { - typedef boost::int8_t exact; - }; - - template <> - struct int_t<16> : public boost::int_t<16> { - typedef boost::int16_t exact; - }; - - template <> - struct int_t<32> : public boost::int_t<32> { - typedef boost::int32_t exact; - }; - - template <> - struct int_t<64> { - typedef boost::int64_t exact; - }; - -} +template +struct uint_t { }; +template <> +struct uint_t<8> : public boost::uint_t<8> { typedef boost::uint8_t exact; }; +template <> +struct uint_t<16> : public boost::uint_t<16> { typedef boost::uint16_t exact; }; +template <> +struct uint_t<32> : public boost::uint_t<32> { typedef boost::uint32_t exact; }; +template <> +struct uint_t<64> { typedef boost::uint64_t exact; }; + +template +struct int_t { }; +template <> +struct int_t<8> : public boost::int_t<8> { typedef boost::int8_t exact; }; +template <> +struct int_t<16> : public boost::int_t<16> { typedef boost::int16_t exact; }; +template <> +struct int_t<32> : public boost::int_t<32> { typedef boost::int32_t exact; }; +template <> +struct int_t<64> { typedef boost::int64_t exact; }; #else -namespace detail { - using boost::uint_t; - using boost::int_t; -} +using boost::uint_t; +using boost::int_t; #endif +/*! + * Get an with a specific bit size and signedness, + * but with no more bits than the original. + */ +template ::is_signed> +struct compatible_integer { + typedef void type; +}; template struct compatible_integer { - typedef typename detail::uint_t< + typedef typename uint_t< boost::static_unsigned_min::value >::exact type; }; - template struct compatible_integer { - typedef typename detail::int_t< + typedef typename int_t< boost::static_unsigned_min::value >::exact type; }; + +//! Get the alignment of a type. template unsigned int alignment_of() { #if defined(_MSC_VER) && _MSC_VER >= 1300 @@ -121,17 +100,20 @@ unsigned int alignment_of() { #endif } +//! Check if a pointer has aparticular alignment. inline bool is_aligned_on(const void * p, size_t alignment) { return alignment == 1 || (is_power_of_2(alignment) ? mod_power_of_2(size_t(p), alignment) == 0 : size_t(p) % alignment == 0); } +//! Check if a pointer is aligned for a specific type. template bool is_aligned(const void * p) { return is_aligned_on(p, alignment_of()); } +//! CRTP helper class to hide the ugly static casts needed to get to the derived class. template class static_polymorphic { @@ -145,4 +127,6 @@ protected: }; +} // namespace util + #endif // INNOEXTRACT_UTIL_TYPES_HPP diff --git a/src/util/util.hpp b/src/util/util.hpp index 652eb21..8171f64 100644 --- a/src/util/util.hpp +++ b/src/util/util.hpp @@ -18,6 +18,9 @@ * 3. This notice may not be removed or altered from any source distribution. */ +/*! + * Miscellaneous utility functions. + */ #ifndef INNOEXTRACT_UTIL_UTIL_HPP #define INNOEXTRACT_UTIL_UTIL_HPP @@ -25,18 +28,24 @@ #include #endif +namespace util { + +//! Get the number of elements in a statically-sized array. #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*(array))) +//! Divide by a number and round up the result. template T ceildiv(T num, T denom) { return (num + (denom - T(1))) / denom; } +//! Check if an integer is a power of two. template bool is_power_of_2(const T & n) { return n > 0 && (n & (n - 1)) == 0; } +//! Calculate a % b where b is always a power of two. template T2 mod_power_of_2(const T1 & a, const T2 & b) { return T2(a) & (b - 1); @@ -76,16 +85,19 @@ struct safe_shifter { } // namespace detail +//! Right-shift a value without shifting past the size of the type or return 0. template T safe_right_shift(T value) { return detail::safe_shifter<(bits >= (8 * sizeof(T)))>::right_shift(value, bits); } +//! Left-shift a value without shifting past the size of the type or return 0. template T safe_left_shift(T value) { return detail::safe_shifter<(bits >= (8 * sizeof(T)))>::left_shift(value, bits); } +//! Rotate left. template T rotl_fixed(T x, unsigned int y) { return T((x << y) | (x >> (sizeof(T) * 8 - y))); } @@ -118,4 +130,6 @@ inline boost::uint64_t rotl_fixed(boost::uint64_t x, unsigned i } #endif +} // namespace util + #endif // INNOEXTRACT_UTIL_UTIL_HPP