[haiku-commits] r36076 - haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale

  • From: zooey@xxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 7 Apr 2010 23:54:50 +0200 (CEST)

Author: zooey
Date: 2010-04-07 23:54:50 +0200 (Wed, 07 Apr 2010)
New Revision: 36076
Changeset: http://dev.haiku-os.org/changeset/36076/haiku

Modified:
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.cpp
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.h
Log:
* implement filling of many lconv-members in SetLocale(), the positional
  arguments and some other bits are still missing, though

Modified: 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.cpp
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.cpp
    2010-04-07 21:52:28 UTC (rev 36075)
+++ 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.cpp
    2010-04-07 21:54:50 UTC (rev 36076)
@@ -12,27 +12,39 @@
 #include <locale.h>
 #include <string.h>
 
+#include <unicode/decimfmt.h>
 
+
 namespace BPrivate {
 
 
 /*
- * the values below initialize the struct to the "C"/"POSIX" locale, but it
+ * the values below initialize the struct to let each member point to a static
+ * buffer, which will be initialized to match the "C"/"POSIX" locale, but it
  * will be changed according to any locale requested via SetLocale()
  */
+static const uint16 skLCBufSize = 10;
+static char sDecimalPoint[skLCBufSize] = ".";
+static char sThousandsSep[skLCBufSize] = "";
+static char sGrouping[skLCBufSize] = "";
+static char sIntCurrSymbol[skLCBufSize] = "";
+static char sCurrencySymbol[skLCBufSize] = "";
+static char sMonDecimalPoint[skLCBufSize] = "";
+static char sMonThousandsSep[skLCBufSize] = "";
+static char sMonGrouping[skLCBufSize] = "";
+static char sPositiveSign[skLCBufSize] = "";
+static char sNegativeSign[skLCBufSize] = "";
 static struct lconv sLocaleConv = {
-       ".",            // decimal point
-
-       "",                     // thousands separator
-       "",                     // grouping
-       "",                     // international currency symbol
-       "",                     // local currency symbol
-       "",                     // monetary decimal point
-       "",                     // monetary thousands separator
-       "",                     // monetary grouping
-       "",                     // positive sign
-       "",                     // negative sign
-
+       sDecimalPoint,
+       sThousandsSep,
+       sGrouping,
+       sIntCurrSymbol,
+       sCurrencySymbol,
+       sMonDecimalPoint,
+       sMonThousandsSep,
+       sMonGrouping,
+       sPositiveSign,
+       sNegativeSign,
        CHAR_MAX,       // int_frac_digits
        CHAR_MAX,       // frac_digits
        CHAR_MAX,       // p_cs_precedes
@@ -45,6 +57,8 @@
 
 
 CategoryData::CategoryData()
+       :
+       fConverter(NULL)
 {
        *fPosixLocaleName = '\0';
        *fGivenCharset = '\0';
@@ -53,6 +67,8 @@
 
 CategoryData::~CategoryData()
 {
+       if (fConverter)
+               ucnv_close(fConverter);
 }
 
 
@@ -81,12 +97,54 @@
                snprintf(fGivenCharset, UCNV_MAX_CONVERTER_NAME_LENGTH, "%.*s", 
l,
                        charsetStart);
        }
+       if (!strlen(fGivenCharset))
+               strcpy(fGivenCharset, "utf-8");
 
+       UErrorCode icuStatus = U_ZERO_ERROR;
+       fConverter = ucnv_open(fGivenCharset, &icuStatus);
+       if (fConverter == NULL)
+               return B_NAME_NOT_FOUND;
+
+       ucnv_setFromUCallBack(fConverter, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL,
+               NULL, &icuStatus);
+       if (!U_SUCCESS(icuStatus))
+               return B_ERROR;
+
        return B_OK;
 }
 
 
 status_t
+CategoryData::_ConvertUnicodeStringToLocaleconvEntry(UnicodeString& string,
+       char* destination, char* defaultValue)
+{
+       status_t result = B_OK;
+       UErrorCode icuStatus = U_ZERO_ERROR;
+
+       ucnv_fromUChars(fConverter, destination, skLCBufSize, 
string.getBuffer(),
+               string.length(), &icuStatus);
+       if (!U_SUCCESS(icuStatus)) {
+               switch (icuStatus) {
+                       case U_BUFFER_OVERFLOW_ERROR:
+                               result = B_NAME_TOO_LONG;
+                               break;
+                       case U_INVALID_CHAR_FOUND:
+                       case U_TRUNCATED_CHAR_FOUND:
+                       case U_ILLEGAL_CHAR_FOUND:
+                               result = B_BAD_DATA;
+                               break;
+                       default:
+                               result = B_ERROR;
+                               break;
+               }
+               strcpy(destination, defaultValue);
+       }
+
+       return result;
+}
+
+
+status_t
 CollateData::SetTo(const Locale& locale, const char* posixLocaleName)
 {
        status_t result = CategoryData::SetTo(locale, posixLocaleName);
@@ -96,16 +154,12 @@
 
 
 CtypeData::CtypeData()
-       :
-       fConverter(NULL)
 {
 }
 
 
 CtypeData::~CtypeData()
 {
-       if (fConverter)
-               ucnv_close(fConverter);
 }
 
 
@@ -113,12 +167,6 @@
 CtypeData::SetTo(const Locale& locale, const char* posixLocaleName)
 {
        status_t result = CategoryData::SetTo(locale, posixLocaleName);
-       if (result == B_OK && *fGivenCharset != '\0') {
-               UErrorCode icuStatus = U_ZERO_ERROR;
-               fConverter = ucnv_open(fGivenCharset, &icuStatus);
-               if (fConverter == NULL)
-                       result = B_BAD_VALUE;
-       }
 
        return result;
 }
@@ -134,10 +182,96 @@
 
 
 status_t
+LocaleconvData::_SetLocaleconvEntry(const DecimalFormatSymbols* formatSymbols,
+       char* destination, FormatSymbol symbol, char* defaultValue)
+{
+       status_t result = B_OK;
+
+       UnicodeString symbolString = formatSymbols->getSymbol(symbol);
+       if (!symbolString.isEmpty()) {
+               result = _ConvertUnicodeStringToLocaleconvEntry(symbolString,
+                       destination, defaultValue);
+       } else
+               destination[0] = '\0';
+
+       return result;
+}
+
+
+status_t
 MonetaryData::SetTo(const Locale& locale, const char* posixLocaleName)
 {
        status_t result = CategoryData::SetTo(locale, posixLocaleName);
 
+       if (result == B_OK) {
+               UErrorCode icuStatus = U_ZERO_ERROR;
+               DecimalFormat* currencyFormat = dynamic_cast<DecimalFormat*>(
+                       NumberFormat::createInstance(locale, 
DecimalFormat::kCurrencyStyle,
+                               icuStatus));
+               if (!U_SUCCESS(icuStatus))
+                       return B_UNSUPPORTED;
+               if (!currencyFormat)
+                       return B_BAD_TYPE;
+               const DecimalFormatSymbols* formatSymbols
+                       = currencyFormat->getDecimalFormatSymbols();
+               if (!formatSymbols)
+                       result = B_BAD_DATA;
+
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sMonDecimalPoint,
+                               DecimalFormatSymbols::kMonetarySeparatorSymbol);
+               }
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sMonThousandsSep,
+                               
DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
+               }
+               if (result == B_OK) {
+                       int32 groupingSize = currencyFormat->getGroupingSize();
+                       if (groupingSize < 1)
+                               sMonGrouping[0] = '\0';
+                       else {
+                               sMonGrouping[0] = groupingSize;
+                               int32 secondaryGroupingSize
+                                       = 
currencyFormat->getSecondaryGroupingSize();
+                               if (secondaryGroupingSize < 1)
+                                       sMonGrouping[1] = '\0';
+                               else {
+                                       sMonGrouping[1] = secondaryGroupingSize;
+                                       sMonGrouping[2] = '\0';
+                               }
+                       }
+               }
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sIntCurrSymbol,
+                               DecimalFormatSymbols::kIntlCurrencySymbol);
+               }
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sCurrencySymbol,
+                               DecimalFormatSymbols::kCurrencySymbol);
+                       if (sCurrencySymbol[0] == '\0') {
+                               // fall back to the international currency 
symbol
+                               result = _SetLocaleconvEntry(formatSymbols, 
sCurrencySymbol,
+                                       
DecimalFormatSymbols::kIntlCurrencySymbol);
+                       }
+               }
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sPositiveSign,
+                               DecimalFormatSymbols::kPlusSignSymbol);
+               }
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sNegativeSign,
+                               DecimalFormatSymbols::kMinusSignSymbol);
+               }
+               if (result == B_OK) {
+                       sLocaleConv.int_frac_digits
+                               = currencyFormat->getMinimumFractionDigits();
+                       sLocaleConv.frac_digits
+                               = currencyFormat->getMinimumFractionDigits();
+               }
+
+               delete currencyFormat;
+       }
+
        return result;
 }
 
