diff -r 2d65c2f76d7b -r 947f0dc9f7a8 kernel/eka/common/des16.cpp --- a/kernel/eka/common/des16.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/common/des16.cpp Fri Apr 16 16:24:37 2010 +0300 @@ -765,6 +765,13 @@ #endif } +// Surrogate-aware version of lookup() above. +// aChar can be over 0xFFFF. +inline TUint lookup2(const TUint aChar, const TText *aConv) + { + return TUnicode(aChar).Fold((TInt)aConv, GetLocaleCharSet()->iCharDataSet); + } + TInt DoMatch16(const TDesC16 &aLeftD,const TDesC16 &aRightD,TMatchType aType) { const TText* table=convTable(aType); @@ -1368,6 +1375,558 @@ #endif // !defined(__DES16_MACHINE_CODED__) + +/** + * A helper function, which moves a pointer one Unicode character forward. + * + * @aStart points to the head of the string to process. + * @aEnd points to the end of the string. Note that aEnd points to the first + * 16-bit unit after the string. That is, the string length (i.e, count + * of 16-bit units) is (aEnd-aStart). + * + * On return, + * if find valid character, then return KErrNone, with aNewStart pointing + * to the 16-bit unit after the found character; + * if meet corrupt surrogate before find a valid character, then return + * KErrCorruptSurrogateFound, with aNewStart pointing to the corrupt surrogate; + * if meet aEnd before find a valid character, then return KErrNotFound. + * + * @return KErrNone if ok; + * KErrNotFound if get to aEnd; + * KErrCorruptSurrogateFound if meet corrupt surrogate. + */ +TInt ProceedOneCharacter(const TText16* aStart, const TText16* aEnd, TText16*& aNewStart, TUint& aCurrentChar) + { + if (!aStart || !aEnd || aStart>=aEnd) + return KErrNotFound; + if (!TChar::IsSurrogate(aStart[0])) + { + aCurrentChar = aStart[0]; + aNewStart = const_cast (aStart + 1); + return KErrNone; + } + else if (TChar::IsHighSurrogate(aStart[0])) + { + if (aEnd < aStart + 2) + return KErrCorruptSurrogateFound; + if (!TChar::IsLowSurrogate(aStart[1])) + { + aNewStart = const_cast (aStart + 2); + return KErrCorruptSurrogateFound; + } + aCurrentChar = TChar::JoinSurrogate(aStart[0], aStart[1]); + aNewStart = const_cast (aStart + 2); + return KErrNone; + } + else + { + aNewStart = const_cast (aStart); + return KErrCorruptSurrogateFound; + } + } + +/** + * A helper function, which moves a pointer one or more Unicode characters forward. + * + * This function starts from aStart, stops when one of below conditions matched: + * 1) 16-bit position >= (aEnd - aStart); + * 2) 16-bit position >= aMaxInt16Position; + * 3) character position >= aMaxCharacterPosition; + * + * Specify a huge integer (say KMaskDesLength16) for aMaxInt16Position or + * aMaxCharacterPosition to indicate unlimited 16-bit position or character + * position. + * + * When return, aOutInt16Position, aOutCharacterPosition and aLastChar will + * indicate the same one character, whose + * 16-bit position <= aMaxInt16Position, and + * character position <= aMaxCharacterPosition. + * + * @return KErrNone if no error found; + * KErrNotFound if get to aEnd before find wanted position; or, + * if aMaxIntPosition<=0 or aMaxCharacterPosition<=0; + * KErrCorruptSurrogateFound if meet corrupt surrogate. + */ +TInt ProceedMultiCharacters(const TText16* aStart, const TText16* aEnd, + const TInt aMaxInt16Position, const TInt aMaxCharacterPosition, + TInt& aOutInt16Position, TInt& aOutCharacterPosition, TUint& aLastChar) + { + TText16 *next; + TInt status = KErrNotFound; + aOutInt16Position = 0; + aOutCharacterPosition = 0; + while (aOutInt16Position <= aMaxInt16Position && aOutCharacterPosition <= aMaxCharacterPosition) + { + status = ::ProceedOneCharacter(aStart+aOutInt16Position, aEnd, next, aLastChar); + if (status == KErrNotFound || status == KErrCorruptSurrogateFound) + return status; + if (next - aStart > aMaxInt16Position || aOutInt16Position == aMaxInt16Position || aOutCharacterPosition == aMaxCharacterPosition) + { + return status; + } + aOutInt16Position = (next - aStart); + ++aOutCharacterPosition; + } + return status; + } + +EXPORT_C TInt TDesC16::FindCorruptSurrogate() const +/** +Look for the first corrupt surrogate in the descriptor. + +@return The 16-bit position of the first corrupt surrogate. KErrNotFound, if + not found. +*/ + { + // Do not use TUTF32Iterator, because it hides some characters, including corrupt surrogate. + TInt strLength = Length(); + + const TText16* start = Ptr(); + const TText16* end = Ptr() + strLength; + TInt int16Pos; + TInt charPos; + TUint lastChar; + TInt status = ::ProceedMultiCharacters(start, end, KMaskDesLength16, KMaskDesLength16, int16Pos, charPos, lastChar); + if (status == KErrCorruptSurrogateFound) + return int16Pos; + return KErrNotFound; + } + +EXPORT_C TInt TDesC16::Locate2(TChar aChar) const +/** +The surrogate aware version of Locate(). + +Searches for the first occurrence of a character within this descriptor's +data. + +The search starts at the beginning of the data, i.e. at the leftmost +position. + +@param aChar The Unicode character to be found. Can be inside or outside BMP. + +@return The offset of the character position from the beginning of the data. + KErrNotFound, if no matching character can be found. + KErrCorruptSurrogateFound, if meet corrupt surrogate in the searching. + +@see TDesC16::Locate() +*/ + { + TInt strLength = Length(); + const TText16* start = Ptr(); + const TText16* end = Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + if (status != KErrNone) + return status; + if (currentChar == aChar) + return int16Index; + int16Index = (next - start); + } + } + +LOCAL_C TInt DoLocateF16_2(const TDesC16& aDes, TUint aChar) +// Surrogate-aware version of DoLocateF16(). +// Locate character aChar in the descriptor folded. + { + const TText* table = convTable(EMatchFolded); + TUint aChar32 = aChar; + aChar = lookup2(aChar32, table); + + // find aChar in aDes + TInt strLength = aDes.Length(); + const TText16* start = aDes.Ptr(); + const TText16* end = aDes.Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + while (status == KErrNone) + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + if (status != KErrNone) + break; + if (lookup2(currentChar, table) == aChar) + return int16Index; + int16Index = (next - start); + } + return status; + } + +EXPORT_C TInt TDesC16::LocateF2(TChar aChar) const +/** +The surrogate aware version of LocateF(). + +Searches for the first occurrence of a folded character within this +descriptor's folded data. + +The search starts at the beginning of the data, i.e. at the leftmost +position. + +Note that folding is locale-independent behaviour. It is also important to +note that there can be no guarantee that folding is in any way culturally +appropriate, and should not be used for searching strings in natural language. + +@param aChar The Unicode character to be found. Can be inside or outside BMP. + +@return The offset of the character position from the beginning of the data. + KErrNotFound, if no matching character can be found. + KErrCorruptSurrogateFound, if meet corrupt surrogate in the searching. + +@see TDesC16::LocateF() +*/ + { + return DoLocateF16_2(*this, aChar); + } + +/** + * Proceed backward from aEnd toward aStart by one character. + * + * @aStart points to the first 16-bit unit in a descriptor. + * @aEnd points to the 16-bit unit after the last one. So, count of 16-bit + * units to process is (aEnd-aStart). + * + * On return, + * if valid character found, then return KErrNone, with aNewEnd pointing + * to the character found; + * if meet corrupt surrogate before find a valid character, then return + * KErrCorruptSurrogateFound, with aNewStart point to the corrupt + * surrogate; + * if aStart met, then return KErrNotFound. + * + * @return KErrNone if ok; + * KErrNotFound if get to aStart; + * KErrCorruptSurrogateFound if meet corrupt surrogate. + */ +TInt RecedeOneCharacter(const TText16* aStart, const TText16* aEnd, TText16*& aNewEnd, TUint& aCurrentChar) + { + if (!aStart || !aEnd || aStart>=aEnd) + return KErrNotFound; + if (!TChar::IsSurrogate(aEnd[-1])) + { + aCurrentChar = aEnd[-1]; + aNewEnd = const_cast (aEnd - 1); + return KErrNone; + } + else if (TChar::IsLowSurrogate(aEnd[-1])) + { + if (aEnd < aStart + 2) + return KErrNotFound; + if (!TChar::IsHighSurrogate(aEnd[-2])) + { + aNewEnd = const_cast (aEnd - 2); + return KErrCorruptSurrogateFound; + } + aCurrentChar = TChar::JoinSurrogate(aEnd[-2], aEnd[-1]); + aNewEnd = const_cast (aEnd - 2); + return KErrNone; + } + else + { + aNewEnd = const_cast (aEnd); + return KErrCorruptSurrogateFound; + } + } + +EXPORT_C TInt TDesC16::LocateReverse2(TChar aChar) const +/** +The surrogate aware version of LocateReverse(). + +Searches for the first occurrence of a character within this descriptor's +data, searching from the end of the data. + +The search starts at the rightmost position. + +@param aChar The Unicode character to be found. Can be inside or outside BMP. + +@return The offset of the character position from the beginning of the data. + KErrNotFound, if no matching character can be found. + KErrCorruptSurrogateFound, if meet corrupt surrogate in the searching. + +@see TDesC16::LocateReverse() +*/ + { + TInt strLength = Length(); + const TText16* start = Ptr(); + TText16* newEnd; + TUint currentChar; + TInt int16Index = strLength; + TInt status = KErrNone; + FOREVER + { + status = ::RecedeOneCharacter(start, start+int16Index, newEnd, currentChar); + if (status != KErrNone) + return status; + int16Index = (newEnd - start); + if (currentChar == aChar) + return int16Index; + } + } + +EXPORT_C TInt TDesC16::LocateReverseF2(TChar aChar) const +/** +The surrogate aware version of LocateReverseF(). + +Searches for the first occurrence of a folded character within this descriptor's +folded data, searching from the end of the data. + +The search starts at the rightmost position. + +Note that folding is locale-independent behaviour. It is also important to +note that there can be no guarantee that folding is in any way culturally +appropriate, and should not be used for searching strings in natural language. + +@param aChar The Unicode character to be found. Can be inside or outside BMP. + +@return The offset of the character position from the beginning of the data. + KErrNotFound, if no matching character can be found. + KErrCorruptSurrogateFound, if meet corrupt surrogate in the searching. + +@see TDesC16::LocateReverseF() +*/ + { + TInt strLength = Length(); + const TText16* start = Ptr(); + const TText16* end = Ptr() + strLength; + TText16* newEnd; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::RecedeOneCharacter(start, end, newEnd, currentChar); + if (status != KErrNone) + return status; + TCharF c(currentChar); + if (c == aChar) + return int16Index; + int16Index = (newEnd - start); + } + } + +inline TUint conv2(TUint aChar, const TText *aConv, const TUnicodeDataSet* aCharDataSet) +// Surrogate-aware version of conv(). +// If aConv is not NULL then convert the character. + { + if (aConv) + return TUnicode(aChar).Fold((TInt)aConv, aCharDataSet); + else + return aChar; + } + +// Surrogate-aware version of DoMatch16(). +// This helper function uses the same search algorithm as DoMatch16(). +TInt DoMatch16_2(const TDesC16 &aLeftD, const TDesC16 &aRightD, TMatchType aType) + { + const TText* table=convTable(aType); + const TUint16* const pRight=aRightD.Ptr(); + const TUint16* pM=pRight-1; // pre-increment addressing + const TUint16* const pP=pM+aRightD.Length(); + const TUint16* const pLeft=aLeftD.Ptr()-1; // pre-increment addressing + const TUint16* pB=pLeft; + const TUint16* pB2=pLeft; // always points to current char; pB2==pB or pB-1 + const TUint16* const pE=pB+aLeftD.Length(); + + // Note: pM and pB always point to the int16 unit before the character to handle. + // so, pM[0] and pB[0] may be a low surrogate. + // but, pM[1] and pB[1] must be start of a character. + // Note: pB2 always points to current character being handled. + // pB2 is used to generated return value. + // if pB[0] is low surrogate, then pB2=pB-1; + // if pB[0] is BMP, then pB2=pB. + // + // A 'diagram' shows the pointers: + // + // before search: + // left: ############################ + // ^ ^ + // pLeft/pB/pB2 pE + // + // right: ############################ + // ^^ ^ + // pM pRight pP + // + // + // after several iterations (C is the next character going to be checked): + // left: ###############C############ + // ^ ^ ^ + // pLeft pB/pB2 pE + // + // right: ##########C################# + // ^ ^ ^ + // pRight pM pP + // + + const TUnicodeDataSet* charDataSet = GetLocaleCharSet()->iCharDataSet; + + // Match any pattern up to the first star + TUint c; + TInt status; + TText* newStart; + for (;;) + { + status = ::ProceedOneCharacter(pM+1, pP+1, newStart, c); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + if (status == KErrNotFound) // exhausted the pattern + return pB==pE ? 0 : KErrNotFound; + pM = newStart - 1; + c = conv2(c, table, charDataSet); + if (c==KMatchAny) + break; + if (pB==pE) // no more input + return KErrNotFound; + TUint c2; + pB2 = pB + 1; + status = ::ProceedOneCharacter(pB+1, pE+1, newStart, c2); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + pB = newStart - 1; + if (c != conv2(c2, table, charDataSet) && c != KMatchOne) // match failed + return KErrNotFound; + } + // reached a star + if (pM==pP) + return 0; + TInt r=pM==pRight ? -1 : 0; // r = how many int16 has been matched in candidate (aLeftD) + for (;;) + { + status = ::ProceedOneCharacter(pM+1, pP+1, newStart, c); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + pM = newStart - 1; + c = conv2(c, table, charDataSet); + if (c==KMatchAny) + { +star: if (pM==pP) // star at end of pattern, always matches + return Max(r,0); + if (r<-1) // skipped some '?', matches at beginning + r=0; + continue; + } + if (pB==pE) // no more input + return KErrNotFound; + if (c==KMatchOne) + { // skip a character in the input + if (pM==pP) + return r+((r>=0) ? 0 : (pE-pLeft)); + TUint dummyC; + pB2 = pB + 1; + status = ::ProceedOneCharacter(pB+1, pE+1, newStart, dummyC); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + pB = newStart - 1; + if (r < 0) + r -= (newStart - pB2); // back r by 1 or 2, depending on dummyC is BMP or non-BMP. + continue; + } + // Matching a non-wild character + for (;;) + { + if (table) + { + TUint c2; + for (;;) + { + pB2 = pB + 1; + status = ::ProceedOneCharacter(pB+1, pE+1, newStart, c2); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + pB = newStart - 1; + if (lookup2(c2, table) == c) + break; + if (pB==pE) // no more input + return KErrNotFound; + } + } + else + { + TUint c2; + for (;;) + { + pB2 = pB + 1; + status = ::ProceedOneCharacter(pB+1, pE+1, newStart, c2); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + pB = newStart - 1; + if (c2 == c) + break; + if (pB==pE) // no more input + return KErrNotFound; + } + } + // Try to match up to the next star + const TUint16* pb=pB; + const TUint16* pm=pM; + for (;;) + { + if (pm=0 ? 0 : pB2-pLeft); + pB=pb; + pM=pm; + goto star; + } + if (pb==pE) + return KErrNotFound; // no more input + TUint cc2; + status = ::ProceedOneCharacter(pb+1, pE+1, newStart, cc2); + if (status == KErrCorruptSurrogateFound) + return KErrCorruptSurrogateFound; + pb = newStart - 1; + if (cc != conv2(cc2, table, charDataSet) && cc != KMatchOne) + break; // sub-match failed, try next input character + } + else if (pb==pE) // end of matching pattern + { + return r+(r>=0 ? 0 : pB2-pLeft); // end of input, so have a match + } + else + break; // try next input character + } + } + } + } + +EXPORT_C TInt TDesC16::Match2(const TDesC16 &aDes) const +/** +The surrogate aware version of Match(). + +Searches this descriptor's data for a match with the match pattern supplied +in the specified descriptor. + +The match pattern can contain the wildcard characters "*" and "?", where "*" +matches zero or more consecutive occurrences of any character and "?" matches +a single occurrence of any character. + +Note that there is no 'escape character', which means that it is not possible +to match either the "*" character itself or the "?" character itself using +this function. + +@param aDes A 16-bit non-modifable descriptor containing the match pattern. + +@return If a match is found, the offset within this descriptor's data where + the match first occurs. KErrNotFound, if there is no match. + KErrCorruptSurrogateFound, if meet corrupt surrogate in the searching. + +@see TDesC16::Match() +*/ + { + return DoMatch16_2(*this, aDes, EMatchNormal); + } + #if !defined( __DES16_MACHINE_CODED__) | defined(__EABI_CTORS__) EXPORT_C TBufCBase16::TBufCBase16() // @@ -3383,6 +3942,930 @@ AppendFormatList(aFmt,list); } +EXPORT_C void TDes16::Append2(TChar aChar) +/** +The surrogate aware version of Append(). + +Appends data onto the end of this descriptor's data. + +The length of this descriptor is incremented to reflect the new content. The +length will be increased by 1 if aChar is inside BMP or 2 if aChar is outside +BMP. + +@param aChar A single character to be appended. Can be inside or outside BMP. + +@panic USER 11 if the resulting new length of this descriptor is greater than + its maximum length. + +@panic USER 217 if corrupt surrogate found in aChar. This functions will not + validate already existing surrogate in the descriptor. + +@see TDes16::Append() +*/ + { + __ASSERT_ALWAYS(TChar::IsSupplementary(aChar) || !TChar::IsSurrogate((TText16)aChar), Panic(ECorruptSurrogateFound)); + + TInt len = Length(); + TUint16 *pB = WPtr() + len; + if (TChar::IsSupplementary(aChar)) + { + SetLength(len + 2); + *pB++ = TChar::GetHighSurrogate(aChar); + *pB = TChar::GetLowSurrogate(aChar); + } + else + { + SetLength(len + 1); + *pB = (TText16)aChar; + } + } + +EXPORT_C void TDes16::Fill2(TChar aChar) +/** +The surrogate aware version of Fill(). + +Fills the descriptor's data area with the specified character, replacing any +existing data. + +The descriptor is filled from the beginning up to its current length. The +descriptor's length does not change. It is not filled to its maximum length. +If aChar is supplementary character, and available space to fill is odd in +16-bit unit, then the last 16-bit unit will be left unchanged, and the length +will keep unchanged. + +@param aChar The fill character. Can be inside or outside BMP. + +@see TDes16::Fill() +*/ + { + TUint16 *pB = WPtr(); + TUint16 *pE = pB + Length(); + if (!TChar::IsSupplementary(aChar)) + { + while (pB < pE) + *pB++ = (TUint16)aChar; + } + else + { + while (pB < pE - 1) + { + *pB++ = TChar::GetHighSurrogate(aChar); + *pB++ = TChar::GetLowSurrogate(aChar); + } + } + } + +EXPORT_C void TDes16::Fill2(TChar aChar, TInt aLength) +/** +The surrogate aware version of Fill(). + +Fills the descriptor's data area with the specified character, replacing any +existing data. + +The descriptor is filled with the specified number of characters, +and its length is changed to reflect this. + +If aChar is supplementary character, and available space to fill is odd in +16-bit unit, then the last 16-bit unit will be left unchanged. + +@param aChar The fill character. Can be inside or outside BMP. +@param aLength The new length of the descriptor. + +@panic USER 11 if aLength is negative or is greater than the maximum length + of this descriptor. + +@panic USER 217 if corrupt surrogate found in aChar. These functions will not + validate already existing surrogate in the descriptor. + +@see TDes16::Fill() +*/ + { + __ASSERT_ALWAYS(TChar::IsSupplementary(aChar) || !TChar::IsSurrogate((TText16)aChar), Panic(ECorruptSurrogateFound)); + + SetLength(aLength); + Fill2(aChar); + } + +EXPORT_C void TDes16::AppendFill2(TChar aChar, TInt aLength) +/** +The surrogate aware version of AppendFill(). + +Appends and fills this descriptor with the specified character. + +The descriptor is appended with the specified number of characters, and its +length is changed to reflect this. + +If aChar is supplementary character, and available space to fill is odd in +16-bit unit, then the last 16-bit unit will be left unchanged. + +@param aChar The fill character. Can be inside or outside BMP. +@param aLength The length of additional space to append into. + +@panic USER 11 if aLength is negative, or the resulting length of this + descriptor is greater than its maximum length. + +@panic USER 217 if corrupt surrogate found in aChar. These functions will not + validate already existing surrogate in the descriptor. + +@see TDes16::AppendFill() +*/ + { + __ASSERT_ALWAYS(TChar::IsSupplementary(aChar) || !TChar::IsSurrogate((TText16)aChar), Panic(ECorruptSurrogateFound)); + + TInt len=Length(); + TUint16 *pB=WPtr()+len; + SetLength(len+aLength); + TUint16 *pE=pB+aLength; + if (!TChar::IsSupplementary(aChar)) + { + while (pB < pE) + *pB++ = (TUint16)aChar; + } + else + { + while (pB < pE - 1) + { + *pB++ = TChar::GetHighSurrogate(aChar); + *pB++ = TChar::GetLowSurrogate(aChar); + } + } + } + +EXPORT_C void TDes16::Justify2(const TDesC16 &aDes, TInt aWidth, TAlign anAlignment, TChar aFill) +/** +The surrogate aware version of Justify(). + +Copies data into this descriptor and justifies it, replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +The target area is considered to be an area of specified width positioned at +the beginning of this descriptor's data area. Source data is copied into, and +aligned within this target area according to the specified alignment +instruction. + +If the length of the target area is larger than the length of the source, then +spare space within the target area is padded with the fill character. + +@param aDes A 16-bit non-modifiable descriptor containing the source data. + The length of the data to be copied is the smaller of: + the length of the source descriptor, and + the width of the target area (only if this is not the + explicit negative value KDefaultJustifyWidth). + +@param aWidth The width of the target area. If this has the specific + negative value KDefaultJustifyWidth, then the width is + re-set to the length of the data source. + +@param anAlignment The alignment of the data within the target area + +@param aFill The fill character used to pad the target area. Can be + inside or outside BMP. + +@panic USER 11 if the resulting length of this descriptor is greater than + its maximum length or aWidth has a negative value other + than KDefaultJustifyWidth. + +@panic USER 217 if corrupt surrogate found in the parameters or in the + descriptor. + +@see TDes16::Justify() +*/ + { + Zero(); + AppendJustify2(aDes.Ptr(),aDes.Length(),aWidth,anAlignment,aFill); + } + +EXPORT_C void TDes16::AppendJustify2(const TDesC16 &aDes, TInt aWidth, TAlign anAlignment, TChar aFill) +/** +The surrogate aware version of AppendJustify. + +Appends data onto the end of this descriptor's data and justifies it. + +The source of the appended data is an existing descriptor. + +The target area is considered to be an area of specified width, immediately +following this descriptor's existing data. Source data is copied into, and +aligned within this target area according to the specified alignment instruction. + +If the length of the target area is larger than the length of the source, +then spare space within the target area is padded with the fill character. + +@param aDes A 16-bit non-modifiable descriptor containing the source + data. The length of the data to be copied is the smaller of: + the length of the source descriptor, and + the width of the target area (only if this is not the + explicit negative value KDefaultJustifyWidth). + +@param aWidth The width of the target area. If this has the specific + negative value KDefaultJustifyWidth, then the width is + re-set to the length of the data source. + +@param anAlignment The alignment of the data within the target area. + +@param aFill The fill character used to pad the target area. Can be + inside or outside BMP. + +@panic USER 11 if the resulting length of this descriptor is greater than + its maximum length or aWidth has a negative value other + than KDefaultJustifyWidth. + +@panic USER 217 if corrupt surrogate found in the parameters or in the + descriptor. + +@see TDes16::AppendJustify() +*/ + { + AppendJustify2(aDes.Ptr(),aDes.Length(),aWidth,anAlignment,aFill); + } + +EXPORT_C void TDes16::AppendJustify2(const TDesC16 &aDes, TInt aLength, TInt aWidth, TAlign anAlignment, TChar aFill) +/** +The surrogate aware version of AppendJustify. + +Appends data onto the end of this descriptor's data and justifies it. + +The source of the appended data is an existing descriptor. + +The target area is considered to be an area of specified width, immediately +following this descriptor's existing data. Source data is copied into, and +aligned within this target area according to the specified alignment instruction. + +If the length of the target area is larger than the length of the source, +then spare space within the target area is padded with the fill character. + +@param aDes An 8-bit non-modifiable descriptor containing the source data. + +@param aLength The length of data to be copied from the source descriptor. + If this is greater than the width of the target area, then + the length of data copied is limited to the width. + The length of data to be copied must not be greater than + the length of the source descriptor. Note that this + condition is not automatically tested. + +@param aWidth The width of the target area. If this has the specific negative + value KDefaultJustifyWidth, then the width is + re-set to the length of the data source. + +@param anAlignment The alignment of the data within the target area. + +@param aFill The fill character used to pad the target area. Can be + inside or outside BMP. + +@panic USER 11 if the resulting length of this descriptor is greater than + its maximum length or aWidth has a negative value other + than KDefaultJustifyWidth. + +@panic USER 217 if corrupt surrogate found in the parameters or in the + descriptor. + +@see TDes16::AppendJustify() +*/ + { + AppendJustify2(aDes.Ptr(),aLength,aWidth,anAlignment,aFill); + } + +EXPORT_C void TDes16::AppendJustify2(const TUint16 *aString, TInt aWidth, TAlign anAlignment, TChar aFill) +/** +The surrogate aware version of AppendJustify. + +Appends a zero terminated string onto the end of this descriptor's data and +justifies it. + +The zero terminator is not copied. + +The target area is considered to be an area of specified width, immediately +following this descriptor's existing data. Source data is copied into, and +aligned within, this target area according to the specified alignment instruction. + +If the length of the target area is larger than the length of the source, +then spare space within the target area is padded with the fill character. + +@param aString A pointer to a zero terminated string The length of the data + to be copied is the smaller of: the length of the string (excluding the zero + terminator), the width of the target area (only if this is not the explicit + negative value KDefaultJustifyWidth). + +@param aWidth The width of the target area. If this has the specific negative + value KDefaultJustifyWidth, then the width is re-set to the length of the + zero terminated string (excluding the zero terminator). + +@param anAlignment The alignment of the data within the target area. + +@param aFill The fill character used to pad the target area. Can be + inside or outside BMP. + +@panic USER 11 if the resulting length of this descriptor is greater than + its maximum length or aWidth has a negative value other + than KDefaultJustifyWidth. + +@panic USER 217 if corrupt surrogate found in the parameters or in the + descriptor. + +@see TDes16::AppendJustify() +*/ + { + __CHECK_ALIGNMENT(aString,ETDes16AppendJustify1); + AppendJustify2(aString,STRING_LENGTH_16(aString),aWidth,anAlignment,aFill); + } + +EXPORT_C void TDes16::AppendJustify2(const TUint16 *aString, TInt aLength, TInt aWidth, TAlign anAlignment, TChar aFill) +/** +The surrogate aware version of AppendJustify. + +Appends data onto the end of this descriptor's data and justifies it. + +The source of the appended data is a memory location. + +The target area is considered to be an area of specified width, immediately +following this descriptor's existing data. Source data is copied into, and +aligned within, this target area according to the specified alignment instruction. + +If the length of the target area is larger than the length of the source, +then spare space within the target area is padded with the fill character. + +@param aString A pointer to a source memory location. + +@param aLength The length of data to be copied. If this is greater than the + width of the target area, then the length of data copied is + limited to the width. + +@param aWidth The width of the target area. If this has the specific negative + value KDefaultJustifyWidth, then the width is + re-set to the length of the data source. + +@param anAlignment The alignment of the data within the target area. + +@param aFill The fill character used to pad the target area. Can be + inside or outside BMP. + +@panic USER 11 if the resulting length of this descriptor is greater than + its maximum length or aWidth has a negative value other + than KDefaultJustifyWidth. + +@panic USER 17 if aLength is negative. + +@panic USER 217 if corrupt surrogate found in the parameters or in the + descriptor. + +@see TDes16::AppendJustify() +*/ + { + __ASSERT_ALWAYS(aLength>=0,Panic(ETDes16LengthNegative)); + __CHECK_ALIGNMENT(aString,ETDes16AppendJustify2); + if (aWidth==KDefaultJustifyWidth) + aWidth=aLength; + if (aLength>aWidth) + aLength=aWidth; + TInt offset=Length(); + AppendFill2(aFill,aWidth); + TInt r=aWidth-aLength; + if (anAlignment==ECenter) + r>>=1; + else if (anAlignment==ELeft) + r=0; + memCopy(WPtr()+offset+r,aString,aLength); + } + +EXPORT_C void TDes16::Fold2() +/** +The surrogate aware version of Fold(). + +Performs folding on the content of this descriptor. + +Note that folding is locale-independent behaviour. It is also important to +note that there can be no guarantee that folding is in any way culturally +appropriate, and should not be used when dealing with strings in natural +language. + +@panic USER 217 if corrupt surrogate found in the descriptor. + +@see TDes16::Fold() +*/ + { + TInt strLength = Length(); + TText16* start = WPtr(); + const TText16* end = Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + TCharF c(currentChar); + // at present, c and currentChar always in the same plane + if (TChar::IsSupplementary(c)) + { + start[int16Index] = TChar::GetHighSurrogate(c); + start[int16Index+1] = TChar::GetLowSurrogate(c); + } + else + { + start[int16Index] = (TText16)c; + } + int16Index = (next - start); + } + } + +EXPORT_C void TDes16::Collate2() +/** +The surrogate aware version of Collate(). + +Performs collation on the content of this descriptor. + +@panic USER 217 if corrupt surrogate found in the descriptor. + +@see TDes16::Collate() +*/ + { + TInt strLength = Length(); + TText16* start = WPtr(); + const TText16* end = Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + TChar c = User::Collate(currentChar); + // at present, c and currentChar always in the same plane + if (TChar::IsSupplementary(c)) + { + start[int16Index] = TChar::GetHighSurrogate(c); + start[int16Index+1] = TChar::GetLowSurrogate(c); + } + else + { + start[int16Index] = (TText16)c; + } + int16Index = (next - start); + } + } + +EXPORT_C void TDes16::LowerCase2() +/** +The surrogate aware version of LowerCase(). + +Converts the content of this descriptor to lower case. + +Conversion is implemented as appropriate to the current locale. + +@panic USER 217 if corrupt surrogate found in the descriptor. + +@see TDes16::LowerCase() +*/ + { + TInt strLength = Length(); + TText16* start = WPtr(); + const TText16* end = Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + TCharLC c(currentChar); + // at present, c and currentChar always in the same plane + if (TChar::IsSupplementary(c)) + { + start[int16Index] = TChar::GetHighSurrogate(c); + start[int16Index+1] = TChar::GetLowSurrogate(c); + } + else + { + start[int16Index] = (TText16)c; + } + int16Index = (next - start); + } + } + +EXPORT_C void TDes16::UpperCase2() +/** +The surrogate aware version of UpperCase(). + +Converts the content of this descriptor to upper case. + +Conversion is implemented as appropriate to the current locale. + +@panic USER 217 if corrupt surrogate found in the descriptor. + +@see TDes16::UpperCase() +*/ + { + TInt strLength = Length(); + TText16* start = WPtr(); + const TText16* end = Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + TCharUC c(currentChar); + // at present, c and currentChar always in the same plane + if (TChar::IsSupplementary(c)) + { + start[int16Index] = TChar::GetHighSurrogate(c); + start[int16Index+1] = TChar::GetLowSurrogate(c); + } + else + { + start[int16Index] = (TText16)c; + } + int16Index = (next - start); + } + } + +EXPORT_C void TDes16::Capitalize2() +/** +The surrogate aware version of Capitalize(). + +Capitalises the content of this descriptor. + +Capitalisation is implemented as appropriate to the current locale. + +@panic USER 217 if corrupt surrogate found in the descriptor. + +@see TDes16::Capitalize() +*/ + { + TInt strLength = Length(); + TText16* start = WPtr(); + const TText16* end = Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + + // the first character: title case + status = ::ProceedOneCharacter(start, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + TChar c = User::TitleCase(currentChar); + // at present, c and currentChar always in the same plane + if (TChar::IsSupplementary(c)) + { + start[0] = TChar::GetHighSurrogate(c); + start[1] = TChar::GetLowSurrogate(c); + } + else + { + start[0] = (TText16)c; + } + int16Index = (next - start); + + // following characters: lower case + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + TChar c = User::LowerCase(currentChar); + // at present, c and currentChar always in the same plane + if (TChar::IsSupplementary(c)) + { + start[int16Index] = TChar::GetHighSurrogate(c); + start[int16Index+1] = TChar::GetLowSurrogate(c); + } + else + { + start[int16Index] = (TText16)c; + } + int16Index = (next - start); + } + } + +EXPORT_C void TDes16::CopyF2(const TDesC16 &aDes) +/** +The surrogate aware version of CopyF(). + +Copies and folds data from the specified descriptor into this descriptor replacing +any existing data. + +The length of this descriptor is set to reflect the new +data. + +Note that folding is locale-independent behaviour. It is also important to +note that there can be no guarantee that folding is in any way culturally +appropriate, and should not be used when dealing with strings in natural +language. + +@param aDes A 16-bit non-modifiable descriptor. + +@panic USER 11 if the length of aDes is greater than the maximum length of + this target descriptor. + +@panic USER 217 if corrupt surrogate found in aDes or in the descriptor. + +@see TDes16::CopyF() +*/ + { + TText16* pT = WPtr(); + TInt len = 0; + const TInt maxLen = MaxLength(); + + // iterate through aDes + TInt strLength = aDes.Length(); + const TText16* start = aDes.Ptr(); + const TText16* end = aDes.Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + int16Index = (next - start); + TCharF c(currentChar); + if (TChar::IsSupplementary(c)) + { + len += 2; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-2] = TChar::GetHighSurrogate(c); + pT[len-1] = TChar::GetLowSurrogate(c); + } + else + { + ++len; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-1] = (TText16)c; + } + } + SetLength(len); + } + +EXPORT_C void TDes16::CopyC2(const TDesC16 &aDes) +/** +The surrogate aware version of CopyC(). + +Copies and collates data from the specified descriptor +into this descriptor replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +@param aDes A 16-bit non-modifiable descriptor. + +@panic USER 11 if the length of aDes is greater than the maximum length of + this target descriptor. + +@panic USER 217 if corrupt surrogate found in aDes or in the descriptor. + +@see TDes16::CopyC() +*/ + { + TText16* pT = WPtr(); + TInt len = 0; + const TInt maxLen = MaxLength(); + + // iterate through aDes + TInt strLength = aDes.Length(); + const TText16* start = aDes.Ptr(); + const TText16* end = aDes.Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + int16Index = (next - start); + TChar c = User::Collate(currentChar); + if (TChar::IsSupplementary(c)) + { + len += 2; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-2] = TChar::GetHighSurrogate(c); + pT[len-1] = TChar::GetLowSurrogate(c); + } + else + { + ++len; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-1] = (TText16)c; + } + } + SetLength(len); + } + +EXPORT_C void TDes16::CopyLC2(const TDesC16 &aDes) +/** +The surrogate aware version of CopyLC(). + +Copies text from the specified descriptor and converts it to lower case before +putting it into this descriptor, replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +Conversion to lower case is implemented as appropriate to the current locale. + +@param aDes A 16-bit non modifiable descriptor. + +@panic USER 11 if the length of aDes is greater than the maximum length of + this target descriptor. + +@panic USER 217 if corrupt surrogate found in aDes or in the descriptor. + +@see TDes16::CopyLC() +*/ + { + TText16* pT = WPtr(); + TInt len = 0; + const TInt maxLen = MaxLength(); + + // iterate through aDes + TInt strLength = aDes.Length(); + const TText16* start = aDes.Ptr(); + const TText16* end = aDes.Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + int16Index = (next - start); + TCharLC c(currentChar); + if (TChar::IsSupplementary(c)) + { + len += 2; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-2] = TChar::GetHighSurrogate(c); + pT[len-1] = TChar::GetLowSurrogate(c); + } + else + { + ++len; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-1] = (TText16)c; + } + } + SetLength(len); + } + +EXPORT_C void TDes16::CopyUC2(const TDesC16 &aDes) +/** +The surrogate aware version of CopyUC(). + +Copies text from the specified descriptor and converts it to upper case before +putting it into this descriptor, replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +Conversion to upper case is implemented as appropriate to the current locale. + +@param aDes A 16-bit non modifiable descriptor. + +@panic USER 11 if the length of aDes is greater than the maximum length of + this target descriptor. + +@panic USER 217 if corrupt surrogate found in aDes or in the descriptor. + +@see TDes16::CopyUC() +*/ + { + TText16* pT = WPtr(); + TInt len = 0; + const TInt maxLen = MaxLength(); + + // iterate through aDes + TInt strLength = aDes.Length(); + const TText16* start = aDes.Ptr(); + const TText16* end = aDes.Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + int16Index = (next - start); + TCharUC c(currentChar); + if (TChar::IsSupplementary(c)) + { + len += 2; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-2] = TChar::GetHighSurrogate(c); + pT[len-1] = TChar::GetLowSurrogate(c); + } + else + { + ++len; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-1] = (TText16)c; + } + } + SetLength(len); + } + +EXPORT_C void TDes16::CopyCP2(const TDesC16 &aDes) +/** +The surrogate aware version of CopyCP(). + +Copies text from the specified descriptor and capitalises it before putting +it into this descriptor, replacing any existing data. + +The length of this descriptor is set to reflect the new data. + +Capitalisation is implemented as appropriate to the current locale. + +@param aDes A 16-bit non-modifiable descriptor. + +@panic USER 11 if the length of aDes is greater than the maximum length of + this target descriptor. + +@panic USER 217 if corrupt surrogate found in aDes or in the descriptor. + +@see TDes16::CopyCP() +*/ + { + TText16* pT = WPtr(); + TInt len = 0; + const TInt maxLen = MaxLength(); + + // iterate through aDes + TInt strLength = aDes.Length(); + const TText16* start = aDes.Ptr(); + const TText16* end = aDes.Ptr() + strLength; + TText16* next; + TUint currentChar; + TInt int16Index = 0; + TInt status = KErrNone; + + // first character: title case + status = ::ProceedOneCharacter(start, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + int16Index = (next - start); + TChar c(currentChar); + c.TitleCase(); + if (TChar::IsSupplementary(c)) + { + len += 2; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-2] = TChar::GetHighSurrogate(c); + pT[len-1] = TChar::GetLowSurrogate(c); + } + else + { + ++len; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-1] = (TText16)c; + } + + // following characters: lower case + FOREVER + { + status = ::ProceedOneCharacter(start+int16Index, end, next, currentChar); + __ASSERT_ALWAYS(status != KErrCorruptSurrogateFound, Panic(ECorruptSurrogateFound)); + if (status == KErrNotFound) + break; + int16Index = (next - start); + TCharLC c(currentChar); + if (TChar::IsSupplementary(c)) + { + len += 2; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-2] = TChar::GetHighSurrogate(c); + pT[len-1] = TChar::GetLowSurrogate(c); + } + else + { + ++len; + __ASSERT_ALWAYS(len<=maxLen, Panic(ETDes16Overflow)); + pT[len-1] = (TText16)c; + } + } + SetLength(len); + } + + #if !defined(__DES16_MACHINE_CODED__) | defined(__EABI_CTORS__) EXPORT_C TPtrC16::TPtrC16() : TDesC16(EPtrC,0),iPtr(0)