/*------------------------------------------------------------------------------*
 * File Name: File.h															*
 * Creation: 4/2/2001															*
 * Purpose: Origin C header	for File class and other related functions			*
 * Copyright (c) OriginLab Corp.2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007	*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/

#ifndef _FILE_H
#define _FILE_H

#include <common.h> // must always include this
#include <string.h> // most likely you will also need strings

//constants for file nOpenFlags
//CPY, we will change into enum later
/*
enum {
	modeRead =          0x0000,
	modeWrite =         0x0001,
	modeReadWrite =     0x0002,
	shareCompat =       0x0000,
	shareExclusive =    0x0010,
	shareDenyWrite =    0x0020,
	shareDenyRead =     0x0030,
	shareDenyNone =     0x0040,
	modeNoInherit =     0x0080,
	modeCreate =        0x1000,
	modeNoTruncate =    0x2000,
	typeText =          0x4000, // typeText and typeBinary are used in
	typeBinary =   (int)0x8000 // derived classes only
};
*/
#define	file::modeRead			0x0000
#define	file::modeWrite			0x0001
#define	file::modeReadWrite		0x0002
#define	file::shareCompat		0x0000
#define	file::shareExclusive	0x0010
#define	file::shareDenyWrite	0x0020
#define	file::shareDenyRead		0x0030
#define	file::shareDenyNone		0x0040
#define	file::modeNoInherit		0x0080
#define	file::modeCreate		0x1000
#define	file::modeNoTruncate	0x2000
#define	file::typeText			0x4000 // typeText and typeBinary are used in
#define	file::typeBinary		((int)0x8000) // derived classes only
	

#define file::hFileNull		    0

#define file::begin		    	0
#define file::current			1
#define file::end				2

//constants for file Error Code 
#define FileError::none					0	//No error occurred.
#define FileError::generic				1	//An unspecified error occurred.
#define FileError::fileNotFound			2	//The file could not be located.
#define FileError::badPath				3	//All or part of the path is invalid.
#define FileError::tooManyOpenFiles		4	//The permitted number of open files was exceeded.
#define FileError::accessDenied			5	//The file could not be accessed.
#define FileError::invalidFile			6	//There was an attempt to use an invalid file handle.
#define FileError::removeCurrentDir		7	//The current working directory cannot be removed.
#define FileError::directoryFull		8	//There are no more directory entries.
#define FileError::badSeek				9	//There was an error trying to set the file pointer.
#define FileError::hardIO				10	//There was a hardware error.
#define FileError::sharingViolation		11	//SHARE.EXE was not loaded, or a shared region was locked.
#define FileError::lockViolation		12	//There was an attempt to lock a region that was already locked.
#define FileError::diskFull				13	//The disk is full.
#define FileError::endOfFile			14	//The end of file was reached. 


/** >System
		The Origin C file class provides read/write access to binary files using unbuffered io
		(immediate disk access) similar to the MFC CFile class. See also the stdioFile class
		for buffered stream io to text files.
	Example:
		char szTemp[MAXFULLPATH];
		GetTempPath(MAXFULLPATH, szTemp); // Get temp folder path.
		string strFile = szTemp + "\\test.Dat";
		file ff(strFile, file::modeCreate | file::modeWrite); // Create a new write only file.
		int bb[4] = {1, 2, 3, 4};
		int iSize = sizeof(bb);
		ff.Write(bb,iSize);
		ff.Close();
*/
class file
{
public:

	/**
		Remarks:
			The default constructor does not open a file but rather sets m_hFile to file::hFileNull.
		Example:
			file ff;
		SeeAlso:
			file::Open,file::Close.
	*/
	file(); // Set the public data member m_hFile to a null value. 
	
