Find the first occurrence in the character string STRING of any character in the character string ACCEPT. Copied from gnulib's mbscspn, with two differences: 1. Returns 1-based position of first found character, or zero if not found. 2. Returned value is the logical character index, NOT byte offset. Examples: mbs_logical_cspn ('hello','a') => 0 mbs_logical_cspn ('hello'
| 113 | mbs_logical_cspn ('\xCE\xB1bc','\xCE\xB1') => 1 |
| 114 | mbs_logical_cspn ('\xCE\xB1bc','c') => 3 */ |
| 115 | static size_t |
| 116 | mbs_logical_cspn (char const *s, char const *accept) |
| 117 | { |
| 118 | if (accept[0] == '\0') |
| 119 | return 0; |
| 120 | |
| 121 | /* General case. */ |
| 122 | if (MB_CUR_MAX > 1) |
| 123 | { |
| 124 | size_t idx = 0; |
| 125 | for (char const *p = s; *p; ) |
| 126 | { |
| 127 | ++idx; |
| 128 | mcel_t g = mcel_scanz (p); |
| 129 | if (g.len == 1) |
| 130 | { |
| 131 | if (mbschr (accept, *p)) |
| 132 | return idx; |
| 133 | } |
| 134 | else |
| 135 | for (char const *a = accept; *a; ) |
| 136 | { |
| 137 | mcel_t h = mcel_scanz (a); |
| 138 | if (mcel_eq (g, h)) |
| 139 | return idx; |
| 140 | a += h.len; |
| 141 | } |
| 142 | p += g.len; |
| 143 | } |
| 144 | } |
| 145 | else |
| 146 | { |
| 147 | /* single-byte locale, |
| 148 | convert returned byte offset to 1-based index or zero if not found. */ |
| 149 | size_t i = strcspn (s, accept); |
| 150 | if (s[i]) |
| 151 | return i + 1; |
| 152 | } |
| 153 | |
| 154 | /* not found */ |
| 155 | return 0; |
| 156 | } |
| 157 | |
| 158 | /* Extract the substring of S, from logical character |
| 159 | position POS and LEN characters. |