JS_XDRString(JSXDRState *xdr, JSString **strp) { uint32 i, len, padlen, nbytes; jschar *chars = NULL, *raw; if (xdr->mode == JSXDR_ENCODE) len = JSSTRING_LENGTH(*strp); if (!JS_XDRUint32(xdr, &len)) return JS_FALSE; nbytes = len * sizeof(jschar); if (xdr->mode == JSXDR_DECODE) { if (!(chars = (jschar *) JS_malloc(xdr->cx, nbytes + sizeof(jschar)))) return JS_FALSE; } else { chars = JSSTRING_CHARS(*strp); } padlen = nbytes % JSXDR_ALIGN; if (padlen) { padlen = JSXDR_ALIGN - padlen; nbytes += padlen; } if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes))) goto bad; if (xdr->mode == JSXDR_ENCODE) { for (i = 0; i < len; i++) raw[i] = JSXDR_SWAB16(chars[i]); if (padlen) memset((char *)raw + nbytes - padlen, 0, padlen); } else if (xdr->mode == JSXDR_DECODE) { for (i = 0; i < len; i++) chars[i] = JSXDR_SWAB16(raw[i]); chars[len] = 0; if (!(*strp = JS_NewUCString(xdr->cx, chars, len))) goto bad; } return JS_TRUE; bad: if (xdr->mode == JSXDR_DECODE) JS_free(xdr->cx, chars); return JS_FALSE; }
JSString* str_from_binary(JSContext* cx, char* data, size_t length) { jschar* conv = (jschar*) JS_malloc(cx, length * sizeof(jschar)); JSString* ret = NULL; size_t i; if(!conv) return NULL; for(i = 0; i < length; i++) { conv[i] = (jschar) data[i]; } ret = JS_NewUCString(cx, conv, length); if(!ret) JS_free(cx, conv); return ret; }
JSBool gjs_string_from_utf8(JSContext *context, const char *utf8_string, gssize n_bytes, jsval *value_p) { jschar *u16_string; glong u16_string_length; JSString *str; GError *error; /* intentionally using n_bytes even though glib api suggests n_chars; with * n_chars (from g_utf8_strlen()) the result appears truncated */ error = NULL; u16_string = g_utf8_to_utf16(utf8_string, n_bytes, NULL, &u16_string_length, &error); if (!u16_string) { gjs_throw(context, "Failed to convert UTF-8 string to " "JS string: %s", error->message); g_error_free(error); return JS_FALSE; } JS_BeginRequest(context); /* Avoid a copy - assumes that g_malloc == js_malloc == malloc */ str = JS_NewUCString(context, u16_string, u16_string_length); if (str && value_p) *value_p = STRING_TO_JSVAL(str); JS_EndRequest(context); return str != NULL; }
bool gjs_string_from_utf8(JSContext *context, const char *utf8_string, ssize_t n_bytes, JS::MutableHandleValue value_p) { char16_t *u16_string; glong u16_string_length; GError *error; /* intentionally using n_bytes even though glib api suggests n_chars; with * n_chars (from g_utf8_strlen()) the result appears truncated */ error = NULL; u16_string = reinterpret_cast<char16_t *>(g_utf8_to_utf16(utf8_string, n_bytes, NULL, &u16_string_length, &error)); if (!u16_string) { gjs_throw(context, "Failed to convert UTF-8 string to " "JS string: %s", error->message); g_error_free(error); return false; } JS_BeginRequest(context); /* Avoid a copy - assumes that g_malloc == js_malloc == malloc */ JS::RootedString str(context, JS_NewUCString(context, u16_string, u16_string_length)); if (str) value_p.setString(str); JS_EndRequest(context); return str != NULL; }
jsval to_js_string(ErlNifEnv* env, JSContext* cx, ERL_NIF_TERM term) { ErlNifBinary bin; JSString* str; jschar* chars; size_t charslen; if(!enif_inspect_binary(env, term, &bin)) { return JSVAL_VOID; } if(!JS_DecodeBytes(cx, (char*) bin.data, bin.size, NULL, &charslen)) { return JSVAL_VOID; } chars = JS_malloc(cx, (charslen + 1) * sizeof(jschar)); if(chars == NULL) return JSVAL_VOID; if(!JS_DecodeBytes(cx, (char*) bin.data, bin.size, chars, &charslen)) { JS_free(cx, chars); return JSVAL_VOID; } chars[charslen] = '\0'; str = JS_NewUCString(cx, chars, charslen); if(!str) { JS_free(cx, chars); return JSVAL_VOID; } return STRING_TO_JSVAL(str); }
JSBool ToUnicode(JSContext* cx, const char* src, jsval* rval) { nsresult rv; if (!mDecoder) { // use app default locale nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsILocale> appLocale; rv = localeService->GetApplicationLocale(getter_AddRefs(appLocale)); if (NS_SUCCEEDED(rv)) { nsAutoString localeStr; rv = appLocale-> GetCategory(NS_LITERAL_STRING(NSILOCALE_TIME), localeStr); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get app locale info"); nsCOMPtr<nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { nsCAutoString charset; rv = platformCharset->GetDefaultCharsetForLocale(localeStr, charset); if (NS_SUCCEEDED(rv)) { // get/create unicode decoder for charset nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) ccm->GetUnicodeDecoder(charset.get(), getter_AddRefs(mDecoder)); } } } } } JSString *str = nsnull; PRInt32 srcLength = PL_strlen(src); if (mDecoder) { PRInt32 unicharLength = srcLength; PRUnichar *unichars = (PRUnichar *)JS_malloc(cx, (srcLength + 1) * sizeof(PRUnichar)); if (unichars) { rv = mDecoder->Convert(src, &srcLength, unichars, &unicharLength); if (NS_SUCCEEDED(rv)) { // terminate the returned string unichars[unicharLength] = 0; // nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars if (unicharLength + 1 < srcLength + 1) { PRUnichar *shrunkUnichars = (PRUnichar *)JS_realloc(cx, unichars, (unicharLength + 1) * sizeof(PRUnichar)); if (shrunkUnichars) unichars = shrunkUnichars; } str = JS_NewUCString(cx, reinterpret_cast<jschar*>(unichars), unicharLength); } if (!str) JS_free(cx, unichars); } } if (!str) { nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_OUT_OF_MEMORY); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); return JS_TRUE; }
// 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); }
JSBool openfiledlg(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) { JSObject * filterArray = NULL; LPWSTR initialDirectory = NULL; LPWSTR dlgTitle = NULL; LPWSTR defaultExtension = NULL; JSBool save = JS_FALSE; JS_BeginRequest(cx); if(!JS_ConvertArguments(cx, argc, argv, "W W W o/ b", &initialDirectory, &defaultExtension, &dlgTitle, &filterArray, &save)) { JS_ReportError(cx, "Error parsing arguments in OpenFileDialog"); JS_EndRequest(cx); return JS_FALSE; } jsuint nFilters; JS_GetArrayLength(cx, filterArray, &nFilters); LPWSTR filterBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (50 * nFilters) * sizeof(WCHAR)); long filterBufferUsed = 0, filterBufferSize = (50 * nFilters); for(jsuint i = 0; i < nFilters; i++) { jsval curFilter; JS_GetElement(cx, filterArray, i, &curFilter); JSString * curFilterString = JS_ValueToString(cx, curFilter); LPWSTR curFilterRaw = (LPWSTR)JS_GetStringChars(curFilterString); int delta = wcslen(curFilterRaw); if(filterBufferSize - ( 2 + JS_GetStringLength(curFilterString) + filterBufferUsed) <= 0) { filterBufferSize += 50; HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, filterBuffer, filterBufferSize * sizeof(WCHAR)); } wcscpy_s(filterBuffer + filterBufferUsed, filterBufferSize - filterBufferUsed, (LPWSTR)JS_GetStringChars(curFilterString)); filterBufferUsed += JS_GetStringLength(curFilterString) + 1; } filterBuffer[filterBufferUsed] = TEXT('\0'); OPENFILENAME ofn; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.lpstrFilter = filterBuffer; ofn.nFilterIndex = 0; ofn.lpstrFile = (LPWSTR)JS_malloc(cx, 260 * sizeof(WCHAR)); memset(ofn.lpstrFile, 0, sizeof(WCHAR) * 260); ofn.nMaxFile = 260; ofn.lpstrFileTitle = (LPWSTR)JS_malloc(cx, 260 * sizeof(WCHAR)); memset(ofn.lpstrFileTitle, 0, sizeof(WCHAR) * 260); ofn.nMaxFileTitle = 260; ofn.lpstrInitialDir = initialDirectory; ofn.lpstrTitle = dlgTitle; ofn.lpstrDefExt = defaultExtension; ofn.lpfnHook = OFN_Hook; ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; jsrefcount rCount = JS_SuspendRequest(cx); BOOL ok; if(save) ok = GetSaveFileName(&ofn); else ok = GetOpenFileName(&ofn); DWORD errorCode = CommDlgExtendedError(); HeapFree(GetProcessHeap(), 0, filterBuffer); JS_ResumeRequest(cx, rCount); if(!ok) { JS_free(cx, ofn.lpstrFile); JS_free(cx, ofn.lpstrFileTitle); *rval = JSVAL_FALSE; return JS_TRUE; } JSObject * retObj = JS_NewObject(cx, NULL, NULL, obj); *rval = OBJECT_TO_JSVAL(retObj); jsval filePathVal = STRING_TO_JSVAL(JS_NewUCString(cx, (jschar*)ofn.lpstrFile, wcslen(ofn.lpstrFile))); JS_DefineProperty(cx, retObj, "filePath", filePathVal, NULL, NULL, JSPROP_PERMANENT | JSPROP_ENUMERATE); jsval fileTitleVal = STRING_TO_JSVAL(JS_NewUCString(cx, (jschar*)ofn.lpstrFileTitle, wcslen(ofn.lpstrFileTitle))); JS_DefineProperty(cx, retObj, "fileTitle", fileTitleVal, NULL, NULL, JSPROP_PERMANENT | JSPROP_ENUMERATE); JS_EndRequest(cx); return JS_TRUE; }