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:
Uoti Urpala 2011-02-23 16:18:09 +02:00
parent e8af22db81
commit 962eec0440
5 changed files with 190 additions and 32 deletions

91
bstr.c
View File

@ -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
View File

@ -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 */

View File

@ -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
View File

@ -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
View File

@ -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 */