	/**
		Remarks:
			Creates a file object and opens the file having the path specified by the parameter lpszFileName.  This
			constructor combines the functions of the default constructor file() and the Open member function.  An exception
			is thrown if an error occurs while opening the file.  Depending on the severity of the error, the user should be
			alerted by an exception handler.
		Example:
			char szTemp[MAXFULLPATH];
			GetTempPath(MAXFULLPATH, szTemp); // Get temp folder path.
			string strFile = szTemp + "\\test.txt";
			file ff(strFile, file::modeCreate | file::modeWrite); // Create a new write only file.
			int bb[4] = {1, 2, 3, 4};
			ff.Write(bb, sizeof(bb));
			ff.Close();
		Parameters:
			lpszFileName=A string containing an absolute or relative path to the desired file. 
			nOpenFlags=Specifies the share and access modes of the opened file.  Modes are defined below and can be combined
			using the bitwise OR operator "|".  At least one access and one share mode should be specified.
			modeRead		Opens the file in read only mode.
			modeWrite		Opens the file in write only mode.
			modeReadWrite	Opens the file in read and write modes.
			shareCompat		Not available...see shareExclusive below.
			shareExclusive	Opens the file disallowing read and write access to all other processes. Construction fails
							if file is already opened in read or write mode. 
			shareDenyWrite	Opens the file disallowing write access to all other processes. Construction fails if file
							is already opened in write mode. 
			shareDenyRead	Opens the file disallowing read access to all other processes. Construction fails if file
							is already opened in read mode.
			shareDenyNone	Opens the file allowing read and write access to all other processes.
			modeNoInherit	Opens the file but disallows inheritance by child processes.
			modeCreate		Creates a new file of length 0 bytes.  Pre-existing files are truncated to 0 bytes by default.
			modeNoTruncate	Used in combination with modeCreate to specify that pre-existing files should not be truncated.
							When used together, modeCreate and modeNoTruncate open a specified file if it exists or	create
							the specified file if it does not exist.							
			typeText		Sets text mode for specified file enabling special processing of carriage return-line feed
							character combinations.  Used in derived classes only.
			typeBinary		Sets binary mode for specified file.  Used in derived classes only.
		SeeAlso:
			file::Open,file::Close.
	*/
	file(LPCTSTR lpszFileName, UINT nOpenFlags); // Create a File object and open the file having the specified path.

	// Attributes
	/**
		Remarks:
			Get the value of the last error that occured.
			FileError::none					= No error occurred.
			FileError::generic				= An unspecified error occurred.
			FileError::fileNotFound			= The file could not be located.
			FileError::badPath				= All or part of the path is invalid.
			FileError::tooManyOpenFiles		= The permitted number of open files was exceeded.
			FileError::accessDenied			= The file could not be accessed.
			FileError::invalidFile			= There was an attempt to use an invalid file handle.
			FileError::removeCurrentDir		= The current working directory cannot be removed.
			FileError::directoryFull		= There are no more directory entries.
			FileError::badSeek				= There was an error trying to set the file pointer.
			FileError::hardIO				= There was a hardware error.
			FileError::sharingViolation		= SHARE.EXE was not loaded, or a shared region was locked.
			FileError::lockViolation		= There was an attempt to lock a region that was already locked.
			FileError::diskFull				= The disk is full.
			FileError::endOfFile			= The end of file was reached. 
		
		Example:
			This function open/create the file c:\test.txt and get the value of the last error 
			if open file fails.
			void run_GetLastError()  
			{
				file ff;
				string strFile = "C:\\test.txt";  
				string FileErr;
				BOOL bOK;
				
				bOK = ff.Open(strFile, file::modeCreate | file::modeWrite); //Create a write only file and open it
				if (!bOK)
				{
					printf("failed to open the file");  //the string should not be output
					FileErr = ff.GetLastError();
				}
				else
				{
					ff.Close();
				}				
			}
	*/
	UINT	GetLastError();
	/**
		Remarks:
			Check file object is open or not, when use a method of File object which is not open will lead a runtime error.
			Use this function before you call the method of File object. 
		Example:
			This function opens/creates the file c:\test.txt.
			void run_IsOpen()   
			{
				file ff;
			    BOOL bOK;
			
				string strFile = "C:\\test.txt";  
				       
				bOK = ff.Open(strFile, file::modeCreate | file::modeWrite);  //create a new write only file and open it
				if(!bOK)
					out_str("failed to open the file");			   		
				else
				{
					if( ff.IsOpen() )
					{
						printf("The ff file is open");  //The string should be output
						ff.Close();  //Close the ff file
					}
				}
			}
	*/
	BOOL IsOpen();

