(charset, iscased=None, fixup=None, fixes=None)
| 241 | emit(FAILURE) |
| 242 | |
| 243 | def _optimize_charset(charset, iscased=None, fixup=None, fixes=None): |
| 244 | # internal: optimize character set |
| 245 | out = [] |
| 246 | tail = [] |
| 247 | charmap = bytearray(256) |
| 248 | hascased = False |
| 249 | for op, av in charset: |
| 250 | while True: |
| 251 | try: |
| 252 | if op is LITERAL: |
| 253 | if fixup: |
| 254 | lo = fixup(av) |
| 255 | charmap[lo] = 1 |
| 256 | if fixes and lo in fixes: |
| 257 | for k in fixes[lo]: |
| 258 | charmap[k] = 1 |
| 259 | if not hascased and iscased(av): |
| 260 | hascased = True |
| 261 | else: |
| 262 | charmap[av] = 1 |
| 263 | elif op is RANGE: |
| 264 | r = range(av[0], av[1]+1) |
| 265 | if fixup: |
| 266 | if fixes: |
| 267 | for i in map(fixup, r): |
| 268 | charmap[i] = 1 |
| 269 | if i in fixes: |
| 270 | for k in fixes[i]: |
| 271 | charmap[k] = 1 |
| 272 | else: |
| 273 | for i in map(fixup, r): |
| 274 | charmap[i] = 1 |
| 275 | if not hascased: |
| 276 | hascased = any(map(iscased, r)) |
| 277 | else: |
| 278 | for i in r: |
| 279 | charmap[i] = 1 |
| 280 | elif op is NEGATE: |
| 281 | out.append((op, av)) |
| 282 | else: |
| 283 | tail.append((op, av)) |
| 284 | except IndexError: |
| 285 | if len(charmap) == 256: |
| 286 | # character set contains non-UCS1 character codes |
| 287 | charmap += b'\0' * 0xff00 |
| 288 | continue |
| 289 | # Character set contains non-BMP character codes. |
| 290 | # For range, all BMP characters in the range are already |
| 291 | # proceeded. |
| 292 | if fixup: |
| 293 | hascased = True |
| 294 | # For now, IN_UNI_IGNORE+LITERAL and |
| 295 | # IN_UNI_IGNORE+RANGE_UNI_IGNORE work for all non-BMP |
| 296 | # characters, because two characters (at least one of |
| 297 | # which is not in the BMP) match case-insensitively |
| 298 | # if and only if: |
| 299 | # 1) c1.lower() == c2.lower() |
| 300 | # 2) c1.lower() == c2 or c1.lower().upper() == c2 |
no test coverage detected