DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (d1ed7de67f5a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/ArrayUtils.h"

#include "SQLCollations.h"

namespace mozilla {
namespace storage {

////////////////////////////////////////////////////////////////////////////////
//// Local Helper Functions

namespace {

/**
 * Helper function for the UTF-8 locale collations.
 *
 * @param  aService
 *         The Service that owns the nsICollation used by this collation.
 * @param  aLen1
 *         The number of bytes in aStr1.
 * @param  aStr1
 *         The string to be compared against aStr2 as provided by SQLite.  It
 *         must be a non-null-terminated char* buffer.
 * @param  aLen2
 *         The number of bytes in aStr2.
 * @param  aStr2
 *         The string to be compared against aStr1 as provided by SQLite.  It
 *         must be a non-null-terminated char* buffer.
 * @param  aComparisonStrength
 *         The sorting strength, one of the nsICollation constants.
 * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
 *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
 *         returns 0.
 */
int
localeCollationHelper8(void *aService,
                       int aLen1,
                       const void *aStr1,
                       int aLen2,
                       const void *aStr2,
                       int32_t aComparisonStrength)
{
  NS_ConvertUTF8toUTF16 str1(static_cast<const char *>(aStr1), aLen1);
  NS_ConvertUTF8toUTF16 str2(static_cast<const char *>(aStr2), aLen2);
  Service *serv = static_cast<Service *>(aService);
  return serv->localeCompareStrings(str1, str2, aComparisonStrength);
}

/**
 * Helper function for the UTF-16 locale collations.
 *
 * @param  aService
 *         The Service that owns the nsICollation used by this collation.
 * @param  aLen1
 *         The number of bytes (not characters) in aStr1.
 * @param  aStr1
 *         The string to be compared against aStr2 as provided by SQLite.  It
 *         must be a non-null-terminated char16_t* buffer.
 * @param  aLen2
 *         The number of bytes (not characters) in aStr2.
 * @param  aStr2
 *         The string to be compared against aStr1 as provided by SQLite.  It
 *         must be a non-null-terminated char16_t* buffer.
 * @param  aComparisonStrength
 *         The sorting strength, one of the nsICollation constants.
 * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
 *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
 *         returns 0.
 */
int
localeCollationHelper16(void *aService,
                        int aLen1,
                        const void *aStr1,
                        int aLen2,
                        const void *aStr2,
                        int32_t aComparisonStrength)
{
  const char16_t *buf1 = static_cast<const char16_t *>(aStr1);
  const char16_t *buf2 = static_cast<const char16_t *>(aStr2);

  // The second argument to the nsDependentSubstring constructor is exclusive:
  // It points to the char16_t immediately following the last one in the target
  // substring.  Since aLen1 and aLen2 are in bytes, divide by sizeof(char16_t)
  // so that the pointer arithmetic is correct.
  nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(char16_t)));
  nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(char16_t)));
  Service *serv = static_cast<Service *>(aService);
  return serv->localeCompareStrings(str1, str2, aComparisonStrength);
}

// This struct is used only by registerCollations below, but ISO C++98 forbids
// instantiating a template dependent on a locally-defined type.  Boo-urns!
struct Collations {
  const char *zName;
  int enc;
  int(*xCompare)(void*, int, const void*, int, const void*);
};

} // anonymous namespace

////////////////////////////////////////////////////////////////////////////////
//// Exposed Functions

int
registerCollations(sqlite3 *aDB,
                   Service *aService)
{
  Collations collations[] = {
    {"locale",
     SQLITE_UTF8,
     localeCollation8},
    {"locale_case_sensitive",
     SQLITE_UTF8,
     localeCollationCaseSensitive8},
    {"locale_accent_sensitive",
     SQLITE_UTF8,
     localeCollationAccentSensitive8},
    {"locale_case_accent_sensitive",
     SQLITE_UTF8,
     localeCollationCaseAccentSensitive8},
    {"locale",
     SQLITE_UTF16,
     localeCollation16},
    {"locale_case_sensitive",
     SQLITE_UTF16,
     localeCollationCaseSensitive16},
    {"locale_accent_sensitive",
     SQLITE_UTF16,
     localeCollationAccentSensitive16},
    {"locale_case_accent_sensitive",
     SQLITE_UTF16,
     localeCollationCaseAccentSensitive16},
  };

  int rv = SQLITE_OK;
  for (size_t i = 0; SQLITE_OK == rv && i < ArrayLength(collations); ++i) {
    struct Collations *p = &collations[i];
    rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService,
                                    p->xCompare);
  }

  return rv;
}

////////////////////////////////////////////////////////////////////////////////
//// SQL Collations

int
localeCollation8(void *aService,
                 int aLen1,
                 const void *aStr1,
                 int aLen2,
                 const void *aStr2)
{
  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
                                nsICollation::kCollationCaseInSensitive);
}

int
localeCollationCaseSensitive8(void *aService,
                              int aLen1,
                              const void *aStr1,
                              int aLen2,
                              const void *aStr2)
{
  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
                                nsICollation::kCollationAccentInsenstive);
}

int
localeCollationAccentSensitive8(void *aService,
                                int aLen1,
                                const void *aStr1,
                                int aLen2,
                                const void *aStr2)
{
  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
                                nsICollation::kCollationCaseInsensitiveAscii);
}

int
localeCollationCaseAccentSensitive8(void *aService,
                                    int aLen1,
                                    const void *aStr1,
                                    int aLen2,
                                    const void *aStr2)
{
  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
                                nsICollation::kCollationCaseSensitive);
}

int
localeCollation16(void *aService,
                  int aLen1,
                  const void *aStr1,
                  int aLen2,
                  const void *aStr2)
{
  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
                                 nsICollation::kCollationCaseInSensitive);
}

int
localeCollationCaseSensitive16(void *aService,
                               int aLen1,
                               const void *aStr1,
                               int aLen2,
                               const void *aStr2)
{
  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
                                 nsICollation::kCollationAccentInsenstive);
}

int
localeCollationAccentSensitive16(void *aService,
                                 int aLen1,
                                 const void *aStr1,
                                 int aLen2,
                                 const void *aStr2)
{
  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
                                 nsICollation::kCollationCaseInsensitiveAscii);
}

int
localeCollationCaseAccentSensitive16(void *aService,
                                     int aLen1,
                                     const void *aStr1,
                                     int aLen2,
                                     const void *aStr2)
{
  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
                                 nsICollation::kCollationCaseSensitive);
}

} // namespace storage
} // namespace mozilla