Ejemplo n.º 1
0
UBool
Normalizer::previousNormalize()
{
	clearBuffer();
	nextIndex = currentIndex;
	text->setIndex(currentIndex);
	if (!text->hasPrevious())
	{
		return FALSE;
	}
	UnicodeString segment;
	while (text->hasPrevious())
	{
		UChar32 c = text->previous32();
		segment.insert(0, c);
		if (fNorm2->hasBoundaryBefore(c))
		{
			break;
		}
	}
	currentIndex = text->getIndex();
	UErrorCode errorCode = U_ZERO_ERROR;
	fNorm2->normalize(segment, buffer, errorCode);
	bufferPos = buffer.length();
	return U_SUCCESS(errorCode) && !buffer.isEmpty();
}
Ejemplo n.º 2
0
/**
 * Do a normalization using the iterative API in the given direction.
 * @param dir either +1 or -1
 */
void NormalizerConformanceTest::iterativeNorm(const UnicodeString& str,
                                              UNormalizationMode mode, int32_t options,
                                              UnicodeString& result,
                                              int8_t dir) {
    UErrorCode status = U_ZERO_ERROR;
    normalizer.setText(str, status);
    normalizer.setMode(mode);
    normalizer.setOption(-1, 0);        // reset all options
    normalizer.setOption(options, 1);   // set desired options
    result.truncate(0);
    if (U_FAILURE(status)) {
        return;
    }
    UChar32 ch;
    if (dir > 0) {
        for (ch = normalizer.first(); ch != Normalizer::DONE;
             ch = normalizer.next()) {
            result.append(ch);
        }
    } else {
        for (ch = normalizer.last(); ch != Normalizer::DONE;
             ch = normalizer.previous()) {
            result.insert(0, ch);
        }
    }
}
void G7CollationTest::TestDemo3(/* char* par */)
{
    logln("Demo Test 3 : Create a new table collation with rules \"& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'\"");
    UErrorCode status = U_ZERO_ERROR;
    Collator *col = Collator::createInstance("en_US", status);
    if(U_FAILURE(status)) {
        errln("Couldn't instantiate collator. Error: %s", u_errorName(status));
        delete col;
        return;
    }
    const UnicodeString baseRules = ((RuleBasedCollator*)col)->getRules();
    UnicodeString newRules = "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'";
    newRules.insert(0, baseRules);
    RuleBasedCollator *myCollation = new RuleBasedCollator(newRules, status);

    if (U_FAILURE(status))
    {
        errln("Demo Test 3 Table Collation object creation failed.");
        return;
    }

    int32_t j, n;
    for (j = 0; j < TOTALTESTSET; j++)
    {
        for (n = j+1; n < TOTALTESTSET; n++)
        {
            doTest(myCollation, testCases[results[10][j]], testCases[results[10][n]], Collator::LESS);
        }
    }

    delete myCollation;
    delete col;
}
void G7CollationTest::TestDemo4(/* char* par */)
{
    logln("Demo Test 4 : Create a new table collation with rules \" & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' \"");
    UErrorCode status = U_ZERO_ERROR;
    Collator *col = Collator::createInstance("en_US", status);
    if(U_FAILURE(status)) {
        delete col;
        errln("Couldn't instantiate collator. Error: %s", u_errorName(status));
        return;
    }

    const UnicodeString baseRules = ((RuleBasedCollator*)col)->getRules();
    UnicodeString newRules = " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' ";
    newRules.insert(0, baseRules);
    RuleBasedCollator *myCollation = new RuleBasedCollator(newRules, status);

    int32_t j, n;
    for (j = 0; j < TOTALTESTSET; j++)
    {
        for (n = j+1; n < TOTALTESTSET; n++)
        {
            doTest(myCollation, testCases[results[11][j]], testCases[results[11][n]], Collator::LESS);
        }
    }

    delete myCollation;
    delete col;
}
Ejemplo n.º 5
0
/**
 * 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.
 * @return a SingleID; never returns NULL.  Returned object always
 * has 'filter' field of NULL.
 */
