1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/src/SQLCollations.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,242 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "mozilla/ArrayUtils.h" 1.11 + 1.12 +#include "SQLCollations.h" 1.13 + 1.14 +namespace mozilla { 1.15 +namespace storage { 1.16 + 1.17 +//////////////////////////////////////////////////////////////////////////////// 1.18 +//// Local Helper Functions 1.19 + 1.20 +namespace { 1.21 + 1.22 +/** 1.23 + * Helper function for the UTF-8 locale collations. 1.24 + * 1.25 + * @param aService 1.26 + * The Service that owns the nsICollation used by this collation. 1.27 + * @param aLen1 1.28 + * The number of bytes in aStr1. 1.29 + * @param aStr1 1.30 + * The string to be compared against aStr2 as provided by SQLite. It 1.31 + * must be a non-null-terminated char* buffer. 1.32 + * @param aLen2 1.33 + * The number of bytes in aStr2. 1.34 + * @param aStr2 1.35 + * The string to be compared against aStr1 as provided by SQLite. It 1.36 + * must be a non-null-terminated char* buffer. 1.37 + * @param aComparisonStrength 1.38 + * The sorting strength, one of the nsICollation constants. 1.39 + * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number. 1.40 + * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2, 1.41 + * returns 0. 1.42 + */ 1.43 +int 1.44 +localeCollationHelper8(void *aService, 1.45 + int aLen1, 1.46 + const void *aStr1, 1.47 + int aLen2, 1.48 + const void *aStr2, 1.49 + int32_t aComparisonStrength) 1.50 +{ 1.51 + NS_ConvertUTF8toUTF16 str1(static_cast<const char *>(aStr1), aLen1); 1.52 + NS_ConvertUTF8toUTF16 str2(static_cast<const char *>(aStr2), aLen2); 1.53 + Service *serv = static_cast<Service *>(aService); 1.54 + return serv->localeCompareStrings(str1, str2, aComparisonStrength); 1.55 +} 1.56 + 1.57 +/** 1.58 + * Helper function for the UTF-16 locale collations. 1.59 + * 1.60 + * @param aService 1.61 + * The Service that owns the nsICollation used by this collation. 1.62 + * @param aLen1 1.63 + * The number of bytes (not characters) in aStr1. 1.64 + * @param aStr1 1.65 + * The string to be compared against aStr2 as provided by SQLite. It 1.66 + * must be a non-null-terminated char16_t* buffer. 1.67 + * @param aLen2 1.68 + * The number of bytes (not characters) in aStr2. 1.69 + * @param aStr2 1.70 + * The string to be compared against aStr1 as provided by SQLite. It 1.71 + * must be a non-null-terminated char16_t* buffer. 1.72 + * @param aComparisonStrength 1.73 + * The sorting strength, one of the nsICollation constants. 1.74 + * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number. 1.75 + * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2, 1.76 + * returns 0. 1.77 + */ 1.78 +int 1.79 +localeCollationHelper16(void *aService, 1.80 + int aLen1, 1.81 + const void *aStr1, 1.82 + int aLen2, 1.83 + const void *aStr2, 1.84 + int32_t aComparisonStrength) 1.85 +{ 1.86 + const char16_t *buf1 = static_cast<const char16_t *>(aStr1); 1.87 + const char16_t *buf2 = static_cast<const char16_t *>(aStr2); 1.88 + 1.89 + // The second argument to the nsDependentSubstring constructor is exclusive: 1.90 + // It points to the char16_t immediately following the last one in the target 1.91 + // substring. Since aLen1 and aLen2 are in bytes, divide by sizeof(char16_t) 1.92 + // so that the pointer arithmetic is correct. 1.93 + nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t))); 1.94 + nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t))); 1.95 + Service *serv = static_cast<Service *>(aService); 1.96 + return serv->localeCompareStrings(str1, str2, aComparisonStrength); 1.97 +} 1.98 + 1.99 +// This struct is used only by registerCollations below, but ISO C++98 forbids 1.100 +// instantiating a template dependent on a locally-defined type. Boo-urns! 1.101 +struct Collations { 1.102 + const char *zName; 1.103 + int enc; 1.104 + int(*xCompare)(void*, int, const void*, int, const void*); 1.105 +}; 1.106 + 1.107 +} // anonymous namespace 1.108 + 1.109 +//////////////////////////////////////////////////////////////////////////////// 1.110 +//// Exposed Functions 1.111 + 1.112 +int 1.113 +registerCollations(sqlite3 *aDB, 1.114 + Service *aService) 1.115 +{ 1.116 + Collations collations[] = { 1.117 + {"locale", 1.118 + SQLITE_UTF8, 1.119 + localeCollation8}, 1.120 + {"locale_case_sensitive", 1.121 + SQLITE_UTF8, 1.122 + localeCollationCaseSensitive8}, 1.123 + {"locale_accent_sensitive", 1.124 + SQLITE_UTF8, 1.125 + localeCollationAccentSensitive8}, 1.126 + {"locale_case_accent_sensitive", 1.127 + SQLITE_UTF8, 1.128 + localeCollationCaseAccentSensitive8}, 1.129 + {"locale", 1.130 + SQLITE_UTF16, 1.131 + localeCollation16}, 1.132 + {"locale_case_sensitive", 1.133 + SQLITE_UTF16, 1.134 + localeCollationCaseSensitive16}, 1.135 + {"locale_accent_sensitive", 1.136 + SQLITE_UTF16, 1.137 + localeCollationAccentSensitive16}, 1.138 + {"locale_case_accent_sensitive", 1.139 + SQLITE_UTF16, 1.140 + localeCollationCaseAccentSensitive16}, 1.141 + }; 1.142 + 1.143 + int rv = SQLITE_OK; 1.144 + for (size_t i = 0; SQLITE_OK == rv && i < ArrayLength(collations); ++i) { 1.145 + struct Collations *p = &collations[i]; 1.146 + rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService, 1.147 + p->xCompare); 1.148 + } 1.149 + 1.150 + return rv; 1.151 +} 1.152 + 1.153 +//////////////////////////////////////////////////////////////////////////////// 1.154 +//// SQL Collations 1.155 + 1.156 +int 1.157 +localeCollation8(void *aService, 1.158 + int aLen1, 1.159 + const void *aStr1, 1.160 + int aLen2, 1.161 + const void *aStr2) 1.162 +{ 1.163 + return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 1.164 + nsICollation::kCollationCaseInSensitive); 1.165 +} 1.166 + 1.167 +int 1.168 +localeCollationCaseSensitive8(void *aService, 1.169 + int aLen1, 1.170 + const void *aStr1, 1.171 + int aLen2, 1.172 + const void *aStr2) 1.173 +{ 1.174 + return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 1.175 + nsICollation::kCollationAccentInsenstive); 1.176 +} 1.177 + 1.178 +int 1.179 +localeCollationAccentSensitive8(void *aService, 1.180 + int aLen1, 1.181 + const void *aStr1, 1.182 + int aLen2, 1.183 + const void *aStr2) 1.184 +{ 1.185 + return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 1.186 + nsICollation::kCollationCaseInsensitiveAscii); 1.187 +} 1.188 + 1.189 +int 1.190 +localeCollationCaseAccentSensitive8(void *aService, 1.191 + int aLen1, 1.192 + const void *aStr1, 1.193 + int aLen2, 1.194 + const void *aStr2) 1.195 +{ 1.196 + return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2, 1.197 + nsICollation::kCollationCaseSensitive); 1.198 +} 1.199 + 1.200 +int 1.201 +localeCollation16(void *aService, 1.202 + int aLen1, 1.203 + const void *aStr1, 1.204 + int aLen2, 1.205 + const void *aStr2) 1.206 +{ 1.207 + return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 1.208 + nsICollation::kCollationCaseInSensitive); 1.209 +} 1.210 + 1.211 +int 1.212 +localeCollationCaseSensitive16(void *aService, 1.213 + int aLen1, 1.214 + const void *aStr1, 1.215 + int aLen2, 1.216 + const void *aStr2) 1.217 +{ 1.218 + return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 1.219 + nsICollation::kCollationAccentInsenstive); 1.220 +} 1.221 + 1.222 +int 1.223 +localeCollationAccentSensitive16(void *aService, 1.224 + int aLen1, 1.225 + const void *aStr1, 1.226 + int aLen2, 1.227 + const void *aStr2) 1.228 +{ 1.229 + return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 1.230 + nsICollation::kCollationCaseInsensitiveAscii); 1.231 +} 1.232 + 1.233 +int 1.234 +localeCollationCaseAccentSensitive16(void *aService, 1.235 + int aLen1, 1.236 + const void *aStr1, 1.237 + int aLen2, 1.238 + const void *aStr2) 1.239 +{ 1.240 + return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2, 1.241 + nsICollation::kCollationCaseSensitive); 1.242 +} 1.243 + 1.244 +} // namespace storage 1.245 +} // namespace mozilla