@@ -147,6 +281,48 @@
 {
        status_t result = CategoryData::SetTo(locale, posixLocaleName);
 
+       if (result == B_OK) {
+               UErrorCode icuStatus = U_ZERO_ERROR;
+               DecimalFormat* numberFormat = dynamic_cast<DecimalFormat*>(
+                       NumberFormat::createInstance(locale, 
DecimalFormat::kNumberStyle,
+                               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, 
sDecimalPoint,
+                               DecimalFormatSymbols::kDecimalSeparatorSymbol);
+               }
+               if (result == B_OK) {
+                       result = _SetLocaleconvEntry(formatSymbols, 
sThousandsSep,
+                               DecimalFormatSymbols::kGroupingSeparatorSymbol);
+               }
+               if (result == B_OK) {
+                       int32 groupingSize = numberFormat->getGroupingSize();
+                       if (groupingSize < 1)
+                               sGrouping[0] = '\0';
+                       else {
+                               sGrouping[0] = groupingSize;
+                               int32 secondaryGroupingSize
+                                       = 
numberFormat->getSecondaryGroupingSize();
+                               if (secondaryGroupingSize < 1)
+                                       sGrouping[1] = '\0';
+                               else {
+                                       sGrouping[1] = secondaryGroupingSize;
+                                       sGrouping[2] = '\0';
+                               }
+                       }
+               }
+
+               delete numberFormat;
+       }
+
        return result;
 }
 

