Example #1
0
bool CParaFile::OpenFile(const char* sfilename, bool bReadyOnly, const char* relativePath, bool bUseCompressed, uint32 dwWhereToOpen)
{
	int32 dwFoundPlace = FILE_NOT_FOUND;
	if (!GetDevDirectory().empty() && dwWhereToOpen != FILE_ON_ZIP_ARCHIVE && ((dwWhereToOpen & FILE_ON_ZIP_ARCHIVE) > 0))
	{
		// in development version, find in current directory and search path and then zip archive
		dwWhereToOpen &= (~((uint32)FILE_ON_ZIP_ARCHIVE));
		return OpenFile(sfilename, bReadyOnly, relativePath, bUseCompressed, dwWhereToOpen) ||
			OpenFile(m_filename.empty() ? sfilename : m_filename.c_str(), bReadyOnly, relativePath, bUseCompressed, FILE_ON_ZIP_ARCHIVE);
	}

	if ((dwWhereToOpen & FILE_ON_SEARCH_PATH) > 0)
	{
		dwWhereToOpen &= (~((uint32)FILE_ON_SEARCH_PATH));

		std::list<SearchPath>& searchPaths = CFileManager::GetInstance()->GetSearchPaths();

		if (searchPaths.size() == 0 || (sfilename[0] == '/') || (sfilename[0] == '\\') || relativePath != NULL)
		{
			if (dwWhereToOpen!=0)
				return OpenFile(sfilename, bReadyOnly, relativePath, bUseCompressed, dwWhereToOpen);
			return false;
		}
		else
		{
			// find in current directory and zip file, and then in search path
			bool bFound = (dwWhereToOpen != 0) && OpenFile(sfilename, bReadyOnly, relativePath, bUseCompressed, dwWhereToOpen);
			if (!bFound)
			{
				if (!m_filename.empty())
					sfilename = m_filename.c_str();
				list<SearchPath>::iterator itCurCP, itEndCP = searchPaths.end();
				for (itCurCP = searchPaths.begin(); !bFound && itCurCP != itEndCP; ++itCurCP)
				{
					bFound = OpenFile(sfilename, bReadyOnly, (*itCurCP).GetPath().c_str(), bUseCompressed, FILE_ON_DISK);
				}
			}
			return bFound;
		}
	}

	m_bIsOwner = true;
	char filename[MAX_PATH];

	int i = 0;
	int j = 0;
#ifdef WIN32
	// remove the heading slash
	if ((sfilename[0] == '/') || (sfilename[0] == '\\'))
		i++;
#endif

	// replace '\\' with '/'
	for (; sfilename[i] != '\0' && j<(MAX_PATH - 1); i++, j++)
	{
		if (sfilename[i] == '\\')
			filename[j] = '/';
		else
			filename[j] = sfilename[i];
	}
	filename[j] = '\0';

	/// append the relative path
	if (relativePath != NULL)
	{
		char sRelativePath[MAX_PATH];
		int nLastSlash = -1;
		for (int i = 0; relativePath[i] != '\0' && i<(MAX_PATH - 1); i++)
		{
			if (relativePath[i] == '\\')
				sRelativePath[i] = '/';
			else
				sRelativePath[i] = relativePath[i];
			if (sRelativePath[i] == '/')
				nLastSlash = i;
		}
		sRelativePath[nLastSlash + 1] = '\0';

		if (sRelativePath[0] != '\0')
		{
			string sPath = sRelativePath;
			sPath.append(filename);
			strncpy(filename, sPath.c_str(), MAX_PATH);
		}
	}

	if (m_filename.empty())
		m_filename = filename;

	if (CFileReplaceMap::GetSingleton().ReplaceFile(m_filename))
	{
		strcpy(filename, m_filename.c_str());
	}

	if (bReadyOnly)
	{
		if (!(!m_filename.empty() && m_filename[0] == ':'))
		{
			BOOL succ = FALSE;
			/// for ready-only file, we will read everything in to the buffer, and close the file handle
			if ((dwWhereToOpen & FILE_ON_DISK)>0 && GetDiskFilePriority() >= 0)
			{
				FileData data = CFileUtils::GetDataFromFile(filename);
				if (!data.isNull())
				{
					m_buffer = data.GetBytes();
					m_size = data.GetSize();
					data.ReleaseOwnership();
					m_eof = FALSE;
					succ = TRUE;
				}
			}

			if (!succ && (dwWhereToOpen & FILE_ON_ZIP_ARCHIVE)>0)
			{
				CFileManager* pFileManager = CFileManager::GetInstance();
				/// load from Zip files, if the file does not exist on disk
				succ = pFileManager->OpenFile(filename, m_handle);
				m_curPos = 0;
				if (succ)
				{
					if (bUseCompressed)
					{
						DWORD compressedSize = 0;
						DWORD uncompressedSize = 0;
						if (pFileManager->ReadFileRaw(m_handle, (LPVOID*)(&m_buffer), &compressedSize, &uncompressedSize))
						{
							m_size = compressedSize;
							m_uncompressed_size = uncompressedSize;
							// this fix a bug for non-compressed files
							if (m_uncompressed_size > 0)
								SetIsCompressed(true);
							m_eof = false;
						}
						else
						{
							m_buffer = 0;
							m_eof = true;
						}
					}
					else
					{
						DWORD s = pFileManager->GetFileSize(m_handle);
						DWORD bytesRead = 0;
						m_buffer = new char[s + 1];
						m_buffer[s] = '\0';
						pFileManager->ReadFile(m_handle, m_buffer, s, &bytesRead);
						pFileManager->CloseFile(m_handle);
						m_size = (size_t)bytesRead;
						m_eof = false;
					}

				}
				else
				{
					m_eof = true;
					m_buffer = 0;
				}
			}

			if (!succ && GetDiskFilePriority()<0 && (dwWhereToOpen & FILE_ON_DISK)>0)
			{
				FileData data = CFileUtils::GetDataFromFile(filename);
				if (!data.isNull())
				{
					m_buffer = data.GetBytes();
					m_size = data.GetSize();
					data.ReleaseOwnership();
					m_eof = FALSE;
					succ = TRUE;
				}
			}

			/** extract file to disk for debugging purposes. */
			if (m_bExtractFileToDisk && !isEof())
			{
				string filenameDest = m_strExtractRootPath;
				filenameDest.append(filename);
				ExtractFileToDisk(filenameDest, false);
			}
		}
		else
		{
			/** If the file name begins with ':', it is treated as a win32 resource.
			e.g.":IDR_FX_OCEANWATER". loads data from a resource of type "TEXTFILE". See MSDN for more information about Windows resources.*/
			m_eof = true;
			FileData data = CFileUtils::GetResDataFromFile(filename);
			if (!data.isNull())
			{
				m_buffer = data.GetBytes();
				m_size = data.GetSize();
				data.ReleaseOwnership();
				m_bIsOwner = false; // resource file do not need to be deleted on Close().
				m_eof = false;
			}
		}
	}
	else
	{
		/// for write-only file, we will save file handle.
		m_eof = true; /// set end of file to prevent read access.

		if (m_filename == "<memory>")
		{
			m_bMemoryFile = true;
			m_bIsOwner = false;
			m_handle.m_pVoidPtr = new StringBuilder();
			return true;
		}
		else
		{

			FileHandle fileHandle = CFileUtils::OpenFile(filename, false, true);

			if (fileHandle.IsValid())
			{
				m_handle = fileHandle;
				m_bDiskFileOpened = true;
				return true;
			}
			else
				m_bDiskFileOpened = false;
		}
		return false;
	}
#ifdef FILE_LOGGER_HOOK
	if (CFileLogger::GetInstance()->IsBegin())
	{
		if (!m_eof && !m_filename.empty() && m_filename[0] != ':')
		{
			CFileLogger::GetInstance()->AddFile(m_filename.c_str(), bReadyOnly);
		}
	}
#endif
	return !m_eof;
}