root/src/system/libroot/posix/locale/wctype.cpp
/*
** Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
** Distributed under the terms of the MIT License.
*/

#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <wctype.h>

#include <errno_private.h>

#include "LocaleBackend.h"


using BPrivate::Libroot::GetCurrentLocaleBackend;
using BPrivate::Libroot::LocaleBackend;


/*
 * In many of the following functions, we make use of the fact that with
 * gLocaleBackend == NULL, the POSIX locale is active. Since the POSIX locale
 * only contains chars 0-127 and those ASCII chars are compatible with the
 * UTF32 values used in wint_t, we can delegate to the respective ctype
 * function.
 */

int
iswctype(wint_t wc, wctype_t charClass)
{
        LocaleBackend* backend = GetCurrentLocaleBackend();

        if (backend == NULL) {
                if (wc < 0 || wc > 127)
                        return 0;
                return __isctype(wc, charClass);
        }

        return backend->IsWCType(wc, charClass);
}


int
iswalnum(wint_t wc)
{
        return iswctype(wc, _ISalnum);
}


int
iswalpha(wint_t wc)
{
        return iswctype(wc, _ISalpha);
}


int
iswblank(wint_t wc)
{
        return iswctype(wc, _ISblank);
}


int
iswcntrl(wint_t wc)
{
        return iswctype(wc, _IScntrl);
}


int
iswdigit(wint_t wc)
{
        return iswctype(wc, _ISdigit);
}


int
iswgraph(wint_t wc)
{
        return iswctype(wc, _ISgraph);
}


int
iswlower(wint_t wc)
{
        return iswctype(wc, _ISlower);
}


int
iswprint(wint_t wc)
{
        return iswctype(wc, _ISprint);
}


int
iswpunct(wint_t wc)
{
        return iswctype(wc, _ISpunct);
}


int
iswspace(wint_t wc)
{
        return iswctype(wc, _ISspace);
}


int
iswupper(wint_t wc)
{
        return iswctype(wc, _ISupper);
}


int
iswxdigit(wint_t wc)
{
        return iswctype(wc, _ISxdigit);
}


wint_t
towlower(wint_t wc)
{
        LocaleBackend* backend = GetCurrentLocaleBackend();

        if (backend == NULL) {
                if (wc < 0 || wc > 127)
                        return wc;
                return tolower(wc);
        }

        wint_t result = wc;
        backend->ToWCTrans(wc, _ISlower, result);

        return result;
}


wint_t
towupper(wint_t wc)
{
        LocaleBackend* backend = GetCurrentLocaleBackend();

        if (backend == NULL) {
                if (wc < 0 || wc > 127)
                        return wc;
                return toupper(wc);
        }

        wint_t result = wc;
        backend->ToWCTrans(wc, _ISupper, result);

        return result;
}


wint_t
towctrans(wint_t wc, wctrans_t transition)
{
        LocaleBackend* backend = GetCurrentLocaleBackend();

        if (backend == NULL) {
                if (transition == _ISlower)
                        return tolower(wc);
                if (transition == _ISupper)
                        return toupper(wc);

                __set_errno(EINVAL);
                return wc;
        }

        wint_t result = wc;
        status_t status = backend->ToWCTrans(wc, transition, result);
        if (status != B_OK)
                __set_errno(EINVAL);

        return result;
}


wctrans_t
wctrans(const char *charClass)
{
        if (charClass != NULL) {
                // we do not know any locale-specific character classes
                if (strcmp(charClass, "tolower") == 0)
                        return _ISlower;
                if (strcmp(charClass, "toupper") == 0)
                        return _ISupper;
        }

        __set_errno(EINVAL);
        return 0;
}


wctype_t
wctype(const char *property)
{
        // currently, we do not support any locale-specific properties
        if (strcmp(property, "alnum") == 0)
                return _ISalnum;
        if (strcmp(property, "alpha") == 0)
                return _ISalpha;
        if (strcmp(property, "blank") == 0)
                return _ISblank;
        if (strcmp(property, "cntrl") == 0)
                return _IScntrl;
        if (strcmp(property, "digit") == 0)
                return _ISdigit;
        if (strcmp(property, "graph") == 0)
                return _ISgraph;
        if (strcmp(property, "lower") == 0)
                return _ISlower;
        if (strcmp(property, "print") == 0)
                return _ISprint;
        if (strcmp(property, "punct") == 0)
                return _ISpunct;
        if (strcmp(property, "space") == 0)
                return _ISspace;
        if (strcmp(property, "upper") == 0)
                return _ISupper;
        if (strcmp(property, "xdigit") == 0)
                return _ISxdigit;

        return 0;
}