	/**
		Remarks:
			Get the current value of the file pointer which is an offset from the beginning of the file.
		Example:
			char szTemp[MAXFULLPATH];
			GetTempPath(MAXFULLPATH, szTemp); // Get temp folder path.
			string strFile = szTemp + "\\test.txt";
			file ff;
			if( ff.Open(strFile, file::modeCreate | file::modeWrite) )
			{
				int i = 10;
				int ia[4] = {1, 2, 3, 4};
				LONG lPosition;
				
				ff.Write(&i, sizeof(i));		// Write 1 int (4 bytes) to file.
				lPosition = ff.GetPosition();	// Position now equals 4. 
				ff.Write(ia, sizeof(ia));		// Write 4 ints (16 bytes) to file following previous int.
				lPosition = ff.GetPosition();	// Position now equals 20.
				ff.SeekToBegin();				// Set file pointer to start of file.
				lPosition = ff.GetPosition();	// Position now equals 0.
				ff.Close();
			}
		Return:
			Returns the current value of the file pointer.
		SeeAlso:
			file::Seek.
	*/
	LONG    GetPosition();

	/**
		Remarks:
			A safe method of opening a file when failure is a likely outcome.  The Open member function should be called after
			the default File constructor has been invoked.  It is a safe method of opening a file because it returns FALSE
			or 0 on failure instead of throwing an exception.  When a file is opened the current pointer position is
			initialized to 0.
		Example 1:
			file ff;
			//Get the origin folder path.
			string strOriginPath;
			strOriginPath = GetAppPath() + "OriginC";
			string strFile = strOriginPath + "\\test.txt";
			BOOL bOK = ff.Open(strFile, file::modeCreate | file::modeWrite);		//create a new write only file.
			int bb[4] = {1, 2, 3, 4};
			ff.Write(bb, sizeof(bb));
			ff.Close();
			bOK = ff.Open(strFile, file::modeRead | file::shareDenyWrite);			//open the file created previously and set it to read only file.
			int aa;
			ff.Read(&aa, sizeof(aa));		//aa equals 1 now.
			ff.Close();
		Example 2:		
			//Get temp folder path.
			char sztemp[MAXFULLPATH];
			DWORD aa = GetTempPath(MAXFULLPATH, sztemp);
			string str1, strFile;
			str1 = sztemp;
			strFile = str1 + "\\test.txt";
			bOK = ff.Open(strFile, file::modeCreate | file::modeReadWrite );
			int bb[4] = {1, 2, 3, 4};
			ff.Write(bb, sizeof(bb));
			int aa;
			ff.Read(&aa, sizeof(aa));		//aa equals 1 now.
			ff.Close();
		Example 3:
			//This console program is used to copy files.
			int test()
			{
				char sztemp[MAXFULLPATH];
				DWORD aa = GetTempPath(MAXFULLPATH, sztemp);
				string str1, strFile, strFile2;
				str1 = sztemp;
				strFile = str1 + "\\test.txt";
				strFile2 = str1 + "\\dest.txt";
			
		   		// constructing these file objects doesn't open them
		   		file sourceFile;
		   		file destFile;
		
		   		// open the source file for reading
		   		bool bOK = sourceFile.Open(strFile, file::modeRead | file::shareDenyWrite);
		   		if(!bOK)
		   		{
		   			out_str("failed to open the source file");
		   			return 0;
		   		}
		   
		   		// open the destination file for writing
		   		bOK = destFile.Open(strFile2, file::modeWrite | file::shareExclusive | file::modeCreate);
		   		if(!bOK)
		   		{
		   			out_str("failed to open the destination file");
		   			return 0;
		   		}
		
		   		BYTE buffer[196];
		   		DWORD dwRead;
		
		    	// Read in 196-byte blocks. Remember how many bytes were actually read, and try to 
		    	// write that many out. This loop ends when there are no more bytes to read.
		      	do
		      	{
		         	dwRead = sourceFile.Read(buffer, 196);
		         	destFile.Write(buffer, dwRead);
		      	}
		      	while (dwRead > 0);
		
		      	// Close both files
		      	destFile.Close();
		      	sourceFile.Close();
		      	
		      	return 1;
			}
		Parameters:
			lpszFileName=A string containing an absolute or relative path to the desired file. 
			nOpenFlags=Specifies the share and access modes of the opened file.  See the default File constructor for
			definitions of all supported modes.  Modes can be combined using the bitwise OR operator "|".  At least one access
			and one share mode should be specified.
		Return:
			Returns FALSE or 0 if the file fails to open and returns TRUE or a non-zero if the file opens successfully.
		SeeAlso:
			file::file,file::Close.
	*/
	BOOL	Open(LPCTSTR lpszFileName, UINT nOpenFlags); // Open a file returning FALSE or 0 on failure and TRUE or a non-zero on success.
	
