String Color::serialized() const { if (!hasAlpha()) { StringBuilder builder; builder.reserveCapacity(7); builder.append('#'); appendByteAsHex(red(), builder, Lowercase); appendByteAsHex(green(), builder, Lowercase); appendByteAsHex(blue(), builder, Lowercase); return builder.toString(); } StringBuilder result; result.reserveCapacity(28); result.appendLiteral("rgba("); result.appendNumber(red()); result.appendLiteral(", "); result.appendNumber(green()); result.appendLiteral(", "); result.appendNumber(blue()); result.appendLiteral(", "); if (!alpha()) result.append('0'); else { result.append(Decimal::fromDouble(alpha() / 255.0).toString()); } result.append(')'); return result.toString(); }
String Locale::convertFromLocalizedNumber(const String& localized) { initializeLocaleData(); String input = localized.removeCharacters(isASCIISpace); if (!m_hasLocaleData || input.isEmpty()) return input; bool isNegative; unsigned startIndex; unsigned endIndex; if (!detectSignAndGetDigitRange(input, isNegative, startIndex, endIndex)) return input; StringBuilder builder; builder.reserveCapacity(input.length()); if (isNegative) builder.append('-'); for (unsigned i = startIndex; i < endIndex;) { unsigned symbolIndex = matchedDecimalSymbolIndex(input, i); if (symbolIndex >= DecimalSymbolsSize) return input; if (symbolIndex == DecimalSeparatorIndex) builder.append('.'); else if (symbolIndex == GroupSeparatorIndex) return input; else builder.append(static_cast<UChar>('0' + symbolIndex)); } return builder.toString(); }
String Text::wholeText() const { const Text* startText = earliestLogicallyAdjacentTextNode(this); const Text* endText = latestLogicallyAdjacentTextNode(this); Node* onePastEndText = endText->nextSibling(); unsigned resultLength = 0; for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) { if (!n->isTextNode()) continue; const String& data = toText(n)->data(); if (std::numeric_limits<unsigned>::max() - data.length() < resultLength) CRASH(); resultLength += data.length(); } StringBuilder result; result.reserveCapacity(resultLength); for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) { if (!n->isTextNode()) continue; result.append(toText(n)->data()); } ASSERT(result.length() == resultLength); return result.toString(); }
void PagePopupClient::addJavaScriptString(const String& str, SharedBuffer* data) { addLiteral("\"", data); StringBuilder builder; builder.reserveCapacity(str.length()); for (unsigned i = 0; i < str.length(); ++i) { if (str[i] == '\r') { builder.append("\\r"); } else if (str[i] == '\n') { builder.append("\\n"); } else if (str[i] == '\\' || str[i] == '"') { builder.append('\\'); builder.append(str[i]); } else if (str[i] == '<') { // Need to avoid to add "</script>" because the resultant string is // typically embedded in <script>. builder.append("\\x3C"); } else if (str[i] < 0x20 || str[i] == lineSeparator || str[i] == paragraphSeparator) { builder.append(String::format("\\u%04X", str[i])); } else { builder.append(str[i]); } } addString(builder.toString(), data); addLiteral("\"", data); }
String extractMIMETypeFromMediaType(const String& mediaType) { StringBuilder mimeType; unsigned length = mediaType.length(); mimeType.reserveCapacity(length); for (unsigned i = 0; i < length; i++) { UChar c = mediaType[i]; if (c == ';') break; // While RFC 2616 does not allow it, other browsers allow multiple values in the HTTP media // type header field, Content-Type. In such cases, the media type string passed here may contain // the multiple values separated by commas. For now, this code ignores text after the first comma, // which prevents it from simply failing to parse such types altogether. Later for better // compatibility we could consider using the first or last valid MIME type instead. // See https://bugs.webkit.org/show_bug.cgi?id=25352 for more discussion. if (c == ',') break; // FIXME: The following is not correct. RFC 2616 allows linear white space before and // after the MIME type, but not within the MIME type itself. And linear white space // includes only a few specific ASCII characters; a small subset of isSpaceOrNewline. // See https://bugs.webkit.org/show_bug.cgi?id=8644 for a bug tracking part of this. if (isSpaceOrNewline(c)) continue; mimeType.append(c); } if (mimeType.length() == length) return mediaType; return mimeType.toString(); }
String Color::serializedAsCSSComponentValue() const { StringBuilder result; result.reserveCapacity(32); bool colorHasAlpha = hasAlpha(); if (colorHasAlpha) result.appendLiteral("rgba("); else result.appendLiteral("rgb("); result.appendNumber(static_cast<unsigned char>(red())); result.appendLiteral(", "); result.appendNumber(static_cast<unsigned char>(green())); result.appendLiteral(", "); result.appendNumber(static_cast<unsigned char>(blue())); if (colorHasAlpha) { result.appendLiteral(", "); NumberToStringBuffer buffer; const char* alphaString = numberToFixedPrecisionString(alpha() / 255.0f, 6, buffer, true); result.append(alphaString, strlen(alphaString)); } result.append(')'); return result.toString(); }
String ICULocale::convertFromLocalizedNumber(const String& localized) { initializeDecimalFormat(); String input = localized.stripWhiteSpace(); if (!m_numberFormat || input.isEmpty()) return input; bool isNegative; unsigned startIndex; unsigned endIndex; if (!detectSignAndGetDigitRange(input, isNegative, startIndex, endIndex)) { // Input is broken. Returning an invalid number string. return "*"; } StringBuilder builder; builder.reserveCapacity(input.length()); if (isNegative) builder.append("-"); for (unsigned i = startIndex; i < endIndex;) { unsigned symbolIndex = matchedDecimalSymbolIndex(input, i); if (symbolIndex >= DecimalSymbolsSize) return "*"; if (symbolIndex == DecimalSeparatorIndex) builder.append('.'); else if (symbolIndex == GroupSeparatorIndex) { // Ignore group separators. } else builder.append(static_cast<UChar>('0' + symbolIndex)); } return builder.toString(); }
String stringValue(Node* node) { switch (node->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::COMMENT_NODE: case Node::TEXT_NODE: case Node::CDATA_SECTION_NODE: case Node::XPATH_NAMESPACE_NODE: return node->nodeValue(); default: if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) { StringBuilder result; result.reserveCapacity(1024); for (Node* n = node->firstChild(); n; n = n->traverseNextNode(node)) { if (n->isTextNode()) { const String& nodeValue = n->nodeValue(); result.append(nodeValue); } } return result.toString(); } } return String(); }
String Text::wholeText() const { const Text* startText = earliestLogicallyAdjacentTextNode(this); const Text* endText = latestLogicallyAdjacentTextNode(this); Node* onePastEndText = endText->nextSibling(); Checked<unsigned> resultLength = 0; for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) { if (!n->isTextNode()) continue; const Text* t = static_cast<const Text*>(n); const String& data = t->data(); resultLength += data.length(); } StringBuilder result; result.reserveCapacity(resultLength.unsafeGet()); for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) { if (!n->isTextNode()) continue; const Text* t = static_cast<const Text*>(n); result.append(t->data()); } ASSERT(result.length() == resultLength.unsafeGet()); return result.toString(); }
String InspectorValue::toJSONString() const { StringBuilder result; result.reserveCapacity(512); writeJSON(&result); return result.toString(); }
String CookieManager::getCookie(const KURL& url, CookieFilter filter) const { // If the database hasn't been sync-ed at this point, force a sync load if (!m_syncedWithDatabase && !m_privateMode) m_cookieBackingStore->openAndLoadDatabaseSynchronously(cookieJar()); Vector<RefPtr<ParsedCookie> > rawCookies; rawCookies.reserveInitialCapacity(s_maxCookieCountPerHost); // Retrieve cookies related to this url getRawCookies(rawCookies, url, filter); CookieLog("CookieManager - there are %d cookies in raw cookies\n", rawCookies.size()); // Generate the cookie header string using the retrieved cookies StringBuilder cookieStringBuilder; cookieStringBuilder.reserveCapacity(512); size_t cookieSize = rawCookies.size(); for (size_t i = 0; i < cookieSize; i++) { cookieStringBuilder.append(rawCookies[i]->toNameValuePair()); if (i != cookieSize-1) cookieStringBuilder.append("; "); } CookieLog("CookieManager - cookieString is - %s\n", cookieStringBuilder.toString().utf8().data()); return cookieStringBuilder.toString(); }
String SVGFontData::createStringWithMirroredCharacters(const String& string) const { if (string.isEmpty()) return emptyString(); unsigned length = string.length(); StringBuilder mirroredCharacters; mirroredCharacters.reserveCapacity(length); if (string.is8Bit()) { const LChar* characters = string.characters8(); for (unsigned i = 0; i < length; ++i) mirroredCharacters.append(mirroredChar(characters[i])); } else { const UChar* characters = string.characters16(); unsigned i = 0; while (i < length) { UChar32 character; U16_NEXT(characters, i, length, character); mirroredCharacters.append(mirroredChar(character)); } } return mirroredCharacters.toString(); }
String CSSQuadValue::customCSSText() const { String top = m_top->cssText(); String right = m_right->cssText(); String bottom = m_bottom->cssText(); String left = m_left->cssText(); if (m_serializationType == TypeForSerialization::SerializeAsRect) return "rect(" + top + ' ' + right + ' ' + bottom + ' ' + left + ')'; StringBuilder result; // reserve space for the four strings, plus three space separator characters. result.reserveCapacity(top.length() + right.length() + bottom.length() + left.length() + 3); result.append(top); if (right != top || bottom != top || left != top) { result.append(' '); result.append(right); if (bottom != top || right != left) { result.append(' '); result.append(bottom); if (left != right) { result.append(' '); result.append(left); } } } return result.toString(); }
String CSSWrapShapePolygon::cssText() const { DEFINE_STATIC_LOCAL(const String, polygonParenEvenOdd, ("polygon(evenodd, ")); DEFINE_STATIC_LOCAL(const String, polygonParenNonZero, ("polygon(nonzero, ")); DEFINE_STATIC_LOCAL(const String, comma, (", ")); StringBuilder result; result.reserveCapacity(32); if (m_windRule == RULE_EVENODD) result.append(polygonParenEvenOdd); else result.append(polygonParenNonZero); ASSERT(!(m_values.size() % 2)); for (unsigned i = 0; i < m_values.size(); i += 2) { if (i) result.append(' '); result.append(m_values.at(i)->cssText()); result.append(comma); result.append(m_values.at(i + 1)->cssText()); } result.append(')'); return result.toString(); }
TEST(StringBuilderTest, ToAtomicString) { StringBuilder builder; builder.append("123"); AtomicString atomicString = builder.toAtomicString(); EXPECT_EQ(String("123"), atomicString); builder.reserveCapacity(256); EXPECT_TRUE(builder.canShrink()); for (int i = builder.length(); i < 128; i++) builder.append('x'); AtomicString atomicString1 = builder.toAtomicString(); EXPECT_EQ(128u, atomicString1.length()); EXPECT_EQ('x', atomicString1[127]); // Later change of builder should not affect the atomic string. for (int i = builder.length(); i < 256; i++) builder.append('x'); EXPECT_EQ(128u, atomicString1.length()); EXPECT_FALSE(builder.canShrink()); String string = builder.toString(); AtomicString atomicString2 = builder.toAtomicString(); // They should share the same StringImpl. EXPECT_EQ(atomicString2.impl(), string.impl()); }
void StyleElement::process(Element* e) { if (!e || !e->inDocument()) return; unsigned resultLength = 0; for (Node* c = e->firstChild(); c; c = c->nextSibling()) { if (isValidStyleChild(c)) { unsigned length = c->nodeValue().length(); if (length > std::numeric_limits<unsigned>::max() - resultLength) { createSheet(e, m_startLineNumber, ""); return; } resultLength += length; } } StringBuilder sheetText; sheetText.reserveCapacity(resultLength); for (Node* c = e->firstChild(); c; c = c->nextSibling()) { if (isValidStyleChild(c)) { sheetText.append(c->nodeValue()); } } ASSERT(sheetText.length() == resultLength); createSheet(e, m_startLineNumber, sheetText.toString()); }
String JSONValue::toPrettyJSONString() const { StringBuilder result; result.reserveCapacity(512); prettyWriteJSON(&result); return result.toString(); }
String HTMLSourceTracker::sourceForToken(const HTMLToken& token) { if (!m_cachedSourceForToken.isEmpty()) return m_cachedSourceForToken; size_t length; if (token.type() == HTMLToken::EndOfFile) { // Consume the remainder of the input, omitting the null character we use to mark the end of the file. length = m_previousSource.length() + m_currentSource.length() - 1; } else { ASSERT(!token.startIndex()); length = static_cast<size_t>(token.endIndex() - token.startIndex()); } StringBuilder source; source.reserveCapacity(length); size_t i = 0; for ( ; i < length && !m_previousSource.isEmpty(); ++i) { source.append(m_previousSource.currentChar()); m_previousSource.advance(); } for ( ; i < length; ++i) { ASSERT(!m_currentSource.isEmpty()); source.append(m_currentSource.currentChar()); m_currentSource.advance(); } m_cachedSourceForToken = source.toString(); return m_cachedSourceForToken; }
static String buildRectangleString(const String& x, const String& y, const String& width, const String& height, const String& radiusX, const String& radiusY, const String& layoutBox) { const char opening[] = "rectangle("; const char separator[] = ", "; StringBuilder result; // Compute the required capacity in advance to reduce allocations. result.reserveCapacity((sizeof(opening) - 1) + (5 * (sizeof(separator) - 1)) + 1 + x.length() + y.length() + width.length() + height.length() + radiusX.length() + radiusY.length() + (layoutBox.isEmpty() ? 0 : layoutBox.length() + 1)); result.appendLiteral(opening); result.append(x); result.appendLiteral(separator); result.append(y); result.appendLiteral(separator); result.append(width); result.appendLiteral(separator); result.append(height); if (!radiusX.isNull()) { result.appendLiteral(separator); result.append(radiusX); if (!radiusY.isNull()) { result.appendLiteral(separator); result.append(radiusY); } } if (!layoutBox.isEmpty()) { result.append(' '); result.append(layoutBox); } result.append(')'); return result.toString(); }
TEST(StringBuilderTest, ToString) { StringBuilder builder; builder.append("0123456789"); String string = builder.toString(); ASSERT_EQ(String("0123456789"), string); ASSERT_EQ(string.impl(), builder.toString().impl()); // Changing the StringBuilder should not affect the original result of toString(). builder.append("abcdefghijklmnopqrstuvwxyz"); ASSERT_EQ(String("0123456789"), string); // Changing the StringBuilder should not affect the original result of toString() in case the capacity is not changed. builder.reserveCapacity(200); string = builder.toString(); ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string); builder.append("ABC"); ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string); // Changing the original result of toString() should not affect the content of the StringBuilder. String string1 = builder.toString(); ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1); string1.append("DEF"); ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), builder.toString()); ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABCDEF"), string1); // Resizing the StringBuilder should not affect the original result of toString(). string1 = builder.toString(); builder.resize(10); builder.append("###"); ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1); }
static String buildInsetRectangleString(const String& top, const String& right, const String& bottom, const String& left, const String& radiusX, const String& radiusY, const String& layoutBox) { const char opening[] = "inset-rectangle("; const char separator[] = ", "; StringBuilder result; // Compute the required capacity in advance to reduce allocations. result.reserveCapacity((sizeof(opening) - 1) + (5 * (sizeof(separator) - 1)) + 1 + top.length() + right.length() + bottom.length() + left.length() + radiusX.length() + radiusY.length() + (layoutBox.isEmpty() ? 0 : layoutBox.length() + 1)); result.appendLiteral(opening); result.append(top); result.appendLiteral(separator); result.append(right); result.appendLiteral(separator); result.append(bottom); result.appendLiteral(separator); result.append(left); if (!radiusX.isNull()) { result.appendLiteral(separator); result.append(radiusX); if (!radiusY.isNull()) { result.appendLiteral(separator); result.append(radiusY); } } result.append(')'); if (!layoutBox.isEmpty()) { result.append(' '); result.append(layoutBox); } return result.toString(); }
String HTMLSourceTracker::sourceForToken(const HTMLToken& token) { if (token.type() == HTMLToken::EndOfFile) return String(); // Hides the null character we use to mark the end of file. if (!m_cachedSourceForToken.isEmpty()) return m_cachedSourceForToken; ASSERT(!token.startIndex()); size_t length = static_cast<size_t>(token.endIndex() - token.startIndex()); StringBuilder source; source.reserveCapacity(length); size_t i = 0; for ( ; i < length && !m_previousSource.isEmpty(); ++i) { source.append(m_previousSource.currentChar()); m_previousSource.advance(); } for ( ; i < length; ++i) { ASSERT(!m_currentSource.isEmpty()); source.append(m_currentSource.currentChar()); m_currentSource.advance(); } m_cachedSourceForToken = source.toString(); return m_cachedSourceForToken; }
String CookieManager::getCookie(const KURL& url, CookieFilter filter) const { if (!m_syncedWithDatabase && !m_privateMode) { LOG_ERROR("CookieManager is calling getCookies before database values are loaded."); return String(); } Vector<ParsedCookie*> rawCookies; rawCookies.reserveInitialCapacity(s_maxCookieCountPerHost); // Retrieve cookies related to this url getRawCookies(rawCookies, url, filter); CookieLog("CookieManager - there are %d cookies in raw cookies\n", rawCookies.size()); // Generate the cookie header string using the retrieved cookies StringBuilder cookieStringBuilder; cookieStringBuilder.reserveCapacity(512); size_t cookieSize = rawCookies.size(); for (size_t i = 0; i < cookieSize; i++) { cookieStringBuilder.append(rawCookies[i]->toNameValuePair()); if (i != cookieSize-1) cookieStringBuilder.append("; "); } CookieLog("CookieManager - cookieString is - %s\n", cookieStringBuilder.toString().utf8().data()); return cookieStringBuilder.toString(); }
String MarkupAccumulator::serializeNodes(Node* node, Node* nodeToSkip, EChildrenOnly childrenOnly) { StringBuilder out; serializeNodesWithNamespaces(node, nodeToSkip, childrenOnly, 0); out.reserveCapacity(length()); concatenateMarkup(out); return out.toString(); }
// When getting properties on CSSStyleDeclarations, the name used from // Javascript and the actual name of the property are not the same, so // we have to do the following translation. The translation turns upper // case characters into lower case characters and inserts dashes to // separate words. // // Example: 'backgroundPositionY' -> 'background-position-y' // // Also, certain prefixes such as 'pos', 'css-' and 'pixel-' are stripped // and the hadPixelOrPosPrefix out parameter is used to indicate whether or // not the property name was prefixed with 'pos-' or 'pixel-'. static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String>v8PropertyName) { String propertyName = toWebCoreString(v8PropertyName); typedef HashMap<String, CSSPropertyInfo*> CSSPropertyInfoMap; DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ()); CSSPropertyInfo* propInfo = map.get(propertyName); if (!propInfo) { unsigned length = propertyName.length(); bool hadPixelOrPosPrefix = false; if (!length) return 0; StringBuilder builder; builder.reserveCapacity(length); unsigned i = 0; if (hasCSSPropertyNamePrefix(propertyName, "css")) i += 3; else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) { i += 5; hadPixelOrPosPrefix = true; } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) { i += 3; hadPixelOrPosPrefix = true; } else if (hasCSSPropertyNamePrefix(propertyName, "webkit") #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) || hasCSSPropertyNamePrefix(propertyName, "khtml") || hasCSSPropertyNamePrefix(propertyName, "apple") #endif ) builder.append('-'); else if (isASCIIUpper(propertyName[0])) return 0; builder.append(toASCIILower(propertyName[i++])); for (; i < length; ++i) { UChar c = propertyName[i]; if (!isASCIIUpper(c)) builder.append(c); else builder.append(makeString('-', toASCIILower(c))); } String propName = builder.toString(); CSSPropertyID propertyID = cssPropertyID(propName); if (propertyID) { propInfo = new CSSPropertyInfo(); propInfo->hadPixelOrPosPrefix = hadPixelOrPosPrefix; propInfo->propID = propertyID; map.add(propertyName, propInfo); } } return propInfo; }
static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPosPrefix = 0) { if (hadPixelOrPosPrefix) *hadPixelOrPosPrefix = false; unsigned length = propertyName.length(); if (!length) return String(); StringImpl* propertyNameString = propertyName.impl(); // If there is no uppercase character in the propertyName, there can // be no prefix, nor extension and we can return the same string. if (!containsASCIIUpperChar(*propertyNameString)) return String(propertyNameString); StringBuilder builder; builder.reserveCapacity(length); unsigned i = 0; switch (getCSSPropertyNamePrefix(*propertyNameString)) { case PropertyNamePrefixNone: if (isASCIIUpper((*propertyNameString)[0])) return String(); break; case PropertyNamePrefixCSS: i += 3; break; case PropertyNamePrefixPixel: i += 5; if (hadPixelOrPosPrefix) *hadPixelOrPosPrefix = true; break; case PropertyNamePrefixPos: i += 3; if (hadPixelOrPosPrefix) *hadPixelOrPosPrefix = true; break; case PropertyNamePrefixApple: case PropertyNamePrefixEpub: case PropertyNamePrefixKHTML: case PropertyNamePrefixWebKit: builder.append('-'); } builder.append(toASCIILower((*propertyNameString)[i++])); for (; i < length; ++i) { UChar c = (*propertyNameString)[i]; if (!isASCIIUpper(c)) builder.append(c); else builder.append(makeString('-', toASCIILower(c))); } return builder.toString(); }
TEST(StringBuilderTest, CanShrink) { StringBuilder builder; builder.reserveCapacity(256); EXPECT_TRUE(builder.canShrink()); for (int i = 0; i < 256; i++) builder.append('x'); EXPECT_EQ(builder.length(), builder.capacity()); EXPECT_FALSE(builder.canShrink()); }
String Font::normalizeSpaces(const UChar* characters, unsigned length) { StringBuilder normalized; normalized.reserveCapacity(length); for (unsigned i = 0; i < length; ++i) normalized.append(normalizeSpaces(characters[i])); return normalized.toString(); }
String NetworkCacheKey::hashAsString() const { StringBuilder builder; builder.reserveCapacity(hashStringLength()); for (auto byte : m_hash) { builder.append(upperNibbleToASCIIHexDigit(byte)); builder.append(lowerNibbleToASCIIHexDigit(byte)); } return builder.toString(); }
static inline String normalizeSpacesInternal(const CharacterType* characters, unsigned length) { StringBuilder normalized; normalized.reserveCapacity(length); for (unsigned i = 0; i < length; ++i) normalized.append(Font::normalizeSpaces(characters[i])); return normalized.toString(); }