// Common/MyString.cpp

#include "StdAfx.h"

#ifndef _WIN32
#include <ctype.h>
#endif

#ifndef _UNICODE
#include "StringConvert.h"
#endif

#include "MyString.h"


#ifdef _WIN32

#ifndef _UNICODE

wchar_t MyCharUpper(wchar_t c)
{
  if (c == 0)
    return 0;
  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c);
  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    return (wchar_t)(unsigned int)(UINT_PTR)res;
  const int kBufferSize = 4;
  char s[kBufferSize + 1];
  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
  if (numChars == 0 || numChars > kBufferSize)
    return c;
  s[numChars] = 0;
  ::CharUpperA(s);
  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
  return c;
}

wchar_t MyCharLower(wchar_t c)
{
  if (c == 0)
    return 0;
  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c);
  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    return (wchar_t)(unsigned int)(UINT_PTR)res;
  const int kBufferSize = 4;
  char s[kBufferSize + 1];
  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
  if (numChars == 0 || numChars > kBufferSize)
    return c;
  s[numChars] = 0;
  ::CharLowerA(s);
  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
  return c;
}

wchar_t * MyStringUpper(wchar_t *s)
{
  if (s == 0)
    return 0;
  wchar_t *res = CharUpperW(s);
  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    return res;
  AString a = UnicodeStringToMultiByte(s);
  a.MakeUpper();
  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
}

wchar_t * MyStringLower(wchar_t *s)
{
  if (s == 0)
    return 0;
  wchar_t *res = CharLowerW(s);
  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    return res;
  AString a = UnicodeStringToMultiByte(s);
  a.MakeLower();
  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
}

#endif

/*
inline int ConvertCompareResult(int r) { return r - 2; }

int MyStringCollate(const wchar_t *s1, const wchar_t *s2)
{
  int res = CompareStringW(
        LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1);
  #ifdef _UNICODE
  return ConvertCompareResult(res);
  #else
  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    return ConvertCompareResult(res);
  return MyStringCollate(UnicodeStringToMultiByte(s1),
        UnicodeStringToMultiByte(s2));
  #endif
}

#ifndef UNDER_CE
int MyStringCollate(const char *s1, const char *s2)
{
  return ConvertCompareResult(CompareStringA(
    LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1));
}

int MyStringCollateNoCase(const char *s1, const char *s2)
{
  return ConvertCompareResult(CompareStringA(
    LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1));
}
#endif

int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
{
  int res = CompareStringW(
        LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1);
  #ifdef _UNICODE
  return ConvertCompareResult(res);
  #else
  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
    return ConvertCompareResult(res);
  return MyStringCollateNoCase(UnicodeStringToMultiByte(s1),
      UnicodeStringToMultiByte(s2));
  #endif
}
*/

#else

wchar_t MyCharUpper(wchar_t c)
{
  return toupper(c);
}

/*
int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
{
  for (;;)
  {
    wchar_t c1 = *s1++;
    wchar_t c2 = *s2++;
    wchar_t u1 = MyCharUpper(c1);
    wchar_t u2 = MyCharUpper(c2);

    if (u1 < u2) return -1;
    if (u1 > u2) return 1;
    if (u1 == 0) return 0;
  }
}
*/

#endif

int MyStringCompare(const char *s1, const char *s2)
{
  for (;;)
  {
    unsigned char c1 = (unsigned char)*s1++;
    unsigned char c2 = (unsigned char)*s2++;
    if (c1 < c2) return -1;
    if (c1 > c2) return 1;
    if (c1 == 0) return 0;
  }
}

int MyStringCompare(const wchar_t *s1, const wchar_t *s2)
{
  for (;;)
  {
    wchar_t c1 = *s1++;
    wchar_t c2 = *s2++;
    if (c1 < c2) return -1;
    if (c1 > c2) return 1;
    if (c1 == 0) return 0;
  }
}

int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)
{
  for (;;)
  {
    wchar_t c1 = *s1++;
    wchar_t c2 = *s2++;
    if (c1 != c2)
    {
      wchar_t u1 = MyCharUpper(c1);
      wchar_t u2 = MyCharUpper(c2);
      if (u1 < u2) return -1;
      if (u1 > u2) return 1;
    }
    if (c1 == 0) return 0;
  }
}

/*
int MyStringCompareNoCase(const char *s1, const char *s2)
{
  return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
}
*/
