Commits

mitsuhiko  committed 7e07185

Added OS X path support

  • Participants
  • Parent commits af7e275

Comments (0)

Files changed (8)

File neglect/cpplib/CMakeLists.txt

     src/format.cpp
     src/platform.cpp
     src/ntpath.cpp
+    src/posixpath.cpp
 )
 set(HEADERS
 	include/neglect/boot.hpp
 	include/neglect/unittest.hpp
 	include/neglect/path.hpp
 	include/neglect/ntpath.hpp
+    include/neglect/posixpath.hpp
 	
 	include/neglect/boot.h
 )

File neglect/cpplib/include/neglect/posixpath.hpp

+#ifndef _INC_NEGLECT_POSIXPATH_HPP_
+#define _INC_NEGLECT_POSIXPATH_HPP_
+
+#include <neglect/boot.hpp>
+
+namespace neglect { namespace posixpath {
+
+    /* the kind of integer used for filesizes on this platform */
+    typedef boost::int64_t filesize_t;
+
+    /* checks if a path is absolute */
+    bool is_abs(const neglect::string &filename);
+
+    /* joins two paths */
+    neglect::string join(const neglect::string &a, const neglect::string &b);
+
+    /* returns the directory name from a path */
+    neglect::string dirname(const neglect::string &filename);
+
+    /* returns the filename or last folder from a path */
+    neglect::string basename(const neglect::string &filename);
+
+    // the following functions will only work if compiled for
+    // a posix platform
+#if NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+
+    /* makes a path absolute */
+    neglect::string abspath(const neglect::string &filename);
+
+    /* returns the current working directory */
+    neglect::string getcwd();
+
+    /* checks if a path exists */
+    bool exists(const neglect::string &filename);
+
+    /* checks if a path is a file */
+    bool is_file(const neglect::string &filename);
+
+    /* checks if a path is a directory */
+    bool is_dir(const neglect::string &filename);
+
+    /* creates a directory.  returns true if the directory exists
+       after this call (it either was created or existed already) */
+    bool mkdir(const neglect::string &filename);
+
+    /* removes a directory or file.  When removing directories, the
+       directory has to be empty.  Returns true if the file does
+       not exist after this call (either did not exist to begin with
+       or was successfully removed)*/
+    bool remove(const neglect::string &filename);
+
+    /* renames a file or directory.  Returns true if this
+       worked out well.  This overrites the target file if it
+       existed already. */
+    bool rename(const neglect::string &filename,
+                const neglect::string &new_name);
+
+    /* return the file size of a file */
+    filesize_t filesize(const neglect::string &filename);
+#endif
+}}
+
+#endif

File neglect/cpplib/libneglect.a

Binary file added.

File neglect/cpplib/src/platform.cpp

 
 #if NEGLECT_PLATFORM == NEGLECT_PLATFORM_WINDOWS
 #   include "shlobj.h"
+#elif NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+#   include <sys/types.h>
+#   include <pwd.h>
+extern "C" {
+    extern int *_NSGetArgc(void);
+    extern char ***_NSGetArgv(void);
+}
 #endif
 
 using namespace neglect;
         struct passwd *pw = getpwuid(getuid());
         endpwent();
         if (!pw)
-            throw platform_exception("Unable to locate home folder");
-        _home_folder = neglect::string(pw->pw_dir);
-        if (!_home_folder.empty() and dir[dir.size() - 1] == '/')
-            _home_folder.resize(_home_folder.size() - 1);
+            _home_folder = "/tmp";
+        else {
+            _home_folder = neglect::string(pw->pw_dir);
+            if (!_home_folder.empty() and _home_folder[_home_folder.size() - 1] == '/')
+                _home_folder.resize(_home_folder.size() - 1);
+        }
     }
 #else
 #   error "unsupported platform for platform::get_home_folder()"
     CoTaskMemFree(pidl);
     return neglect::string(path) + "\\" + appname;
 #elif NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
-    return platform::get_home_folder() + "/Library/Application Support/" + appname
+    return platform::get_home_folder() + "/Library/Application Support/" + appname;
 #else
 #   error "unsupported platform for platform::get_settings_folder()"
 #endif
     char path[MAX_PATH];
     GetModuleFileNameA(0, path, MAX_PATH);
     _executable = neglect::string(path);
+#elif NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+    _executable = path::abspath((*_NSGetArgv())[0]);
 #else
 #   error "unsupported platform for platform::get_executable()
 #endif
 #if NEGLECT_PLATFORM == NEGLECT_PLATFORM_WINDOWS
     for (int i = 1; i < __argc; i++)
         _arguments.push_back(__argv[i]);
+#elif NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+    int argc = *_NSGetArgc();
+    char **argv = *_NSGetArgv();
+    for (int i = 1; i < argc; i++)
+        _arguments.push_back(argv[i]);
 #else
 #   error "unsupported platform for platform::get_arguments()
 #endif
     _arguments_found = true;
     return _arguments;
-}
+}

File neglect/cpplib/src/posixpath.cpp

