blob: 60d4da84097b8c13e833bcb19f750a7470bbbf8e [file] [log] [blame]
Raphael628920b2011-11-22 10:40:13 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _H_UTILS
18#define _H_UTILS
19
20#ifdef _WIN32
21
22#include <direct.h>
23#include <stdio.h>
24#include <stdarg.h>
25#include <string.h>
26#include <windows.h>
27
28// VS vs MINGW specific includes
29#ifdef USE_VS_CRT
30 #include <crtdbg.h> // for _ASSERT
31#else
32 #define _ASSERT(x) // undef
33#endif
34
35extern bool gDebug;
36
37// An array that knows its own size. Not dynamically resizable.
38template <class T> class CArray {
39 T* mPtr;
40 int mSize;
41public:
42 explicit CArray(int size) {
43 mSize = size;
44 mPtr = new T[size];
45 }
46
47 ~CArray() {
48 if (mPtr != NULL) {
49 delete[] mPtr;
50 mPtr = NULL;
51 }
52 mSize = 0;
53 }
54
55 T& operator[](int i) {
56 _ASSERT(i >= 0 && i < mSize);
57 return mPtr[i];
58 }
59
60 int size() const {
61 return mSize;
62 }
63};
64
65// A simple string class wrapper.
66class CString {
67protected:
68 char *mStr;
69public:
70 CString() { mStr = NULL; }
71 CString(const CString &str) { mStr = str.mStr == NULL ? NULL : _strdup(str.mStr); }
72 explicit CString(const char *str) { mStr = NULL; set(str); }
73 CString(const char *start, int length) { mStr = NULL; set(start, length); }
74
75 CString& set(const char *str) {
76 _free();
77 if (str != NULL) {
78 mStr = _strdup(str);
79 }
80 return *this;
81 }
82
83 CString& set(const char *start, int length) {
84 _free();
85 if (start != NULL) {
86 mStr = (char *)malloc(length + 1);
87 strncpy(mStr, start, length);
88 mStr[length] = 0;
89 }
90 return *this;
91 }
92
93 CString& setv(const char *str, va_list ap) {
94 _free();
95 // _vscprintf(str, ap) is only available with the MSVCRT, not MinGW.
96 // Instead we'll iterate till we have enough space to generate the string.
97 int len = strlen(str) + 1024;
98 mStr = (char *)malloc(len);
99 strcpy(mStr, str); // provide a default in case vsnprintf totally fails
100 for (int guard = 0; guard < 10; guard++) {
101 int ret = vsnprintf(mStr, len, str, ap);
102 if (ret == -1) {
103 // Some implementations don't give the proper size needed
104 // so double the space and try again.
105 len *= 2;
106 } else if (ret >= len) {
107 len = ret + 1;
108 } else {
109 // There was enough space to write.
110 break;
111 }
112 mStr = (char *)realloc((void *)mStr, len);
113 strcpy(mStr, str); // provide a default in case vsnprintf totally fails
114 }
115 return *this;
116 }
117
118 CString& setf(const char *str, ...) {
119 _free();
120 va_list ap;
121 va_start(ap, str);
122 setv(str, ap);
123 va_end(ap);
124 return *this;
125 }
126
127 virtual ~CString() { _free(); }
128
129 // Returns the C string owned by this CString. It will be
130 // invalid as soon as this CString is deleted or out of scope.
131 const char * cstr() const {
132 return mStr;
133 }
134
135 bool isEmpty() const {
136 return mStr == NULL || *mStr == 0;
137 }
138
139 int length() const {
140 return mStr == NULL ? 0 : strlen(mStr);
141 }
142
143 CString& add(const char *s) {
144 if (mStr == NULL) {
145 set(s);
146 } else {
147 mStr = (char *)realloc((void *)mStr, strlen(mStr) + strlen(s) + 1);
148 strcat(mStr, s);
149 }
150 return *this;
151 }
152
153 CArray<CString> * split(char sep) const {
154 if (mStr == NULL) {
155 return new CArray<CString>(0);
156 }
157 const char *last = NULL;
158 int n = 0;
159 for (const char *s = mStr; *s; s++) {
160 if (*s == sep && s != mStr && (last == NULL || s > last+1)) {
161 n++;
162 last = s;
163 }
164 }
165
166 CArray<CString> *result = new CArray<CString>(n);
167 last = NULL;
168 n = 0;
169 for (const char *s = mStr; *s; s++) {
170 if (*s == sep) {
171 if (s != mStr && (last == NULL || s > last+1)) {
172 const char *start = last ? last : mStr;
173 (*result)[n++].set(start, s-start);
174 }
175 last = s+1;
176 }
177 }
178
179 return result;
180 }
181
182 CString& setLastWin32Error() {
183 DWORD err = GetLastError();
184 LPSTR errStr;
185 if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | /* dwFlags */
186 FORMAT_MESSAGE_FROM_SYSTEM,
187 NULL, /* lpSource */
188 err, /* dwMessageId */
189 0, /* dwLanguageId */
190 (LPSTR)&errStr, /* lpBuffer */
191 0, /* nSize */
192 NULL) != 0) { /* va_list args */
193 set(errStr);
194 LocalFree(errStr);
195 }
196 return *this;
197 }
198
199private:
200 void _free() {
201 if (mStr != NULL) {
202 free((void *)mStr);
203 mStr = NULL;
204 }
205 }
206
207};
208
209// A simple path class wrapper.
210class CPath : public CString {
211public:
212 CPath() : CString() { }
213 CPath(const CPath &str) : CString(str) { }
214 explicit CPath(const char *str) : CString(str) { }
215 CPath(const char *start, int length) : CString(start, length) { }
216
217 // Appends a path segment, adding a \ as necessary.
218 CPath& addPath(const CString &s) {
219 return addPath(s.cstr());
220 }
221
222 // Appends a path segment, adding a \ as necessary.
223 CPath& addPath(const char *s) {
224 _ASSERT(s != NULL);
225 if (s != NULL && s[0] != 0) {
226 int n = length();
227 if (n > 0 && s[0] != '\\' && mStr[n-1] != '\\') add("\\");
228 add(s);
229 }
230 return *this;
231 }
232
233 // Returns true if file exist and is not a directory.
234 // There's no garantee we have rights to access it.
235 bool fileExists() const {
236 if (mStr == NULL) return false;
237 DWORD attribs = GetFileAttributesA(mStr);
238 return attribs != INVALID_FILE_ATTRIBUTES &&
239 !(attribs & FILE_ATTRIBUTE_DIRECTORY);
240 }
241
242 // Returns true if file exist and is a directory.
243 // There's no garantee we have rights to access it.
244 bool dirExists() const {
245 if (mStr == NULL) return false;
246 DWORD attribs = GetFileAttributesA(mStr);
247 return attribs != INVALID_FILE_ATTRIBUTES &&
248 (attribs & FILE_ATTRIBUTE_DIRECTORY) != 0;
249 }
250
251 // Returns a copy of the directory portion of the path, if any
252 CPath dirName() const {
253 CPath result;
254 if (mStr != NULL) {
255 char *pos = strrchr(mStr, '\\');
256 if (pos != NULL) {
257 result.set(mStr, pos - mStr);
258 }
259 }
260 return result;
261 }
262
263 // Returns a pointer to the baseName part of the path.
264 // It becomes invalid if the path changes.
265 const char * baseName() const {
266 if (mStr != NULL) {
267 char *pos = strrchr(mStr, '\\');
268 if (pos != NULL) {
269 return pos + 1;
270 }
271 }
272 return NULL;
273 }
274
275 // If the path ends with the given searchName, replace in-place by the new name
276 void replaceName(const char *searchName, const char* newName) {
277 if (mStr == NULL) return;
278 int n = length();
279 int sn = strlen(searchName);
280 if (n < sn) return;
281 // if mStr ends with searchName
282 if (strcmp(mStr + n - sn, searchName) == 0) {
283 int sn2 = strlen(newName);
284 if (sn2 > sn) {
285 mStr = (char *)realloc((void *)mStr, n + sn2 - sn + 1);
286 }
287 strcpy(mStr + n - sn, newName);
288 mStr[n + sn2 - sn] = 0;
289 }
290 }
291};
292
293// Displays a message in an ok+info dialog box.
294void msgBox(const char* text, ...);
295
296// Displays GetLastError prefixed with a description in an error dialog box
297void displayLastError(const char *description, ...);
298
299// Executes the command line. Does not wait for the program to finish.
300// The return code is from CreateProcess (0 means failure), not the running app.
301int execNoWait(const char *app, const char *params, const char *workDir);
302
303// Executes command, waits for completion and returns exit code.
304// As indicated in MSDN for CreateProcess, callers should double-quote the program name
305// e.g. cmd="\"c:\program files\myapp.exe\" arg1 arg2";
306int execWait(const char *cmd);
307
308bool getModuleDir(CPath *outDir);
309
310// Disables the FS redirection done by WOW64.
311// Because this runs as a 32-bit app, Windows automagically remaps some
312// folder under the hood (e.g. "Programs Files(x86)" is mapped as "Program Files").
313// This prevents the app from correctly searching for java.exe in these folders.
314// The registry is also remapped.
315PVOID disableWow64FsRedirection();
316
317// Reverts the redirection disabled in disableWow64FsRedirection.
318void revertWow64FsRedirection(PVOID oldWow64Value);
319
320#endif /* _WIN32 */
321#endif /* _H_UTILS */