	/**
		Remarks:
			Read data into a buffer from the file associated with the file object.
		Example:
			//read integer and array of integers.
			file ff;
			bool bOK = ff.Open("c:\\test.dat", file::modeRead);
			if(!bOK)
			{
				out_str("Failed to open file C:\test.txt");
				return 0;
			}
			int aa, intlist[10];
			ff.Read(&aa, sizeof(aa));
			ff.Read(intlist, sizeof(intlist));
			ff.Read(&intlist[0], sizeof(intlist));
			
			//read double
			double bb;
			ff.Read(&bb, sizeof(bb));
			
			//read structure
			WIN32_FIND_DATAA cc;
			ff.Read(&cc, sizeof(cc));
			
			//read char array
			char dd[100];
			ff.Read(dd, sizeof(dd));
			
			//read vector
			vector<int> kk;
			kk.SetSize(5);
			int size = sizeof(int) * kk.GetSize();
			ff.Read(kk, size);
			
		Parameters:
			lpBuf=A buffer where the data read is stored.
			nCount=The number of bytes to read from the file indicated by the file object.
		Return:
			Number of bytes read from the file.  May be less than nCount if EOF is reached.
		SeeAlso:
			File::Write.
	*/
	UINT	Read(void *lpBuf, UINT nCount);

	/**
		Remarks:
			Write data from a buffer into the file associated with the file object.
		Example:
		int test_write()
		{
			file ff;
			bool bOK = ff.Open("C:\\test.txt", file::modeCreate | file::modeReadWrite);
			if(!bOK)
			{
				out_str("Failed to open file C:\test.txt");
				return 0;
			}
			int ia = 10;
			ff.Write(&ia, sizeof(ia));			//write 4 to file.
			int ib[4] = {1, 2, 3, 4};
			ff.Write(ib, sizeof(ib));			//write 1, 2, 3, 4 to file following previous 4.
	
			//write double
			double da = 123.345;
			ff.Write(&da, sizeof(da));
			
			//write structure
			WIN32_FIND_DATAA sa;
			memset(&sa, 0, sizeof(WIN32_FIND_DATAA));
			sa.dwFileAttributes = 20000;
			sa.ftCreationTime.dwLowDateTime = 10;
			sa.ftCreationTime.dwHighDateTime = 50;
			sa.ftLastAccessTime.dwLowDateTime = 100000;
			sa.ftLastAccessTime.dwHighDateTime = 500000;
			sa.ftLastWriteTime.dwLowDateTime = 1000;
			sa.ftLastWriteTime.dwHighDateTime = 5000;
			sa.nFileSizeHigh = 9000000;
			sa.nFileSizeLow = 1;
			sa.dwReserved0 = 600;
			sa.dwReserved1 = 98745;
			lstrcpy(sa.cFileName, "C:\\Origin70\\OriginC\\origin.h");
			lstrcpy(sa.cAlternateFileName,"originc.h");
			ff.Write(&sa, sizeof(sa));
			
			//write char array
			char ca[20] = "This is a string.";
			ff.Write(ca, sizeof(ca));
			
			//write vector
			vector<int> ik = {1, 2, 3, 4, 5};
			int size = sizeof(int) * ik.GetSize();
			ff.Write(ik, size);
			
			return 1;
		}
		
		Parameters:
			lpBuf=A buffer where the data to be written is stored.
			nCount=The number of bytes to write from the buffer to the file indicated by the File object.  Carriage return-line
			feed character combinations are counted as one byte. 
		Return:
			The number of bytes written to the file from the buffer.
		SeeAlso:
			File::Read,StdioFile::WriteString.
	*/
	UINT	Write(void *lpBuf, UINT nCount);
     