TransliteratorIDParser::SingleID*
TransliteratorIDParser::specsToID(const Specs* specs, int32_t dir) {
    UnicodeString canonID;
    UnicodeString basicID;
    UnicodeString basicPrefix;
    if (specs != NULL) {
        UnicodeString buf;
        if (dir == FORWARD) {
            if (specs->sawSource) {
                buf.append(specs->source).append(TARGET_SEP);
            } else {
                basicPrefix = specs->source;
                basicPrefix.append(TARGET_SEP);
            }
            buf.append(specs->target);
        } else {
            buf.append(specs->target).append(TARGET_SEP).append(specs->source);
        }
        if (specs->variant.length() != 0) {
            buf.append(VARIANT_SEP).append(specs->variant);
        }
        basicID = basicPrefix;
        basicID.append(buf);
        if (specs->filter.length() != 0) {
            buf.insert(0, specs->filter);
        }
        canonID = buf;
    }
    return new SingleID(canonID, basicID);
}
Ejemplo n.º 6
0
static int32_t
_iterate(UCharIterator *src, UBool forward,
              UChar *dest, int32_t destCapacity,
              const Normalizer2 *n2,
              UBool doNormalize, UBool *pNeededToNormalize,
              UErrorCode *pErrorCode) {
    if(U_FAILURE(*pErrorCode)) {
        return 0;
    }
    if(destCapacity<0 || (dest==NULL && destCapacity>0) || src==NULL) {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    if(pNeededToNormalize!=NULL) {
        *pNeededToNormalize=FALSE;
    }
    if(!(forward ? src->hasNext(src) : src->hasPrevious(src))) {
        return u_terminateUChars(dest, destCapacity, 0, pErrorCode);
    }

    UnicodeString buffer;
    UChar32 c;
    if(forward) {
        /* get one character and ignore its properties */
        buffer.append(uiter_next32(src));
        /* get all following characters until we see a boundary */
        while((c=uiter_next32(src))>=0) {
            if(n2->hasBoundaryBefore(c)) {
                /* back out the latest movement to stop at the boundary */
                src->move(src, -U16_LENGTH(c), UITER_CURRENT);
                break;
            } else {
                buffer.append(c);
            }
        }
    } else {
        while((c=uiter_previous32(src))>=0) {
            /* always write this character to the front of the buffer */
            buffer.insert(0, c);
            /* stop if this just-copied character is a boundary */
            if(n2->hasBoundaryBefore(c)) {
                break;
            }
        }
    }

    UnicodeString destString(dest, 0, destCapacity);
    if(buffer.length()>0 && doNormalize) {
        n2->normalize(buffer, destString, *pErrorCode).extract(dest, destCapacity, *pErrorCode);
        if(pNeededToNormalize!=NULL && U_SUCCESS(*pErrorCode)) {
            *pNeededToNormalize= destString!=buffer;
        }
        return destString.length();
    } else {
        /* just copy the source characters */
        return buffer.extract(dest, destCapacity, *pErrorCode);
    }
}
Ejemplo n.º 7
0
/**
 * If in "by digits" mode, fills in the substitution one decimal digit
 * at a time using the rule set containing this substitution.
 * Otherwise, uses the superclass function.
 * @param number The number being formatted
 * @param toInsertInto The string to insert the result of formatting
 * the substitution into
 * @param pos The position of the owning rule's rule text in
 * toInsertInto
 */
void
FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) const
{
  // if we're not in "byDigits" mode, just use the inherited
  // doSubstitution() routine
  if (!byDigits) {
    NFSubstitution::doSubstitution(number, toInsertInto, _pos);

    // if we're in "byDigits" mode, transform the value into an integer
    // by moving the decimal point eight places to the right and
    // pulling digits off the right one at a time, formatting each digit
    // as an integer using this substitution's owning rule set
    // (this is slower, but more accurate, than doing it from the
    // other end)
  } else {
    //          int32_t numberToFormat = (int32_t)uprv_round(transformNumber(number) * uprv_pow(10, kMaxDecimalDigits));
    //          // this flag keeps us from formatting trailing zeros.  It starts
    //          // out false because we're pulling from the right, and switches
    //          // to true the first time we encounter a non-zero digit
    //          UBool doZeros = FALSE;
    //          for (int32_t i = 0; i < kMaxDecimalDigits; i++) {
    //              int64_t digit = numberToFormat % 10;
    //              if (digit != 0 || doZeros) {
    //                  if (doZeros && useSpaces) {
    //                      toInsertInto.insert(_pos + getPos(), gSpace);
    //                  }
    //                  doZeros = TRUE;
    //                  getRuleSet()->format(digit, toInsertInto, _pos + getPos());
    //              }
    //              numberToFormat /= 10;
    //          }

    DigitList dl;
    dl.set(number);
    dl.roundFixedPoint(20);     // round to 20 fraction digits.
    dl.reduce();                // Removes any trailing zeros.
    
    UBool pad = FALSE;
    for (int32_t didx = dl.getCount()-1; didx>=dl.getDecimalAt(); didx--) {
      // Loop iterates over fraction digits, starting with the LSD.
      //   include both real digits from the number, and zeros
      //   to the left of the MSD but to the right of the decimal point.
      if (pad && useSpaces) {
        toInsertInto.insert(_pos + getPos(), gSpace);
      } else {
        pad = TRUE;
      }
      int64_t digit = didx>=0 ? dl.getDigit(didx) - '0' : 0;
      getRuleSet()->format(digit, toInsertInto, _pos + getPos());
    }

    if (!pad) {
      // hack around lack of precision in digitlist. if we would end up with
      // "foo point" make sure we add a " zero" to the end.
      getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos());
    }
  }
}
Ejemplo n.º 8
0
void
IntlTestRBNFParse::testfmt(RuleBasedNumberFormat* formatter, int val, UErrorCode& status) {
    UnicodeString us;
    formatter->format((const Formattable)(int32_t)val, us, status);
    if (U_SUCCESS(status)) {
        us.insert(0, (UChar)'"');
        us.append((UChar)'"');
        logln(us);
    } else {
        logln("error: could not format %d, returned status: %d", val, status);
    }
}
Ejemplo n.º 9
0
void
NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t apos) const {
    // perform a transformation on the number being formatted that
    // is dependent on the type of substitution this is

    double numberToFormat = transformNumber(number);
    int64_t longNF = util64_fromDouble(numberToFormat);

    const NFRuleSet* aruleSet = getRuleSet();
    if (withZeros && aruleSet != NULL) {
        // if there are leading zeros in the decimal expansion then emit them
        int64_t nf =longNF;
        int32_t len = toInsertInto.length();
        while ((nf *= 10) < denominator) {
            toInsertInto.insert(apos + getPos(), gSpace);
            aruleSet->format((int64_t)0, toInsertInto, apos + getPos());
        }
        apos += toInsertInto.length() - len;
    }

    // if the result is an integer, from here on out we work in integer
    // space (saving time and memory and preserving accuracy)
    if (numberToFormat == longNF && aruleSet != NULL) {
        aruleSet->format(longNF, toInsertInto, apos + getPos());

        // if the result isn't an integer, then call either our rule set's
        // format() method or our DecimalFormat's format() method to
        // format the result
    } else {
        if (aruleSet != NULL) {
            aruleSet->format(numberToFormat, toInsertInto, apos + getPos());
        } else {
            UErrorCode status = U_ZERO_ERROR;
            UnicodeString temp;
            getNumberFormat()->format(numberToFormat, temp, status);
            toInsertInto.insert(apos + getPos(), temp);
        }
    }
}
Ejemplo n.º 10
0
UnicodeString& StringReplacer::toReplacerPattern(UnicodeString& rule,
                                                 UBool escapeUnprintable) const {
    rule.truncate(0);
    UnicodeString quoteBuf;

    int32_t cursor = cursorPos;

    // Handle a cursor preceding the output
    if (hasCursor && cursor < 0) {
        while (cursor++ < 0) {
            ICU_Utility::appendToRule(rule, (UChar)0x0040 /*@*/, TRUE, escapeUnprintable, quoteBuf);
        }
        // Fall through and append '|' below
    }

    for (int32_t i=0; i<output.length(); ++i) {
        if (hasCursor && i == cursor) {
            ICU_Utility::appendToRule(rule, (UChar)0x007C /*|*/, TRUE, escapeUnprintable, quoteBuf);
        }
        UChar c = output.charAt(i); // Ok to use 16-bits here

        UnicodeReplacer* r = data->lookupReplacer(c);
        if (r == NULL) {
            ICU_Utility::appendToRule(rule, c, FALSE, escapeUnprintable, quoteBuf);
        } else {
            UnicodeString buf;
            r->toReplacerPattern(buf, escapeUnprintable);
            buf.insert(0, (UChar)0x20);
            buf.append((UChar)0x20);
            ICU_Utility::appendToRule(rule, buf,
                                      TRUE, escapeUnprintable, quoteBuf);
        }
    }

    // Handle a cursor after the output.  Use > rather than >= because
    // if cursor == output.length() it is at the end of the output,
    // which is the default position, so we need not emit it.
    if (hasCursor && cursor > output.length()) {
        cursor -= output.length();
        while (cursor-- > 0) {
            ICU_Utility::appendToRule(rule, (UChar)0x0040 /*@*/, TRUE, escapeUnprintable, quoteBuf);
        }
        ICU_Utility::appendToRule(rule, (UChar)0x007C /*|*/, TRUE, escapeUnprintable, quoteBuf);
    }
    // Flush quoteBuf out to result
    ICU_Utility::appendToRule(rule, -1,
                              TRUE, escapeUnprintable, quoteBuf);

    return rule;
}
Ejemplo n.º 11
0
UnicodeString word_wrap(const UnicodeString& message, unsigned wrap_bound) {
  UnicodeString msg = message;
  unsigned limit = wrap_bound;
  unsigned idx = -1;
  for (unsigned i = 0; i < msg.size(); i++) {
    if (i >= limit) {
      if (idx != -1) {
        msg.insert(idx, '\n');
        i = idx + 1;
        limit = idx + 2 + wrap_bound;
        idx = -1;
        continue;
      }
    }
    if (msg[i] == ' ') idx = i;
  }
  return msg;
}
Ejemplo n.º 12
0
UnicodeString RegExpManager::Encode(const UnicodeString& regexp) const
{
	UnicodeString result = regexp;
	int32_t pos = 0;

	// Replace + with \+
	while ((pos = result.indexOf('+', pos)) != -1)
	{
		result.insert(pos, '\\');
		pos += 2;
	}
	// Replace ' ' with +
	while ((pos = result.indexOf(' ')) != -1)
	{
		result.setCharAt(pos, '+');
	}
	return result;
}
Ejemplo n.º 13
0
void TextBox::InsertText( const Gwen::UnicodeString& strInsert )
{
	// TODO: Make sure fits (implement maxlength)

	if ( HasSelection() )
	{
		EraseSelection();
	}

	if ( m_iCursorPos > TextLength() ) m_iCursorPos = TextLength();

	if ( !IsTextAllowed( strInsert, m_iCursorPos )  )
		return;

	UnicodeString str = GetText();
	str.insert( m_iCursorPos, strInsert );
	SetText( str );

	m_iCursorPos += (int) strInsert.size();
	m_iCursorEnd = m_iCursorPos;

	RefreshCursorBounds();
}
Ejemplo n.º 14
0
/**
 * Performs a mathematical operation on the number, formats it using
 * either ruleSet or decimalFormat, and inserts the result into
 * toInsertInto.
 * @param number The number being formatted.
 * @param toInsertInto The string we insert the result into
 * @param pos The position in toInsertInto where the owning rule's
 * rule text begins (this value is added to this substitution's
 * position to determine exactly where to insert the new text)
 */
