/** Merge graph \p ga into graph \p gb. Returns false on failure. */ bool mergeNfaPair(NGHolder &ga, NGHolder &gb, const ReportManager *rm, const CompileContext &cc) { assert(ga.kind == gb.kind); auto a_state_ids = numberStates(ga); auto b_state_ids = numberStates(gb); // Vacuous NFAs require special checks on their starts to ensure that tops // match, and that reports match for mixed-accept cases. if (!mergeableStarts(ga, gb)) { DEBUG_PRINTF("starts aren't mergeable\n"); return false; } u32 cpl = commonPrefixLength(ga, a_state_ids, gb, b_state_ids); if (!shouldMerge(gb, b_state_ids, ga, a_state_ids, cpl, rm, cc)) { return false; } mergeNfaComponent(gb, ga, cpl); reduceImplementableGraph(gb, SOM_NONE, rm, cc); b_state_ids = numberStates(gb); return true; }
QString TrackOrganizer::buildDestination(const QString& format, const Meta::TrackPtr& track) const { // get hold of the shared pointers Meta::AlbumPtr album = track->album(); Meta::ArtistPtr artist = track->artist(); Meta::ComposerPtr composer = track->composer(); Meta::ArtistPtr albumArtist = album ? album->albumArtist() : Meta::ArtistPtr(); Meta::GenrePtr genre = track->genre(); Meta::YearPtr year = track->year(); bool isCompilation = album && album->isCompilation(); QMap<QString, QString> args; QString strArtist = artist ? artist->name() : QString(); QString strAlbumArtist = isCompilation ? i18n( "Various Artists" ) : ( albumArtist ? albumArtist->name() : strArtist ); args["theartist"] = strArtist; args["thealbumartist"] = strAlbumArtist; if( m_postfixThe ) { Amarok::manipulateThe( strArtist, true ); Amarok::manipulateThe( strAlbumArtist, true ); } if ( track->trackNumber() ) { QString trackNum = QString("%1").arg( track->trackNumber(), 2, 10, QChar('0') ); args["track"] = trackNum; } args["title"] = track->name(); args["artist"] = strArtist; args["composer"] = composer ? composer->name() : QString(); // if year == 0 then we don't want include it QString strYear = year ? year->name() : QString(); args["year"] = strYear.localeAwareCompare( "0" ) == 0 ? QString() : strYear; args["album"] = track->album() ? track->album()->name() : QString(); args["albumartist"] = strAlbumArtist; args["comment"] = track->comment(); args["genre"] = genre ? genre->name() : QString(); if( m_targetFileExtension.isEmpty() ) args["filetype"] = track->type(); else args["filetype"] = m_targetFileExtension; QString strFolder = QFileInfo( track->playableUrl().toLocalFile() ).path(); strFolder = strFolder.mid( commonPrefixLength( m_folderPrefix, strFolder ) ); args["folder"] = strFolder; args["initial"] = strAlbumArtist.mid( 0, 1 ).toUpper(); //artists starting with The are already handled above if( track->discNumber() ) args["discnumber"] = QString::number( track->discNumber() ); args["collectionroot"] = m_folderPrefix; // some additional properties not supported by organize dialog. args["rating"] = track->statistics()->rating(); args["filesize"] = track->filesize(); args["length"] = track->length() / 1000; // Fill up default empty values for StringX formater // TODO make this values changeable by user args["default_album"] = i18n( "Unknown album" ); args["default_albumartist"] = i18n( "Unknown artist" ); args["default_artist"] = args["albumartist"]; args["default_thealbumartist"] = args["albumartist"]; args["default_theartist"] = args["albumartist"]; args["default_comment"] = i18n( "No comments" ); args["default_composer"] = i18n( "Unknown composer" ); args["default_discnumber"] = i18n( "Unknown disc number" ); args["default_genre"] = i18n( "Unknown genre" ); args["default_title"] = i18n( "Unknown title" ); args["default_year"] = i18n( "Unknown year" ); foreach( const QString &key, args.keys() ) if( key != "collectionroot" && key != "folder" ) args[key] = args[key].replace( '/', '-' ); Amarok::QStringx formatx( format ); QString result = formatx.namedOptArgs( args ); return cleanPath( result ); }
static never_inline void buildNfaMergeQueue(const vector<NGHolder *> &cluster, priority_queue<NfaMergeCandidateH> *pq) { const size_t cs = cluster.size(); assert(cs < NO_COMPONENT); // First, make sure all holders have numbered states and collect their // counts. vector<ue2::unordered_map<NFAVertex, u32>> states_map(cs); for (size_t i = 0; i < cs; i++) { assert(cluster[i]); NGHolder &g = *(cluster[i]); states_map[i] = numberStates(g); } vector<u16> seen_cpl(cs * cs, 0); vector<u32> best_comp(cs, NO_COMPONENT); /* TODO: understand, explain */ for (u32 ci = 0; ci < cs; ci++) { for (u32 cj = ci + 1; cj < cs; cj++) { u16 cpl = 0; bool calc = false; if (best_comp[ci] != NO_COMPONENT) { u32 bc = best_comp[ci]; if (seen_cpl[bc + cs * cj] < seen_cpl[bc + cs * ci]) { cpl = seen_cpl[bc + cs * cj]; DEBUG_PRINTF("using cached cpl from %u %u\n", bc, cpl); calc = true; } } if (!calc && best_comp[cj] != NO_COMPONENT) { u32 bc = best_comp[cj]; if (seen_cpl[bc + cs * ci] < seen_cpl[bc + cs * cj]) { cpl = seen_cpl[bc + cs * ci]; DEBUG_PRINTF("using cached cpl from %u %u\n", bc, cpl); calc = true; } } NGHolder &g_i = *(cluster[ci]); NGHolder &g_j = *(cluster[cj]); if (!compatibleStarts(g_i, g_j)) { continue; } if (!calc) { cpl = commonPrefixLength(g_i, states_map[ci], g_j, states_map[cj]); } seen_cpl[ci + cs * cj] = cpl; seen_cpl[cj + cs * ci] = cpl; if (best_comp[cj] == NO_COMPONENT || seen_cpl[best_comp[cj] + cs * cj] < cpl) { best_comp[cj] = ci; } DEBUG_PRINTF("cpl %u %u = %u\n", ci, cj, cpl); pq->push(NfaMergeCandidateH(cpl, cluster[ci], cluster[cj], ci * cs + cj)); } } }