summaryrefslogtreecommitdiffstats
path: root/libass/ass_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libass/ass_utils.c')
-rw-r--r--libass/ass_utils.c123
1 files changed, 95 insertions, 28 deletions
diff --git a/libass/ass_utils.c b/libass/ass_utils.c
index b1c736c..a6a063b 100644
--- a/libass/ass_utils.c
+++ b/libass/ass_utils.c
@@ -165,50 +165,117 @@ int mystrtoll(char **p, long long *res)
return *p != start;
}
-int mystrtou32(char **p, int base, uint32_t *res)
+int mystrtod(char **p, double *res)
{
char *start = *p;
- *res = strtoll(*p, p, base);
+ *res = ass_strtod(*p, p);
return *p != start;
}
-int mystrtod(char **p, double *res)
+int mystrtoi32(char **p, int base, int32_t *res)
{
char *start = *p;
- *res = ass_strtod(*p, p);
+ long long temp_res = strtoll(*p, p, base);
+ *res = FFMINMAX(temp_res, INT32_MIN, INT32_MAX);
return *p != start;
}
-uint32_t string2color(ASS_Library *library, char *p, int hex)
+static int read_digits(char **str, int base, uint32_t *res)
{
- uint32_t color = 0;
- int base = hex ? 16 : 10;
+ char *p = *str;
+ char *start = p;
+ uint32_t val = 0;
+
+ while (1) {
+ int digit;
+ if (*p >= '0' && *p < base + '0')
+ digit = *p - '0';
+ else if (*p >= 'a' && *p < base - 10 + 'a')
+ digit = *p - 'a' + 10;
+ else if (*p >= 'A' && *p < base - 10 + 'A')
+ digit = *p - 'A' + 10;
+ else
+ break;
+ val = val * base + digit;
+ ++p;
+ }
+
+ *res = val;
+ *str = p;
+ return p != start;
+}
- if (*p == '&')
- while (*p == '&')
- ++p;
- else
- ass_msg(library, MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
+/**
+ * \brief Convert a string to an integer reduced modulo 2**32
+ * Follows the rules for strtoul but reduces the number modulo 2**32
+ * instead of saturating it to 2**32 - 1.
+ */
+static int mystrtou32_modulo(char **p, int base, uint32_t *res)
+{
+ // This emulates scanf with %d or %x format as it works on
+ // Windows, because that's what is used by VSFilter. In practice,
+ // scanf works the same way on other platforms too, but
+ // the standard leaves its behavior on overflow undefined.
- if (*p == 'H' || *p == 'h') {
- ++p;
- mystrtou32(&p, 16, &color);
- } else
- mystrtou32(&p, base, &color);
+ // Unlike scanf and like strtoul, produce 0 for invalid inputs.
- while (*p == '&' || *p == 'H')
- ++p;
+ char *start = *p;
+ int sign = 1;
+
+ skip_spaces(p);
+
+ if (**p == '+')
+ ++*p;
+ else if (**p == '-')
+ sign = -1, ++*p;
- unsigned char *tmp = (unsigned char *) (&color);
- unsigned char b;
- b = tmp[0];
- tmp[0] = tmp[3];
- tmp[3] = b;
- b = tmp[1];
- tmp[1] = tmp[2];
- tmp[2] = b;
+ if (base == 16 && !strncasecmp(*p, "0x", 2))
+ *p += 2;
+
+ if (read_digits(p, base, res)) {
+ *res *= sign;
+ return 1;
+ } else {
+ *p = start;
+ return 0;
+ }
+}
+
+int32_t parse_alpha_tag(char *str)
+{
+ int32_t alpha = 0;
+
+ while (*str == '&' || *str == 'H')
+ ++str;
+
+ mystrtoi32(&str, 16, &alpha);
+ return alpha;
+}
+
+uint32_t parse_color_tag(char *str)
+{
+ int32_t color = 0;
+
+ while (*str == '&' || *str == 'H')
+ ++str;
+
+ mystrtoi32(&str, 16, &color);
+ return ass_bswap32((uint32_t) color);
+}
+
+uint32_t parse_color_header(char *str)
+{
+ uint32_t color = 0;
+ int base;
+
+ if (!strncasecmp(str, "&h", 2) || !strncasecmp(str, "0x", 2)) {
+ str += 2;
+ base = 16;
+ } else
+ base = 10;
- return color;
+ mystrtou32_modulo(&str, base, &color);
+ return ass_bswap32(color);
}
// Return a boolean value for a string