{-------------------------------------------------------------------------------
 
 Copyright (c) 1999-2021 Ralf Junker, Yunqa
 Internet: https://www.yunqa.de
 E-Mail:   delphi@yunqa.de

-------------------------------------------------------------------------------}

unit DISQLite3Collations;

{$I DICompilers.inc}
{$I DISQLite3.inc}

{$IFDEF DISQLite3_Personal}
!!! This file requires functionality unavailable in DISQLite3 Personal. !!!
!!! To compile, download DISQLite3 Pro from www.yunqa.de.               !!!
{$ENDIF DISQLite3_Personal}

interface

const

  COMPARE_CUSTOM_IGNORE_CASE = 1 shl 31;

function SQLite3_Compare_Custom_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_Custom_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_System_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_System_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_System_NoCase_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_System_NoCase_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_User_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_User_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_User_NoCase_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

function SQLite3_Compare_User_NoCase_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;

implementation

uses
  {$IFDEF HAS_UNITSCOPE}
  Winapi.Windows, System.SysUtils
  {$ELSE HAS_UNIT_SCOPE}
  Windows, SysUtils
  {$ENDIF HAS_UNIT_SCOPE}
  ;

{$IFNDEF Unicode}

var
  CompareStringFunc: function(
    Locale: LCID;
    dwCmpFlags: DWORD;
    lpString1: PWideChar; cchCount1: Integer;
    lpString2: PWideChar; cchCount2: Integer): Integer stdcall;

  {$ENDIF !Unicode}

function SQLite3_Compare_Custom_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
var
  Flags: Cardinal;
  LCID: Cardinal;
begin

  LCID := Cardinal(UserData) and $FFFF8;

  if Cardinal(UserData) and COMPARE_CUSTOM_IGNORE_CASE <> 0 then
    Flags := NORM_IGNORECASE
  else
    Flags := 0;
  Result := CompareStringA(LCID and $FFFFFF, Flags, s1, l1, s2, l2) - 2;
end;

function SQLite3_Compare_Custom_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
var
  Flags: Cardinal;
  LCID: Cardinal;
begin

  LCID := Cardinal(UserData) and $FFFF8;

  if Cardinal(UserData) and COMPARE_CUSTOM_IGNORE_CASE <> 0 then
    Flags := NORM_IGNORECASE
  else
    Flags := 0;
  Result := {$IFDEF Unicode}CompareStringW{$ELSE}CompareStringFunc{$ENDIF}
  (LCID, Flags, s1, l1 shr 1, s2, l2 shr 1) - 2;
end;

function SQLite3_Compare_System_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, s1, l1, s2, l2) - 2;
end;

function SQLite3_Compare_System_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := {$IFDEF Unicode}CompareStringW{$ELSE}CompareStringFunc{$ENDIF}
  (LOCALE_SYSTEM_DEFAULT, 0, s1, l1 shr 1, s2, l2 shr 1) - 2;
end;

function SQLite3_Compare_System_NoCase_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, s1, l1, s2, l2) - 2;
end;

function SQLite3_Compare_System_NoCase_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := {$IFDEF Unicode}CompareStringW{$ELSE}CompareStringFunc{$ENDIF}
  (LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, s1, l1 shr 1, s2, l2 shr 1) - 2;
end;

function SQLite3_Compare_User_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := CompareStringA(LOCALE_USER_DEFAULT, 0, s1, l1, s2, l2) - 2;
end;

function SQLite3_Compare_User_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := {$IFDEF Unicode}CompareStringW{$ELSE}CompareStringFunc{$ENDIF}
  (LOCALE_USER_DEFAULT, 0, s1, l1 shr 1, s2, l2 shr 1) - 2;
end;

function SQLite3_Compare_User_NoCase_Ansi(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE, s1, l1, s2, l2) - 2;
end;

function SQLite3_Compare_User_NoCase_UTF16LE(
  UserData: Pointer;
  l1: Integer; const s1: Pointer;
  l2: Integer; const s2: Pointer): Integer;
begin
  Result := {$IFDEF Unicode}CompareStringW{$ELSE}CompareStringFunc{$ENDIF}
  (LOCALE_USER_DEFAULT, NORM_IGNORECASE, s1, l1 shr 1, s2, l2 shr 1) - 2;
end;

{$IFNDEF Unicode}

function CompareString95(
  Locale: LCID;
  dwCmpFlags: DWORD;
  lpString1: PWideChar; cchCount1: Integer;
  lpString2: PWideChar; cchCount2: Integer): Integer; stdcall;
var
  b1, b2: PAnsiChar;
  i1, i2: Integer;
begin
  GetMem(b1, cchCount1);
  i1 := WideCharToMultiByte(CP_ACP, 0, lpString1, cchCount1, b1, cchCount1, nil, nil);
  GetMem(b2, cchCount2);
  i2 := WideCharToMultiByte(CP_ACP, 0, lpString2, cchCount2, b2, cchCount2, nil, nil);
  Result := CompareStringA(Locale, dwCmpFlags, b1, i1, b2, i2);
  FreeMem(b2);
  FreeMem(b1);
end;

{$ENDIF !Unicode}

{$IFNDEF Unicode}

initialization
  if (Win32Platform and VER_PLATFORM_WIN32_NT) <> 0 then
    @CompareStringFunc := @CompareStringW
  else
    @CompareStringFunc := @CompareString95;

  {$ENDIF !Unicode}

end.

