/*---------------------------------------------------------------------------*
  Project:  TwlSDK - FS - libraries
  File:     util.h

  Copyright 2007-2008 Nintendo. All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Date:: 2008-09-25#$
  $Rev: 8648 $
  $Author: yosizaki $

 *---------------------------------------------------------------------------*/


#if	!defined(NITRO_FS_UTIL_H_)
#define NITRO_FS_UTIL_H_

#include <nitro/misc.h>
#include <nitro/types.h>


#ifdef __cplusplus
extern "C" {
#endif


/*---------------------------------------------------------------------------*/
/* Constants */

// Enable this definition when you want to use the file system from the ARM7.
// #define SDK_ARM7FS

// This is only defined for environments that should include the full set of file system functionality
#if	!defined(SDK_ARM7) || defined(SDK_ARM7FS)
#define	FS_IMPLEMENT
#endif


/*---------------------------------------------------------------------------*/
/* functions */

/*---------------------------------------------------------------------------*
  Name:         FSi_IsSlash

  Description:  Internal function.
                Determine if a character is a directory delimiter.

  Arguments:    c:                Character to determine.

  Returns:      TRUE if a directory delimiting character.
 *---------------------------------------------------------------------------*/
SDK_INLINE BOOL FSi_IsSlash(u32 c)
{
    return (c == '/') || (c == '\\');
}

/*---------------------------------------------------------------------------*
  Name:         FSi_IncrementSjisPosition

  Description:  Advances the access position of a Shift JIS string by one character.

  Arguments:    str: Pointer to the start of a Shift JIS string.
                pos: The current access position in the string. (in bytes)

  Returns:      The access position that results from advancing pos by one character.
 *---------------------------------------------------------------------------*/
SDK_INLINE int FSi_IncrementSjisPosition(const char *str, int pos)
{
    return pos + 1 + STD_IsSjisLeadByte(str[pos]);
}

/*---------------------------------------------------------------------------*
  Name:         FSi_DecrementSjisPosition

  Description:  Moves the access position of a Shift JIS string backward by one character.

  Arguments:    str: Pointer to the start of a Shift JIS string.
                pos: The current access position in the string. (in bytes)

  Returns:      Either -1 or the access position that results from moving pos backward by one character.
 *---------------------------------------------------------------------------*/
int FSi_DecrementSjisPosition(const char *str, int pos);

/*---------------------------------------------------------------------------*
  Name:         FSi_IncrementSjisPositionToSlash

  Description:  Advances the access position in a Shift JIS string to either a directory-delimiting character or the end of the string.
                

  Arguments:    str: Pointer to the start of a Shift JIS string.
                pos: The current access position in the string. (in bytes)

  Returns:      Either the first directory delimiter starting from pos or the end of the string.
 *---------------------------------------------------------------------------*/
int FSi_IncrementSjisPositionToSlash(const char *str, int pos);

/*---------------------------------------------------------------------------*
  Name:         FSi_DecrementSjisPositionToSlash

  Description:  Moves the access position in a Shift JIS string backward to either a directory-delimiting character or the start of the string.
                

  Arguments:    str: Pointer to the start of a Shift JIS string.
                pos: The current access position in the string. (in bytes)

  Returns:      Either the first directory delimiter before pos or -1.
 *---------------------------------------------------------------------------*/
int FSi_DecrementSjisPositionToSlash(const char *str, int pos);

/*---------------------------------------------------------------------------*
  Name:         FSi_TrimSjisTrailingSlash

  Description:  Deletes a directory-delimiting character if it exists at the end of a Shift JIS string.

  Arguments:    str: Shift JIS string.

  Returns:      Length of string
 *---------------------------------------------------------------------------*/
int FSi_TrimSjisTrailingSlash(char *str);

/*---------------------------------------------------------------------------*
  Name:         FSi_StrNICmp

  Description:  Performs a case-insensitive string comparison for only the specified number of bytes.
                Note that this does not consider the terminating NULL character.

  Arguments:    str1: Source string to compare
                str2: Target string to compare
                len: Number of bytes to compare

  Returns:      The result of comparing (str1 - str2)
 *---------------------------------------------------------------------------*/
SDK_INLINE int FSi_StrNICmp(const char *str1, const char *str2, u32 len)
{
    int     retval = 0;
    int     i;
    for (i = 0; i < len; ++i)
    {
        u32     c = (u8)(str1[i] - 'A');
        u32     d = (u8)(str2[i] - 'A');
        if (c <= 'Z' - 'A')
        {
            c += 'a' - 'A';
        }
        if (d <= 'Z' - 'A')
        {
            d += 'a' - 'A';
        }
        retval = (int)(c - d);
        if (retval != 0)
        {
            break;
        }
    }
    return retval;
}

/*---------------------------------------------------------------------------*
  Name:         FSi_IsUnicodeSlash

  Description:  Determines whether a Unicode character is a path delimiter.

  Arguments:    c: Unicode1 character
                
  Returns:      TRUE if it is L'/' (0x2F) or L'\\' (0x5C).
 *---------------------------------------------------------------------------*/
SDK_INLINE BOOL FSi_IsUnicodeSlash(u16 c)
{
    return (c == L'/') || (c == L'\\');
}

/*---------------------------------------------------------------------------*
  Name:         FSi_DecrementUnicodePosition

  Description:  Moves the access position of a Unicode string backward by one character.

  Arguments:    str: Pointer to the start of a Unicode string.
                pos: The current access position in the string. (in bytes)

  Returns:      Either -1 or the access position that results from moving pos backward by one character.
 *---------------------------------------------------------------------------*/
int FSi_DecrementUnicodePosition(const u16 *str, int pos);

/*---------------------------------------------------------------------------*
  Name:         FSi_DecrementUnicodePositionToSlash

  Description:  Moves the access position in a Unicode string backward to either a directory-delimiting character or the start of the string.
                

  Arguments:    str: Pointer to the start of a Unicode string.
                pos: The current access position in the string. (in bytes)

  Returns:      Either the first directory delimiter before pos or -1.
 *---------------------------------------------------------------------------*/
int FSi_DecrementUnicodePositionToSlash(const u16 *str, int pos);

/*---------------------------------------------------------------------------*
  Name:         FSi_WaitConditionOn

  Description:  Sleeps until the specified bit is 1.

  Arguments:    flags: Bit set to monitor
                bits: Bit that should change to 1
                queue: A sleep queue or NULL

  Returns:      None.
 *---------------------------------------------------------------------------*/
SDK_INLINE void FSi_WaitConditionOn(u32 *flags, u32 bits, OSThreadQueue *queue)
{
    OSIntrMode bak = OS_DisableInterrupts();
    while ((*flags & bits) == 0)
    {
        OS_SleepThread(queue);
    }
    (void)OS_RestoreInterrupts(bak);
}

/*---------------------------------------------------------------------------*
  Name:         FSi_WaitConditionOff

  Description:  Sleeps until the specified bit is 0.

  Arguments:    flags: Bit set to monitor
                bits: Bit that should change to 0
                queue: A sleep queue or NULL

  Returns:      None.
 *---------------------------------------------------------------------------*/
SDK_INLINE void FSi_WaitConditionOff(u32 *flags, u32 bits, OSThreadQueue *queue)
{
    OSIntrMode bak = OS_DisableInterrupts();
    while ((*flags & bits) != 0)
    {
        OS_SleepThread(queue);
    }
    (void)OS_RestoreInterrupts(bak);
}

/*---------------------------------------------------------------------------*
  Name:         FSi_GetFileLengthIfProc

  Description:  Gets the size of the specified file if it is an archive procedure.

  Arguments:    file: File handle
                length: Location to save the size

  Returns:      The size of the specified file if it is an archive procedure
 *---------------------------------------------------------------------------*/
BOOL FSi_GetFileLengthIfProc(FSFile *file, u32 *length);

/*---------------------------------------------------------------------------*
  Name:         FSi_GetFilePositionIfProc

  Description:  Gets the current position of the specified file if it is an archive procedure.

  Arguments:    file: File handle
                length: Location to save the size

  Returns:      The current position of the specified file if it is an archive procedure
 *---------------------------------------------------------------------------*/
BOOL FSi_GetFilePositionIfProc(FSFile *file, u32 *length);


/*---------------------------------------------------------------------------*/


#ifdef __cplusplus
} /* extern "C" */
#endif


#endif /* NITRO_FS_UTIL_H_ */
