gecko/widget/nsPrimitiveHelpers.cpp
Wes Kocher f01fa1274c Backed out 25 changesets (bug 1156742) for build bustage in SkOSLibrary_win.cpp CLOSED TREE
Backed out changeset 31c0aadae8e7 (bug 1156742)
Backed out changeset f08df57ff700 (bug 1156742)
Backed out changeset 90c026d5dcb1 (bug 1156742)
Backed out changeset 8c6d14d80238 (bug 1156742)
Backed out changeset 72d86b0471c9 (bug 1156742)
Backed out changeset 363829accc09 (bug 1156742)
Backed out changeset 16360fe94d54 (bug 1156742)
Backed out changeset 5355c636a81a (bug 1156742)
Backed out changeset 18844d26b873 (bug 1156742)
Backed out changeset 99df86591613 (bug 1156742)
Backed out changeset 7ac1c7e15a11 (bug 1156742)
Backed out changeset de352000aae1 (bug 1156742)
Backed out changeset 4dd34ea230c6 (bug 1156742)
Backed out changeset 48c6ce65a5c2 (bug 1156742)
Backed out changeset dd52947f73c6 (bug 1156742)
Backed out changeset 5fe429ee880c (bug 1156742)
Backed out changeset dedca8fb19b0 (bug 1156742)
Backed out changeset d748b1354f92 (bug 1156742)
Backed out changeset 7f8e59588518 (bug 1156742)
Backed out changeset b90d302c57f6 (bug 1156742)
Backed out changeset 7a4da453572c (bug 1156742)
Backed out changeset a40eea914519 (bug 1156742)
Backed out changeset 99a8859afcdb (bug 1156742)
Backed out changeset 4934e88b2d7a (bug 1156742)
Backed out changeset 79733166f05e (bug 1156742) for build bustage in SkOSLibrary_win.cpp CLOSED TREE
2015-12-21 13:47:33 -08:00

