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