mirror of https://github.com/mpv-player/mpv
bstr.[ch], path.[ch]: add string and path handling functions
Add some new string and path handling functions to be used in following commits. Use new path handling functions to simplify find_files().
This commit is contained in:
parent
e8af22db81
commit
962eec0440
91
bstr.c
91
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;
|
||||
}
|
||||
|
|
36
bstr.h
36
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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
43
path.c
43
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));
|
||||
}
|
||||
|
|
18
path.h
18
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 */
|
||||
|
|
Loading…
Reference in New Issue