Much less re-compiles.
Also eliminate wide-spread use of PATH_MAX.
#ifndef _OS_HPP_
#define _OS_HPP_
-#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
-#include <vector>
-
#ifdef _WIN32
#ifndef snprintf
#define snprintf _snprintf
#ifndef vsnprintf
#define vsnprintf _vsnprintf
#endif
-#define PATH_SEP '\\'
-#else /* !_WIN32 */
-#define PATH_SEP '/'
#endif /* !_WIN32 */
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-
namespace os {
void acquireMutex(void);
void releaseMutex(void);
-
-class Path {
-protected:
- typedef std::vector<char> Buffer;
- Buffer buffer;
-
- Buffer::iterator rfind(char c) {
- Buffer::iterator it = buffer.end();
- while (it != buffer.begin()) {
- --it;
- if (*it == c) {
- return it;
- }
- }
- return buffer.end();
- }
-
-public:
- Path() {
- buffer.push_back(0);
- }
-
- Path(const char *s) :
- buffer(s, s + strlen(s) + 1)
- {}
-
- template <class InputIterator>
- Path(InputIterator first, InputIterator last) :
- buffer(first, last)
- {
- buffer.push_back(0);
- }
-
- char *buf(size_t size) {
- buffer.resize(size);
- return &buffer[0];
- }
-
- void trimDirectory(void) {
- Buffer::iterator sep = rfind(PATH_SEP);
- if (sep != buffer.end()) {
- buffer.erase(buffer.begin(), sep + 1);
- }
- }
-
- void trimExtension(void) {
- Buffer::iterator dot = rfind('.');
- if (dot != buffer.end()) {
- buffer.erase(dot, buffer.end());
- }
- }
-
- size_t length(void) const {
- size_t size = buffer.size();
- assert(size > 0);
- assert(buffer[size - 1] == 0);
- return size - 1;
- }
-
- void truncate(size_t length) {
- assert(length < buffer.size());
- buffer[length] = 0;
- buffer.resize(length + 1);
- }
-
- void truncate(void) {
- truncate(strlen(str()));
- }
-
- const char *str(void) const {
- assert(buffer[buffer.size() - 1] == 0);
- return &buffer[0];
- }
-
- void join(const Path & other) {
- size_t len = length();
- if (len > 0 && buffer[len - 1] != PATH_SEP) {
- buffer.insert(buffer.begin() + len++, PATH_SEP);
- }
- buffer.insert(buffer.begin() + len, other.buffer.begin(), other.buffer.end() - 1);
- }
-
-};
-
-Path getProcessName();
-Path getCurrentDir();
-
void log(const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 1, 2)))
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Path manipulation.
+ */
+
+#ifndef _OS_PATH_HPP_
+#define _OS_PATH_HPP_
+
+
+#include <assert.h>
+
+#include <vector>
+
+#include "os.hpp"
+
+
+#ifdef _WIN32
+#define OS_DIR_SEP '\\'
+#else /* !_WIN32 */
+#define OS_DIR_SEP '/'
+#endif /* !_WIN32 */
+
+
+namespace os {
+
+
+class Path {
+protected:
+ typedef std::vector<char> Buffer;
+ Buffer buffer;
+
+ Buffer::iterator rfind(char c) {
+ Buffer::iterator it = buffer.end();
+ while (it != buffer.begin()) {
+ --it;
+ if (*it == c) {
+ return it;
+ }
+ }
+ return buffer.end();
+ }
+
+ Path(size_t size) :
+ buffer(size) {
+ }
+
+ char *buf(void) {
+ return &buffer[0];
+ }
+
+public:
+ Path() {
+ buffer.push_back(0);
+ }
+
+ Path(const char *s) :
+ buffer(s, s + strlen(s) + 1)
+ {}
+
+ template <class InputIterator>
+ Path(InputIterator first, InputIterator last) :
+ buffer(first, last)
+ {
+ buffer.push_back(0);
+ }
+
+ char *buf(size_t size) {
+ buffer.resize(size);
+ return &buffer[0];
+ }
+
+ void trimDirectory(void) {
+ Buffer::iterator sep = rfind(OS_DIR_SEP);
+ if (sep != buffer.end()) {
+ buffer.erase(buffer.begin(), sep + 1);
+ }
+ }
+
+ void trimExtension(void) {
+ Buffer::iterator dot = rfind('.');
+ if (dot != buffer.end()) {
+ buffer.erase(dot, buffer.end());
+ }
+ }
+
+ size_t length(void) const {
+ size_t size = buffer.size();
+ assert(size > 0);
+ assert(buffer[size - 1] == 0);
+ return size - 1;
+ }
+
+ void truncate(size_t length) {
+ assert(length < buffer.size());
+ buffer[length] = 0;
+ buffer.resize(length + 1);
+ }
+
+ void truncate(void) {
+ truncate(strlen(str()));
+ }
+
+ const char *str(void) const {
+ assert(buffer[buffer.size() - 1] == 0);
+ return &buffer[0];
+ }
+
+ operator const char *(void) const {
+ return str();
+ }
+
+ void join(const Path & other) {
+ size_t len = length();
+ if (len > 0 && buffer[len - 1] != OS_DIR_SEP) {
+ buffer.insert(buffer.begin() + len++, OS_DIR_SEP);
+ }
+ buffer.insert(buffer.begin() + len, other.buffer.begin(), other.buffer.end() - 1);
+ }
+
+ /**
+ * Create a path from a printf-like format string
+ */
+ static Path
+ format(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ {
+
+ va_list args;
+
+ va_start(args, format);
+
+ int length;
+ va_list args_copy;
+ va_copy(args_copy, args);
+#ifdef _MSC_VER
+ /* We need to use _vcsprintf to calculate the length as vsnprintf returns -1
+ * if the number of characters to write is greater than count.
+ */
+ length = _vscprintf(format, args_copy);
+#else
+ char dummy;
+ length = vsnprintf(&dummy, sizeof dummy, format, args_copy);
+#endif
+ va_end(args_copy);
+
+ assert(length >= 0);
+ size_t size = length + 1;
+
+ Path path(size);
+
+ va_start(args, format);
+ vsnprintf(path.buf(), size, format, args);
+ va_end(args);
+
+ return path;
+ }
+};
+
+
+Path getProcessName();
+Path getCurrentDir();
+
+
+} /* namespace os */
+
+#endif /* _OS_PATH_HPP_ */
#include <fcntl.h>
#include <signal.h>
+#if defined(__linux__)
+#include <linux/limits.h> // PATH_MAX
+#endif
+
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
+#ifndef PATH_MAX
+#warning PATH_MAX undefined
+#define PATH_MAX 4096
+#endif
+
#include "os.hpp"
+#include "os_path.hpp"
namespace os {
getProcessName(void)
{
Path path;
-
- char *szProcessPath = path.buf(PATH_MAX);
+ size_t size = PATH_MAX;
+ char *buf = path.buf(size);
// http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
#ifdef __APPLE__
- uint32_t len = PATH_MAX;
- if (_NSGetExecutablePath(szProcessPath, &len) != 0) {
- *szProcessPath = 0;
+ uint32_t len = size;
+ if (_NSGetExecutablePath(buf, &len) != 0) {
+ *buf = 0;
return path;
}
#else
ssize_t len;
- len = readlink("/proc/self/exe", szProcessPath, PATH_MAX - 1);
+ len = readlink("/proc/self/exe", buf, size - 1);
if (len == -1) {
// /proc/self/exe is not available on setuid processes, so fallback to
// /proc/self/cmdline.
int fd = open("/proc/self/cmdline", O_RDONLY);
if (fd >= 0) {
- len = read(fd, szProcessPath, PATH_MAX - 1);
+ len = read(fd, buf, size - 1);
close(fd);
}
}
if (len <= 0) {
- snprintf(szProcessPath, PATH_MAX, "%i", (int)getpid());
+ snprintf(buf, size, "%i", (int)getpid());
return path;
}
#endif
{
Path path;
size_t size = PATH_MAX;
- char *str = path.buf(size);
- getcwd(str, size);
- str[size - 1] = 0;
+ char *buf = path.buf(size);
+
+ getcwd(buf, size);
+ buf[size - 1] = 0;
+
path.truncate();
return path;
}
#include <stdio.h>
#include "os.hpp"
+#include "os_path.hpp"
namespace os {
getProcessName(void)
{
Path path;
+ size_t size = MAX_PATH;
+ char *buf = path.buf(size);
- char *szProcessPath = path.buf(PATH_MAX);
-
- DWORD nWritten = GetModuleFileNameA(NULL, szProcessPath, PATH_MAX);
+ DWORD nWritten = GetModuleFileNameA(NULL, buf, size);
+ (void)nWritten;
path.truncate();
return path;
}
-bool
-getCurrentDir(char *str, size_t size)
+Path
+getCurrentDir(void)
{
- DWORD ret;
- ret = GetCurrentDirectoryA(size, str);
- str[size - 1] = 0;
- return ret == 0 ? false : true;
+ Path path;
+ size_t size = MAX_PATH;
+ char *buf = path.buf(size);
+
+ DWORD ret = GetCurrentDirectoryA(size, buf);
+ (void)ret;
+
+ buf[size - 1] = 0;
+ path.truncate();
+
+ return path;
}
void
#include <string.h>
#include "os.hpp"
+#include "os_path.hpp"
#include "trace_file.hpp"
#include "trace_writer.hpp"
#include "trace_format.hpp"
LocalWriter::open(void) {
os::Path szFileName;
- char *lpFileName;
+ const char *lpFileName;
- lpFileName = const_cast<char *>(getenv("TRACE_FILE"));
+ lpFileName = getenv("TRACE_FILE");
if (!lpFileName) {
- lpFileName = szFileName.buf(PATH_MAX);
static unsigned dwCounter = 0;
os::Path process = os::getProcessName();
FILE *file;
if (dwCounter)
- snprintf(lpFileName, PATH_MAX, "%s.%u.trace", prefix.str(), dwCounter);
+ szFileName = os::Path::format("%s.%u.trace", prefix.str(), dwCounter);
else
- snprintf(lpFileName, PATH_MAX, "%s.trace", prefix.str());
+ szFileName = os::Path::format("%s.trace", prefix.str());
file = fopen(lpFileName, "rb");
if (file == NULL)
++dwCounter;
}
+
+ lpFileName = szFileName;
}
os::log("apitrace: tracing to %s\n", lpFileName);
#include <string.h>
+#include "os_path.hpp"
#include "image.hpp"
#include "retrace.hpp"
#include "glproc.hpp"
image::Image *ref = NULL;
if (compare_prefix) {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", compare_prefix, call_no);
+ os::Path filename = os::Path::format("%s%010u.png", compare_prefix, call_no);
ref = image::readPNG(filename);
if (!ref) {
return;
snprintf(comment, sizeof comment, "%u", call_no);
src->writePNM(std::cout, comment);
} else {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no);
+ os::Path filename = os::Path::format("%s%010u.png", snapshot_prefix, call_no);
if (src->writePNG(filename) && retrace::verbosity >= 0) {
std::cout << "Wrote " << filename << "\n";
}
#include <assert.h>
#include <stdint.h>
+#include "os_path.hpp"
#include "image.hpp"
#include "glproc.hpp"
#include "glsize.hpp"
if (snapshot_prefix) {
image::Image *src = getDrawableImage();
if (src) {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no);
+ os::Path filename = os::Path::format("%s%010u.png", snapshot_prefix, call_no);
if (src->writePNG(filename)) {
- os::log("apitrace: wrote %s\n", filename);
+ os::log("apitrace: wrote %s\n", filename.str());
}
delete src;