It removes the hardcoded limit on the key size without making the code much more complex, and it makes for a more versatile API.
Unified · Split
| @@ -829,31 +829,27 @@ static int is_key_char(char c) · 828 unmodified lines | ||
| 829 | 829 | * Read a key from a string. |
| 830 | 830 | * |
| 831 | 831 | * The key consists of is_key_char characters and must be terminated by a |
| 832 | − * character from the delim string; spaces are ignored. The key buffer must | |
| 833 | − * be 4 bytes larger than the longest acceptable key. If the key is too | |
| 834 | − * long, an ellipsis will be written at the end. | |
| 832 | + * character from the delim string; spaces are ignored. | |
| 835 | 833 | * |
| 836 | 834 | * @return 0 for success (even with ellipsis), <0 for failure |
| 837 | 835 | */ |
| 838 | −static int get_key(const char **ropts, const char *delim, char *key, unsigned key_size) | |
| 836 | +static int get_key(const char **ropts, const char *delim, char **rkey) | |
| 839 | 837 | { |
| 840 | − unsigned key_pos = 0; | |
| 841 | 838 | const char *opts = *ropts; |
| 839 | + const char *key_start, *key_end; | |
| 842 | 840 | |
| 843 | − opts += strspn(opts, WHITESPACES); | |
| 844 | − while (is_key_char(*opts)) { | |
| 845 | − key[key_pos++] = *opts; | |
| 846 | − if (key_pos == key_size) | |
| 847 | − key_pos--; | |
| 848 | − (opts)++; | |
| 849 | − } | |
| 841 | + key_start = opts += strspn(opts, WHITESPACES); | |
| 842 | + while (is_key_char(*opts)) | |
| 843 | + opts++; | |
| 844 | + key_end = opts; | |
| 850 | 845 | opts += strspn(opts, WHITESPACES); |
| 851 | 846 | if (!*opts || !strchr(delim, *opts)) |
| 852 | 847 | return AVERROR(EINVAL); |
| 853 | 848 | opts++; |
| 854 | − key[key_pos++] = 0; | |
| 855 | − if (key_pos == key_size) | |
| 856 | − key[key_pos - 4] = key[key_pos - 3] = key[key_pos - 2] = '.'; | |
| 849 | + if (!(*rkey = av_malloc(key_end - key_start + 1))) | |
| 850 | + return AVERROR(ENOMEM); | |
| 851 | + memcpy(*rkey, key_start, key_end - key_start); | |
| 852 | + (*rkey)[key_end - key_start] = 0; | |
| 857 | 853 | *ropts = opts; |
| 858 | 854 | return 0; |
| 859 | 855 | } |
| @@ -864,7 +860,7 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 4 unmodified lines | ||
| 864 | 860 | { |
| 865 | 861 | int ret, count = 0; |
| 866 | 862 | const char *dummy_shorthand = NULL; |
| 867 | − char key_buf[68], *value; | |
| 863 | + char *parsed_key, *value; | |
| 868 | 864 | const char *key; |
| 869 | 865 | |
| 870 | 866 | if (!opts) |
| @@ -873,7 +869,8 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 2 unmodified lines | ||
| 873 | 869 | shorthand = &dummy_shorthand; |
| 874 | 870 | |
| 875 | 871 | while (*opts) { |
| 876 | − if ((ret = get_key(&opts, key_val_sep, key_buf, sizeof(key_buf))) < 0) { | |
| 872 | + parsed_key = NULL; /* so we can free it anyway */ | |
| 873 | + if ((ret = get_key(&opts, key_val_sep, &parsed_key)) < 0) { | |
| 877 | 874 | if (*shorthand) { |
| 878 | 875 | key = *(shorthand++); |
| 879 | 876 | } else { |
| @@ -881,7 +878,7 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 1 unmodified line | ||
| 881 | 878 | return AVERROR(EINVAL); |
| 882 | 879 | } |
| 883 | 880 | } else { |
| 884 | − key = key_buf; | |
| 881 | + key = parsed_key; | |
| 885 | 882 | while (*shorthand) /* discard all remaining shorthand */ |
| 886 | 883 | shorthand++; |
| 887 | 884 | } |
| @@ -896,10 +893,12 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 8 unmodified lines | ||
| 896 | 893 | if (ret == AVERROR_OPTION_NOT_FOUND) |
| 897 | 894 | av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); |
| 898 | 895 | av_free(value); |
| 896 | + av_free(parsed_key); | |
| 899 | 897 | return ret; |
| 900 | 898 | } |
| 901 | 899 | |
| 902 | 900 | av_free(value); |
| 901 | + av_free(parsed_key); | |
| 903 | 902 | count++; |
| 904 | 903 | } |
| 905 | 904 | return count; |