diff --git a/autotest/PathOps/PathOps.cpp b/autotest/PathOps/PathOps.cpp new file mode 100644 index 000000000..9f5dce14b --- /dev/null +++ b/autotest/PathOps/PathOps.cpp @@ -0,0 +1,40 @@ +#include + +using namespace Upp; + +CONSOLE_APP_MAIN +{ + StdLogSetup(LOG_COUT|LOG_FILE); + + String testdir = GetHomeDirFile("path_test_dir__"); + DirectoryCreate(testdir); + ASSERT(DirectoryExists(testdir)); + ASSERT(!FileExists(testdir)); + ASSERT(!DirectoryExists(testdir + "q24312")); + + String path = AppendFileName(testdir, "test.txt"); + Time tm0 = GetSysTime(); + SaveFile(path, "test"); + ASSERT(FileExists(path)); + ASSERT(!DirectoryExists(path)); + ASSERT(!FileExists(path + "1")); + + ASSERT(GetFileLength(path) == 4); + ASSERT(GetFileLength(path + "1") < 0); + + Time tm = GetFileTime(path); + DDUMP(tm); + + ASSERT(tm >= tm0 && tm <= GetSysTime()); + + String newpath = AppendFileName(testdir, "test2.txt"); + ASSERT(FileMove(path, newpath)); + ASSERT(FileExists(newpath)); + ASSERT(!FileExists(path)); + ASSERT(!DirectoryExists(newpath)); + + DeleteFolderDeep(testdir); + ASSERT(!DirectoryExists(testdir)); + + LOG("================== OK"); +} diff --git a/autotest/PathOps/PathOps.upp b/autotest/PathOps/PathOps.upp new file mode 100644 index 000000000..139d5650d --- /dev/null +++ b/autotest/PathOps/PathOps.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + PathOps.cpp; + +mainconfig + "" = ""; + diff --git a/uppsrc/Core/FileMapping.cpp b/uppsrc/Core/FileMapping.cpp index 8f2ba07f6..e76b21336 100644 --- a/uppsrc/Core/FileMapping.cpp +++ b/uppsrc/Core/FileMapping.cpp @@ -6,22 +6,24 @@ namespace Upp { -static int sMappingGranularity_() +int FileMapping::MappingGranularity() { #ifdef PLATFORM_WIN32 static int mg = 0; - if(!mg) { + ONCELOCK { SYSTEM_INFO info; GetSystemInfo(&info); mg = info.dwAllocationGranularity; } #else - static int mg = 4096; + ONCELOCK { + mg = getpagesize(); + } #endif return mg; } -FileMapping::FileMapping(const char *file_, bool delete_share_) +FileMapping::FileMapping(const char *file_) { #ifdef PLATFORM_WIN32 hfile = INVALID_HANDLE_VALUE; @@ -37,10 +39,10 @@ FileMapping::FileMapping(const char *file_, bool delete_share_) filesize = -1; write = false; if(file_) - Open(file_, delete_share_); + Open(file_); } -bool FileMapping::Open(const char *file, bool delete_share) +bool FileMapping::Open(const char *file) { Close(); write = false; @@ -96,45 +98,40 @@ bool FileMapping::Create(const char *file, int64 filesize_, bool delete_share) return true; } -bool FileMapping::Map(int64 mapoffset, size_t maplen) +byte *FileMapping::Map(int64 mapoffset, size_t maplen) { ASSERT(IsOpen()); - if(maplen == 0) - return Unmap(); + Unmap(); mapoffset = minmax(mapoffset, 0, filesize); - int gran = sMappingGranularity_(); + int gran = MappingGranularity(); int64 rawoff = mapoffset & -gran; maplen = (size_t)min(maplen, filesize - mapoffset); size_t rawsz = (size_t)min((maplen + (size_t)(mapoffset - rawoff) + gran - 1) & -gran, filesize - rawoff); - if(rawbase && (mapoffset < rawoffset || mapoffset + maplen > rawoffset + rawsize)) - Unmap(); - if(!rawbase) { - rawoffset = rawoff; - rawsize = rawsz; + rawoffset = rawoff; + rawsize = rawsz; #ifdef PLATFORM_WIN32 - rawbase = (byte *)MapViewOfFile(hmap, write ? FILE_MAP_WRITE : FILE_MAP_READ, - (dword)(rawoffset >> 32), (dword)(rawoffset >> 0), rawsize); + rawbase = (byte *)MapViewOfFile(hmap, write ? FILE_MAP_WRITE : FILE_MAP_READ, + (dword)(rawoffset >> 32), (dword)(rawoffset >> 0), rawsize); #else - rawbase = (byte *)mmap(0, rawsize, - PROT_READ | (write ? PROT_WRITE : 0), + rawbase = (byte *)mmap(0, rawsize, + PROT_READ | (write ? PROT_WRITE : 0), #ifdef PLATFORM_FREEBSD - MAP_NOSYNC, + MAP_NOSYNC, #else - MAP_SHARED, + MAP_SHARED, #endif - hfile, rawoffset); + hfile, rawoffset); #endif #ifdef PLATFORM_POSIX - if(rawbase == (byte *)~0) + if(rawbase == (byte *)~0) #else - if(!rawbase) + if(!rawbase) #endif - return false; - } + return NULL; offset = mapoffset; size = maplen; base = rawbase + (int)(offset - rawoffset); - return true; + return base; } bool FileMapping::Unmap() diff --git a/uppsrc/Core/Path.cpp b/uppsrc/Core/Path.cpp index 975de1c7e..5be8cab52 100644 --- a/uppsrc/Core/Path.cpp +++ b/uppsrc/Core/Path.cpp @@ -638,23 +638,6 @@ String FindFile::GetPath() const return AppendFileName(path, GetName()); } -bool FileExists(const char *name) { - FindFile ff(name); - return ff && ff.IsFile(); -} - -int64 GetFileLength(const char *name) { - FindFile ff(name); - return ff ? ff.GetLength() : -1; -} - -bool DirectoryExists(const char *name) { - if(*name == '\0') - return false; - FindFile ff(name + String("/*")); - return ff; -} - String NormalizePath(const char *path) { #ifdef PLATFORM_WINCE return NormalizePath(path, ""); @@ -756,16 +739,9 @@ Time FileGetTime(const char *filename) FileTime GetFileTime(const char *filename) { #if defined(PLATFORM_WIN32) - HANDLE handle; - handle = CreateFileW(ToSystemCharsetW(filename), GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + WIN32_FILE_ATTRIBUTE_DATA wfad; static FileTime ft0; - if(handle == INVALID_HANDLE_VALUE) - return ft0; - FileTime ft; - bool res = GetFileTime(handle, 0, 0, &ft); - CloseHandle(handle); - return res ? ft : ft0; + return GetFileAttributesEx(filename, GetFileExInfoStandard, &wfad) ? wfad.ftLastWriteTime : ft0; #elif defined(PLATFORM_POSIX) struct stat st; if(stat(ToSystemCharset(filename), &st)) @@ -776,6 +752,47 @@ FileTime GetFileTime(const char *filename) #endif//PLATFORM } +int64 GetFileLength(const char *path) { +#if defined(PLATFORM_WIN32) + WIN32_FILE_ATTRIBUTE_DATA wfad; + static FileTime ft0; + return GetFileAttributesEx(path, GetFileExInfoStandard, &wfad) ? MAKEQWORD(wfad.nFileSizeLow, wfad.nFileSizeHigh) : -1; +#elif defined(PLATFORM_POSIX) + struct stat st; + return stat(ToSystemCharset(filename), &st) ? -1 : st.st_size; +#else + #error +#endif//PLATFORM +} + +bool FileExists(const char *path) +{ +#if defined(PLATFORM_WIN32) + WIN32_FILE_ATTRIBUTE_DATA wfad; + static FileTime ft0; + return GetFileAttributesEx(path, GetFileExInfoStandard, &wfad) && !(wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); +#elif defined(PLATFORM_POSIX) + struct stat st; + return stat(ToSystemCharset(filename), &st) ? false : S_ISREG(st.st_mode); +#else + #error +#endif//PLATFORM +} + +bool DirectoryExists(const char *path) +{ +#if defined(PLATFORM_WIN32) + WIN32_FILE_ATTRIBUTE_DATA wfad; + static FileTime ft0; + return GetFileAttributesEx(path, GetFileExInfoStandard, &wfad) && (wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); +#elif defined(PLATFORM_POSIX) + struct stat st; + return stat(ToSystemCharset(filename), &st) ? false : S_ISDIR(st.st_mode); +#else + #error +#endif//PLATFORM +} + bool SetFileTime(const char *filename, FileTime ft) { #if defined(PLATFORM_WIN32) diff --git a/uppsrc/Core/Stream.h b/uppsrc/Core/Stream.h index 138953fea..be3ed1165 100644 --- a/uppsrc/Core/Stream.h +++ b/uppsrc/Core/Stream.h @@ -549,13 +549,14 @@ public: class FileMapping { public: - FileMapping(const char *file = NULL, bool delete_share = false); + FileMapping(const char *file = NULL); ~FileMapping() { Close(); } - bool Open(const char *file, bool delete_share = false); + bool Open(const char *file); bool Create(const char *file, int64 filesize, bool delete_share = false); bool Expand(int64 filesize); - bool Map(int64 offset, size_t len); + byte *Map(int64 mapoffset, size_t maplen); + byte *Map() { return Map(0, GetFileSize()); } bool Unmap(); bool Close(); @@ -572,16 +573,22 @@ public: size_t GetRawCount() const { return rawsize; } const byte *operator ~ () const { ASSERT(IsOpen()); return base; } - const byte *Begin() const { ASSERT(IsOpen()); return base; } - const byte *End() const { ASSERT(IsOpen()); return base + size; } - const byte *GetIter(int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } + const byte *begin() const { ASSERT(IsOpen()); return base; } + const byte *end() const { ASSERT(IsOpen()); return base + size; } const byte& operator [] (int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } byte *operator ~ () { ASSERT(IsOpen()); return base; } + byte *begin() { ASSERT(IsOpen()); return base; } + byte *end() { ASSERT(IsOpen()); return base + size; } + byte& operator [] (int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } + + const byte *Begin() const { ASSERT(IsOpen()); return base; } + const byte *End() const { ASSERT(IsOpen()); return base + size; } + const byte *GetIter(int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } + byte *Begin() { ASSERT(IsOpen()); return base; } byte *End() { ASSERT(IsOpen()); return base + size; } byte *GetIter(int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } - byte& operator [] (int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } private: #ifdef PLATFORM_WIN32 @@ -601,6 +608,9 @@ private: size_t size; size_t rawsize; bool write; + + + static int MappingGranularity(); }; diff --git a/uppsrc/Core/src.tpp/Path_en-us.tpp b/uppsrc/Core/src.tpp/Path_en-us.tpp index 5f50e08c6..07cca3fe0 100644 --- a/uppsrc/Core/src.tpp/Path_en-us.tpp +++ b/uppsrc/Core/src.tpp/Path_en-us.tpp @@ -97,7 +97,8 @@ in Win32). Separator [*/ is not] included at the end of result. If there is none, returns empty string.&] [s2;%% Example (POSIX): GetFileFolder([@3 `"/home/user/test.ext`"]) returns [@3 `"/home/user`"].&] -[s3;%% &] +[s2;%% &] +[s3; &] [s4;%% &] [s5;:GetFileTitle`(const char`*`): [_^String^ String]_[* GetFileTitle]([@(0.0.255) const]_[@(0.0.255) c har]_`*[*@3 path])&]