/** * Parse a filter ID, that is, an ID of the general form * "[f1] s1-t1/v1", with the filters optional, and the variants optional. * @param id the id to be parsed * @param pos INPUT-OUTPUT parameter. On input, the position of * the first character to parse. On output, the position after * the last character parsed. * @return a SingleID object or null if the parse fails */ TransliteratorIDParser::SingleID* TransliteratorIDParser::parseFilterID(const UnicodeString& id, int32_t& pos) { int32_t start = pos; Specs* specs = parseFilterID(id, pos, TRUE); if (specs == NULL) { pos = start; return NULL; } // Assemble return results SingleID* single = specsToID(specs, FORWARD); single->filter = specs->filter; delete specs; return single; }
/** * Parse a single ID, that is, an ID of the general form * "[f1] s1-t1/v1 ([f2] s2-t3/v2)", with the parenthesized element * optional, the filters optional, and the variants optional. * @param id the id to be parsed * @param pos INPUT-OUTPUT parameter. On input, the position of * the first character to parse. On output, the position after * the last character parsed. * @param dir the direction. If the direction is REVERSE then the * SingleID is constructed for the reverse direction. * @return a SingleID object or NULL */ TransliteratorIDParser::SingleID * TransliteratorIDParser::parseSingleID(const UnicodeString & id, int32_t & pos, int32_t dir, UErrorCode & status) { int32_t start = pos; // The ID will be of the form A, A(), A(B), or (B), where // A and B are filter IDs. Specs * specsA = NULL; Specs * specsB = NULL; UBool sawParen = FALSE; // On the first pass, look for (B) or (). If this fails, then // on the second pass, look for A, A(B), or A(). for (int32_t pass = 1; pass <= 2; ++pass) { if (pass == 2) { specsA = parseFilterID(id, pos, TRUE); if (specsA == NULL) { pos = start; return NULL; } } if (ICU_Utility::parseChar(id, pos, OPEN_REV)) { sawParen = TRUE; if (!ICU_Utility::parseChar(id, pos, CLOSE_REV)) { specsB = parseFilterID(id, pos, TRUE); // Must close with a ')' if (specsB == NULL || !ICU_Utility::parseChar(id, pos, CLOSE_REV)) { delete specsA; pos = start; return NULL; } } break; } } // Assemble return results SingleID * single; if (sawParen) { if (dir == FORWARD) { SingleID * b = specsToID(specsB, FORWARD); single = specsToID(specsA, FORWARD); // Null pointers check if (b == NULL || single == NULL) { delete b; delete single; status = U_MEMORY_ALLOCATION_ERROR; return NULL; } single->canonID.append(OPEN_REV) .append(b->canonID).append(CLOSE_REV); if (specsA != NULL) { single->filter = specsA->filter; } delete b; } else { SingleID * a = specsToID(specsA, FORWARD); single = specsToID(specsB, FORWARD); // Check for null pointer. if (a == NULL || single == NULL) { delete a; delete single; status = U_MEMORY_ALLOCATION_ERROR; return NULL; } single->canonID.append(OPEN_REV) .append(a->canonID).append(CLOSE_REV); if (specsB != NULL) { single->filter = specsB->filter; } delete a; } } else { // assert(specsA != NULL); if (dir == FORWARD) { single = specsToID(specsA, FORWARD); } else { single = specsToSpecialInverse(*specsA, status); if (single == NULL) { single = specsToID(specsA, REVERSE); } } // Check for NULL pointer if (single == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } single->filter = specsA->filter; } delete specsA; delete specsB; return single; }