root/src/system/libroot/add-ons/icu/ICUNumericData.cpp
/*
 * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de.
 * Distributed under the terms of the MIT License.
 */


#include "ICUNumericData.h"

#include <langinfo.h>
#include <locale.h>
#include <string.h>
#include <strings.h>


U_NAMESPACE_USE


namespace BPrivate {
namespace Libroot {


ICUNumericData::ICUNumericData(pthread_key_t tlsKey, struct lconv& localeConv)
        :
        inherited(tlsKey),
        fLocaleConv(localeConv),
        fDataBridge(NULL)
{
        fLocaleConv.decimal_point = fDecimalPoint;
        fLocaleConv.thousands_sep = fThousandsSep;
        fLocaleConv.grouping = fGrouping;
}


void
ICUNumericData::Initialize(LocaleNumericDataBridge* dataBridge)
{
        fDataBridge = dataBridge;
}


status_t
ICUNumericData::SetTo(const Locale& locale, const char* posixLocaleName)
{
        status_t result = inherited::SetTo(locale, posixLocaleName);

        if (result == B_OK) {
                UErrorCode icuStatus = U_ZERO_ERROR;
                DecimalFormat* numberFormat = dynamic_cast<DecimalFormat*>(
                        NumberFormat::createInstance(locale, UNUM_DECIMAL, icuStatus));
                if (!U_SUCCESS(icuStatus))
                        return B_UNSUPPORTED;
                if (!numberFormat)
                        return B_BAD_TYPE;
                const DecimalFormatSymbols* formatSymbols
                        = numberFormat->getDecimalFormatSymbols();
                if (!formatSymbols)
                        result = B_BAD_DATA;

                if (result == B_OK) {
                        result = _SetLocaleconvEntry(formatSymbols, fDecimalPoint,
                                DecimalFormatSymbols::kDecimalSeparatorSymbol);
                }
                if (result == B_OK) {
                        result = _SetLocaleconvEntry(formatSymbols, fThousandsSep,
                                DecimalFormatSymbols::kGroupingSeparatorSymbol);
                }
                if (result == B_OK) {
                        int32 groupingSize = numberFormat->getGroupingSize();
                        if (groupingSize < 1)
                                fGrouping[0] = '\0';
                        else {
                                fGrouping[0] = groupingSize;
                                int32 secondaryGroupingSize
                                        = numberFormat->getSecondaryGroupingSize();
                                if (secondaryGroupingSize < 1)
                                        fGrouping[1] = '\0';
                                else {
                                        fGrouping[1] = secondaryGroupingSize;
                                        fGrouping[2] = '\0';
                                }
                        }
                }

                delete numberFormat;
        }

        return result;
}


status_t
ICUNumericData::SetToPosix()
{
        status_t result = inherited::SetToPosix();

        if (result == B_OK) {
                strcpy(fDecimalPoint, fDataBridge->posixLocaleConv->decimal_point);
                strcpy(fThousandsSep, fDataBridge->posixLocaleConv->thousands_sep);
                strcpy(fGrouping, fDataBridge->posixLocaleConv->grouping);
        }

        return result;
}


const char*
ICUNumericData::GetLanginfo(int index)
{
        switch(index) {
                case RADIXCHAR:
                        return fDecimalPoint;
                case THOUSEP:
                        return fThousandsSep;
                default:
                        return "";
        }
}


}       // namespace Libroot
}       // namespace BPrivate