Line data Source code
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/ArrayUtils.h"
8 :
9 : #include "SQLCollations.h"
10 :
11 : namespace mozilla {
12 : namespace storage {
13 :
14 : ////////////////////////////////////////////////////////////////////////////////
15 : //// Local Helper Functions
16 :
17 : namespace {
18 :
19 : /**
20 : * Helper function for the UTF-8 locale collations.
21 : *
22 : * @param aService
23 : * The Service that owns the nsICollation used by this collation.
24 : * @param aLen1
25 : * The number of bytes in aStr1.
26 : * @param aStr1
27 : * The string to be compared against aStr2 as provided by SQLite. It
28 : * must be a non-null-terminated char* buffer.
29 : * @param aLen2
30 : * The number of bytes in aStr2.
31 : * @param aStr2
32 : * The string to be compared against aStr1 as provided by SQLite. It
33 : * must be a non-null-terminated char* buffer.
34 : * @param aComparisonStrength
35 : * The sorting strength, one of the nsICollation constants.
36 : * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
37 : * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
38 : * returns 0.
39 : */
40 : int
41 0 : localeCollationHelper8(void *aService,
42 : int aLen1,
43 : const void *aStr1,
44 : int aLen2,
45 : const void *aStr2,
46 : int32_t aComparisonStrength)
47 : {
48 0 : NS_ConvertUTF8toUTF16 str1(static_cast<const char *>(aStr1), aLen1);
49 0 : NS_ConvertUTF8toUTF16 str2(static_cast<const char *>(aStr2), aLen2);
50 0 : Service *serv = static_cast<Service *>(aService);
51 0 : return serv->localeCompareStrings(str1, str2, aComparisonStrength);
52 : }
53 :
54 : /**
55 : * Helper function for the UTF-16 locale collations.
56 : *
57 : * @param aService
58 : * The Service that owns the nsICollation used by this collation.
59 : * @param aLen1
60 : * The number of bytes (not characters) in aStr1.
61 : * @param aStr1
62 : * The string to be compared against aStr2 as provided by SQLite. It
63 : * must be a non-null-terminated char16_t* buffer.
64 : * @param aLen2
65 : * The number of bytes (not characters) in aStr2.
66 : * @param aStr2
67 : * The string to be compared against aStr1 as provided by SQLite. It
68 : * must be a non-null-terminated char16_t* buffer.
69 : * @param aComparisonStrength
70 : * The sorting strength, one of the nsICollation constants.
71 : * @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative number.
72 : * If aStr1 > aStr2, returns a positive number. If aStr1 == aStr2,
73 : * returns 0.
74 : */
75 : int
76 0 : localeCollationHelper16(void *aService,
77 : int aLen1,
78 : const void *aStr1,
79 : int aLen2,
80 : const void *aStr2,
81 : int32_t aComparisonStrength)
82 : {
83 0 : const char16_t *buf1 = static_cast<const char16_t *>(aStr1);
84 0 : const char16_t *buf2 = static_cast<const char16_t *>(aStr2);
85 :
86 : // The second argument to the nsDependentSubstring constructor is exclusive:
87 : // It points to the char16_t immediately following the last one in the target
88 : // substring. Since aLen1 and aLen2 are in bytes, divide by sizeof(char16_t)
89 : // so that the pointer arithmetic is correct.
90 0 : nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t)));
91 0 : nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t)));
92 0 : Service *serv = static_cast<Service *>(aService);
93 0 : return serv->localeCompareStrings(str1, str2, aComparisonStrength);
94 : }
95 :
96 : // This struct is used only by registerCollations below, but ISO C++98 forbids
97 : // instantiating a template dependent on a locally-defined type. Boo-urns!
98 : struct Collations {
99 : const char *zName;
100 : int enc;
101 : int(*xCompare)(void*, int, const void*, int, const void*);
102 : };
103 :
104 : } // namespace
105 :
106 : ////////////////////////////////////////////////////////////////////////////////
107 : //// Exposed Functions
108 :
109 : int
110 8 : registerCollations(sqlite3 *aDB,
111 : Service *aService)
112 : {
113 : Collations collations[] = {
114 : {"locale",
115 : SQLITE_UTF8,
116 : localeCollation8},
117 : {"locale_case_sensitive",
118 : SQLITE_UTF8,
119 : localeCollationCaseSensitive8},
120 : {"locale_accent_sensitive",
121 : SQLITE_UTF8,
122 : localeCollationAccentSensitive8},
123 : {"locale_case_accent_sensitive",
124 : SQLITE_UTF8,
125 : localeCollationCaseAccentSensitive8},
126 : {"locale",
127 : SQLITE_UTF16,
128 : localeCollation16},
129 : {"locale_case_sensitive",
130 : SQLITE_UTF16,
131 : localeCollationCaseSensitive16},
132 : {"locale_accent_sensitive",
133 : SQLITE_UTF16,
134 : localeCollationAccentSensitive16},
135 : {"locale_case_accent_sensitive",
136 : SQLITE_UTF16,
137 : localeCollationCaseAccentSensitive16},
138 8 : };
139 :
140 8 : int rv = SQLITE_OK;
141 72 : for (size_t i = 0; SQLITE_OK == rv && i < ArrayLength(collations); ++i) {
142 64 : struct Collations *p = &collations[i];
143 64 : rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService,
144 64 : p->xCompare);
145 : }
146 :
147 8 : return rv;
148 : }
149 :
150 : ////////////////////////////////////////////////////////////////////////////////
151 : //// SQL Collations
152 :
153 : int
154 0 : localeCollation8(void *aService,
155 : int aLen1,
156 : const void *aStr1,
157 : int aLen2,
158 : const void *aStr2)
159 : {
160 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
161 0 : nsICollation::kCollationCaseInSensitive);
162 : }
163 :
164 : int
165 0 : localeCollationCaseSensitive8(void *aService,
166 : int aLen1,
167 : const void *aStr1,
168 : int aLen2,
169 : const void *aStr2)
170 : {
171 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
172 0 : nsICollation::kCollationAccentInsenstive);
173 : }
174 :
175 : int
176 0 : localeCollationAccentSensitive8(void *aService,
177 : int aLen1,
178 : const void *aStr1,
179 : int aLen2,
180 : const void *aStr2)
181 : {
182 : return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
183 0 : nsICollation::kCollationCaseInsensitiveAscii);
184 : }
185 :
186 : int
187 0 : localeCollationCaseAccentSensitive8(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 0 : nsICollation::kCollationCaseSensitive);
195 : }
196 :
197 : int
198 0 : localeCollation16(void *aService,
199 : int aLen1,
200 : const void *aStr1,
201 : int aLen2,
202 : const void *aStr2)
203 : {
204 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
205 0 : nsICollation::kCollationCaseInSensitive);
206 : }
207 :
208 : int
209 0 : localeCollationCaseSensitive16(void *aService,
210 : int aLen1,
211 : const void *aStr1,
212 : int aLen2,
213 : const void *aStr2)
214 : {
215 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
216 0 : nsICollation::kCollationAccentInsenstive);
217 : }
218 :
219 : int
220 0 : localeCollationAccentSensitive16(void *aService,
221 : int aLen1,
222 : const void *aStr1,
223 : int aLen2,
224 : const void *aStr2)
225 : {
226 : return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
227 0 : nsICollation::kCollationCaseInsensitiveAscii);
228 : }
229 :
230 : int
231 0 : localeCollationCaseAccentSensitive16(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 0 : nsICollation::kCollationCaseSensitive);
239 : }
240 :
241 : } // namespace storage
242 : } // namespace mozilla
|