michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Note: we are already in the namepace mozilla::storage michael@0: michael@0: // Note 2: whoever #includes this file must provide implementations of michael@0: // sqlite3_T_* prior. michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// variantToSQLiteT Implementation michael@0: michael@0: template michael@0: int michael@0: variantToSQLiteT(T aObj, michael@0: nsIVariant *aValue) michael@0: { michael@0: // Allow to return nullptr not wrapped to nsIVariant for speed. michael@0: if (!aValue) michael@0: return sqlite3_T_null(aObj); michael@0: michael@0: uint16_t type; michael@0: (void)aValue->GetDataType(&type); michael@0: switch (type) { michael@0: case nsIDataType::VTYPE_INT8: michael@0: case nsIDataType::VTYPE_INT16: michael@0: case nsIDataType::VTYPE_INT32: michael@0: case nsIDataType::VTYPE_UINT8: michael@0: case nsIDataType::VTYPE_UINT16: michael@0: { michael@0: int32_t value; michael@0: nsresult rv = aValue->GetAsInt32(&value); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: return sqlite3_T_int(aObj, value); michael@0: } michael@0: case nsIDataType::VTYPE_UINT32: // Try to preserve full range michael@0: case nsIDataType::VTYPE_INT64: michael@0: // Data loss possible, but there is no unsigned types in SQLite michael@0: case nsIDataType::VTYPE_UINT64: michael@0: { michael@0: int64_t value; michael@0: nsresult rv = aValue->GetAsInt64(&value); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: return sqlite3_T_int64(aObj, value); michael@0: } michael@0: case nsIDataType::VTYPE_FLOAT: michael@0: case nsIDataType::VTYPE_DOUBLE: michael@0: { michael@0: double value; michael@0: nsresult rv = aValue->GetAsDouble(&value); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: return sqlite3_T_double(aObj, value); michael@0: } michael@0: case nsIDataType::VTYPE_BOOL: michael@0: { michael@0: bool value; michael@0: nsresult rv = aValue->GetAsBool(&value); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: return sqlite3_T_int(aObj, value ? 1 : 0); michael@0: } michael@0: case nsIDataType::VTYPE_CHAR: michael@0: case nsIDataType::VTYPE_CHAR_STR: michael@0: case nsIDataType::VTYPE_STRING_SIZE_IS: michael@0: case nsIDataType::VTYPE_UTF8STRING: michael@0: case nsIDataType::VTYPE_CSTRING: michael@0: { michael@0: nsAutoCString value; michael@0: // GetAsAUTF8String should never perform conversion when coming from michael@0: // 8-bit string types, and thus can accept strings with arbitrary encoding michael@0: // (including UTF8 and ASCII). michael@0: nsresult rv = aValue->GetAsAUTF8String(value); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: return sqlite3_T_text(aObj, value); michael@0: } michael@0: case nsIDataType::VTYPE_WCHAR: michael@0: case nsIDataType::VTYPE_DOMSTRING: michael@0: case nsIDataType::VTYPE_WCHAR_STR: michael@0: case nsIDataType::VTYPE_WSTRING_SIZE_IS: michael@0: case nsIDataType::VTYPE_ASTRING: michael@0: { michael@0: nsAutoString value; michael@0: // GetAsAString does proper conversion to UCS2 from all string-like types. michael@0: // It can be used universally without problems (unless someone implements michael@0: // their own variant, but that's their problem). michael@0: nsresult rv = aValue->GetAsAString(value); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: return sqlite3_T_text16(aObj, value); michael@0: } michael@0: case nsIDataType::VTYPE_VOID: michael@0: case nsIDataType::VTYPE_EMPTY: michael@0: case nsIDataType::VTYPE_EMPTY_ARRAY: michael@0: return sqlite3_T_null(aObj); michael@0: case nsIDataType::VTYPE_ARRAY: michael@0: { michael@0: uint16_t type; michael@0: nsIID iid; michael@0: uint32_t count; michael@0: void *data; michael@0: nsresult rv = aValue->GetAsArray(&type, &iid, &count, &data); michael@0: NS_ENSURE_SUCCESS(rv, SQLITE_MISMATCH); michael@0: michael@0: // Check to make sure it's a supported type. michael@0: NS_ASSERTION(type == nsIDataType::VTYPE_UINT8, michael@0: "Invalid type passed! You may leak!"); michael@0: if (type != nsIDataType::VTYPE_UINT8) { michael@0: // Technically this could leak with certain data types, but somebody was michael@0: // being stupid passing us this anyway. michael@0: NS_Free(data); michael@0: return SQLITE_MISMATCH; michael@0: } michael@0: michael@0: // Finally do our thing. The function should free the array accordingly! michael@0: int rc = sqlite3_T_blob(aObj, data, count); michael@0: return rc; michael@0: } michael@0: // Maybe, it'll be possible to convert these michael@0: // in future too. michael@0: case nsIDataType::VTYPE_ID: michael@0: case nsIDataType::VTYPE_INTERFACE: michael@0: case nsIDataType::VTYPE_INTERFACE_IS: michael@0: default: michael@0: return SQLITE_MISMATCH; michael@0: } michael@0: return SQLITE_OK; michael@0: }