]> git.cworth.org Git - apitrace/blob - common/os_path.hpp
Move os::Path to a separate header.
[apitrace] / common / os_path.hpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 /*
27  * Path manipulation.
28  */
29
30 #ifndef _OS_PATH_HPP_
31 #define _OS_PATH_HPP_
32
33
34 #include <assert.h>
35
36 #include <vector>
37
38 #include "os.hpp"
39
40
41 #ifdef _WIN32
42 #define OS_DIR_SEP '\\'
43 #else /* !_WIN32 */
44 #define OS_DIR_SEP '/'
45 #endif /* !_WIN32 */
46
47
48 namespace os {
49
50
51 class Path {
52 protected:
53     typedef std::vector<char> Buffer;
54     Buffer buffer;
55
56     Buffer::iterator rfind(char c) {
57         Buffer::iterator it = buffer.end();
58         while (it != buffer.begin()) {
59             --it;
60             if (*it == c) {
61                 return it;
62             }
63         }
64         return buffer.end();
65     }
66
67     Path(size_t size) :
68         buffer(size) {
69     }
70
71     char *buf(void) {
72         return &buffer[0];
73     }
74
75 public:
76     Path() {
77         buffer.push_back(0);
78     }
79
80     Path(const char *s) :
81         buffer(s, s + strlen(s) + 1)
82     {}
83
84     template <class InputIterator>
85     Path(InputIterator first, InputIterator last) :
86         buffer(first, last)
87     {
88         buffer.push_back(0);
89     }
90
91     char *buf(size_t size) {
92         buffer.resize(size);
93         return &buffer[0];
94     }
95
96     void trimDirectory(void) {
97         Buffer::iterator sep = rfind(OS_DIR_SEP);
98         if (sep != buffer.end()) {
99             buffer.erase(buffer.begin(), sep + 1);
100         }
101     }
102
103     void trimExtension(void) {
104         Buffer::iterator dot = rfind('.');
105         if (dot != buffer.end()) {
106             buffer.erase(dot, buffer.end());
107         }
108     }
109
110     size_t length(void) const {
111         size_t size = buffer.size();
112         assert(size > 0);
113         assert(buffer[size - 1] == 0);
114         return size - 1;
115     }
116
117     void truncate(size_t length) {
118         assert(length < buffer.size());
119         buffer[length] = 0;
120         buffer.resize(length + 1);
121     }
122
123     void truncate(void) {
124         truncate(strlen(str()));
125     }
126
127     const char *str(void) const {
128         assert(buffer[buffer.size() - 1] == 0);
129         return &buffer[0];
130     }
131
132     operator const char *(void) const {
133         return str();
134     }
135
136     void join(const Path & other) {
137         size_t len = length();
138         if (len > 0 && buffer[len - 1] != OS_DIR_SEP) {
139             buffer.insert(buffer.begin() + len++, OS_DIR_SEP);
140         }
141         buffer.insert(buffer.begin() + len, other.buffer.begin(), other.buffer.end() - 1);
142     }
143
144     /**
145      * Create a path from a printf-like format string
146      */
147     static Path
148     format(const char *format, ...)
149 #ifdef __GNUC__
150     __attribute__ ((format (printf, 1, 2)))
151 #endif
152     {
153
154         va_list args;
155
156         va_start(args, format);
157
158         int length;
159         va_list args_copy;
160         va_copy(args_copy, args);
161 #ifdef _MSC_VER
162         /* We need to use _vcsprintf to calculate the length as vsnprintf returns -1
163          * if the number of characters to write is greater than count.
164          */
165         length = _vscprintf(format, args_copy);
166 #else
167         char dummy;
168         length = vsnprintf(&dummy, sizeof dummy, format, args_copy);
169 #endif
170         va_end(args_copy);
171
172         assert(length >= 0);
173         size_t size = length + 1;
174
175         Path path(size);
176
177         va_start(args, format);
178         vsnprintf(path.buf(), size, format, args);
179         va_end(args);
180
181         return path;
182     }
183 };
184
185
186 Path getProcessName();
187 Path getCurrentDir();
188
189
190 } /* namespace os */
191
192 #endif /* _OS_PATH_HPP_ */