	/**
		Remarks:
			Get the handle of current open file.
		Example:
			file ff;
			bool bOK = ff.Open("C:\\test.txt", file::modeCreate | file::modeReadWrite);
			if(!bOK)
			{
				out_str("Failed to open file C:\test.txt");
				return 0;
			}
			UINT hFile = ff.GetHandle();
		Return:
			A variable of type UINT. It is file::hFileNull (an operating-system-independent empty file indicator)
			if the handle has not been assigned. 
	*/
	UINT GetHandle();	
	
	/**
		Remarks:
			Moves the pointer to the current file position as specified.  Seek enables random access within a file. 
		Example: 
			file ff;
			bool bOK = ff.Open("C:\\test.txt", file::modeCreate);
			if(!bOK)
			{
				out_str("Failed to open file C:\test.txt");
				return 0;
			}
			LONG lCurrent = ff.Seek(20, file::begin);	// lCurrent = 20.
			lCurrent = ff.Seek(16, file::current);		// lCurrent = 20 + 16 = 36.
			lCurrent = ff.Seek(-16, file::end);			// lCurrent = length of file - 16.		
		Parameters:
			lOffset=Number of bytes to move the file pointer relative to and in the direction indicated by nFrom.
			nFrom=Specifies the referenece position and direction to move the pointer to the current file position.  
				file::begin		Moves the current file position lOffset bytes forward from the beginning of the file.
				file::current	Moves the current file position lOffset bytes from the current position in the file.
				file::end		Moves the current file position lOffset bytes backward from the end of the file.  The value of
								lOffset must be negative otherwise the current file position will be outside the file. 
		Return:
			If the current file position is valid, seek returns the number of bytes from the beginning of the file
			otherwise an exception is thrown.  
		SeeAlso:
			file::GetPosition,file::SeekToBegin,file::SeekToEnd.
	*/	
	LONG	Seek(LONG lOffset, UINT nFrom);
	
	/**
		Remarks:
			Sets the file pointer value to the beginning of the file.
			This is the same as file::Seek(0, file::begin).
		Examples:
			// Assume strFile is a string containing the name of an exsiting file.
			file ff;
			strFile="C:\\test.dat";
			if( ff.Open(strFile, file::modeRead) )
			{
				LONG lFileSize = ff.SeekToEnd(); // Go to the end of the file.
				ff.SeekToBegin(); // Go to the beginning of the file.
				ff.Close();
			}
		SeeAlso:
			file::GetPosition,file::Seek,file::SeekToEnd.
	*/
	void	SeekToBegin();

	/**
		Remarks:
			Sets the file pointer value to the end of the file.
			This is the same as file::Seek(0, file::end).
		Examples:
			// Assume strFile is a string containing the name of an exsiting file.
			file ff;
			strFile="C:\\test.dat";
			if( ff.Open(strFile, file::modeRead) )
			{
				LONG lFileSize = ff.SeekToEnd();
				ff.Close();
			}
		Return:
			The number of bytes of the whole file
		SeeAlso:
			file::GetPosition,file::Seek,file::SeekToBegin.
	*/
	LONG	SeekToEnd();	

