mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-8314 Appendable interface, AppendableAdapter default impl & UnicodeString is-an Appendable
X-SVN-Rev: 29390
This commit is contained in:
parent
7c69a86709
commit
d8ea46628b
12 changed files with 553 additions and 110 deletions
|
@ -86,7 +86,7 @@ ucnv_ext.o ucnvmbcs.o ucnv2022.o ucnvhz.o ucnv_lmb.o ucnvisci.o ucnvdisp.o ucnv_
|
|||
uresbund.o ures_cnv.o uresdata.o resbund.o resbund_cnv.o \
|
||||
ucat.o locmap.o uloc.o locid.o locutil.o locavailable.o locdispnames.o loclikely.o locresdata.o \
|
||||
bytestream.o stringpiece.o bytestrie.o bytestrieiterator.o \
|
||||
ustr_cnv.o unistr_cnv.o unistr.o unistr_case.o unistr_props.o \
|
||||
appendable.o ustr_cnv.o unistr_cnv.o unistr.o unistr_case.o unistr_props.o \
|
||||
utf_impl.o ustring.o ustrcase.o ucasemap.o cstring.o ustrfmt.o ustrtrns.o ustr_wcs.o utext.o \
|
||||
normalizer2impl.o normalizer2.o filterednormalizer2.o normlzr.o unorm.o unormcmp.o unorm_it.o \
|
||||
chariter.o schriter.o uchriter.o uiter.o \
|
||||
|
|
71
icu4c/source/common/appendable.cpp
Normal file
71
icu4c/source/common/appendable.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* file name: appendable.cpp
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 2010dec07
|
||||
* created by: Markus W. Scherer
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/appendable.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
Appendable::~Appendable() {}
|
||||
|
||||
UBool
|
||||
AppendableAdapter::appendCodePoint(UChar32 c) {
|
||||
if(c<=0xffff) {
|
||||
return appendCodeUnit((UChar)c);
|
||||
} else {
|
||||
return appendCodeUnit(U16_LEAD(c)) && appendCodeUnit(U16_TRAIL(c));
|
||||
}
|
||||
}
|
||||
|
||||
UBool
|
||||
AppendableAdapter::appendString(const UChar *s, int32_t length) {
|
||||
if(length<0) {
|
||||
UChar c;
|
||||
while((c=*s++)!=0) {
|
||||
if(!appendCodeUnit(c)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else if(length>0) {
|
||||
const UChar *limit=s+length;
|
||||
do {
|
||||
if(!appendCodeUnit(*s++)) {
|
||||
return FALSE;
|
||||
}
|
||||
} while(s<limit);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UBool
|
||||
AppendableAdapter::reserveAppendCapacity(int32_t /*appendCapacity*/) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UChar *
|
||||
AppendableAdapter::getAppendBuffer(int32_t minCapacity,
|
||||
int32_t /*desiredCapacityHint*/,
|
||||
UChar *scratch, int32_t scratchCapacity,
|
||||
int32_t *resultCapacity) {
|
||||
if(minCapacity<1 || scratchCapacity<minCapacity) {
|
||||
*resultCapacity=0;
|
||||
return NULL;
|
||||
}
|
||||
*resultCapacity=scratchCapacity;
|
||||
return scratch;
|
||||
}
|
||||
|
||||
UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(AppendableAdapter)
|
||||
|
||||
U_NAMESPACE_END
|
|
@ -399,6 +399,7 @@
|
|||
<ClCompile Include="servrbf.cpp" />
|
||||
<ClCompile Include="servslkf.cpp" />
|
||||
<ClCompile Include="usprep.cpp" />
|
||||
<ClCompile Include="appendable.cpp" />
|
||||
<ClCompile Include="bytestream.cpp" />
|
||||
<ClCompile Include="bytestrie.cpp" />
|
||||
<ClCompile Include="bytestrieiterator.cpp" />
|
||||
|
@ -1351,6 +1352,20 @@
|
|||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
|
||||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="unicode\appendable.h">
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
|
||||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
|
||||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
|
||||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
|
||||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
|
|
213
icu4c/source/common/unicode/appendable.h
Normal file
213
icu4c/source/common/unicode/appendable.h
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* file name: appendable.h
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 2010dec07
|
||||
* created by: Markus W. Scherer
|
||||
*/
|
||||
|
||||
#ifndef __APPENDABLE_H__
|
||||
#define __APPENDABLE_H__
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C++ API: Appendable interface: Sink for Unicode code points and 16-bit code units (UChars).
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/uobject.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Interface/mixin class for objects to which Unicode characters and strings can be appended.
|
||||
* Combines elements of Java Appendable and ICU4C ByteSink.
|
||||
*
|
||||
* This class is not intended for public subclassing.
|
||||
* You should subclass AppendableAdapter instead, in case methods are added to this interface.
|
||||
*
|
||||
* This interface can be used in APIs where it does not matter whether the actual destination is
|
||||
* a UnicodeString, a UChar[] array, a UnicodeSet, or any other object
|
||||
* that receives and processes characters and/or strings.
|
||||
*
|
||||
* Note: UnicodeString is-an Appendable.
|
||||
*
|
||||
* The methods do not take UErrorCode parameters.
|
||||
* If an error occurs (e.g., out-of-memory),
|
||||
* in addition to returning FALSE from failing operations,
|
||||
* the implementation must prevent unexpected behavior (e.g., crashes)
|
||||
* from further calls and should make the error condition available separately
|
||||
* (e.g., store a UErrorCode, make/keep a UnicodeString bogus).
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
class U_COMMON_API Appendable /* not : public UObject because this is an interface/mixin class */ {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual ~Appendable();
|
||||
|
||||
/**
|
||||
* Appends a 16-bit code unit.
|
||||
* @param c code unit
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendCodeUnit(UChar c) = 0;
|
||||
|
||||
/**
|
||||
* Appends a code point.
|
||||
* @param c code point 0..0x10ffff
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendCodePoint(UChar32 c) = 0;
|
||||
|
||||
/**
|
||||
* Appends a string.
|
||||
* @param s string, must not be NULL if length!=0
|
||||
* @param length string length, or -1 if NUL-terminated
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendString(const UChar *s, int32_t length) = 0;
|
||||
|
||||
/**
|
||||
* Tells the object that the caller is going to append roughly
|
||||
* appendCapacity UChars. A subclass might use this to pre-allocate
|
||||
* a larger buffer if necessary.
|
||||
* @param appendCapacity estimated number of UChars that will be appended
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool reserveAppendCapacity(int32_t appendCapacity) = 0;
|
||||
|
||||
/**
|
||||
* Returns a writable buffer for appending and writes the buffer's capacity to
|
||||
* *resultCapacity. Guarantees *resultCapacity>=minCapacity.
|
||||
* May return a pointer to the caller-owned scratch buffer which must have
|
||||
* scratchCapacity>=minCapacity.
|
||||
* The returned buffer is only valid until the next operation
|
||||
* on this Appendable.
|
||||
*
|
||||
* After writing at most *resultCapacity UChars, call appendString() with the
|
||||
* pointer returned from this function and the number of UChars written.
|
||||
* Many appendString() implementations will avoid copying UChars if this function
|
||||
* returned an internal buffer.
|
||||
*
|
||||
* Partial usage example:
|
||||
* \code
|
||||
* int32_t capacity;
|
||||
* UChar* buffer = app.getAppendBuffer(..., &capacity);
|
||||
* ... Write n UChars into buffer, with n <= capacity.
|
||||
* app.appendString(buffer, n);
|
||||
* \endcode
|
||||
* In many implementations, that call to append will avoid copying UChars.
|
||||
*
|
||||
* If the Appendable allocates or reallocates an internal buffer, it should use
|
||||
* the desiredCapacityHint if appropriate.
|
||||
* If a caller cannot provide a reasonable guess at the desired capacity,
|
||||
* it should pass desiredCapacityHint=0.
|
||||
*
|
||||
* If a non-scratch buffer is returned, the caller may only pass
|
||||
* a prefix to it to appendString().
|
||||
* That is, it is not correct to pass an interior pointer to appendString().
|
||||
*
|
||||
* @param minCapacity required minimum capacity of the returned buffer;
|
||||
* must be non-negative
|
||||
* @param desiredCapacityHint desired capacity of the returned buffer;
|
||||
* must be non-negative
|
||||
* @param scratch default caller-owned buffer
|
||||
* @param scratchCapacity capacity of the scratch buffer
|
||||
* @param resultCapacity pointer to an integer which will be set to the
|
||||
* capacity of the returned buffer
|
||||
* @return a buffer with *resultCapacity>=minCapacity
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UChar *getAppendBuffer(int32_t minCapacity,
|
||||
int32_t desiredCapacityHint,
|
||||
UChar *scratch, int32_t scratchCapacity,
|
||||
int32_t *resultCapacity) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Default Appendable implementation.
|
||||
* This class provides default implementations for all Appendable methods
|
||||
* except appendCodeUnit(), to make subclassing easy.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
class U_COMMON_API AppendableAdapter : public UObject, public Appendable {
|
||||
public:
|
||||
/**
|
||||
* Appends a code point.
|
||||
* The default implementation calls appendCodeUnit(UChar) once or twice.
|
||||
* @param c code point 0..0x10ffff
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendCodePoint(UChar32 c);
|
||||
|
||||
/**
|
||||
* Appends a string.
|
||||
* The default implementation calls appendCodeUnit(UChar) for each code unit.
|
||||
* @param s string, must not be NULL if length!=0
|
||||
* @param length string length, or -1 if NUL-terminated
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendString(const UChar *s, int32_t length);
|
||||
|
||||
/**
|
||||
* Tells the object that the caller is going to append roughly
|
||||
* appendCapacity UChars. A subclass might use this to pre-allocate
|
||||
* a larger buffer if necessary.
|
||||
* The default implementation does nothing. (It always returns TRUE.)
|
||||
* @param appendCapacity estimated number of UChars that will be appended
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool reserveAppendCapacity(int32_t appendCapacity);
|
||||
|
||||
/**
|
||||
* Returns a writable buffer for appending and writes the buffer's capacity to
|
||||
* *resultCapacity. Guarantees *resultCapacity>=minCapacity.
|
||||
* May return a pointer to the caller-owned scratch buffer which must have
|
||||
* scratchCapacity>=minCapacity.
|
||||
* The returned buffer is only valid until the next operation
|
||||
* on this Appendable.
|
||||
*
|
||||
* For details see Appendable::getAppendBuffer().
|
||||
*
|
||||
* The default implementation always returns the scratch buffer.
|
||||
*
|
||||
* @param minCapacity required minimum capacity of the returned buffer;
|
||||
* must be non-negative
|
||||
* @param desiredCapacityHint desired capacity of the returned buffer;
|
||||
* must be non-negative
|
||||
* @param scratch default caller-owned buffer
|
||||
* @param scratchCapacity capacity of the scratch buffer
|
||||
* @param resultCapacity pointer to an integer which will be set to the
|
||||
* capacity of the returned buffer
|
||||
* @return a buffer with *resultCapacity>=minCapacity
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UChar *getAppendBuffer(int32_t minCapacity,
|
||||
int32_t desiredCapacityHint,
|
||||
UChar *scratch, int32_t scratchCapacity,
|
||||
int32_t *resultCapacity);
|
||||
|
||||
private:
|
||||
// No ICU "poor man's RTTI" for this class nor its subclasses.
|
||||
virtual UClassID getDynamicClassID() const;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif // __APPENDABLE_H__
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 1998-2010, International Business Machines
|
||||
* Copyright (C) 1998-2011, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*
|
||||
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/appendable.h"
|
||||
#include "unicode/rep.h"
|
||||
#include "unicode/std_string.h"
|
||||
#include "unicode/stringpiece.h"
|
||||
|
@ -184,7 +185,7 @@ class BreakIterator; // unicode/brkiter.h
|
|||
* @see CharacterIterator
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
class U_COMMON_API UnicodeString : public Replaceable
|
||||
class U_COMMON_API UnicodeString : public Replaceable, public Appendable
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -2035,7 +2036,7 @@ public:
|
|||
* @param srcStart the offset into <TT>srcChars</TT> where new characters
|
||||
* will be obtained
|
||||
* @param srcLength the number of characters in <TT>srcChars</TT> in
|
||||
* the append string
|
||||
* the append string; can be -1 if <TT>srcChars</TT> is NUL-terminated
|
||||
* @return a reference to this
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
|
@ -2047,7 +2048,8 @@ public:
|
|||
* Append the characters in <TT>srcChars</TT> to the UnicodeString object
|
||||
* at offset <TT>start</TT>. <TT>srcChars</TT> is not modified.
|
||||
* @param srcChars the source for the new characters
|
||||
* @param srcLength the number of Unicode characters in <TT>srcChars</TT>
|
||||
* @param srcLength the number of Unicode characters in <TT>srcChars</TT>;
|
||||
* can be -1 if <TT>srcChars</TT> is NUL-terminated
|
||||
* @return a reference to this
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
|
@ -2070,6 +2072,46 @@ public:
|
|||
*/
|
||||
inline UnicodeString& append(UChar32 srcChar);
|
||||
|
||||
/**
|
||||
* Appends a 16-bit code unit.
|
||||
* Equivalent to
|
||||
* \code
|
||||
* return !append(c).isBogus();
|
||||
* \endcode
|
||||
* (Implements Appendable.)
|
||||
* @param c code unit
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendCodeUnit(UChar c);
|
||||
|
||||
/**
|
||||
* Appends a code point.
|
||||
* Equivalent to
|
||||
* \code
|
||||
* return !append(c).isBogus();
|
||||
* \endcode
|
||||
* (Implements Appendable.)
|
||||
* @param c code point 0..0x10ffff
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendCodePoint(UChar32 c);
|
||||
|
||||
/**
|
||||
* Appends a string.
|
||||
* Equivalent to
|
||||
* \code
|
||||
* return !append(s, length).isBogus();
|
||||
* \endcode
|
||||
* (Implements Appendable.)
|
||||
* @param s string, must not be NULL if length!=0
|
||||
* @param length string length, or -1 if NUL-terminated
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool appendString(const UChar *s, int32_t length);
|
||||
|
||||
|
||||
/* Insert operations */
|
||||
|
||||
|
@ -2781,6 +2823,43 @@ public:
|
|||
*/
|
||||
inline const UChar *getTerminatedBuffer();
|
||||
|
||||
/**
|
||||
* Tells the UnicodeString that the caller is going to append roughly
|
||||
* appendCapacity UChars.
|
||||
* (Implements Appendable.)
|
||||
* @param appendCapacity estimated number of UChars that will be appended
|
||||
* @return TRUE if the operation succeeded
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UBool reserveAppendCapacity(int32_t appendCapacity);
|
||||
|
||||
/**
|
||||
* Returns a writable buffer for appending and writes the buffer's capacity to
|
||||
* *resultCapacity. Guarantees *resultCapacity>=minCapacity.
|
||||
* May return a pointer to the caller-owned scratch buffer which must have
|
||||
* scratchCapacity>=minCapacity.
|
||||
* The returned buffer is only valid until the next operation
|
||||
* on this UnicodeString.
|
||||
*
|
||||
* (Implements Appendable.)
|
||||
* For details see Appendable::getAppendBuffer().
|
||||
*
|
||||
* @param minCapacity required minimum capacity of the returned buffer;
|
||||
* must be non-negative
|
||||
* @param desiredCapacityHint desired capacity of the returned buffer;
|
||||
* must be non-negative
|
||||
* @param scratch default caller-owned buffer
|
||||
* @param scratchCapacity capacity of the scratch buffer
|
||||
* @param resultCapacity pointer to an integer which will be set to the
|
||||
* capacity of the returned buffer
|
||||
* @return a buffer with *resultCapacity>=minCapacity
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
virtual UChar *getAppendBuffer(int32_t minCapacity,
|
||||
int32_t desiredCapacityHint,
|
||||
UChar *scratch, int32_t scratchCapacity,
|
||||
int32_t *resultCapacity);
|
||||
|
||||
//========================================
|
||||
// Constructors
|
||||
//========================================
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1999-2010, International Business Machines Corporation and *
|
||||
* Copyright (C) 1999-2011, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -1260,14 +1260,24 @@ UnicodeString::doReplace(int32_t start,
|
|||
}
|
||||
|
||||
// calculate the size of the string after the replace
|
||||
int32_t newSize;
|
||||
int32_t newLength;
|
||||
|
||||
// optimize append() onto a large-enough, owned string
|
||||
if(start >= oldLength) {
|
||||
newSize = oldLength + srcLength;
|
||||
if(newSize <= getCapacity() && isBufferWritable()) {
|
||||
us_arrayCopy(srcChars, srcStart, getArrayStart(), oldLength, srcLength);
|
||||
setLength(newSize);
|
||||
newLength = oldLength + srcLength;
|
||||
if(newLength <= getCapacity() && isBufferWritable()) {
|
||||
UChar *oldArray = getArrayStart();
|
||||
// Do not copy characters when
|
||||
// UChar *buffer=str.getAppendBuffer(...);
|
||||
// is followed by
|
||||
// str.append(buffer, length);
|
||||
// or
|
||||
// str.appendString(buffer, length)
|
||||
// or similar.
|
||||
if(srcChars + srcStart != oldArray + start || start > oldLength) {
|
||||
us_arrayCopy(srcChars, srcStart, oldArray, oldLength, srcLength);
|
||||
}
|
||||
setLength(newLength);
|
||||
return *this;
|
||||
} else {
|
||||
// pin the indices to legal values
|
||||
|
@ -1278,14 +1288,14 @@ UnicodeString::doReplace(int32_t start,
|
|||
// pin the indices to legal values
|
||||
pinIndices(start, length);
|
||||
|
||||
newSize = oldLength - length + srcLength;
|
||||
newLength = oldLength - length + srcLength;
|
||||
}
|
||||
|
||||
// the following may change fArray but will not copy the current contents;
|
||||
// therefore we need to keep the current fArray
|
||||
UChar oldStackBuffer[US_STACKBUF_SIZE];
|
||||
UChar *oldArray;
|
||||
if((fFlags&kUsingStackBuffer) && (newSize > US_STACKBUF_SIZE)) {
|
||||
if((fFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) {
|
||||
// copy the stack buffer contents because it will be overwritten with
|
||||
// fUnion.fFields values
|
||||
u_memcpy(oldStackBuffer, fUnion.fStackBuffer, oldLength);
|
||||
|
@ -1296,7 +1306,7 @@ UnicodeString::doReplace(int32_t start,
|
|||
|
||||
// clone our array and allocate a bigger array if needed
|
||||
int32_t *bufferToDelete = 0;
|
||||
if(!cloneArrayIfNeeded(newSize, newSize + (newSize >> 2) + kGrowSize,
|
||||
if(!cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize,
|
||||
FALSE, &bufferToDelete)
|
||||
) {
|
||||
return *this;
|
||||
|
@ -1321,7 +1331,7 @@ UnicodeString::doReplace(int32_t start,
|
|||
// now fill in the hole with the new string
|
||||
us_arrayCopy(srcChars, srcStart, newArray, start, srcLength);
|
||||
|
||||
setLength(newSize);
|
||||
setLength(newLength);
|
||||
|
||||
// delayed delete in case srcChars == fArray when we started, and
|
||||
// to keep oldArray alive for the above operations
|
||||
|
@ -1332,6 +1342,28 @@ UnicodeString::doReplace(int32_t start,
|
|||
return *this;
|
||||
}
|
||||
|
||||
// Implements Appendable.
|
||||
UBool
|
||||
UnicodeString::appendCodeUnit(UChar c) {
|
||||
return doReplace(length(), 0, &c, 0, 1).isWritable();
|
||||
}
|
||||
|
||||
// Implements Appendable.
|
||||
UBool
|
||||
UnicodeString::appendCodePoint(UChar32 c) {
|
||||
UChar buffer[U16_MAX_LENGTH];
|
||||
int32_t cLength = 0;
|
||||
UBool isError = FALSE;
|
||||
U16_APPEND(buffer, cLength, U16_MAX_LENGTH, c, isError);
|
||||
return !isError && doReplace(length(), 0, buffer, 0, cLength).isWritable();
|
||||
}
|
||||
|
||||
// Implements Appendable.
|
||||
UBool
|
||||
UnicodeString::appendString(const UChar *s, int32_t sLength) {
|
||||
return doReplace(length(), 0, s, 0, sLength).isWritable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable API
|
||||
*/
|
||||
|
@ -1513,6 +1545,25 @@ UnicodeString::releaseBuffer(int32_t newLength) {
|
|||
}
|
||||
}
|
||||
|
||||
// Implements Appendable.
|
||||
UChar *
|
||||
UnicodeString::getAppendBuffer(int32_t minCapacity,
|
||||
int32_t desiredCapacityHint,
|
||||
UChar *scratch, int32_t scratchCapacity,
|
||||
int32_t *resultCapacity) {
|
||||
if(minCapacity < 1 || scratchCapacity < minCapacity) {
|
||||
*resultCapacity = 0;
|
||||
return NULL;
|
||||
}
|
||||
int32_t oldLength = length();
|
||||
if(cloneArrayIfNeeded(oldLength + minCapacity, oldLength + desiredCapacityHint)) {
|
||||
*resultCapacity = getCapacity() - oldLength;
|
||||
return getArrayStart() + oldLength;
|
||||
}
|
||||
*resultCapacity = scratchCapacity;
|
||||
return scratch;
|
||||
}
|
||||
|
||||
//========================================
|
||||
// Miscellaneous
|
||||
//========================================
|
||||
|
@ -1616,6 +1667,13 @@ UnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Implements Appendable.
|
||||
UBool
|
||||
UnicodeString::reserveAppendCapacity(int32_t appendCapacity) {
|
||||
return cloneArrayIfNeeded(length() + appendCapacity);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#ifdef U_STATIC_IMPLEMENTATION
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "unicode/utypes.h"
|
||||
#include "unicode/localpointer.h"
|
||||
#include "unicode/uniset.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "ucharstrie.h"
|
||||
#include "ucharstriebuilder.h"
|
||||
#include "intltest.h"
|
||||
|
@ -494,23 +495,13 @@ void UCharsTrieTest::TestHasUniqueValue() {
|
|||
}
|
||||
}
|
||||
|
||||
class UnicodeStringAppendable : public Appendable {
|
||||
public:
|
||||
UnicodeStringAppendable(UnicodeString &dest) : str(dest) {}
|
||||
virtual Appendable &append(UChar c) { str.append(c); return *this; }
|
||||
UnicodeStringAppendable &reset() { str.remove(); return *this; }
|
||||
private:
|
||||
UnicodeString &str;
|
||||
};
|
||||
|
||||
void UCharsTrieTest::TestGetNextUChars() {
|
||||
LocalPointer<UCharsTrie> trie(buildMonthsTrie(USTRINGTRIE_BUILD_SMALL));
|
||||
if(trie.isNull()) {
|
||||
return; // buildTrie() reported an error
|
||||
}
|
||||
UnicodeString buffer;
|
||||
UnicodeStringAppendable app(buffer);
|
||||
int32_t count=trie->getNextUChars(app);
|
||||
int32_t count=trie->getNextUChars(buffer);
|
||||
if(count!=2 || buffer.length()!=2 || buffer[0]!=u_a || buffer[1]!=u_j) {
|
||||
errln("months getNextUChars()!=[aj] at root");
|
||||
}
|
||||
|
@ -518,31 +509,31 @@ void UCharsTrieTest::TestGetNextUChars() {
|
|||
trie->next(u_a);
|
||||
trie->next(u_n);
|
||||
// getNextUChars() directly after next()
|
||||
count=trie->getNextUChars(app.reset());
|
||||
count=trie->getNextUChars(buffer.remove());
|
||||
if(count!=20 || buffer!=UNICODE_STRING_SIMPLE(".abcdefghijklmnopqru")) {
|
||||
errln("months getNextUChars()!=[.abcdefghijklmnopqru] after \"jan\"");
|
||||
}
|
||||
// getNextUChars() after getValue()
|
||||
trie->getValue(); // next() had returned USTRINGTRIE_INTERMEDIATE_VALUE.
|
||||
count=trie->getNextUChars(app.reset());
|
||||
count=trie->getNextUChars(buffer.remove());
|
||||
if(count!=20 || buffer!=UNICODE_STRING_SIMPLE(".abcdefghijklmnopqru")) {
|
||||
errln("months getNextUChars()!=[.abcdefghijklmnopqru] after \"jan\"+getValue()");
|
||||
}
|
||||
// getNextUChars() from a linear-match node
|
||||
trie->next(u_u);
|
||||
count=trie->getNextUChars(app.reset());
|
||||
count=trie->getNextUChars(buffer.remove());
|
||||
if(count!=1 || buffer.length()!=1 || buffer[0]!=u_a) {
|
||||
errln("months getNextUChars()!=[a] after \"janu\"");
|
||||
}
|
||||
trie->next(u_a);
|
||||
count=trie->getNextUChars(app.reset());
|
||||
count=trie->getNextUChars(buffer.remove());
|
||||
if(count!=1 || buffer.length()!=1 || buffer[0]!=u_r) {
|
||||
errln("months getNextUChars()!=[r] after \"janua\"");
|
||||
}
|
||||
trie->next(u_r);
|
||||
trie->next(u_y);
|
||||
// getNextUChars() after a final match
|
||||
count=trie->getNextUChars(app.reset());
|
||||
count=trie->getNextUChars(buffer.remove());
|
||||
if(count!=0 || buffer.length()!=0) {
|
||||
errln("months getNextUChars()!=[] after \"january\"");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2010, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
* Copyright (C) 2010 , Yahoo! Inc.
|
||||
********************************************************************/
|
||||
|
@ -249,6 +249,7 @@ UObject *UObjectTest::testClassNoClassID(UObject *obj, const char *className, co
|
|||
#include "reldtfmt.h"
|
||||
|
||||
// External Things
|
||||
#include "unicode/appendable.h"
|
||||
#include "unicode/brkiter.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "unicode/caniter.h"
|
||||
|
@ -311,6 +312,12 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
// AppendableAdapter is abstract; we define a subclass to verify that there is no "poor man's RTTI".
|
||||
class DummyAppendable : public AppendableAdapter {
|
||||
public:
|
||||
virtual UBool appendCodeUnit(UChar /*c*/) { return TRUE; }
|
||||
};
|
||||
|
||||
void UObjectTest::testIDs()
|
||||
{
|
||||
ids_count = 0;
|
||||
|
@ -445,7 +452,8 @@ void UObjectTest::testIDs()
|
|||
TESTCLASSID_FACTORY(OlsonTimeZone, TimeZone::createTimeZone(UnicodeString("America/Los_Angeles")));
|
||||
TESTCLASSID_FACTORY_HIDDEN(KeywordEnumeration, TimeZone::createEnumeration());
|
||||
#endif
|
||||
|
||||
|
||||
TESTCLASSID_NONE_DEFAULT(DummyAppendable);
|
||||
TESTCLASSID_DEFAULT(UnicodeString);
|
||||
TESTCLASSID_CTOR(UnicodeSet, (0, 1));
|
||||
TESTCLASSID_ABSTRACT(UnicodeFilter);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2010, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
#include "ustrtest.h"
|
||||
#include "unicode/appendable.h"
|
||||
#include "unicode/std_string.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/uchar.h"
|
||||
|
@ -62,6 +63,8 @@ void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &
|
|||
case 17: name = "TestUTF32"; if (exec) TestUTF32(); break;
|
||||
case 18: name = "TestUTF8"; if (exec) TestUTF8(); break;
|
||||
case 19: name = "TestReadOnlyAlias"; if (exec) TestReadOnlyAlias(); break;
|
||||
case 20: name = "TestAppendable"; if (exec) TestAppendable(); break;
|
||||
case 21: name = "TestUnicodeStringImplementsAppendable"; if (exec) TestUnicodeStringImplementsAppendable(); break;
|
||||
|
||||
default: name = ""; break; //needed to end loop
|
||||
}
|
||||
|
@ -2013,3 +2016,61 @@ UnicodeStringTest::TestReadOnlyAlias() {
|
|||
errln("UnicodeString.setToBogus().tempSubStringBetween(8, 18) failed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UnicodeStringTest::doTestAppendable(UnicodeString &dest, Appendable &app) {
|
||||
static const UChar cde[3]={ 0x63, 0x64, 0x65 };
|
||||
static const UChar fg[3]={ 0x66, 0x67, 0 };
|
||||
if(!app.reserveAppendCapacity(12)) {
|
||||
errln("Appendable.reserve(12) failed");
|
||||
}
|
||||
app.appendCodeUnit(0x61);
|
||||
app.appendCodePoint(0x62);
|
||||
app.appendCodePoint(0x50000);
|
||||
app.appendString(cde, 3);
|
||||
app.appendString(fg, -1);
|
||||
UChar scratch[3];
|
||||
int32_t capacity=-1;
|
||||
UChar *buffer=app.getAppendBuffer(3, 3, scratch, 3, &capacity);
|
||||
if(capacity<3) {
|
||||
errln("Appendable.getAppendBuffer(min=3) returned capacity=%d<3", (int)capacity);
|
||||
return;
|
||||
}
|
||||
static const UChar hij[3]={ 0x68, 0x69, 0x6a };
|
||||
u_memcpy(buffer, hij, 3);
|
||||
app.appendString(buffer, 3);
|
||||
if(dest!=UNICODE_STRING_SIMPLE("ab\\U00050000cdefghij").unescape()) {
|
||||
errln("Appendable.append(...) failed");
|
||||
}
|
||||
buffer=app.getAppendBuffer(0, 3, scratch, 3, &capacity);
|
||||
if(buffer!=NULL || capacity!=0) {
|
||||
errln("Appendable.getAppendBuffer(min=0) failed");
|
||||
}
|
||||
capacity=1;
|
||||
buffer=app.getAppendBuffer(3, 3, scratch, 2, &capacity);
|
||||
if(buffer!=NULL || capacity!=0) {
|
||||
errln("Appendable.getAppendBuffer(scratch<min) failed");
|
||||
}
|
||||
}
|
||||
|
||||
class UnicodeStringAppendable : public AppendableAdapter {
|
||||
public:
|
||||
UnicodeStringAppendable(UnicodeString &dest) : str(dest) {}
|
||||
virtual UBool appendCodeUnit(UChar c) { str.append(c); return TRUE; }
|
||||
UnicodeStringAppendable &reset() { str.remove(); return *this; }
|
||||
private:
|
||||
UnicodeString &str;
|
||||
};
|
||||
|
||||
void
|
||||
UnicodeStringTest::TestAppendable() {
|
||||
UnicodeString dest;
|
||||
UnicodeStringAppendable app(dest);
|
||||
doTestAppendable(dest, app);
|
||||
}
|
||||
|
||||
void
|
||||
UnicodeStringTest::TestUnicodeStringImplementsAppendable() {
|
||||
UnicodeString dest;
|
||||
doTestAppendable(dest, dest);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2010, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2011, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
|
@ -10,6 +10,12 @@
|
|||
#include "unicode/unistr.h"
|
||||
#include "intltest.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class Appendable;
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
/**
|
||||
* Perform API and functionality tests for class UnicodeString
|
||||
**/
|
||||
|
@ -70,13 +76,16 @@ public:
|
|||
void TestUnescape(void);
|
||||
|
||||
void _testUnicodeStringHasMoreChar32Than(const UnicodeString &s, int32_t start, int32_t length, int32_t number);
|
||||
void TestCountChar32(void);
|
||||
void TestCountChar32();
|
||||
void TestBogus();
|
||||
void TestStringEnumeration();
|
||||
void TestNameSpace(void);
|
||||
void TestUTF32(void);
|
||||
void TestUTF8(void);
|
||||
void TestReadOnlyAlias(void);
|
||||
void TestNameSpace();
|
||||
void TestUTF32();
|
||||
void TestUTF8();
|
||||
void TestReadOnlyAlias();
|
||||
void doTestAppendable(UnicodeString &dest, Appendable &app);
|
||||
void TestAppendable();
|
||||
void TestUnicodeStringImplementsAppendable();
|
||||
};
|
||||
|
||||
class StringCaseTest: public IntlTest {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/appendable.h"
|
||||
#include "unicode/uobject.h"
|
||||
#include "cmemory.h"
|
||||
#include "uassert.h"
|
||||
|
@ -20,35 +21,6 @@
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
Appendable &
|
||||
Appendable::appendCodePoint(UChar32 c) {
|
||||
if(c<=0xffff) {
|
||||
return append((UChar)c);
|
||||
} else {
|
||||
return append(U16_LEAD(c)).append(U16_TRAIL(c));
|
||||
}
|
||||
}
|
||||
|
||||
Appendable &
|
||||
Appendable::append(const UChar *s, int32_t length) {
|
||||
if(s!=NULL && length!=0) {
|
||||
if(length<0) {
|
||||
UChar c;
|
||||
while((c=*s++)!=0) {
|
||||
append(c);
|
||||
}
|
||||
} else {
|
||||
const UChar *limit=s+length;
|
||||
while(s<limit) {
|
||||
append(*s++);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(Appendable)
|
||||
|
||||
UCharsTrie::~UCharsTrie() {
|
||||
uprv_free(ownedArray_);
|
||||
}
|
||||
|
@ -376,7 +348,7 @@ UCharsTrie::getNextUChars(Appendable &out) const {
|
|||
return 0;
|
||||
}
|
||||
if(remainingMatchLength_>=0) {
|
||||
out.append(*pos); // Next unit of a pending linear-match node.
|
||||
out.appendCodeUnit(*pos); // Next unit of a pending linear-match node.
|
||||
return 1;
|
||||
}
|
||||
int32_t node=*pos++;
|
||||
|
@ -392,11 +364,12 @@ UCharsTrie::getNextUChars(Appendable &out) const {
|
|||
if(node==0) {
|
||||
node=*pos++;
|
||||
}
|
||||
getNextBranchUChars(pos, ++node, out);
|
||||
out.reserveAppendCapacity(++node);
|
||||
getNextBranchUChars(pos, node, out);
|
||||
return node;
|
||||
} else {
|
||||
// First unit of the linear-match node.
|
||||
out.append(*pos);
|
||||
out.appendCodeUnit(*pos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -410,10 +383,10 @@ UCharsTrie::getNextBranchUChars(const UChar *pos, int32_t length, Appendable &ou
|
|||
pos=skipDelta(pos);
|
||||
}
|
||||
do {
|
||||
out.append(*pos++);
|
||||
out.appendCodeUnit(*pos++);
|
||||
pos=skipValue(pos);
|
||||
} while(--length>1);
|
||||
out.append(*pos);
|
||||
out.appendCodeUnit(*pos);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -29,44 +29,10 @@
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class Appendable;
|
||||
class UCharsTrieBuilder;
|
||||
class UVector32;
|
||||
|
||||
/**
|
||||
* Base class for objects to which Unicode characters and strings can be appended.
|
||||
* Combines elements of Java Appendable and ICU4C ByteSink.
|
||||
* TODO: Should live in separate files, could be public API.
|
||||
*/
|
||||
class U_TOOLUTIL_API Appendable : public UObject {
|
||||
public:
|
||||
/**
|
||||
* Appends a 16-bit code unit.
|
||||
* @param c code unit
|
||||
* @return *this
|
||||
*/
|
||||
virtual Appendable &append(UChar c) = 0;
|
||||
/**
|
||||
* Appends a code point; has a default implementation.
|
||||
* @param c code point
|
||||
* @return *this
|
||||
*/
|
||||
virtual Appendable &appendCodePoint(UChar32 c);
|
||||
/**
|
||||
* Appends a string; has a default implementation.
|
||||
* @param s string
|
||||
* @param length string length, or -1 if NUL-terminated
|
||||
* @return *this
|
||||
*/
|
||||
virtual Appendable &append(const UChar *s, int32_t length);
|
||||
|
||||
// TODO: getAppendBuffer(), see ByteSink
|
||||
// TODO: flush() (?) see ByteSink
|
||||
|
||||
private:
|
||||
// No ICU "poor man's RTTI" for this class nor its subclasses.
|
||||
virtual UClassID getDynamicClassID() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Light-weight, non-const reader class for a UCharsTrie.
|
||||
* Traverses a UChar-serialized data structure with minimal state,
|
||||
|
@ -263,7 +229,6 @@ public:
|
|||
* Finds each UChar which continues the string from the current state.
|
||||
* That is, each UChar c for which it would be next(c)!=USTRINGTRIE_NO_MATCH now.
|
||||
* @param out Each next UChar is appended to this object.
|
||||
* (Only uses the out.append(c) method.)
|
||||
* @return the number of UChars which continue the string from here
|
||||
*/
|
||||
int32_t getNextUChars(Appendable &out) const;
|
||||
|
|
Loading…
Add table
Reference in a new issue