/** ******************************************************************************* * @file etk/File.cpp * @brief Ewol Tool Kit : File folder and name abstraction (Sources) * @author Edouard DUPIN * @date 16/07/2011 * @par Project * Ewol TK * * @par Copyright * Copyright 2011 Edouard DUPIN, all right reserved * * This software is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY. * * Licence summary : * You can modify and redistribute the sources code and binaries. * You can send me the bug-fix * * Term of the licence in in the file licence.txt. * ******************************************************************************* */ #include #include #include #include #ifdef DATA_INTERNAL_BINARY # include "GeneratedData.h" #endif #undef __class__ #define __class__ "etk::File" etk::CCout& etk::operator <<(etk::CCout &os, const etk::File &obj) { os << obj.m_folder; os << "/"; os << obj.m_shortFilename; return os; } etk::File::File(etk::String &filename, etk::FileType_te type, int32_t LineNumber) { m_lineNumberOpen = LineNumber; m_PointerFile = NULL; SetCompleateName(filename, type); } etk::File::File(const char *filename, etk::FileType_te type, int32_t LineNumber) { etk::String tmpString = filename; m_lineNumberOpen = LineNumber; m_PointerFile = NULL; SetCompleateName(tmpString, type); } etk::File::File(etk::String &filename, etk::String &folder, etk::FileType_te type, int32_t lineNumber) { etk::String tmpString = folder; tmpString += '/'; tmpString += filename; m_PointerFile = NULL; SetCompleateName(tmpString, type); m_lineNumberOpen = lineNumber; } etk::File::~File(void) { // nothing to do ... if (NULL != m_PointerFile) { TK_ERROR("Missing close the file : \"" << GetCompleateName() << "\""); fClose(); } } etk::String etk::File::GetFolder(void) const { return m_folder; } etk::String etk::File::GetShortFilename(void) const { return m_shortFilename; } etk::String etk::File::GetCompleateName(void) const { etk::String out; out = m_folder; out += '/'; out += m_shortFilename; return out; } const etk::File& etk::File::operator= (const etk::File &etkF ) { if( this != &etkF ) // avoid copy to itself { m_folder = etkF.m_folder; m_shortFilename = etkF.m_shortFilename; m_lineNumberOpen = etkF.m_lineNumberOpen; m_type = etkF.m_type; if (NULL != m_PointerFile) { TK_ERROR("Missing close the file : \"" << GetCompleateName() << "\""); fClose(); } #ifdef DATA_INTERNAL_BINARY m_idInternal = etkF.m_idInternal; m_readingOffset = 0; #endif } return *this; } /** * @brief * * @param[in,out] * * @return * */ bool etk::File::operator== (const etk::File &etkF) const { if( this != &etkF ) { if (etkF.GetCompleateName() == GetCompleateName() ) { return true; } else { return false; } return true; } return true; } /** * @brief * * @param[in,out] * * @return * */ bool etk::File::operator!= (const etk::File &etkF) const { return !(*this == etkF); } etk::String baseFolderData = "./"; etk::String baseFolderDataUser = "~/.tmp/userData"; etk::String baseFolderCache = "~/.tmp/cache"; // for specific device contraint : void etk::SetBaseFolderData(const char * folder) { baseFolderData = folder; } void etk::SetBaseFolderDataUser(const char * folder) { baseFolderDataUser = folder; } void etk::SetBaseFolderCache(const char * folder) { baseFolderCache = folder; } void etk::File::SetCompleateName(etk::String &newFilename, etk::FileType_te type) { char buf[MAX_FILE_NAME]; memset(buf, 0, MAX_FILE_NAME); char * ok; #ifdef DATA_INTERNAL_BINARY m_idInternal = -1; #endif // Reset ALL DATA : m_folder = ""; m_shortFilename = ""; m_lineNumberOpen = 0; TK_VERBOSE("1 :Set Name : " << newFilename ); etk::String destFilename; if (newFilename.Size() == 0) { destFilename = "no-name"; } else { destFilename = newFilename; } TK_VERBOSE("2 : Get file Name : " << destFilename ); if ('/' == *destFilename.c_str()) { m_type = etk::FILE_TYPE_DIRECT; if (type != etk::FILE_TYPE_DIRECT) { TK_WARNING("Incompatible type with a file=\"" << newFilename << "\" ==> force it in direct mode ..."); } } else { if (type == etk::FILE_TYPE_DIRECT) { TK_WARNING("Incompatible type with a file=\"" << newFilename << "\" ==> force it in FILE_TYPE_DATA mode ..."); m_type = etk::FILE_TYPE_DATA; } else { m_type = type; } } bool needUnpack = false; #if ETK_DEBUG_LEVEL > 3 char *mode = NULL; #endif switch (m_type) { case etk::FILE_TYPE_DATA: { #if ETK_DEBUG_LEVEL > 3 mode = "FILE_TYPE_DATA"; #endif #ifdef DATA_INTERNAL_BINARY for(int32_t iii=0; iii 3 mode = "FILE_TYPE_USER_DATA"; #endif etk::String tmpFilename = destFilename; destFilename = baseFolderDataUser; destFilename += '/'; destFilename += tmpFilename; } needUnpack = true; break; case etk::FILE_TYPE_CACHE: { #if ETK_DEBUG_LEVEL > 3 mode = "FILE_TYPE_CACHE"; #endif etk::String tmpFilename = destFilename; destFilename = baseFolderCache; destFilename += '/'; destFilename += tmpFilename; } needUnpack = true; break; default: // nothing to do ... #if ETK_DEBUG_LEVEL > 3 mode = "FILE_TYPE_DIRECT"; #endif needUnpack = true; break; } TK_VERBOSE("3 : Get file Name : " << destFilename ); if (true == needUnpack) { // Get the real Path of the current File ok = realpath(destFilename.c_str(), buf); if (!ok) { int32_t lastPos = destFilename.FindBack('/'); if (-1 != lastPos) { // Get the FileName etk::String tmpFilename = destFilename.Extract(lastPos+1); destFilename.Remove(lastPos, destFilename.Size() - lastPos); TK_VERBOSE("try to find :\"" << destFilename << "\" / \"" << tmpFilename << "\" "); ok = realpath(destFilename.c_str(), buf); if (!ok) { TK_VERBOSE("Can not find real Path name of \"" << destFilename << "\""); m_shortFilename = tmpFilename; m_folder = destFilename; } else { // ALL is OK ... m_shortFilename = tmpFilename; m_folder = destFilename; } } else { TK_WARNING("file : \"" << destFilename << "\" ==> No data???"); // Basic ERROR ... m_shortFilename = destFilename; } } else { destFilename = buf; int32_t lastPos = destFilename.FindBack('/'); if (-1 != lastPos) { m_shortFilename = destFilename.Extract(lastPos+1); m_folder = destFilename.Extract(0, lastPos); } else { // Basic ERROR ... TK_WARNING("file : \"" << destFilename << "\" ==> No data???"); m_shortFilename = destFilename; } } } else { int32_t lastPos = destFilename.FindBack('/'); if (-1 != lastPos) { m_shortFilename = destFilename.Extract(lastPos+1); m_folder = destFilename.Extract(0, lastPos); } else { // Basic ERROR ... TK_WARNING("file : \"" << destFilename << "\" ==> No data???"); m_shortFilename = destFilename; } } TK_VERBOSE("Set FileName :\"" << m_folder << "\" / \"" << m_shortFilename << "\" mode=" << mode); } int32_t etk::File::GetLineNumber(void) { return m_lineNumberOpen; } void etk::File::SetLineNumber(int32_t newline) { m_lineNumberOpen = newline; } bool etk::File::HasExtention(void) { int32_t lastPos = m_shortFilename.FindBack('.'); if( -1 != lastPos // not find the . && 0 != lastPos // Find a . at the fist position .jdlskjdfklj ==> hiden file && m_shortFilename.Size() != lastPos ) // Remove file ended with . { return true; } else { return false; } } etk::String etk::File::GetExtention(void) { etk::String tmpExt = ""; int32_t lastPos = m_shortFilename.FindBack('.'); if( -1 != lastPos // not find the . && 0 != lastPos // Find a . at the fist position .jdlskjdfklj ==> hiden file && m_shortFilename.Size() != lastPos ) // Remove file ended with . { // Get the FileName tmpExt = m_shortFilename.Extract(lastPos+1); } return tmpExt; } int32_t etk::File::Size(void) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { return internalDataFiles[m_idInternal].fileLenght; } return 0; } #endif FILE *myFile=NULL; etk::String myCompleateName = GetCompleateName(); myFile=fopen(myCompleateName.c_str(),"rb"); if(NULL == myFile) { //EWOL_ERROR("Can not find the file name=\"" << m_folder << "\" / \"" << m_shortFilename << "\""); return -1; } int32_t size = 0; fseek(myFile, 0, SEEK_END); size = ftell(myFile); fseek(myFile, 0, SEEK_SET); fclose(myFile); return size; } bool etk::File::Exist(void) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { return true; } return false; } #endif FILE *myFile=NULL; etk::String myCompleateName = GetCompleateName(); myFile=fopen(myCompleateName.c_str(),"rb"); if(NULL == myFile) { return false; } fclose(myFile); return true; } bool etk::File::fOpenRead(void) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { m_readingOffset = 0; if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { TK_DEBUG("Open file : " << GetCompleateName() << " with size=" << internalDataFilesSize << " Octets"); return true; } return false; } #endif if (NULL != m_PointerFile) { TK_CRITICAL("File Already open : \"" << GetCompleateName() << "\""); return true; } m_PointerFile=fopen(GetCompleateName().c_str(),"rb"); if(NULL == m_PointerFile) { TK_ERROR("Can not find the file name=\"" << GetCompleateName() << "\""); return false; } return true; } bool etk::File::fOpenWrite(void) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { m_readingOffset = 0; return false; } #endif if (NULL != m_PointerFile) { TK_CRITICAL("File Already open : \"" << GetCompleateName() << "\""); return true; } m_PointerFile=fopen(GetCompleateName().c_str(),"wb"); if(NULL == m_PointerFile) { TK_ERROR("Can not find the file name=\"" << GetCompleateName() << "\""); return false; } return true; } bool etk::File::fClose(void) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { m_readingOffset = 0; if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { return true; } return false; } #endif if (NULL == m_PointerFile) { TK_CRITICAL("File Already closed : \"" << GetCompleateName() << "\""); return false; } fclose(m_PointerFile); m_PointerFile = NULL; return true; } char * etk::File::fGets(char * elementLine, int32_t maxData) { #ifdef DATA_INTERNAL_BINARY char * element = elementLine; if (etk::FILE_TYPE_DATA == m_type) { if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { // TODO ... //char * tmpData = internalDataFiles[iii].data + m_readingOffset; if (m_readingOffset>internalDataFilesSize) { element[0] = '\0'; return NULL; } while (internalDataFiles[m_idInternal].data[m_readingOffset] != '\0') { if( internalDataFiles[m_idInternal].data[m_readingOffset] == '\n' || internalDataFiles[m_idInternal].data[m_readingOffset] == '\r') { *element = internalDataFiles[m_idInternal].data[m_readingOffset]; element++; m_readingOffset++; *element = '\0'; return elementLine; } *element = internalDataFiles[m_idInternal].data[m_readingOffset]; element++; m_readingOffset++; // TODO : Understand why this does not work /*if (m_readingOffset>internalDataFilesSize) { *element = '\0'; return elementLine; }*/ } } return NULL; } #endif return fgets(elementLine, maxData, m_PointerFile); } int32_t etk::File::fRead(void * data, int32_t blockSize, int32_t nbBlock) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { int32_t dataToRead = blockSize * nbBlock; if (dataToRead + m_readingOffset > internalDataFilesSize) { nbBlock = ((internalDataFilesSize - m_readingOffset) / blockSize); dataToRead = blockSize * nbBlock; } memcpy(data, &internalDataFiles[m_idInternal].data[m_readingOffset], dataToRead); m_readingOffset +=dataToRead; return nbBlock; } return 0; } #endif return fread(data, blockSize, nbBlock, m_PointerFile); } int32_t etk::File::fWrite(void * data, int32_t blockSize, int32_t nbBlock) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { TK_CRITICAL("Can not write on data inside memory : \"" << GetCompleateName() << "\""); return 0; } #endif return fwrite(data, blockSize, nbBlock, m_PointerFile); } char * etk::File::GetDirectPointer(void) { #ifdef DATA_INTERNAL_BINARY if (etk::FILE_TYPE_DATA == m_type) { if (m_idInternal >= -1 && m_idInternal < internalDataFilesSize) { return (char*)internalDataFiles[m_idInternal].data; } } #endif return NULL; }