Back to index

lightning-sunbird  0.9+nobinonly
xpcstring.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 2001
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Mike Shaver <shaver@mozilla.org>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 /*
00042  * Infrastructure for sharing DOMString data with JSStrings.
00043  *
00044  * Importing an nsAString into JS:
00045  * If possible (GetSharedBufferHandle works) use the external string support in
00046  * JS to create a JSString that points to the readable's buffer.  We keep a
00047  * reference to the buffer handle until the JSString is finalized.
00048  *
00049  * Exporting a JSString as an nsAReadable:
00050  * Wrap the JSString with a root-holding XPCJSReadableStringWrapper, which roots
00051  * the string and exposes its buffer via the nsAString interface, as
00052  * well as providing refcounting support.
00053  */
00054 
00055 #include "xpcprivate.h"
00056 #include "nsStringBuffer.h"
00057 
00058 static int sDOMStringFinalizerIndex = -1;
00059 
00060 static void JS_DLL_CALLBACK
00061 DOMStringFinalizer(JSContext *cx, JSString *str)
00062 {
00063     nsStringBuffer::FromData(JS_GetStringChars(str))->Release();
00064 }
00065 
00066 void
00067 XPCStringConvert::ShutdownDOMStringFinalizer()
00068 {
00069     if (sDOMStringFinalizerIndex == -1)
00070         return;
00071 
00072     JS_RemoveExternalStringFinalizer(DOMStringFinalizer);
00073     sDOMStringFinalizerIndex = -1;
00074 }
00075 
00076 // convert a readable to a JSString, copying string data
00077 // static
00078 JSString *
00079 XPCStringConvert::ReadableToJSString(JSContext *cx,
00080                                      const nsAString &readable)
00081 {
00082     JSString *str;
00083 
00084     PRUint32 length = readable.Length();
00085 
00086     nsStringBuffer *buf = nsStringBuffer::FromString(readable);
00087     if (buf)
00088     {
00089         // yay, we can share the string's buffer!
00090 
00091         if (sDOMStringFinalizerIndex == -1)
00092         {
00093             sDOMStringFinalizerIndex =
00094                     JS_AddExternalStringFinalizer(DOMStringFinalizer);
00095             if (sDOMStringFinalizerIndex == -1)
00096                 return NULL;
00097         }
00098 
00099         str = JS_NewExternalString(cx, 
00100                                    NS_REINTERPRET_CAST(jschar *, buf->Data()),
00101                                    length, sDOMStringFinalizerIndex);
00102 
00103         if (str)
00104             buf->AddRef();
00105     }
00106     else
00107     {
00108         // blech, have to copy.
00109 
00110         jschar *chars = NS_REINTERPRET_CAST(jschar *,
00111                                             JS_malloc(cx, (length + 1) *
00112                                                       sizeof(jschar)));
00113         if (!chars)
00114             return NULL;
00115 
00116         if (length && !CopyUnicodeTo(readable, 0,
00117                                      NS_REINTERPRET_CAST(PRUnichar *, chars),
00118                                      length))
00119         {
00120             JS_free(cx, chars);
00121             return NULL;
00122         }
00123 
00124         chars[length] = 0;
00125 
00126         str = JS_NewUCString(cx, chars, length);
00127         if (!str)
00128             JS_free(cx, chars);
00129     }
00130     return str;
00131 }
00132 
00133 // static
00134 XPCReadableJSStringWrapper *
00135 XPCStringConvert::JSStringToReadable(JSString *str)
00136 {
00137     return new
00138         XPCReadableJSStringWrapper(NS_REINTERPRET_CAST(PRUnichar *,
00139                                                        JS_GetStringChars(str)),
00140                                    JS_GetStringLength(str));
00141 }