Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
/**
 * 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;
}