void nsAttrValue::SetTo(const nsAString& aValue) { ResetIfSet(); if (!aValue.IsEmpty()) { PRUint32 len = aValue.Length(); nsStringBuffer* buf = nsStringBuffer::FromString(aValue); if (buf && (buf->StorageSize()/sizeof(PRUnichar) - 1) == len) { buf->AddRef(); SetPtrValueAndType(buf, eStringBase); return; } buf = nsStringBuffer::Alloc((len + 1) * sizeof(PRUnichar)); if (!buf) { return; } PRUnichar *data = static_cast<PRUnichar*>(buf->Data()); CopyUnicodeTo(aValue, 0, data, len); data[len] = PRUnichar(0); SetPtrValueAndType(buf, eStringBase); } }
nsresult nsScanner::Peek(nsAString& aStr, PRInt32 aNumChars, PRInt32 aOffset) { if (!mSlidingBuffer) { return kEOF; } if (mCurrentPosition == mEndPosition) { return FillBuffer(); } nsScannerIterator start, end; start = mCurrentPosition; if ((PRInt32)mCountRemaining <= aOffset) { return kEOF; } if (aOffset > 0) { start.advance(aOffset); } if (mCountRemaining < PRUint32(aNumChars + aOffset)) { end = mEndPosition; } else { end = start; end.advance(aNumChars); } CopyUnicodeTo(start, end, aStr); return NS_OK; }
// convert a readable to a JSString, copying string data // static jsval XPCStringConvert::ReadableToJSVal(JSContext *cx, const nsAString &readable, nsStringBuffer** sharedBuffer) { JSString *str; *sharedBuffer = nullptr; uint32_t length = readable.Length(); if (length == 0) return JS_GetEmptyStringValue(cx); nsStringBuffer *buf = nsStringBuffer::FromString(readable); if (buf) { if (buf == sCachedBuffer && js::GetGCThingCompartment(sCachedString) == js::GetContextCompartment(cx)) { // We're done. Just return our existing string. return JS::StringValue(sCachedString); } // yay, we can share the string's buffer! str = JS_NewExternalString(cx, reinterpret_cast<jschar *>(buf->Data()), length, &sDOMStringFinalizer); if (str) { *sharedBuffer = buf; sCachedString = str; sCachedBuffer = buf; } } else { // blech, have to copy. jschar *chars = reinterpret_cast<jschar *> (JS_malloc(cx, (length + 1) * sizeof(jschar))); if (!chars) return JSVAL_NULL; if (length && !CopyUnicodeTo(readable, 0, reinterpret_cast<PRUnichar *>(chars), length)) { JS_free(cx, chars); return JSVAL_NULL; } chars[length] = 0; str = JS_NewUCString(cx, chars, length); if (!str) JS_free(cx, chars); } return str ? STRING_TO_JSVAL(str) : JSVAL_NULL; }
// convert a readable to a JSString, copying string data // static JSString * XPCStringConvert::ReadableToJSString(JSContext *cx, const nsAString &readable) { JSString *str; PRUint32 length = readable.Length(); nsStringBuffer *buf = nsStringBuffer::FromString(readable); if (buf) { // yay, we can share the string's buffer! if (sDOMStringFinalizerIndex == -1) { sDOMStringFinalizerIndex = JS_AddExternalStringFinalizer(DOMStringFinalizer); if (sDOMStringFinalizerIndex == -1) return NULL; } str = JS_NewExternalString(cx, reinterpret_cast<jschar *>(buf->Data()), length, sDOMStringFinalizerIndex); if (str) buf->AddRef(); } else { // blech, have to copy. jschar *chars = reinterpret_cast<jschar *> (JS_malloc(cx, (length + 1) * sizeof(jschar))); if (!chars) return NULL; if (length && !CopyUnicodeTo(readable, 0, reinterpret_cast<PRUnichar *>(chars), length)) { JS_free(cx, chars); return NULL; } chars[length] = 0; str = JS_NewUCString(cx, chars, length); if (!str) JS_free(cx, chars); } return str; }
/** * call this to copy bytes out of the scanner that have not yet been consumed * by the tokenization process. * * @update gess 5/12/98 * @param aCopyBuffer is where the scanner buffer will be copied to * @return nada */ void nsScanner::CopyUnusedData(nsString& aCopyBuffer) { if (!mSlidingBuffer) { aCopyBuffer.Truncate(); return; } nsScannerIterator start, end; start = mCurrentPosition; end = mEndPosition; CopyUnicodeTo(start, end, aCopyBuffer); }
// convert a readable to a JSString, copying string data // static jsval XPCStringConvert::ReadableToJSVal(JSContext *cx, const nsAString &readable, nsStringBuffer** sharedBuffer) { JSString *str; *sharedBuffer = nullptr; uint32_t length = readable.Length(); if (length == 0) return JS_GetEmptyStringValue(cx); nsStringBuffer *buf = nsStringBuffer::FromString(readable); if (buf) { JS::RootedValue val(cx); bool shared; bool ok = StringBufferToJSVal(cx, buf, length, &val, &shared); if (!ok) { return JS::NullValue(); } if (shared) { *sharedBuffer = buf; } return val; } // blech, have to copy. jschar *chars = reinterpret_cast<jschar *> (JS_malloc(cx, (length + 1) * sizeof(jschar))); if (!chars) return JS::NullValue(); if (length && !CopyUnicodeTo(readable, 0, reinterpret_cast<PRUnichar *>(chars), length)) { JS_free(cx, chars); return JS::NullValue(); } chars[length] = 0; str = JS_NewUCString(cx, chars, length); if (!str) { JS_free(cx, chars); } return str ? STRING_TO_JSVAL(str) : JSVAL_NULL; }
nsHtml5Atom::nsHtml5Atom(const nsAString& aString) { mLength = aString.Length(); RefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString); if (buf) { mString = static_cast<char16_t*>(buf->Data()); } else { buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char16_t)); mString = static_cast<char16_t*>(buf->Data()); CopyUnicodeTo(aString, 0, mString, mLength); mString[mLength] = char16_t(0); } NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated"); NS_ASSERTION(buf && buf->StorageSize() >= (mLength+1) * sizeof(char16_t), "enough storage"); NS_ASSERTION(Equals(aString), "correct data"); // Take ownership of buffer mozilla::Unused << buf.forget(); }
const nsSubstring& nsScannerSubstring::AsString() const { if (mIsDirty) { nsScannerSubstring* mutable_this = NS_CONST_CAST(nsScannerSubstring*, this); if (mStart.mBuffer == mEnd.mBuffer) { // We only have a single fragment to deal with, so just return it // as a substring. mutable_this->mFlattenedRep.Rebind(mStart.mPosition, mEnd.mPosition); } else { // Otherwise, we need to copy the data into a flattened buffer. nsScannerIterator start, end; CopyUnicodeTo(BeginReading(start), EndReading(end), mutable_this->mFlattenedRep); } mutable_this->mIsDirty = PR_FALSE; } return mFlattenedRep; }
nsStringBuffer* nsAttrValue::GetStringBuffer(const nsAString& aValue) const { PRUint32 len = aValue.Length(); if (!len) { return nsnull; } nsStringBuffer* buf = nsStringBuffer::FromString(aValue); if (buf && (buf->StorageSize()/sizeof(PRUnichar) - 1) == len) { buf->AddRef(); return buf; } buf = nsStringBuffer::Alloc((len + 1) * sizeof(PRUnichar)); if (!buf) { return nsnull; } PRUnichar *data = static_cast<PRUnichar*>(buf->Data()); CopyUnicodeTo(aValue, 0, data, len); data[len] = PRUnichar(0); return buf; }
NS_IMETHODIMP nsAOLCiter::StripCites(const nsAString& aInString, nsAString& aOutString) { // Remove the beginning cites, if any: nsAutoString tOutputString; nsReadingIterator <PRUnichar> iter, enditer; aInString.BeginReading(iter); aInString.EndReading(enditer); if (StringBeginsWith(aInString, NS_LITERAL_STRING(">>"))) { iter.advance(2); while (nsCRT::IsAsciiSpace(*iter)) ++iter; AppendUnicodeTo(iter, enditer, tOutputString); } else CopyUnicodeTo(iter, enditer, tOutputString); // Remove the end cites, if any: tOutputString.Trim("<", PR_FALSE, PR_TRUE, PR_FALSE); aOutString.Assign(tOutputString); return NS_OK; }
NS_IMETHODIMP nsExpatDriver::ConsumeToken(nsScanner& aScanner, PRBool& aFlushTokens) { // We keep the scanner pointing to the position where Expat will start // parsing. nsScannerIterator currentExpatPosition; aScanner.CurrentPosition(currentExpatPosition); // This is the start of the first buffer that we need to pass to Expat. nsScannerIterator start = currentExpatPosition; start.advance(mExpatBuffered); // This is the end of the last buffer (at this point, more data could come in // later). nsScannerIterator end; aScanner.EndReading(end); PR_LOG(gExpatDriverLog, PR_LOG_DEBUG, ("Remaining in expat's buffer: %i, remaining in scanner: %i.", mExpatBuffered, Distance(start, end))); // We want to call Expat if we have more buffers, or if we know there won't // be more buffers (and so we want to flush the remaining data), or if we're // currently blocked and there's data in Expat's buffer. while (start != end || (mIsFinalChunk && !mMadeFinalCallToExpat) || (BlockedOrInterrupted() && mExpatBuffered > 0)) { PRBool noMoreBuffers = start == end && mIsFinalChunk; PRBool blocked = BlockedOrInterrupted(); const PRUnichar *buffer; PRUint32 length; if (blocked || noMoreBuffers) { // If we're blocked we just resume Expat so we don't need a buffer, if // there aren't any more buffers we pass a null buffer to Expat. buffer = nsnull; length = 0; #if defined(PR_LOGGING) || defined (DEBUG) if (blocked) { PR_LOG(gExpatDriverLog, PR_LOG_DEBUG, ("Resuming Expat, will parse data remaining in Expat's " "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n", NS_ConvertUTF16toUTF8(currentExpatPosition.get(), mExpatBuffered).get())); } else { NS_ASSERTION(mExpatBuffered == Distance(currentExpatPosition, end), "Didn't pass all the data to Expat?"); PR_LOG(gExpatDriverLog, PR_LOG_DEBUG, ("Last call to Expat, will parse data remaining in Expat's " "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n", NS_ConvertUTF16toUTF8(currentExpatPosition.get(), mExpatBuffered).get())); } #endif } else { buffer = start.get(); length = PRUint32(start.size_forward()); PR_LOG(gExpatDriverLog, PR_LOG_DEBUG, ("Calling Expat, will parse data remaining in Expat's buffer and " "new data.\nContent of Expat's buffer:\n-----\n%s\n-----\nNew " "data:\n-----\n%s\n-----\n", NS_ConvertUTF16toUTF8(currentExpatPosition.get(), mExpatBuffered).get(), NS_ConvertUTF16toUTF8(start.get(), length).get())); } PRUint32 consumed; ParseBuffer(buffer, length, noMoreBuffers, &consumed); if (consumed > 0) { nsScannerIterator oldExpatPosition = currentExpatPosition; currentExpatPosition.advance(consumed); // We consumed some data, we want to store the last line of data that // was consumed in case we run into an error (to show the line in which // the error occurred). // The length of the last line that Expat has parsed. XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser); if (lastLineLength <= consumed) { // The length of the last line was less than what expat consumed, so // there was at least one line break in the consumed data. Store the // last line until the point where we stopped parsing. nsScannerIterator startLastLine = currentExpatPosition; startLastLine.advance(-((ptrdiff_t)lastLineLength)); CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine); } else { // There was no line break in the consumed data, append the consumed // data. AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine); } } mExpatBuffered += length - consumed; if (BlockedOrInterrupted()) { PR_LOG(gExpatDriverLog, PR_LOG_DEBUG, ("Blocked or interrupted parser (probably for loading linked " "stylesheets or scripts).")); aScanner.SetPosition(currentExpatPosition, PR_TRUE); aScanner.Mark(); return mInternalState; } if (noMoreBuffers && mExpatBuffered == 0) { mMadeFinalCallToExpat = PR_TRUE; } if (NS_FAILED(mInternalState)) { if (XML_GetErrorCode(mExpatParser) != XML_ERROR_NONE) { NS_ASSERTION(mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING, "Unexpected error"); // Look for the next newline after the last one we consumed nsScannerIterator lastLine = currentExpatPosition; while (lastLine != end) { length = PRUint32(lastLine.size_forward()); PRUint32 endOffset = 0; const PRUnichar *buffer = lastLine.get(); while (endOffset < length && buffer[endOffset] != '\n' && buffer[endOffset] != '\r') { ++endOffset; } mLastLine.Append(Substring(buffer, buffer + endOffset)); if (endOffset < length) { // We found a newline. break; } lastLine.advance(length); } HandleError(); } return mInternalState; } // Either we have more buffers, or we were blocked (and we'll flush in the // next iteration), or we should have emptied Expat's buffer. NS_ASSERTION(!noMoreBuffers || blocked || (mExpatBuffered == 0 && currentExpatPosition == end), "Unreachable data left in Expat's buffer"); start.advance(length); // It's possible for start to have passed end if we received more data // (e.g. if we spun the event loop in an inline script). Reload end now // to compensate. aScanner.EndReading(end); } aScanner.SetPosition(currentExpatPosition, PR_TRUE); aScanner.Mark(); PR_LOG(gExpatDriverLog, PR_LOG_DEBUG, ("Remaining in expat's buffer: %i, remaining in scanner: %i.", mExpatBuffered, Distance(currentExpatPosition, end))); return NS_SUCCEEDED(mInternalState) ? kEOF : NS_OK; }
// convert a readable to a JSString, copying string data // static jsval XPCStringConvert::ReadableToJSVal(JSContext *cx, const nsAString &readable, nsStringBuffer** sharedBuffer) { JSString *str; *sharedBuffer = nsnull; PRUint32 length = readable.Length(); JSAtom *atom; if (length == 0 && (atom = cx->runtime->atomState.emptyAtom)) { return ATOM_TO_JSVAL(atom); } nsStringBuffer *buf = nsStringBuffer::FromString(readable); if (buf) { // yay, we can share the string's buffer! if (sDOMStringFinalizerIndex == -1) { sDOMStringFinalizerIndex = JS_AddExternalStringFinalizer(DOMStringFinalizer); if (sDOMStringFinalizerIndex == -1) return JSVAL_NULL; } str = JS_NewExternalString(cx, reinterpret_cast<jschar *>(buf->Data()), length, sDOMStringFinalizerIndex); if (str) { *sharedBuffer = buf; } } else { // blech, have to copy. jschar *chars = reinterpret_cast<jschar *> (JS_malloc(cx, (length + 1) * sizeof(jschar))); if (!chars) return JSVAL_NULL; if (length && !CopyUnicodeTo(readable, 0, reinterpret_cast<PRUnichar *>(chars), length)) { JS_free(cx, chars); return JSVAL_NULL; } chars[length] = 0; str = JS_NewUCString(cx, chars, length); if (!str) JS_free(cx, chars); } return STRING_TO_JSVAL(str); }