SQLCollations.cpp (7553B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/intl/Collator.h" 8 9 #include "SQLCollations.h" 10 11 using mozilla::intl::Collator; 12 13 namespace mozilla { 14 namespace storage { 15 16 //////////////////////////////////////////////////////////////////////////////// 17 //// Local Helper Functions 18 19 namespace { 20 21 /** 22 * Helper function for the UTF-8 locale collations. 23 * 24 * @param aService 25 * The Service that owns the collator used by this collation. 26 * @param aLen1 27 * The number of bytes in aStr1. 28 * @param aStr1 29 * The string to be compared against aStr2 as provided by SQLite. It 30 * must be a non-null-terminated char* buffer. 31 * @param aLen2 32 * The number of bytes in aStr2. 33 * @param aStr2 34 * The string to be compared against aStr1 as provided by SQLite. It 35 * must be a non-null-terminated char* buffer. 36 * @param aSensitivity 37 * The sorting sensitivity. 38 * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number. 39 * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2, 40 * returns 0. 41 */ 42 int localeCollationHelper8(void* aService, int aLen1, const void* aStr1, 43 int aLen2, const void* aStr2, 44 Collator::Sensitivity aSensitivity) { 45 NS_ConvertUTF8toUTF16 str1(static_cast<const char*>(aStr1), aLen1); 46 NS_ConvertUTF8toUTF16 str2(static_cast<const char*>(aStr2), aLen2); 47 Service* serv = static_cast<Service*>(aService); 48 return serv->localeCompareStrings(str1, str2, aSensitivity); 49 } 50 51 /** 52 * Helper function for the UTF-16 locale collations. 53 * 54 * @param aService 55 * The Service that owns the collator used by this collation. 56 * @param aLen1 57 * The number of bytes (not characters) in aStr1. 58 * @param aStr1 59 * The string to be compared against aStr2 as provided by SQLite. It 60 * must be a non-null-terminated char16_t* buffer. 61 * @param aLen2 62 * The number of bytes (not characters) in aStr2. 63 * @param aStr2 64 * The string to be compared against aStr1 as provided by SQLite. It 65 * must be a non-null-terminated char16_t* buffer. 66 * @param aSensitivity 67 * The sorting sensitivity. 68 * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number. 69 * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2, 70 * returns 0. 71 */ 72 int localeCollationHelper16(void* aService, int aLen1, const void* aStr1, 73 int aLen2, const void* aStr2, 74 Collator::Sensitivity aSensitivity) { 75 const char16_t* buf1 = static_cast<const char16_t*>(aStr1); 76 const char16_t* buf2 = static_cast<const char16_t*>(aStr2); 77 78 // The second argument to the nsDependentSubstring constructor is exclusive: 79 // It points to the char16_t immediately following the last one in the target 80 // substring. Since aLen1 and aLen2 are in bytes, divide by sizeof(char16_t) 81 // so that the pointer arithmetic is correct. 82 nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t))); 83 nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t))); 84 Service* serv = static_cast<Service*>(aService); 85 return serv->localeCompareStrings(str1, str2, aSensitivity); 86 } 87 88 // This struct is used only by registerCollations below, but ISO C++98 forbids 89 // instantiating a template dependent on a locally-defined type. Boo-urns! 90 struct Collations { 91 const char* zName; 92 int enc; 93 int (*xCompare)(void*, int, const void*, int, const void*); 94 }; 95 96 } // namespace 97 98 //////////////////////////////////////////////////////////////////////////////// 99 //// Exposed Functions 100 101 int registerCollations(sqlite3* aDB, Service* aService) { 102 Collations collations[] = { 103 {"locale", SQLITE_UTF8, localeCollation8}, 104 {"locale_case_sensitive", SQLITE_UTF8, localeCollationCaseSensitive8}, 105 {"locale_accent_sensitive", SQLITE_UTF8, localeCollationAccentSensitive8}, 106 {"locale_case_accent_sensitive", SQLITE_UTF8, 107 localeCollationCaseAccentSensitive8}, 108 {"locale", SQLITE_UTF16_ALIGNED, localeCollation16}, 109 {"locale_case_sensitive", SQLITE_UTF16_ALIGNED, 110 localeCollationCaseSensitive16}, 111 {"locale_accent_sensitive", SQLITE_UTF16_ALIGNED, 112 localeCollationAccentSensitive16}, 113 {"locale_case_accent_sensitive", SQLITE_UTF16_ALIGNED, 114 localeCollationCaseAccentSensitive16}, 115 }; 116 117 int rv = SQLITE_OK; 118 for (size_t i = 0; SQLITE_OK == rv && i < std::size(collations); ++i) { 119 struct Collations* p = &collations[i]; 120 rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService, 121 p->xCompare); 122 } 123 124 return rv; 125 } 126 127 //////////////////////////////////////////////////////////////////////////////// 128 //// SQL Collations 129 130 int localeCollation8(void* aService, int aLen1, const void* aStr1, int aLen2, 131 const void* aStr2) { 132 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 133 Collator::Sensitivity::Base); 134 } 135 136 int localeCollationCaseSensitive8(void* aService, int aLen1, const void* aStr1, 137 int aLen2, const void* aStr2) { 138 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 139 Collator::Sensitivity::Case); 140 } 141 142 int localeCollationAccentSensitive8(void* aService, int aLen1, 143 const void* aStr1, int aLen2, 144 const void* aStr2) { 145 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 146 Collator::Sensitivity::Accent); 147 } 148 149 int localeCollationCaseAccentSensitive8(void* aService, int aLen1, 150 const void* aStr1, int aLen2, 151 const void* aStr2) { 152 return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 153 Collator::Sensitivity::Variant); 154 } 155 156 int localeCollation16(void* aService, int aLen1, const void* aStr1, int aLen2, 157 const void* aStr2) { 158 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 159 Collator::Sensitivity::Base); 160 } 161 162 int localeCollationCaseSensitive16(void* aService, int aLen1, const void* aStr1, 163 int aLen2, const void* aStr2) { 164 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 165 Collator::Sensitivity::Case); 166 } 167 168 int localeCollationAccentSensitive16(void* aService, int aLen1, 169 const void* aStr1, int aLen2, 170 const void* aStr2) { 171 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 172 Collator::Sensitivity::Accent); 173 } 174 175 int localeCollationCaseAccentSensitive16(void* aService, int aLen1, 176 const void* aStr1, int aLen2, 177 const void* aStr2) { 178 return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 179 Collator::Sensitivity::Variant); 180 } 181 182 } // namespace storage 183 } // namespace mozilla