Make it so .sm files can contain \-escaped characters. Also, make the
writer for .dwi files replace control characters with dwi-safe characters. Other file formats are unaffected.
This commit is contained in:
@@ -39,7 +39,7 @@ static CourseDifficulty CRSStringToDifficulty( const RString& s )
|
||||
bool CourseLoaderCRS::LoadFromBuffer( const RString &sPath, const RString &sBuffer, Course &out )
|
||||
{
|
||||
MsdFile msd;
|
||||
msd.ReadFromString( sBuffer );
|
||||
msd.ReadFromString( sBuffer, false ); // don't unescape
|
||||
return LoadFromMsd( sPath, msd, out, true );
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ bool CourseLoaderCRS::LoadFromCRSFile( const RString &_sPath, Course &out )
|
||||
}
|
||||
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile(sPath) )
|
||||
if( !msd.ReadFile( sPath, false ) ) // don't unescape
|
||||
{
|
||||
|
||||
LOG->UserLog( "Course file", sPath, "couldn't be opened: %s.", msd.GetError().c_str() );
|
||||
@@ -389,7 +389,7 @@ bool CourseLoaderCRS::LoadEditFromFile( const RString &sEditFilePath, ProfileSlo
|
||||
}
|
||||
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sEditFilePath ) )
|
||||
if( !msd.ReadFile( sEditFilePath, false ) ) // don't unescape
|
||||
{
|
||||
LOG->UserLog( "Edit file", sEditFilePath, "couldn't be opened: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
|
||||
+49
-35
@@ -10,19 +10,15 @@
|
||||
* #VALUE:PARAM1
|
||||
* #VALUE2:PARAM2
|
||||
* we'll recover.
|
||||
*
|
||||
* TODO: Normal text fields need some way of escaping. We need to be able to escape
|
||||
* colons and "//". Also, we should escape #s, so if we really want to put a # at the
|
||||
* beginning of a line, we can.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "MsdFile.h"
|
||||
#include "RageFile.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageFile.h"
|
||||
|
||||
void MsdFile::AddParam( char *buf, int len )
|
||||
void MsdFile::AddParam( const char *buf, int len )
|
||||
{
|
||||
values.back().params.push_back( RString(buf, len) );
|
||||
}
|
||||
@@ -33,22 +29,21 @@ void MsdFile::AddValue() /* (no extra charge) */
|
||||
values.back().params.reserve( 32 );
|
||||
}
|
||||
|
||||
void MsdFile::ReadBuf( char *buf, int len )
|
||||
void MsdFile::ReadBuf( const char *buf, int len, bool bUnescape )
|
||||
{
|
||||
values.reserve( 64 );
|
||||
|
||||
int value_start = -1;
|
||||
|
||||
bool ReadingValue=false;
|
||||
int i = 0;
|
||||
char *cProcessed = new char[len];
|
||||
int iProcessedLen = -1;
|
||||
while( i < len )
|
||||
{
|
||||
if( i+1 < len && buf[i] == '/' && buf[i+1] == '/' )
|
||||
{
|
||||
/* //; erase with spaces until newline */
|
||||
/* Skip a comment entirely; don't copy the comment to the value/parameter */
|
||||
do
|
||||
{
|
||||
buf[i] = ' ';
|
||||
i++;
|
||||
} while( i < len && buf[i] != '\n' );
|
||||
|
||||
@@ -62,11 +57,14 @@ void MsdFile::ReadBuf( char *buf, int len )
|
||||
* missed the ;. Back up and end the value. */
|
||||
/* Make sure this # is the first non-whitespace character on the line. */
|
||||
bool FirstChar = true;
|
||||
int j;
|
||||
for( j = i-1; j >= 0 && !strchr("\r\n", buf[j]); --j )
|
||||
int j = iProcessedLen;
|
||||
while( j > 0 && cProcessed[j - 1] != '\r' && cProcessed[j - 1] != '\n' )
|
||||
{
|
||||
if(buf[j] == ' ' || buf[j] == '\t')
|
||||
if( cProcessed[j - 1] == ' ' || cProcessed[j - 1] == '\t' )
|
||||
{
|
||||
--j;
|
||||
continue;
|
||||
}
|
||||
|
||||
FirstChar = false;
|
||||
break;
|
||||
@@ -74,16 +72,20 @@ void MsdFile::ReadBuf( char *buf, int len )
|
||||
|
||||
if( !FirstChar )
|
||||
{
|
||||
/* Oops, we're not; handle this like a regular character. */
|
||||
i++;
|
||||
/* We're not the first char on a line. Treat it as if it were a normal character. */
|
||||
cProcessed[iProcessedLen++] = buf[i++];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip newlines and whitespace before adding the value. */
|
||||
while( j >= 1 && strchr("\r\n", buf[j-1]) )
|
||||
--j;
|
||||
iProcessedLen = j;
|
||||
while( iProcessedLen > 0 &&
|
||||
( cProcessed[iProcessedLen - 1] == '\r' || cProcessed[iProcessedLen - 1] == '\n' ||
|
||||
cProcessed[iProcessedLen - 1] == ' ' || cProcessed[iProcessedLen - 1] == '\t' ) )
|
||||
--iProcessedLen;
|
||||
|
||||
AddParam( buf+value_start, j - value_start );
|
||||
AddParam( cProcessed, iProcessedLen );
|
||||
iProcessedLen = 0;
|
||||
ReadingValue=false;
|
||||
}
|
||||
|
||||
@@ -96,36 +98,52 @@ void MsdFile::ReadBuf( char *buf, int len )
|
||||
|
||||
if( !ReadingValue )
|
||||
{
|
||||
i++;
|
||||
if( bUnescape && buf[i] == '\\' )
|
||||
i += 2;
|
||||
else
|
||||
++i;
|
||||
continue; /* nothing else is meaningful outside of a value */
|
||||
}
|
||||
|
||||
/* : and ; end the current param, if any. */
|
||||
if( value_start != -1 && (buf[i] == ':' || buf[i] == ';') )
|
||||
AddParam(buf+value_start, i - value_start);
|
||||
if( iProcessedLen != -1 && (buf[i] == ':' || buf[i] == ';') )
|
||||
AddParam( cProcessed, iProcessedLen );
|
||||
|
||||
/* # and : begin new params. */
|
||||
if( buf[i] == '#' || buf[i] == ':' )
|
||||
{
|
||||
i++; /* skip */
|
||||
value_start = i;
|
||||
++i;
|
||||
iProcessedLen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ; ends the current value. */
|
||||
if( buf[i] == ';' )
|
||||
{
|
||||
ReadingValue=false;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
/* We've gone through all the control characters. All that is left is either an escaped character,
|
||||
* ie \#, \\, \:, etc., or a regular character. */
|
||||
if( bUnescape && i < len && buf[i] == '\\' )
|
||||
++i;
|
||||
if( i < len )
|
||||
{
|
||||
cProcessed[iProcessedLen++] = buf[i++];
|
||||
}
|
||||
}
|
||||
|
||||
/* Add any unterminated value at the very end. */
|
||||
if( ReadingValue )
|
||||
AddParam( buf+value_start, i - value_start );
|
||||
AddParam( cProcessed, iProcessedLen );
|
||||
|
||||
delete [] cProcessed;
|
||||
}
|
||||
|
||||
// returns true if successful, false otherwise
|
||||
bool MsdFile::ReadFile( RString sNewPath )
|
||||
bool MsdFile::ReadFile( RString sNewPath, bool bUnescape )
|
||||
{
|
||||
error = "";
|
||||
|
||||
@@ -148,18 +166,14 @@ bool MsdFile::ReadFile( RString sNewPath )
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadBuf( (char*) FileString.c_str(), iBytesRead );
|
||||
ReadBuf( FileString.c_str(), iBytesRead, bUnescape );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MsdFile::ReadFromString( const RString &sString )
|
||||
void MsdFile::ReadFromString( const RString &sString, bool bUnescape )
|
||||
{
|
||||
/* Be careful. ReadBuf modifies the buffer given to it. */
|
||||
char *pCopy = new char[sString.size()];
|
||||
memcpy( pCopy, sString.data(), sString.size() );
|
||||
ReadBuf( pCopy, sString.size() );
|
||||
delete [] pCopy;
|
||||
ReadBuf( sString.c_str(), sString.size(), bUnescape );
|
||||
}
|
||||
|
||||
RString MsdFile::GetParam(unsigned val, unsigned par) const
|
||||
@@ -171,7 +185,7 @@ RString MsdFile::GetParam(unsigned val, unsigned par) const
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2001-2004 Chris Danford, Glenn Maynard
|
||||
* (c) 2001-2006 Chris Danford, Glenn Maynard
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
|
||||
@@ -17,8 +17,8 @@ public:
|
||||
virtual ~MsdFile() { }
|
||||
|
||||
// Returns true if successful, false otherwise.
|
||||
bool ReadFile( RString sFilePath );
|
||||
void ReadFromString( const RString &sString );
|
||||
bool ReadFile( RString sFilePath, bool bUnescape );
|
||||
void ReadFromString( const RString &sString, bool bUnescape );
|
||||
|
||||
RString GetError() const { return error; }
|
||||
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void ReadBuf( char *buf, int len );
|
||||
void AddParam( char *buf, int len );
|
||||
void ReadBuf( const char *buf, int len, bool bUnescape );
|
||||
void AddParam( const char *buf, int len );
|
||||
void AddValue();
|
||||
|
||||
vector<value_t> values;
|
||||
|
||||
@@ -362,7 +362,7 @@ bool DWILoader::LoadFromDWIFile( const RString &sPath, Song &out )
|
||||
m_sLoadingFile = sPath;
|
||||
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sPath ) )
|
||||
if( !msd.ReadFile( sPath, false ) ) // don't unescape
|
||||
{
|
||||
LOG->UserLog( "Song file", sPath, "couldn't be opened: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
|
||||
@@ -63,7 +63,7 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
||||
LOG->Trace( "Steps::LoadFromKSFFile( '%s' )", sPath.c_str() );
|
||||
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sPath ) )
|
||||
if( !msd.ReadFile( sPath, false ) ) // don't unescape
|
||||
{
|
||||
LOG->UserLog( "Song file", sPath, "couldn't be opened: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
@@ -334,7 +334,7 @@ void KSFLoader::LoadTags( const RString &str, Song &out )
|
||||
bool KSFLoader::LoadGlobalData( const RString &sPath, Song &out )
|
||||
{
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sPath ) )
|
||||
if( !msd.ReadFile( sPath, false ) ) // don't unescape
|
||||
{
|
||||
LOG->UserLog( "Song file", sPath, "couldn't be opened: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
|
||||
@@ -70,7 +70,7 @@ void SMLoader::GetApplicableFiles( const RString &sPath, vector<RString> &out )
|
||||
bool SMLoader::LoadTimingFromFile( const RString &fn, TimingData &out )
|
||||
{
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( fn ) )
|
||||
if( !msd.ReadFile( fn, true ) ) // unescape
|
||||
{
|
||||
LOG->UserLog( "Song file", fn, "couldn't be loaded: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
@@ -165,11 +165,13 @@ bool LoadFromBGChangesString( BackgroundChange &change, const RString &sBGChange
|
||||
{
|
||||
case 11:
|
||||
change.m_def.m_sColor2 = aBGChangeValues[10];
|
||||
change.m_def.m_sColor2.Replace( '^', ',' ); // UGLY: unescape "," in colors
|
||||
// .sm files made before we started escaping will still have '^' instead of ','
|
||||
change.m_def.m_sColor2.Replace( '^', ',' );
|
||||
// fall through
|
||||
case 10:
|
||||
change.m_def.m_sColor1 = aBGChangeValues[9];
|
||||
change.m_def.m_sColor1.Replace( '^', ',' ); // UGLY: unescape "," in colors
|
||||
// .sm files made before we started escaping will still have '^' instead of ','
|
||||
change.m_def.m_sColor1.Replace( '^', ',' );
|
||||
// fall through
|
||||
case 9:
|
||||
change.m_sTransition = aBGChangeValues[8];
|
||||
@@ -225,7 +227,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out )
|
||||
LOG->Trace( "Song::LoadFromSMFile(%s)", sPath.c_str() );
|
||||
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sPath ) )
|
||||
if( !msd.ReadFile( sPath, true ) ) // unescape
|
||||
{
|
||||
LOG->UserLog( "Song file", sPath, "couldn't be opened: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
@@ -462,7 +464,7 @@ bool SMLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool b
|
||||
}
|
||||
|
||||
MsdFile msd;
|
||||
if( !msd.ReadFile( sEditFilePath ) )
|
||||
if( !msd.ReadFile( sEditFilePath, true ) ) // unescape
|
||||
{
|
||||
LOG->UserLog( "Edit file", sEditFilePath, "couldn't be opened: %s", msd.GetError().c_str() );
|
||||
return false;
|
||||
@@ -474,7 +476,7 @@ bool SMLoader::LoadEditFromFile( RString sEditFilePath, ProfileSlot slot, bool b
|
||||
bool SMLoader::LoadEditFromBuffer( const RString &sBuffer, const RString &sEditFilePath, ProfileSlot slot )
|
||||
{
|
||||
MsdFile msd;
|
||||
msd.ReadFromString( sBuffer );
|
||||
msd.ReadFromString( sBuffer, true ); // unescape
|
||||
return LoadEditFromMsd( msd, sEditFilePath, slot, true );
|
||||
}
|
||||
|
||||
|
||||
@@ -356,16 +356,16 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
|
||||
}
|
||||
|
||||
/* Write transliterations, if we have them, since DWI doesn't support UTF-8. */
|
||||
f.PutLine( ssprintf("#TITLE:%s;", out.GetTranslitFullTitle().c_str()) );
|
||||
f.PutLine( ssprintf("#ARTIST:%s;", out.GetTranslitArtist().c_str()) );
|
||||
f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).c_str()) );
|
||||
f.PutLine( ssprintf("#ARTIST:%s;", DwiEscape(out.GetTranslitArtist()).c_str()) );
|
||||
ASSERT( out.m_Timing.m_BPMSegments[0].m_iStartIndex == 0 );
|
||||
f.PutLine( ssprintf("#FILE:%s;", out.m_sMusicFile.c_str()) );
|
||||
f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) );
|
||||
f.PutLine( ssprintf("#BPM:%.3f;", out.m_Timing.m_BPMSegments[0].GetBPM()) );
|
||||
f.PutLine( ssprintf("#GAP:%d;", int(-roundf( out.m_Timing.m_fBeat0OffsetInSeconds*1000 ))) );
|
||||
f.PutLine( ssprintf("#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds) );
|
||||
f.PutLine( ssprintf("#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds) );
|
||||
if( out.m_sCDTitleFile.size() )
|
||||
f.PutLine( ssprintf("#CDTITLE:%s;", out.m_sCDTitleFile.c_str()) );
|
||||
f.PutLine( ssprintf("#CDTITLE:%s;", DwiEscape(out.m_sCDTitleFile).c_str()) );
|
||||
switch( out.m_DisplayBPMType )
|
||||
{
|
||||
case Song::DISPLAY_ACTUAL:
|
||||
@@ -435,7 +435,7 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2001-2004 Chris Danford, Glenn Maynard
|
||||
* (c) 2001-2006 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
|
||||
static RString BackgroundChangeToString( const BackgroundChange &bgc )
|
||||
{
|
||||
// TODO: Technically we need to double-escape the filename (because it might contain '=') and then
|
||||
// unescape the value returned by the MsdFile.
|
||||
RString s = ssprintf(
|
||||
"%.3f=%s=%.3f=%d=%d=%d=%s=%s=%s=%s=%s",
|
||||
bgc.m_fStartBeat,
|
||||
bgc.m_def.m_sFile1.c_str(),
|
||||
SmEscape(bgc.m_def.m_sFile1).c_str(),
|
||||
bgc.m_fRate,
|
||||
bgc.m_sTransition == SBT_CrossFade, // backward compat
|
||||
bgc.m_def.m_sEffect == SBE_StretchRewind, // backward compat
|
||||
@@ -29,28 +31,27 @@ static RString BackgroundChangeToString( const BackgroundChange &bgc )
|
||||
bgc.m_def.m_sEffect.c_str(),
|
||||
bgc.m_def.m_sFile2.c_str(),
|
||||
bgc.m_sTransition.c_str(),
|
||||
bgc.m_def.m_sColor1.c_str(),
|
||||
bgc.m_def.m_sColor2.c_str()
|
||||
SmEscape(bgc.m_def.m_sColor1).c_str(),
|
||||
SmEscape(bgc.m_def.m_sColor2).c_str()
|
||||
);
|
||||
s.Replace( ',', '^' ); // UGLY: escape "," in colors.
|
||||
return s;
|
||||
}
|
||||
|
||||
static void WriteGlobalTags( RageFile &f, const Song &out )
|
||||
{
|
||||
f.PutLine( ssprintf( "#TITLE:%s;", out.m_sMainTitle.c_str() ) );
|
||||
f.PutLine( ssprintf( "#SUBTITLE:%s;", out.m_sSubTitle.c_str() ) );
|
||||
f.PutLine( ssprintf( "#ARTIST:%s;", out.m_sArtist.c_str() ) );
|
||||
f.PutLine( ssprintf( "#TITLETRANSLIT:%s;", out.m_sMainTitleTranslit.c_str() ) );
|
||||
f.PutLine( ssprintf( "#SUBTITLETRANSLIT:%s;", out.m_sSubTitleTranslit.c_str() ) );
|
||||
f.PutLine( ssprintf( "#ARTISTTRANSLIT:%s;", out.m_sArtistTranslit.c_str() ) );
|
||||
f.PutLine( ssprintf( "#GENRE:%s;", out.m_sGenre.c_str() ) );
|
||||
f.PutLine( ssprintf( "#CREDIT:%s;", out.m_sCredit.c_str() ) );
|
||||
f.PutLine( ssprintf( "#BANNER:%s;", out.m_sBannerFile.c_str() ) );
|
||||
f.PutLine( ssprintf( "#BACKGROUND:%s;", out.m_sBackgroundFile.c_str() ) );
|
||||
f.PutLine( ssprintf( "#LYRICSPATH:%s;", out.m_sLyricsFile.c_str() ) );
|
||||
f.PutLine( ssprintf( "#CDTITLE:%s;", out.m_sCDTitleFile.c_str() ) );
|
||||
f.PutLine( ssprintf( "#MUSIC:%s;", out.m_sMusicFile.c_str() ) );
|
||||
f.PutLine( ssprintf( "#TITLE:%s;", SmEscape(out.m_sMainTitle).c_str() ) );
|
||||
f.PutLine( ssprintf( "#SUBTITLE:%s;", SmEscape(out.m_sSubTitle).c_str() ) );
|
||||
f.PutLine( ssprintf( "#ARTIST:%s;", SmEscape(out.m_sArtist).c_str() ) );
|
||||
f.PutLine( ssprintf( "#TITLETRANSLIT:%s;", SmEscape(out.m_sMainTitleTranslit).c_str() ) );
|
||||
f.PutLine( ssprintf( "#SUBTITLETRANSLIT:%s;", SmEscape(out.m_sSubTitleTranslit).c_str() ) );
|
||||
f.PutLine( ssprintf( "#ARTISTTRANSLIT:%s;", SmEscape(out.m_sArtistTranslit).c_str() ) );
|
||||
f.PutLine( ssprintf( "#GENRE:%s;", SmEscape(out.m_sGenre).c_str() ) );
|
||||
f.PutLine( ssprintf( "#CREDIT:%s;", SmEscape(out.m_sCredit).c_str() ) );
|
||||
f.PutLine( ssprintf( "#BANNER:%s;", SmEscape(out.m_sBannerFile).c_str() ) );
|
||||
f.PutLine( ssprintf( "#BACKGROUND:%s;", SmEscape(out.m_sBackgroundFile).c_str() ) );
|
||||
f.PutLine( ssprintf( "#LYRICSPATH:%s;", SmEscape(out.m_sLyricsFile).c_str() ) );
|
||||
f.PutLine( ssprintf( "#CDTITLE:%s;", SmEscape(out.m_sCDTitleFile).c_str() ) );
|
||||
f.PutLine( ssprintf( "#MUSIC:%s;", SmEscape(out.m_sMusicFile).c_str() ) );
|
||||
f.PutLine( ssprintf( "#OFFSET:%.3f;", out.m_Timing.m_fBeat0OffsetInSeconds ) );
|
||||
f.PutLine( ssprintf( "#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds ) );
|
||||
f.PutLine( ssprintf( "#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds ) );
|
||||
@@ -164,11 +165,12 @@ static RString GetSMNotesTag( const Song &song, const Steps &in, bool bSavingCac
|
||||
vector<RString> lines;
|
||||
|
||||
lines.push_back( "" );
|
||||
// Escape to prevent some clown from making a comment of "\r\n;"
|
||||
lines.push_back( ssprintf("//---------------%s - %s----------------",
|
||||
GameManager::StepsTypeToString(in.m_StepsType).c_str(), in.GetDescription().c_str()) );
|
||||
GameManager::StepsTypeToString(in.m_StepsType).c_str(), SmEscape(in.GetDescription()).c_str()) );
|
||||
lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" );
|
||||
lines.push_back( ssprintf( " %s:", GameManager::StepsTypeToString(in.m_StepsType).c_str() ) );
|
||||
lines.push_back( ssprintf( " %s:", in.GetDescription().c_str() ) );
|
||||
lines.push_back( ssprintf( " %s:", SmEscape(in.GetDescription()).c_str() ) );
|
||||
lines.push_back( ssprintf( " %s:", DifficultyToString(in.GetDifficulty()).c_str() ) );
|
||||
lines.push_back( ssprintf( " %d:", in.GetMeter() ) );
|
||||
|
||||
|
||||
@@ -559,6 +559,55 @@ RString join( const RString &sDelimitor, vector<RString>::const_iterator begin,
|
||||
return sRet;
|
||||
}
|
||||
|
||||
RString SmEscape( const RString &sUnescaped )
|
||||
{
|
||||
return SmEscape( sUnescaped.c_str(), sUnescaped.size() );
|
||||
}
|
||||
|
||||
RString SmEscape( const char *cUnescaped, int len )
|
||||
{
|
||||
RString answer = "";
|
||||
for( int i = 0; i < len; ++i )
|
||||
{
|
||||
if( cUnescaped[i] == '=' || cUnescaped[i] == '\\' || cUnescaped[i] == ':' ||
|
||||
cUnescaped[i] == '[' || cUnescaped[i] == ']' || cUnescaped[i] == ';' ||
|
||||
cUnescaped[i] == '#' || cUnescaped[i] == '\r' || cUnescaped[i] == '\n' ||
|
||||
cUnescaped[i] == ',' )
|
||||
answer += "\\";
|
||||
answer += cUnescaped[i];
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
RString DwiEscape( const RString &sUnescaped )
|
||||
{
|
||||
return DwiEscape( sUnescaped.c_str(), sUnescaped.size() );
|
||||
}
|
||||
|
||||
RString DwiEscape( const char *cUnescaped, int len )
|
||||
{
|
||||
RString answer = "";
|
||||
for( int i = 0; i < len; ++i )
|
||||
{
|
||||
switch( cUnescaped[i] )
|
||||
{
|
||||
case '=': answer += '-'; break;
|
||||
case '\\':
|
||||
case ':':
|
||||
case '[':
|
||||
case ']':
|
||||
case ';': answer += 'I'; break;
|
||||
case '#':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case ',': answer += ' '; break;
|
||||
default: answer += cUnescaped[i];
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
template <class S>
|
||||
static int DelimitorLength( const S &Delimitor )
|
||||
{
|
||||
|
||||
@@ -406,6 +406,14 @@ void split( const wstring &sSource, const wstring &sDelimitor, int &iBegin, int
|
||||
RString join( const RString &sDelimitor, const vector<RString>& sSource );
|
||||
RString join( const RString &sDelimitor, vector<RString>::const_iterator begin, vector<RString>::const_iterator end );
|
||||
|
||||
// These methods escapes a string for saving in a .sm or .crs file
|
||||
RString SmEscape( const RString &sUnescaped );
|
||||
RString SmEscape( const char *cUnescaped, int len );
|
||||
|
||||
// These methods "escape" a string for .dwi by turning = into -, ] into I, etc. That is "lossy".
|
||||
RString DwiEscape( const RString &sUnescaped );
|
||||
RString DwiEscape( const char *cUnescaped, int len );
|
||||
|
||||
RString GetCwd();
|
||||
|
||||
void SetCommandlineArguments( int argc, char **argv );
|
||||
|
||||
@@ -272,7 +272,7 @@ void SongManager::LoadGroupSymLinks(RString sDir, RString sGroupFolder)
|
||||
for( unsigned s=0; s< arraySymLinks.size(); s++ ) // for each symlink in this dir, add it in as a song.
|
||||
{
|
||||
MsdFile msdF;
|
||||
msdF.ReadFile( sDir+sGroupFolder+"/"+arraySymLinks[s].c_str() );
|
||||
msdF.ReadFile( sDir+sGroupFolder+"/"+arraySymLinks[s].c_str(), false ); // don't unescape
|
||||
RString sSymDestination = msdF.GetParam(0,1); // Should only be 1 vale¶m...period.
|
||||
|
||||
Song* pNewSong = new Song;
|
||||
|
||||
Reference in New Issue
Block a user