/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
template <int SIZE> static StringBuffer apply_format_string(constchar* format, va_list args, char (&stackBuffer)[SIZE],
SkString* heapBuffer) { // First, attempt to print directly to the stack buffer.
va_list argsCopy;
va_copy(argsCopy, args); int outLength = std::vsnprintf(stackBuffer, SIZE, format, args); if (outLength < 0) {
SkDebugf("SkString: vsnprintf reported error.");
va_end(argsCopy); return {stackBuffer, 0};
} if (outLength < SIZE) {
va_end(argsCopy); return {stackBuffer, outLength};
}
// Our text was too long to fit on the stack! However, we now know how much space we need to // format it. Format the string into our heap buffer. `set` automatically reserves an extra // byte at the end of the buffer for a null terminator, so we don't need to add one here.
heapBuffer->set(nullptr, outLength); char* heapBufferDest = heapBuffer->data();
SkDEBUGCODE(int checkLength =) std::vsnprintf(heapBufferDest, outLength + 1, format, argsCopy);
SkASSERT(checkLength == outLength);
va_end(argsCopy); return {heapBufferDest, outLength};
}
char* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
uint64_t udec = dec; if (dec < 0) {
*string++ = '-';
udec = ~udec + 1; // udec = -udec, but silences some warnings that are trying to be helpful
} return SkStrAppendU64(string, udec, minDigits);
}
char* SkStrAppendScalar(char string[], SkScalar value) { // Handle infinity and NaN ourselves to ensure consistent cross-platform results. // (e.g.: `inf` versus `1.#INF00`, `nan` versus `-nan` for high-bit-set NaNs) if (SkIsNaN(value)) {
strcpy(string, "nan"); return string + 3;
} if (!SkIsFinite(value)) { if (value > 0) {
strcpy(string, "inf"); return string + 3;
} else {
strcpy(string, "-inf"); return string + 4;
}
}
// since floats have at most 8 significant digits, we limit our %g to that. staticconstchar gFormat[] = "%.8g"; // make it 1 larger for the terminating 0 char buffer[kSkStrAppendScalar_MaxSize + 1]; int len = snprintf(buffer, sizeof(buffer), gFormat, value);
memcpy(string, buffer, len);
SkASSERT(len <= kSkStrAppendScalar_MaxSize); return string + len;
}
SkSafeMath safe; // We store a 32bit version of the length
uint32_t stringLen = safe.castTo<uint32_t>(len); // Add SizeOfRec() for our overhead and 1 for null-termination
size_t allocationSize = safe.add(len, SizeOfRec() + sizeof(char)); // Align up to a multiple of 4
allocationSize = safe.alignUp(allocationSize, 4);
const SkString& SkString::validate() const { // make sure no one has written over our global
SkASSERT(0 == gEmptyRec.fLength);
SkASSERT(0 == gEmptyRec.getRefCnt());
SkASSERT(0 == gEmptyRec.data()[0]);
// Check if length + len exceeds 32bits, we trim len
len = check_add32(length, len); if (0 == len) { return;
}
/* If we're the only owner, and we have room in our allocation for the insert, do it in place, rather than allocating a new buffer.
To know we have room, compare the allocated sizes beforeAlloc = SkAlign4(length + 1) afterAlloc = SkAligh4(length + 1 + len) but SkAlign4(x) is (x + 3) >> 2 << 2 which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2 and we can then eliminate the +1+3 since that doesn't affec the answer
*/ if (fRec->unique() && (length >> 2) == ((length + len) >> 2)) { char* dst = this->data();
dst[length + len] = 0;
fRec->fLength = SkToU32(length + len);
} else { /* Seems we should use realloc here, since that is safe if it fails (we have the original data), and might be faster than alloc/copy/free.
*/
SkString tmp(fRec->fLength + len); char* dst = tmp.data();
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.