title: Case-insensitive UTF-8 string collation for SQLite (C/C++)
body: <p>I am looking for a method to compare and sort UTF-8 strings in C++ in a case-insensitive manner to use it in a <a href="http://www.sqlite.org/c3ref/create_collation.html" rel="noreferrer">custom collation function in SQLite</a>.</p>
  
  <ol>
  <li>The method should <em>ideally</em> be locale-independent. However I won't be holding my breath, as far as I know, collation is very language-dependent, so anything that works on languages other than English will do, even if it means switching locales.</li>
  <li>Options include using standard C or C++ library or a <em>small</em> (suitable for embedded system) and <em>non-GPL</em> (suitable for a proprietary system) third-party library.</li>
  </ol>
  
  <p>What I have so far:</p>
  
  <ol>
  <li><code>strcoll</code> with C locales and <code>std::collate</code>/<code>std::collate_byname</code> are case-sensitive. (Are there case-insensitive versions of these?)</li>
  <li><p>I tried to use a POSIX strcasecmp, but it seems to be <a href="http://www.opengroup.org/onlinepubs/007908775/xsh/strcasecmp.html" rel="noreferrer">not defined</a> for locales other than <code>"POSIX"</code></p>
  
  <blockquote>
    <p><em>In the POSIX locale, strcasecmp() and strncasecmp() do upper to lower conversions, then a byte comparison. The results are unspecified in other locales.</em></p>
  </blockquote>
  
  <p>And, indeed, the result of <code>strcasecmp</code> does not change between locales on Linux with GLIBC.</p>
  
  <pre><code>#include &lt;clocale&gt;
  #include &lt;cstdio&gt;
  #include &lt;cassert&gt;
  #include &lt;cstring&gt;
  
  const static char *s1 = "Äaa";
  const static char *s2 = "äaa";
  
  int main() {
      printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2));
      printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2));
      assert(setlocale(LC_ALL, "en_AU.UTF-8"));
      printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2));
      printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2));
      assert(setlocale(LC_ALL, "fi_FI.UTF-8"));
      printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2));
      printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2));
  }
  </code></pre>
  
  <p>This is printed:</p>
  
  <pre><code>strcasecmp('Äaa', 'äaa') == -32
  strcoll('Äaa', 'äaa') == -32
  strcasecmp('Äaa', 'äaa') == -32
  strcoll('Äaa', 'äaa') == 7
  strcasecmp('Äaa', 'äaa') == -32
  strcoll('Äaa', 'äaa') == 7
  </code></pre></li>
  </ol>
  
  <p>P. S.</p>
  
  <p>And yes, I am aware about <a href="http://icu-project.org/" rel="noreferrer">ICU</a>, but we can't use it on the embedded platform due to its <a href="http://www.icu-project.org/charts/icu4c_footprint.html" rel="noreferrer">enormous size</a>.</p>