//
// Asura_PlatformBasics.cpp
//
// Created by KJFL - Wednesday, February 04, 2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "Debugging/Asura_Assert.h"

#include "Core/Asura_PlatformBasics.h"

#if (0 && defined __SNC__)
extern "C" int iswalnum(const Asura_UnicodeChar wC)
{
    return iswalpha(wC) || iswdigit(wC);
}
#endif

#if (defined __SNC__ || defined __GNUC__)
extern "C" int wcsicmp(register const Asura_UnicodeChar* wszA,
    register const Asura_UnicodeChar* wszB)
{
    register Asura_UnicodeChar wA, wB;

    do
    {
        wA = towlower(*wszA++);
        wB = towlower(*wszB++);
    }
    while (wA != (Asura_UnicodeChar) 0 && wA == wB);

    return wA - wB;
}

extern "C" int wcsnicmp(register const Asura_UnicodeChar* wszA,
    register const Asura_UnicodeChar* wszB,register size_t uMax)
{
    if (uMax == 0) { return 0; }

    register Asura_UnicodeChar wA, wB;

    do
    {
        wA = towlower(*wszA++);
        wB = towlower(*wszB++);
    }
    while (--uMax > 0 && wA != (Asura_UnicodeChar) 0 && wA == wB);

    return wA - wB;
}
#endif

// ARC - 21 November 2006 16:24:30 - Added to support wcsrchr
extern "C" Asura_UnicodeChar* Asura_UnicodeChar_FindCharRev(
	register const Asura_UnicodeChar* wszHaystack,
	register Asura_UnicodeChar wNeedle
	)
{
	register const Asura_UnicodeChar* const wszStart = wszHaystack;

	// Go to end of string
	while( *wszHaystack++ ) { }

	// And search backwards.
	for( ; wszHaystack >= wszStart; --wszHaystack )
	{
		if( *wszHaystack == wNeedle )
		{
			return const_cast<Asura_UnicodeChar*>( wszHaystack );
		}
	}

	return NULL;
}

#if (defined __GNUC__ && !defined __SNC__)
extern "C" int Asura_UnicodeChar_Len(register const Asura_UnicodeChar* wszA)
{
    register const Asura_UnicodeChar* const wszB = wszA;

    while (*wszA++ != (Asura_UnicodeChar) 0)
    {
        continue;
    }

    return wszA-1 - wszB;
}

extern "C" Asura_UnicodeChar* Asura_UnicodeChar_FindChar(
    register const Asura_UnicodeChar* wszA,
    register const Asura_UnicodeChar wC
)
{
    register Asura_UnicodeChar wT;
    
    for (wszA; (wT = *wszA) != (Asura_UnicodeChar) 0; wszA++)
    {
        if (wT == wC)
            return const_cast<Asura_UnicodeChar*>(wszA);
    }

    return 0;
}

extern "C" int Asura_UnicodeChar_Cmp(register const Asura_UnicodeChar* wszA,
									 register const Asura_UnicodeChar* wszB)
{
	register Asura_UnicodeChar wA, wB;

	while ((wA = *wszA++) == (wB = *wszB++))
	{
		if (wA == (Asura_UnicodeChar) 0)
			return 0;
	}

	return wA - wB;
}


extern "C" int Asura_UnicodeChar_CmpN(register const Asura_UnicodeChar* wszA,
									  register const Asura_UnicodeChar* wszB,
									  register size_t uMax)
{
	if (uMax == 0) { return 0; }

	register Asura_UnicodeChar wA, wB;

	do
	{
		wA = *wszA++;
		wB = *wszB++;
	}
	while (--uMax > 0 && wA != (Asura_UnicodeChar) 0 && wA == wB);

	return wA - wB;
}

extern "C" Asura_UnicodeChar* Asura_UnicodeChar_CopyTo(
    Asura_UnicodeChar* const wszA,
    register const Asura_UnicodeChar* wszB
)
{
    register Asura_UnicodeChar* wszP;

#if 1
    Asura_Assert(__alignof__(Asura_UnicodeChar) >= sizeof (Asura_UnicodeChar),
        "The alignment must be at least the size for pointer difference");
#else
    if (__alignof__(Asura_UnicodeChar) < sizeof (Asura_UnicodeChar),
    {
        for (wszP = wszA;
             (*wszP++ = *wszB++) != (Asura_UnicodeChar) 0;
             wszP, wszB)
        {
            continue;
        }

        return wszA;
    }
#endif

    {
        register const ptrdiff_t iDelta = wszB - wszA;

        for (wszP = wszA;
             (*wszP = *(wszP+iDelta)) != (Asura_UnicodeChar) 0;
             wszP++)
        {
            continue;
        }

        return wszA;
    }
}

extern "C" Asura_UnicodeChar* Asura_UnicodeChar_CopyToMax(
    Asura_UnicodeChar* const wszA,
    register const Asura_UnicodeChar* wszB,
    register size_t uMax
)
{
    register Asura_UnicodeChar* wszP = wszA;

#if 1
    Asura_Assert(__alignof__(Asura_UnicodeChar) >= sizeof (Asura_UnicodeChar),
        "The alignment must be at least the size for pointer difference");
#else
    if (__alignof__(Asura_UnicodeChar) < sizeof (Asura_UnicodeChar),
    {
        for (uMax, wszP = wszA;
             uMax != 0 && (*wszP++ = *wszB++) != (Asura_UnicodeChar) 0;
             --uMax)
        {
            continue;
        }

        return wszA;
    }
#endif

    {
        register const ptrdiff_t iDelta = wszB - wszA;

        for (uMax, wszP = wszA;
             uMax != 0 && (*wszP = *(wszP+iDelta)) != (Asura_UnicodeChar) 0;
             --uMax, wszP++)
        {
            continue;
        }

        return wszA;
    }
}

extern "C" Asura_UnicodeChar* Asura_UnicodeChar_Cat(
	Asura_UnicodeChar* wszA,
	register const Asura_UnicodeChar* wszB
)
{
	// store start of destination
	Asura_UnicodeChar* wszRet = wszA;

	// skip to end of destination
	while (*wszA)
	{
		wszA++;
	}

	// copy each character in source
	while (*wszB)
	{
		*wszA++ = *wszB++;
	}

	// terminate new string
	*wszA = 0;

	// return destination string
	return wszRet;
}
#endif
