| 612 | } |
| 613 | |
| 614 | const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset) |
| 615 | { |
| 616 | const char *orig_start = feature_list; |
| 617 | size_t len; |
| 618 | |
| 619 | if (!feature_list) |
| 620 | return NULL; |
| 621 | |
| 622 | len = strlen(feature); |
| 623 | if (offset) |
| 624 | feature_list += *offset; |
| 625 | while (*feature_list) { |
| 626 | const char *found = strstr(feature_list, feature); |
| 627 | if (!found) |
| 628 | return NULL; |
| 629 | if (feature_list == found || isspace(found[-1])) { |
| 630 | const char *value = found + len; |
| 631 | /* feature with no value (e.g., "thin-pack") */ |
| 632 | if (!*value || isspace(*value)) { |
| 633 | if (lenp) |
| 634 | *lenp = 0; |
| 635 | if (offset) |
| 636 | *offset = found + len - orig_start; |
| 637 | return value; |
| 638 | } |
| 639 | /* feature with a value (e.g., "agent=git/1.2.3-Linux") */ |
| 640 | else if (*value == '=') { |
| 641 | size_t end; |
| 642 | |
| 643 | value++; |
| 644 | end = strcspn(value, " \t\n"); |
| 645 | if (lenp) |
| 646 | *lenp = end; |
| 647 | if (offset) |
| 648 | *offset = value + end - orig_start; |
| 649 | return value; |
| 650 | } |
| 651 | /* |
| 652 | * otherwise we matched a substring of another feature; |
| 653 | * keep looking |
| 654 | */ |
| 655 | } |
| 656 | feature_list = found + 1; |
| 657 | } |
| 658 | return NULL; |
| 659 | } |
| 660 | |
| 661 | int server_supports_hash(const char *desired, int *feature_supported) |
| 662 | { |
no outgoing calls
no test coverage detected