Browse Source

Cleanup loading functions

- Remove configure-time endianness check
  (replaced by run-time check to be optimized out by the compiler)
- Move loading functions into the util namespace
- Only keep the setup header entries we actually need
coverity_scan
Daniel Scharrer 13 years ago
parent
commit
08f5036ec7
  1. 3
      CMakeLists.txt
  2. 11
      src/cli/main.cpp
  3. 1
      src/configure.hpp.in
  4. 18
      src/crypto/checksum.hpp
  5. 92
      src/crypto/crc32.cpp
  6. 1
      src/crypto/crc32.hpp
  7. 105
      src/crypto/iteratedhash.hpp
  8. 2
      src/crypto/md5.cpp
  9. 3
      src/crypto/md5.hpp
  10. 29
      src/crypto/sha1.cpp
  11. 3
      src/crypto/sha1.hpp
  12. 32
      src/loader/exereader.cpp
  13. 28
      src/loader/offsets.cpp
  14. 22
      src/setup/component.cpp
  15. 42
      src/setup/data.cpp
  16. 4
      src/setup/delete.cpp
  17. 10
      src/setup/directory.cpp
  18. 20
      src/setup/file.cpp
  19. 144
      src/setup/header.cpp
  20. 22
      src/setup/icon.cpp
  21. 109
      src/setup/info.cpp
  22. 66
      src/setup/info.hpp
  23. 10
      src/setup/ini.cpp
  24. 12
      src/setup/item.cpp
  25. 36
      src/setup/language.cpp
  26. 21
      src/setup/message.cpp
  27. 5
      src/setup/message.hpp
  28. 2
      src/setup/permission.cpp
  29. 14
      src/setup/registry.cpp
  30. 18
      src/setup/run.cpp
  31. 16
      src/setup/task.cpp
  32. 12
      src/setup/type.cpp
  33. 10
      src/setup/windows.cpp
  34. 20
      src/stream/block.cpp
  35. 2
      src/stream/block.hpp
  36. 8
      src/stream/lzma.cpp
  37. 2
      src/stream/slice.cpp
  38. 3
      src/util/boostfs_compat.hpp
  39. 46
      src/util/console.hpp
  40. 208
      src/util/endian.hpp
  41. 6
      src/util/flags.hpp
  42. 26
      src/util/load.cpp
  43. 128
      src/util/load.hpp
  44. 17
      src/util/log.hpp
  45. 3
      src/util/output.hpp
  46. 12
      src/util/storedenum.hpp
  47. 3
      src/util/time.hpp
  48. 106
      src/util/types.hpp
  49. 14
      src/util/util.hpp

3
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:

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

1
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

18
src/crypto/checksum.hpp

