summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bstr.c91
-rw-r--r--bstr.h36
-rw-r--r--osdep/findfiles.c34
-rw-r--r--path.c43
-rw-r--r--path.h18
5 files changed, 190 insertions, 32 deletions
diff --git a/bstr.c b/bstr.c
index 3cc3928086..d86b488912 100644
--- a/bstr.c
+++ b/bstr.c
@@ -18,6 +18,10 @@
#include <string.h>
#include <libavutil/avutil.h>
+#include <assert.h>
+
+#include "talloc.h"
+
#include "bstr.h"
int bstrcmp(struct bstr str1, struct bstr str2)
@@ -49,3 +53,90 @@ int bstrcasecmp(struct bstr str1, struct bstr str2)
}
return ret;
}
+
+int bstrchr(struct bstr str, int c)
+{
+ for (int i = 0; i < str.len; i++)
+ if (str.start[i] == c)
+ return i;
+ return -1;
+}
+
+struct bstr bstr_strip(struct bstr str)
+{
+ while (str.len && isspace(*str.start)) {
+ str.start++;
+ str.len--;
+ }
+ while (str.len && isspace(str.start[str.len - 1]))
+ str.len--;
+ return str;
+}
+
+struct bstr bstr_split(struct bstr str, char *sep, struct bstr *rest)
+{
+ int start, end;
+ for (start = 0; start < str.len; start++)
+ if (!strchr(sep, str.start[start]))
+ break;
+ for (end = start; end < str.len; end++)
+ if (strchr(sep, str.start[end]))
+ break;
+ if (rest) {
+ *rest = bstr_cut(str, end);
+ }
+ str.start += start;
+ str.len = end - start;
+ return str;
+}
+
+
+struct bstr bstr_splice(struct bstr str, int start, int end)
+{
+ if (start < 0)
+ start += str.len;
+ if (end < 0)
+ end += str.len;
+ end = FFMIN(end, str.len);
+ start = FFMAX(start, 0);
+ if (start >= end)
+ return (struct bstr){NULL, 0};
+ str.start += start;
+ str.len = end - start;
+ return str;
+}
+
+long long bstrtoll(struct bstr str, struct bstr *rest, int base)
+{
+ char buf[51];
+ int len = FFMIN(str.len, 50);
+ memcpy(buf, str.start, len);
+ buf[len] = 0;
+ char *endptr;
+ long long r = strtoll(buf, &endptr, base);
+ if (rest)
+ *rest = bstr_cut(str, endptr - buf);
+ return r;
+}
+
+struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str)
+{
+ if (str.len == 0)
+ return NULL;
+ int count = 0;
+ for (int i = 0; i < str.len; i++)
+ if (str.start[i] == '\n')
+ count++;
+ if (str.start[str.len - 1] != '\n')
+ count++;
+ struct bstr *r = talloc_array_ptrtype(talloc_ctx, r, count);
+ unsigned char *p = str.start;
+ for (int i = 0; i < count - 1; i++) {
+ r[i].start = p;
+ while (*p++ != '\n');
+ r[i].len = p - r[i].start;
+ }
+ r[count - 1].start = p;
+ r[count - 1].len = str.start + str.len - p;
+ return r;
+}
diff --git a/bstr.h b/bstr.h
index 459bf70bef..33a47c0abc 100644
--- a/bstr.h
+++ b/bstr.h
@@ -22,18 +22,50 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
+#include <stdbool.h>
+#include "talloc.h"
+
+/* NOTE: 'len' is size_t, but most string-handling functions below assume
+ * that input size has been sanity checked and len fits in an int.
+ */
struct bstr {
- const uint8_t *start;
+ unsigned char *start;
size_t len;
};
int bstrcmp(struct bstr str1, struct bstr str2);
int bstrcasecmp(struct bstr str1, struct bstr str2);
+int bstrchr(struct bstr str, int c);
+struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str);
+struct bstr bstr_strip(struct bstr str);
+struct bstr bstr_split(struct bstr str, char *sep, struct bstr *rest);
+struct bstr bstr_splice(struct bstr str, int start, int end);
+long long bstrtoll(struct bstr str, struct bstr *rest, int base);
+
+static inline struct bstr bstr_cut(struct bstr str, int n)
+{
+ return (struct bstr){str.start + n, str.len - n};
+}
+
+static inline bool bstr_startswith(struct bstr str, struct bstr prefix)
+{
+ if (str.len < prefix.len)
+ return false;
+ return !memcmp(str.start, prefix.start, prefix.len);
+}
+
+static inline char *bstrdup0(void *talloc_ctx, struct bstr str)
+{
+ // cast is live555 C++ compilation workaround
+ return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
+}
// Create bstr compound literal from null-terminated string
-#define BSTR(s) (struct bstr){(s), (s) ? strlen(s) : 0}
+#define BSTR(s) (struct bstr){(char *)(s), (s) ? strlen(s) : 0}
// create a pair (not single value!) for "%.*s" printf syntax
#define BSTR_P(bstr) (int)((bstr).len), (bstr).start
+#define WHITESPACE " \f\n\r\t\v"
+
#endif /* MPLAYER_BSTR_H */
diff --git a/osdep/findfiles.c b/osdep/findfiles.c
index 879f6d5c98..e35174dfd4 100644
--- a/osdep/findfiles.c
+++ b/osdep/findfiles.c
@@ -22,38 +22,18 @@
#include <assert.h>
#include "talloc.h"
-
-#if defined(__MINGW32__) || defined(__CYGWIN__)
-static const char dir_separators[] = "/\\:";
-#else
-static const char dir_separators[] = "/";
-#endif
+#include "path.h"
+#include "bstr.h"
char **find_files(const char *original_file, const char *suffix,
int *num_results_ptr)
{
void *tmpmem = talloc_new(NULL);
- char *fname = talloc_strdup(tmpmem, original_file);
- char *basename = NULL;
- char *next = fname;
- while (1) {
- next = strpbrk(next, dir_separators);
- if (!next)
- break;
- basename = next++;
- }
- char *directory;
- if (basename) {
- directory = fname;
- *basename++ = 0;
- } else {
- directory = ".";
- basename = fname;
- }
-
-
+ char *basename = mp_basename(original_file);
+ struct bstr directory = mp_dirname(original_file);
char **results = talloc_size(NULL, 0);
- DIR *dp = opendir(directory);
+ char *dir_zero = bstrdup0(tmpmem, directory);
+ DIR *dp = opendir(dir_zero);
struct dirent *ep;
char ***names_by_matchlen = talloc_array(tmpmem, char **,
strlen(basename) + 1);
@@ -68,7 +48,7 @@ char **find_files(const char *original_file, const char *suffix,
if (!strcmp(ep->d_name, basename))
continue;
- char *name = talloc_asprintf(results, "%s/%s", directory, ep->d_name);
+ char *name = mp_path_join(results, directory, BSTR(ep->d_name));
char *s1 = ep->d_name;
char *s2 = basename;
int matchlen = 0;
diff --git a/path.c b/path.c
index 7f4ce88f17..f97e8a6c3a 100644
--- a/path.c
+++ b/path.c
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include "config.h"
#include "mp_msg.h"
#include "path.h"
@@ -42,6 +43,8 @@
#include <sys/cygwin.h>
#endif
+#include "talloc.h"
+
#include "osdep/osdep.h"
char *get_path(const char *filename){
@@ -194,7 +197,7 @@ void set_codec_path(const char *path)
needs_free = 1;
}
-const char *mp_basename(const char *path)
+char *mp_basename(const char *path)
{
char *s;
@@ -207,5 +210,41 @@ const char *mp_basename(const char *path)
path = s + 1;
#endif
s = strrchr(path, '/');
- return s ? s + 1 : path;
+ return s ? s + 1 : (char *)path;
+}
+
+struct bstr mp_dirname(const char *path)
+{
+ struct bstr ret = {(uint8_t *)path, mp_basename(path) - path};
+ if (ret.len == 0)
+ return BSTR(".");
+ return ret;
+}
+
+char *mp_path_join(void *talloc_ctx, struct bstr p1, struct bstr p2)
+{
+ if (p1.len == 0)
+ return bstrdup0(talloc_ctx, p2);
+ if (p2.len == 0)
+ return bstrdup0(talloc_ctx, p1);
+
+#if HAVE_DOS_PATHS
+ if (p2.len >= 2 && p2.start[1] == ':'
+ || p2.start[0] == '\\' || p2.start[0] == '/')
+#else
+ if (p2.start[0] == '/')
+#endif
+ return bstrdup0(talloc_ctx, p2); // absolute path
+
+ bool have_separator;
+ int endchar1 = p1.start[p1.len - 1];
+#if HAVE_DOS_PATHS
+ have_separator = endchar1 == '/' || endchar1 == '\\'
+ || p1.len == 2 && endchar1 == ':'; // "X:" only
+#else
+ have_separator = endchar1 == '/';
+#endif
+
+ return talloc_asprintf(talloc_ctx, "%.*s%s%.*s", BSTR_P(p1),
+ have_separator ? "" : "/", BSTR_P(p2));
}
diff --git a/path.h b/path.h
index 349f55e3cc..ffa052d680 100644
--- a/path.h
+++ b/path.h
@@ -21,11 +21,27 @@
#ifndef MPLAYER_PATH_H
#define MPLAYER_PATH_H
+#include "bstr.h"
+
extern char *codec_path;
char *get_path(const char *filename);
void set_path_env(void);
void set_codec_path(const char *path);
-const char *mp_basename(const char *path);
+
+// Return pointer to filename part of path
+
+char *mp_basename(const char *path);
+
+/* Return struct bstr referencing directory part of path, or if that
+ * would be empty, ".".
+ */
+struct bstr mp_dirname(const char *path);
+
+/* Join two path components and return a newly allocated string
+ * for the result. '/' is inserted between the components if needed.
+ * If p2 is an absolute path then the value of p1 is ignored.
+ */
+char *mp_path_join(void *talloc_ctx, struct bstr p1, struct bstr p2);
#endif /* MPLAYER_PATH_H */