void
NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos) const
{
    if (ruleSet != NULL) {
        // perform a transformation on the number that is dependent
        // on the type of substitution this is, then just call its
        // rule set's format() method to format the result
        ruleSet->format(transformNumber(number), toInsertInto, _pos + this->pos);
    } else if (numberFormat != NULL) {
        // or perform the transformation on the number (preserving
        // the result's fractional part if the formatter it set
        // to show it), then use that formatter's format() method
        // to format the result
        double numberToFormat = transformNumber((double)number);
        if (numberFormat->getMaximumFractionDigits() == 0) {
            numberToFormat = uprv_floor(numberToFormat);
        }

        UnicodeString temp;
        numberFormat->format(numberToFormat, temp);
        toInsertInto.insert(_pos + this->pos, temp);
    }
}
Ejemplo n.º 15
0
/**
 * Performs a mathematical operation on the number, formats it using
 * either ruleSet or decimalFormat, and inserts the result into
 * toInsertInto.
 * @param number The number being formatted.
 * @param toInsertInto The string we insert the result into
 * @param pos The position in toInsertInto where the owning rule's
 * rule text begins (this value is added to this substitution's
 * position to determine exactly where to insert the new text)
 */
void
NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) const {
    // perform a transformation on the number being formatted that
    // is dependent on the type of substitution this is
    double numberToFormat = transformNumber(number);

    // if the result is an integer, from here on out we work in integer
    // space (saving time and memory and preserving accuracy)
    if (numberToFormat == uprv_floor(numberToFormat) && ruleSet != NULL) {
        ruleSet->format(util64_fromDouble(numberToFormat), toInsertInto, _pos + this->pos);

        // if the result isn't an integer, then call either our rule set's
        // format() method or our DecimalFormat's format() method to
        // format the result
    } else {
        if (ruleSet != NULL) {
            ruleSet->format(numberToFormat, toInsertInto, _pos + this->pos);
        } else if (numberFormat != NULL) {
            UnicodeString temp;
            numberFormat->format(numberToFormat, temp);
            toInsertInto.insert(_pos + this->pos, temp);
        }
    }
}
Ejemplo n.º 16
0
void  U_EXPORT2 
DateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
                 const UnicodeString& bestMatchSkeleton,
                 const UnicodeString& bestIntervalPattern,
                 int8_t differenceInfo,
                 UnicodeString& adjustedPtn) {
    adjustedPtn = bestIntervalPattern;
    int32_t inputSkeletonFieldWidth[] = 
    {
    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    //   P   Q   R   S   T   U   V   W   X   Y   Z
         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    //   p   q   r   s   t   u   v   w   x   y   z
         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
    };

    int32_t bestMatchSkeletonFieldWidth[] = 
    {
    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    //   P   Q   R   S   T   U   V   W   X   Y   Z
         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    //   p   q   r   s   t   u   v   w   x   y   z
         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
    };

    DateIntervalInfo::parseSkeleton(inputSkeleton, inputSkeletonFieldWidth);
    DateIntervalInfo::parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
    if ( differenceInfo == 2 ) {
        adjustedPtn.findAndReplace("v", "z");
    }

    UBool inQuote = false;
    UChar prevCh = 0;
    int32_t count = 0;

    const int8_t PATTERN_CHAR_BASE = 0x41;
    
    // loop through the pattern string character by character 
    int32_t adjustedPtnLength = adjustedPtn.length();
    int32_t i;
    for (i = 0; i < adjustedPtnLength; ++i) {
        UChar ch = adjustedPtn.charAt(i);
        if (ch != prevCh && count > 0) {
            // check the repeativeness of pattern letter
            UChar skeletonChar = prevCh;
            if ( skeletonChar ==  CAP_L ) {
                // there is no "L" (always be "M") in skeleton, 
                // but there is "L" in pattern.
                // for skeleton "M+", the pattern might be "...L..." 
                skeletonChar = CAP_M;
            }
            int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
            int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
            if ( fieldCount == count && inputFieldCount > fieldCount ) {
                count = inputFieldCount - fieldCount;
                int32_t j;
                for ( j = 0; j < count; ++j ) {
                    adjustedPtn.insert(i, prevCh);    
                }                    
                i += count;
                adjustedPtnLength += count;
            }
            count = 0;
        }
        if (ch == '\'') {
            // Consecutive single quotes are a single quote literal,
            // either outside of quotes or between quotes
            if ((i+1) < adjustedPtn.length() && adjustedPtn.charAt(i+1) == '\'') {
                ++i;
            } else {
                inQuote = ! inQuote;
            }
        } 
        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 
                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
            // ch is a date-time pattern character 
            prevCh = ch;
            ++count;
        }
    }
    if ( count > 0 ) {
        // last item
        // check the repeativeness of pattern letter
        UChar skeletonChar = prevCh;
        if ( skeletonChar == CAP_L ) {
            // there is no "L" (always be "M") in skeleton, 
            // but there is "L" in pattern.
            // for skeleton "M+", the pattern might be "...L..." 
            skeletonChar = CAP_M;
        }
        int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
        int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
        if ( fieldCount == count && inputFieldCount > fieldCount ) {
            count = inputFieldCount - fieldCount;
            int32_t j;
            for ( j = 0; j < count; ++j ) {
                adjustedPtn.append(prevCh);    
            }                    
        }
    }
}
Ejemplo n.º 17
0
/**
 * Parse a global filter of the form "[f]" or "([f])", depending
 * on 'withParens'.
 * @param id the pattern the parse
 * @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.
 * @param withParens INPUT-OUTPUT parameter.  On entry, if
 * withParens is 0, then parens are disallowed.  If it is 1,
 * then parens are requires.  If it is -1, then parens are
 * optional, and the return result will be set to 0 or 1.
 * @param canonID OUTPUT parameter.  The pattern for the filter
 * added to the canonID, either at the end, if dir is FORWARD, or
 * at the start, if dir is REVERSE.  The pattern will be enclosed
 * in parentheses if appropriate, and will be suffixed with an
 * ID_DELIM character.  May be NULL.
 * @return a UnicodeSet object or NULL.  A non-NULL results
 * indicates a successful parse, regardless of whether the filter
 * applies to the given direction.  The caller should discard it
 * if withParens != (dir == REVERSE).
 */
