libraries/iosrv/client/file_utils.cpp
changeset 0 7f656887cf89
child 50 e81b4e28b3e2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/iosrv/client/file_utils.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,513 @@
+// 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));
+	}
+