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 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Storage code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Mozilla Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 2009
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Drew Willcoxon <adw@mozilla.com> (Original Author)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "mozilla/Util.h"
41 :
42 : #include "SQLCollations.h"
43 :
44 : namespace mozilla {
45 : namespace storage {
46 :
47 : ////////////////////////////////////////////////////////////////////////////////
48 : //// Local Helper Functions
49 :
50 : namespace {
51 :
52 : /**
53 : * Helper function for the UTF-8 locale collations.
54 : *
55 : * @param aService
56 : * The Service that owns the nsICollation used by this collation.
57 : * @param aLen1
58 : * The number of bytes in aStr1.
59 : * @param aStr1
60 : * The string to be compared against aStr2 as provided by SQLite. It
61 : * must be a non-null-terminated char* buffer.
62 : * @param aLen2
63 : * The number of bytes in aStr2.
64 : * @param aStr2
65 : * The string to be compared against aStr1 as provided by SQLite. It
66 : * must be a non-null-terminated char* buffer.
67 : * @param aComparisonStrength
68 : * The sorting strength, one of the nsICollation constants.
69 : * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
70 : * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
71 : * returns 0.
72 : */
73 : int
74 3549 : localeCollationHelper8(void *aService,
75 : int aLen1,
76 : const void *aStr1,
77 : int aLen2,
78 : const void *aStr2,
79 : PRInt32 aComparisonStrength)
80 : {
81 7098 : NS_ConvertUTF8toUTF16 str1(static_cast<const char *>(aStr1), aLen1);
82 7098 : NS_ConvertUTF8toUTF16 str2(static_cast<const char *>(aStr2), aLen2);
83 3549 : Service *serv = static_cast<Service *>(aService);
84 3549 : return serv->localeCompareStrings(str1, str2, aComparisonStrength);
85 : }
86 :
87 : /**
88 : * Helper function for the UTF-16 locale collations.
89 : *
90 : * @param aService
91 : * The Service that owns the nsICollation used by this collation.
92 : * @param aLen1
93 : * The number of bytes (not characters) in aStr1.
94 : * @param aStr1
95 : * The string to be compared against aStr2 as provided by SQLite. It
96 : * must be a non-null-terminated PRUnichar* buffer.
97 : * @param aLen2
98 : * The number of bytes (not characters) in aStr2.
99 : * @param aStr2
100 : * The string to be compared against aStr1 as provided by SQLite. It
101 : * must be a non-null-terminated PRUnichar* buffer.
102 : * @param aComparisonStrength
103 : * The sorting strength, one of the nsICollation constants.
104 : * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
105 : * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
106 : * returns 0.
107 : */
108 : int
109 3549 : localeCollationHelper16(void *aService,
110 : int aLen1,
111 : const void *aStr1,
112 : int aLen2,
113 : const void *aStr2,
114 : PRInt32 aComparisonStrength)
115 : {
116 3549 : const PRUnichar *buf1 = static_cast<const PRUnichar *>(aStr1);
117 3549 : const PRUnichar *buf2 = static_cast<const PRUnichar *>(aStr2);
118 :
119 : // The second argument to the nsDependentSubstring constructor is exclusive:
120 : // It points to the PRUnichar immediately following the last one in the target
121 : // substring. Since aLen1 and aLen2 are in bytes, divide by sizeof(PRUnichar)
122 : // so that the pointer arithmetic is correct.
123 7098 : nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(PRUnichar)));
124 7098 : nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(PRUnichar)));
125 3549 : Service *serv = static_cast<Service *>(aService);
126 3549 : return serv->localeCompareStrings(str1, str2, aComparisonStrength);
127 : }
128 :
129 : // This struct is used only by registerCollations below, but ISO C++98 forbids
130 : // instantiating a template dependent on a locally-defined type. Boo-urns!
131 : struct Collations {
132 : const char *zName;
133 : int enc;
134 : int(*xCompare)(void*, int, const void*, int, const void*);
135 : };
136 :
137 : } // anonymous namespace
138 :
139 : ////////////////////////////////////////////////////////////////////////////////
140 : //// Exposed Functions
141 :
142 : int
143 3267 : registerCollations(sqlite3 *aDB,
144 : Service *aService)
145 : {
146 : Collations collations[] = {
147 : {"locale",
148 : SQLITE_UTF8,
149 : localeCollation8},
150 : {"locale_case_sensitive",
151 : SQLITE_UTF8,
152 : localeCollationCaseSensitive8},
153 : {"locale_accent_sensitive",
154 : SQLITE_UTF8,
155 : localeCollationAccentSensitive8},
156 : {"locale_case_accent_sensitive",
157 : SQLITE_UTF8,
158 : localeCollationCaseAccentSensitive8},
159 : {"locale",
160 : SQLITE_UTF16,
161 : localeCollation16},
162 : {"locale_case_sensitive",
163 : SQLITE_UTF16,
164 : localeCollationCaseSensitive16},
165 : {"locale_accent_sensitive",
166 : SQLITE_UTF16,
167 : localeCollationAccentSensitive16},
168 : {"locale_case_accent_sensitive",
169 : SQLITE_UTF16,
170 : localeCollationCaseAccentSensitive16},
171 3267 : };
172 :
173 3267 : int rv = SQLITE_OK;
174 29403 : for (size_t i = 0; SQLITE_OK == rv && i < ArrayLength(collations); ++i) {
175 26136 : struct Collations *p = &collations[i];
176 : rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService,
177 26136 : p->xCompare);
178 : }
179 :
180 3267 : return rv;
181 : }
182 :
183 : ////////////////////////////////////////////////////////////////////////////////
184 : //// SQL Collations
185 :
186 : int
187 886 : localeCollation8(void *aService,
188 : int aLen1,
189 : const void *aStr1,
190 : int aLen2,
191 : const void *aStr2)
192 : {
193 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
194 886 : nsICollation::kCollationCaseInSensitive);
195 : }
196 :
197 : int
198 886 : localeCollationCaseSensitive8(void *aService,
199 : int aLen1,
200 : const void *aStr1,
201 : int aLen2,
202 : const void *aStr2)
203 : {
204 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
205 886 : nsICollation::kCollationAccentInsenstive);
206 : }
207 :
208 : int
209 886 : localeCollationAccentSensitive8(void *aService,
210 : int aLen1,
211 : const void *aStr1,
212 : int aLen2,
213 : const void *aStr2)
214 : {
215 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
216 886 : nsICollation::kCollationCaseInsensitiveAscii);
217 : }
218 :
219 : int
220 891 : localeCollationCaseAccentSensitive8(void *aService,
221 : int aLen1,
222 : const void *aStr1,
223 : int aLen2,
224 : const void *aStr2)
225 : {
226 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
227 891 : nsICollation::kCollationCaseSensitive);
228 : }
229 :
230 : int
231 886 : localeCollation16(void *aService,
232 : int aLen1,
233 : const void *aStr1,
234 : int aLen2,
235 : const void *aStr2)
236 : {
237 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
238 886 : nsICollation::kCollationCaseInSensitive);
239 : }
240 :
241 : int
242 886 : localeCollationCaseSensitive16(void *aService,
243 : int aLen1,
244 : const void *aStr1,
245 : int aLen2,
246 : const void *aStr2)
247 : {
248 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
249 886 : nsICollation::kCollationAccentInsenstive);
250 : }
251 :
252 : int
253 886 : localeCollationAccentSensitive16(void *aService,
254 : int aLen1,
255 : const void *aStr1,
256 : int aLen2,
257 : const void *aStr2)
258 : {
259 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
260 886 : nsICollation::kCollationCaseInsensitiveAscii);
261 : }
262 :
263 : int
264 891 : localeCollationCaseAccentSensitive16(void *aService,
265 : int aLen1,
266 : const void *aStr1,
267 : int aLen2,
268 : const void *aStr2)
269 : {
270 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
271 891 : nsICollation::kCollationCaseSensitive);
272 : }
273 :
274 : } // namespace storage
275 : } // namespace mozilla
|