std::vector< CHashMatch > CDataBase::searchByHash_offs( CHash hash ) const { std::vector< CHashMatch > result; std::ifstream hash_file; std::vector< std::pair< uint64_t, int64_t > > matches; // vector of pairs ( mel_id, offset ) // hash offset cycle for( int64_t fixed_hash_offset = 0; fixed_hash_offset < static_cast< int64_t >( hash.getLength() ) - static_cast< int64_t >( CFixedHash::length ); ++fixed_hash_offset ) { CFixedHash fixed_hash( hash, fixed_hash_offset ); std::string hash_filename = makeFilenameOfHash( fixed_hash ); hash_file.open( makeFilenameOfHash( fixed_hash ), std::fstream::in | std::fstream::binary ); if( ! hash_file.is_open() ) { std::cout << "ERROR: Couldn't open hash file for reading: " << hash_filename << '\n'; return result; } // fixed hash file read cycle while( hash_file.is_open() && hash_file.good() && hash_file.peek() != EOF ) { // read melody id uint64_t mel_id = 0; Raspoznavayka::mel_size_t mel_chm_offs = 0; if( ! ( read_number_from_file( mel_id, mel_number_size_koeff, hash_file ) // read melody id && read_number_from_file( mel_chm_offs, mel_max_size_koeff, hash_file ) // read fixed hash match offset in melody ) ) { return result; } int64_t total_offset = static_cast<int64_t>( mel_chm_offs ) - static_cast<int64_t>( fixed_hash_offset ); // check distinct bool found = false; for( auto i = matches.begin(); i != matches.end(); ++i ) { if( i->first == mel_id && i->second == total_offset ) { found = true; break; } } if( !found ) { // push to matches matches.push_back( std::pair< uint64_t, int64_t >( mel_id, total_offset ) ); } } // end of fixed hash file read cycle hash_file.close(); } // end of hash offset cycle // read found melodies' data std::ifstream index_file; std::ifstream id3_file; std::ifstream mel_file; index_file.open( index_filename, std::fstream::in | std::fstream::binary ); id3_file.open( id3_filename, std::fstream::in ); mel_file.open( mel_filename, std::fstream::in | std::fstream::binary ); if( ! ( index_file.is_open() && id3_file.is_open() && mel_file.is_open() ) ) { std::cout << "ERROR: Couldn't open some DB file for writing in " << directory << '\n'; return result; } for( auto match = matches.begin(); match != matches.end(); ++match ) { int64_t mel_id = match->first, total_offset = match->second; // get index entry on this song index_file.seekg( mel_id * ( mel_number_size_koeff + mel_file_max_size_koeff ) ); // get id3 and and melody addresses uint64_t id3_start = 0, id3_end = 0, mel_start = 0, mel_end = 0; if( ! ( read_number_from_file( id3_start, id3_file_max_size_koeff, index_file ) && read_number_from_file( mel_start, mel_file_max_size_koeff, index_file ) && read_number_from_file( id3_end, id3_file_max_size_koeff, index_file ) && read_number_from_file( mel_end, mel_file_max_size_koeff, index_file ) ) ) { return result; } // read id3 tags assert( id3_start < id3_end ); assert( mel_start < mel_end ); std::string artist, album, name, year; uint64_t record_size = id3_end - id3_start; if( ! id3_file.seekg( id3_start ).good() ) { std::cout << "ERROR: in id3 file\n"; break; } std::getline( id3_file, artist ); record_size -= id3_file.gcount(); std::getline( id3_file, album ); record_size -= id3_file.gcount(); std::getline( id3_file, name ); record_size -= id3_file.gcount(); std::getline( id3_file, year ); if( ! mel_file.seekg( mel_start ).good() ) { std::cout << "ERROR: in mel file\n"; break; } std::vector< Raspoznavayka::interval_t > intervals( mel_end - mel_start ); for( uint64_t i = 0; i < mel_end - mel_start; ++i ) { char interval; if( mel_file.get( interval ).fail() ) { std::cout << "ERROR: in mel file\n"; break; } intervals[i] = static_cast< Raspoznavayka::interval_t >( interval ); } CIDTag idtag( artist, album, name, std::atoi( year.c_str() ) ); CInDBMelody new_melody( intervals, idtag ); CHashMatch new_chm( &new_melody, total_offset ); result.push_back( new_chm ); } // end of found melodies' data read cycle id3_file.close(); mel_file.close(); index_file.close(); return result; }