UnicodeSet * TransliteratorIDParser::parseGlobalFilter(const UnicodeString & id, int32_t & pos,
        int32_t dir,
        int32_t & withParens,
        UnicodeString * canonID)
{
	UnicodeSet * filter = NULL;
	int32_t start = pos;

	if (withParens == -1)
	{
		withParens = ICU_Utility::parseChar(id, pos, OPEN_REV) ? 1 : 0;
	}
	else if (withParens == 1)
	{
		if (!ICU_Utility::parseChar(id, pos, OPEN_REV))
		{
			pos = start;
			return NULL;
		}
	}

	ICU_Utility::skipWhitespace(id, pos, TRUE);

	if (UnicodeSet::resemblesPattern(id, pos))
	{
		ParsePosition ppos(pos);
		UErrorCode ec = U_ZERO_ERROR;
		filter = new UnicodeSet(id, ppos, USET_IGNORE_SPACE, NULL, ec);
		/* test for NULL */
		if (filter == 0)
		{
			pos = start;
			return 0;
		}
		if (U_FAILURE(ec))
		{
			delete filter;
			pos = start;
			return NULL;
		}

		UnicodeString pattern;
		id.extractBetween(pos, ppos.getIndex(), pattern);
		pos = ppos.getIndex();

		if (withParens == 1 && !ICU_Utility::parseChar(id, pos, CLOSE_REV))
		{
			pos = start;
			return NULL;
		}

		// In the forward direction, append the pattern to the
		// canonID.  In the reverse, insert it at zero, and invert
		// the presence of parens ("A" <-> "(A)").
		if (canonID != NULL)
		{
			if (dir == FORWARD)
			{
				if (withParens == 1)
				{
					pattern.insert(0, OPEN_REV);
					pattern.append(CLOSE_REV);
				}
				canonID->append(pattern).append(ID_DELIM);
			}
			else
			{
				if (withParens == 0)
				{
					pattern.insert(0, OPEN_REV);
					pattern.append(CLOSE_REV);
				}
				canonID->insert(0, pattern);
				canonID->insert(pattern.length(), ID_DELIM);
			}
		}
	}

	return filter;
}
Ejemplo n.º 18
0
/**
 * If in "by digits" mode, fills in the substitution one decimal digit
 * at a time using the rule set containing this substitution.
 * Otherwise, uses the superclass function.
 * @param number The number being formatted
 * @param toInsertInto The string to insert the result of formatting
 * the substitution into
 * @param pos The position of the owning rule's rule text in
 * toInsertInto
 */
