String StructureShape::leastUpperBound(Vector<RefPtr<StructureShape>>* shapes) { if (!shapes->size()) return ""; StringBuilder lub; RefPtr<StructureShape> origin = shapes->at(0); lub.append("{"); for (auto iter = origin->m_fields.begin(), end = origin->m_fields.end(); iter != end; ++iter) { bool shouldAdd = true; for (size_t i = 1, size = shapes->size(); i < size; i++) { // If all other Shapes have the same field as origin, add it to the least upper bound. if (!shapes->at(i)->m_fields.contains(iter->key)) { shouldAdd = false; break; } } if (shouldAdd) lub.append(String(iter->key.get()) + String(", ")); } if (lub.length() >= 3) lub.resize(lub.length() - 2); // Remove the trailing ', ' lub.append("}"); return lub.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()); }
public boolean isValid(String s) { StringBuilder sb = new StringBuilder(); boolean valid = true; for (int i = 0; valid && i < s.length(); i++) { int lastIdx = sb.length() - 1; char c = s.charAt(i); switch (c) { case '{': case '(': case '[': sb.append(c); break; case '}': case ')': case ']': char lchar = (c == ']' ? '[' : (c == ')' ? '(' : '{')); if (lastIdx >= 0 && sb.charAt(lastIdx) == lchar) sb.setLength(lastIdx); else valid = false; break; } } return valid && sb.length() == 0; }
void Element::formatForDebugger(char* buffer, unsigned length) const { StringBuilder result; String s; result.append(nodeName()); s = getIdAttribute(); if (s.length() > 0) { if (result.length() > 0) result.appendLiteral("; "); result.appendLiteral("id="); result.append(s); } s = getAttribute(HTMLNames::classAttr); if (s.length() > 0) { if (result.length() > 0) result.appendLiteral("; "); result.appendLiteral("class="); result.append(s); } strncpy(buffer, result.toString().utf8().data(), length - 1); }
String StructureShape::stringRepresentation() { StringBuilder representation; RefPtr<StructureShape> curShape = this; representation.append('{'); while (curShape) { for (auto it = curShape->m_fields.begin(), end = curShape->m_fields.end(); it != end; ++it) { String prop((*it).get()); representation.append(prop); representation.append(", "); } if (curShape->m_proto) { String prot = makeString("__proto__ [", curShape->m_proto->m_constructorName, ']'); representation.append(prot); representation.append(", "); } curShape = curShape->m_proto; } if (representation.length() >= 3) representation.resize(representation.length() - 2); representation.append('}'); return representation.toString(); }
// This is only needed for TextDocuments where we might have text nodes // approaching the default length limit (~64k) and we don't want to // break a text node in the middle of a combining character. static unsigned findBreakIndexBetween(const StringBuilder& string, unsigned currentPosition, unsigned proposedBreakIndex) { ASSERT(currentPosition < proposedBreakIndex); ASSERT(proposedBreakIndex <= string.length()); // The end of the string is always a valid break. if (proposedBreakIndex == string.length()) return proposedBreakIndex; // Latin-1 does not have breakable boundaries. If we ever moved to a differnet 8-bit encoding this could be wrong. if (string.is8Bit()) return proposedBreakIndex; const UChar* breakSearchCharacters = string.characters16() + currentPosition; // We need at least two characters look-ahead to account for UTF-16 surrogates, but can't search off the end of the buffer! unsigned breakSearchLength = std::min(proposedBreakIndex - currentPosition + 2, string.length() - currentPosition); NonSharedCharacterBreakIterator it(breakSearchCharacters, breakSearchLength); if (it.isBreak(proposedBreakIndex - currentPosition)) return proposedBreakIndex; int adjustedBreakIndexInSubstring = it.preceding(proposedBreakIndex - currentPosition); if (adjustedBreakIndexInSubstring > 0) return currentPosition + adjustedBreakIndexInSubstring; // We failed to find a breakable point, let the caller figure out what to do. return 0; }
static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) { Document* document = frame->document(); if (!document) return; if (!frame->view()) return; // Select the document body. RefPtr<Range> range(document->createRange()); TrackExceptionState exceptionState; range->selectNodeContents(document, exceptionState); if (!exceptionState.had_exception()) { // The text iterator will walk nodes giving us text. This is similar to // the plainText() function in core/editing/TextIterator.h, but we implement the maximum // size and also copy the results directly into a wstring, avoiding the // string conversion. for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { it.appendTextToStringBuilder(output, 0, maxChars - output.length()); if (output.length() >= maxChars) return; // Filled up the buffer. } } }
static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) { Document* document = frame->document(); if (!document) return; if (!frame->view()) return; // Select the document body. if (document->body()) { const EphemeralRange range = EphemeralRange::rangeOfContents(*document->body()); // The text iterator will walk nodes giving us text. This is similar to // the plainText() function in core/editing/TextIterator.h, but we implement the maximum // size and also copy the results directly into a wstring, avoiding the // string conversion. for (TextIterator it(range.startPosition(), range.endPosition()); !it.atEnd(); it.advance()) { it.text().appendTextToStringBuilder(output, 0, maxChars - output.length()); if (output.length() >= maxChars) return; // Filled up the buffer. } } // The separator between frames when the frames are converted to plain text. const LChar frameSeparator[] = { '\n', '\n' }; const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator); // Recursively walk the children. const FrameTree& frameTree = frame->tree(); for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) { if (!curChild->isLocalFrame()) continue; LocalFrame* curLocalChild = toLocalFrame(curChild); // Ignore the text of non-visible frames. LayoutView* contentLayoutObject = curLocalChild->contentLayoutObject(); LayoutPart* ownerLayoutObject = curLocalChild->ownerLayoutObject(); if (!contentLayoutObject || !contentLayoutObject->size().width() || !contentLayoutObject->size().height() || (contentLayoutObject->location().x() + contentLayoutObject->size().width() <= 0) || (contentLayoutObject->location().y() + contentLayoutObject->size().height() <= 0) || (ownerLayoutObject && ownerLayoutObject->style() && ownerLayoutObject->style()->visibility() != VISIBLE)) { continue; } // Make sure the frame separator won't fill up the buffer, and give up if // it will. The danger is if the separator will make the buffer longer than // maxChars. This will cause the computation above: // maxChars - output->size() // to be a negative number which will crash when the subframe is added. if (output.length() >= maxChars - frameSeparatorLength) return; output.append(frameSeparator, frameSeparatorLength); frameContentAsPlainText(maxChars, curLocalChild, output); if (output.length() >= maxChars) return; // Filled up the buffer. } }
// This returns an AtomicString because it is always passed as argument to // setValue() and setValue() takes an AtomicString in argument. AtomicString DOMTokenList::removeTokens(const AtomicString& input, const Vector<String>& tokens) { // Algorithm defined at // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#remove-a-token-from-a-string // New spec is at https://dom.spec.whatwg.org/#remove-a-token-from-a-string unsigned inputLength = input.length(); StringBuilder output; // 3 output.reserveCapacity(inputLength); unsigned position = 0; // 4 // Step 5 while (position < inputLength) { if (isHTMLSpace<UChar>(input[position])) { // 6 position++; continue; // 6.3 } // Step 7 StringBuilder tokenBuilder; while (position < inputLength && isNotHTMLSpace<UChar>(input[position])) tokenBuilder.append(input[position++]); // Step 8 String token = tokenBuilder.toString(); if (tokens.contains(token)) { // Step 8.1 while (position < inputLength && isHTMLSpace<UChar>(input[position])) ++position; // Step 8.2 size_t j = output.length(); while (j > 0 && isHTMLSpace<UChar>(output[j - 1])) --j; output.resize(j); } else { output.append(token); // Step 9 } if (position < inputLength && !output.isEmpty()) output.append(' '); } size_t j = output.length(); if (j > 0 && isHTMLSpace<UChar>(output[j - 1])) output.resize(j - 1); return output.toAtomicString(); }
public String toString() { StringBuilder result = new StringBuilder(8 * getDegree()); for (int degree = getDegree(); degree >= 0; degree--) { int coefficient = getCoefficient(degree); if (coefficient != 0) { if (coefficient < 0) { result.append(" - "); coefficient = -coefficient; } else { if (result.length() > 0) { result.append(" + "); } } if (degree == 0 || coefficient != 1) { result.append(coefficient); } if (degree != 0) { if (degree == 1) { result.append('x'); } else { result.append("x^"); result.append(degree); } } } } return result.toString(); }
static void commitLiteralToken(StringBuilder& literalBuffer, Vector<DateFormatToken>& tokens) { if (literalBuffer.length() <= 0) return; tokens.append(DateFormatToken(literalBuffer.toString())); literalBuffer.clear(); }
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(); }
String generateHTMLContent(unsigned contentLength) { String baseString("abcdefghijklmnopqrstuvwxyz0123457890"); unsigned baseLength = baseString.length(); StringBuilder builder; builder.append("<html><body>"); if (contentLength <= baseLength) builder.append(baseString, 0, contentLength); else { unsigned currentLength = 0; while (currentLength < contentLength) { if ((currentLength + baseLength) <= contentLength) builder.append(baseString); else builder.append(baseString, 0, contentLength - currentLength); // Account for the 12 characters of the '<html><body>' prefix. currentLength = builder.length() - 12; } } builder.append("</body></html>"); return builder.toString(); }
static void stripTrailingNewline(StringBuilder& result) { // Remove one trailing newline; there's always one that's collapsed out by rendering. size_t size = result.length(); if (size && result[size - 1] == newlineCharacter) result.resize(size - 1); }
const String WebMediaConstraintsPrivate::toString() const { StringBuilder builder; if (!isEmpty()) { builder.append('{'); builder.append(basic().toString()); if (!advanced().isEmpty()) { if (builder.length() > 1) builder.appendLiteral(", "); builder.appendLiteral("advanced: ["); bool first = true; for (const auto& constraintSet : advanced()) { if (!first) builder.appendLiteral(", "); builder.append('{'); builder.append(constraintSet.toString()); builder.append('}'); first = false; } builder.append(']'); } builder.append('}'); } return builder.toString(); }
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(); }
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()); }
void StyledMarkupAccumulator::appendText(StringBuilder& out, Text* text) { const bool parentIsTextarea = text->parentElement() && text->parentElement()->tagQName() == textareaTag; const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextarea; if (wrappingSpan) { RefPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy(); // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance // Make sure spans are inline style in paste side e.g. span { display: block }. wrappingStyle->forceInline(); // FIXME: Should this be included in forceInline? wrappingStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); StringBuilder openTag; appendStyleNodeOpenTag(openTag, wrappingStyle->style(), text->document()); out.append(openTag.characters(), openTag.length()); } if (!shouldAnnotate() || parentIsTextarea) MarkupAccumulator::appendText(out, text); else { const bool useRenderedText = !enclosingNodeWithTag(firstPositionInNode(text), selectTag); String content = useRenderedText ? renderedText(text, m_range) : stringValueForRange(text, m_range); StringBuilder buffer; appendCharactersReplacingEntities(buffer, content.characters(), content.length(), EntityMaskInPCDATA); out.append(convertHTMLTextToInterchangeFormat(buffer.toString(), text)); } if (wrappingSpan) out.append(styleNodeCloseTag()); }
std::string ParagraphStream::read() throw(IOException) { StringBuilder *paragraph = new StringBuilder(); while (true) { std::string line = samples->read(); // The last paragraph in the input might not // be terminated well with a new line at the end. if (line == "" || line == "") { if (paragraph->length() > 0) { //JAVA TO C++ CONVERTER TODO TASK: There is no native C++ equivalent to 'toString': return paragraph->toString(); } } else { paragraph->append(line)->append('\n'); } if (line == "") return 0; } }
static void commitLiteralToken(StringBuilder& literalBuffer, StringBuilder& converted) { if (literalBuffer.length() <= 0) return; DateTimeFormat::quoteAndappend(literalBuffer.toString(), converted); literalBuffer.clear(); }
void RenderMathMLFenced::updateFromElement() { const auto& fenced = element(); // The open operator defaults to a left parenthesis. AtomicString open = fenced.fastGetAttribute(MathMLNames::openAttr); m_open = open.isNull() ? gOpeningBraceChar : open; // The close operator defaults to a right parenthesis. AtomicString close = fenced.fastGetAttribute(MathMLNames::closeAttr); m_close = close.isNull() ? gClosingBraceChar : close; AtomicString separators = fenced.fastGetAttribute(MathMLNames::separatorsAttr); if (!separators.isNull()) { StringBuilder characters; for (unsigned int i = 0; i < separators.length(); i++) { if (!isSpaceOrNewline(separators[i])) characters.append(separators[i]); } m_separators = !characters.length() ? 0 : characters.toString().impl(); } else { // The separator defaults to a single comma. m_separators = StringImpl::create(","); } if (isEmpty()) makeFences(); else { // FIXME: The mfenced element fails to update dynamically when its open, close and separators attributes are changed (https://bugs.webkit.org/show_bug.cgi?id=57696). toRenderMathMLOperator(firstChild())->updateTokenContent(m_open); m_closeFenceRenderer->updateTokenContent(m_close); } }
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(); }
WebString StringConstraint::toString() const { StringBuilder builder; builder.append('{'); if (!m_ideal.isEmpty()) { builder.append("ideal: ["); bool first = true; for (const auto& iter : m_ideal) { if (!first) builder.append(", "); builder.append('"'); builder.append(iter); builder.append('"'); first = false; } builder.append(']'); } if (!m_exact.isEmpty()) { if (builder.length() > 1) builder.append(", "); builder.append("exact: ["); bool first = true; for (const auto& iter : m_exact) { if (!first) builder.append(", "); builder.append('"'); builder.append(iter); builder.append('"'); } builder.append(']'); } builder.append('}'); return builder.toString(); }
void RenderMathMLFenced::updateFromElement() { Element* fenced = static_cast<Element*>(node()); // FIXME: Handle open/close values with more than one character (they should be treated like text). AtomicString openValue = fenced->getAttribute(MathMLNames::openAttr); if (openValue.length() > 0) m_open = openValue[0]; AtomicString closeValue = fenced->getAttribute(MathMLNames::closeAttr); if (closeValue.length() > 0) m_close = closeValue[0]; AtomicString separators = fenced->getAttribute(MathMLNames::separatorsAttr); if (!separators.isNull()) { StringBuilder characters; for (unsigned int i = 0; i < separators.length(); i++) { if (!isSpaceOrNewline(separators[i])) characters.append(separators[i]); } m_separators = !characters.length() ? 0 : characters.toString().impl(); } else { // The separator defaults to a single comma. m_separators = StringImpl::create(","); } if (isEmpty()) makeFences(); }
static bool parseHTMLIntegerInternal(const CharacterType* position, const CharacterType* end, int& value) { // Step 3 int sign = 1; // Step 4 while (position < end) { if (!isHTMLSpace<CharacterType>(*position)) break; ++position; } // Step 5 if (position == end) return false; ASSERT(position < end); // Step 6 if (*position == '-') { sign = -1; ++position; } else if (*position == '+') ++position; if (position == end) return false; ASSERT(position < end); // Step 7 if (!isASCIIDigit(*position)) return false; // Step 8 StringBuilder digits; while (position < end) { if (!isASCIIDigit(*position)) break; digits.append(*position++); } // Step 9 bool ok; if (digits.is8Bit()) value = sign * charactersToIntStrict(digits.characters8(), digits.length(), &ok); else value = sign * charactersToIntStrict(digits.characters16(), digits.length(), &ok); return ok; }
String StructureShape::stringRepresentation() { StringBuilder representation; representation.append("{"); for (auto iter = m_fields.begin(), end = m_fields.end(); iter != end; ++iter) { String prop(iter->key.get()); representation.append(prop); representation.append(", "); } if (representation.length() >= 3) representation.resize(representation.length() - 2); representation.append("}"); return representation.toString(); }
static String finishText(StringBuilder& result) { // Remove one trailing newline; there's always one that's collapsed out by rendering. size_t size = result.length(); if (size && result[size - 1] == '\n') result.resize(--size); return result.toString(); }
TEST(StringBuilderTest, Resize) { StringBuilder builder; builder.append("0123456789"); builder.resize(10); EXPECT_EQ(10U, builder.length()); expectBuilderContent("0123456789", builder); builder.resize(8); EXPECT_EQ(8U, builder.length()); expectBuilderContent("01234567", builder); builder.toString(); builder.resize(7); EXPECT_EQ(7U, builder.length()); expectBuilderContent("0123456", builder); builder.resize(0); expectEmpty(builder); }
static Position findWordBoundary(const HTMLElement* innerEditor, const Position& startPosition, const Position& endPosition, FindOption findOption) { StringBuilder concatTexts; Vector<unsigned> lengthList; HeapVector<Member<Text>> textList; if (startPosition.anchorNode()->isTextNode()) ASSERT(startPosition.isOffsetInAnchor()); if (endPosition.anchorNode()->isTextNode()) ASSERT(endPosition.isOffsetInAnchor()); // Traverse text nodes. for (Node* node = startPosition.anchorNode(); node; node = NodeTraversal::next(*node, innerEditor)) { bool isStartNode = node == startPosition.anchorNode(); bool isEndNode = node == endPosition.anchorNode(); if (node->isTextNode()) { Text* text = toText(node); const unsigned start = isStartNode ? startPosition.offsetInContainerNode() : 0; const unsigned end = isEndNode ? endPosition.offsetInContainerNode() : text->data().length(); const unsigned length = end - start; concatTexts.append(text->data(), start, length); lengthList.append(length); textList.append(text); } if (isEndNode) break; } if (concatTexts.length() == 0) return startPosition; int start, end; if (findOption == FindEnd && concatTexts[0] == '\n') { // findWordBoundary("\ntext", 0, &start, &end) assigns 1 to |end| but // we expect 0 at the case. start = 0; end = 0; } else { Vector<UChar> characters; concatTexts.toString().appendTo(characters); findWordBoundary(characters.data(), characters.size(), findOption == FindStart ? characters.size() : 0, &start, &end); } ASSERT(start >= 0); ASSERT(end >= 0); unsigned remainingOffset = findOption == FindStart ? start : end; // Find position. for (unsigned i = 0; i < lengthList.size(); ++i) { if (remainingOffset <= lengthList[i]) return Position(textList[i], (textList[i] == startPosition.anchorNode()) ? remainingOffset + startPosition.offsetInContainerNode() : remainingOffset); remainingOffset -= lengthList[i]; } ASSERT_NOT_REACHED(); return Position(); }
String ScrollingCoordinator::synchronousScrollingReasonsAsText(SynchronousScrollingReasons reasons) { StringBuilder stringBuilder; if (reasons & ScrollingCoordinator::ForcedOnMainThread) stringBuilder.append("Forced on main thread, "); if (reasons & ScrollingCoordinator::HasSlowRepaintObjects) stringBuilder.append("Has slow repaint objects, "); if (reasons & ScrollingCoordinator::HasViewportConstrainedObjectsWithoutSupportingFixedLayers) stringBuilder.append("Has viewport constrained objects without supporting fixed layers, "); if (reasons & ScrollingCoordinator::HasNonLayerViewportConstrainedObjects) stringBuilder.append("Has non-layer viewport-constrained objects, "); if (reasons & ScrollingCoordinator::IsImageDocument) stringBuilder.append("Is image document, "); if (stringBuilder.length()) stringBuilder.resize(stringBuilder.length() - 2); return stringBuilder.toString(); }