]> git.notmuchmail.org Git - apitrace/blobdiff - common/os_path.hpp
Add os::Path.trimFilename function.
[apitrace] / common / os_path.hpp
index 33f9f33f5af2e0edde6b8539646c9875532cd1ab..5058651d8231b7ec0a286fc0859574827dded961 100644 (file)
 
 
 #include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#ifdef __MINGW32__
+// Some versions of MinGW are missing _vscprintf's declaration, although they
+// still provide the symbol in the import library.
+extern "C" _CRTIMP int _vscprintf(const char *format, va_list argptr);
+#endif
+
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy(dest, src) __va_copy((dest), (src))
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
 
 #include <vector>
 
@@ -53,8 +70,23 @@ protected:
     typedef std::vector<char> Buffer;
     Buffer buffer;
 
+    Buffer::iterator find(char c) {
+        Buffer::iterator it = buffer.begin();
+        /* Why do we make these functions fail on empty paths? */
+        assert(it != buffer.end());
+        while (it != buffer.end()) {
+            if (*it == c) {
+                return it;
+            }
+            ++it;
+        }
+        return buffer.end();
+    }
+
     Buffer::iterator rfind(char c) {
         Buffer::iterator it = buffer.end();
+        assert(it != buffer.begin());
+        --it; // skip null
         while (it != buffer.begin()) {
             --it;
             if (*it == c) {
@@ -100,10 +132,35 @@ public:
         }
     }
 
+    /* Trim filename component (leaving containing directory).
+     *
+     * This function removes everything after the final path
+     * separator, as well as that separator itself if it is not the
+     * only remaining separator.
+     *
+     * Some specific consequences of the above:
+     *
+     * 1. A path with no separator at all is unchanged.
+     * 2. A path with a trailing separator has only that separator removed
+     * 3. A path of just the root directory is unchaged.
+     */
+    void trimFilename(void) {
+        Buffer::iterator first = find(OS_DIR_SEP);
+        Buffer::iterator last = rfind(OS_DIR_SEP);
+        if (last == buffer.end()) {
+            return;
+        }
+        if (last == first) {
+            buffer.erase(first + 1, buffer.end() - 1);
+        } else {
+            buffer.erase(last, buffer.end() - 1);
+        }
+    }
+
     void trimExtension(void) {
         Buffer::iterator dot = rfind('.');
         if (dot != buffer.end()) {
-            buffer.erase(dot, buffer.end());
+            buffer.erase(dot, buffer.end() - 1);
         }
     }
 
@@ -158,7 +215,7 @@ public:
         int length;
         va_list args_copy;
         va_copy(args_copy, args);
-#ifdef _MSC_VER
+#ifdef _WIN32
         /* We need to use _vcsprintf to calculate the length as vsnprintf returns -1
          * if the number of characters to write is greater than count.
          */