+#include <neglect/posixpath.hpp>
+
+#if NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+#   include <sys/stat.h>
+#   include <stdio.h>
+#   include <errno.h>
+#   include <unistd.h>
+#endif
+
+using namespace neglect;
+
+bool posixpath::is_abs(const neglect::string &filename)
+{
+    return !filename.empty() && filename[0] == '/';
+}
+
+neglect::string posixpath::join(const neglect::string &a, const neglect::string &b)
+{
+    if (b.empty())
+        return a;
+    if (a.empty() || b[0] == '/')
+        return b;
+    if (a[a.size() - 1] == '/')
+        return a + b;
+    return a + "/" + b;
+}
+
+neglect::string posixpath::dirname(const neglect::string &filename)
+{
+    size_t idx = filename.rfind('/');
+    if (idx == neglect::string::npos)
+        return filename;
+    neglect::string rv = filename.substr(0, idx);
+    while (!rv.empty() && rv[rv.size() - 1] == '/')
+        rv.resize(rv.size() - 1);
+    if (rv.empty() && !filename.empty() && filename[0] == '/')
+        return "/";
+    return rv;
+}
+
+neglect::string posixpath::basename(const neglect::string &filename)
+{
+    size_t idx = filename.rfind('/');
+    if (idx == neglect::string::npos)
+        return filename;
+    return filename.substr(idx + 1);
+}
+
+
+#if NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+
+neglect::string posixpath::getcwd()
+{
+    char *buffer = ::getcwd(0, 0);
+    if (!buffer)
+        return "";
+    neglect::string rv(buffer);
+    free(buffer);
+    return rv;
+}
+
+neglect::string posixpath::abspath(const neglect::string &filename)
+{
+    if (!posixpath::is_abs(filename))
+        return posixpath::join(posixpath::getcwd(), filename);
+    return filename;
+}
+
+bool posixpath::exists(const neglect::string &filename)
+{
+    struct stat buf;
+    if (stat(filename.c_str(), &buf) != 0)
+        if (errno == ENOENT)
+            return false;
+    return true;
+}
+
+bool posixpath::is_file(const neglect::string &filename)
+{
+    struct stat buf;
+    int rv = stat(filename.c_str(), &buf);
+    if (rv != 0)
+        return false;
+    return !!(buf.st_mode & S_IFREG);
+}
+
+bool posixpath::is_dir(const neglect::string &filename)
+{
+    struct stat buf;
+    int rv = stat(filename.c_str(), &buf);
+    if (rv != 0)
+        return false;
+    return !!(buf.st_mode & S_IFDIR);
+}
+
+bool posixpath::mkdir(const neglect::string &filename)
+{
+    if (::mkdir(filename.c_str(), 0777) == 0)
+        return true;
+    return errno == EEXIST;
+}
+
+bool posixpath::remove(const neglect::string &filename)
+{
+    if (posixpath::is_dir(filename)) {
+        if (rmdir(filename.c_str()) == 0)
+            return true;
+    }
+    else if (unlink(filename.c_str()) == 0)
+        return true;
+    return errno == ENOENT;
+}
+
+bool posixpath::rename(const neglect::string &filename,
+                    const neglect::string &new_name)
+{
+    return ::rename(filename.c_str(), new_name.c_str()) == 0;
+}
+
+posixpath::filesize_t posixpath::filesize(const neglect::string &filename)
+{
+    struct stat64 buf;
+    int rv = stat64(filename.c_str(), &buf);
+    if (rv != 0)
+        return 0;
+    return buf.st_size;
+}
+
+#endif

File neglect/tests/neglect_tests

Binary file added.

File neglect/tests/src/test_path.cpp

 }
 
 
+NUT_TESTGROUP(posixpath) {
+
+    NUT_TESTCASE(join)
+    {
+        NUT_CHECK_EQUAL(posixpath::join("a", "b"), "a/b");
+        NUT_CHECK_EQUAL(posixpath::join("a", "/b"), "/b");
+        NUT_CHECK_EQUAL(posixpath::join("a/", "b"), "a/b");
+        NUT_CHECK_EQUAL(posixpath::join("a/b", "c"), "a/b/c");
+        NUT_CHECK_EQUAL(posixpath::join("a/b", "c/d"), "a/b/c/d");
+        NUT_CHECK_EQUAL(posixpath::join("", "b"), "b");
+        NUT_CHECK_EQUAL(posixpath::join("a", ""), "a");
+    }
+
+    NUT_TESTCASE(is_abs)
+    {
+        NUT_CHECK(posixpath::is_abs("/a"));
+        NUT_CHECK(posixpath::is_abs("/a/b"));
+        NUT_CHECK(!posixpath::is_abs("a"));
+        NUT_CHECK(!posixpath::is_abs("a/b"));
+    }
+
+    NUT_TESTCASE(dirname)
+    {
+        NUT_CHECK_EQUAL(posixpath::dirname("foo/bar"), "foo");
+        NUT_CHECK_EQUAL(posixpath::dirname("foo////bar"), "foo");
+        NUT_CHECK_EQUAL(posixpath::dirname("/foo////bar"), "/foo");
+        NUT_CHECK_EQUAL(posixpath::dirname("/foo"), "/");
+    }
+
+    NUT_TESTCASE(basename)
+    {
+        NUT_CHECK_EQUAL(posixpath::basename("foo/bar"), "bar");
+        NUT_CHECK_EQUAL(posixpath::basename("foo////bar"), "bar");
+        NUT_CHECK_EQUAL(posixpath::basename("/foo////bar"), "bar");
+        NUT_CHECK_EQUAL(posixpath::basename("/foo"), "foo");
+    }
+}
+
+
 NUT_TESTGROUP(native_path) {
 
     NUT_TESTCASE(select_correct)
         NUT_REQUIRE(!path::is_file(filename2));
         NUT_REQUIRE(!path::is_file(filename2));
     }
-}
+}

File neglect/tests/src/test_platform.cpp

     {
 #if NEGLECT_PLATFORM == NEGLECT_PLATFORM_WINDOWS
         NUT_CHECK_EQUAL(platform::name, "Windows");
+#elif NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+        NUT_CHECK_EQUAL(platform::name, "OS X");
 #else
 #error  "unsupported platform in platform::name test"
 #endif
         std::string executable = platform::get_executable();
         NUT_REQUIRE(path::is_file(executable));
     }
-}
+}