/// <summary> /// Given a Specs object, return a SingleID representing the special inverse /// of that ID. If there is no special inverse then return null. /// </summary> /// /// <returns>a SingleID or null. Returned object always has 'filter' field of /// null.</returns> private static TransliteratorIDParser.SingleID SpecsToSpecialInverse(TransliteratorIDParser.Specs specs) { if (!specs.source.Equals(ANY, StringComparison.InvariantCultureIgnoreCase)) { return(null); } String inverseTarget = (String)SPECIAL_INVERSES[new CaseInsensitiveString(specs.target)]; if (inverseTarget != null) { // If the original ID contained "Any-" then make the // special inverse "Any-Foo"; otherwise make it "Foo". // So "Any-NFC" => "Any-NFD" but "NFC" => "NFD". StringBuilder buf = new StringBuilder(); if (specs.filter != null) { buf.Append(specs.filter); } if (specs.sawSource) { buf.Append(ANY).Append(TARGET_SEP); } buf.Append(inverseTarget); String basicID_0 = ANY + TARGET_SEP + inverseTarget; if (specs.variant != null) { buf.Append(VARIANT_SEP).Append(specs.variant); basicID_0 = basicID_0 + VARIANT_SEP + specs.variant; } return(new TransliteratorIDParser.SingleID(buf.ToString(), basicID_0)); } return(null); }
/// <summary> /// Parse a filter ID, that is, an ID of the general form "[f1] s1-t1/v1", /// with the filters optional, and the variants optional. /// </summary> /// /// <param name="id">the id to be parsed</param> /// <param name="pos">INPUT-OUTPUT parameter. On input, the position of the firstcharacter to parse. On output, the position after the lastcharacter parsed.</param> /// <returns>a SingleID object or null if the parse fails</returns> public static TransliteratorIDParser.SingleID ParseFilterID(String id, int[] pos) { int start = pos[0]; TransliteratorIDParser.Specs specs = ParseFilterID(id, pos, true); if (specs == null) { pos[0] = start; return(null); } // Assemble return results TransliteratorIDParser.SingleID single = SpecsToID(specs, FORWARD); single.filter = specs.filter; return(single); }
/// <summary> /// Givens a Spec object, convert it to a SingleID object. The Spec object is /// a more unprocessed parse result. The SingleID object contains information /// about canonical and basic IDs. /// </summary> /// /// <returns>a SingleID; never returns null. Returned object always has /// 'filter' field of null.</returns> private static TransliteratorIDParser.SingleID SpecsToID(TransliteratorIDParser.Specs specs, int dir) { String canonID_0 = ""; String basicID_1 = ""; String basicPrefix = ""; if (specs != null) { StringBuilder buf = new StringBuilder(); if (dir == FORWARD) { if (specs.sawSource) { buf.Append(specs.source).Append(TARGET_SEP); } else { basicPrefix = specs.source + TARGET_SEP; } buf.Append(specs.target); } else { buf.Append(specs.target).Append(TARGET_SEP) .Append(specs.source); } if (specs.variant != null) { buf.Append(VARIANT_SEP).Append(specs.variant); } basicID_1 = basicPrefix + buf.ToString(); if (specs.filter != null) { buf.Insert(0, specs.filter); } canonID_0 = buf.ToString(); } return(new TransliteratorIDParser.SingleID(canonID_0, basicID_1)); }
/// <summary> /// 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. /// </summary> /// /// <param name="id">the id to be parsed</param> /// <param name="pos">INPUT-OUTPUT parameter. On input, the position of the firstcharacter to parse. On output, the position after the lastcharacter parsed.</param> /// <param name="dir">the direction. If the direction is REVERSE then the SingleIDis constructed for the reverse direction.</param> /// <returns>a SingleID object or null</returns> public static TransliteratorIDParser.SingleID ParseSingleID(String id, int[] pos, int dir) { int start = pos[0]; // The ID will be of the form A, A(), A(B), or (B), where // A and B are filter IDs. TransliteratorIDParser.Specs specsA = null; TransliteratorIDParser.Specs specsB = null; bool 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 (int pass = 1; pass <= 2; ++pass) { if (pass == 2) { specsA = ParseFilterID(id, pos, true); if (specsA == null) { pos[0] = start; return(null); } } if (IBM.ICU.Impl.Utility.ParseChar(id, pos, OPEN_REV)) { sawParen = true; if (!IBM.ICU.Impl.Utility.ParseChar(id, pos, CLOSE_REV)) { specsB = ParseFilterID(id, pos, true); // Must close with a ')' if (specsB == null || !IBM.ICU.Impl.Utility.ParseChar(id, pos, CLOSE_REV)) { pos[0] = start; return(null); } } break; } } // Assemble return results TransliteratorIDParser.SingleID single; if (sawParen) { if (dir == FORWARD) { single = SpecsToID(specsA, FORWARD); single.canonID = single.canonID + OPEN_REV + SpecsToID(specsB, FORWARD).canonID + CLOSE_REV; if (specsA != null) { single.filter = specsA.filter; } } else { single = SpecsToID(specsB, FORWARD); single.canonID = single.canonID + OPEN_REV + SpecsToID(specsA, FORWARD).canonID + CLOSE_REV; if (specsB != null) { single.filter = specsB.filter; } } } else { // assert(specsA != null); if (dir == FORWARD) { single = SpecsToID(specsA, FORWARD); } else { single = SpecsToSpecialInverse(specsA); if (single == null) { single = SpecsToID(specsA, REVERSE); } } single.filter = specsA.filter; } return(single); }