From e65b01bdc035719fbeec87f2b3f8f67f35e4cdb1 Mon Sep 17 00:00:00 2001 From: Vincent Yang Date: Mon, 13 Jul 2015 17:06:01 +0800 Subject: [PATCH 1/2] Merge pr11866: FileUtilsWin32 correct use all unicode version winapi. --- cocos/platform/CCFileUtils.cpp | 312 ++++-------------- cocos/platform/CCFileUtils.h | 2 +- cocos/platform/apple/CCFileUtils-apple.h | 3 +- cocos/platform/apple/CCFileUtils-apple.mm | 25 +- cocos/platform/linux/CCFileUtils-linux.cpp | 10 - cocos/platform/linux/CCFileUtils-linux.h | 1 - cocos/platform/win32/CCFileUtils-win32.cpp | 310 ++++++++++++++--- cocos/platform/win32/CCFileUtils-win32.h | 48 ++- cocos/platform/winrt/CCFileUtilsWinRT.cpp | 203 +++++++++++- cocos/platform/winrt/CCFileUtilsWinRT.h | 43 ++- .../proj.android-studio/app/jni/Android.mk | 5 +- .../cpp-tests.Shared.vcxitems.filters | 6 +- 12 files changed, 640 insertions(+), 328 deletions(-) diff --git a/cocos/platform/CCFileUtils.cpp b/cocos/platform/CCFileUtils.cpp index c554be52a0..bd7803cafb 100644 --- a/cocos/platform/CCFileUtils.cpp +++ b/cocos/platform/CCFileUtils.cpp @@ -41,24 +41,12 @@ THE SOFTWARE. #endif #include -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) -#include -#endif +NS_CC_BEGIN -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) -#include -#endif - -#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) -#include -#include -#include -#endif +// Implement DictMaker #if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) && (CC_TARGET_PLATFORM != CC_PLATFORM_MAC) -NS_CC_BEGIN - typedef enum { SAX_NONE = 0, @@ -540,7 +528,6 @@ static tinyxml2::XMLElement* generateElementForArray(const ValueVector& array, t } #else -NS_CC_BEGIN /* The subclass FileUtilsApple should override these two method. */ ValueMap FileUtils::getValueMapFromFile(const std::string& filename) {return ValueMap();} @@ -550,6 +537,7 @@ bool FileUtils::writeToFile(ValueMap& dict, const std::string &fullPath) {return #endif /* (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) && (CC_TARGET_PLATFORM != CC_PLATFORM_MAC) */ +// Implement FileUtils FileUtils* FileUtils::s_sharedFileUtils = nullptr; void FileUtils::destroyInstance() @@ -1070,6 +1058,59 @@ bool FileUtils::isDirectoryExist(const std::string& dirPath) const return false; } +#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + +bool FileUtils::isDirectoryExistInternal(const std::string& dirPath) const +{ + CCASSERT(false, "FileUtils not support isDirectoryExistInternal"); + return false; +} + +bool FileUtils::createDirectory(const std::string& path) +{ + CCASSERT(false, "FileUtils not support createDirectory"); + return false; +} + +bool FileUtils::removeDirectory(const std::string& path) +{ + CCASSERT(false, "FileUtils not support removeDirectory"); + return false; +} + +bool FileUtils::removeFile(const std::string &path) +{ + CCASSERT(false, "FileUtils not support removeFile"); + return false; +} + +bool FileUtils::renameFile(const std::string &path, const std::string &oldname, const std::string &name) +{ + CCASSERT(false, "FileUtils not support renameFile"); + return false; +} + +std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const +{ + CCASSERT(false, "getSuitableFOpen should be override by platform FileUtils"); + return filenameUtf8; +} + +#else +#include +#include +#include + +bool FileUtils::isDirectoryExistInternal(const std::string& dirPath) const +{ + struct stat st; + if (stat(dirPath.c_str(), &st) == 0) + { + return S_ISDIR(st.st_mode); + } + return false; +} + bool FileUtils::createDirectory(const std::string& path) { CCASSERT(!path.empty(), "Invalid path"); @@ -1103,47 +1144,6 @@ bool FileUtils::createDirectory(const std::string& path) } } - -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) - WIN32_FILE_ATTRIBUTE_DATA wfad; - std::wstring wpath(path.begin(), path.end()); - if (!(GetFileAttributesEx(wpath.c_str(), GetFileExInfoStandard, &wfad))) - { - subpath = ""; - for(unsigned int i = 0 ; i < dirs.size() ; ++i) - { - subpath += dirs[i]; - if (i > 0 && !isDirectoryExist(subpath)) - { - std::wstring wsubpath(subpath.begin(), subpath.end()); - BOOL ret = CreateDirectory(wsubpath.c_str(), NULL); - if (!ret && ERROR_ALREADY_EXISTS != GetLastError()) - { - return false; - } - } - } - } - return true; -#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) - if ((GetFileAttributesA(path.c_str())) == INVALID_FILE_ATTRIBUTES) - { - subpath = ""; - for (unsigned int i = 0; i < dirs.size(); ++i) - { - subpath += dirs[i]; - if (!isDirectoryExist(subpath)) - { - BOOL ret = CreateDirectoryA(subpath.c_str(), NULL); - if (!ret && ERROR_ALREADY_EXISTS != GetLastError()) - { - return false; - } - } - } - } - return true; -#else DIR *dir = NULL; // Create path recursively @@ -1172,22 +1172,8 @@ bool FileUtils::createDirectory(const std::string& path) } } return true; -#endif } -#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) -static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) -{ - auto ret = remove(fpath); - if (ret) - { - log("Fail to remove: %s ",fpath); - } - - return ret; -} -#endif - bool FileUtils::removeDirectory(const std::string& path) { if (path.size() > 0 && path[path.size() - 1] != '/') @@ -1196,58 +1182,6 @@ bool FileUtils::removeDirectory(const std::string& path) return false; } - // Remove downloaded files - -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) - std::wstring wpath = std::wstring(path.begin(), path.end()); - std::wstring files = wpath + L"*.*"; - WIN32_FIND_DATA wfd; - HANDLE search = FindFirstFileEx(files.c_str(), FindExInfoStandard, &wfd, FindExSearchNameMatch, NULL, 0); - bool ret=true; - if (search!=INVALID_HANDLE_VALUE) - { - BOOL find=true; - while (find) - { - //. .. - if(wfd.cFileName[0]!='.') - { - std::wstring temp = wpath + wfd.cFileName; - if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - temp += '/'; - ret = ret && this->removeDirectory(std::string(temp.begin(), temp.end())); - } - else - { - SetFileAttributes(temp.c_str(), FILE_ATTRIBUTE_NORMAL); - ret = ret && DeleteFile(temp.c_str()); - } - } - find = FindNextFile(search, &wfd); - } - FindClose(search); - } - if (ret && RemoveDirectory(wpath.c_str())) - { - return true; - } - return false; -#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) - std::string command = "cmd /c rd /s /q "; - // Path may include space. - command += "\"" + path + "\""; - - if (WinExec(command.c_str(), SW_HIDE) > 31) - return true; - else - return false; -#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) - if (nftw(path.c_str(),unlink_cb, 64, FTW_DEPTH | FTW_PHYS)) - return false; - else - return true; -#else std::string command = "rm -r "; // Path may include space. command += "\"" + path + "\""; @@ -1255,44 +1189,15 @@ bool FileUtils::removeDirectory(const std::string& path) return true; else return false; -#endif } bool FileUtils::removeFile(const std::string &path) { - // Remove downloaded file - -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) - std::wstring wpath(path.begin(), path.end()); - if (DeleteFile(wpath.c_str())) - { - return true; - } - return false; -#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) - std::string command = "cmd /c del /q "; - std::string win32path = path; - int len = win32path.length(); - for (int i = 0; i < len; ++i) - { - if (win32path[i] == '/') - { - win32path[i] = '\\'; - } - } - command += win32path; - - if (WinExec(command.c_str(), SW_HIDE) > 31) - return true; - else - return false; -#else if (remove(path.c_str())) { return false; } else { return true; } -#endif } bool FileUtils::renameFile(const std::string &path, const std::string &oldname, const std::string &name) @@ -1301,41 +1206,6 @@ bool FileUtils::renameFile(const std::string &path, const std::string &oldname, std::string oldPath = path + oldname; std::string newPath = path + name; - // Rename a file -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) - std::regex pat("\\/"); - std::string _old = std::regex_replace(oldPath, pat, "\\"); - std::string _new = std::regex_replace(newPath, pat, "\\"); - if (MoveFileEx(std::wstring(_old.begin(), _old.end()).c_str(), - std::wstring(_new.begin(), _new.end()).c_str(), - MOVEFILE_REPLACE_EXISTING & MOVEFILE_WRITE_THROUGH)) - { - return true; - } - return false; -#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) - std::regex pat("\\/"); - std::string _old = std::regex_replace(oldPath, pat, "\\"); - std::string _new = std::regex_replace(newPath, pat, "\\"); - - if(FileUtils::getInstance()->isFileExist(_new)) - { - if (!DeleteFileA(_new.c_str())) - { - CCLOGERROR("Fail to delete file %s !Error code is 0x%x", newPath.c_str(), GetLastError()); - } - } - - if (MoveFileA(_old.c_str(), _new.c_str())) - { - return true; - } - else - { - CCLOGERROR("Fail to rename file %s to %s !Error code is 0x%x", oldPath.c_str(), newPath.c_str(), GetLastError()); - return false; - } -#else int errorCode = rename(oldPath.c_str(), newPath.c_str()); if (0 != errorCode) @@ -1344,9 +1214,14 @@ bool FileUtils::renameFile(const std::string &path, const std::string &oldname, return false; } return true; -#endif } +std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const +{ + return filenameUtf8; +} + +#endif long FileUtils::getFileSize(const std::string &filepath) { CCASSERT(!filepath.empty(), "Invalid path"); @@ -1390,68 +1265,5 @@ bool FileUtils::isPopupNotify() const return s_popupNotify; } -#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) -static std::wstring StringUtf8ToWideChar(const std::string& strUtf8) -{ - std::wstring ret; - if (!strUtf8.empty()) - { - int nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, nullptr, 0); - if (nNum) - { - WCHAR* wideCharString = new WCHAR[nNum + 1]; - wideCharString[0] = 0; - - nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, wideCharString, nNum + 1); - - ret = wideCharString; - delete[] wideCharString; - } - else - { - CCLOG("Wrong convert to WideChar code:0x%x", GetLastError()); - } - } - return ret; -} - -static std::string UTF8StringToMultiByte(const std::string& strUtf8) -{ - std::string ret; - if (!strUtf8.empty()) - { - std::wstring strWideChar = StringUtf8ToWideChar(strUtf8); - int nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE); - if (nNum) - { - char* ansiString = new char[nNum + 1]; - ansiString[0] = 0; - - nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, ansiString, nNum + 1, nullptr, FALSE); - - ret = ansiString; - delete[] ansiString; - } - else - { - CCLOG("Wrong convert to Ansi code:0x%x", GetLastError()); - } - } - - return ret; -} - -std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const -{ - return UTF8StringToMultiByte(filenameUtf8); -} -#else -std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const -{ - return filenameUtf8; -} - -#endif - NS_CC_END diff --git a/cocos/platform/CCFileUtils.h b/cocos/platform/CCFileUtils.h index aa788aa11e..5b11a3c730 100644 --- a/cocos/platform/CCFileUtils.h +++ b/cocos/platform/CCFileUtils.h @@ -497,7 +497,7 @@ protected: * @param dirPath The directory (with absolute path) to look up for * @return Returns true if the directory found at the given absolute path, otherwise returns false */ - virtual bool isDirectoryExistInternal(const std::string& dirPath) const = 0; + virtual bool isDirectoryExistInternal(const std::string& dirPath) const; /** * Gets full path for filename, resolution directory and search path. diff --git a/cocos/platform/apple/CCFileUtils-apple.h b/cocos/platform/apple/CCFileUtils-apple.h index 8d23520e74..add8109323 100644 --- a/cocos/platform/apple/CCFileUtils-apple.h +++ b/cocos/platform/apple/CCFileUtils-apple.h @@ -57,7 +57,8 @@ public: void setBundle(NSBundle* bundle); private: virtual bool isFileExistInternal(const std::string& filePath) const override; - virtual bool isDirectoryExistInternal(const std::string& dirPath) const override; + virtual bool removeDirectory(const std::string& dirPath) override; + NSBundle* getBundle() const; NSBundle* _bundle; }; diff --git a/cocos/platform/apple/CCFileUtils-apple.mm b/cocos/platform/apple/CCFileUtils-apple.mm index 4debc348b0..d4aa2e76df 100644 --- a/cocos/platform/apple/CCFileUtils-apple.mm +++ b/cocos/platform/apple/CCFileUtils-apple.mm @@ -394,14 +394,29 @@ bool FileUtilsApple::isFileExistInternal(const std::string& filePath) const return ret; } -bool FileUtilsApple::isDirectoryExistInternal(const std::string& dirPath) const +static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - struct stat st; - if (stat(dirPath.c_str(), &st) == 0) + auto ret = remove(fpath); + if (ret) { - return S_ISDIR(st.st_mode); + log("Fail to remove: %s ",fpath); } - return false; + + return ret; +} + +bool FileUtilsApple::removeDirectory(const std::string& path) +{ + if (path.size() > 0 && path[path.size() - 1] != '/') + { + CCLOGERROR("Fail to remove directory, path must termniate with '/': %s", path.c_str()); + return false; + } + + if (nftw(path.c_str(),unlink_cb, 64, FTW_DEPTH | FTW_PHYS)) + return false; + else + return true; } std::string FileUtilsApple::getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const diff --git a/cocos/platform/linux/CCFileUtils-linux.cpp b/cocos/platform/linux/CCFileUtils-linux.cpp index 7cd958ffb7..cd915e940d 100644 --- a/cocos/platform/linux/CCFileUtils-linux.cpp +++ b/cocos/platform/linux/CCFileUtils-linux.cpp @@ -122,16 +122,6 @@ bool FileUtilsLinux::isFileExistInternal(const std::string& strFilePath) const return (stat(strPath.c_str(), &sts) != -1) ? true : false; } -bool FileUtilsLinux::isDirectoryExistInternal(const std::string& dirPath) const -{ - struct stat st; - if (stat(dirPath.c_str(), &st) == 0) - { - return S_ISDIR(st.st_mode); - } - return false; -} - NS_CC_END #endif // CC_TARGET_PLATFORM == CC_PLATFORM_LINUX diff --git a/cocos/platform/linux/CCFileUtils-linux.h b/cocos/platform/linux/CCFileUtils-linux.h index 1605e8289f..2cddbb5ecb 100644 --- a/cocos/platform/linux/CCFileUtils-linux.h +++ b/cocos/platform/linux/CCFileUtils-linux.h @@ -53,7 +53,6 @@ public: virtual std::string getWritablePath() const; private: virtual bool isFileExistInternal(const std::string& strFilePath) const override; - virtual bool isDirectoryExistInternal(const std::string& dirPath) const override; }; // end of platform group diff --git a/cocos/platform/win32/CCFileUtils-win32.cpp b/cocos/platform/win32/CCFileUtils-win32.cpp index 488e761052..27a2444809 100644 --- a/cocos/platform/win32/CCFileUtils-win32.cpp +++ b/cocos/platform/win32/CCFileUtils-win32.cpp @@ -30,6 +30,7 @@ THE SOFTWARE. #include "platform/CCCommon.h" #include #include +#include using namespace std; @@ -56,6 +57,81 @@ static inline std::string convertPathFormatToUnixStyle(const std::string& path) return ret; } +static std::wstring StringUtf8ToWideChar(const std::string& strUtf8) +{ + std::wstring ret; + if (!strUtf8.empty()) + { + int nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, nullptr, 0); + if (nNum) + { + WCHAR* wideCharString = new WCHAR[nNum + 1]; + wideCharString[0] = 0; + + nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, wideCharString, nNum + 1); + + ret = wideCharString; + delete[] wideCharString; + } + else + { + CCLOG("Wrong convert to WideChar code:0x%x", GetLastError()); + } + } + return ret; +} + +static std::string StringWideCharToUtf8(const std::wstring& strWideChar) +{ + std::string ret; + if (!strWideChar.empty()) + { + int nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE); + if (nNum) + { + char* utf8String = new char[nNum + 1]; + utf8String[0] = 0; + + nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, utf8String, nNum + 1, nullptr, FALSE); + + ret = utf8String; + delete[] utf8String; + } + else + { + CCLOG("Wrong convert to Utf8 code:0x%x", GetLastError()); + } + } + + return ret; +} + +static std::string UTF8StringToMultiByte(const std::string& strUtf8) +{ + std::string ret; + if (!strUtf8.empty()) + { + std::wstring strWideChar = StringUtf8ToWideChar(strUtf8); + int nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE); + if (nNum) + { + char* ansiString = new char[nNum + 1]; + ansiString[0] = 0; + + nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, ansiString, nNum + 1, nullptr, FALSE); + + ret = ansiString; + delete[] ansiString; + } + else + { + CCLOG("Wrong convert to Ansi code:0x%x", GetLastError()); + } + } + + return ret; +} + static void _checkPath() { if (0 == s_resourcePath.length()) @@ -99,6 +175,22 @@ bool FileUtilsWin32::init() return FileUtils::init(); } +bool FileUtilsWin32::isDirectoryExistInternal(const std::string& dirPath) const +{ + unsigned long fAttrib = GetFileAttributes(StringUtf8ToWideChar(dirPath).c_str()); + if (fAttrib != INVALID_FILE_ATTRIBUTES && + (fAttrib & FILE_ATTRIBUTE_DIRECTORY)) + { + return true; + } + return false; +} + +std::string FileUtilsWin32::getSuitableFOpen(const std::string& filenameUtf8) const +{ + return UTF8StringToMultiByte(filenameUtf8); +} + bool FileUtilsWin32::isFileExistInternal(const std::string& strFilePath) const { if (0 == strFilePath.length()) @@ -112,26 +204,12 @@ bool FileUtilsWin32::isFileExistInternal(const std::string& strFilePath) const strPath.insert(0, _defaultResRootPath); } - WCHAR utf16Buf[CC_MAX_PATH] = {0}; - MultiByteToWideChar(CP_UTF8, 0, strPath.c_str(), -1, utf16Buf, sizeof(utf16Buf)/sizeof(utf16Buf[0])); - - DWORD attr = GetFileAttributesW(utf16Buf); + DWORD attr = GetFileAttributesW(StringUtf8ToWideChar(strPath).c_str()); if(attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY)) return false; // not a file return true; } -bool FileUtilsWin32::isDirectoryExistInternal(const std::string& dirPath) const -{ - unsigned long fAttrib = GetFileAttributesA(dirPath.c_str()); - if (fAttrib != INVALID_FILE_ATTRIBUTES && - (fAttrib & FILE_ATTRIBUTE_DIRECTORY)) - { - return true; - } - return false; -} - bool FileUtilsWin32::isAbsolutePath(const std::string& strPath) const { if ( (strPath.length() > 2 @@ -206,10 +284,7 @@ static Data getData(const std::string& filename, bool forString) // check if the filename uses correct case characters CC_BREAK_IF(!checkFileName(fullPath, filename)); - WCHAR wszBuf[CC_MAX_PATH] = {0}; - MultiByteToWideChar(CP_UTF8, 0, fullPath.c_str(), -1, wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0])); - - HANDLE fileHandle = ::CreateFileW(wszBuf, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr); + HANDLE fileHandle = ::CreateFile(StringUtf8ToWideChar(fullPath).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr); CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE); size = ::GetFileSize(fileHandle, nullptr); @@ -291,10 +366,7 @@ unsigned char* FileUtilsWin32::getFileData(const std::string& filename, const ch // check if the filename uses correct case characters CC_BREAK_IF(!checkFileName(fullPath, filename)); - WCHAR wszBuf[CC_MAX_PATH] = {0}; - MultiByteToWideChar(CP_UTF8, 0, fullPath.c_str(), -1, wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0])); - - HANDLE fileHandle = ::CreateFileW(wszBuf, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr); + HANDLE fileHandle = ::CreateFile(StringUtf8ToWideChar(fullPath).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr); CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE); *size = ::GetFileSize(fileHandle, nullptr); @@ -351,49 +423,191 @@ string FileUtilsWin32::getWritablePath() const } // Get full path of executable, e.g. c:\Program Files (x86)\My Game Folder\MyGame.exe - char full_path[CC_MAX_PATH + 1]; - ::GetModuleFileNameA(nullptr, full_path, CC_MAX_PATH + 1); + WCHAR full_path[CC_MAX_PATH + 1] = { 0 }; + ::GetModuleFileName(nullptr, full_path, CC_MAX_PATH + 1); // Debug app uses executable directory; Non-debug app uses local app data directory //#ifndef _DEBUG - // Get filename of executable only, e.g. MyGame.exe - char *base_name = strrchr(full_path, '\\'); + // Get filename of executable only, e.g. MyGame.exe + WCHAR *base_name = wcsrchr(full_path, '\\'); + wstring retPath; + if(base_name) + { + WCHAR app_data_path[CC_MAX_PATH + 1]; - if(base_name) + // Get local app data directory, e.g. C:\Documents and Settings\username\Local Settings\Application Data + if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, app_data_path))) { - char app_data_path[CC_MAX_PATH + 1]; + wstring ret(app_data_path); - // Get local app data directory, e.g. C:\Documents and Settings\username\Local Settings\Application Data - if (SUCCEEDED(SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, app_data_path))) + // Adding executable filename, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame.exe + ret += base_name; + + // Remove ".exe" extension, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame + ret = ret.substr(0, ret.rfind(L".")); + + ret += L"\\"; + + // Create directory + if (SUCCEEDED(SHCreateDirectoryEx(nullptr, ret.c_str(), nullptr))) { - string ret((char*)app_data_path); + retPath = ret; + } + } + } + if (retPath.empty()) +//#endif // not defined _DEBUG + { + // If fetching of local app data directory fails, use the executable one + retPath = full_path; - // Adding executable filename, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame.exe - ret += base_name; + // remove xxx.exe + retPath = retPath.substr(0, retPath.rfind(L"\\") + 1); + } - // Remove ".exe" extension, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame - ret = ret.substr(0, ret.rfind(".")); + return convertPathFormatToUnixStyle(StringWideCharToUtf8(retPath)); +} - ret += "\\"; +bool FileUtilsWin32::renameFile(const std::string &path, const std::string &oldname, const std::string &name) +{ + CCASSERT(!path.empty(), "Invalid path"); + std::string oldPath = path + oldname; + std::string newPath = path + name; - // Create directory - if (SUCCEEDED(SHCreateDirectoryExA(nullptr, ret.c_str(), nullptr))) + std::regex pat("\\/"); + std::string _old = std::regex_replace(oldPath, pat, "\\"); + std::string _new = std::regex_replace(newPath, pat, "\\"); + + std::wstring _wNew = StringUtf8ToWideChar(_new); + + if (FileUtils::getInstance()->isFileExist(_new)) + { + if (!DeleteFile(_wNew.c_str())) + { + CCLOGERROR("Fail to delete file %s !Error code is 0x%x", newPath.c_str(), GetLastError()); + } + } + + if (MoveFile(StringUtf8ToWideChar(_old).c_str(), _wNew.c_str())) + { + return true; + } + else + { + CCLOGERROR("Fail to rename file %s to %s !Error code is 0x%x", oldPath.c_str(), newPath.c_str(), GetLastError()); + return false; + } +} + +bool FileUtilsWin32::createDirectory(const std::string& dirPath) +{ + CCASSERT(!dirPath.empty(), "Invalid path"); + + if (isDirectoryExist(dirPath)) + return true; + + std::wstring path = StringUtf8ToWideChar(dirPath); + + // Split the path + size_t start = 0; + size_t found = path.find_first_of(L"/\\", start); + std::wstring subpath; + std::vector dirs; + + if (found != std::wstring::npos) + { + while (true) + { + subpath = path.substr(start, found - start + 1); + if (!subpath.empty()) + dirs.push_back(subpath); + start = found + 1; + found = path.find_first_of(L"/\\", start); + if (found == std::wstring::npos) + { + if (start < path.length()) { - return convertPathFormatToUnixStyle(ret); + dirs.push_back(path.substr(start)); + } + break; + } + } + } + + if ((GetFileAttributes(path.c_str())) == INVALID_FILE_ATTRIBUTES) + { + subpath = L""; + for (unsigned int i = 0; i < dirs.size(); ++i) + { + subpath += dirs[i]; + + std::string utf8Path = StringWideCharToUtf8(subpath); + if (!isDirectoryExist(utf8Path)) + { + BOOL ret = CreateDirectory(subpath.c_str(), NULL); + if (!ret && ERROR_ALREADY_EXISTS != GetLastError()) + { + CCLOGERROR("Fail create directory %s !Error code is 0x%x", utf8Path.c_str(), GetLastError()); + return false; } } } -//#endif // not defined _DEBUG + } + return true; +} - // If fetching of local app data directory fails, use the executable one - string ret((char*)full_path); +bool FileUtilsWin32::removeFile(const std::string &filepath) +{ + std::regex pat("\\/"); + std::string win32path = std::regex_replace(filepath, pat, "\\"); - // remove xxx.exe - ret = ret.substr(0, ret.rfind("\\") + 1); + if (DeleteFile(StringUtf8ToWideChar(win32path).c_str())) + { + return true; + } + else + { + CCLOGERROR("Fail remove file %s !Error code is 0x%x", filepath.c_str(), GetLastError()); + return false; + } +} - ret = convertPathFormatToUnixStyle(ret); - - return ret; +bool FileUtilsWin32::removeDirectory(const std::string& dirPath) +{ + std::wstring wpath = StringUtf8ToWideChar(dirPath); + std::wstring files = wpath + L"*.*"; + WIN32_FIND_DATA wfd; + HANDLE search = FindFirstFileEx(files.c_str(), FindExInfoStandard, &wfd, FindExSearchNameMatch, NULL, 0); + bool ret = true; + if (search != INVALID_HANDLE_VALUE) + { + BOOL find = true; + while (find) + { + //. .. + if (wfd.cFileName[0] != '.') + { + std::wstring temp = wpath + wfd.cFileName; + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + temp += '/'; + ret = ret && this->removeDirectory(StringWideCharToUtf8(temp)); + } + else + { + SetFileAttributes(temp.c_str(), FILE_ATTRIBUTE_NORMAL); + ret = ret && DeleteFile(temp.c_str()); + } + } + find = FindNextFile(search, &wfd); + } + FindClose(search); + } + if (ret && RemoveDirectory(wpath.c_str())) + { + return true; + } + return false; } NS_CC_END diff --git a/cocos/platform/win32/CCFileUtils-win32.h b/cocos/platform/win32/CCFileUtils-win32.h index 86e0f9d4d9..fdb57df7ab 100644 --- a/cocos/platform/win32/CCFileUtils-win32.h +++ b/cocos/platform/win32/CCFileUtils-win32.h @@ -49,12 +49,54 @@ class CC_DLL FileUtilsWin32 : public FileUtils public: /* override funtions */ bool init(); - virtual std::string getWritablePath() const; - virtual bool isAbsolutePath(const std::string& strPath) const; + virtual std::string getWritablePath() const override; + virtual bool isAbsolutePath(const std::string& strPath) const override; + virtual std::string getSuitableFOpen(const std::string& filenameUtf8) const override; protected: virtual bool isFileExistInternal(const std::string& strFilePath) const override; + + /** + * Renames a file under the given directory. + * + * @param path The parent directory path of the file, it must be an absolute path. + * @param oldname The current name of the file. + * @param name The new name of the file. + * @return True if the file have been renamed successfully, false if not. + */ + virtual bool renameFile(const std::string &path, const std::string &oldname, const std::string &name) override; + + /** + * Checks whether a directory exists without considering search paths and resolution orders. + * @param dirPath The directory (with absolute path) to look up for + * @return Returns true if the directory found at the given absolute path, otherwise returns false + */ virtual bool isDirectoryExistInternal(const std::string& dirPath) const override; + + /** + * Removes a file. + * + * @param filepath The full path of the file, it must be an absolute path. + * @return True if the file have been removed successfully, false if not. + */ + virtual bool removeFile(const std::string &filepath) override; + + /** + * Creates a directory. + * + * @param dirPath The path of the directory, it must be an absolute path. + * @return True if the directory have been created successfully, false if not. + */ + virtual bool createDirectory(const std::string& dirPath) override; + + /** + * Removes a directory. + * + * @param dirPath The full path of the directory, it must be an absolute path. + * @return True if the directory have been removed successfully, false if not. + */ + virtual bool removeDirectory(const std::string& dirPath) override; + /** * Gets resource file data * @@ -64,7 +106,7 @@ protected: * @return Upon success, a pointer to the data is returned, otherwise NULL. * @warning Recall: you are responsible for calling delete[] on any Non-NULL pointer returned. */ - virtual unsigned char* getFileData(const std::string& filename, const char* mode, ssize_t * size) override; + CC_DEPRECATED_ATTRIBUTE virtual unsigned char* getFileData(const std::string& filename, const char* mode, ssize_t * size) override; /** * Gets string from a file. diff --git a/cocos/platform/winrt/CCFileUtilsWinRT.cpp b/cocos/platform/winrt/CCFileUtilsWinRT.cpp index 78cfb434bf..5a474b83fb 100644 --- a/cocos/platform/winrt/CCFileUtilsWinRT.cpp +++ b/cocos/platform/winrt/CCFileUtilsWinRT.cpp @@ -23,9 +23,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "CCFileUtilsWinRT.h" +#include #include "CCWinRTUtils.h" #include "platform/CCCommon.h" - using namespace std; NS_CC_BEGIN @@ -47,6 +47,80 @@ static inline std::string convertPathFormatToUnixStyle(const std::string& path) return ret; } +static std::wstring StringUtf8ToWideChar(const std::string& strUtf8) +{ + std::wstring ret; + if (!strUtf8.empty()) + { + int nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, nullptr, 0); + if (nNum) + { + WCHAR* wideCharString = new WCHAR[nNum + 1]; + wideCharString[0] = 0; + + nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, wideCharString, nNum + 1); + + ret = wideCharString; + delete[] wideCharString; + } + else + { + CCLOG("Wrong convert to WideChar code:0x%x", GetLastError()); + } + } + return ret; +} + +static std::string StringWideCharToUtf8(const std::wstring& strWideChar) +{ + std::string ret; + if (!strWideChar.empty()) + { + int nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE); + if (nNum) + { + char* utf8String = new char[nNum + 1]; + utf8String[0] = 0; + + nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, utf8String, nNum + 1, nullptr, FALSE); + + ret = utf8String; + delete[] utf8String; + } + else + { + CCLOG("Wrong convert to Utf8 code:0x%x", GetLastError()); + } + } + + return ret; +} + +static std::string UTF8StringToMultiByte(const std::string& strUtf8) +{ + std::string ret; + if (!strUtf8.empty()) + { + std::wstring strWideChar = StringUtf8ToWideChar(strUtf8); + int nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE); + if (nNum) + { + char* ansiString = new char[nNum + 1]; + ansiString[0] = 0; + + nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, ansiString, nNum + 1, nullptr, FALSE); + + ret = ansiString; + delete[] ansiString; + } + else + { + CCLOG("Wrong convert to Ansi code:0x%x", GetLastError()); + } + } + + return ret; +} static void _checkPath() { @@ -72,7 +146,6 @@ FileUtils* FileUtils::getInstance() return s_sharedFileUtils; } - CCFileUtilsWinRT::CCFileUtilsWinRT() { } @@ -100,6 +173,11 @@ std::string CCFileUtilsWinRT::getFullPathForDirectoryAndFilename(const std::stri return FileUtils::getFullPathForDirectoryAndFilename(unixDirectory, unixFilename); } +std::string CCFileUtilsWinRT::getSuitableFOpen(const std::string& filenameUtf8) const +{ + return UTF8StringToMultiByte(filenameUtf8); +} + bool CCFileUtilsWinRT::isFileExistInternal(const std::string& strFilePath) const { bool ret = false; @@ -132,6 +210,99 @@ bool CCFileUtilsWinRT::isDirectoryExistInternal(const std::string& dirPath) cons return false; } +bool CCFileUtilsWinRT::createDirectory(const std::string& path) +{ + CCASSERT(!path.empty(), "Invalid path"); + + if (isDirectoryExist(path)) + return true; + + // Split the path + size_t start = 0; + size_t found = path.find_first_of("/\\", start); + std::string subpath; + std::vector dirs; + + if (found != std::string::npos) + { + while (true) + { + subpath = path.substr(start, found - start + 1); + if (!subpath.empty()) + dirs.push_back(subpath); + start = found + 1; + found = path.find_first_of("/\\", start); + if (found == std::string::npos) + { + if (start < path.length()) + { + dirs.push_back(path.substr(start)); + } + break; + } + } + } + + WIN32_FILE_ATTRIBUTE_DATA wfad; + std::wstring wpath(path.begin(), path.end()); + if (!(GetFileAttributesEx(wpath.c_str(), GetFileExInfoStandard, &wfad))) + { + subpath = ""; + for (unsigned int i = 0; i < dirs.size(); ++i) + { + subpath += dirs[i]; + if (i > 0 && !isDirectoryExist(subpath)) + { + std::wstring wsubpath(subpath.begin(), subpath.end()); + BOOL ret = CreateDirectory(wsubpath.c_str(), NULL); + if (!ret && ERROR_ALREADY_EXISTS != GetLastError()) + { + return false; + } + } + } + } + return true; +} + +bool CCFileUtilsWinRT::removeDirectory(const std::string& path) +{ + std::wstring wpath = std::wstring(path.begin(), path.end()); + std::wstring files = wpath + L"*.*"; + WIN32_FIND_DATA wfd; + HANDLE search = FindFirstFileEx(files.c_str(), FindExInfoStandard, &wfd, FindExSearchNameMatch, NULL, 0); + bool ret = true; + if (search != INVALID_HANDLE_VALUE) + { + BOOL find = true; + while (find) + { + //. .. + if (wfd.cFileName[0] != '.') + { + std::wstring temp = wpath + wfd.cFileName; + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + temp += '/'; + ret = ret && this->removeDirectory(std::string(temp.begin(), temp.end())); + } + else + { + SetFileAttributes(temp.c_str(), FILE_ATTRIBUTE_NORMAL); + ret = ret && DeleteFile(temp.c_str()); + } + } + find = FindNextFile(search, &wfd); + } + FindClose(search); + } + if (ret && RemoveDirectory(wpath.c_str())) + { + return true; + } + return false; +} + bool CCFileUtilsWinRT::isAbsolutePath(const std::string& strPath) const { if ( strPath.length() > 2 @@ -143,6 +314,34 @@ bool CCFileUtilsWinRT::isAbsolutePath(const std::string& strPath) const return false; } +bool CCFileUtilsWinRT::removeFile(const std::string &path) +{ + std::wstring wpath(path.begin(), path.end()); + if (DeleteFile(wpath.c_str())) + { + return true; + } + return false; +} + +bool CCFileUtilsWinRT::renameFile(const std::string &path, const std::string &oldname, const std::string &name) +{ + CCASSERT(!path.empty(), "Invalid path"); + std::string oldPath = path + oldname; + std::string newPath = path + name; + + std::regex pat("\\/"); + std::string _old = std::regex_replace(oldPath, pat, "\\"); + std::string _new = std::regex_replace(newPath, pat, "\\"); + if (MoveFileEx(std::wstring(_old.begin(), _old.end()).c_str(), + std::wstring(_new.begin(), _new.end()).c_str(), + MOVEFILE_REPLACE_EXISTING & MOVEFILE_WRITE_THROUGH)) + { + return true; + } + return false; +} + static Data getData(const std::string& filename, bool forString) { if (filename.empty()) diff --git a/cocos/platform/winrt/CCFileUtilsWinRT.h b/cocos/platform/winrt/CCFileUtilsWinRT.h index 9cbd6a70a6..e6db42abe4 100644 --- a/cocos/platform/winrt/CCFileUtilsWinRT.h +++ b/cocos/platform/winrt/CCFileUtilsWinRT.h @@ -49,14 +49,55 @@ public: bool init(); virtual std::string getWritablePath() const; virtual bool isAbsolutePath(const std::string& strPath) const; - virtual std::string getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) const override; + virtual std::string getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) const override; virtual std::string getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename) const override; virtual std::string getStringFromFile(const std::string& filename) override; + virtual std::string getSuitableFOpen(const std::string& filenameUtf8) const override; static std::string getAppPath(); private: virtual bool isFileExistInternal(const std::string& strFilePath) const override; + + /** + * Renames a file under the given directory. + * + * @param path The parent directory path of the file, it must be an absolute path. + * @param oldname The current name of the file. + * @param name The new name of the file. + * @return True if the file have been renamed successfully, false if not. + */ + virtual bool renameFile(const std::string &path, const std::string &oldname, const std::string &name) override; + + /** + * Checks whether a directory exists without considering search paths and resolution orders. + * @param dirPath The directory (with absolute path) to look up for + * @return Returns true if the directory found at the given absolute path, otherwise returns false + */ virtual bool isDirectoryExistInternal(const std::string& dirPath) const override; + + /** + * Removes a file. + * + * @param filepath The full path of the file, it must be an absolute path. + * @return True if the file have been removed successfully, false if not. + */ + virtual bool removeFile(const std::string &filepath) override; + + /** + * Creates a directory. + * + * @param dirPath The path of the directory, it must be an absolute path. + * @return True if the directory have been created successfully, false if not. + */ + virtual bool createDirectory(const std::string& dirPath) override; + + /** + * Removes a directory. + * + * @param dirPath The full path of the directory, it must be an absolute path. + * @return True if the directory have been removed successfully, false if not. + */ + virtual bool removeDirectory(const std::string& dirPath) override; }; // end of platform group diff --git a/tests/cpp-tests/proj.android-studio/app/jni/Android.mk b/tests/cpp-tests/proj.android-studio/app/jni/Android.mk index bc7073018c..ad86e4c835 100644 --- a/tests/cpp-tests/proj.android-studio/app/jni/Android.mk +++ b/tests/cpp-tests/proj.android-studio/app/jni/Android.mk @@ -95,6 +95,7 @@ LOCAL_SRC_FILES := main.cpp \ ../../../Classes/NewAudioEngineTest/NewAudioEngineTest.cpp \ ../../../Classes/NewEventDispatcherTest/NewEventDispatcherTest.cpp \ ../../../Classes/NewRendererTest/NewRendererTest.cpp \ +../../../Classes/NavMeshTest/NavMeshTest.cpp \ ../../../Classes/NodeTest/NodeTest.cpp \ ../../../Classes/OpenURLTest/OpenURLTest.cpp \ ../../../Classes/ParallaxTest/ParallaxTest.cpp \ @@ -201,10 +202,10 @@ LOCAL_SRC_FILES := main.cpp \ ../../../Classes/UnitTest/UnitTest.cpp \ ../../../Classes/UserDefaultTest/UserDefaultTest.cpp \ ../../../Classes/VisibleRect.cpp \ +../../../Classes/VibrateTest/VibrateTest.cpp \ ../../../Classes/ZwoptexTest/ZwoptexTest.cpp \ ../../../Classes/controller.cpp \ -../../../Classes/testBasic.cpp \ -../../../Classes/NavMeshTest/NavMeshTest.cpp +../../../Classes/testBasic.cpp LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../Classes \ $(LOCAL_PATH)/../../../../.. diff --git a/tests/cpp-tests/proj.win8.1-universal/cpp-tests.Shared/cpp-tests.Shared.vcxitems.filters b/tests/cpp-tests/proj.win8.1-universal/cpp-tests.Shared/cpp-tests.Shared.vcxitems.filters index b245f7bcdc..2848d57fe6 100644 --- a/tests/cpp-tests/proj.win8.1-universal/cpp-tests.Shared/cpp-tests.Shared.vcxitems.filters +++ b/tests/cpp-tests/proj.win8.1-universal/cpp-tests.Shared/cpp-tests.Shared.vcxitems.filters @@ -799,6 +799,7 @@ Classes\NavMeshTest + @@ -1260,9 +1261,6 @@ Classes\UITest\CocostudioGUISceneTest\UICheckBoxTest - - Classes\UITest\CocostudioGUISceneTest\UIRadioButtonTest - Classes\UITest\CocostudioGUISceneTest\UIFocusTest @@ -1780,4 +1778,4 @@ Classes\NavMeshTest - + \ No newline at end of file From 74227eaf16940b27205948214d65cdfbd1b3ab89 Mon Sep 17 00:00:00 2001 From: Vincent Yang Date: Mon, 13 Jul 2015 22:44:40 +0800 Subject: [PATCH 2/2] Add TestIsDirectoryExist and TestUnicodePath in cpp-tests FileUtil test. --- cocos/platform/CCFileUtils.cpp | 4 +- .../Classes/FileUtilsTest/FileUtilsTest.cpp | 157 +++++++++++++++++- .../Classes/FileUtilsTest/FileUtilsTest.h | 23 +++ 3 files changed, 182 insertions(+), 2 deletions(-) diff --git a/cocos/platform/CCFileUtils.cpp b/cocos/platform/CCFileUtils.cpp index bd7803cafb..29aa995398 100644 --- a/cocos/platform/CCFileUtils.cpp +++ b/cocos/platform/CCFileUtils.cpp @@ -1059,7 +1059,7 @@ bool FileUtils::isDirectoryExist(const std::string& dirPath) const } #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) - +// windows os implement should override in platform specific FileUtiles class bool FileUtils::isDirectoryExistInternal(const std::string& dirPath) const { CCASSERT(false, "FileUtils not support isDirectoryExistInternal"); @@ -1097,6 +1097,7 @@ std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const } #else +// default implements for unix like os #include #include #include @@ -1222,6 +1223,7 @@ std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const } #endif + long FileUtils::getFileSize(const std::string &filepath) { CCASSERT(!filepath.empty(), "Invalid path"); diff --git a/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.cpp b/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.cpp index b21c4c7ad9..41865bd86b 100644 --- a/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.cpp +++ b/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.cpp @@ -8,6 +8,7 @@ FileUtilsTests::FileUtilsTests() ADD_TEST_CASE(TestSearchPath); ADD_TEST_CASE(TestFilenameLookup); ADD_TEST_CASE(TestIsFileExist); + ADD_TEST_CASE(TestIsDirectoryExist); ADD_TEST_CASE(TestFileFuncs); ADD_TEST_CASE(TestDirectoryFuncs); ADD_TEST_CASE(TextWritePlist); @@ -15,6 +16,7 @@ FileUtilsTests::FileUtilsTests() ADD_TEST_CASE(TestWriteData); ADD_TEST_CASE(TestWriteValueMap); ADD_TEST_CASE(TestWriteValueVector); + ADD_TEST_CASE(TestUnicodePath); } // TestResolutionDirectories @@ -122,7 +124,7 @@ void TestSearchPath::onEnter() if (fp) { char szReadBuf[100] = {0}; - size_t read = fread(szReadBuf, 1, strlen(szBuf), fp); + size_t read = fread(szReadBuf, 1, strlen(szReadBuf), fp); if (read > 0) log("The content of file from writable path: %s", szReadBuf); fclose(fp); @@ -232,6 +234,61 @@ std::string TestIsFileExist::subtitle() const return ""; } +// TestIsDirectoryExist + +void TestIsDirectoryExist::onEnter() +{ + FileUtilsDemo::onEnter(); + auto s = Director::getInstance()->getWinSize(); + auto util = FileUtils::getInstance(); + int x = s.width/2, y = s.height/3; + + Label* label = nullptr; + std::string dir; + char msg[512]; + auto getMsg = [&dir, &msg](bool b)->const char * + { + snprintf((char *)msg, 512, "%s for dir: \"%s\"", b ? "success" : "failed", dir.c_str()); + return msg; + }; + + dir = "Images"; + label = Label::createWithSystemFont(getMsg(util->isDirectoryExist(dir)), "", 20); + label->setPosition(x, y * 2); + this->addChild(label); + + dir = util->getWritablePath(); + label = Label::createWithSystemFont(getMsg(util->isDirectoryExist(dir)), "", 20); + label->setPosition(x, y * 1); + this->addChild(label); + + dir = util->getWritablePath(); + label = Label::createWithSystemFont(getMsg(util->isDirectoryExist(dir)), "", 20); + label->setPosition(x, y * 1); + this->addChild(label); +} + +void TestIsDirectoryExist::onExit() +{ + + FileUtils *sharedFileUtils = FileUtils::getInstance(); + + // reset filename lookup + sharedFileUtils->purgeCachedEntries(); + + FileUtilsDemo::onExit(); +} + +std::string TestIsDirectoryExist::title() const +{ + return "FileUtils: check whether the directory exists"; +} + +std::string TestIsDirectoryExist::subtitle() const +{ + return ""; +} + // TestFileFuncs void TestFileFuncs::onEnter() @@ -801,3 +858,101 @@ std::string TestWriteValueVector::subtitle() const { return ""; } + +// TestUnicodePath + +void TestUnicodePath::onEnter() +{ + FileUtilsDemo::onEnter(); + auto s = Director::getInstance()->getWinSize(); + auto util = FileUtils::getInstance(); + + int x = s.width/2, + y = s.height/5; + Label* label = nullptr; + + std::string dir = "中文路径/"; + std::string filename = "测试文件.test"; + + std::string act; + char msg[512]; + auto getMsg = [&act, &msg](bool b, const std::string& path)->const char * + { + snprintf((char *)msg, 512, "%s for %s path: \"%s\"", b ? "success" : "failed", act.c_str(), path.c_str()); + return msg; + }; + + // Check whether unicode dir should be create or not + std::string dirPath = util->getWritablePath() + dir; + if (!util->isDirectoryExist(dirPath)) + { + util->createDirectory(dirPath); + } + + act = "create"; + bool isExist = util->isDirectoryExist(dirPath); + label = Label::createWithSystemFont(getMsg(isExist, dirPath), "", 12, Size(s.width, 0)); + label->setPosition(x, y * 4); + this->addChild(label); + + if (isExist) + { + // Check whether unicode file should be create or not + std::string filePath = dirPath + filename; + if (! util->isFileExist(filePath)) + { + std::string writeDataStr = " 测试字符串."; + Data writeData; + writeData.copy((unsigned char *)writeDataStr.c_str(), writeDataStr.size()); + util->writeDataToFile(writeData, filePath); + } + + isExist = util->isFileExist(filePath); + label = Label::createWithSystemFont(getMsg(isExist, filePath), "", 12, Size(s.width, 0)); + label->setPosition(x, y * 3); + this->addChild(label); + + act = "remove"; + if (isExist) + { + // read file content and log it + unsigned char* buffer = nullptr; + Data readData = util->getDataFromFile(filePath); + buffer = (unsigned char*)malloc(sizeof(unsigned char) * (readData.getSize() + 1)); + memcpy(buffer, readData.getBytes(), readData.getSize()); + buffer[readData.getSize()] = '\0'; + // vc can't treat unicode string correctly, don't use unicode string in code + log("The content of file from writable path: %s", buffer); + free(buffer); + + // remove test file + label = Label::createWithSystemFont(getMsg(util->removeFile(filePath), filePath), "", 12, Size(s.width, 0)); + label->setPosition(x, y * 2); + this->addChild(label); + } + + // remove test dir + label = Label::createWithSystemFont(getMsg(util->removeDirectory(dirPath), dirPath), "", 12, Size(s.width, 0)); + label->setPosition(x, y * 1); + this->addChild(label); + } +} + +void TestUnicodePath::onExit() +{ + + FileUtils *sharedFileUtils = FileUtils::getInstance(); + sharedFileUtils->purgeCachedEntries(); + sharedFileUtils->setFilenameLookupDictionary(ValueMap()); + FileUtilsDemo::onExit(); +} + +std::string TestUnicodePath::title() const +{ + return "FileUtils: check unicode path"; +} + +std::string TestUnicodePath::subtitle() const +{ + return ""; +} diff --git a/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.h b/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.h index b177ed0755..e8f6856fd5 100644 --- a/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.h +++ b/tests/cpp-tests/Classes/FileUtilsTest/FileUtilsTest.h @@ -60,6 +60,17 @@ public: virtual std::string subtitle() const override; }; +class TestIsDirectoryExist : public FileUtilsDemo +{ +public: + CREATE_FUNC(TestIsDirectoryExist); + + virtual void onEnter() override; + virtual void onExit() override; + virtual std::string title() const override; + virtual std::string subtitle() const override; +}; + class TestFileFuncs : public FileUtilsDemo { public: @@ -134,4 +145,16 @@ public: virtual std::string title() const override; virtual std::string subtitle() const override; }; + +class TestUnicodePath : public FileUtilsDemo +{ +public: + CREATE_FUNC(TestUnicodePath); + + virtual void onEnter() override; + virtual void onExit() override; + virtual std::string title() const override; + virtual std::string subtitle() const override; +}; + #endif /* __FILEUTILSTEST_H__ */