	/**
		Remarks:
			Force data remaining in the file buffer to be written to the file.
		Example:
			char szTemp[MAXFULLPATH];
			GetTempPath(MAXFULLPATH, szTemp); // Get temp folder path.
			string strFile = szTemp + "\\test.txt";
			file ff;
			if( ff.Open(strFile, file::modeCreate | file::modeWrite) )
			{
				ff.Write(&strFile, strFile.GetLength()); // Write the file name into the file.
				ff.Flush(); // Make sure the file buffer has been written into the file.
				ff.Close();
			}
		Return:
			TRUE for success and FALSE for error.
		SeeAlso:
			file::Write.
	*/	
	BOOL	Flush();

	/**
		Remarks:
			Closes the file associated with the indicated file object.  The file is then no longer available for reading and
			writing.
		Example:
			char szTemp[MAXFULLPATH];
			GetTempPath(MAXFULLPATH, szTemp); // Get temp folder path.
			string strFile = szTemp + "\\test.txt";
			file ff;
			if( ff.Open(strFile, file::modeCreate | file::modeWrite) )
			{
				ff.Write(strFile, strFile.GetLength()); // Write the file name into the file.
				ff.Close(); // Close the file when we are done.
			}
		Return:
			A value of FALSE or 0 indicates fail to close file and a value of TRUE or a 
			non-zero indicates sucessfully closing file.
		SeeAlso:
			file::Open.		
	*/
	BOOL	Close(); // Close the file associated with the indicated file object.

	/**
		Remarks:
			Obtains the current logical length of the file in bytes.
		Example:
			string strFile = "c:\\myfile.txt";
			file ff;
			if( ff.Open(strFile, file::modeRead|file::typeBinary) )
			{
				DWORD dwLen = ff.GetLength();
				printf("Length of file %s is %d bytes\n", strFile, dwLen);
				ff.Close();
			}
		Return:
			The length of the file.
	*/
	DWORD GetLength();

