int32_t
UnicodeString::extract(int32_t start,
int32_t length,
char *target,
uint32_t dstSize, const char *codepage) const
{ // if the arguments are illegal, then do nothing
if (/*dstSize < 0 || */(dstSize > 0 && target == nullptr)) { return0;
}
// pin the indices to legal values
pinIndices(start, length);
// We need to cast dstSize to int32_t for all subsequent code. // I don't know why the API was defined with uint32_t but we are stuck with it. // Also, dstSize==0xffffffff means "unlimited" but if we use target+dstSize // as a limit in some functions, it may wrap around and yield a pointer // that compares less-than target.
int32_t capacity;
if(dstSize < 0x7fffffff) { // Assume that the capacity is real and a limit pointer won't wrap around.
capacity = static_cast<int32_t>(dstSize);
} else { // Pin the capacity so that a limit pointer does not wrap around.
char* targetLimit = static_cast<char*>(U_MAX_PTR(target)); // U_MAX_PTR(target) returns a targetLimit that is at most 0x7fffffff // greater than target and does not wrap around the top of the address space.
capacity = static_cast<int32_t>(targetLimit - target);
}
// create the converter
UConverter *converter;
UErrorCode status = U_ZERO_ERROR;
// just write the NUL if the string length is 0
if(length == 0) { return u_terminateChars(target, capacity, 0, &status);
}
// if the codepage is the default, use our cache // if it is an empty string, then use the "invariant character" conversion
if (codepage == nullptr) { const char *defaultName = ucnv_getDefaultName();
if(UCNV_FAST_IS_UTF8(defaultName)) { return toUTF8(start, length, target, capacity);
}
converter = u_getDefaultConverter(&status);
} else if (*codepage == 0) { // use the "invariant characters" conversion
int32_t destLength;
if(length <= capacity) {
destLength = length;
} else {
destLength = capacity;
}
u_UCharsToChars(getArrayStart() + start, target, destLength); return u_terminateChars(target, capacity, length, &status);
} else {
converter = ucnv_open(codepage, &status);
}
if(destCapacity==0) {
destLimit=dest=nullptr;
} else if(destCapacity==-1) { // Pin the limit to U_MAX_PTR if the "magic" destCapacity is used.
destLimit = static_cast<char*>(U_MAX_PTR(dest)); // for NUL-termination, translate into highest int32_t
destCapacity=0x7fffffff;
} else {
destLimit=dest+destCapacity;
}
// create the converter // if the codepage is the default, use our cache // if it is an empty string, then use the "invariant character" conversion
UConverter *converter;
if (codepage == nullptr) { const char *defaultName = ucnv_getDefaultName();
if(UCNV_FAST_IS_UTF8(defaultName)) {
setToUTF8(StringPiece(codepageData, dataLength)); return;
}
converter = u_getDefaultConverter(&status);
} else if (*codepage == 0) { // use the "invariant characters" conversion
if(cloneArrayIfNeeded(dataLength, dataLength, false)) {
u_charsToUChars(codepageData, getArrayStart(), dataLength);
setLength(dataLength);
} else {
setToBogus();
} return;
} else {
converter = ucnv_open(codepage, &status);
}
// if we failed, set the appropriate flags and return
if(U_FAILURE(status)) {
setToBogus(); return;
}
// set up the conversion parameters const char *mySource = codepageData; const char *mySourceEnd = mySource + dataLength;
char16_t *array, *myTarget;
// estimate the size needed:
int32_t arraySize;
if(dataLength <= US_STACKBUF_SIZE) { // try to use the stack buffer
arraySize = US_STACKBUF_SIZE;
} else { // 1.25 char16_t's per source byte should cover most cases
arraySize = dataLength + (dataLength >> 2);
}
// we do not care about the current contents
UBool doCopyArray = false;
for(;;) {
if(!cloneArrayIfNeeded(arraySize, arraySize, doCopyArray)) {
setToBogus(); break;
}
// update the conversion parameters
setLength(static_cast<int32_t>(myTarget - array));
// allocate more space and copy data, if needed
if(bufferStatus == U_BUFFER_OVERFLOW_ERROR) { // keep the previous conversion results
doCopyArray = true;
// estimate the new size needed, larger than before // try 2 char16_t's per remaining source byte
arraySize = static_cast<int32_t>(length() + 2 * (mySourceEnd - mySource));
} else {
if (U_FAILURE(bufferStatus)) {
status = bufferStatus;
} break;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.