summaryrefslogtreecommitdiffstats
path: root/m_property.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-09-23 23:00:54 +0200
committerwm4 <wm4@nowhere>2012-10-12 10:10:32 +0200
commit32c5a87a0131e33e592a2986a8d2d98f2ca963b9 (patch)
treed9917a9fe65b691c2472cf557b1602a8234855b1 /m_property.c
parentdf2b0f99485e065224af89b910370c394d0ef8d0 (diff)
downloadmpv-32c5a87a0131e33e592a2986a8d2d98f2ca963b9.tar.bz2
mpv-32c5a87a0131e33e592a2986a8d2d98f2ca963b9.tar.xz
commands: change property expansion format string
This affects property format strings like they are used in the "show_text" input command, for --playing-msg, and other places. To quote the documentation comment on m_properties_expand_string(): ${NAME} is expanded to the value of property NAME. If NAME starts with '=', use the raw value of the property. ${NAME:STR} expands to the property, or STR if the property is not available. ${?NAME:STR} expands to STR if the property is available. ${!NAME:STR} expands to STR if the property is not available. STR is recursively expanded using the same rules. "$$" can be used to escape "$", and "$}" to escape "}". "$>" disables parsing of "$" for the rest of the string. Most importantly, "?(property:str)" becomes "${?property:str}". Make the simple fallback case easier, e.g. "${property:fallback}" instead of "${property}?(!property:fallback)". Add the ability to escape the format meta characters. "$" is used for escaping, because escaping with "\" is taken by the commands parser in the layer below. "$>" can be used to disable interpretation of format strings (of course escapes by the commands parser can't be canceled). By default, properties which are unavailable or don't exist are turned into a string signaling the status (e.g. "(unavailable)"), instead of an empty string. If an empty string is desired, this has to be done explicitly: "${property:}" (the fallback part is an empty string). Raw properties still return an empty string on error. m_properties_expand_string() now returns a talloc'ed pointer, instead of a malloc'ed one.
Diffstat (limited to 'm_property.c')
-rw-r--r--m_property.c137
1 files changed, 80 insertions, 57 deletions
diff --git a/m_property.c b/m_property.c
index 68be17c974..acdf91200c 100644
--- a/m_property.c
+++ b/m_property.c
@@ -27,6 +27,8 @@
#include <inttypes.h>
#include <assert.h>
+#include <libavutil/common.h>
+
#include "talloc.h"
#include "m_option.h"
#include "m_property.h"
@@ -140,73 +142,94 @@ int m_property_do(const m_option_t *prop_list, const char *name,
}
}
-char *m_properties_expand_string(const m_option_t *prop_list, char *str,
+static int m_property_do_bstr(const m_option_t *prop_list, bstr name,
+ int action, void *arg, void *ctx)
+{
+ char name0[64];
+ if (name.len >= sizeof(name0))
+ return M_PROPERTY_UNKNOWN;
+ snprintf(name0, sizeof(name0), "%.*s", BSTR_P(name));
+ return m_property_do(prop_list, name0, action, arg, ctx);
+}
+
+static void append_str(char **s, int *len, bstr append)
+{
+ MP_TARRAY_GROW(NULL, *s, *len + append.len);
+ memcpy(*s + *len, append.start, append.len);
+ *len = *len + append.len;
+}
+
+char *m_properties_expand_string(const m_option_t *prop_list, char *str0,
void *ctx)
{
- int l, fr = 0, pos = 0, size = strlen(str) + 512;
- char *p = NULL, *e, *ret = malloc(size);
- int skip = 0, lvl = 0, skip_lvl = 0;
+ char *ret = NULL;
+ int ret_len = 0;
+ bool skip = false;
+ int level = 0, skip_level = 0;
+ bstr str = bstr0(str0);
+
+ while (str.len) {
+ if (level > 0 && bstr_eatstart0(&str, "}")) {
+ if (skip && level <= skip_level)
+ skip = false;
+ level--;
+ } else if (bstr_startswith0(str, "${") && bstr_find0(str, "}") >= 0) {
+ str = bstr_cut(str, 2);
+ level++;
+
+ // Assume ":" and "}" can't be part of the property name
+ // => if ":" comes before "}", it must be for the fallback
+ int term_pos = bstrcspn(str, ":}");
+ bstr name = bstr_splice(str, 0, term_pos < 0 ? str.len : term_pos);
+ str = bstr_cut(str, term_pos);
+ bool have_fallback = bstr_eatstart0(&str, ":");
- while (str[0]) {
- if (lvl > 0 && str[0] == ')') {
- if (skip && lvl <= skip_lvl)
- skip = 0;
- lvl--, str++, l = 0;
- } else if (str[0] == '$' && str[1] == '{'
- && (e = strchr(str + 2, '}'))) {
- str += 2;
- int method = M_PROPERTY_PRINT;
- if (str[0] == '=') {
- str += 1;
- method = M_PROPERTY_GET_STRING;
- }
- int pl = e - str;
- char pname[pl + 1];
- memcpy(pname, str, pl);
- pname[pl] = 0;
- if (m_property_do(prop_list, pname, method, &p, ctx) >= 0 && p)
- l = strlen(p), fr = 1;
- else
- l = 0;
- str = e + 1;
- } else if (str[0] == '?' && str[1] == '('
- && (e = strchr(str + 2, ':'))) {
- lvl++;
if (!skip) {
- int is_not = str[2] == '!';
- int pl = e - str - (is_not ? 3 : 2);
- char pname[pl + 1];
- memcpy(pname, str + (is_not ? 3 : 2), pl);
- pname[pl] = 0;
- struct m_option opt = {0};
- union m_option_value val = {0};
- if (m_property_do(prop_list, pname, M_PROPERTY_GET_TYPE, &opt, ctx) <= 0 &&
- m_property_do(prop_list, pname, M_PROPERTY_GET, &val, ctx) <= 0)
- {
- if (!is_not)
- skip = 1, skip_lvl = lvl;
- m_option_free(&opt, &val);
- } else if (is_not)
- skip = 1, skip_lvl = lvl;
+ bool cond_yes = bstr_eatstart0(&name, "?");
+ bool cond_no = !cond_yes && bstr_eatstart0(&name, "!");
+ bool raw = bstr_eatstart0(&name, "=");
+ int method = (raw || cond_yes || cond_no)
+ ? M_PROPERTY_GET_STRING : M_PROPERTY_PRINT;
+
+ char *s = NULL;
+ int r = m_property_do_bstr(prop_list, name, method, &s, ctx);
+ if (cond_yes || cond_no) {
+ skip = (!!s != cond_yes);
+ } else {
+ skip = !!s;
+ char *append = s;
+ if (!s && !have_fallback && !raw) {
+ append = r == M_PROPERTY_UNAVAILABLE
+ ? "(unavailable)" : "(error)";
+ }
+ append_str(&ret, &ret_len, bstr0(append));
+ }
+ talloc_free(s);
+ if (skip)
+ skip_level = level;
}
- str = e + 1, l = 0;
- } else
- p = str, l = 1, str++;
+ } else if (level == 0 && bstr_eatstart0(&str, "$>")) {
+ append_str(&ret, &ret_len, str);
+ break;
+ } else {
+ char c;
- if (skip || l <= 0)
- continue;
+ // Other combinations, e.g. "$x", are added verbatim
+ if (bstr_eatstart0(&str, "$$")) {
+ c = '$';
+ } else if (bstr_eatstart0(&str, "$}")) {
+ c = '}';
+ } else {
+ c = str.start[0];
+ str = bstr_cut(str, 1);
+ }
- if (pos + l + 1 > size) {
- size = pos + l + 512;
- ret = realloc(ret, size);
+ if (!skip)
+ MP_TARRAY_APPEND(NULL, ret, ret_len, c);
}
- memcpy(ret + pos, p, l);
- pos += l;
- if (fr)
- talloc_free(p), fr = 0;
}
- ret[pos] = 0;
+ MP_TARRAY_APPEND(NULL, ret, ret_len, '\0');
return ret;
}