void
FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos) const
{
  // if we're not in "byDigits" mode, just use the inherited
  // doSubstitution() routine
  if (!byDigits) {
    NFSubstitution::doSubstitution(number, toInsertInto, _pos);

    // if we're in "byDigits" mode, transform the value into an integer
    // by moving the decimal point eight places to the right and
    // pulling digits off the right one at a time, formatting each digit
    // as an integer using this substitution's owning rule set
    // (this is slower, but more accurate, than doing it from the
    // other end)
  } else {
    //          int32_t numberToFormat = (int32_t)uprv_round(transformNumber(number) * uprv_pow(10, kMaxDecimalDigits));
    //          // this flag keeps us from formatting trailing zeros.  It starts
    //          // out false because we're pulling from the right, and switches
    //          // to true the first time we encounter a non-zero digit
    //          UBool doZeros = FALSE;
    //          for (int32_t i = 0; i < kMaxDecimalDigits; i++) {
    //              int64_t digit = numberToFormat % 10;
    //              if (digit != 0 || doZeros) {
    //                  if (doZeros && useSpaces) {
    //                      toInsertInto.insert(_pos + getPos(), gSpace);
    //                  }
    //                  doZeros = TRUE;
    //                  getRuleSet()->format(digit, toInsertInto, _pos + getPos());
    //              }
    //              numberToFormat /= 10;
    //          }

    DigitList dl;
    dl.set(number, 20, TRUE);
    
    UBool pad = FALSE;
    while (dl.fCount > (dl.fDecimalAt <= 0 ? 0 : dl.fDecimalAt)) {
      if (pad && useSpaces) {
        toInsertInto.insert(_pos + getPos(), gSpace);
      } else {
        pad = TRUE;
      }
      getRuleSet()->format((int64_t)(dl.fDigits[--dl.fCount] - '0'), toInsertInto, _pos + getPos());
    }
    while (dl.fDecimalAt < 0) {
      if (pad && useSpaces) {
        toInsertInto.insert(_pos + getPos(), gSpace);
      } else {
        pad = TRUE;
      }
      getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos());
      ++dl.fDecimalAt;
    }

    if (!pad) {
      // hack around lack of precision in digitlist. if we would end up with
      // "foo point" make sure we add a " zero" to the end.
      getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos());
    }
  }
}
Ejemplo n.º 19
0
UnicodeString& RelativeDateFormat::format(  Calendar& cal,
                                UnicodeString& appendTo,
                                FieldPosition& pos) const {

    UErrorCode status = U_ZERO_ERROR;
    UnicodeString relativeDayString;
    UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);

    // calculate the difference, in days, between 'cal' and now.
    int dayDiff = dayDifference(cal, status);

    // look up string
    int32_t len = 0;
    const UChar *theString = getStringForDay(dayDiff, len, status);
    if(U_SUCCESS(status) && (theString!=NULL)) {
        // found a relative string
        relativeDayString.setTo(theString, len);
    }

    if ( relativeDayString.length() > 0 && !fDatePattern.isEmpty() &&
         (fTimePattern.isEmpty() || fCombinedFormat == NULL || fCombinedHasDateAtStart)) {
#if !UCONFIG_NO_BREAK_ITERATION
        // capitalize relativeDayString according to context for relative, set formatter no context
        if ( u_islower(relativeDayString.char32At(0)) && fCapitalizationBrkIter!= NULL &&
             ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
               (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) ||
               (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone) ) ) {
            // titlecase first word of relativeDayString
            relativeDayString.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
        }
