initial import
[vuplus_webkit] / Source / WebKit / win / MarshallingHelpers.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "WebKitDLL.h"
28 #include "MarshallingHelpers.h"
29 #include "MathExtras.h"
30
31 #include <WebCore/IntRect.h>
32 #include <WebCore/KURL.h>
33 #include <WebCore/PlatformString.h>
34
35 using namespace WebCore;
36
37 static const double secondsPerDay = 60 * 60 * 24;
38
39 CFArrayCallBacks MarshallingHelpers::kIUnknownArrayCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
40 CFDictionaryValueCallBacks MarshallingHelpers::kIUnknownDictionaryValueCallBacks = {0, IUnknownRetainCallback, IUnknownReleaseCallback, 0, 0};
41
42 KURL MarshallingHelpers::BSTRToKURL(BSTR urlStr)
43 {
44     return KURL(KURL(), String(urlStr, SysStringLen(urlStr)));
45 }
46
47 BSTR MarshallingHelpers::KURLToBSTR(const KURL& url)
48 {
49     return SysAllocStringLen(url.string().characters(), url.string().length());
50 }
51
52 CFURLRef MarshallingHelpers::PathStringToFileCFURLRef(const String& string)
53 {
54     CFStringRef cfPath = CFStringCreateWithCharactersNoCopy(0, (const UniChar*)string.characters(), string.length(), kCFAllocatorNull);
55     CFURLRef pathURL = CFURLCreateWithFileSystemPath(0, cfPath, kCFURLWindowsPathStyle, false);
56     CFRelease(cfPath);
57     return pathURL;
58 }
59
60 String MarshallingHelpers::FileCFURLRefToPathString(CFURLRef fileURL)
61 {
62     CFStringRef string = CFURLCopyFileSystemPath(fileURL, kCFURLWindowsPathStyle);
63     String result(string);
64     CFRelease(string);
65     return result;
66 }
67
68 CFURLRef MarshallingHelpers::BSTRToCFURLRef(BSTR urlStr)
69 {
70     CFStringRef urlCFString = BSTRToCFStringRef(urlStr);
71     if (!urlCFString)
72         return 0;
73
74     CFURLRef urlRef = CFURLCreateWithString(0, urlCFString, 0);
75     CFRelease(urlCFString);
76
77     return urlRef;
78 }
79
80 CFStringRef MarshallingHelpers::BSTRToCFStringRef(BSTR str)
81 {
82     return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), SysStringLen(str));
83 }
84
85 CFStringRef MarshallingHelpers::LPCOLESTRToCFStringRef(LPCOLESTR str)
86 {
87     return CFStringCreateWithCharacters(0, (const UniChar*)(str ? str : TEXT("")), (CFIndex)(str ? wcslen(str) : 0));
88 }
89
90 BSTR MarshallingHelpers::CFStringRefToBSTR(CFStringRef str)
91 {
92     if (!str)
93         return 0;
94
95     const UniChar* uniChars = CFStringGetCharactersPtr(str);
96     if (uniChars)
97         return SysAllocStringLen((LPCTSTR)uniChars, CFStringGetLength(str));
98
99     CFIndex length = CFStringGetLength(str);
100     BSTR bstr = SysAllocStringLen(0, length);
101     if (bstr) {
102         CFStringGetCharacters(str, CFRangeMake(0, length), (UniChar*)bstr);
103         bstr[length] = 0;
104     }
105     return bstr;
106 }
107
108 int MarshallingHelpers::CFNumberRefToInt(CFNumberRef num)
109 {
110     int number;
111     CFNumberGetValue(num, kCFNumberIntType, &number);
112     return number;
113 }
114
115 CFNumberRef MarshallingHelpers::intToCFNumberRef(int num)
116 {
117     return CFNumberCreate(0, kCFNumberSInt32Type, &num);
118 }
119
120 CFAbsoluteTime MarshallingHelpers::windowsEpochAbsoluteTime()
121 {
122     static CFAbsoluteTime windowsEpochAbsoluteTime = 0;
123     if (!windowsEpochAbsoluteTime) {
124         CFGregorianDate windowsEpochDate = {1899, 12, 30, 0, 0, 0.0};
125         windowsEpochAbsoluteTime = CFGregorianDateGetAbsoluteTime(windowsEpochDate, 0) / secondsPerDay;
126     }
127     return windowsEpochAbsoluteTime;
128 }
129
130 CFAbsoluteTime MarshallingHelpers::DATEToCFAbsoluteTime(DATE date)
131 {
132     // <http://msdn2.microsoft.com/en-us/library/ms221627.aspx>
133     // DATE: This is the same numbering system used by most spreadsheet programs,
134     // although some specify incorrectly that February 29, 1900 existed, and thus
135     // set January 1, 1900 to 1.0. The date can be converted to and from an MS-DOS
136     // representation using VariantTimeToDosDateTime, which is discussed in
137     // Conversion and Manipulation Functions.
138
139     // CFAbsoluteTime: Type used to represent a specific point in time relative
140     // to the absolute reference date of 1 Jan 2001 00:00:00 GMT.
141     // Absolute time is measured by the number of seconds between the reference
142     // date and the specified date. Negative values indicate dates/times before
143     // the reference date. Positive values indicate dates/times after the
144     // reference date.
145
146     return round((date + windowsEpochAbsoluteTime()) * secondsPerDay);
147 }
148
149 DATE MarshallingHelpers::CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime)
150 {
151     return (round(absoluteTime)/secondsPerDay - windowsEpochAbsoluteTime());
152 }
153
154 // utility method to store a 1-dim string vector into a newly created SAFEARRAY
155 SAFEARRAY* MarshallingHelpers::stringArrayToSafeArray(CFArrayRef inArray)
156 {
157     CFIndex size = CFArrayGetCount(inArray);
158     SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_BSTR, 0, (ULONG) size, 0);
159     long count = 0;
160     for (CFIndex i=0; i<size; i++) {
161         CFStringRef item = (CFStringRef) CFArrayGetValueAtIndex(inArray, i);
162         BSTR bstr = CFStringRefToBSTR(item);
163         ::SafeArrayPutElement(sa, &count, bstr);
164         SysFreeString(bstr);    // SafeArrayPutElement() should make a copy of the string
165         count++;
166     }
167     return sa;
168 }
169
170 // utility method to store a 1-dim int vector into a newly created SAFEARRAY
171 SAFEARRAY* MarshallingHelpers::intArrayToSafeArray(CFArrayRef inArray)
172 {
173     CFIndex size = CFArrayGetCount(inArray);
174     SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, (ULONG) size, 0);
175     long count = 0;
176     for (CFIndex i=0; i<size; i++) {
177         CFNumberRef item = (CFNumberRef) CFArrayGetValueAtIndex(inArray, i);
178         int number = CFNumberRefToInt(item);
179         ::SafeArrayPutElement(sa, &count, &number);
180         count++;
181     }
182     return sa;
183 }
184
185 SAFEARRAY* MarshallingHelpers::intRectToSafeArray(const WebCore::IntRect& rect)
186 {
187     SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_I4, 0, 4, 0);
188     long count = 0;
189     int value;
190
191     value = rect.x();
192     ::SafeArrayPutElement(sa, &count, &value);
193     count++;
194
195     value = rect.y();
196     ::SafeArrayPutElement(sa, &count, &value);
197     count++;
198
199     value = rect.width();
200     ::SafeArrayPutElement(sa, &count, &value);
201     count++;
202
203     value = rect.height();
204     ::SafeArrayPutElement(sa, &count, &value);
205     count++;
206
207     return sa;
208 }
209
210 // utility method to store a 1-dim IUnknown* vector into a newly created SAFEARRAY
211 SAFEARRAY* MarshallingHelpers::iunknownArrayToSafeArray(CFArrayRef inArray)
212 {
213     CFIndex size = CFArrayGetCount(inArray);
214     SAFEARRAY* sa = ::SafeArrayCreateVectorEx(VT_UNKNOWN, 0, (ULONG) size, (LPVOID)&IID_IUnknown);
215     long count = 0;
216     for (CFIndex i=0; i<size; i++) {
217         IUnknown* item = (IUnknown*) CFArrayGetValueAtIndex(inArray, i);
218         ::SafeArrayPutElement(sa, &count, item);    // SafeArrayPutElement() adds a reference to the IUnknown added
219         count++;
220     }
221     return sa;
222 }
223
224 CFArrayRef MarshallingHelpers::safeArrayToStringArray(SAFEARRAY* inArray)
225 {
226     long lBound=0, uBound=-1;
227     HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
228     if (SUCCEEDED(hr))
229         hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
230     long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
231     CFStringRef* items = 0;
232     if (len > 0) {
233         items = new CFStringRef[len];
234         for (; lBound <= uBound; lBound++) {
235             BSTR str;
236             hr = ::SafeArrayGetElement(inArray, &lBound, &str);
237             items[lBound] = BSTRToCFStringRef(str);
238             SysFreeString(str);
239         }
240     }
241     CFArrayRef result = CFArrayCreate(0, (const void**)items, len, &kCFTypeArrayCallBacks);
242     if (items)
243         delete[] items;
244     return result;
245 }
246
247 CFArrayRef MarshallingHelpers::safeArrayToIntArray(SAFEARRAY* inArray)
248 {
249     long lBound=0, uBound=-1;
250     HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
251     if (SUCCEEDED(hr))
252         hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
253     long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
254     CFNumberRef* items = 0;
255     if (len > 0) {
256         items = new CFNumberRef[len];
257         for (; lBound <= uBound; lBound++) {
258             int num;
259             hr = ::SafeArrayGetElement(inArray, &lBound, &num);
260             items[lBound] = intToCFNumberRef(num);
261         }
262     }
263     CFArrayRef result = CFArrayCreate(0, (const void**) items, len, &kCFTypeArrayCallBacks);
264     if (items)
265         delete[] items;
266     return result;
267 }
268
269 CFArrayRef MarshallingHelpers::safeArrayToIUnknownArray(SAFEARRAY* inArray)
270 {
271     long lBound=0, uBound=-1;
272     HRESULT hr = ::SafeArrayGetLBound(inArray, 1, &lBound);
273     if (SUCCEEDED(hr))
274         hr = ::SafeArrayGetUBound(inArray, 1, &uBound);
275     long len = (SUCCEEDED(hr)) ? (uBound-lBound+1) : 0;
276     void* items;
277     hr = ::SafeArrayAccessData(inArray, &items);
278     CFArrayRef result = CFArrayCreate(0, (const void**) items, len, &kIUnknownArrayCallBacks);
279     hr = ::SafeArrayUnaccessData(inArray);
280     return result;
281 }
282
283 const void* MarshallingHelpers::IUnknownRetainCallback(CFAllocatorRef /*allocator*/, const void* value)
284 {
285     ((IUnknown*) value)->AddRef();
286     return value;
287 }
288
289 void MarshallingHelpers::IUnknownReleaseCallback(CFAllocatorRef /*allocator*/, const void* value)
290 {
291     ((IUnknown*) value)->Release();
292 }