/* Copyright 2015, Michele Santullo
* This file is part of "dindexer".
*
* "dindexer" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "dindexer" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "dindexer". If not, see .
*/
#include "tiger.hpp"
#include
#include
#include
#include
#include
#include
#if defined(__SSE2__)
extern "C" void tiger_sse2_chunk ( const char* parStr1, const char* parStr2, uint64_t parLength, uint64_t parRes1[3], uint64_t parRes2[3] );
extern "C" void tiger_sse2_last_chunk ( const char* parStr1, const char* parStr2, uint64_t parLength, uint64_t parRealLength, uint64_t parRes1[3], uint64_t parRes2[3], char pad );
#else
# error "Not implemented without SSE2"
#endif
namespace din {
namespace {
const uint32_t g_buff_size = 1024 * 8;
const char g_tiger_padding = 0x80; //0x01 for V1
uint64_t swap_long (uint64_t parNum) {
parNum = (parNum & 0x00000000FFFFFFFF) << 32 | (parNum & 0xFFFFFFFF00000000) >> 32;
parNum = (parNum & 0x0000FFFF0000FFFF) << 16 | (parNum & 0xFFFF0000FFFF0000) >> 16;
parNum = (parNum & 0x00FF00FF00FF00FF) << 8 | (parNum & 0xFF00FF00FF00FF00) >> 8;
return parNum;
}
} //unnamed namespace
void tiger_init_hash (TigerHash& parHash) {
parHash.part_a = 0x0123456789ABCDEFULL;
parHash.part_b = 0xFEDCBA9876543210ULL;
parHash.part_c = 0xF096A5B4C3B2E187ULL;
}
void tiger_file (const std::string& parPath, TigerHash& parHashFile, TigerHash& parHashDir) {
tiger_init_hash(parHashFile);
std::ifstream src(parPath, std::ios::binary);
src.seekg(0, std::ios_base::end);
const auto file_size = src.tellg();
src.seekg(0, std::ios_base::beg);
const uint32_t buffsize = static_cast(std::min(file_size, g_buff_size));
std::unique_ptr buff(new char[63 + buffsize]);
char* const buff_ptr = reinterpret_cast(reinterpret_cast(buff.get() + 63) & (-64));
assert(buff_ptr >= buff.get() and buff_ptr + buffsize <= buff.get() + 63 + buffsize);
auto remaining = file_size;
while (remaining > buffsize) {
assert(buffsize >= sizeof(uint64_t) * 3);
assert(buffsize == (buffsize & -64));
remaining -= buffsize;
src.read(buff_ptr, buffsize);
tiger_sse2_chunk(buff_ptr, buff_ptr, buffsize, parHashFile.data, parHashDir.data);
}
{
assert(remaining <= buffsize);
src.read(buff_ptr, remaining);
const auto aligned_size = remaining & -64;
if (aligned_size) {
tiger_sse2_chunk(buff_ptr, buff_ptr, aligned_size, parHashFile.data, parHashDir.data);
}
tiger_sse2_last_chunk(buff_ptr + aligned_size, buff_ptr + aligned_size, remaining - aligned_size, file_size, parHashFile.data, parHashDir.data, g_tiger_padding);
}
}
std::string tiger_to_string (const TigerHash& parHash) {
std::ostringstream oss;
oss << std::hex << swap_long(parHash.part_a) << swap_long(parHash.part_b) << swap_long(parHash.part_c);
return oss.str();
}
} //namespace din