summaryrefslogtreecommitdiff
path: root/goo
diff options
context:
space:
mode:
authorGreg Knight <lyngvi@gmail.com>2019-02-10 10:28:26 +0100
committerAlbert Astals Cid <aacid@kde.org>2019-02-10 15:30:31 +0100
commit2ba81611e9ccdcb49275ee247308bd0dcba3e64d (patch)
tree2e88b5613a44dca034c32baebff3e676574331c3 /goo
parent7f4da59665969f624c18a1ba3e1f1ac1ca3478b1 (diff)
Introduce gbasename
Diffstat (limited to 'goo')
-rw-r--r--goo/gbasename.cc51
-rw-r--r--goo/gbasename.h22
2 files changed, 73 insertions, 0 deletions
diff --git a/goo/gbasename.cc b/goo/gbasename.cc
new file mode 100644
index 00000000..dd4607b4
--- /dev/null
+++ b/goo/gbasename.cc
@@ -0,0 +1,51 @@
+//========================================================================
+//
+// gbasename.cc
+//
+// Wrapper for libgen's basename() call which returns a std::string.
+// This is a convenience method working around questionable behavior
+// in the copy of basename() provided by libgen.h.
+//
+// According to man 3 basename:
+//
+// Both dirname() and basename() may modify the contents of path, so it
+// may be desirable to pass a copy when calling one of these functions.
+//
+// ...
+//
+// These functions may return pointers to statically allocated memory
+// which may be overwritten by subsequent calls. Alternatively, they
+// may return a pointer to some part of path, so that the string
+// referred to by path should not be modified or freed until the pointer
+// returned by the function is no longer required.
+//
+// Because basename can modify filename (for some reason), we have to
+// duplicate our input into a mutable buffer before we can call it.
+// The return value might be part of this mutable temporary, but not
+// generally the front, so 'char *' cannot be used as our return value.
+// The return value might also be a statically allocated string,
+// rendering basename (and thus gbasename) non-thread-safe. Because
+// we don't know how basename()'s return value is lifecycled, we need
+// to duplicate it again into something whose lifecycle we can predict.
+//
+// This is how a method that should amount to finding the last slash
+// in a string ends up requiring two memory allocations while managing
+// not to be thread-safe. In a way, it's kind of impressive.
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2018 Greg Knight <lyngvi@gmail.com>
+//
+//========================================================================
+
+#include "gbasename.h"
+#include <libgen.h>
+#include <string.h>
+
+std::string gbasename(const char* filename)
+{
+ char* mutabl = strdup(filename);
+ std::string retu = basename(mutabl);
+ free(mutabl);
+ return retu;
+}
diff --git a/goo/gbasename.h b/goo/gbasename.h
new file mode 100644
index 00000000..3c5e0065
--- /dev/null
+++ b/goo/gbasename.h
@@ -0,0 +1,22 @@
+//========================================================================
+//
+// gbasename.h
+//
+// Wrapper for libgen's basename() call which returns a std::string.
+// This is a convenience method working around questionable behavior
+// in the copy of basename() provided by libgen.h.
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2018 Greg Knight <lyngvi@gmail.com>
+//
+//========================================================================
+
+#ifndef GBASENAME_H
+#define GBASENAME_H
+
+#include <string>
+
+std::string gbasename(const char* input);
+
+#endif // ndef GBASENAME_H