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 | * Read a key from a string. | 829 | * Read a key from a string. |
| 830 | * | 830 | * |
| 831 | * The key consists of is_key_char characters and must be terminated by a | 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 | 832 | * character from the delim string; spaces are ignored. |
| 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. | ||
| 835 | * | 833 | * |
| 836 | * @return 0 for success (even with ellipsis), <0 for failure | 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 | const char *opts = *ropts; | 838 | const char *opts = *ropts; |
| 839 | const char *key_start, *key_end; | ||
| 842 | 840 | ||
| 843 | opts += strspn(opts, WHITESPACES); | 841 | key_start = opts += strspn(opts, WHITESPACES); |
| 844 | while (is_key_char(*opts)) { | 842 | while (is_key_char(*opts)) |
| 845 | key[key_pos++] = *opts; | 843 | opts++; |
| 846 | if (key_pos == key_size) | 844 | key_end = opts; |
| 847 | key_pos--; | ||
| 848 | (opts)++; | ||
| 849 | } | ||
| 850 | opts += strspn(opts, WHITESPACES); | 845 | opts += strspn(opts, WHITESPACES); |
| 851 | if (!*opts || !strchr(delim, *opts)) | 846 | if (!*opts || !strchr(delim, *opts)) |
| 852 | return AVERROR(EINVAL); | 847 | return AVERROR(EINVAL); |
| 853 | opts++; | 848 | opts++; |
| 854 | key[key_pos++] = 0; | 849 | if (!(*rkey = av_malloc(key_end - key_start + 1))) |
| 855 | if (key_pos == key_size) | 850 | return AVERROR(ENOMEM); |
| 856 | key[key_pos - 4] = key[key_pos - 3] = key[key_pos - 2] = '.'; | 851 | memcpy(*rkey, key_start, key_end - key_start); |
| 852 | (*rkey)[key_end - key_start] = 0; | ||
| 857 | *ropts = opts; | 853 | *ropts = opts; |
| 858 | return 0; | 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 | int ret, count = 0; | 861 | int ret, count = 0; |
| 866 | const char *dummy_shorthand = NULL; | 862 | const char *dummy_shorthand = NULL; |
| 867 | char key_buf[68], *value; | 863 | char *parsed_key, *value; |
| 868 | const char *key; | 864 | const char *key; |
| 869 | 865 | ||
| 870 | if (!opts) | 866 | if (!opts) |
| @@ -873,7 +869,8 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 2 unmodified lines | |||
| 873 | shorthand = &dummy_shorthand; | 869 | shorthand = &dummy_shorthand; |
| 874 | 870 | ||
| 875 | while (*opts) { | 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 | if (*shorthand) { | 874 | if (*shorthand) { |
| 878 | key = *(shorthand++); | 875 | key = *(shorthand++); |
| 879 | } else { | 876 | } else { |
| @@ -881,7 +878,7 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 1 unmodified line | |||
| 881 | return AVERROR(EINVAL); | 878 | return AVERROR(EINVAL); |
| 882 | } | 879 | } |
| 883 | } else { | 880 | } else { |
| 884 | key = key_buf; | 881 | key = parsed_key; |
| 885 | while (*shorthand) /* discard all remaining shorthand */ | 882 | while (*shorthand) /* discard all remaining shorthand */ |
| 886 | shorthand++; | 883 | shorthand++; |
| 887 | } | 884 | } |
| @@ -896,10 +893,12 @@ int av_opt_set_from_string(void *ctx, const char *opts, · 8 unmodified lines | |||
| 896 | if (ret == AVERROR_OPTION_NOT_FOUND) | 893 | if (ret == AVERROR_OPTION_NOT_FOUND) |
| 897 | av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); | 894 | av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); |
| 898 | av_free(value); | 895 | av_free(value); |
| 896 | av_free(parsed_key); | ||
| 899 | return ret; | 897 | return ret; |
| 900 | } | 898 | } |
| 901 | 899 | ||
| 902 | av_free(value); | 900 | av_free(value); |
| 901 | av_free(parsed_key); | ||
| 903 | count++; | 902 | count++; |
| 904 | } | 903 | } |
| 905 | return count; | 904 | return count; |