/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** * A helper function that allocates a buffer of the desired character type big * enough to hold a copy of the supplied string (plus a zero terminator). * * @param aSource an string you will eventually be making a copy of * @return a new buffer which you must free with |free|. *
*/ template <class FromStringT, class CharT> inline CharT* AllocateStringCopy(const FromStringT& aSource, CharT*) { returnstatic_cast<CharT*>(
malloc((size_t(aSource.Length()) + 1) * sizeof(CharT)));
}
char* ToNewCString(const nsAString& aSource, const mozilla::fallible_t& aFallible) { char* dest = AllocateStringCopy(aSource, (char*)nullptr); if (!dest) { return nullptr;
}
auto len = aSource.Length();
LossyConvertUtf16toLatin1(aSource, Span(dest, len));
dest[len] = 0; return dest;
}
char* ToNewUTF8String(const nsAString& aSource, uint32_t* aUTF8Count, const mozilla::fallible_t& aFallible) { auto len = aSource.Length(); // The uses of this function seem temporary enough that it's not // worthwhile to be fancy about the allocation size. Let's just use // the worst case. // Times 3 plus 1, because ConvertUTF16toUTF8 requires times 3 and // then we have the terminator. // Using CheckedInt<uint32_t>, because aUTF8Count is uint32_t* for // historical reasons.
mozilla::CheckedInt<uint32_t> destLen(len);
destLen *= 3;
destLen += 1; if (!destLen.isValid()) { return nullptr;
}
size_t destLenVal = destLen.value(); char* dest = static_cast<char*>(malloc(destLenVal)); if (!dest) { return nullptr;
}
size_t written = ConvertUtf16toUtf8(aSource, Span(dest, destLenVal));
dest[written] = 0;
char* ToNewCString(const nsACString& aSource, const mozilla::fallible_t& aFallible) { // no conversion needed, just allocate a buffer of the correct length and copy // into it
char* dest = AllocateStringCopy(aSource, (char*)nullptr); if (!dest) { return nullptr;
}
auto len = aSource.Length();
memcpy(dest, aSource.BeginReading(), len * sizeof(char));
dest[len] = 0; return dest;
}
char16_t* ToNewUnicode(const nsAString& aSource, const mozilla::fallible_t& aFallible) { // no conversion needed, just allocate a buffer of the correct length and copy // into it
char16_t* dest = AllocateStringCopy(aSource, (char16_t*)nullptr); if (!dest) { return nullptr;
}
auto len = aSource.Length();
memcpy(dest, aSource.BeginReading(), len * sizeof(char16_t));
dest[len] = 0; return dest;
}
char16_t* ToNewUnicode(const nsACString& aSource, const mozilla::fallible_t& aFallible) {
char16_t* dest = AllocateStringCopy(aSource, (char16_t*)nullptr); if (!dest) { return nullptr;
}
auto len = aSource.Length();
ConvertLatin1toUtf16(aSource, Span(dest, len));
dest[len] = 0; return dest;
}
char16_t* UTF8ToNewUnicode(const nsACString& aSource, uint32_t* aUTF16Count, const mozilla::fallible_t& aFallible) { // Compute length plus one as required by ConvertUTF8toUTF16
uint32_t lengthPlusOne = aSource.Length() + 1; // Can't overflow
mozilla::CheckedInt<size_t> allocLength(lengthPlusOne); // Add space for zero-termination
allocLength += 1; // We need UTF-16 units
allocLength *= sizeof(char16_t);
if (!allocLength.isValid()) { return nullptr;
}
char16_t* dest = (char16_t*)malloc(allocLength.value()); if (!dest) { return nullptr;
}
size_t written = ConvertUtf8toUtf16(aSource, Span(dest, lengthPlusOne));
dest[written] = 0;
// only bother searching at all if we're given a non-empty range to search if (aSearchStart != aSearchEnd) {
IteratorT aPatternStart, aPatternEnd;
aPattern.BeginReading(aPatternStart);
aPattern.EndReading(aPatternEnd);
// outer loop keeps searching till we find it or run out of string to search while (!found_it) { // fast inner loop (that's what it's called, not what it is) looks for a // potential match while (aSearchStart != aSearchEnd &&
aCompare(aPatternStart.get(), aSearchStart.get(), 1, 1)) {
++aSearchStart;
}
// if we broke out of the `fast' loop because we're out of string ... // we're done: no match if (aSearchStart == aSearchEnd) { break;
}
// otherwise, we're at a potential match, let's see if we really hit one
IteratorT testPattern(aPatternStart);
IteratorT testSearch(aSearchStart);
// slow inner loop verifies the potential match (found by the `fast' loop) // at the current position for (;;) { // we already compared the first character in the outer loop, // so we'll advance before the next comparison
++testPattern;
++testSearch;
// if we verified all the way to the end of the pattern, then we found // it! if (testPattern == aPatternEnd) {
found_it = true;
aSearchEnd = testSearch; // return the exact found range through the // parameters break;
}
// if we got to end of the string we're searching before we hit the end // of the // pattern, we'll never find what we're looking for if (testSearch == aSearchEnd) {
aSearchStart = aSearchEnd; break;
}
// else if we mismatched ... it's time to advance to the next search // position // and get back into the `fast' loop if (aCompare(testPattern.get(), testSearch.get(), 1, 1)) {
++aSearchStart; break;
}
}
}
}
return found_it;
}
/** * This searches the entire string from right to left, and returns the first * match found, if any.
*/ template <class StringT, class IteratorT> bool RFindInReadable_Impl( const StringT& aPattern, IteratorT& aSearchStart, IteratorT& aSearchEnd,
nsTStringComparator<typename StringT::char_type> aCompare) {
IteratorT patternStart, patternEnd, searchEnd = aSearchEnd;
aPattern.BeginReading(patternStart);
aPattern.EndReading(patternEnd);
// Point to the last character in the pattern
--patternEnd; // outer loop keeps searching till we run out of string to search while (aSearchStart != searchEnd) { // Point to the end position of the next possible match
--searchEnd;
// Check last character, if a match, explore further from here if (aCompare(patternEnd.get(), searchEnd.get(), 1, 1) == 0) { // We're at a potential match, let's see if we really hit one
IteratorT testPattern(patternEnd);
IteratorT testSearch(searchEnd);
// inner loop verifies the potential match at the current position do { // if we verified all the way to the end of the pattern, then we found // it! if (testPattern == patternStart) {
aSearchStart = testSearch; // point to start of match
aSearchEnd = ++searchEnd; // point to end of match returntrue;
}
// if we got to end of the string we're searching before we hit the end // of the // pattern, we'll never find what we're looking for if (testSearch == aSearchStart) {
aSearchStart = aSearchEnd; returnfalse;
}
// test previous character for a match
--testPattern;
--testSearch;
} while (aCompare(testPattern.get(), testSearch.get(), 1, 1) == 0);
}
}
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 ist noch experimentell.