/** 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;
}
Beispiel #2
0
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));
        }
    }
}