Minor fixes.
* Fixed some static anaylsis warnings
* Fixed armv5smp build re topsampler
* Changed 'more' command to understand CTRL-C
// file_utils.cpp
//
// Copyright (c) 2006 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Accenture - Initial contribution
//
#include <e32base.h>
#include <f32file.h>
#include "ioutils.h"
using namespace IoUtils;
//
// Constants.
//
_LIT(KSlash, "\\");
_LIT(KDoubleSlash, "\\\\");
_LIT(KDot, ".");
_LIT(KDoubleDot, "..");
__ASSERT_COMPILE(sizeof(TFileName2) == sizeof(TFileName) + 4);
//
// TFileName2.
//
EXPORT_C TFileName2::TFileName2()
{
new(this) TFileName2(EFile);
}
EXPORT_C TFileName2::TFileName2(TType aType)
{
new(this) TFileName2(KNullDesC, aType);
}
EXPORT_C TFileName2::TFileName2(const TDesC& aName)
: TBuf<256>(aName), iType(EFile)
{
new(this) TFileName2(aName, EFile);
}
EXPORT_C TFileName2::TFileName2(const TDesC& aName, TType aType)
: TBuf<256>(aName), iType(aType)
{
// Remove any double slashes that may be present.
TInt pos;
while ((pos = Find(KDoubleSlash)) >= 0)
{
Delete(pos, 1);
}
}
EXPORT_C TBool TFileName2::IsAbsolute() const
{
return ((Length() >= 3) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':') && ((*this)[2] == '\\'));
}
EXPORT_C TBool TFileName2::IsDriveLetter() const
{
return (Length() == 2) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':');
}
EXPORT_C TBool TFileName2::IsDriveRoot() const
{
return ((Length() == 3) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':') && ((*this)[2] == '\\'));
}
EXPORT_C TBool TFileName2::IsWild() const
{
return TParsePtrC(*this).IsWild();
}
EXPORT_C TBool TFileName2::IsFile() const
{
TBool ret = (iType == EFile);
ASSERT((ret && !HasTrailingSlash()) || (!ret && HasTrailingSlash()));
return ret;
}
EXPORT_C TBool TFileName2::IsDir() const
{
TBool ret = (iType == EDirectory);
ASSERT((ret && HasTrailingSlash()) || (!ret && !HasTrailingSlash()));
return ret;
}
EXPORT_C TBool TFileName2::HasDriveLetter() const
{
return ((Length() >= 2) && TChar((*this)[0]).IsAlpha() && ((*this)[1] == ':'));
}
EXPORT_C TBool TFileName2::HasLeadingSlash() const
{
return ((Length() >= 1) && ((*this)[0] == '\\'));
}
EXPORT_C TBool TFileName2::HasTrailingSlash() const
{
return ((Length() >= 1) && ((*this)[Length() - 1] == '\\'));
}
EXPORT_C TPtrC TFileName2::Drive() const
{
return TParsePtrC(*this).Drive();
}
EXPORT_C TPtrC TFileName2::Path() const
{
return TParsePtrC(*this).Path();
}
EXPORT_C TPtrC TFileName2::DriveAndPath() const
{
return TParsePtrC(*this).DriveAndPath();
}
EXPORT_C TPtrC TFileName2::Name() const
{
return TParsePtrC(*this).Name();
}
EXPORT_C TPtrC TFileName2::Ext() const
{
return TParsePtrC(*this).Ext();
}
EXPORT_C TPtrC TFileName2::NameAndExt() const
{
return TParsePtrC(*this).NameAndExt();
}
EXPORT_C void TFileName2::SetL(const TFileName2& aName)
{
Zero();
AppendComponentL(aName);
}
EXPORT_C void TFileName2::SetTypeL(TType aType)
{
switch (aType)
{
case EFile:
{
if (HasTrailingSlash() && ((HasDriveLetter() && (Length() > 3)) || (!HasDriveLetter() && (Length() > 1))))
{
Delete(Length() - 1, 1);
}
iType = EFile;
break;
}
case EDirectory:
{
if (!HasTrailingSlash())
{
AppendComponentL(KNullDesC());
}
iType = EDirectory;
break;
}
default:
{
ASSERT(EFalse);
}
}
}
EXPORT_C void TFileName2::SetTypeL(RFs& aFs)
{
if (IsDirL(aFs))
{
SetTypeL(EDirectory);
}
else
{
SetTypeL(EFile);
}
}
EXPORT_C void TFileName2::SetDriveL(const TDesC& aDrive)
{
if (Drive().Length() > 0)
{
(*this)[0] = aDrive[0];
}
else
{
PrependL(aDrive);
}
}
EXPORT_C void TFileName2::SetPathL(const TDesC& aPath)
{
TFileName2 temp;
temp.SetDriveL(Drive());
temp.AppendComponentL(aPath);
temp.SetNameAndExtL(NameAndExt());
Copy(temp);
}
EXPORT_C void TFileName2::SetNameL(const TDesC& aName)
{
TPtrC namePtrC(Name());
if (namePtrC.Length() > 0)
{
CheckSpaceL(aName.Length() - namePtrC.Length());
TInt namePos = namePtrC.Ptr() - Ptr();
Delete(namePos, namePtrC.Length());
Insert(namePos, aName);
}
else
{
AppendComponentL(aName);
}
}
EXPORT_C void TFileName2::SetExtL(const TDesC& aExt)
{
TPtrC extPtrC(Ext());
if (extPtrC.Length() > 0)
{
CheckSpaceL(aExt.Length() + ((aExt[0] == '.') ? 0 : 1) - extPtrC.Length());
Delete(extPtrC.Ptr() - Ptr(), extPtrC.Length());
}
else
{
CheckSpaceL(aExt.Length() + ((aExt[0] == '.') ? 0 : 1));
}
if (aExt[0] != '.')
{
Append('.');
}
Append(aExt);
}
EXPORT_C void TFileName2::SetNameAndExtL(const TDesC& aNameAndExt)
{
TPtrC nameAndExtPtrC(NameAndExt());
if (nameAndExtPtrC.Length() > 0)
{
CheckSpaceL(aNameAndExt.Length() - nameAndExtPtrC.Length());
TInt nameAndExtPos = nameAndExtPtrC.Ptr() - Ptr();
Delete(nameAndExtPos, nameAndExtPtrC.Length());
Insert(nameAndExtPos, aNameAndExt);
}
else
{
AppendComponentL(aNameAndExt);
}
}
EXPORT_C void TFileName2::PrependL(const TFileName2& aName)
{
if (Length() == 0)
{
CheckSpaceL(aName.Length() + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
Append(aName);
}
else if (aName.HasTrailingSlash() && HasLeadingSlash())
{
CheckSpaceL(aName.Length() - 1 + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
Insert(0, aName.Mid(1));
}
else if (!aName.HasTrailingSlash() && !HasLeadingSlash())
{
CheckSpaceL(aName.Length() + 1 + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
Insert(0, KSlash);
Insert(0, aName);
}
else
{
CheckSpaceL(aName.Length() + (((iType == EDirectory) && !HasTrailingSlash()) ? 1 : 0));
Insert(0, aName);
}
if ((iType == EDirectory) && (!HasTrailingSlash()))
{
Append(KSlash);
}
}
EXPORT_C void TFileName2::AppendComponentL(const TFileName2& aName)
{
AppendComponentL(aName, iType);
}
EXPORT_C void TFileName2::AppendComponentL(const TDesC& aPathComponent, TFileName2::TType aType)
{
// This function doesn't use iType, therefore you can call it and get the same results regardless of whether the type has been set - you will only get a trailing slash if (a) aPathComponent ends in a slash, or (b) aType is EDirectory.
TPtrC pathWithoutLeadingSlash(aPathComponent);
if (aPathComponent.Length() && aPathComponent[0] == '\\') pathWithoutLeadingSlash.Set(aPathComponent.Mid(1));
TInt pathLen = pathWithoutLeadingSlash.Length();
const TDesC* middle = &KNullDesC;
if (Length() && !HasTrailingSlash()) middle = &KSlash;
const TDesC* end = &KNullDesC;
if (aType == EDirectory && pathLen && pathWithoutLeadingSlash[pathLen-1] != '\\') end = &KSlash;
CheckSpaceL(pathLen + middle->Length() + end->Length());
Append(*middle);
Append(pathWithoutLeadingSlash);
Append(*end);
}
EXPORT_C void TFileName2::AppendComponentL(const TEntry& aEntry)
{
AppendComponentL(aEntry.iName, aEntry.IsDir() ? EDirectory : EFile);
}
EXPORT_C void TFileName2::SetIsDirectoryL()
{
// This is the more complicated way to do it, the other would be: if (!HasTrailingSlash()) AppendL(KSlash);
// Or indeed, AppendComponentL(KNullDesC, EDirectory) since the type is irrelevant if the component is empty
AppendComponentL(KNullDesC, EFile);
}
void TFileName2::CheckSpaceL(TInt aLengthToAdd) const
{
if ((MaxLength() - Length()) < aLengthToAdd)
{
User::Leave(KErrTooBig);
}
}
EXPORT_C void TFileName2::SplitL(RArray<TFileName2>& aOutput)
{
TLex lex(*this);
while (!lex.Eos())
{
lex.Mark();
while (!lex.Eos() && (lex.Peek() != '\\'))
{
lex.Get();
}
User::LeaveIfError(aOutput.Append(TFileName2(lex.MarkedToken())));
if (!lex.Eos())
{
// Skip over the slash
lex.Get();
if (lex.Eos())
{
// ended with slash - insert empty path component
User::LeaveIfError(aOutput.Append(TFileName2()));
}
}
}
}
EXPORT_C void TFileName2::MakeAbsoluteL(const TFileName2& aAbsoluteTo)
{
ASSERT(aAbsoluteTo.IsAbsolute());
if (IsAbsolute())
{
return;
}
if (HasLeadingSlash())
{
// Just prepend drive letter.
PrependL(aAbsoluteTo.Left(2));
return;
}
PrependL(aAbsoluteTo);
RArray<TFileName2> splitName;
CleanupClosePushL(splitName);
SplitL(splitName);
TInt i = 0;
while (i < splitName.Count())
{
const TFileName2& piece = splitName[i];
if (piece == KDot)
{
splitName.Remove(i);
}
else if (piece == KDoubleDot)
{
if ((i == 0) || ((i == 1) && splitName[0].IsDriveLetter()))
{
User::Leave(KErrBadName);
}
splitName.Remove(i);
splitName.Remove(i - 1);
--i;
}
else if ((piece == KNullDesC) && (i != 0) && (i != splitName.Count()-1))
{
// Allow empty piece in first or last slot to support leading/trailing slashes.
splitName.Remove(i);
}
else
{
++i;
}
}
UnsplitL(splitName);
CleanupStack::PopAndDestroy(&splitName);
}
EXPORT_C void TFileName2::MakeAbsoluteL(RFs& aFs)
{
TFileName2 sessionPath;
User::LeaveIfError(aFs.SessionPath(sessionPath));
MakeAbsoluteL(sessionPath);
}
EXPORT_C void TFileName2::UnsplitL(const RArray<TFileName2>& aInput)
{
Zero();
const TInt count = aInput.Count();
for (TInt i = 0; i < count; ++i)
{
AppendComponentL(aInput[i]);
}
if ((count == 1) && (aInput[0].Match(_L("?:")) == 0))
{
Append(KSlash);
}
}
EXPORT_C TBool TFileName2::Exists(RFs& aFs) const
{
TInt err;
if (IsDriveRoot())
{
TInt driveNumber;
err = RFs::CharToDrive(Drive()[0], driveNumber);
if (err == KErrNone)
{
TDriveInfo driveInfo;
err = aFs.Drive(driveInfo, driveNumber);
}
}
else
{
TUint att;
err = aFs.Att(*this, att);
}
return (err == KErrNone);
}
EXPORT_C TBool TFileName2::IsReadOnlyL(RFs& aFs) const
{
TEntry entry;
User::LeaveIfError(aFs.Entry(*this, entry));
return entry.IsReadOnly();
}
EXPORT_C TBool TFileName2::IsHiddenL(RFs& aFs) const
{
TEntry entry;
User::LeaveIfError(aFs.Entry(*this, entry));
return entry.IsHidden();
}
EXPORT_C TBool TFileName2::IsSystemL(RFs& aFs) const
{
TEntry entry;
User::LeaveIfError(aFs.Entry(*this, entry));
return entry.IsSystem();
}
EXPORT_C TBool TFileName2::IsDirL(RFs& aFs) const
{
if (IsDriveRoot())
{
if (!Exists(aFs))
{
User::Leave(KErrNotFound);
}
return ETrue;
}
else
{
TEntry entry;
User::LeaveIfError(aFs.Entry(*this, entry));
return entry.IsDir();
}
}
EXPORT_C TBool TFileName2::IsArchiveL(RFs& aFs) const
{
TEntry entry;
User::LeaveIfError(aFs.Entry(*this, entry));
return entry.IsArchive();
}
EXPORT_C TInt TFileName2::FindFile(RFs& aFs)
{
TFindFile ff(aFs);
TInt err = ff.FindByDir(*this, KNullDesC);
if (err==KErrNone)
{
*this = ff.File();
}
return err;
}
EXPORT_C void TFileName2::FindFileL(RFs& aFs)
{
User::LeaveIfError(FindFile(aFs));
}
EXPORT_C void TFileName2::Normalize(RFs& aFs)
{
// Change this so that the case of each component matches what the file system reckons. ie C:\SYS\Bin would be changed to c:\sys\bin
ASSERT(IsAbsolute());
TInt err = KErrNone;
TEntry entry;
TParse parse;
parse.Set(*this, NULL, NULL);
while (!err)
{
err = aFs.Entry(parse.FullName(), entry);
if (!err) err = parse.PopDir();
if (!err)
{
Replace(parse.FullName().Length(), entry.iName.Length(), entry.iName);
}
}
}