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: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include "SQLCollations.h" michael@0: michael@0: namespace mozilla { michael@0: namespace storage { michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Local Helper Functions michael@0: michael@0: namespace { michael@0: michael@0: /** michael@0: * Helper function for the UTF-8 locale collations. michael@0: * michael@0: * @param aService michael@0: * The Service that owns the nsICollation used by this collation. michael@0: * @param aLen1 michael@0: * The number of bytes in aStr1. michael@0: * @param aStr1 michael@0: * The string to be compared against aStr2 as provided by SQLite. It michael@0: * must be a non-null-terminated char* buffer. michael@0: * @param aLen2 michael@0: * The number of bytes in aStr2. michael@0: * @param aStr2 michael@0: * The string to be compared against aStr1 as provided by SQLite. It michael@0: * must be a non-null-terminated char* buffer. michael@0: * @param aComparisonStrength michael@0: * The sorting strength, one of the nsICollation constants. michael@0: * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number. michael@0: * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2, michael@0: * returns 0. michael@0: */ michael@0: int michael@0: localeCollationHelper8(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2, michael@0: int32_t aComparisonStrength) michael@0: { michael@0: NS_ConvertUTF8toUTF16 str1(static_cast(aStr1), aLen1); michael@0: NS_ConvertUTF8toUTF16 str2(static_cast(aStr2), aLen2); michael@0: Service *serv = static_cast(aService); michael@0: return serv->localeCompareStrings(str1, str2, aComparisonStrength); michael@0: } michael@0: michael@0: /** michael@0: * Helper function for the UTF-16 locale collations. michael@0: * michael@0: * @param aService michael@0: * The Service that owns the nsICollation used by this collation. michael@0: * @param aLen1 michael@0: * The number of bytes (not characters) in aStr1. michael@0: * @param aStr1 michael@0: * The string to be compared against aStr2 as provided by SQLite. It michael@0: * must be a non-null-terminated char16_t* buffer. michael@0: * @param aLen2 michael@0: * The number of bytes (not characters) in aStr2. michael@0: * @param aStr2 michael@0: * The string to be compared against aStr1 as provided by SQLite. It michael@0: * must be a non-null-terminated char16_t* buffer. michael@0: * @param aComparisonStrength michael@0: * The sorting strength, one of the nsICollation constants. michael@0: * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number. michael@0: * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2, michael@0: * returns 0. michael@0: */ michael@0: int michael@0: localeCollationHelper16(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2, michael@0: int32_t aComparisonStrength) michael@0: { michael@0: const char16_t *buf1 = static_cast(aStr1); michael@0: const char16_t *buf2 = static_cast(aStr2); michael@0: michael@0: // The second argument to the nsDependentSubstring constructor is exclusive: michael@0: // It points to the char16_t immediately following the last one in the target michael@0: // substring. Since aLen1 and aLen2 are in bytes, divide by sizeof(char16_t) michael@0: // so that the pointer arithmetic is correct. michael@0: nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t))); michael@0: nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t))); michael@0: Service *serv = static_cast(aService); michael@0: return serv->localeCompareStrings(str1, str2, aComparisonStrength); michael@0: } michael@0: michael@0: // This struct is used only by registerCollations below, but ISO C++98 forbids michael@0: // instantiating a template dependent on a locally-defined type. Boo-urns! michael@0: struct Collations { michael@0: const char *zName; michael@0: int enc; michael@0: int(*xCompare)(void*, int, const void*, int, const void*); michael@0: }; michael@0: michael@0: } // anonymous namespace michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Exposed Functions michael@0: michael@0: int michael@0: registerCollations(sqlite3 *aDB, michael@0: Service *aService) michael@0: { michael@0: Collations collations[] = { michael@0: {"locale", michael@0: SQLITE_UTF8, michael@0: localeCollation8}, michael@0: {"locale_case_sensitive", michael@0: SQLITE_UTF8, michael@0: localeCollationCaseSensitive8}, michael@0: {"locale_accent_sensitive", michael@0: SQLITE_UTF8, michael@0: localeCollationAccentSensitive8}, michael@0: {"locale_case_accent_sensitive", michael@0: SQLITE_UTF8, michael@0: localeCollationCaseAccentSensitive8}, michael@0: {"locale", michael@0: SQLITE_UTF16, michael@0: localeCollation16}, michael@0: {"locale_case_sensitive", michael@0: SQLITE_UTF16, michael@0: localeCollationCaseSensitive16}, michael@0: {"locale_accent_sensitive", michael@0: SQLITE_UTF16, michael@0: localeCollationAccentSensitive16}, michael@0: {"locale_case_accent_sensitive", michael@0: SQLITE_UTF16, michael@0: localeCollationCaseAccentSensitive16}, michael@0: }; michael@0: michael@0: int rv = SQLITE_OK; michael@0: for (size_t i = 0; SQLITE_OK == rv && i < ArrayLength(collations); ++i) { michael@0: struct Collations *p = &collations[i]; michael@0: rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService, michael@0: p->xCompare); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// SQL Collations michael@0: michael@0: int michael@0: localeCollation8(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationCaseInSensitive); michael@0: } michael@0: michael@0: int michael@0: localeCollationCaseSensitive8(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationAccentInsenstive); michael@0: } michael@0: michael@0: int michael@0: localeCollationAccentSensitive8(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationCaseInsensitiveAscii); michael@0: } michael@0: michael@0: int michael@0: localeCollationCaseAccentSensitive8(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationCaseSensitive); michael@0: } michael@0: michael@0: int michael@0: localeCollation16(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationCaseInSensitive); michael@0: } michael@0: michael@0: int michael@0: localeCollationCaseSensitive16(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationAccentInsenstive); michael@0: } michael@0: michael@0: int michael@0: localeCollationAccentSensitive16(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationCaseInsensitiveAscii); michael@0: } michael@0: michael@0: int michael@0: localeCollationCaseAccentSensitive16(void *aService, michael@0: int aLen1, michael@0: const void *aStr1, michael@0: int aLen2, michael@0: const void *aStr2) michael@0: { michael@0: return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, michael@0: nsICollation::kCollationCaseSensitive); michael@0: } michael@0: michael@0: } // namespace storage michael@0: } // namespace mozilla