Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Zolotarev <deathbaba@gmail.com>2011-10-31 00:14:52 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:27:10 +0300
commiteea66458919753af7edc32b9210adfa1a1f36751 (patch)
tree4545e07fbda279938b77b45069c7973c2437a857 /platform
parent29f6e38b349ca9620ed36a637c692fbccb12eb32 (diff)
Completed platform refactoring and fixed paths for resources/writable dirs
Diffstat (limited to 'platform')
-rw-r--r--platform/platform.hpp20
-rw-r--r--platform/platform_android.cpp21
-rw-r--r--platform/platform_ios.mm21
-rw-r--r--platform/platform_linux.cpp55
-rw-r--r--platform/platform_mac.mm85
-rw-r--r--platform/platform_qt.cpp111
-rw-r--r--platform/platform_tests/platform_test.cpp23
-rw-r--r--platform/platform_win.cpp65
8 files changed, 184 insertions, 217 deletions
diff --git a/platform/platform.hpp b/platform/platform.hpp
index 793f8bacb1..ad745ae478 100644
--- a/platform/platform.hpp
+++ b/platform/platform.hpp
@@ -16,8 +16,22 @@ class Platform
protected:
string m_writableDir, m_resourcesDir;
class PlatformImpl;
+ /// Used only on those platforms where needed
PlatformImpl * m_impl;
+ /// Internal function to use files from writable dir if they override the same in the resources
+ string ReadPathForFile(string const & file) const
+ {
+ string fullPath = m_writableDir + file;
+ if (!IsFileExists(fullPath))
+ {
+ fullPath = m_resourcesDir + file;
+ if (!IsFileExists(fullPath))
+ MYTHROW(FileAbsentException, ("File doesn't exist", fullPath));
+ }
+ return fullPath;
+ }
+
public:
Platform();
~Platform();
@@ -46,11 +60,7 @@ public:
/// @return false if file is not exist
bool GetFileSize(string const & file, uint64_t & size) const;
/// Simple file existing check
- bool IsFileExists(string const & file) const
- {
- uint64_t dummy;
- return GetFileSize(file, dummy);
- }
+ bool IsFileExists(string const & file) const;
//@}
int CpuCores() const;
diff --git a/platform/platform_android.cpp b/platform/platform_android.cpp
index f85780d697..adbbb5c12e 100644
--- a/platform/platform_android.cpp
+++ b/platform/platform_android.cpp
@@ -7,26 +7,14 @@
#include <unistd.h>
#include <sys/stat.h>
-static string ReadPathForFile(string const & writableDir,
- string const & resourcesDir, string const & file)
-{
- string fullPath = writableDir + file;
- if (!GetPlatform().IsFileExists(fullPath))
- {
- fullPath = resourcesDir + file;
- if (!GetPlatform().IsFileExists(fullPath))
- MYTHROW(FileAbsentException, ("File doesn't exist", fullPath));
- }
- return fullPath;
-}
-
Platform::Platform()
{}
Platform::~Platform()
{}
-static bool IsFilePresent(string const & file)
+/// @warning doesn't work for files inside .apk (zip)!!!
+bool Platform::IsFileExists(string const & file) const
{
struct stat s;
return stat(file.c_str(), &s) == 0;
@@ -34,9 +22,8 @@ static bool IsFilePresent(string const & file)
ModelReader * Platform::GetReader(string const & file) const
{
- // can't use Platform::IsFileExists here to avoid recursion
- if (IsFilePresent(m_writableDir + file))
- return new FileReader(ReadPathForFile(m_writableDir, m_resourcesDir, file), 10, 12);
+ if (IsFileExists(m_writableDir + file))
+ return new FileReader(ReadPathForFile(file), 10, 12);
else
{ // paths from GetFilesInDir will already contain "assets/"
if (file.find("assets/") != string::npos)
diff --git a/platform/platform_ios.mm b/platform/platform_ios.mm
index c951332022..21e5714762 100644
--- a/platform/platform_ios.mm
+++ b/platform/platform_ios.mm
@@ -91,6 +91,12 @@ Platform::~Platform()
delete m_impl;
}
+bool Platform::IsFileExists(string const & file) const
+{
+ struct stat s;
+ return stat(file.c_str(), &s) == 0;
+}
+
void Platform::GetFilesInDir(string const & directory, string const & mask, FilesList & res) const
{
DIR * dir;
@@ -144,22 +150,9 @@ void Platform::GetFontNames(FilesList & res) const
sort(res.begin(), res.end());
}
-static string ReadPathForFile(string const & writableDir,
- string const & resourcesDir, string const & file)
-{
- string fullPath = writableDir + file;
- if (!GetPlatform().IsFileExists(fullPath))
- {
- fullPath = resourcesDir + file;
- if (!GetPlatform().IsFileExists(fullPath))
- MYTHROW(FileAbsentException, ("File doesn't exist", fullPath));
- }
- return fullPath;
-}
-
ModelReader * Platform::GetReader(string const & file) const
{
- return new FileReader(ReadPathForFile(m_writableDir, m_resourcesDir, file), 10, 12);
+ return new FileReader(ReadPathForFile(file), 10, 12);
}
int Platform::CpuCores() const
diff --git a/platform/platform_linux.cpp b/platform/platform_linux.cpp
index 748fd50dcd..be9b580cf4 100644
--- a/platform/platform_linux.cpp
+++ b/platform/platform_linux.cpp
@@ -4,33 +4,56 @@
#include <unistd.h>
#include <sys/stat.h>
-#define LOCALAPPDATA_DIR "MapsWithMe"
+//static bool GetUserWritableDir(string & outDir)
+//{
+// char * path = ::getenv("HOME");
+// if (path)
+// {
+// outDir = path;
+// outDir += "/.MapsWithMe/";
+// ::mkdir(outDir.c_str(), 0755);
+// return true;
+// }
+// return false;
+//}
-bool GetUserWritableDir(string & outDir)
-{
- char * path = ::getenv("HOME");
- if (path)
- {
- outDir = path;
- outDir += "." LOCALAPPDATA_DIR "/";
- ::mkdir(outDir.c_str(), 0755);
- return true;
- }
- return false;
-}
-
-/// @return full path including binary itself
-bool GetPathToBinary(string & outPath)
+/// @return directory where binary resides, including slash at the end
+static bool GetBinaryFolder(string & outPath)
{
char path[4096] = {0};
if (0 < ::readlink("/proc/self/exe", path, ARRAY_SIZE(path)))
{
outPath = path;
+ outPath.erase(outPath.find_last_of('/') + 1);
return true;
}
return false;
}
+Platform::Platform()
+{
+ // init directories
+ string path;
+ CHECK(GetBinaryFolder(path), ("Can't retrieve path to executable"));
+
+ // @TODO implement correct resources and writable directories for public releases
+ m_resourcesDir = path + "../../../data";
+ m_writableDir = m_resourcesDir;
+
+ LOG(LDEBUG, ("Resources directory:", m_resourcesDir));
+ LOG(LDEBUG, ("Writable directory:", m_writableDir));
+}
+
+Platform::~Platform()
+{
+}
+
+bool Platform::IsFileExists(string const & file) const
+{
+ struct stat s;
+ return stat(file.c_str(), &s) == 0;
+}
+
int Platform::CpuCores() const
{
long numCPU = sysconf(_SC_NPROCESSORS_ONLN);
diff --git a/platform/platform_mac.mm b/platform/platform_mac.mm
index 2eed808312..ae406f3caa 100644
--- a/platform/platform_mac.mm
+++ b/platform/platform_mac.mm
@@ -1,62 +1,65 @@
#include "platform.hpp"
+#include "../base/logging.hpp"
+
#include "../std/target_os.hpp"
-#include <glob.h>
-#include <NSSystemDirectories.h>
-#include <mach-o/dyld.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/sysctl.h>
#include <IOKit/IOKitLib.h>
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSAutoreleasePool.h>
-#define LOCALAPPDATA_DIR "MapsWithMe"
+#include <sys/stat.h>
+#include <sys/sysctl.h>
-static string ExpandTildePath(char const * path)
+Platform::Platform()
{
- glob_t globbuf;
- string result = path;
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) //success
+ // get resources directory path
+ string const resourcesPath = [[[NSBundle mainBundle] resourcePath] UTF8String];
+ string const bundlePath = [[[NSBundle mainBundle] bundlePath] UTF8String];
+ if (resourcesPath == bundlePath)
{
- if (globbuf.gl_pathc > 0)
- result = globbuf.gl_pathv[0];
+ // we're the console app, probably unit test, and path is our directory
+ m_resourcesDir = bundlePath + "/../../data/";
+ m_writableDir = m_resourcesDir;
+ }
+ else
+ {
+ m_resourcesDir = resourcesPath + "/";
- globfree(&globbuf);
+ // get writable path
+#ifndef OMIM_PRODUCTION
+ // developers can have symlink to data folder
+ char const * dataPath = "../../../../../data/";
+ if (IsFileExists(m_resourcesDir + dataPath))
+ m_writableDir = m_resourcesDir + dataPath;
+#endif
+
+ if (m_writableDir.empty())
+ {
+ NSArray * dirPaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ NSString * supportDir = [dirPaths objectAtIndex:0];
+ m_writableDir = [supportDir UTF8String];
+ m_writableDir += "/MapsWithMe/";
+ ::mkdir(m_writableDir.c_str(), 0755);
+ }
}
- return result;
+ [pool release];
+
+ LOG(LDEBUG, ("Resources Directory:", m_resourcesDir));
+ LOG(LDEBUG, ("Writable Directory:", m_writableDir));
}
-bool GetUserWritableDir(string & outDir)
+Platform::~Platform()
{
- char pathBuf[PATH_MAX];
- NSSearchPathEnumerationState state = ::NSStartSearchPathEnumeration(NSApplicationSupportDirectory, NSUserDomainMask);
- while ((state = NSGetNextSearchPathEnumeration(state, pathBuf)))
- {
- outDir = ExpandTildePath(pathBuf);
- ::mkdir(outDir.c_str(), 0755);
- outDir += "/" LOCALAPPDATA_DIR "/";
- ::mkdir(outDir.c_str(), 0755);
- return true;
- }
- return false;
}
-/// @return full path including binary itself
-bool GetPathToBinary(string & outPath)
+bool Platform::IsFileExists(string const & file) const
{
- char path[MAXPATHLEN] = {0};
- uint32_t pathSize = ARRAY_SIZE(path);
- if (0 == ::_NSGetExecutablePath(path, &pathSize))
- {
- char fixedPath[MAXPATHLEN] = {0};
- if (::realpath(path, fixedPath))
- {
- outPath = fixedPath;
- return true;
- }
- }
- return false;
+ struct stat s;
+ return stat(file.c_str(), &s) == 0;
}
int Platform::CpuCores() const
diff --git a/platform/platform_qt.cpp b/platform/platform_qt.cpp
index 10ab490789..17895bfe08 100644
--- a/platform/platform_qt.cpp
+++ b/platform/platform_qt.cpp
@@ -8,119 +8,10 @@
#include <QtCore/QFileInfo>
#include <QtCore/QTemporaryFile>
-// default writable directory name for dev/standalone installs
-#define MAPDATA_DIR "data"
-// default writable dir name in LocalAppData or ~/Library/AppData/ folders
-#define LOCALAPPDATA_DIR "MapsWithMe"
-// default Resources read-only dir
-#define RESOURCES_DIR "Resources"
-
-/// @name Platform-dependent implementations in separate files
-//@{
-bool GetUserWritableDir(string & outDir);
-bool GetPathToBinary(string & outDir);
-//@}
-
-static bool IsDirectoryWritable(string const & dir)
-{
- if (!dir.empty())
- {
- QString qDir = dir.c_str();
- if (dir[dir.size() - 1] != '/' && dir[dir.size() - 1] != '\\')
- qDir.append('/');
-
- QTemporaryFile file(qDir + "XXXXXX");
- if (file.open())
- return true;
- }
- return false;
-}
-
-/// Scans all upper directories for the presence of given directory
-/// @param[in] startPath full path to lowest file in hierarchy (usually binary)
-/// @param[in] dirName directory name we want to be present
-/// @return if not empty, contains full path to existing directory
-static string DirFinder(string const & startPath, string dirName)
-{
- char const SLASH = QDir::separator().toAscii();
- dirName = SLASH + dirName + SLASH;
-
- size_t slashPos = startPath.size();
- while (slashPos > 0 && (slashPos = startPath.rfind(SLASH, slashPos - 1)) != string::npos)
- {
- string const dir = startPath.substr(0, slashPos) + dirName;
- if (QFileInfo(dir.c_str()).exists())
- return dir;
- }
- return string();
-}
-
-static bool GetOSSpecificResourcesDir(string const & exePath, string & dir)
-{
- dir = DirFinder(exePath, RESOURCES_DIR);
- return !dir.empty();
-}
-
-static void InitResourcesDir(string & dir)
-{
- // Resources dir can be any "data" folder found in the nearest upper directory,
- // where all necessary resources files are present and accessible
- string exePath;
- CHECK( GetPathToBinary(exePath), ("Can't get full path to executable") );
- dir = DirFinder(exePath, MAPDATA_DIR);
- if (dir.empty())
- {
- CHECK( GetOSSpecificResourcesDir(exePath, dir), ("Can't retrieve resources directory") );
- }
-
- /// @todo Check all necessary files
-}
-
-static void InitWritableDir(string & dir)
-{
- // Writable dir can be any "data" folder found in the nearest upper directory
- // ./data - For Windows portable builds
- // ../data
- // ../../data - For developer builds
- // etc. (for Mac in can be up to 6 levels above due to packages structure
- // and if no _writable_ "data" folder was found, User/Application Data/MapsWithMe will be used
-
- string path;
- CHECK( GetPathToBinary(path), ("Can't get full path to executable") );
- dir = DirFinder(path, MAPDATA_DIR);
- if (dir.empty() || !IsDirectoryWritable(dir))
- {
- CHECK( GetUserWritableDir(dir), ("Can't get User's Application Data writable directory") );
- }
-}
-
-static string ReadPathForFile(string const & writableDir,
- string const & resourcesDir, string const & file)
-{
- string fullPath = writableDir + file;
- if (!GetPlatform().IsFileExists(fullPath))
- {
- fullPath = resourcesDir + file;
- if (!GetPlatform().IsFileExists(fullPath))
- MYTHROW(FileAbsentException, ("File doesn't exist", fullPath));
- }
- return fullPath;
-}
-
////////////////////////////////////////////////////////////////////////////////////////
-Platform::Platform()
-{
- InitWritableDir(m_writableDir);
- InitResourcesDir(m_resourcesDir);
-}
-
-Platform::~Platform()
-{
-}
-
ModelReader * Platform::GetReader(string const & file) const
{
- return new FileReader(ReadPathForFile(m_writableDir, m_resourcesDir, file), 10, 12);
+ return new FileReader(ReadPathForFile(file), 10, 12);
}
bool Platform::GetFileSize(string const & file, uint64_t & size) const
diff --git a/platform/platform_tests/platform_test.cpp b/platform/platform_tests/platform_test.cpp
index 5904700dee..c66cac2c3a 100644
--- a/platform/platform_tests/platform_test.cpp
+++ b/platform/platform_tests/platform_test.cpp
@@ -4,7 +4,7 @@
#include "../../defines.hpp"
-#include "../../coding/writer.hpp"
+#include "../../coding/file_writer.hpp"
#include "../../coding/internal/file_data.hpp"
#include "../../base/logging.hpp"
@@ -72,13 +72,20 @@ UNIT_TEST(GetFilesInDir)
TEST_EQUAL(files.size(), 0, ());
}
-//UNIT_TEST(GetFileSize)
-//{
-// Platform & pl = GetPlatform();
-// uint64_t size = 0;
-// pl.GetFileSize(pl.ReadPathForFile("classificator.txt").c_str(), size);
-// TEST_GREATER(size, 0, ("File classificator.txt should exist for test"));
-//}
+UNIT_TEST(GetFileSize)
+{
+ Platform & pl = GetPlatform();
+
+ {
+ FileWriter testFile(TEST_FILE_NAME);
+ testFile.Write("HOHOHO", 6);
+ }
+ uint64_t size = 0;
+ pl.GetFileSize(TEST_FILE_NAME, size);
+ TEST_EQUAL(size, 6, ());
+
+ FileWriter::DeleteFileX(TEST_FILE_NAME);
+}
UNIT_TEST(CpuCores)
{
diff --git a/platform/platform_win.cpp b/platform/platform_win.cpp
index ff59584210..b0013e7c95 100644
--- a/platform/platform_win.cpp
+++ b/platform/platform_win.cpp
@@ -1,27 +1,28 @@
#include "platform.hpp"
+#include "../coding/file_writer.hpp"
+
#include "../std/windows.hpp"
#include <shlobj.h>
+#include <sys/stat.h>
-#define LOCALAPPDATA_DIR "MapsWithMe"
-
-bool GetUserWritableDir(string & outDir)
+static bool GetUserWritableDir(string & outDir)
{
char pathBuf[MAX_PATH] = {0};
if (SUCCEEDED(::SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, pathBuf)))
{
outDir = pathBuf;
::CreateDirectoryA(outDir.c_str(), NULL);
- outDir += "\\" LOCALAPPDATA_DIR "\\";
+ outDir += "\\MapsWithMe\\";
::CreateDirectoryA(outDir.c_str(), NULL);
return true;
}
return false;
}
-/// @return full path including binary itself
-bool GetPathToBinary(string & outPath)
+/// @return Full path to the executable file
+static bool GetPathToBinary(string & outPath)
{
// get path to executable
char pathBuf[MAX_PATH] = {0};
@@ -33,6 +34,58 @@ bool GetPathToBinary(string & outPath)
return false;
}
+Platform::Platform()
+{
+ string path;
+ CHECK(GetPathToBinary(path), ("Can't get path to binary"));
+
+ // resources path:
+ // 1. try to use data folder in the same path as executable
+ // 2. if not found, try to use ..\..\..\data (for development only)
+ path.erase(path.find_last_of('\\'));
+ if (IsFileExists(path + "\\data\\"))
+ m_resourcesDir = path + "\\data\\";
+ else
+ {
+#ifndef OMIM_PRODUCTION
+ path.erase(path.find_last_of('\\'));
+ path.erase(path.find_last_of('\\'));
+ if (IsFileExists(path + "\\data\\"))
+ m_resourcesDir = path + "\\data\\";
+#else
+ CHECK(false, ("Can't find resources directory"));
+#endif
+ }
+
+ // writable path:
+ // 1. the same as resources if we have write access to this folder
+ // 2. otherwise, use system-specific folder
+ try
+ {
+ FileWriter tmpfile(m_resourcesDir + "mapswithmetmptestfile");
+ tmpfile.Write("Hi from Alex!", 13);
+ FileWriter::DeleteFileX(m_resourcesDir + "mapswithmetmptestfile");
+ m_writableDir = m_resourcesDir;
+ }
+ catch (FileWriter::RootException const &)
+ {
+ CHECK(GetUserWritableDir(m_writableDir), ("Can't get writable directory"));
+ }
+
+ LOG(LDEBUG, ("Resources Directory:", m_resourcesDir));
+ LOG(LDEBUG, ("Writable Directory:", m_writableDir));
+}
+
+Platform::~Platform()
+{
+}
+
+bool Platform::IsFileExists(string const & file) const
+{
+ struct _stat s;
+ return _stat(file.c_str(), &s) == 0;
+}
+
int Platform::CpuCores() const
{
SYSTEM_INFO sysinfo;