blob: 256089319045746a9395e5ded6c6a73cdcdbf8ae [file] [log] [blame]
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "WebKitDLL.h"
#include "MarshallingHelpers.h"
#include <WebCore/BString.h>
#include <WebCore/IntRect.h>
#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
#include <wtf/URL.h>
#include <wtf/text/WTFString.h>
using namespace WebCore;
#if USE(CF)
CFArrayCallBacks MarshallingHelpers::kIUnknownArrayCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
CFDictionaryValueCallBacks MarshallingHelpers::kIUnknownDictionaryValueCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
#endif
URL MarshallingHelpers::BSTRToKURL(BSTR urlStr)
{
return URL(URL(), String(urlStr, SysStringLen(urlStr)));
}
BSTR MarshallingHelpers::URLToBSTR(const URL& url)
{
return BString(url.string()).release();
}
#if USE(CF)
CFURLRef MarshallingHelpers::PathStringToFileCFURLRef(const String& string)
{
return CFURLCreateWithFileSystemPath(0, string.createCFString().get(), kCFURLWindowsPathStyle, false);
}
String MarshallingHelpers::FileCFURLRefToPathString(CFURLRef fileURL)
{
CFStringRef string = CFURLCopyFileSystemPath(fileURL, kCFURLWindowsPathStyle);
String result(string);
CFRelease(string);
return result;
}
CFURLRef MarshallingHelpers::BSTRToCFURLRef(BSTR urlStr)
{
CFStringRef urlCFString = BSTRToCFStringRef(urlStr);
if (!urlCFString)
return 0;
CFURLRef urlRef = CFURLCreateWithString(0, urlCFString, 0);
CFRelease(urlCFString);
return urlRef;
}
CFStringRef MarshallingHelpers::BSTRToCFStringRef(BSTR str)
{
return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), SysStringLen(str));
}
CFStringRef MarshallingHelpers::LPCOLESTRToCFStringRef(LPCOLESTR str)
{
return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), (CFIndex)(str ? wcslen(str) : 0));
}
BSTR MarshallingHelpers::CFStringRefToBSTR(CFStringRef str)
{
return BString(str).release();
}
int MarshallingHelpers::CFNumberRefToInt(CFNumberRef num)
{
int number;
CFNumberGetValue(num, kCFNumberIntType, &number);
return number;
}
CFNumberRef MarshallingHelpers::intToCFNumberRef(int num)
{
return CFNumberCreate(0, kCFNumberSInt32Type, &num);
}
#endif
#if USE(CF)
CFAbsoluteTime MarshallingHelpers::windowsEpochAbsoluteTime()
{
static CFAbsoluteTime windowsEpochAbsoluteTime = 0;
if (!windowsEpochAbsoluteTime) {
CFGregorianDate windowsEpochDate = {1899, 12, 30, 0, 0, 0.0};
windowsEpochAbsoluteTime = CFGregorianDateGetAbsoluteTime(windowsEpochDate, 0) / secondsPerDay;
}
return windowsEpochAbsoluteTime;
}
#else
double MarshallingHelpers::windowsEpochAbsoluteTime()
{
static double windowsEpochAbsoluteTime = 0;
if (!windowsEpochAbsoluteTime) {
SYSTEMTIME windowsEpochDate = { };
windowsEpochDate.wYear = 1899;
windowsEpochDate.wMonth = 12;
windowsEpochDate.wDay = 30;
FILETIME absoluteFileTime;
SystemTimeToFileTime(&windowsEpochDate, &absoluteFileTime);
ULARGE_INTEGER timeValue;
timeValue.LowPart = absoluteFileTime.dwLowDateTime;
timeValue.HighPart = absoluteFileTime.dwHighDateTime;
windowsEpochAbsoluteTime = timeValue.QuadPart;
}
return windowsEpochAbsoluteTime;
}
#endif
#if USE(CF)
CFAbsoluteTime MarshallingHelpers::DATEToCFAbsoluteTime(DATE date)
#else
double MarshallingHelpers::DATEToAbsoluteTime(DATE date)
#endif
{
// <http://msdn2.microsoft.com/en-us/library/ms221627.aspx>
// DATE: This is the same numbering system used by most spreadsheet programs,
// although some specify incorrectly that February 29, 1900 existed, and thus
// set January 1, 1900 to 1.0. The date can be converted to and from an MS-DOS
// representation using VariantTimeToDosDateTime, which is discussed in
// Conversion and Manipulation Functions.
// CFAbsoluteTime: Type used to represent a specific point in time relative
// to the absolute reference date of 1 Jan 2001 00:00:00 GMT.
// Absolute time is measured by the number of seconds between the reference
// date and the specified date. Negative values indicate dates/times before
// the reference date. Positive values indicate dates/times after the
// reference date.
return round((date + windowsEpochAbsoluteTime()) * secondsPerDay);
}
#if USE(CF)
DATE MarshallingHelpers::CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime)
#else
DATE MarshallingHelpers::absoluteTimeToDATE(double absoluteTime)
#endif
{
return (round(absoluteTime)/secondsPerDay - windowsEpochAbsoluteTime());
}
#if USE(CF)
// utility method to store a 1-dim string vector into a newly created SAFEARRAY
SAFEARRAY* MarshallingHelpers::stringArrayToSafeArray(CFArrayRef inArray)
{
CFIndex size = CFArrayGetCount(inArray);
SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_BSTR, 0, (ULONG) size, 0);
long count = 0;
for (CFIndex i=0; i<size; i++) {
CFStringRef item = (CFStringRef) CFArrayGetValueAtIndex(inArray, i);
BString bstr(item);
::SafeArrayPutElement(sa, &count, bstr); // SafeArrayPutElement() copies the string correctly.
count++;
}
return sa;
}
// utility method to store a 1-dim int vector into a newly created SAFEARRAY
SAFEARRAY* MarshallingHelpers::intArrayToSafeArray(CFArrayRef inArray)
{
CFIndex size = CFArrayGetCount(inArray);
SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, (ULONG) size, 0);
long count = 0;
for (CFIndex i=0; i<size; i++) {
CFNumberRef item = (CFNumberRef) CFArrayGetValueAtIndex(inArray, i);
int number = CFNumberRefToInt(item);
::SafeArrayPutElement(sa, &count, &number);
count++;
}
return sa;
}
#endif
SAFEARRAY* MarshallingHelpers::intRectToSafeArray(const WebCore::IntRect& rect)
{
SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, 4, 0);
long count = 0;
int value;
value = rect.x();
::SafeArrayPutElement(sa, &count, &value);
count++;
value = rect.y();
::SafeArrayPutElement(sa, &count, &value);
count++;
value = rect.width();
::SafeArrayPutElement(sa, &count, &value);
count++;
value = rect.height();
::SafeArrayPutElement(sa, &count, &value);
count++;
return sa;
}
#if USE(CF)
// utility method to store a 1-dim IUnknown* vector into a newly created SAFEARRAY
SAFEARRAY* MarshallingHelpers::iunknownArrayToSafeArray(CFArrayRef inArray)
{
CFIndex size = CFArrayGetCount(inArray);
SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_UNKNOWN, 0, (ULONG) size, (LPVOID)&IID_IUnknown);
long count = 0;
for (CFIndex i=0; i<size; i++) {
IUnknown* item = (IUnknown*) CFArrayGetValueAtIndex(inArray, i);
::SafeArrayPutElement(sa, &count, item); // SafeArrayPutElement() adds a reference to the IUnknown added
count++;
}
return sa;
}
CFArrayRef MarshallingHelpers::safeArrayToStringArray(SAFEARRAY* inArray)
{
long lBound=0, uBound=-1;
HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
if (SUCCEEDED(hr))
hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
Vector<CFStringRef> items;
if (len > 0) {
items.resize(len);
for (; lBound <= uBound; lBound++) {
BString str;
hr = ::SafeArrayGetElement(inArray, &lBound, &str);
items[lBound] = BSTRToCFStringRef(str);
}
}
CFArrayRef result = CFArrayCreate(0, (const void**)items.data(), len, &kCFTypeArrayCallBacks);
return result;
}
CFArrayRef MarshallingHelpers::safeArrayToIntArray(SAFEARRAY* inArray)
{
long lBound=0, uBound=-1;
HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
if (SUCCEEDED(hr))
hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
Vector<CFNumberRef> items;
if (len > 0) {
items.resize(len);
for (; lBound <= uBound; lBound++) {
int num = 0;
hr = ::SafeArrayGetElement(inArray, &lBound, &num);
items[lBound] = SUCCEEDED(hr) ? intToCFNumberRef(num) : kCFNumberNaN;
}
}
CFArrayRef result = CFArrayCreate(0, (const void**)items.data(), len, &kCFTypeArrayCallBacks);
return result;
}
CFArrayRef MarshallingHelpers::safeArrayToIUnknownArray(SAFEARRAY* inArray)
{
long lBound=0, uBound=-1;
HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
if (SUCCEEDED(hr))
hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
void* items = nullptr;
hr = ::SafeArrayAccessData(inArray, &items);
CFArrayRef result = SUCCEEDED(hr) ? CFArrayCreate(0, (const void**) items, len, &kIUnknownArrayCallBacks) : nullptr;
hr = ::SafeArrayUnaccessData(inArray);
return result;
}
const void* MarshallingHelpers::IUnknownRetainCallback(CFAllocatorRef /*allocator*/, const void* value)
{
((IUnknown*) value)->AddRef();
return value;
}
void MarshallingHelpers::IUnknownReleaseCallback(CFAllocatorRef /*allocator*/, const void* value)
{
((IUnknown*) value)->Release();
}
#endif