#endif
        fDateTimeFormatter->setContext(UDISPCTX_CAPITALIZATION_NONE, status);
    } else {
        // set our context for the formatter
        fDateTimeFormatter->setContext(capitalizationContext, status);
    }

    if (fDatePattern.isEmpty()) {
        fDateTimeFormatter->applyPattern(fTimePattern);
        fDateTimeFormatter->format(cal,appendTo,pos);
    } else if (fTimePattern.isEmpty() || fCombinedFormat == NULL) {
        if (relativeDayString.length() > 0) {
            appendTo.append(relativeDayString);
        } else {
            fDateTimeFormatter->applyPattern(fDatePattern);
            fDateTimeFormatter->format(cal,appendTo,pos);
        }
    } else {
        UnicodeString datePattern;
        if (relativeDayString.length() > 0) {
            // Need to quote the relativeDayString to make it a legal date pattern
            relativeDayString.findAndReplace(UNICODE_STRING("'", 1), UNICODE_STRING("''", 2)); // double any existing APOSTROPHE
            relativeDayString.insert(0, APOSTROPHE); // add APOSTROPHE at beginning...
            relativeDayString.append(APOSTROPHE); // and at end
            datePattern.setTo(relativeDayString);
        } else {
            datePattern.setTo(fDatePattern);
        }
        UnicodeString combinedPattern;
        fCombinedFormat->format(fTimePattern, datePattern, combinedPattern, status);
        fDateTimeFormatter->applyPattern(combinedPattern);
        fDateTimeFormatter->format(cal,appendTo,pos);
    }

    return appendTo;
}
Ejemplo n.º 20
0
void 
DateIntervalFormat::initializePattern(UErrorCode& status) {
    if ( U_FAILURE(status) ) {
        return;
    }
    const Locale& locale = fDateFormat->getSmpFmtLocale();
    if ( fSkeleton.isEmpty() ) {
        UnicodeString fullPattern;
        fDateFormat->toPattern(fullPattern);
#ifdef DTITVFMT_DEBUG
    char result[1000];
    char result_1[1000];
    char mesg[2000];
    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
    PRINTMESG(mesg)
#endif
        // fSkeleton is already set by createDateIntervalInstance()
        // or by createInstance(UnicodeString skeleton, .... )
        fSkeleton = fDtpng->getSkeleton(fullPattern, status);
        if ( U_FAILURE(status) ) {
            return;    
        }
    }

    // initialize the fIntervalPattern ordering
    int8_t i;
    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
        fIntervalPatterns[i].laterDateFirst = fInfo->getDefaultOrder();
    }

    /* Check whether the skeleton is a combination of date and time.
     * For the complication reason 1 explained above.
     */
    UnicodeString dateSkeleton;
    UnicodeString timeSkeleton;
    UnicodeString normalizedTimeSkeleton;
    UnicodeString normalizedDateSkeleton;


    /* the difference between time skeleton and normalizedTimeSkeleton are:
     * 1. (Formerly, normalized time skeleton folded 'H' to 'h'; no longer true)
     * 2. 'a' is omitted in normalized time skeleton.
     * 3. there is only one appearance for 'h' or 'H', 'm','v', 'z' in normalized 
     *    time skeleton
     *
     * The difference between date skeleton and normalizedDateSkeleton are:
     * 1. both 'y' and 'd' appear only once in normalizeDateSkeleton
     * 2. 'E' and 'EE' are normalized into 'EEE'
     * 3. 'MM' is normalized into 'M'
     */
    getDateTimeSkeleton(fSkeleton, dateSkeleton, normalizedDateSkeleton,
                        timeSkeleton, normalizedTimeSkeleton);

