| 309 | } |
| 310 | |
| 311 | void parsePrimary(int* parseFlagOut) |
| 312 | { |
| 313 | *parseFlagOut = 0; |
| 314 | |
| 315 | fb_assert(hasPatternChar()); |
| 316 | auto savePos = patternPos; |
| 317 | auto op = getPatternChar(); |
| 318 | |
| 319 | if (op == '_') |
| 320 | { |
| 321 | *parseFlagOut |= PARSE_FLAG_NOT_EMPTY; |
| 322 | re2PatternStr.append("."); |
| 323 | return; |
| 324 | } |
| 325 | else if (op == '%') |
| 326 | { |
| 327 | re2PatternStr.append((flags & COMP_FLAG_PREFER_FEWER) ? ".*?" : ".*"); |
| 328 | return; |
| 329 | } |
| 330 | else if (op == '[') |
| 331 | { |
| 332 | struct |
| 333 | { |
| 334 | const char* similarClass; |
| 335 | const char* re2ClassInclude; |
| 336 | const char* re2ClassExcludeUtf; |
| 337 | const char* re2ClassExcludeLatin; |
| 338 | } static const classes[] = |
| 339 | { |
| 340 | {"alnum", "[:alnum:]", "[:^alnum:]", "[:^alnum:]"}, |
| 341 | {"alpha", "[:alpha:]", "[:^alpha:]", "[:^alpha:]"}, |
| 342 | {"digit", "[:digit:]", "[:^digit:]", "[:^digit:]"}, |
| 343 | {"lower", "[:lower:]", "[:^lower:]", "[:^lower:]"}, |
| 344 | {"space", " ", "\\x00-\\x1F\\x21-\\x{10FFFF}", "\\x00-\\x1F\\x21-\\xFF"}, |
| 345 | {"upper", "[:upper:]", "[:^upper:]", "[:^upper:]"}, |
| 346 | {"whitespace", "[:space:]", "[:^space:]", "[:^space:]"} |
| 347 | }; |
| 348 | |
| 349 | struct Item |
| 350 | { |
| 351 | int clazz; |
| 352 | unsigned firstStart, firstEnd, lastStart, lastEnd; |
| 353 | }; |
| 354 | |
| 355 | const UChar32 maxChar = (flags & COMP_FLAG_LATIN) ? 0xFF : 0x10FFFF; |
| 356 | Array<Item> items; |
| 357 | unsigned includeCount = 0; |
| 358 | bool exclude = false; |
| 359 | bool invalidInclude = false; |
| 360 | |
| 361 | do |
| 362 | { |
| 363 | if (!hasPatternChar()) |
| 364 | status_exception::raise(Arg::Gds(isc_invalid_similar_pattern)); |
| 365 | |
| 366 | unsigned charSavePos = patternPos; |
| 367 | UChar32 c = getPatternChar(); |
| 368 | bool charClass = false; |