Pulled in from FCL: input, base64, fshell thread pool
Also:
* fed console size fixes
* fzip smoketest
* CBtraceAppStart
// base64.cpp
//
// Copyright (c) 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 <fshell/ioutils.h>
#include <fshell/common.mmh>
using namespace IoUtils;
const TInt KBlockSize = 512;
const TInt KLineLength = 76;
const TUint8 KBase64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const TUint8 KPadCharacter = '=';
const TUint8 KInvBase64[] =
{
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x3e,
0x0,
0x0,
0x0,
0x3f,
0x34,
0x35,
0x36,
0x37,
0x38,
0x39,
0x3a,
0x3b,
0x3c,
0x3d,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x1,
0x2,
0x3,
0x4,
0x5,
0x6,
0x7,
0x8,
0x9,
0xa,
0xb,
0xc,
0xd,
0xe,
0xf,
0x10,
0x11,
0x12,
0x13,
0x14,
0x15,
0x16,
0x17,
0x18,
0x19,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x1a,
0x1b,
0x1c,
0x1d,
0x1e,
0x1f,
0x20,
0x21,
0x22,
0x23,
0x24,
0x25,
0x26,
0x27,
0x28,
0x29,
0x2a,
0x2b,
0x2c,
0x2d,
0x2e,
0x2f,
0x30,
0x31,
0x32,
0x33
};
_LIT(KNewLine, "\r\n");
_LIT(KCr, "\r");
_LIT(KLf, "\n");
class CCmdBase64 : public CCommandBase
{
public:
static CCommandBase* NewLC();
~CCmdBase64();
private:
CCmdBase64();
void DecodeL();
void EncodeL();
private: // From CCommandBase.
virtual const TDesC& Name() const;
virtual void DoRunL();
virtual void ArgumentsL(RCommandArgumentList& aArguments);
virtual void OptionsL(RCommandOptionList& aOptions);
private:
enum
{
EDecode,
EEncode
} iOperation;
TFileName2 iFileName;
TBool iVerbose;
TBool iOverwrite;
};
EXE_BOILER_PLATE(CCmdBase64)
CCommandBase* CCmdBase64::NewLC()
{
CCmdBase64* self = new(ELeave) CCmdBase64();
CleanupStack::PushL(self);
self->BaseConstructL();
return self;
}
CCmdBase64::~CCmdBase64()
{
}
CCmdBase64::CCmdBase64()
{
}
void CCmdBase64::DecodeL()
{
if (!iOverwrite)
{
LeaveIfFileExists(iFileName);
}
User::LeaveIfError(Stdin().CaptureAllKeys()); // To iosrv buffering incoming data if we're not keeping up.
Stdin().SetReadModeL(RIoReadHandle::ELine);
RFile file;
LeaveIfErr(file.Replace(FsL(), iFileName, EFileWrite | EFileStream), _L("Unabled to open '%S' for writing"), &iFileName);
CleanupClosePushL(file);
TBuf<KLineLength + 2> lineBuf;
TBuf8<(KLineLength / 4) * 3> outputBuf;
TBool finished(EFalse);
TBool started(EFalse);
while (!finished)
{
TInt err = Stdin().Read(lineBuf);
if (err == KErrNone)
{
if (iVerbose)
{
Printf(_L("Read %d chars:\r\n'%S'\r\n"), lineBuf.Length(), &lineBuf);
}
if ((lineBuf == KNewLine) || (lineBuf == KCr) || (lineBuf == KLf))
{
if (started)
{
finished = ETrue;
}
}
else
{
if (lineBuf.Right(2) == KNewLine)
{
lineBuf.SetLength(lineBuf.Length() - 2);
}
if ((lineBuf.Right(1) == KCr) || (lineBuf.Right(1) == KLf))
{
lineBuf.SetLength(lineBuf.Length() - 1);
}
const TInt lineLength = lineBuf.Length();
if ((lineLength % 4) > 0)
{
LeaveIfErr(KErrArgument, _L("Invalid base 64 encoded line (not a multiple of 4 characters in length):\r\n%S\r\n"), &lineBuf);
}
started = ETrue;
outputBuf.Zero();
for (TInt i = 0; i < lineLength; i += 4)
{
TInt n = ((TInt)KInvBase64[lineBuf[i]] << 18) + ((TInt)KInvBase64[lineBuf[i + 1]] << 12) + ((TInt)KInvBase64[lineBuf[i + 2]] << 6) + (TInt)KInvBase64[lineBuf[i + 3]];
if (lineBuf[i + 2] == KPadCharacter)
{
// Two pad characters
outputBuf.Append((n >> 16) & 0x000000FF);
}
else if (lineBuf[i + 3] == KPadCharacter)
{
// One pad character
outputBuf.Append((n >> 16) & 0x000000FF);
outputBuf.Append((n >> 8) & 0x000000FF);
}
else
{
outputBuf.Append((n >> 16) & 0x000000FF);
outputBuf.Append((n >> 8) & 0x000000FF);
outputBuf.Append(n & 0x000000FF);
}
}
LeaveIfErr(file.Write(outputBuf), _L("Failed to write to '%S'"), &iFileName);
if (iVerbose)
{
Printf(_L("Wrote %d bytes to '%S'\r\n"), outputBuf.Length(), &iFileName);
}
}
}
else if (err == KErrEof)
{
finished = ETrue;
}
else
{
LeaveIfErr(err, _L("Couldn't read STDIN"));
}
}
CleanupStack::PopAndDestroy(&file);
}
void CCmdBase64::EncodeL()
{
LeaveIfFileNotFound(iFileName);
RFile file;
User::LeaveIfError(file.Open(FsL(), iFileName, EFileRead | EFileStream));
CleanupClosePushL(file);
TBuf8<KBlockSize> inputBuf;
TBuf<KLineLength + 2> outputBuf;
TBool finished(EFalse);
while (!finished)
{
TPtr8 ptr((TUint8*)inputBuf.Ptr() + inputBuf.Length(), 0, inputBuf.MaxLength() - inputBuf.Length());
LeaveIfErr(file.Read(ptr), _L("Couldn't read from '%S'"), &iFileName);
if (ptr.Length() > 0)
{
inputBuf.SetLength(inputBuf.Length() + ptr.Length());
const TInt inputBufLength = inputBuf.Length();
const TInt excess = inputBufLength % 3;
const TInt bytesToProcess = inputBufLength - excess;
for (TInt i = 0; i < bytesToProcess; i += 3)
{
// Combine the next three bytes into a 24 bit number.
TInt n = ((TInt)inputBuf[i] << 16) + ((TInt)inputBuf[i + 1] << 8) + (TInt)inputBuf[i + 2];
// Split the 24-bit number into four 6-bit numbers.
TUint8 n0 = (TUint8)(n >> 18) & 0x3F;
TUint8 n1 = (TUint8)(n >> 12) & 0x3F;
TUint8 n2 = (TUint8)(n >> 6) & 0x3F;
TUint8 n3 = (TUint8)n & 0x3F;
// Buffer the base64 encoded equivalent.
outputBuf.Append(KBase64Chars[n0]);
outputBuf.Append(KBase64Chars[n1]);
outputBuf.Append(KBase64Chars[n2]);
outputBuf.Append(KBase64Chars[n3]);
// Flush output buffer if it's full.
if (outputBuf.Length() == KLineLength)
{
outputBuf.Append(KNewLine);
Write(outputBuf);
outputBuf.Zero();
}
}
inputBuf.Delete(0, inputBufLength - excess);
}
else
{
// Process what's left over in inputBuf from the previous successful read, padding as required.
const TInt inputBufLength = inputBuf.Length();
if (inputBufLength > 0)
{
TInt n = (TInt)inputBuf[0] << 16;
if (inputBufLength > 1)
{
n += (TInt)inputBuf[1] << 8;
if (inputBufLength > 2)
{
n += (TInt)inputBuf[2];
}
}
TUint8 n0 = (TUint8)(n >> 18) & 0x3F;
TUint8 n1 = (TUint8)(n >> 12) & 0x3F;
TUint8 n2 = (TUint8)(n >> 6) & 0x3F;
TUint8 n3 = (TUint8)n & 0x3F;
outputBuf.Append(KBase64Chars[n0]);
outputBuf.Append(KBase64Chars[n1]);
if (inputBufLength > 1)
{
outputBuf.Append(KBase64Chars[n2]);
if (inputBufLength > 2)
{
outputBuf.Append(KBase64Chars[n3]);
}
}
for (TInt i = inputBufLength; i < 3; ++i)
{
outputBuf.Append('=');
}
}
if (outputBuf.Length() > 0)
{
outputBuf.Append(KNewLine);
Write(outputBuf);
}
finished = ETrue;
}
}
CleanupStack::PopAndDestroy(&file);
}
const TDesC& CCmdBase64::Name() const
{
_LIT(KName, "base64");
return KName;
}
void CCmdBase64::ArgumentsL(RCommandArgumentList& aArguments)
{
_LIT(KArgOperation, "operation");
aArguments.AppendEnumL((TInt&)iOperation, KArgOperation);
_LIT(KArgFilename, "filename");
aArguments.AppendFileNameL(iFileName, KArgFilename);
}
void CCmdBase64::OptionsL(RCommandOptionList& aOptions)
{
_LIT(KOptVerbose, "verbose");
aOptions.AppendBoolL(iVerbose, KOptVerbose);
_LIT(KOptOverwrite, "overwrite");
aOptions.AppendBoolL(iOverwrite, KOptOverwrite);
}
void CCmdBase64::DoRunL()
{
switch (iOperation)
{
case EDecode:
DecodeL();
break;
case EEncode:
EncodeL();
break;
default:
ASSERT(EFalse);
}
}