@ -57,7 +57,7 @@ struct checksum {
};
template <class Impl>
class checksum_base : public static_polymorphic<Impl> {
class checksum_base : public util::static_polymorphic<Impl> {
public:
@ -66,13 +66,11 @@ public:
* Data is processed as-is and then converted according to Endianness.
*/
template <class T, class Endianness>
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<T>(buffer);
}
/*!
@ -80,8 +78,8 @@ public:
* Data is processed as-is and then converted if the host endianness is not little_endian.
*/
template <class T>
T load_number(std::istream & is) {
return load_number<T, little_endian>(is);
T load(std::istream & is) {
return load<T, util::little_endian>(is);
}
};

92
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<const boost::uint32_t *>(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<boost::uint32_t>(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

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

105
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<T>::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<boost::uint8_t *>(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<T>(input)) {
size_t leftOver = hash(reinterpret_cast<const hash_word *>(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 <class T>
size_t iterated_hash<T>::hash(const hash_word * input, size_t length) {
size_t iterated_hash<T>::hash(const char * input, size_t length) {
do {
if(byte_order::native() && util::is_aligned<T>(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<const hash_word *>(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 <class T>
void iterated_hash<T>::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<T>::pad(size_t last_block_size, char pad_first) {
boost::uint8_t * d = reinterpret_cast<boost::uint8_t *>(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 <class T>
void iterated_hash<T>::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<hash_word>(digest) && hash_size % sizeof(hash_word) == 0) {
byte_order::byteswap_if_alien(state, reinterpret_cast<hash_word *>(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);
}

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

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

29
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];

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

32
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<boost::uint16_t>(is);
boost::uint16_t nbnames = util::load<boost::uint16_t>(is);
// Number of id resource entries.
boost::uint16_t nbids = load_number<boost::uint16_t>(is);
boost::uint16_t nbids = util::load<boost::uint16_t>(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<boost::uint32_t>(is);
boost::uint32_t offset = load_number<boost::uint32_t>(is);
boost::uint32_t id = util::load<boost::uint32_t>(is);
boost::uint32_t offset = util::load<boost::uint32_t>(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<boost::uint16_t>(is.seekg(0x3c));
boost::uint16_t peOffset = util::load<boost::uint16_t>(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<boost::uint16_t>(is);
coff.nsections = util::load<boost::uint16_t>(is);
is.seekg(4 + 4 + 4, std::ios_base::cur); // creation time + symbol table offset + nbsymbols
boost::uint16_t optional_header_size = load_number<boost::uint16_t>(is);
boost::uint16_t optional_header_size = util::load<boost::uint16_t>(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<boost::uint16_t>(is);
boost::uint16_t optionalHeaderMagic = util::load<boost::uint16_t>(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<boost::uint32_t>(is);
boost::uint32_t ndirectories = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
boost::uint32_t resource_size = load_number<boost::uint32_t>(is);
coff.resource_table_address = util::load<boost::uint32_t>(is);
boost::uint32_t resource_size = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
section.virtual_address = load_number<boost::uint32_t>(is);
section.virtual_size = util::load<boost::uint32_t>(is);
section.virtual_address = util::load<boost::uint32_t>(is);
is.seekg(4, std::ios_base::cur); // raw size
section.raw_address = load_number<boost::uint32_t>(is);
section.raw_address = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
boost::uint32_t data_size = load_number<boost::uint32_t>(is);
boost::uint32_t data_address = util::load<boost::uint32_t>(is);
boost::uint32_t data_size = util::load<boost::uint32_t>(is);
// ignore codepage and reserved word
if(is.fail()) {
return result;

28
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<boost::uint32_t>(is);
boost::uint32_t magic = util::load<boost::uint32_t>(is);
if(is.fail() || magic != SetupLoaderHeaderMagic) {
is.clear();
return false;
}
boost::uint32_t offset_table_offset = load_number<boost::uint32_t>(is);
boost::uint32_t not_offset_table_offset = load_number<boost::uint32_t>(is);
boost::uint32_t offset_table_offset = util::load<boost::uint32_t>(is);
boost::uint32_t not_offset_table_offset = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
boost::uint32_t revision = checksum.load<boost::uint32_t>(is);
if(is.fail() || revision != 1) {
is.clear();
return false;
}
}
(void)checksum.load_number<boost::uint32_t>(is);
exe_offset = checksum.load_number<boost::uint32_t>(is);
(void)checksum.load<boost::uint32_t>(is);
exe_offset = checksum.load<boost::uint32_t>(is);
if(version >= INNO_VERSION(4, 1, 6)) {
exe_compressed_size = 0;
} else {
exe_compressed_size = checksum.load_number<boost::uint32_t>(is);
exe_compressed_size = checksum.load<boost::uint32_t>(is);
}
exe_uncompressed_size = checksum.load_number<boost::uint32_t>(is);
exe_uncompressed_size = checksum.load<boost::uint32_t>(is);
if(version >= INNO_VERSION(4, 0, 3)) {
exe_checksum.type = crypto::CRC32;
exe_checksum.crc32 = checksum.load_number<boost::uint32_t>(is);
exe_checksum.crc32 = checksum.load<boost::uint32_t>(is);
} else {
exe_checksum.type = crypto::Adler32;
exe_checksum.adler32 = checksum.load_number<boost::uint32_t>(is);
exe_checksum.adler32 = checksum.load<boost::uint32_t>(is);
}
if(version >= INNO_VERSION(4, 0, 0)) {
message_offset = 0;
} else {
message_offset = load_number<boost::uint32_t>(is);
message_offset = util::load<boost::uint32_t>(is);
}
header_offset = checksum.load_number<boost::uint32_t>(is);
data_offset = checksum.load_number<boost::uint32_t>(is);
header_offset = checksum.load<boost::uint32_t>(is);
data_offset = checksum.load<boost::uint32_t>(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<boost::uint32_t>(is);
boost::uint32_t expected = util::load<boost::uint32_t>(is);
if(is.fail()) {
is.clear();
return false;

22
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<boost::uint64_t>(is);
extra_disk_pace_required = util::load<boost::uint64_t>(is);
} else {
extra_disk_pace_required = load_number<boost::uint32_t>(is);
extra_disk_pace_required = util::load<boost::uint32_t>(is);
}
if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) {
level = load_number<boost::int32_t>(is);
used = load_bool(is);
level = util::load<boost::int32_t>(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<boost::uint64_t>(is);
size = util::load<boost::uint64_t>(is);
} else {
size = load_number<boost::uint32_t>(is);
size = util::load<boost::uint32_t>(is);
}
}

42
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<boost::uint32_t>(is, version.bits);
chunk.last_slice = load_number<boost::uint32_t>(is, version.bits);
chunk.first_slice = util::load<boost::uint32_t>(is, version.bits);
chunk.last_slice = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
chunk.offset = util::load<boost::uint32_t>(is);
if(version >= INNO_VERSION(4, 0, 1)) {
file.offset = load_number<boost::uint64_t>(is);
file.offset = util::load<boost::uint64_t>(is);
} else {
file.offset = 0;
}
if(version >= INNO_VERSION(4, 0, 0)) {
file.size = load_number<boost::uint64_t>(is);
chunk.size = load_number<boost::uint64_t>(is);
file.size = util::load<boost::uint64_t>(is);
chunk.size = util::load<boost::uint64_t>(is);
} else {
file.size = load_number<boost::uint32_t>(is);
chunk.size = load_number<boost::uint32_t>(is);
file.size = util::load<boost::uint32_t>(is);
chunk.size = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
file.checksum.crc32 = util::load<boost::uint32_t>(is);
file.checksum.type = crypto::CRC32;
} else {
file.checksum.adler32 = load_number<boost::uint32_t>(is);
file.checksum.adler32 = util::load<boost::uint32_t>(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<boost::uint16_t>(is);
boost::uint16_t date = load_number<boost::uint16_t>(is);
boost::uint16_t time = util::load<boost::uint16_t>(is);
boost::uint16_t date = util::load<boost::uint16_t>(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<boost::int64_t>(is);
boost::int64_t filetime = util::load<boost::int64_t>(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<boost::uint32_t>(is);
file_version_ls = load_number<boost::uint32_t>(is);
file_version_ms = util::load<boost::uint32_t>(is);
file_version_ls = util::load<boost::uint32_t>(is);
options = 0;

4
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<boost::uint32_t>(is); // uncompressed size of the directory entry structure
(void)util::load<boost::uint32_t>(is); // uncompressed size of the entry
}
is >> encoded_string(name, version.codepage());
is >> util::encoded_string(name, version.codepage());
load_condition_data(is, version);

10
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<boost::uint32_t>(is); // uncompressed size of the directory entry structure
(void)util::load<boost::uint32_t>(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<boost::uint32_t>(is);
attributes = util::load<boost::uint32_t>(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<boost::int16_t>(is);
permission = util::load<boost::int16_t>(is);
} else {
permission = -1;
}

20
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<boost::uint32_t>(is); // uncompressed size of the file entry structure
(void)util::load<boost::uint32_t>(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<boost::uint32_t>(is, version.bits);
attributes = load_number<boost::uint32_t>(is, version.bits);
external_size = (version >= INNO_VERSION(4, 0, 0)) ? load_number<boost::uint64_t>(is)
: load_number<boost::uint32_t>(is);
location = util::load<boost::uint32_t>(is, version.bits);
attributes = util::load<boost::uint32_t>(is, version.bits);
external_size = (version >= INNO_VERSION(4, 0, 0)) ? util::load<boost::uint64_t>(is)
: util::load<boost::uint32_t>(is);
if(version < INNO_VERSION(3, 0, 5)) {
file_copy_mode copyMode = stored_enum<stored_file_copy_mode>(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<boost::int16_t>(is);
permission = util::load<boost::int16_t>(is);
} else {
permission = -1;
}

144
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<boost::uint32_t>(is); // uncompressed size of the setup header structure
(void)util::load<boost::uint32_t>(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<boost::uint32_t>(is);
language_count = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
message_count = util::load<boost::uint32_t>(is);
} else {
message_count = 0;
}
if(version >= INNO_VERSION(4, 1, 0)) {
permission_count = load_number<boost::uint32_t>(is);
permission_count = util::load<boost::uint32_t>(is);
} else {
permission_count = 0;
}
if(version >= INNO_VERSION(2, 0, 0)) {
type_count = load_number<boost::uint32_t>(is);
component_count = load_number<boost::uint32_t>(is);
task_count = load_number<boost::uint32_t>(is);
type_count = util::load<boost::uint32_t>(is);
component_count = util::load<boost::uint32_t>(is);
task_count = util::load<boost::uint32_t>(is);
} else {
type_count = 0, component_count = 0, task_count = 0;
}
directory_count = load_number<boost::uint32_t>(is, version.bits);
file_count = load_number<boost::uint32_t>(is, version.bits);
data_entry_count = load_number<boost::uint32_t>(is, version.bits);
icon_count = load_number<boost::uint32_t>(is, version.bits);
ini_entry_count = load_number<boost::uint32_t>(is, version.bits);
registry_entry_count = load_number<boost::uint32_t>(is, version.bits);
delete_entry_count = load_number<boost::uint32_t>(is, version.bits);
uninstall_delete_entry_count = load_number<boost::uint32_t>(is, version.bits);
run_entry_count = load_number<boost::uint32_t>(is, version.bits);
uninstall_run_entry_count = load_number<boost::uint32_t>(is, version.bits);
directory_count = util::load<boost::uint32_t>(is, version.bits);
file_count = util::load<boost::uint32_t>(is, version.bits);
data_entry_count = util::load<boost::uint32_t>(is, version.bits);
icon_count = util::load<boost::uint32_t>(is, version.bits);
ini_entry_count = util::load<boost::uint32_t>(is, version.bits);
registry_entry_count = util::load<boost::uint32_t>(is, version.bits);
delete_entry_count = util::load<boost::uint32_t>(is, version.bits);
uninstall_delete_entry_count = util::load<boost::uint32_t>(is, version.bits);
run_entry_count = util::load<boost::uint32_t>(is, version.bits);
uninstall_run_entry_count = util::load<boost::uint32_t>(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<boost::int32_t>(is, version.bits);
info_before_size = load_number<boost::int32_t>(is, version.bits);
info_after_size = load_number<boost::int32_t>(is, version.bits);
license_size = util::load<boost::int32_t>(is, version.bits);
info_before_size = util::load<boost::int32_t>(is, version.bits);
info_after_size = util::load<boost::int32_t>(is, version.bits);
}
winver.load(is, version);
back_color = load_number<boost::uint32_t>(is);
back_color = util::load<boost::uint32_t>(is);
if(version >= INNO_VERSION(1, 3, 21)) {
back_color2 = load_number<boost::uint32_t>(is);
back_color2 = util::load<boost::uint32_t>(is);
} else {
back_color2 = 0;
}
image_back_color = load_number<boost::uint32_t>(is);
image_back_color = util::load<boost::uint32_t>(is);
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) {
small_image_back_color = load_number<boost::uint32_t>(is);
small_image_back_color = util::load<boost::uint32_t>(is);
} else {
small_image_back_color = 0;
}
if(version < INNO_VERSION(4, 2, 0)) {
password.crc32 = load_number<boost::uint32_t>(is);
password.crc32 = util::load<boost::uint32_t>(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<boost::int64_t>(is);
slices_per_disk = load_number<boost::uint32_t>(is);
extra_disk_space_required = util::load<boost::int64_t>(is);
slices_per_disk = util::load<boost::uint32_t>(is);
} else {
extra_disk_space_required = load_number<boost::int32_t>(is);
extra_disk_space_required = util::load<boost::int32_t>(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<boost::uint32_t>(is);
signed_uninstaller_header_checksum = load_number<boost::uint32_t>(is);
signed_uninstaller_original_size = util::load<boost::uint32_t>(is);
signed_uninstaller_header_checksum = util::load<boost::uint32_t>(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<boost::uint64_t>(is);
uninstall_display_size = util::load<boost::uint64_t>(is);
} else if(version >= INNO_VERSION(5, 3, 6)) {
uninstall_display_size = load_number<boost::uint32_t>(is);
uninstall_display_size = util::load<boost::uint32_t>(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);
}
}

22
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<boost::uint32_t>(is); // uncompressed size of the icon entry structure
(void)util::load<boost::uint32_t>(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<boost::int32_t>(is, version.bits);
icon_index = util::load<boost::int32_t>(is, version.bits);
if(version >= INNO_VERSION(1, 3, 21)) {
show_command = load_number<boost::int32_t>(is);
show_command = util::load<boost::int32_t>(is);
close_on_exit = stored_enum<stored_close_setting>(is).get();
} else {
show_command = 1, close_on_exit = NoSetting;
}
if(version >= INNO_VERSION(2, 0, 7)) {
hotkey = load_number<boost::uint16_t>(is);
hotkey = util::load<boost::uint16_t>(is);
} else {
hotkey = 0;
}

109
src/setup/info.cpp

@ -48,52 +48,98 @@ namespace setup {
namespace {
struct no_arg { };
template <class Entry, class Arg>
static void load_entry(std::istream & is, const setup::version & version,
Entry & entity, Arg arg) {
entity.load(is, version, arg);
}
template <class Entry>
static void load_entry(std::istream & is, const setup::version & version,
Entry & entity, no_arg arg) {
(void)arg;
entity.load(is, version);
}
template <class Entry, class Arg>
static void load_entries(std::istream & is, const setup::version & version,
info::entry_types entry_types, size_t count,
std::vector<Entry> & entries, info::entry_types::enum_type entry_type) {
std::vector<Entry> & 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 <class Entry>
static void load_entries(std::istream & is, const setup::version & version,
info::entry_types entry_types, size_t count,
std::vector<Entry> & entries, info::entry_types::enum_type entry_type) {
load_entries<Entry, no_arg>(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);
}
}

66
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<component_entry> components;
std::vector<data_entry> data_entries;
std::vector<delete_entry> delete_entries;
std::vector<delete_entry> uninstall_delete_entries;
std::vector<directory_entry> directories;
std::vector<file_entry> files;
std::vector<icon_entry> icons;
std::vector<ini_entry> ini_entries;
std::vector<language_entry> languages;
std::vector<message_entry> messages;
std::vector<permission_entry> permissions;
std::vector<registry_entry> registry_entries;
std::vector<run_entry> run_entries;
std::vector<run_entry> uninstall_run_entries;
std::vector<task_entry> tasks;
std::vector<type_entry> types;
std::vector<component_entry> components; //! \ref Components
std::vector<data_entry> data_entries; //! \ref DataEntries
std::vector<delete_entry> delete_entries; //! \ref DeleteEntries
std::vector<delete_entry> uninstall_delete_entries; //! \ref UninstallDeleteEntries
std::vector<directory_entry> directories; //! \ref Directories
std::vector<file_entry> files; //! \ref Files
std::vector<icon_entry> icons; //! \ref Icons
std::vector<ini_entry> ini_entries; //! \ref IniEntries
std::vector<language_entry> languages; //! \ref Languages
std::vector<message_entry> messages; //! \ref Messages
std::vector<permission_entry> permissions; //! \ref Permissions
std::vector<registry_entry> registry_entries; //! \ref RegistryEntries
std::vector<run_entry> run_entries; //! \ref RunEntries
std::vector<run_entry> uninstall_run_entries; //! \ref UninstallRunEntries
std::vector<task_entry> tasks; //! \ref Tasks
std::vector<type_entry> 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);
};

10
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<boost::uint32_t>(is); // uncompressed size of the ini entry structure
(void)util::load<boost::uint32_t>(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);

12
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();
}

36
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<boost::uint32_t>(is);
language_id = util::load<boost::uint32_t>(is);
if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) {
codepage = load_number<boost::uint32_t>(is);
codepage = util::load<boost::uint32_t>(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<boost::uint32_t>(is);
dialog_font_size = util::load<boost::uint32_t>(is);
if(version < INNO_VERSION(4, 1, 0)) {
dialog_font_standard_height = load_number<boost::uint32_t>(is);
dialog_font_standard_height = util::load<boost::uint32_t>(is);
} else {
dialog_font_standard_height = 0;
}
title_font_size = load_number<boost::uint32_t>(is);
welcome_font_size = load_number<boost::uint32_t>(is);
copyright_font_size = load_number<boost::uint32_t>(is);
title_font_size = util::load<boost::uint32_t>(is);
welcome_font_size = util::load<boost::uint32_t>(is);
copyright_font_size = util::load<boost::uint32_t>(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;
}

21
src/setup/message.cpp

@ -22,18 +22,31 @@
#include <boost/cstdint.hpp>
#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<language_entry> & 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<boost::int32_t>(is);
language = util::load<boost::int32_t>(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

5
src/setup/message.hpp

@ -23,10 +23,12 @@
#include <string>
#include <iosfwd>
#include <vector>
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<language_entry> & languages);
};

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

14
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<boost::uint32_t>(is); // uncompressed size of the directory entry structure
(void)util::load<boost::uint32_t>(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<boost::uint32_t>(is) & ~0x80000000);
hive = hive_name(util::load<boost::uint32_t>(is) & ~0x80000000);
} else {
hive = Unset;
}
if(version >= INNO_VERSION(4, 1, 0)) {
permission = load_number<boost::int16_t>(is);
permission = util::load<boost::int16_t>(is);
} else {
permission = -1;
}

18
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<boost::uint32_t>(is); // uncompressed size of the directory entry structure
(void)util::load<boost::uint32_t>(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<boost::int32_t>(is);
show_command = util::load<boost::int32_t>(is);
} else {
show_command = 0;
}

16
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<boost::int32_t>(is);
used = load_bool(is);
is >> util::encoded_string(check, version.codepage());
level = util::load<boost::int32_t>(is);
used = util::load_bool(is);
} else {
check.clear(), level = 0, used = true;
}

12
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<boost::uint64_t>(is);
size = util::load<boost::uint64_t>(is);
} else {
size = load_number<boost::uint32_t>(is);
size = util::load<boost::uint32_t>(is);
}
}

10
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<boost::uint16_t>(is);
build = util::load<boost::uint16_t>(is);
} else {
build = 0;
}
minor = load_number<boost::uint8_t>(is);
major = load_number<boost::uint8_t>(is);
minor = util::load<boost::uint8_t>(is);
major = util::load<boost::uint8_t>(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<boost::uint8_t>(is);
nt_service_pack.major = load_number<boost::uint8_t>(is);
nt_service_pack.minor = util::load<boost::uint8_t>(is);
nt_service_pack.major = util::load<boost::uint8_t>(is);
} else {
nt_service_pack.major = 0, nt_service_pack.minor = 0;
}

20
src/stream/block.cpp

@ -81,8 +81,7 @@ public:
template<typename Source>
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<boost::uint32_t>(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<boost::uint32_t>(base);
boost::uint32_t expected_checksum = util::load<boost::uint32_t>(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<boost::uint32_t>(base);
boost::uint8_t compressed = actual_checksum.load_number<boost::uint8_t>(base);
stored_size = actual_checksum.load<boost::uint32_t>(base);
boost::uint8_t compressed = actual_checksum.load<boost::uint8_t>(base);
compression = compressed ? (version >= INNO_VERSION(4, 1, 6) ? LZMA1 : Zlib) : Stored;
} else {
boost::uint32_t compressed_size = actual_checksum.load_number<boost::uint32_t>(base);
boost::uint32_t uncompressed_size = actual_checksum.load_number<boost::uint32_t>(base);
boost::uint32_t compressed_size = actual_checksum.load<boost::uint32_t>(base);
boost::uint32_t uncompressed_size = actual_checksum.load<boost::uint32_t>(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<boost::uint64_t>(stored_size, 4096) * 4);
stored_size += boost::uint32_t(util::ceildiv<boost::uint64_t>(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());
}

2
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 {

8
src/stream/lzma.cpp

@ -26,6 +26,9 @@
#include <lzma.h>
#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<boost::uint32_t>(header + 1);
stream = init_raw_lzma_stream(LZMA_FILTER_LZMA1, options);
}

2
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<boost::uint32_t>(ifs);
slice_size = util::load<boost::uint32_t>(ifs);
if(ifs.fail()) {
ifs.close();
throw slice_error("error reading slice size");

3
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

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

208
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 <cstdlib>
#include <cstring>
#include "configure.hpp"
@ -31,6 +35,10 @@
#include <boost/cstdint.hpp>
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 <class T>
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 <bool Native>
//! Load/store functions for a specific endianness.
template <typename Endianness>
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 <typename T>
static T load(const char * buffer) {
if(Endianness::native()) {
T value;
std::memcpy(&value, buffer, sizeof(value));
return value;
} else {
return load_alien<T>(buffer);
}
}
template <class T>
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 <code>sizeof(T) * count</code> bytes.
* \param values Output array for the loaded integers.
* \param count How many integers to load.
*/
template <typename T>
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<T>(buffer);
}
}
}
template <class T>
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 <typename T>
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<true> {
/*!
* 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 <code>sizeof(T) * count</code> bytes.
*/
template <typename T>
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 <class T>
static T byteswap_if_alien(T value) { return value; }
template <typename T>
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<T>(buffer);
}
}
template <class T>
static void byteswap_if_alien(const T * in, T * out, size_t byte_count) {
if(in != out) {
std::memcpy(out, in, byte_count);
template <typename T>
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<T>(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<char *>(&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<char *>(&signature) == 4);
}
} // namespace detail
struct little_endian : public endianness<INNOEXTRACT_ENDIANNESS == LITTLE_ENDIAN> {
static const size_t offset = 0;
//! Load and store little-endian integers.
struct little_endian : endianness<little_endian> {
//! \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 <typename T>
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 <typename T>
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<little_endian>;
};
struct big_endian : public endianness<INNOEXTRACT_ENDIANNESS == BIG_ENDIAN> {
static const size_t offset = 1;
//! Load and store big-endian integers.
struct big_endian : endianness<big_endian> {
//! \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 <typename T>
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 <typename T>
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<big_endian>;
};
#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

6
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());
}

26
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<boost::int32_t>(is);
boost::uint32_t length = util::load<boost::uint32_t>(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<boost::uint32_t>(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

128
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: <code>is >> binary_string(str)</code>
*
* 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: <code>is >> encoded_string(str, codepage)</code>
*
* 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 <class T>
//! Load a value of type T that is stored with a specific endianness.
template <class T, class Endianness>
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<T>(buffer);
}
//! Load a value of type T that is stored as little endian.
template <class T>
T load(std::istream & is) { return load<T, little_endian>(is); }
//! Load a bool value
inline bool load_bool(std::istream & is) {
return (load<boost::uint8_t>(is) != 0);
}
template <class T, class Endianness>
T load_number(std::istream & is) {
return Endianness::byteswap_if_alien(load<T>(is));
}
template <class T>
T load_number(std::istream & is) {
return load_number<T, little_endian>(is);
return !!load<boost::uint8_t>(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 <class T, class Endianness>
T load_number(std::istream & is, size_t bits) {
T load(std::istream & is, size_t bits) {
if(bits == 8) {
return load_number<typename compatible_integer<T, 8>::type, Endianness>(is);
return load<typename compatible_integer<T, 8>::type, Endianness>(is);
} else if(bits == 16) {
return load_number<typename compatible_integer<T, 16>::type, Endianness>(is);
return load<typename compatible_integer<T, 16>::type, Endianness>(is);
} else if(bits == 32) {
return load_number<typename compatible_integer<T, 32>::type, Endianness>(is);
return load<typename compatible_integer<T, 32>::type, Endianness>(is);
} else {
return load_number<typename compatible_integer<T, 64>::type, Endianness>(is);
return load<typename compatible_integer<T, 64>::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 <class T>
T load_number(std::istream & is, size_t bits) {
return load_number<T, little_endian>(is, bits);
}
T load(std::istream & is, size_t bits) { return load<T, little_endian>(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 <class T>
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 <typename T>
T get_bits(T number, int first, int last) {
typedef typename detail::uint_t<sizeof(T) * 8>::exact UT;
typedef typename uint_t<sizeof(T) * 8>::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

17
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<class T>

3
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

12
src/util/storedenum.hpp

@ -71,7 +71,7 @@ public:
explicit stored_enum(std::istream & is) {
BOOST_STATIC_ASSERT(size <= (1 << 8));
value = load_number<boost::uint8_t>(is);
value = util::load<boost::uint8_t>(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<base_type>(is);
bits[i] = util::load<base_type>(is);
}
if(count == 3 && PadBits == 32) {
// 3-byte sets are padded to 4 bytes
(void)load_number<base_type>(is);
(void)util::load<base_type>(is);
}
}
@ -139,7 +139,7 @@ public:
std::bitset<size> 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<construct_type>(bits[i] >> (j * construct_size));
result |= std::bitset<size>(chunk) << ((i * base_size) + (j * construct_size));
}
@ -227,7 +227,7 @@ public:
if(pos == 0) {
bytes++;
buffer = load_number<stored_type>(is);
buffer = util::load<stored_type>(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<stored_type>(is);
(void)util::load<stored_type>(is);
}
return result;
}

3
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

106
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 <class Base, size_t Bits,
bool Signed = std::numeric_limits<Base>::is_signed>
struct compatible_integer {
typedef void type;
};
namespace util {
#if BOOST_VERSION < 104200
namespace detail {
template <size_t Bits>
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 <size_t Bits>
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 <size_t Bits>
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 <size_t Bits>
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 <class Base, size_t Bits,
bool Signed = std::numeric_limits<Base>::is_signed>
struct compatible_integer {
typedef void type;
};
template <class Base, size_t Bits>
struct compatible_integer<Base, Bits, false> {
typedef typename detail::uint_t<
typedef typename uint_t<
boost::static_unsigned_min<Bits, sizeof(Base) * 8>::value
>::exact type;
};
template <class Base, size_t Bits>
struct compatible_integer<Base, Bits, true> {
typedef typename detail::int_t<
typedef typename int_t<
boost::static_unsigned_min<Bits, sizeof(Base) * 8>::value
>::exact type;
};
//! Get the alignment of a type.
template <class T>
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 <class T>
bool is_aligned(const void * p) {
return is_aligned_on(p, alignment_of<T>());
}
//! CRTP helper class to hide the ugly static casts needed to get to the derived class.
template <class Impl>
class static_polymorphic {
@ -145,4 +127,6 @@ protected:
};
} // namespace util
#endif // INNOEXTRACT_UTIL_TYPES_HPP

14
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 <intrin.h>
#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 <typename T>
T ceildiv(T num, T denom) {
return (num + (denom - T(1))) / denom;
}
//! Check if an integer is a power of two.
template <class T>
bool is_power_of_2(const T & n) {
return n > 0 && (n & (n - 1)) == 0;
}
//! Calculate <code>a % b</code> where b is always a power of two.
template <class T1, class T2>
T2 mod_power_of_2(const T1 & a, const T2 & b) {
return T2(a) & (b - 1);
@ -76,16 +85,19 @@ struct safe_shifter<false> {
} // namespace detail
//! Right-shift a value without shifting past the size of the type or return 0.
template <unsigned int bits, class T>
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 <unsigned int bits, class T>
T safe_left_shift(T value) {
return detail::safe_shifter<(bits >= (8 * sizeof(T)))>::left_shift(value, bits);
}
//! Rotate left.
template <class T> 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>(boost::uint64_t x, unsigned i
}
#endif
} // namespace util
#endif // INNOEXTRACT_UTIL_UTIL_HPP

Loading…
Cancel
Save