userlibandfileserver/fileserver/sfsrv/cl_ftext.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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