Modified: 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.h
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.h
      2010-04-07 21:52:28 UTC (rev 36075)
+++ 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.h
      2010-04-07 21:54:50 UTC (rev 36076)
@@ -6,8 +6,10 @@
 #define _ICU_LOCALE_BACKEND_H
 
 
+#include <unicode/dcfmtsym.h>
 #include <unicode/locid.h>
 #include <unicode/ucnv.h>
+#include <unicode/unistr.h>
 
 #include "LocaleBackend.h"
 
@@ -15,6 +17,9 @@
 namespace BPrivate {
 
 
+typedef DecimalFormatSymbols::ENumberFormatSymbol FormatSymbol;
+
+
 class CategoryData {
 public:
                                                                CategoryData();
@@ -27,8 +32,14 @@
                                                                        { 
return fPosixLocaleName; }
 
 protected:
+                       status_t                        
_ConvertUnicodeStringToLocaleconvEntry(
+                                                                       
UnicodeString& string, char* destination,
+                                                                       char* 
defaultValue = "");
+
 static const   uint16                  skMaxPosixLocaleNameLen = 128;
+
                        Locale                          fLocale;
+                       UConverter*                     fConverter;
                        char                            
fPosixLocaleName[skMaxPosixLocaleNameLen];
                        char                            
fGivenCharset[UCNV_MAX_CONVERTER_NAME_LENGTH];
 };
@@ -50,7 +61,6 @@
                                                                        const 
char* posixLocaleName);
 
 private:
-                       UConverter*                     fConverter;
 };
 
 
@@ -61,14 +71,23 @@
 };
 
 
-class MonetaryData : public CategoryData {
+class LocaleconvData : public CategoryData {
+protected:
+                       status_t                        _SetLocaleconvEntry(
+                                                                       const 
DecimalFormatSymbols* formatSymbols,
+                                                                       char* 
destination, FormatSymbol symbol,
+                                                                       char* 
defaultValue = "");
+};
+
+
+class MonetaryData : public LocaleconvData {
 public:
 virtual                status_t                        SetTo(const Locale& 
locale,
                                                                        const 
char* posixLocaleName);
 };
 
 
-class NumericData : public CategoryData {
+class NumericData : public LocaleconvData {
 public:
 virtual                status_t                        SetTo(const Locale& 
locale,
                                                                        const 
char* posixLocaleName);


Other related posts:

  • » [haiku-commits] r36076 - haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale - zooey