Split a comma-separated argument string at depth 0 (ignoring commas * inside [], (), {}). Returns NULL-terminated arena array of trimmed * substring copies. Caller passes the inside of `[...]`. */
| 2758 | * inside [], (), {}). Returns NULL-terminated arena array of trimmed |
| 2759 | * substring copies. Caller passes the inside of `[...]`. */ |
| 2760 | static const char **py_split_subscript_args(CBMArena *arena, const char *s, int *out_n) { |
| 2761 | if (!s) { |
| 2762 | *out_n = 0; |
| 2763 | return NULL; |
| 2764 | } |
| 2765 | int cap = 8; |
| 2766 | const char **out = |
| 2767 | (const char **)cbm_arena_alloc(arena, (size_t)(cap + 1) * sizeof(const char *)); |
| 2768 | if (!out) { |
| 2769 | *out_n = 0; |
| 2770 | return NULL; |
| 2771 | } |
| 2772 | int n = 0; |
| 2773 | int depth = 0; |
| 2774 | size_t len = strlen(s); |
| 2775 | size_t start = 0; |
| 2776 | for (size_t i = 0; i <= len; i++) { |
| 2777 | char c = (i < len) ? s[i] : ','; |
| 2778 | if (c == '[' || c == '(' || c == '{') |
| 2779 | depth++; |
| 2780 | else if (c == ']' || c == ')' || c == '}') |
| 2781 | depth--; |
| 2782 | else if (c == ',' && depth == 0) { |
| 2783 | char *part = py_trim_ws(arena, s + start, i - start); |
| 2784 | if (part && part[0]) { |
| 2785 | if (n >= cap) { |
| 2786 | int new_cap = cap * 2; |
| 2787 | const char **grown = (const char **)cbm_arena_alloc( |
| 2788 | arena, (size_t)(new_cap + 1) * sizeof(const char *)); |
| 2789 | if (grown) { |
| 2790 | for (int q = 0; q < n; q++) |
| 2791 | grown[q] = out[q]; |
| 2792 | out = grown; |
| 2793 | cap = new_cap; |
| 2794 | } |
| 2795 | } |
| 2796 | if (n < cap) |
| 2797 | out[n++] = part; |
| 2798 | } |
| 2799 | start = i + 1; |
| 2800 | } |
| 2801 | } |
| 2802 | out[n] = NULL; |
| 2803 | *out_n = n; |
| 2804 | return out; |
| 2805 | } |
| 2806 | |
| 2807 | static const CBMType *py_parse_type_text_qn(CBMArena *arena, const char *ann, |
| 2808 | const char *module_qn) { |
no test coverage detected