207 lines
7.2 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
//
// Part of the reason these routines are all in once place is so that as new
// data flavors are added that are known to be one-byte or two-byte strings, or even
// raw binary data, then we just have to go to one place to change how the data
// moves into/out of the primitives and native line endings.
//
// If you add new flavors that have special consideration (binary data or one-byte
// char* strings), please update all the helper classes in this file.
//
// For now, this is the assumption that we are making:
// - text/plain is always a char*
// - anything else is a char16_t*
//
#include "nsPrimitiveHelpers.h"
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsITransferable.h"
#include "nsIComponentManager.h"
#include "nsLinebreakConverter.h"
#include "nsReadableUtils.h"
//
// CreatePrimitiveForData
//
// Given some data and the flavor it corresponds to, creates the appropriate
// nsISupports* wrapper for passing across IDL boundaries. Right now, everything
// creates a two-byte |nsISupportsString|, except for "text/plain" and native
// platform HTML (CF_HTML on win32)
//
void
nsPrimitiveHelpers :: CreatePrimitiveForData ( const char* aFlavor, const void* aDataBuff,
uint32_t aDataLen, nsISupports** aPrimitive )
{
if ( !aPrimitive )
return;
if ( strcmp(aFlavor,kTextMime) == 0 || strcmp(aFlavor,kNativeHTMLMime) == 0 ||
strcmp(aFlavor,kRTFMime) == 0) {
nsCOMPtr<nsISupportsCString> primitive =
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
if ( primitive ) {
const char * start = reinterpret_cast<const char*>(aDataBuff);
primitive->SetData(Substring(start, start + aDataLen));
NS_ADDREF(*aPrimitive = primitive);
}
}
else {
nsCOMPtr<nsISupportsString> primitive =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
if (primitive ) {
if (aDataLen % 2) {
auto buffer = MakeUnique<char[]>(aDataLen + 1);
if (!MOZ_LIKELY(buffer))
return;
memcpy(buffer.get(), aDataBuff, aDataLen);
buffer[aDataLen] = 0;
const char16_t* start = reinterpret_cast<const char16_t*>(buffer.get());
// recall that length takes length as characters, not bytes
primitive->SetData(Substring(start, start + (aDataLen + 1) / 2));
} else {
const char16_t* start = reinterpret_cast<const char16_t*>(aDataBuff);
// recall that length takes length as characters, not bytes
primitive->SetData(Substring(start, start + (aDataLen / 2)));
}
NS_ADDREF(*aPrimitive = primitive);
}
}
} // CreatePrimitiveForData
//
// CreatePrimitiveForCFHTML
//
// Platform specific CreatePrimitive, windows CF_HTML.
//
void
nsPrimitiveHelpers :: CreatePrimitiveForCFHTML ( const void* aDataBuff,
uint32_t* aDataLen, nsISupports** aPrimitive )
{
if (!aPrimitive)
return;
nsCOMPtr<nsISupportsString> primitive =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
if (!primitive)
return;
// We need to duplicate the input buffer, since the removal of linebreaks
// might reallocte it.
void* utf8 = moz_xmalloc(*aDataLen);
if (!utf8)
return;
memcpy(utf8, aDataBuff, *aDataLen);
int32_t signedLen = static_cast<int32_t>(*aDataLen);
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(kTextMime, &utf8, &signedLen);
*aDataLen = signedLen;
nsAutoString str(NS_ConvertUTF8toUTF16(reinterpret_cast<const char*>(utf8), *aDataLen));
free(utf8);
*aDataLen = str.Length() * sizeof(char16_t);
primitive->SetData(str);
NS_ADDREF(*aPrimitive = primitive);
}
//
// CreateDataFromPrimitive
//
// Given a nsISupports* primitive and the flavor it represents, creates a new data
// buffer with the data in it. This data will be null terminated, but the length
// parameter does not reflect that.
//
void
nsPrimitiveHelpers :: CreateDataFromPrimitive ( const char* aFlavor, nsISupports* aPrimitive,
void** aDataBuff, uint32_t aDataLen )
{
if ( !aDataBuff )
return;
*aDataBuff = nullptr;
if ( strcmp(aFlavor,kTextMime) == 0 ) {
nsCOMPtr<nsISupportsCString> plainText ( do_QueryInterface(aPrimitive) );
if ( plainText ) {
nsAutoCString data;
plainText->GetData ( data );
*aDataBuff = ToNewCString(data);
}
}
else {
nsCOMPtr<nsISupportsString> doubleByteText ( do_QueryInterface(aPrimitive) );
if ( doubleByteText ) {
nsAutoString data;
doubleByteText->GetData ( data );
*aDataBuff = ToNewUnicode(data);
}
}
}
//
// ConvertPlatformToDOMLinebreaks
//
// Given some data, convert from the platform linebreaks into the LF expected by the
// DOM. This will attempt to convert the data in place, but the buffer may still need to
// be reallocated regardless (disposing the old buffer is taken care of internally, see
// the note below).
//
// NOTE: this assumes that it can use 'free' to dispose of the old buffer.
//
nsresult
nsLinebreakHelpers :: ConvertPlatformToDOMLinebreaks ( const char* inFlavor, void** ioData,
int32_t* ioLengthInBytes )
{
NS_ASSERTION ( ioData && *ioData && ioLengthInBytes, "Bad Params");
if ( !(ioData && *ioData && ioLengthInBytes) )
return NS_ERROR_INVALID_ARG;
nsresult retVal = NS_OK;
if ( strcmp(inFlavor, kTextMime) == 0 || strcmp(inFlavor, kRTFMime) == 0) {
char* buffAsChars = reinterpret_cast<char*>(*ioData);
char* oldBuffer = buffAsChars;
retVal = nsLinebreakConverter::ConvertLineBreaksInSitu ( &buffAsChars, nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakContent,
*ioLengthInBytes, ioLengthInBytes );
if ( NS_SUCCEEDED(retVal) ) {
if ( buffAsChars != oldBuffer ) // check if buffer was reallocated
free ( oldBuffer );
*ioData = buffAsChars;
}
}
else if ( strcmp(inFlavor, "image/jpeg") == 0 ) {
// I'd assume we don't want to do anything for binary data....
}
else {
char16_t* buffAsUnichar = reinterpret_cast<char16_t*>(*ioData);
char16_t* oldBuffer = buffAsUnichar;
int32_t newLengthInChars;
retVal = nsLinebreakConverter::ConvertUnicharLineBreaksInSitu ( &buffAsUnichar, nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakContent,
*ioLengthInBytes / sizeof(char16_t), &newLengthInChars );
if ( NS_SUCCEEDED(retVal) ) {
if ( buffAsUnichar != oldBuffer ) // check if buffer was reallocated
free ( oldBuffer );
*ioData = buffAsUnichar;
*ioLengthInBytes = newLengthInChars * sizeof(char16_t);
}
}
return retVal;
} // ConvertPlatformToDOMLinebreaks