	/**
	    Remarks:
			It is used to support Little Endian and Big Endian read and write binary data .
		Example:
           #define INT32_ITEM_COUNT	2
           #define INT16_ITEM_COUNT	4

           // ASCII: A  B  C  D  1  2  3  4
           // HEX  : 41 42 43 44 31 32 33 34
           // 

			int  test_read_endian()
			{
				file fil;
				
				short i16[INT16_ITEM_COUNT];
				long i32[INT32_ITEM_COUNT];
				
				i16[0] = 0x4241;
				i16[1] = 0x4443;
				i16[2] = 0x3231;
				i16[3] = 0x3433;
				
				i32[0] = 0x44434241;
				i32[1] = 0x34333231;
				
				string strFile = "C:\\end.bin";
				
				if( fil.Open(strFile, file::modeCreate | file::modeWrite ) )
				{
					int i = fil.WriteInt(i16, sizeof(short), INT16_ITEM_COUNT);
					ASSERT( INT16_ITEM_COUNT == i);
					
					i = fil.WriteInt(i32, sizeof(long), INT32_ITEM_COUNT);
					ASSERT( INT32_ITEM_COUNT == i);		
					
					i = fil.WriteInt(i16, sizeof(short), INT16_ITEM_COUNT, FALSE);
					ASSERT( INT16_ITEM_COUNT == i);		
					
					i = fil.WriteInt(i32, sizeof(long), INT32_ITEM_COUNT, FALSE);
					ASSERT( INT32_ITEM_COUNT == i);		
					
					fil.Close();		
				}
				
				else
				{
					string strPromptExist = "Before testing, please delete file: " + strFile;
					MessageBox( NULL, strPromptExist );
				}	
				
				if( fil.Open(strFile, file::modeRead|file::shareDenyWrite) )
				{
					int i = fil.ReadInt(i16, sizeof(short), INT16_ITEM_COUNT);
					ASSERT( INT16_ITEM_COUNT == i);
					ASSERT( i16[0] == 0x4241);
					ASSERT( i16[1] == 0x4443);
					ASSERT( i16[2] == 0x3231);
					ASSERT( i16[3] == 0x3433);
					
					fil.SeekToBegin();
					i = fil.ReadInt(i32, sizeof(long), INT32_ITEM_COUNT);
					ASSERT( INT32_ITEM_COUNT == i);
					ASSERT( i32[0] == 0x44434241);
					ASSERT( i32[1] == 0x34333231);
					
					fil.SeekToBegin();
					i = fil.ReadInt(i16, sizeof(short), INT16_ITEM_COUNT, FALSE);
					ASSERT( INT16_ITEM_COUNT == i);
					ASSERT( i16[0] == 0x4142);
					ASSERT( i16[1] == 0x4344);
					ASSERT( i16[2] == 0x3132);
					ASSERT( i16[3] == 0x3334);
					
					fil.SeekToBegin();
					i = fil.ReadInt(i32, sizeof(long), INT32_ITEM_COUNT, FALSE);
					ASSERT( INT32_ITEM_COUNT == i);
					ASSERT( i32[0] == 0x41424344);
					ASSERT( i32[1] == 0x31323334);
					
					fil.Close();
				}
				return 1;
			}			
		Parameters:
			nDataTypeSize: Must be size of datatype, for integal, 1, 2 and 4, for float. 4 and 8.
			nItemCount: Number of data;
			bIsLittleEndian: TRUE, use Little Endian way, FALSE use Big Endian way, default value is TRUE.
		Return:
			The number of items read from file.
	*/
	UINT ReadInt(void *pDestBuffer, int nDataTypeSize, UINT nItemCount, BOOL bIsLittleEndian = TRUE);
	/**
		SeeAlso:
			file::ReadInt.
	*/		
	UINT WriteInt(void *pSrcBuffer, int nDataTypeSize, UINT nItemCount, BOOL bIsLittleEndian = TRUE);
	/**
			Example:
			
			int test_file_readfloat_writefloat()
			{
				file ff;
	
				string strFile = "readwritefloat.dat";
	
				BOOL bOK = ff.Open(strFile, file::modeCreate | file::modeWrite);
				if(!bOK)
				{
					out_str("Could not open the \\readwritefloat.dat file.");
					ASSERT(false);
					return 0;
				}
	
				vector<float> vecfloat={2,4,6,8};
				vector<double> vecdouble={1,3,5,7};
	
				ff.WriteFloat(&vecfloat,sizeof(float),vecfloat.GetSize());
	
				int nposition=ff.GetPosition();
				ASSERT(nposition==16);
	
				ff.WriteFloat(&vecdouble, sizeof(double), vecdouble.GetSize(), false);
	
				nposition=ff.GetPosition();
				ASSERT(nposition==48);
				ff.Close();
	
				bOK = ff.Open(strFile, file::modeRead);
				if(!bOK)
				{
					out_str("Could not open the \\readwritefloat.dat file.");
					ASSERT(false);
					return 0;
				}
	
				ff.SeekToBegin();
	
				vector<float> vecf2(4);
				vector<double> vecd2(4);
	
				ff.ReadFloat(&vecf2,sizeof(float),vecfloat.GetSize());
				ff.ReadFloat(&vecd2,sizeof(double), vecdouble.GetSize(),false);
	
				for(int i=0;i<4;i++)
				{
					printf("%f\t%f\n",vecf2[i],vecd2[i]);
					ASSERT(round(vecfloat[i],8)==round(vecf2[i],8));
					ASSERT(round(vecdouble[i],8)==round(vecd2[i],8));
				}
	
				ff.Close();
	
				return 1;	
		}
		
		SeeAlso:
			file::ReadInt.
	*/	
	UINT ReadFloat(void *pDestBuffer, int nDataTypeSize, UINT nItemCount, BOOL bIsLittleEndian = TRUE);
	/**
		SeeAlso:
			file::ReadFloat.
	*/	
	UINT WriteFloat(void *pSrcBuffer, int nDataTypeSize, UINT nItemCount, BOOL bIsLittleEndian = TRUE);

};


