securityanddataprivacytools/securitytools/certapp/utils/filestream.cpp
author tahirm@symbian.org
Tue, 29 Sep 2009 14:16:08 +0100
branchRCL_1
changeset 7 1d329321bec7
parent 0 2c201484c85f
child 8 35751d3474b7
permissions -rw-r--r--
Created branch for release codeline RCL_1, for maintenance changes to the Symbian^2 platform

/*
* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#include "filestream_private.h"
#include "logger.h"
#include "stringconv.h"
#include "utils.h"

FileStreamBuf::FileStreamBuf(const std::string &aFileName, bool aWritable, bool aSpecialTextHandling)
	: iWritable(aWritable), iSpecialTextHandling(aSpecialTextHandling)
{
	if(iWritable)
		{
		OpenUtf8FStreamForWrite(iFile, aFileName.c_str());
		}
	else
		{
		OpenUtf8FStreamForRead(iFile, aFileName.c_str());
		}
	if(iFile.fail())
		{
		dbg << Log::Indent() << "Failed to open '" << aFileName << "' for " << ((iWritable)?("output"):("input")) << "!" << Log::Endl();
		FatalError();
		}
	
}

static const char utf8Header[] = 
	{
		0xef, 0xbb, 0xbf
	};

static const char utf16HeaderBig[] = 
	{
		0xfe, 0xff
	};

static const char utf16HeaderLittle[] = 
	{
		0xff, 0xfe
	};

void FileStreamBuf::StripUtf8HeaderIfPresent()
{
	if(iWritable)
		{
		FatalError(); // Coding error
		}

	std::streampos savedPos = iFile.tellg();
	char header[3];
	iFile.read(header, sizeof(header));
	
	if(iFile.good() && memcmp(header, utf8Header, sizeof(utf8Header)) == 0)
		{
		// We read a UTF8 file header so simply return (and thereby skip it).
		return;
		}

	if(iFile.good() && memcmp(header, utf16HeaderBig, sizeof(utf16HeaderBig)) == 0)
		{
		dbg << Log::Indent() << "Input file is Big Endian UTF16 - Only UTF-8 and ASCII are supported" << Log::Endl();
		FatalError();
		}
	if(iFile.good() && memcmp(header, utf16HeaderLittle, sizeof(utf16HeaderLittle)) == 0)
		{
		dbg << Log::Indent() << "Input file is Little Endian UTF16 - Only UTF-8 and ASCII are supported" << Log::Endl();
		FatalError();
		}

	iFile.clear();
	iFile.seekg(savedPos);
}


TInt FileStreamBuf::DoReadL(TAny *aPtr,TInt aMaxLength)
{
BULLSEYE_OFF
	if(iFile.fail())
		{
		dbg << Log::Indent() << "Read error" << Log::Endl();
		FatalError(); // Read on broken stream
		}
BULLSEYE_RESTORE

	iFile.read((char *)aPtr, aMaxLength);
    
	if(iFile.eof())
		{
		dbg << Log::Indent() << "Encountered EOF" << Log::Endl();
		TInt len = iFile.gcount();
		if(iSpecialTextHandling)
			{
			// Add a synthetic NL to the returned data to handle a
			// token immediately before the EOF
			((TUint8 *)aPtr)[len++] = '\n';
			}
		return len;
		}

BULLSEYE_OFF
	if(iFile.fail())
		{
		dbg << Log::Indent() << "Read error" << Log::Endl();
		FatalError(); // error other than EOF
		}
BULLSEYE_RESTORE

	return iFile.gcount();
}

void FileStreamBuf::DoWriteL(const TUint8* aPtr,TInt aLength)
{
	iFile.write((const char *)aPtr, aLength);
BULLSEYE_OFF
	if(iFile.fail())
		{
		FatalError(); // error other than EOF
		}
BULLSEYE_RESTORE
	//#warning "flush all data for debugging"
	//	iFile.flush();
}

TStreamPos FileStreamBuf::DoSeekL(TMark aMark,TStreamLocation aLocation,TInt anOffset)
{
	std::ios_base::seekdir dir;
	switch(aLocation)
		{
		case EStreamBeginning:
			dir = std::ios_base::beg;
			break;
		case EStreamMark:
			dir = std::ios_base::cur;
			break;
		case EStreamEnd:
			dir = std::ios_base::end;
			break;
BULLSEYE_OFF
		default:
			FatalError();
BULLSEYE_RESTORE
		}

	if(aMark == ERead)
		{
		iFile.seekg(anOffset, dir);
BULLSEYE_OFF
		if(iFile.fail()) FatalError(); // error other than EOF
BULLSEYE_RESTORE
		return iFile.tellg();
		}

	if(aMark == EWrite)
		{
		iFile.seekp(anOffset, dir);
BULLSEYE_OFF
		if(iFile.fail()) FatalError(); // error other than EOF
BULLSEYE_RESTORE
		return iFile.tellp();
		}
	
	FatalError();
	return -1;
}

void FileStreamBuf::DoRelease()
{
	iFile.close();
}

FileWriteStream::FileWriteStream(const std::string &aFileName)
	: RWriteStream()
{
	iSnk = new FileStreamBuf(aFileName, true);
}

FileWriteStream::~FileWriteStream()
{
BULLSEYE_OFF
	if(iSnk)
		{
		dbg << Log::Indent() << "forgot to close FileWriteStream" << Log::Endl();
		FatalError();
		}
BULLSEYE_RESTORE
	iSnk = 0;
}



FileReadStream::FileReadStream(const std::string &aFileName, bool aSpecialTextHandling)
	: RReadStream()
{
	iSrc = new FileStreamBuf(aFileName, false, aSpecialTextHandling);
	if(aSpecialTextHandling)
		{
		static_cast<FileStreamBuf *>(iSrc)->StripUtf8HeaderIfPresent();
		}
}


FileReadStream::~FileReadStream()
{
BULLSEYE_OFF
	if(iSrc)
		{
		dbg << Log::Indent() << "forgot to close FileReadStream" << Log::Endl();
		FatalError();
		}
BULLSEYE_RESTORE
	iSrc = 0;
}

// End of file