void rm_digest_update(RmDigest *digest, const unsigned char *data, RmOff size) { switch(digest->type) { case RM_DIGEST_EXT: /* Data is assumed to be a hex representation of a cchecksum. * Needs to be compressed in pure memory first. * * Checksum is not updated but rather overwritten. * */ #define CHAR_TO_NUM(c) (unsigned char)(g_ascii_isdigit(c) ? c - '0' : (c - 'a') + 10) rm_assert_gentle(data); digest->bytes = size / 2; digest->checksum = g_slice_alloc0(digest->bytes); for(unsigned i = 0; i < digest->bytes; ++i) { ((guint8 *)digest->checksum)[i] = (CHAR_TO_NUM(data[2 * i]) << 4) + CHAR_TO_NUM(data[2 * i + 1]); } break; case RM_DIGEST_MD5: case RM_DIGEST_SHA512: case RM_DIGEST_SHA256: case RM_DIGEST_SHA1: g_checksum_update(digest->glib_checksum, (const guchar *)data, size); break; case RM_DIGEST_SPOOKY32: digest->checksum[0].first = spooky_hash32(data, size, digest->checksum[0].first); break; case RM_DIGEST_SPOOKY64: digest->checksum[0].first = spooky_hash64(data, size, digest->checksum[0].first); break; case RM_DIGEST_SPOOKY: spooky_hash128(data, size, (uint64_t *)&digest->checksum[0].first, (uint64_t *)&digest->checksum[0].second); break; case RM_DIGEST_XXHASH: digest->checksum[0].first = XXH64(data, size, digest->checksum[0].first); break; case RM_DIGEST_FARMHASH: digest->checksum[0].first = cfarmhash((const char *)data, size); break; case RM_DIGEST_MURMUR512: case RM_DIGEST_MURMUR256: case RM_DIGEST_MURMUR: for(guint8 block = 0; block < (digest->bytes / 16); block++) { #if RM_PLATFORM_32 MurmurHash3_x86_128(data, size, (uint32_t)digest->checksum[block].first, &digest->checksum[block]); //& #elif RM_PLATFORM_64 MurmurHash3_x64_128(data, size, (uint32_t)digest->checksum[block].first, &digest->checksum[block]); #else #error "Probably not a good idea to compile rmlint on 16bit." #endif } break; case RM_DIGEST_CITY: case RM_DIGEST_CITY256: case RM_DIGEST_CITY512: for(guint8 block = 0; block < (digest->bytes / 16); block++) { /* Opt out for the more optimized version. * This needs the crc command of sse4.2 * (available on Intel Nehalem and up; my amd box doesn't have this though) */ uint128 old = {digest->checksum[block].first, digest->checksum[block].second}; old = CityHash128WithSeed((const char *)data, size, old); memcpy(&digest->checksum[block], &old, sizeof(uint128)); } break; case RM_DIGEST_BASTARD: MurmurHash3_x86_128(data, size, (uint32_t)digest->checksum[0].first, &digest->checksum[0]); uint128 old = {digest->checksum[1].first, digest->checksum[1].second}; old = CityHash128WithSeed((const char *)data, size, old); memcpy(&digest->checksum[1], &old, sizeof(uint128)); break; case RM_DIGEST_CUMULATIVE: { /* This is basically FNV1a, it is just important that the order of * adding data to the hash has no effect on the result, so it can * be used as a lookup key: * * http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function * */ RmOff hash = 0xcbf29ce484222325; for(gsize i = 0; i < digest->bytes; ++i) { hash ^= ((guint8 *)data)[i % size]; hash *= 0x100000001b3; ((guint8 *)digest->checksum)[i] += hash; } } break; case RM_DIGEST_PARANOID: default: rm_assert_gentle_not_reached(); } }
void rm_digest_update(RmDigest *digest, const unsigned char *data, RmOff size) { switch(digest->type) { case RM_DIGEST_MD5: case RM_DIGEST_SHA512: case RM_DIGEST_SHA256: case RM_DIGEST_SHA1: g_checksum_update(digest->glib_checksum, (const guchar *)data, size); break; case RM_DIGEST_SPOOKY32: digest->checksum[0].first = spooky_hash32(data, size, digest->checksum[0].first); break; case RM_DIGEST_SPOOKY64: digest->checksum[0].first = spooky_hash64(data, size, digest->checksum[0].first); break; case RM_DIGEST_SPOOKY: spooky_hash128(data, size, &digest->checksum[0].first, &digest->checksum[0].second); break; case RM_DIGEST_MURMUR512: case RM_DIGEST_MURMUR256: case RM_DIGEST_MURMUR: for (guint8 block = 0; block < ( digest->bytes / 16 ); block++) { #if RM_PLATFORM_32 MurmurHash3_x86_128(data, size, (uint32_t)digest->checksum[block].first, &digest->checksum[block]); //& #elif RM_PLATFORM_64 MurmurHash3_x64_128(data, size, (uint32_t)digest->checksum[block].first, &digest->checksum[block]); #else #error "Probably not a good idea to compile rmlint on 16bit." #endif } break; case RM_DIGEST_CITY: case RM_DIGEST_CITY256: case RM_DIGEST_CITY512: for (guint8 block = 0; block < (digest->bytes / 16); block++) { /* Opt out for the more optimized version. * This needs the crc command of sse4.2 * (available on Intel Nehalem and up; my amd box doesn't have this though) */ #if RM_PLATFORM_64 && HAVE_SSE42 digest->checksum[block] = CityHashCrc128WithSeed((const char *)data, size, digest->checksum[block]); #else digest->checksum[block] = CityHash128WithSeed((const char *) data, size, digest->checksum[block]); #endif } break; case RM_DIGEST_BASTARD: MurmurHash3_x86_128(data, size, (uint32_t)digest->checksum[0].first, &digest->checksum[0]); #if RM_PLATFORM_64 && HAVE_SSE42 digest->checksum[1] = CityHashCrc128WithSeed((const char *)data, size, digest->checksum[1]); #else digest->checksum[1] = CityHash128WithSeed((const char *) data, size, digest->checksum[1]); #endif break; case RM_DIGEST_CUMULATIVE: { /* This is basically FNV1a, it is just important that the order of * adding data to the hash has no effect on the result, so it can * be used as a lookup key: * * http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function * */ RmOff hash = 0xcbf29ce484222325; for(gsize i = 0; i < digest->bytes; ++i) { hash ^= ((guint8 *)data)[i % size]; hash *= 0x100000001b3; ((guint8 *)digest->checksum)[i] += hash; } } break; case RM_DIGEST_PARANOID: g_assert(size + digest->paranoid_offset <= digest->bytes); memcpy((char *)digest->checksum + digest->paranoid_offset, data, size); digest->paranoid_offset += size; rm_digest_update(digest->shadow_hash, data, size); break; default: g_assert_not_reached(); } }