/** >System
		The Origin C stdioFile class provides read/write access to text and binary files using
		buffered stream io. However, the stdioFile class does not support stream io to stdin,
		stdout, and stderr. See also the file class for unbuffered io to binary files. The stdioFile
		class is derived from the file class from which it inherits methods and properties.
	Example:
		// Get the Origin folder path
		string strOriginPath, strFile;
		strOriginPath = GetAppPath() + "OriginC";
		strFile = strOriginPath + "\\test.txt";

		// Create a new standard I/O file.
		stdioFile ff(strFile, file::modeCreate | file::modeReadWrite);

		// Write strings
		string strLine1 = "line 1:";
		string strLine3 = "line 3:";
		ff.WriteString(strLine1);
		ff.WriteString("line 2:");
		ff.WriteString(strLine3);
*/
class stdioFile : public file
{

public:
	// Constructors
	/**
		Remarks:
			The default constructor does not open a file but rather sets m_hFile to file::hFileNull.
		Example:
			stdioFile ff;
	*/
	stdioFile();
	
	/**
		Remarks:
			Creates a stdioFile object and opens the file having the path specified by the parameter lpszFileName.  This
			constructor combines the functions of the default constructor stdioFile() and the Open member function.  An exception
			is thrown if an error occurs while opening the file.  Depending on the severity of the error, the user should be
			alerted by an exception handler.
		Example:
			//Create a new standard I/O file.
			//Get the origin folder path.
			string strOriginPath;
			strOriginPath = GetAppPath() + "OriginC";
			string strFile = strOriginPath + "\\test.txt";
			stdioFile ff(strFile, file::modeCreate | file::modeReadWrite);
		Parameters:
			lpszFileName= Specifies a string that is the path to the desired file. 
						   The path can be relative or absolute.
			nOpenFlags= Sharing and access mode. Specifies the action to take when the file is opened.
	*/
	stdioFile(LPCTSTR lpszFileName, UINT nOpenFlags);

	// Operations
	/**
		Remarks:
			Write a line to a file.  End of line character is appended.
		Example:
			//write string.
			string strLine1 = "line 1:";
			string strLine3 = "line 3:";
			stdioFile ff("c:\\test.txt",file::modeCreate | file::modeReadWrite);
			ff.WriteString(strLine1);
			ff.WriteString("line 2:");
			ff.WriteString(strLine3);
		Parameter:
			lpcsz = Specifies a pointer to a buffer containing a null-terminated string.
		Return:
			the length of lpcsz.
		SeeAlso:
			stdioFile::ReadString.
	*/
	int WriteString(LPCTSTR lpcsz);

	/**
			Read a line from a file into a string.  The end of line character is removed.
		Remarks:
			strings in ascii file might be separated by "\r\n", as typical of files fom DOS/Windows
			or can be just "\n" or just "\r", as typical of unix and MAC files. Both forms are supported by this function.
			This function will also return TRUE on the last line even if it does not have a "\n" or "\r" termination. In
			other words, when reaching the end of a file, the function returns FALSE and the resulting string will always be empty.
			Please note a size limitation of 32762 characters for this function, so longer lines will be broken into multiple lines.
		Example:
			//the following example will type out any ascii files from the User folder
			void show_file(string strfile = "origin.ini")
			{
				string strFilename = GetAppPath() + strfile;
				stdioFile ff;
				bool bRet = ff.Open(strFilename, file::modeRead);
				if(!bRet)
				{
					out_str("file not found!");
					return;
				}
				
				string strTemp;
				while(ff.ReadString(strTemp))
					out_str(strTemp);
				
				ff.Close();
			}
		Parameter:
			str=A reference to a string object that will contain the string when the function returns.
		Return:
			TRUE for success, FALSE for end of file reached, or other error.
		SeeAlso:
			stdioFile::WriteString.
	*/	
	BOOL ReadString(string& str);
};

#endif //_FILE_H
