// https://tools.ietf.org/html/rfc6455#section-4.1 // "The HTTP version MUST be at least 1.1." static inline bool headerHasValidHTTPVersion(StringView httpStatusLine) { const char* httpVersionStaticPreambleLiteral = "HTTP/"; StringView httpVersionStaticPreamble(reinterpret_cast<const LChar*>(httpVersionStaticPreambleLiteral), strlen(httpVersionStaticPreambleLiteral)); if (!httpStatusLine.startsWith(httpVersionStaticPreamble)) return false; // Check that there is a version number which should be at least three characters after "HTTP/" unsigned preambleLength = httpVersionStaticPreamble.length(); if (httpStatusLine.length() < preambleLength + 3) return false; auto dotPosition = httpStatusLine.find('.', preambleLength); if (dotPosition == notFound) return false; StringView majorVersionView = httpStatusLine.substring(preambleLength, dotPosition - preambleLength); bool isValid; int majorVersion = majorVersionView.toIntStrict(isValid); if (!isValid) return false; unsigned minorVersionLength; unsigned charactersLeftAfterDotPosition = httpStatusLine.length() - dotPosition; for (minorVersionLength = 1; minorVersionLength < charactersLeftAfterDotPosition; minorVersionLength++) { if (!isASCIIDigit(httpStatusLine[dotPosition + minorVersionLength])) break; } int minorVersion = (httpStatusLine.substring(dotPosition + 1, minorVersionLength)).toIntStrict(isValid); if (!isValid) return false; return (majorVersion >= 1 && minorVersion >= 1) || majorVersion >= 2; }
static void findGrammaticalErrors(TextCheckerClient& client, StringView text, Vector<TextCheckingResult>& results) { for (unsigned checkLocation = 0; checkLocation < text.length(); ) { int badGrammarLocation = -1; int badGrammarLength = 0; Vector<GrammarDetail> badGrammarDetails; client.checkGrammarOfString(text.substring(checkLocation), badGrammarDetails, &badGrammarLocation, &badGrammarLength); if (!badGrammarLength) break; ASSERT(badGrammarLocation >= 0); ASSERT(static_cast<unsigned>(badGrammarLocation) <= text.length() - checkLocation); ASSERT(badGrammarLength > 0); ASSERT(static_cast<unsigned>(badGrammarLength) <= text.length() - checkLocation - badGrammarLocation); TextCheckingResult badGrammar; badGrammar.type = TextCheckingTypeGrammar; badGrammar.location = checkLocation + badGrammarLocation; badGrammar.length = badGrammarLength; badGrammar.details = std::move(badGrammarDetails); results.append(badGrammar); checkLocation += badGrammarLocation + badGrammarLength; } }
static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset) { ErrorInstance::SourceAppender appender = exception->sourceAppender(); exception->clearSourceAppender(); RuntimeType type = exception->runtimeTypeForCause(); exception->clearRuntimeTypeForCause(); if (!callFrame->codeBlock()->hasExpressionInfo()) return; int startOffset = 0; int endOffset = 0; int divotPoint = 0; unsigned line = 0; unsigned column = 0; CodeBlock* codeBlock; CodeOrigin codeOrigin = callFrame->codeOrigin(); if (codeOrigin && codeOrigin.inlineCallFrame) codeBlock = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame); else codeBlock = callFrame->codeBlock(); codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset, line, column); int expressionStart = divotPoint - startOffset; int expressionStop = divotPoint + endOffset; StringView sourceString = codeBlock->source()->source(); if (!expressionStop || expressionStart > static_cast<int>(sourceString.length())) return; VM* vm = &callFrame->vm(); JSValue jsMessage = exception->getDirect(*vm, vm->propertyNames->message); if (!jsMessage || !jsMessage.isString()) return; String message = asString(jsMessage)->value(callFrame); if (expressionStart < expressionStop) message = appender(message, codeBlock->source()->getRange(expressionStart, expressionStop).toString(), type, ErrorInstance::FoundExactSource); else { // No range information, so give a few characters of context. int dataLength = sourceString.length(); int start = expressionStart; int stop = expressionStart; // Get up to 20 characters of context to the left and right of the divot, clamping to the line. // Then strip whitespace. while (start > 0 && (expressionStart - start < 20) && sourceString[start - 1] != '\n') start--; while (start < (expressionStart - 1) && isStrWhiteSpace(sourceString[start])) start++; while (stop < dataLength && (stop - expressionStart < 20) && sourceString[stop] != '\n') stop++; while (stop > expressionStart && isStrWhiteSpace(sourceString[stop - 1])) stop--; message = appender(message, codeBlock->source()->getRange(start, stop).toString(), type, ErrorInstance::FoundApproximateSource); } exception->putDirect(*vm, vm->propertyNames->message, jsString(vm, message)); }
TextRun InlineTextBox::constructTextRun( const ComputedStyle& style, StringView string, int maximumLength, StringBuilder* charactersWithHyphen) const { if (charactersWithHyphen) { const AtomicString& hyphenString = style.hyphenString(); charactersWithHyphen->reserveCapacity(string.length() + hyphenString.length()); charactersWithHyphen->append(string); charactersWithHyphen->append(hyphenString); string = charactersWithHyphen->toString(); maximumLength = string.length(); } ASSERT(maximumLength >= static_cast<int>(string.length())); TextRun run(string, textPos().toFloat(), expansion(), expansionBehavior(), direction(), dirOverride() || style.rtlOrdering() == EOrder::Visual); run.setTabSize(!style.collapseWhiteSpace(), style.getTabSize()); run.setTextJustify(style.getTextJustify()); // Propagate the maximum length of the characters buffer to the TextRun, even // when we're only processing a substring. run.setCharactersLength(maximumLength); ASSERT(run.charactersLength() >= run.length()); return run; }
int findNextWordFromIndex(StringView text, int position, bool forward) { TextBreakIterator* it = wordBreakIterator(text); if (forward) { position = textBreakFollowing(it, position); while (position != TextBreakDone) { // We stop searching when the character preceeding the break is alphanumeric. if (static_cast<unsigned>(position) < text.length() && u_isalnum(text[position - 1])) return position; position = textBreakFollowing(it, position); } return text.length(); } else { position = textBreakPreceding(it, position); while (position != TextBreakDone) { // We stop searching when the character following the break is alphanumeric. if (position && u_isalnum(text[position])) return position; position = textBreakPreceding(it, position); } return 0; } }
StringView::StringView(const StringView &str, uint32 begin, uint32 end) : _str(str.c_str()+begin) , _length(end-begin) { ARC_ASSERT(begin <= str.length(),"Invalid StringView begin."); ARC_ASSERT(end <= str.length(), "Invalid StringView end"); }
UCharIterator createIterator(StringView string) { if (string.is8Bit()) return createLatin1Iterator(string.characters8(), string.length()); UCharIterator iterator; uiter_setString(&iterator, string.characters16(), string.length()); return iterator; }
static void parseImageCandidatesFromSrcsetAttribute(StringView attribute, Vector<ImageCandidate>& imageCandidates) { // FIXME: We should consider replacing the direct pointers in the parsing process with StringView and positions. if (attribute.is8Bit()) parseImageCandidatesFromSrcsetAttribute<LChar>(attribute.characters8(), attribute.length(), imageCandidates); else parseImageCandidatesFromSrcsetAttribute<UChar>(attribute.characters16(), attribute.length(), imageCandidates); }
bool write_string(Slice<char>& buffer, StringView v) { if (buffer.size() < v.length()) return false; memcpy(buffer.ptr(), v.c_str(), v.length()); buffer.trim_front(v.length()); return true; }
static inline bool hostIsInDomain(StringView host, StringView domain) { if (!host.endsWithIgnoringASCIICase(domain)) return false; ASSERT(host.length() >= domain.length()); unsigned suffixOffset = host.length() - domain.length(); return suffixOffset == 0 || host[suffixOffset - 1] == '.'; }
size_t add_string(const size_t vertex, const StringView& s, const bool add_substrings = false) // extend Trie by one string // REQUIRE: all chars in interval [0..alphabet_size] { size_t v = vertex; for (size_t i = 0; i < s.length(); ++i) { v = add_char(v, s[i], add_substrings || i == s.length() - 1); } return v; }
void Write(StringView data) { NEPTOOLS_CHECK(SinkOverflow, offset+buf_put+data.length() <= size, "Sink overflow during write"); auto cp = std::min(data.length(), size_t(buf_size - buf_put)); memcpy(buf+buf_put, data.data(), cp); data.remove_prefix(cp); buf_put += cp; if (!data.empty()) Write_(data); }
v8_inspector::StringView toV8InspectorStringView(const StringView& string) { if (string.isNull()) return v8_inspector::StringView(); if (string.is8Bit()) return v8_inspector::StringView( reinterpret_cast<const uint8_t*>(string.characters8()), string.length()); return v8_inspector::StringView( reinterpret_cast<const uint16_t*>(string.characters16()), string.length()); }
IDBKeyPathLexer::TokenType IDBKeyPathLexer::lexIdentifier(String& element) { StringView start = m_remainingText; if (!m_remainingText.isEmpty() && isIdentifierStartCharacter(m_remainingText[0])) m_remainingText = m_remainingText.substring(1); else return TokenError; while (!m_remainingText.isEmpty() && isIdentifierCharacter(m_remainingText[0])) m_remainingText = m_remainingText.substring(1); element = start.substring(0, start.length() - m_remainingText.length()).toString(); return TokenIdentifier; }
// https://wicg.github.io/entries-api/#resolve-a-relative-path static String resolveRelativeVirtualPath(StringView baseVirtualPath, StringView relativeVirtualPath) { ASSERT(baseVirtualPath[0] == '/'); if (!relativeVirtualPath.isEmpty() && relativeVirtualPath[0] == '/') return relativeVirtualPath.length() == 1 ? relativeVirtualPath.toString() : resolveRelativeVirtualPath("/", relativeVirtualPath.substring(1)); Vector<StringView> virtualPathSegments; for (auto segment : baseVirtualPath.split('/')) virtualPathSegments.append(segment); for (auto segment : relativeVirtualPath.split('/')) { ASSERT(!segment.isEmpty()); if (segment == ".") continue; if (segment == "..") { if (!virtualPathSegments.isEmpty()) virtualPathSegments.removeLast(); continue; } virtualPathSegments.append(segment); } if (virtualPathSegments.isEmpty()) return "/"_s; StringBuilder builder; for (auto& segment : virtualPathSegments) { builder.append('/'); builder.append(segment); } return builder.toString(); }
TextEncoding HTMLMetaCharsetParser::encodingFromMetaAttributes(const AttributeList& attributes) { bool gotPragma = false; enum { None, Charset, Pragma } mode = None; StringView charset; for (auto& attribute : attributes) { const String& attributeName = attribute.first; const String& attributeValue = attribute.second; if (attributeName == http_equivAttr) { if (equalIgnoringCase(attributeValue, "content-type")) gotPragma = true; } else if (charset.isEmpty()) { if (attributeName == charsetAttr) { charset = attributeValue; mode = Charset; } else if (attributeName == contentAttr) { charset = extractCharset(attributeValue); if (charset.length()) mode = Pragma; } } } if (mode == Charset || (mode == Pragma && gotPragma)) return TextEncoding(stripLeadingAndTrailingHTMLSpaces(charset.toStringWithoutCopying())); return TextEncoding(); }
void checkTextOfParagraph(TextCheckerClient& client, StringView text, TextCheckingTypeMask checkingTypes, Vector<TextCheckingResult>& results) { #if USE(UNIFIED_TEXT_CHECKING) results = client.checkTextOfParagraph(text, checkingTypes); #else Vector<TextCheckingResult> mispellings; if (checkingTypes & TextCheckingTypeSpelling) findMisspellings(client, text, mispellings); #if USE(GRAMMAR_CHECKING) // Look for grammatical errors that occur before the first misspelling. Vector<TextCheckingResult> grammaticalErrors; if (checkingTypes & TextCheckingTypeGrammar) { unsigned grammarCheckLength = text.length(); for (auto& mispelling : mispellings) grammarCheckLength = std::min<unsigned>(grammarCheckLength, mispelling.location); findGrammaticalErrors(client, text.substring(0, grammarCheckLength), grammaticalErrors); } results = std::move(grammaticalErrors); #endif if (results.isEmpty()) results = std::move(mispellings); else results.appendVector(mispellings); #endif // USE(UNIFIED_TEXT_CHECKING) }
size_t lastHyphenLocation(const StringView& text, size_t beforeIndex) const override { CFIndex result = CFStringGetHyphenationLocationBeforeIndex( text.toString().impl()->createCFString().get(), beforeIndex, CFRangeMake(0, text.length()), 0, m_localeCF.get(), 0); return result == kCFNotFound ? 0 : result; }
std::u32string StringToUTF32(const StringView str) { if (str.empty()) { return std::u32string(); } const wchar* begin = &str[0]; const wchar* end = begin + str.length(); if (const auto length = detail::CountCodePoints(begin, end)) { std::u32string result(length.value(), L'\0'); while (begin != end) { const auto ch = *begin++; if (!IsUTF16Surrogate(ch)) { result.push_back(ch); } else { result.push_back(SurrogateToUTF32(ch, *begin++)); } } return result; } else { return std::u32string(); } }
static unsigned nextWordOffset(StringView text, unsigned currentOffset) { // FIXME: avoid creating textIterator object here, it could be passed as a parameter. // isTextBreak() leaves the iterator pointing to the first boundary position at // or after "offset" (ubrk_isBoundary side effect). // For many word separators, the method doesn't properly determine the boundaries // without resetting the iterator. TextBreakIterator* textIterator = wordBreakIterator(text); if (!textIterator) return currentOffset; unsigned wordOffset = currentOffset; while (wordOffset < text.length() && isTextBreak(textIterator, wordOffset)) ++wordOffset; // Do not treat the word's boundary as a separator. if (!currentOffset && wordOffset == 1) return currentOffset; // Omit multiple separators. if ((wordOffset - currentOffset) > 1) --wordOffset; return wordOffset; }
unsigned numCodeUnitsInGraphemeClusters(StringView string, unsigned numGraphemeClusters) { unsigned stringLength = string.length(); if (stringLength <= numGraphemeClusters) return stringLength; // The only Latin-1 Extended Grapheme Cluster is CRLF. if (string.is8Bit()) { auto* characters = string.characters8(); unsigned i, j; for (i = 0, j = 0; i < numGraphemeClusters && j + 1 < stringLength; ++i, ++j) j += characters[j] == '\r' && characters[j + 1] == '\n'; return j + (i < numGraphemeClusters); } NonSharedCharacterBreakIterator iterator { string }; if (!iterator) { ASSERT_NOT_REACHED(); return stringLength; } for (unsigned i = 0; i < numGraphemeClusters; ++i) { if (ubrk_next(iterator) == UBRK_DONE) return stringLength; } return ubrk_current(iterator); }
unsigned numGraphemeClusters(StringView string) { unsigned stringLength = string.length(); if (!stringLength) return 0; // The only Latin-1 Extended Grapheme Cluster is CRLF. if (string.is8Bit()) { auto* characters = string.characters8(); unsigned numCRLF = 0; for (unsigned i = 1; i < stringLength; ++i) numCRLF += characters[i - 1] == '\r' && characters[i] == '\n'; return stringLength - numCRLF; } NonSharedCharacterBreakIterator iterator { string }; if (!iterator) { ASSERT_NOT_REACHED(); return stringLength; } unsigned numGraphemeClusters = 0; while (ubrk_next(iterator) != UBRK_DONE) ++numGraphemeClusters; return numGraphemeClusters; }
void processFeaturesString(StringView features, std::function<void(StringView type, StringView value)> callback) { unsigned length = features.length(); for (unsigned i = 0; i < length; ) { // skip to first non-separator while (i < length && isSeparator(features[i])) ++i; unsigned keyBegin = i; // skip to first separator while (i < length && !isSeparator(features[i])) i++; unsigned keyEnd = i; // skip to first '=', but don't skip past a ',' while (i < length && features[i] != '=' && features[i] != ',') ++i; // skip to first non-separator, but don't skip past a ',' while (i < length && isSeparator(features[i]) && features[i] != ',') ++i; unsigned valueBegin = i; // skip to first separator while (i < length && !isSeparator(features[i])) ++i; unsigned valueEnd = i; callback(features.substring(keyBegin, keyEnd - keyBegin), features.substring(valueBegin, valueEnd - valueBegin)); } }
void RenderCombineText::getStringToRender(int start, StringView& string, int& length) const { ASSERT(start >= 0); if (m_isCombined) { string = StringView(originalText()); length = string.length(); return; } string = text().createView(start, length); }
// https://wicg.github.io/entries-api/#path-segment static bool isValidPathSegment(StringView segment) { if (segment.isEmpty() || segment == "." || segment == "..") return true; for (unsigned i = 0; i < segment.length(); ++i) { if (!isValidPathNameCharacter(segment[i])) return false; } return true; }
String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, bool markAll, RefPtr<Range>& firstMisspellingRange) { WordAwareIterator it(*m_range); firstMisspellingOffset = 0; String firstMisspelling; int currentChunkOffset = 0; while (!it.atEnd()) { StringView text = it.text(); int textLength = text.length(); // Skip some work for one-space-char hunks if (textLength == 1 && text[0] == ' ') { int misspellingLocation = -1; int misspellingLength = 0; m_client->textChecker()->checkSpellingOfString(text, &misspellingLocation, &misspellingLength); // 5490627 shows that there was some code path here where the String constructor below crashes. // We don't know exactly what combination of bad input caused this, so we're making this much // more robust against bad input on release builds. ASSERT(misspellingLength >= 0); ASSERT(misspellingLocation >= -1); ASSERT(!misspellingLength || misspellingLocation >= 0); ASSERT(misspellingLocation < textLength); ASSERT(misspellingLength <= textLength); ASSERT(misspellingLocation + misspellingLength <= textLength); if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < textLength && misspellingLength <= textLength && misspellingLocation + misspellingLength <= textLength) { // Compute range of misspelled word RefPtr<Range> misspellingRange = TextIterator::subrange(m_range.get(), currentChunkOffset + misspellingLocation, misspellingLength); // Remember first-encountered misspelling and its offset. if (!firstMisspelling) { firstMisspellingOffset = currentChunkOffset + misspellingLocation; firstMisspelling = text.substring(misspellingLocation, misspellingLength).toString(); firstMisspellingRange = misspellingRange; } // Store marker for misspelled word. misspellingRange->startContainer()->document().markers().addMarker(misspellingRange.get(), DocumentMarker::Spelling); // Bail out if we're marking only the first misspelling, and not all instances. if (!markAll) break; } } currentChunkOffset += textLength; it.advance(); } return firstMisspelling; }
String createStringWithMirroredCharacters(StringView string) { unsigned length = string.length(); StringBuilder mirroredCharacters; mirroredCharacters.reserveCapacity(length); for (unsigned i = 0; i < length; ) { UChar32 character; U16_NEXT(string, i, length, character); mirroredCharacters.append(u_charMirror(character)); } return mirroredCharacters.toString(); }
unsigned startOfLastWordBoundaryContext(StringView text) { unsigned length = text.length(); for (unsigned i = length; i > 0; ) { unsigned last = i; UChar32 ch; U16_PREV(text, 0, i, ch); if (!requiresContextForWordBoundary(ch)) return last; } return 0; }
unsigned endOfFirstWordBoundaryContext(StringView text) { unsigned length = text.length(); for (unsigned i = 0; i < length; ) { unsigned first = i; UChar32 ch; U16_NEXT(text, i, length, ch); if (!requiresContextForWordBoundary(ch)) return first; } return length; }
void WebEditorClient::checkSpellingOfString(StringView text, int* misspellingLocation, int* misspellingLength) { *misspellingLocation = -1; *misspellingLength = 0; COMPtr<IWebEditingDelegate> ed; if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) return; initViewSpecificSpelling(m_webView); ed->checkSpellingOfString(m_webView, text.upconvertedCharacters(), text.length(), misspellingLocation, misspellingLength); }