📄 iodev.cpp
字号:
iUnicodeTextFile=ETrue; // Assume Unicode by default
if (mode&EFileWrite && mode&EFileStreamText && (TheRuntime()->UserFlags() & KOplStateOutputAsciiTextFiles))
iUnicodeTextFile=EFalse;
switch (iMode&FSER_MASK)
{
case (FOPEN):
{
DoOpenFileL(fs,aFileName,mode);
break;
}
case (FCREATE):
{
User::LeaveIfError(iFile.Create(fs,aFileName,mode));
break;
}
case (FREPLACE):
{
User::LeaveIfError(iFile.Replace(fs,aFileName,mode));
break;
}
case (FAPPEND):
{
DoOpenFileL(fs,aFileName,mode);
TInt pos=0;
User::LeaveIfError(iFile.Seek(ESeekEnd,pos));
break;
}
case (FUNIQUE):
{
TFileName fileName;
TParse parse;
User::LeaveIfError(fs.Parse(aFileName,parse));
User::LeaveIfError(iFile.Temp(fs,parse.DriveAndPath(),fileName,mode));
if (fileName.Length()>aFileName.MaxLength())
{
iFile.Close();
User::Leave(KErrBadName);
}
aFileName=fileName;
break;
}
default:
{
User::Leave(KOplErrInvalidIO);
break;
}
}
// If we are in text file mode, additional action is needed. If we are WRITING a file
// and it's non-Unicode we need to dump out 0xFEFF to the start of it to signify it's
// Unicode not ASCII. If we are trying to READ a non-Unicode file, we must leave
// with KErrNotSupported since it's not possible to do this at the moment (i.e.
// the developer can trap for this error and fall back to opening the ASCII text file
// in binary mode instead).
if (mode&EFileStreamText)
{
if (mode&EFileWrite && iUnicodeTextFile)
{
TInt currentPos=0;
User::LeaveIfError(iFile.Seek(ESeekCurrent,currentPos));
if (currentPos==0)
{
TBuf8<2> buf(2);
buf[0]=0xFF;
buf[1]=0xFE;
iFile.Write(buf);
}
}
else if (!(mode&EFileWrite) && !iUnicodeTextFile)
{
iFile.Close();
User::Leave(KErrNotSupported);
}
}
}
TUint COplIOFile::GetModeL()
{
TUint mode=0;
switch (iMode&FMT_MASK)
{
case (FSTREAM):
mode=EFileStream;
break;
case (FSTREAM_TEXT):
mode=EFileStreamText;
break;
default:
User::Leave(KErrArgument);
}
mode|=(iMode&FUPDATE)?EFileWrite:EFileRead;
mode|=(iMode&FSHARE)?EFileShareReadersOnly:EFileShareExclusive;
return mode;
}
void COplIOFile::RunFunctionL(TInt aFuncNo,TIORequest*& aIOStatus,TOplReqStatus* aOplStatusPtr, TAny* aParam1, TAny* aParam2)
// eb205: I've replaced calls to "User::Leave(KOplErrInvalidIO)" with calls
// to "User::RequestComplete(statusPtr,KErrArgument)"
{
if (aFuncNo==FREAD)
{
__LEAVE_IF_UNALIGNED(aParam1,KOplErrBadAlignment); // No statusPtr to RequestComplete against, at this point.
aIOStatus=new(ELeave) TOplIOReadRequest(aOplStatusPtr,EActivePriorityWsEvents+4,(TUint8*)aParam1,aParam2);
iFile.Read(((TOplIOReadRequest*)aIOStatus)->iPtr8,aIOStatus->Status());
}
else if (aFuncNo==FWRITE)
{
__LEAVE_IF_UNALIGNED(aParam1,KOplErrBadAlignment); // No statusPtr to RequestComplete against, at this point.
aIOStatus=new(ELeave) TOplIOPtrRequest(aOplStatusPtr,EActivePriorityWsEvents+4,(TUint8*)aParam1,aParam2);
// NOTE: 09/03/2002 (PhilS). We now use iBufferToWrite because the asynchronous
// Write() method may not complete before this function exits. Previously we just
// used an automatic, but that could potentially be discarded before the write
// had finished (leading to a 'General Failure' error in OPL).
TPtr8 ptr(((TOplIOPtrRequest*)aIOStatus)->iPtr8);
const TInt length=ptr.Length();
if (iBufferToWrite)
{
delete iBufferToWrite;
iBufferToWrite=NULL;
}
if ((!iUnicodeTextFile) && (length))
{
// First get the raw 8-bit data which represents a wide string into an actual
// 16-bit descriptor so it can be converted properly.
const TInt halfLength=length>>1;
HBufC* wideBuf=HBufC::NewLC(halfLength);
wideBuf->Des().Append((TUint16*)(ptr.Ptr()),halfLength);
// Convert Unicode buffer into ASCII, then write it to the text file.
iBufferToWrite=COplRuntimeCharConv::ConvertFromUnicodeToNarrowL(*wideBuf);
CleanupStack::PopAndDestroy(1); // wideBuf
}
else
{
iBufferToWrite=ptr.AllocL();
}
iFile.Write(*iBufferToWrite,aIOStatus->Status());
}
else
{
aIOStatus=new(ELeave) TOplIORequest(aOplStatusPtr,EActivePriorityWsEvents+4);
TRequestStatus* statusPtr=&(aIOStatus->Status());
switch (aFuncNo)
{
case (FCLOSE):
(TheRuntime()->IOCollection()).RemoveObject(iHandle);
User::RequestComplete(statusPtr,KErrNone);
break;
case (FCANCEL):
User::RequestComplete(statusPtr,KErrNone);
break;
case (FFLUSH):
User::RequestComplete(statusPtr,iFile.Flush());
break;
case (FSEEK):
{
if (!(iMode&FRANDOM))
{
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
TSeek seekMode=ESeekStart;
switch (OplUtil::GetWord(aParam1))
{
case (FABS):
//seekMode=ESeekStart;
break;
case (FEND):
seekMode=ESeekEnd;
break;
case (FCUR):
seekMode=ESeekCurrent;
break;
default:
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
TInt pos=OplUtil::GetLong(aParam2);
User::RequestComplete(statusPtr,iFile.Seek(seekMode,pos));
OplUtil::PutLong(aParam2,pos);
break;
}
case (FSETEOF):
User::RequestComplete(statusPtr,iFile.SetSize(OplUtil::GetLong(aParam1))); // eb205: is this really correct?
break;
default:
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
}
}
COplIOFile::~COplIOFile()
{
iFile.Close();
delete iBufferToWrite;
}
COplIOFileText::COplIOFileText(TInt16 aHandle)
:COplIOFile(aHandle)
{
}
void COplIOFileText::ConstructL(TBuf<256>& aFileName,TInt16 aMode)
{
COplIOFile::ConstructL(aFileName,(TInt16)((aMode&~FMT_MASK)|FSTREAM_TEXT)); // open or create as stream-text
iTextFile.Set(iFile);
iMode=aMode;
}
void COplIOFileText::RunFunctionL(TInt aFuncNo,TIORequest*& aIOStatus,TOplReqStatus* aOplStatusPtr, TAny* aParam1, TAny* aParam2)
// eb205: I've replaced calls to "User::Leave(KOplErrInvalidIO)" with calls
// to "User::RequestComplete(statusPtr,KErrArgument)"
{
if (aFuncNo==FREAD)
{
__LEAVE_IF_UNALIGNED(aParam1,KOplErrBadAlignment); // No statusPtr to RequestComplete against, at this point.
TOplIOTextReadRequest* request=new(ELeave) TOplIOTextReadRequest(aOplStatusPtr,EActivePriorityWsEvents+4,(TUint8*)aParam1,aParam2);
aIOStatus=request;
TRequestStatus* statusPtr=&request->Status();
TPtr ptr((TText*)request->iPtr8.Ptr(),request->iPtr8.Length(),request->iPtr8.MaxLength());
User::RequestComplete(statusPtr,iTextFile.Read(ptr));
request->iPtr8.SetLength(ptr.Length());
}
else if (aFuncNo==FWRITE)
{
__LEAVE_IF_UNALIGNED(aParam1,KOplErrBadAlignment); // No statusPtr to RequestComplete against, at this point.
TOplIOPtrRequest* request=new(ELeave) TOplIOPtrRequest(aOplStatusPtr,EActivePriorityWsEvents+4,(TUint8*)aParam1,aParam2);
aIOStatus=request;
TRequestStatus* statusPtr=&request->Status();
const TPtrC ptr((TText*)request->iPtr8.Ptr(),request->iPtr8.Length()); // Text IO takes number of Unicode chars to write, not bytes.
if (!iUnicodeTextFile)
{
// Convert Unicode buffer into ASCII, then write it to the text file.
// Note that we write to iFile and NOT iTextFile - iTextFile expects
// a wide buffer on Unicode builds, but all it does is flush it through
// to an RFile anyway (see COplIOFileText::ConstructL() where this is set)
HBufC8* buf=COplRuntimeCharConv::ConvertFromUnicodeToNarrowLC(ptr);
User::RequestComplete(statusPtr,iFile.Write(*buf));
iTextFile.Set(iFile);
CleanupStack::PopAndDestroy(); // buf
}
else
{
User::RequestComplete(statusPtr,iTextFile.Write(ptr));
}
}
else
{
aIOStatus=new(ELeave) TOplIORequest(aOplStatusPtr,EActivePriorityWsEvents+4);
TRequestStatus* statusPtr=&(aIOStatus->Status());
switch (aFuncNo)
{
case (FCLOSE):
(TheRuntime()->IOCollection()).RemoveObject(iHandle);
User::RequestComplete(statusPtr,KErrNone);
break;
case (FCANCEL):
User::RequestComplete(statusPtr,KErrNone);
break;
case (FFLUSH):
User::RequestComplete(statusPtr,iFile.Flush());
break;
case (FSEEK):
{
if (!(iMode&FRANDOM))
{
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
TSeek seekMode=ESeekStart;
switch (OplUtil::GetWord(aParam1))
{
case (FREWIND):
//seekMode=ESeekStart;
break;
case (FRSENSE):
case (FRSET):
default:
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
//TInt pos=OplUtil::GetLong(aParam2);
User::RequestComplete(statusPtr,iTextFile.Seek(seekMode));
//OplUtil::PutLong(aParam2,0);
break;
}
case (FSETEOF):
{
const TInt error=iFile.SetSize(OplUtil::GetLong(aParam1)); // eb205: is this really correct?
if (error!=KErrNone)
{
User::RequestComplete(statusPtr,error);
return; // return here as there's been an error
}
iTextFile.Set(iFile);
User::RequestComplete(statusPtr,iTextFile.Seek(ESeekEnd));
}
break;
default:
User::RequestComplete(statusPtr,KErrArgument);
return; // return here as there's been an error
}
}
}
//
// Class TOplIOReadRequest
//
TOplIOReadRequest::TOplIOReadRequest(TOplReqStatus* aStatusPtr,TInt aPriority,TAny* aParam1,TAny* aParam2)
:TOplIOPtrRequest(aStatusPtr,aPriority,aParam1,aParam2)
{
iLenPtr=(TUint16*)aParam2;
}
void TOplIOReadRequest::DoParamsUpdate()
{
if (OplUtil::GetWord(iLenPtr)!=0 && iPtr8.Length()==0) //end of file reached!?!
iStatus=KErrEof;
else
OplUtil::PutWord(iLenPtr,(TUint16)iPtr8.Length());
}
//
// Class TOplIOTextReadRequest
//
TOplIOTextReadRequest::TOplIOTextReadRequest(TOplReqStatus* aStatusPtr,TInt aPriority,TAny* aParam1,TAny* aParam2)
:TOplIOReadRequest(aStatusPtr,aPriority,aParam1,aParam2)
{
}
void TOplIOTextReadRequest::DoParamsUpdate()
{
if (iStatus==KErrTooBig)
iStatus=KOplErrRecord; // OPL1993 also positioned to the start of the next record
OplUtil::PutWord(iLenPtr,(TUint16)iPtr8.Length());
}
//
// Class TOplIOPtrRequest
//
TOplIOPtrRequest::TOplIOPtrRequest(TOplReqStatus* aStatusPtr,TInt aPriority,TAny* aParam1,TAny* aParam2)
:TOplIORequest(aStatusPtr,aPriority), iPtr8((TUint8*)aParam1,OplUtil::GetWord(aParam2),OplUtil::GetWord(aParam2))
{
}
//
// Class TOplIOCallBackRequest
//
#pragma warning ( disable: 4310) // cast truncates constant
TOplIOCallBackRequest::TOplIOCallBackRequest(TOplReqStatus* aStatusPtr,TInt aPriority,TCallBack aCallBack)
:TOplIORequest(aStatusPtr,aPriority)
{
OplUtil::PutWord(aStatusPtr,(TInt16)KOplErrFilePending);
iCallBack=aCallBack;
}
#pragma warning ( default: 4310)
void TOplIOCallBackRequest::DoParamsUpdate()
{
TInt ret=iCallBack.CallBack();
__ASSERT_ALWAYS(ret!=KRequestPending, User::Panic(KOplrIODEV, 1));
if (ret)
iStatus=ret;
}
//
// Class TEraIOCallBackRequest
//
TEraIOCallBackRequest::TEraIOCallBackRequest(TInt32* aStatusPtr,TInt aPriority,TCallBack aCallBack)
:TIORequest(aStatusPtr, aPriority)
{
OplUtil::PutLong(aStatusPtr,KRequestPending);
iCallBack=aCallBack;
}
void TEraIOCallBackRequest::DoHandleCompletion()
{
TInt ret=iCallBack.CallBack();
__ASSERT_ALWAYS(ret!=KRequestPending, User::Panic(KOplrIODEV, 2));
OplUtil::PutLong(iStatusPtr,((ret)?ret:iStatus.Int()));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -