os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_ftext.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\sfsrv\cl_ftext.cpp
    15 // 
    16 //
    17 
    18 #include "cl_std.h"
    19 
    20 
    21 
    22 
    23 EXPORT_C TFileText::TFileText()
    24 /**
    25 Default constructor.
    26 */
    27 	{}
    28 
    29 
    30 
    31 
    32 EXPORT_C void TFileText::Set(RFile& aFile)
    33 /**
    34 Sets the Unicode file to be read from, or written to.
    35 
    36 This function must be called before 
    37 Read(), Write() or Seek() can be used.
    38 
    39 @param aFile The file to be used. Must be open.
    40 
    41 @see TFileText::Read
    42 @see TFileText::Write
    43 @see TFileText::Seek
    44 */
    45 	{
    46 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
    47 	iFile=aFile;
    48 #else
    49 	iFile=(RFile64&)aFile;
    50 #endif
    51 	iReadBuf.Zero();
    52 	iNext=(TText*)iReadBuf.Ptr();
    53 	iEnd=iNext;
    54 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
    55 	TInt pos = 0;
    56 #else
    57 	TInt64 pos = 0;
    58 #endif
    59 	iFile.Seek(ESeekCurrent,pos);
    60  	if (pos == 0)
    61  		iState = EStartOfFile;
    62  	else
    63  		iState = ENormal;
    64 	}
    65 
    66 
    67 
    68 
    69 EXPORT_C TInt TFileText::Read(TDes& aDes)
    70 /**
    71 Reads single line text record from a Unicode file into the specified descriptor.
    72 
    73 The read operation begins at the current file position, and ends when
    74 a line delimiter character is read.
    75 
    76 If the maximum length of the descriptor is insufficient to hold the record, 
    77 the function returns KErrTooBig and the descriptor is filled to its maximum 
    78 length.
    79 
    80 If Read() is called when the current position is the end of the file (that 
    81 is, after the last line delimiter in the file), KErrEof is returned, and the 
    82 length of the buffer is set to zero.
    83 
    84 @param aDes On return, contains the single record read from the file. Any 
    85             previous contents are overwritten.
    86 
    87 @return KErrNone if successful, otherwise one of the other system-wide error 
    88         codes.
    89 */
    90 	{
    91 
    92 	TText* pD=(TText*)aDes.Ptr();
    93 	TInt len=aDes.MaxLength();
    94 	TInt newLen=0;
    95 	while (newLen<len)
    96 		{
    97 		if (iNext>=iEnd)
    98 			{
    99 			TInt r=FillBuffer();
   100 			if (r!=KErrNone && r!=KErrEof)
   101 				return(r);
   102 			if (r==KErrEof)
   103 				{
   104 				aDes.SetLength(newLen);
   105 				return(newLen ? KErrNone : KErrEof);
   106 				}
   107 			continue;
   108 			}
   109 		TBool terminate=newLen;
   110 		TInt r=CheckForTerminator(terminate);
   111 		if (r!=KErrNone || terminate)
   112 			{
   113 			aDes.SetLength(newLen);
   114 			return(r);
   115 			}
   116 		*pD++=(*iNext++);
   117 		newLen++;
   118 		}
   119 	aDes.SetLength(newLen);
   120 	TBool terminate=newLen;
   121 	TInt r=CheckForTerminator(terminate);
   122 	if (r!=KErrNone || terminate)
   123 		return(r);
   124 	NextRecord();
   125 	return(KErrTooBig);
   126 	}
   127 
   128 void TFileText::NextRecord()
   129 //
   130 // Move to the start of the next record
   131 //
   132 	{
   133 
   134 	FOREVER
   135 		{
   136 		TBool terminate=EFalse;
   137 		TInt r=CheckForTerminator(terminate);
   138 		if (r!=KErrNone || terminate)
   139 			return;
   140 		iNext++;
   141 		}
   142 	}
   143 
   144 static void SwapWords(TText* aStart,TInt aCount)
   145  	{
   146  	TUint8* p = (TUint8*)aStart;
   147  	while (aCount-- > 0)
   148  		{
   149  		TUint8 temp = *p;
   150  		*p = p[1];
   151  		p[1] = temp;
   152  		p += 2;
   153    		}
   154    	}
   155 
   156 TInt TFileText::FillBuffer()
   157 //
   158 // Read the new data from the file
   159 //
   160 	{
   161 	
   162 	TInt r=iFile.Read(iReadBuf);
   163 	if (r!=KErrNone)
   164 		return(r);
   165 	if (iReadBuf.Length()==0)
   166 		return(KErrEof);
   167 	iNext=(const TText*)iReadBuf.Ptr();
   168 	iEnd=iNext+iReadBuf.Length()/sizeof(TText);
   169 	 
   170  	// Use any leading byte order marker to determine endianness.
   171  	if (iState == EStartOfFile)
   172  		{
   173  		iState = ENormal;
   174 
   175  		// Ignore an ordinary byte order marker.
   176  		if (*iNext == 0xFEFF)
   177  			iNext++;
   178 
   179  		// Set the endianness state to 'reverse' if a reversed byte order marker is found.
   180  		else if (*iNext == 0xFFFE)
   181  			{
   182  			iNext++;
   183  			iState = EReverse;
   184  			}
   185  
   186  		if (iNext == iEnd)
   187  			return KErrEof;
   188  		}
   189  
   190  	if (iState == EReverse)
   191 		SwapWords((TText*)iNext,(iEnd - iNext));
   192 
   193 	return(KErrNone);
   194 	}
   195 
   196 TInt TFileText::CheckForTerminator(TBool& anAnswer)
   197 //
   198 // Return ETrue if the next char is a record terminator: PARAGRAPH SEPARATOR (U+2029), LINE SEPARATOR (U+2028),
   199 // CR-LF (U+000D, U+000A), or LF (U+000A)
   200 //
   201 	{
   202 
   203 	if (iNext>=iEnd)
   204 		{
   205 		TInt r=FillBuffer();
   206 		if (r!=KErrNone)
   207 			{
   208 			if (r==KErrEof && anAnswer)
   209 				return(KErrNone);
   210 			return(r);
   211 			}
   212 		}
   213 
   214 	anAnswer=EFalse;
   215 	const TText* oldNext=iNext;
   216 	TInt oldBufferLength=iReadBuf.Length();
   217 	TText c=(*iNext);
   218 	TBool peek=EFalse;
   219 
   220 	// Check for unambiguous paragraph or line separator.
   221  	if (c == 0x2029 || c == 0x2028)
   222  		{
   223  		iNext++;
   224  		anAnswer = ETrue;
   225 		return KErrNone;
   226  		}
   227  
   228  	// Check for CR-LF or LF.
   229  	if (c == 0x000D)
   230 		{
   231 		iNext++;
   232 		if (iNext<iEnd)
   233 			c=(*iNext);
   234 		else
   235 			{
   236 			peek=ETrue;
   237 			TInt r=FillBuffer();
   238 			if (r!=KErrNone && r!=KErrEof)
   239 				return(r);
   240 			if (r==KErrNone)
   241 				c=(*iNext);
   242 			}
   243 		}
   244 
   245 	if (c == 0x000A)
   246 		{
   247 		iNext++;
   248 		anAnswer=ETrue;
   249 		return(KErrNone);
   250 		}
   251 
   252 	iNext=oldNext;
   253 	if (!peek)
   254 		return(KErrNone);
   255 
   256 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
   257 	TInt pos=(-1)*(oldBufferLength+iReadBuf.Length());
   258 #else
   259 	TInt64 pos=(-1)*(oldBufferLength+iReadBuf.Length());
   260 #endif
   261 	TInt r=iFile.Seek(ESeekCurrent,pos);
   262 	if (r==KErrNone)
   263 		r=FillBuffer();
   264 	if (r!=KErrNone)
   265 		return(r);
   266 	iNext=oldNext;
   267 	return(KErrNone);
   268 	}
   269 
   270 
   271 
   272 
   273 EXPORT_C TInt TFileText::Write(const TDesC& aDes)
   274 /**
   275 Writes the contents of a descriptor to the end of a Unicode file.
   276 
   277 A line delimiter is appended to the descriptor, and the current file position
   278 is set to the new end of file.
   279 
   280 If the descriptor contains one or more paragraph delimiters, Read() will treat 
   281 the contents of the descriptor as more than one record.
   282 
   283 @param aDes The descriptor content to be appended to the file.
   284 
   285 @return KErrNone if successful, otherwise one of the other system-wide error 
   286         codes.
   287         
   288 @see TFileText::Read
   289 */
   290 	{
   291 
   292 	TInt r=Seek(ESeekEnd);
   293 	if (r!=KErrNone)
   294 		return(r);
   295 	TPtrC8 writeBuf((const TUint8*)aDes.Ptr(),aDes.Size());
   296 	r=iFile.Write(writeBuf);
   297 	if (r!=KErrNone)
   298 		return(r);
   299  	TText lf = 0x000A;
   300  	TPtrC8 lf8((const TUint8*)&lf,sizeof(TText));
   301  	r=iFile.Write(lf8);
   302 	return(r);
   303 	}
   304 
   305 
   306 
   307 
   308 EXPORT_C TInt TFileText::Seek(TSeek aMode)
   309 /**
   310 Seeks to start or end of file.
   311 
   312 It is only necessary to call this function before 
   313 using Read() because Write() always seeks to the end of the file
   314 before writing.
   315 
   316 @param aMode ESeekStart to seek to the start of the file;
   317              ESeekEnd to seek to the end.
   318              
   319 @return KErrNone if successful, otherwise one of the other system-wide error 
   320         codes.
   321 
   322 @panic FSCLIENT 5 if aMode is neither ESeekStart nor ESeekEnd.
   323 
   324 @see TFileText::Read
   325 @see TFileText::Write
   326 */
   327 	{
   328 
   329 	__ASSERT_ALWAYS(aMode==ESeekStart || aMode==ESeekEnd,Panic(EFTextIllegalSeekMode));
   330 #ifndef	SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
   331 	TInt pos=0;
   332 #else
   333 	TInt64 pos = 0;
   334 #endif
   335 	TInt ret=iFile.Seek(aMode,pos);
   336  	if (ret == 0 && aMode == ESeekStart)
   337  		iState = EStartOfFile;
   338 	iNext = (TText*)iReadBuf.Ptr();
   339  	iEnd = iNext;
   340 	return ret;
   341 	}
   342