You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k3b/src/rip/k3bpatternparser.cpp

306 lines
8.7 KiB

/*
*
* $Id: k3bpatternparser.cpp 619556 2007-01-03 17:38:12Z trueg $
* Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
* Copyright (C) 2004-2005 Jakob Petsovits <jpetso@gmx.at>
*
* This file is part of the K3b project.
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
*
* This program 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 2 of the License, or
* (at your option) any later version.
* See the file "COPYING" for the exact licensing terms.
*/
#include "k3bpatternparser.h"
#include <tqregexp.h>
#include <tqdatetime.h>
#include <tqvaluestack.h>
#include <tdeglobal.h>
#include <tdelocale.h>
TQString K3bPatternParser::parsePattern( const K3bCddbResultEntry& entry,
unsigned int trackNumber,
const TQString& pattern,
bool replace,
const TQString& replaceString )
{
if( entry.titles.count() < trackNumber )
return "";
TQString dir, s;
char c = ' '; // contains the character representation of a special string
unsigned int len; // length of the current special string
for( unsigned int i = 0; i < pattern.length(); ++i ) {
if( pattern[i] == '%' ) {
if( i + 1 < pattern.length() ) {
len = 2;
if( pattern[i+1] != '{' ) { // strings like %a
c = pattern[i+1];
}
else if( i + 3 >= pattern.length() ) { // too short to contain a %{*} string
c = ' ';
}
else { // long enough to contain %{*}
if( pattern[i+3] == '}' ) { // strings like %{a}
c = pattern[i+2];
len = 4;
}
else { // strings like %{artist}, or anything like %{*
while( i + len - 1 < pattern.length() ) {
++len;
if( pattern[i + len - 1] == '%' ) { // don't touch other special strings
c = ' ';
--len;
break;
}
else if( pattern[i + len - 1] == '}' ) {
s = pattern.mid( i + 2, len - 3 );
if( s == "title" ) {
c = TITLE;
}
else if( s == "artist" ) {
c = ARTIST;
}
else if( s == "number" ) {
c = NUMBER;
}
else if( s == "comment" ) {
c = COMMENT;
}
else if( s == "year" ) {
c = YEAR;
}
else if( s == "genre" ) {
c = GENRE;
}
else if( s == "albumtitle" ) {
c = ALBUMTITLE;
}
else if( s == "albumartist" ) {
c = ALBUMARTIST;
}
else if( s == "albumcomment" ) {
c = ALBUMCOMMENT;
}
else if( s == "date" ) {
c = DATE;
}
else { // no valid pattern in here, don't replace anything
c = ' ';
}
break; // finished parsing %{* string
}
} // end of while(...)
} // end of %{* strings
} // end of if( long enough to contain %{*} )
switch( c ) {
case ARTIST:
s = entry.artists[trackNumber-1];
s.replace( '/', '_' );
s.replace( '*', '_' );
s.replace( '}', '*' ); // for conditional inclusion
dir.append( s.isEmpty()
? i18n("unknown") + TQString(" %1").arg(trackNumber)
: s );
break;
case TITLE:
s = entry.titles[trackNumber-1];
s.replace( '/', '_' );
s.replace( '*', '_' );
s.replace( '}', '*' );
dir.append( s.isEmpty()
? i18n("Track %1").arg(trackNumber)
: s );
break;
case NUMBER:
dir.append( TQString::number(trackNumber).rightJustify( 2, '0' ) );
break;
case YEAR:
dir.append( TQString::number( entry.year ) );
break;
case COMMENT:
s = entry.extInfos[trackNumber-1];
s.replace( '/', '_' );
s.replace( '*', '_' );
s.replace( '}', '*' );
dir.append( s );
break;
case GENRE:
s = ( entry.genre.isEmpty() ? entry.category : entry.genre );
s.replace( '/', '_' );
s.replace( '*', '_' );
s.replace( '}', '*' );
dir.append( s );
break;
case ALBUMARTIST:
dir.append( entry.cdArtist.isEmpty()
? i18n("unknown") : entry.cdArtist );
break;
case ALBUMTITLE:
s = entry.cdTitle;
s.replace( '/', '_' );
s.replace( '*', '_' );
s.replace( '}', '*' );
dir.append( s.isEmpty()
? i18n("unknown") : s );
break;
case ALBUMCOMMENT:
s = entry.cdExtInfo;
s.replace( '/', '_' );
s.replace( '*', '_' );
s.replace( '}', '*' );
dir.append( s ); // I think it makes more sense to allow empty comments
break;
case DATE:
dir.append( TDEGlobal::locale()->formatDate( TQDate::currentDate() ) );
break;
default:
dir.append( pattern.mid(i, len) );
break;
}
i += len - 1;
}
else { // end of pattern
dir.append( "%" );
}
}
else {
dir.append( pattern[i] );
}
}
// /* delete line comment to comment out
// the following part: Conditional Inclusion
TQValueStack<int> offsetStack;
TQString inclusion;
bool isIncluded;
static TQRegExp conditionrx( "^[@|!][atyegrmx](?:='.*')?\\{" );
conditionrx.setMinimal( TRUE );
for( unsigned int i = 0; i < dir.length(); ++i ) {
offsetStack.push(
conditionrx.search(dir, i, TQRegExp::CaretAtOffset) );
if( offsetStack.top() == -1 ) {
offsetStack.pop();
}
else {
i += conditionrx.matchedLength() - 1;
continue;
}
if( dir[i] == '}' && !offsetStack.isEmpty() ) {
int offset = offsetStack.pop();
int length = i - offset + 1;
switch( (TQChar) dir[offset+1] ) {
case ARTIST:
s = entry.artists[trackNumber-1];
break;
case TITLE:
s = entry.titles[trackNumber-1];
break;
case NUMBER:
s = TQString::number( trackNumber );
break;
case YEAR:
s = TQString::number( entry.year );
break;
case COMMENT:
s = entry.extInfos[trackNumber-1];
break;
case GENRE:
s = ( entry.genre.isEmpty() ? entry.category : entry.genre );
break;
case ALBUMARTIST:
s = entry.cdArtist;
break;
case ALBUMTITLE:
s = entry.cdTitle;
break;
case ALBUMCOMMENT:
s = entry.cdExtInfo;
break;
case DATE:
s = TDEGlobal::locale()->formatDate( TQDate::currentDate() );
break;
default: // we must never get here,
break; // all choices should be covered
}
if( dir[offset+2] == '{' ) { // no string matching, e.g. ?y{text}
switch( (TQChar) dir[offset+1] ) {
case YEAR:
isIncluded = (s != "0");
break;
default:
isIncluded = !s.isEmpty();
break;
}
inclusion = dir.mid( offset + 3, length - 4 );
}
else { // with string matching, e.g. ?y='2004'{text}
// Be aware that there might be ' in the condition text
int endOfCondition = dir.find( '{', offset+4 )-1;
TQString condition = dir.mid( offset+4,
endOfCondition - (offset+4) );
isIncluded = (s == condition);
inclusion = dir.mid( endOfCondition+2,
i - (endOfCondition+2) );
}
if( dir[offset] == '!' )
isIncluded = !isIncluded;
// Leave it when it's '@'.
dir.replace( offset, length, ( isIncluded ? inclusion : TQString("") ) );
if( isIncluded == TRUE )
i -= length - inclusion.length();
else
i = offset - 1; // start next loop at offset
continue;
} // end of replace (at closing bracket '}')
} // end of conditional inclusion for(...)
// end of Conditional Inclusion */
dir.replace( '*', '}' ); // bring the brackets back, if there were any
if( replace )
dir.replace( TQRegExp( "\\s" ), replaceString );
return dir;
}