1 /*
2 Copyright (C) 2009/2010 Kai Sterker <kai.sterker@gmail.com>
3 Part of the Adonthell Project <http://adonthell.nongnu.org>
4
5 Dlgedit is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 Dlgedit is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Dlgedit. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file common/util.cc
21 *
22 * @author Kai Sterker
23 * @brief Helper methods.
24 */
25
26 #include <sys/param.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <libgen.h>
31 #include <unistd.h>
32 #include "game.h"
33
34 #ifdef WIN32
35 #define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
36 #undef PATH_MAX
37 #define PATH_MAX _MAX_PATH
38 #endif
39
40 #include "util.h"
41
42 // get path relative to data directory
get_relative_path(const std::string & path,const std::string & target_dir)43 std::string util::get_relative_path (const std::string & path, const std::string & target_dir)
44 {
45 std::string base_path = MK_UNIX_PATH (game::user_data_dir());
46 std::string rel_path = path;
47
48 // make sure to use path relative to (user defined) data directory
49 if (base_path == "" || !remove_common_path (rel_path, base_path))
50 {
51 // fallback to builtin data dir if that doesn't seem to work
52 base_path = MK_UNIX_PATH (game::game_data_dir());
53 if (!remove_common_path (rel_path, base_path))
54 {
55 // if everything fails, try locating target_dir in the path and use
56 // that as relative path
57 size_t pos = rel_path.rfind (target_dir);
58 if (pos != std::string::npos)
59 {
60 rel_path = rel_path.substr (pos);
61 if (rel_path[0] == '/')
62 {
63 rel_path = rel_path.substr (1);
64 }
65 }
66 }
67 }
68
69 return rel_path;
70 }
71
72 // try to make path relative to base path
remove_common_path(std::string & path,const std::string & base_path)73 bool util::remove_common_path (std::string & path, const std::string & base_path)
74 {
75 // make canonical base path
76 char canonical_path[PATH_MAX];
77 if (realpath(base_path.c_str(), canonical_path))
78 {
79 std::string c_base_path = canonical_path;
80 if (realpath(path.c_str(), canonical_path))
81 {
82 path = MK_UNIX_PATH (canonical_path);
83 if (path.compare (0, c_base_path.size(), c_base_path) == 0)
84 {
85 path = path.substr (c_base_path.length());
86 if (path[0] == '/')
87 {
88 path = path.substr (1);
89 }
90 return true;
91 }
92 }
93 }
94
95 return false;
96 }
97
98 // convert windows directory separators to unix style
to_unix_path(const std::string & path)99 std::string util::to_unix_path (const std::string & path)
100 {
101 std::string result = path;
102 for (std::string::iterator i = result.begin(); i != result.end(); i++)
103 {
104 if (*i == '\\') *i = '/';
105 }
106 return result;
107 }
108
109 // convert relative path to absolute path
get_absolute_path(const std::string & path)110 std::string util::get_absolute_path (const std::string & path)
111 {
112 std::string result = path;
113
114 if (result[0] != '/')
115 {
116 char *oldwd = getcwd (NULL, 0);
117 if (chdir (dirname ((char*) result.c_str())))
118 {
119 return path;
120 }
121
122 // get absolute pathname
123 char *cpath = getcwd (NULL, 0);
124 char *bname = strdup (path.c_str());
125 result = std::string(cpath) + "/" + basename (bname);
126
127 // restore working directory
128 chdir (oldwd);
129
130 // cleanup
131 free (oldwd);
132 free (cpath);
133 free (bname);
134 }
135
136 return result;
137 }
138