#ifdef DTITVFMT_DEBUG
    char result[1000];
    char result_1[1000];
    char mesg[2000];
    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
    PRINTMESG(mesg)
#endif


    UBool found = setSeparateDateTimePtn(normalizedDateSkeleton, 
                                         normalizedTimeSkeleton);

    if ( found == false ) {
        // use fallback
        // TODO: if user asks "m"(minute), but "d"(day) differ
        if ( timeSkeleton.length() != 0 ) {
            if ( dateSkeleton.length() == 0 ) {
                // prefix with yMd
                timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort]);
                UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
                if ( U_FAILURE(status) ) {
                    return;    
                }
                // for fall back interval patterns,
                // the first part of the pattern is empty,
                // the second part of the pattern is the full-pattern
                // should be used in fall-back.
                setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); 
                setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); 
                setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); 
            } else {
                // TODO: fall back
            }
        } else {
            // TODO: fall back
        }
        return;
    } // end of skeleton not found
    // interval patterns for skeleton are found in resource 
    if ( timeSkeleton.length() == 0 ) {
        // done
    } else if ( dateSkeleton.length() == 0 ) {
        // prefix with yMd
        timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort]);
        UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
        if ( U_FAILURE(status) ) {
            return;    
        }
        // for fall back interval patterns,
        // the first part of the pattern is empty,
        // the second part of the pattern is the full-pattern
        // should be used in fall-back.
        setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); 
        setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); 
        setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); 
    } else {
        /* if both present,
         * 1) when the year, month, or day differs, 
         * concatenate the two original expressions with a separator between, 
         * 2) otherwise, present the date followed by the 
         * range expression for the time. 
         */
        /*
         * 1) when the year, month, or day differs, 
         * concatenate the two original expressions with a separator between, 
         */
        // if field exists, use fall back
        UnicodeString skeleton = fSkeleton;
        if ( !fieldExistsInSkeleton(UCAL_DATE, dateSkeleton) ) {
            // prefix skeleton with 'd'
            skeleton.insert(0, LOW_D);
            setFallbackPattern(UCAL_DATE, skeleton, status);
        }
        if ( !fieldExistsInSkeleton(UCAL_MONTH, dateSkeleton) ) {
            // then prefix skeleton with 'M'
            skeleton.insert(0, CAP_M);
            setFallbackPattern(UCAL_MONTH, skeleton, status);
        }
        if ( !fieldExistsInSkeleton(UCAL_YEAR, dateSkeleton) ) {
            // then prefix skeleton with 'y'
            skeleton.insert(0, LOW_Y);
            setFallbackPattern(UCAL_YEAR, skeleton, status);
        }
        
        /*
         * 2) otherwise, present the date followed by the 
         * range expression for the time. 
         */
        // Need the Date/Time pattern for concatnation the date with
        // the time interval.
        // The date/time pattern ( such as {0} {1} ) is saved in
        // calendar, that is why need to get the CalendarData here.
        CalendarData* calData = new CalendarData(locale, NULL, status);

        if ( U_FAILURE(status) ) {
            delete calData;
            return;
        }

        if ( calData == NULL ) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return;
        }
       
        const UResourceBundle* dateTimePatternsRes = calData->getByKey(
                                           gDateTimePatternsTag, status);
        int32_t dateTimeFormatLength;
        const UChar* dateTimeFormat = ures_getStringByIndex(
                                            dateTimePatternsRes,
                                            (int32_t)DateFormat::kDateTime,
                                            &dateTimeFormatLength, &status);
        if ( U_FAILURE(status) ) {
            return;
        }

        UnicodeString datePattern = fDtpng->getBestPattern(dateSkeleton, status);

        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
                                      datePattern, UCAL_AM_PM, status);
        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
                                      datePattern, UCAL_HOUR, status);
        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
                                      datePattern, UCAL_MINUTE, status);
        delete calData;
    }
}